64-bit Shift left w/Carry and 64-bit rotate
I've been working on something for VeriSign's RFID EPC network. I came across a need for a 64-bit
shift operation using MSVC's __int64's. Although .NET 2003 has 64 bit versions of _rotl and _rotr,
MSVC 6.0 folks are out of luck. So I whipped up a shift left and rotate left for my project. (These
aren't optimized so you can step through them in the debugger.)
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
////////////////////////////////////////////////////////////////////////////////////
//
// ROT64 - logical 64 bit rotate left
//
////////////////////////////////////////////////////////////////////////////////////
unsigned __int64 ROT64( unsigned __int64 i64Input, int iShift )
{
// Split the 64 bit input into two unsigned longs
struct // little endian in memory for intel, swap for powerpc
{
unsigned long right;
unsigned long left;
} map;
memcpy( &map, &i64Input, sizeof(i64Input) );
unsigned long rmask = 0xFFFFFFFE;
unsigned long cmask = 0x1;
for ( int i = 0; i < iShift; i++ )
{
unsigned long lcarry, lremainder;
// Shift the left side over
map.left = _lrotl( map.left, 1 );
lremainder = map.left & rmask;
lcarry = map.left & cmask;
unsigned long rcarry, rremainder;
// Shift the right side over
map.right = _lrotl( map.right, 1 );
rremainder = map.right & rmask;
rcarry = map.right & cmask;
// Set the right carry in the left remainder
if ( rcarry == 1 )
lremainder = lremainder | 0x1;
else
lremainder = lremainder & rmask;
// Set the left carry in the right remainder
if ( lcarry == 1 )
rremainder = rremainder | 0x1;
else
rremainder = rremainder & rmask;
// Store remainders
map.left = lremainder;
map.right = rremainder;
}
memcpy( &i64Input, &map, sizeof(i64Input) );
return i64Input;
}
////////////////////////////////////////////////////////////////////////////////////
//
// SLC64 - shift left with 32 bit carry
//
// Note, you can convert the 32 bit carry to 64 bit, just remember to drop
// the carry rotation back down into SLC64 instead of using _lrotl.
//
////////////////////////////////////////////////////////////////////////////////////
unsigned __int64 SLC64( unsigned __int64 i64Input, int iShift, unsigned long * lCarry )
{
// Split the 64 bit input into two unsigned longs
struct // little endian in memory for intel, swap for powerpc
{
unsigned long right;
unsigned long left;
} map;
memcpy( &map, &i64Input, sizeof(i64Input) );
unsigned long rmask = 0xFFFFFFFE;
unsigned long cmask = 0x1;
unsigned long carry = 0;
for ( int i = 0; i < iShift; i++ )
{
unsigned long lcarry, lremainder;
// for the loop, rotate the 32 bit carry over one
carry = _lrotl( carry, 1 );
// Shift the left side over
map.left = _lrotl( map.left, 1 );
lremainder = map.left & rmask;
lcarry = map.left & cmask;
unsigned long rcarry, rremainder;
// Shift the right side over
map.right = _lrotl( map.right, 1 );
rremainder = map.right & rmask;
rcarry = map.right & cmask;
// Set the right carry in the left remainder
if ( rcarry == 1 )
lremainder = lremainder | 0x1;
else
lremainder = lremainder & rmask;
// Set the left carry in the carry result
if ( lcarry == 1 )
carry = carry | 0x1;
else
carry = carry & rmask;
// Clear the right lsb
rremainder = rremainder & rmask;
// Store remainders
map.left = lremainder;
map.right = rremainder;
}
memcpy( &i64Input, &map, sizeof(i64Input) );
if ( lCarry ) *lCarry = carry;
return i64Input;
}
int main(int argc, char* argv[])
{
//unsigned __int64 i64Input = 0x8000000000000000;
//unsigned __int64 i64Input = 0x1;
unsigned __int64 i64Input = 0x3;
unsigned long lCarry = 0;
for ( int i = 0; i <= 64; i++ )
{
__int64 i64Tmp = SLC64( i64Input, 1, &lCarry );
printf( "Orig=0x%016I64X Shift=0x%016I64X Carry=0x%X\n", i64Input, i64Tmp, lCarry );
i64Input = i64Tmp;
}
i64Input = 0x1;
__int64 i64Tmp = SLC64( i64Input, 64, &lCarry );
printf( "Orig=0x%016I64X Shift=0x%016I64X Carry=0x%X\n", i64Input, i64Tmp, lCarry );
getchar();
return 0;
}
INTERNET_OPEN_TYPE_PRECONFIG, Proxy settings, and Windows Services
Here's a useful little note about the behavior of Wininet.dll and the INTERNET_OPEN_TYPE_PRECONFIG flag
of InternetOpen for developers writing services which interact with the network. Wininet.dll pulls it's
proxy information from the following registry settings:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings
ProxyEnabled = (DWORD) 1
ProxyServer = (String) "yourproxyserver.com:port"
ProxyOverride = (String) "<local>"
Wininet does not fall back to HKEY_LOCAL_MACHINE if these settings are not present, or allow HKEY_LOCAL_MACHINE
settings to override HKEY_CURRENT_USER. If your developing a service that runs under the NETWORK SERVICE
or LOCAL MACHINE accounts, these settings will not be available to Wininet and your service will fail to
communicate over HTTP, HTTPS and FTP. A solution to this is to go looking for the proxy settings of other
users manually.