📄 winceutils.cpp
字号:
// Start by figuring a lower bound on the scaling needed to make
// the upper 96 bits zero. iHiRes is the index into rgulRes[]
// of the highest non-zero ULONG.
//
iNewScale = iHiRes * 32 - 64 - 1;
if (iNewScale > 0) {
// Find the MSB.
//
ulTmp = rgulRes[iHiRes];
if (!(ulTmp & 0xFFFF0000)) {
iNewScale -= 16;
ulTmp <<= 16;
}
if (!(ulTmp & 0xFF000000)) {
iNewScale -= 8;
ulTmp <<= 8;
}
if (!(ulTmp & 0xF0000000)) {
iNewScale -= 4;
ulTmp <<= 4;
}
if (!(ulTmp & 0xC0000000)) {
iNewScale -= 2;
ulTmp <<= 2;
}
if (!(ulTmp & 0x80000000)) {
iNewScale--;
ulTmp <<= 1;
}
// Multiply bit position by log10(2) to figure it's power of 10.
// We scale the log by 256. log(2) = .30103, * 256 = 77. Doing this
// with a multiply saves a 96-byte lookup table. The power returned
// is <= the power of the number, so we must add one power of 10
// to make it's integer part zero after dividing by 256.
//
// Note: the result of this multiplication by an approximation of
// log10(2) have been exhaustively checked to verify it gives the
// correct result. (There were only 95 to check...)
//
iNewScale = ((iNewScale * 77) >> 8) + 1;
// iNewScale = min scale factor to make high 96 bits zero, 0 - 29.
// This reduces the scale factor of the result. If it exceeds the
// current scale of the result, we'll overflow.
//
if (iNewScale > iScale)
return -1;
}
else
iNewScale = 0;
// Make sure we scale by enough to bring the current scale factor
// into valid range.
//
if (iNewScale < iScale - DEC_SCALE_MAX)
iNewScale = iScale - DEC_SCALE_MAX;
if (iNewScale != 0) {
// Scale by the power of 10 given by iNewScale. Note that this is
// NOT guaranteed to bring the number within 96 bits -- it could
// be 1 power of 10 short.
//
iScale -= iNewScale;
ulSticky = 0;
sdlTmp.Hi = 0; // initialize remainder
for (;;) {
ulSticky |= sdlTmp.Hi; // record remainder as sticky bit
if (iNewScale > POWER10_MAX)
ulPwr = ulTenToNine;
else
ulPwr = rgulPower10[iNewScale];
// Compute first quotient.
// DivMod64by32 returns quotient in Lo, remainder in Hi.
//
sdlTmp.int64 = DivMod64by32(rgulRes[iHiRes], ulPwr);
rgulRes[iHiRes] = sdlTmp.Lo;
iCur = iHiRes - 1;
if (iCur >= 0) {
// If first quotient was 0, update iHiRes.
//
if (sdlTmp.Lo == 0)
iHiRes--;
// Compute subsequent quotients.
//
do {
sdlTmp.Lo = rgulRes[iCur];
sdlTmp.int64 = DivMod64by32(sdlTmp.int64, ulPwr);
rgulRes[iCur] = sdlTmp.Lo;
iCur--;
} while (iCur >= 0);
}
iNewScale -= POWER10_MAX;
if (iNewScale > 0)
continue; // scale some more
// If we scaled enough, iHiRes would be 2 or less. If not,
// divide by 10 more.
//
if (iHiRes > 2) {
iNewScale = 1;
iScale--;
continue; // scale by 10
}
// Round final result. See if remainder >= 1/2 of divisor.
// If remainder == 1/2 divisor, round up if odd or sticky bit set.
//
ulPwr >>= 1; // power of 10 always even
if ( ulPwr <= sdlTmp.Hi && (ulPwr < sdlTmp.Hi ||
((rgulRes[0] & 1) | ulSticky)) ) {
iCur = -1;
while (++rgulRes[++iCur] == 0);
if (iCur > 2) {
// The rounding caused us to carry beyond 96 bits.
// Scale by 10 more.
//
iHiRes = iCur;
ulSticky = 0; // no sticky bit
sdlTmp.Hi = 0; // or remainder
iNewScale = 1;
iScale--;
continue; // scale by 10
}
}
// We may have scaled it more than we planned. Make sure the scale
// factor hasn't gone negative, indicating overflow.
//
if (iScale < 0)
return -1;
return iScale;
} // for(;;)
}
return iScale;
}
STDAPI DecAddSub(LPDECIMAL pdecL, LPDECIMAL pdecR, LPDECIMAL pdecRes, char bSign)
{
ULONG rgulNum[6];
ULONG ulPwr;
int iScale;
int iHiProd;
int iCur;
SPLIT64 sdlTmp;
DECIMAL decRes;
DECIMAL decTmp;
LPDECIMAL pdecTmp;
bSign ^= (pdecR->sign ^ pdecL->sign) & DECIMAL_NEG;
if (pdecR->scale == pdecL->scale) {
// Scale factors are equal, no alignment necessary.
//
decRes.signscale = pdecL->signscale;
AlignedAdd:
if (bSign) {
// Signs differ - subtract
//
decRes.Lo64 = pdecL->Lo64 - pdecR->Lo64;
decRes.Hi32 = pdecL->Hi32 - pdecR->Hi32;
// Propagate carry
//
if (decRes.Lo64 > pdecL->Lo64) {
decRes.Hi32--;
if (decRes.Hi32 >= pdecL->Hi32)
goto SignFlip;
}
else if (decRes.Hi32 > pdecL->Hi32) {
// Got negative result. Flip its sign.
//
SignFlip:
decRes.Lo64 = -(LONGLONG)decRes.Lo64;
decRes.Hi32 = ~decRes.Hi32;
if (decRes.Lo64 == 0)
decRes.Hi32++;
decRes.sign ^= DECIMAL_NEG;
}
}
else {
// Signs are the same - add
//
decRes.Lo64 = pdecL->Lo64 + pdecR->Lo64;
decRes.Hi32 = pdecL->Hi32 + pdecR->Hi32;
// Propagate carry
//
if (decRes.Lo64 < pdecL->Lo64) {
decRes.Hi32++;
if (decRes.Hi32 <= pdecL->Hi32)
goto AlignedScale;
}
else if (decRes.Hi32 < pdecL->Hi32) {
AlignedScale:
// The addition carried above 96 bits. Divide the result by 10,
// dropping the scale factor.
//
if (decRes.scale == 0)
return DISP_E_OVERFLOW;
decRes.scale--;
sdlTmp.Lo = decRes.Hi32;
sdlTmp.Hi = 1;
sdlTmp.int64 = DivMod64by32(sdlTmp.int64, 10);
decRes.Hi32 = sdlTmp.Lo;
sdlTmp.Lo = decRes.Mid32;
sdlTmp.int64 = DivMod64by32(sdlTmp.int64, 10);
decRes.Mid32 = sdlTmp.Lo;
sdlTmp.Lo = decRes.Lo32;
sdlTmp.int64 = DivMod64by32(sdlTmp.int64, 10);
decRes.Lo32 = sdlTmp.Lo;
// See if we need to round up.
//
if (sdlTmp.Hi >= 5 && (sdlTmp.Hi > 5 || (decRes.Lo32 & 1))) {
if (++decRes.Lo64 == 0)
decRes.Hi32++;
}
}
}
}
else {
// Scale factors are not equal. Assume that a larger scale
// factor (more decimal places) is likely to mean that number
// is smaller. Start by guessing that the right operand has
// the larger scale factor. The result will have the larger
// scale factor.
//
decRes.scale = pdecR->scale; // scale factor of "smaller"
decRes.sign = pdecL->sign; // but sign of "larger"
iScale = decRes.scale - pdecL->scale;
if (iScale < 0) {
// Guessed scale factor wrong. Swap operands.
//
iScale = -iScale;
decRes.scale = pdecL->scale;
decRes.sign ^= bSign;
pdecTmp = pdecR;
pdecR = pdecL;
pdecL = pdecTmp;
}
// *pdecL will need to be multiplied by 10^iScale so
// it will have the same scale as *pdecR. We could be
// extending it to up to 192 bits of precision.
//
if (iScale <= POWER10_MAX) {
// Scaling won't make it larger than 4 ULONGs
//
ulPwr = rgulPower10[iScale];
decTmp.Lo64 = UInt32x32To64(pdecL->Lo32, ulPwr);
sdlTmp.int64 = UInt32x32To64(pdecL->Mid32, ulPwr);
sdlTmp.int64 += decTmp.Mid32;
decTmp.Mid32 = sdlTmp.Lo;
decTmp.Hi32 = sdlTmp.Hi;
sdlTmp.int64 = UInt32x32To64(pdecL->Hi32, ulPwr);
sdlTmp.int64 += decTmp.Hi32;
if (sdlTmp.Hi == 0) {
// Result fits in 96 bits. Use standard aligned add.
//
decTmp.Hi32 = sdlTmp.Lo;
pdecL = &decTmp;
goto AlignedAdd;
}
rgulNum[0] = decTmp.Lo32;
rgulNum[1] = decTmp.Mid32;
rgulNum[2] = sdlTmp.Lo;
rgulNum[3] = sdlTmp.Hi;
iHiProd = 3;
}
else {
// Have to scale by a bunch. Move the number to a buffer
// where it has room to grow as it's scaled.
//
rgulNum[0] = pdecL->Lo32;
rgulNum[1] = pdecL->Mid32;
rgulNum[2] = pdecL->Hi32;
iHiProd = 2;
// Scan for zeros in the upper words.
//
if (rgulNum[2] == 0) {
iHiProd = 1;
if (rgulNum[1] == 0) {
iHiProd = 0;
if (rgulNum[0] == 0) {
// Left arg is zero, return right.
//
decRes.Lo64 = pdecR->Lo64;
decRes.Hi32 = pdecR->Hi32;
decRes.sign ^= bSign;
goto RetDec;
}
}
}
// Scaling loop, up to 10^9 at a time. iHiProd stays updated
// with index of highest non-zero ULONG.
//
for (; iScale > 0; iScale -= POWER10_MAX) {
if (iScale > POWER10_MAX)
ulPwr = ulTenToNine;
else
ulPwr = rgulPower10[iScale];
sdlTmp.Hi = 0;
for (iCur = 0; iCur <= iHiProd; iCur++) {
sdlTmp.int64 = UInt32x32To64(rgulNum[iCur], ulPwr) + sdlTmp.Hi;
rgulNum[iCur] = sdlTmp.Lo;
}
if (sdlTmp.Hi != 0)
// We're extending the result by another ULONG.
rgulNum[++iHiProd] = sdlTmp.Hi;
}
}
// Scaling complete, do the add. Could be subtract if signs differ.
//
sdlTmp.Lo = rgulNum[0];
sdlTmp.Hi = rgulNum[1];
if (bSign) {
// Signs differ, subtract.
//
decRes.Lo64 = sdlTmp.int64 - pdecR->Lo64;
decRes.Hi32 = rgulNum[2] - pdecR->Hi32;
// Propagate carry
//
if (decRes.Lo64 > sdlTmp.int64) {
decRes.Hi32--;
if (decRes.Hi32 >= rgulNum[2])
goto LongSub;
}
else if (decRes.Hi32 > rgulNum[2]) {
LongSub:
// If rgulNum has more than 96 bits of precision, then we need to
// carry the subtraction into the higher bits. If it doesn't,
// then we subtracted in the wrong order and have to flip the
// sign of the result.
//
if (iHiProd <= 2)
goto SignFlip;
iCur = 3;
while(rgulNum[iCur++]-- == 0);
if (rgulNum[iHiProd] == 0)
iHiProd--;
}
}
else {
// Signs the same, add.
//
decRes.Lo64 = sdlTmp.int64 + pdecR->Lo64;
decRes.Hi32 = rgulNum[2] + pdecR->Hi32;
// Propagate carry
//
if (decRes.Lo64 < sdlTmp.int64) {
decRes.Hi32++;
if (decRes.Hi32 <= rgulNum[2])
goto LongAdd;
}
else if (decRes.Hi32 < rgulNum[2]) {
LongAdd:
// Had a carry above 96 bits.
//
iCur = 3;
do {
if (iHiProd < iCur) {
rgulNum[iCur] = 1;
iHiProd = iCur;
break;
}
}while (++rgulNum[iCur++] == 0);
}
}
if (iHiProd > 2) {
rgulNum[0] = decRes.Lo32;
rgulNum[1] = decRes.Mid32;
rgulNum[2] = decRes.Hi32;
decRes.scale = ScaleResult(rgulNum, iHiProd, decRes.scale);
if (decRes.scale == -1)
return DISP_E_OVERFLOW;
decRes.Lo32 = rgulNum[0];
decRes.Mid32 = rgulNum[1];
decRes.Hi32 = rgulNum[2];
}
}
RetDec:
COPYDEC(*pdecRes, decRes)
return NOERROR;
}
STDAPI VarDecCmp(LPDECIMAL pdecL, LPDECIMAL pdecR)
{
ULONG ulSgnL;
ULONG ulSgnR;
DECIMAL decRes;
// First check signs and whether either are zero. If both are
// non-zero and of the same sign, just use subtraction to compare.
//
ulSgnL = pdecL->Lo32 | pdecL->Mid32 | pdecL->Hi32;
ulSgnR = pdecR->Lo32 | pdecR->Mid32 | pdecR->Hi32;
if (ulSgnL != 0)
ulSgnL = (pdecL->sign & DECIMAL_NEG) | 1;
if (ulSgnR != 0)
ulSgnR = (pdecR->sign & DECIMAL_NEG) | 1;
// ulSgnL & ulSgnR have values 1, 0, or 0x81 depending on if the left/right
// operand is +, 0, or -.
//
if (ulSgnL == ulSgnR) {
if (ulSgnL == 0) // both are zero
return VARCMP_EQ; // return equal
DecAddSub(pdecL, pdecR, &decRes, DECIMAL_NEG);
if (decRes.Lo64 == 0 && decRes.Hi32 == 0)
return VARCMP_EQ;
if (decRes.sign & DECIMAL_NEG)
return VARCMP_LT;
return VARCMP_GT;
}
// Signs are different. Used signed byte compares
//
if ((char)ulSgnL > (char)ulSgnR)
return VARCMP_GT;
return VARCMP_LT;
}
LONG
My_RegOpenKeyExA (
HKEY hKey,
LPCSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult
)
{
WCHAR wcDest[_MAX_PATH];
WCHAR *pwcDest = wcDest;
if(lpSubKey)
{
if(-1 == mbstowcs(wcDest, lpSubKey, _MAX_PATH))
return ERROR_BAD_ARGUMENTS;
}
else
pwcDest = NULL;
return RegOpenKeyEx (
hKey,
pwcDest,
ulOptions,
samDesired,
phkResult);
}
void _ui64toa (
unsigned __int64 val,
char *buf,
unsigned int radix)
{
char *p; /* pointer to traverse string */
char *firstdig; /* pointer to first digit */
char temp; /* temp char */
unsigned digval; /* value of digit */
p = buf;
firstdig = p; /* save pointer to first digit */
do {
digval = (unsigned) (val % radix);
val /= radix; /* get next digit */
/* convert to ascii and store */
if (digval > 9)
*p++ = (char) (digval - 10 + 'a'); /* a letter */
else
*p++ = (char) (digval + '0'); /* a digit */
} while (val > 0);
/* We now have the digit of the number in the buffer, but in reverse
order. Thus we reverse them now. */
*p-- = '\0'; /* terminate string; p points to last digit */
do {
temp = *p;
*p = *firstdig;
*firstdig = temp; /* swap *p and *firstdig */
--p;
++firstdig; /* advance to next two digits */
} while (firstdig < p); /* repeat until halfway */
}
DummyMarshal::DummyMarshal(IUnknown *_punkCtrl) : punkCtrl(_punkCtrl), _refCount(1)
{
}
HRESULT STDMETHODCALLTYPE
DummyMarshal::QueryInterface(REFIID riid, void** ppv)
{
HRESULT hr = E_NOINTERFACE;
ASSERT(FALSE);
return hr;
}
ULONG STDMETHODCALLTYPE
DummyMarshal::AddRef()
{
return InterlockedIncrement((LONG *)&_refCount);
}
ULONG STDMETHODCALLTYPE
DummyMarshal::Release()
{
ASSERT(_refCount != 0xFFFFFFFF);
ULONG ret = InterlockedDecrement((LONG *)&_refCount);
if(!ret)
delete this;
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -