mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
746 lines
19 KiB
746 lines
19 KiB
/*****************************************************************************\
|
|
* MODULE: genutil.c
|
|
*
|
|
* Various common routines used throughout the gen* files.
|
|
*
|
|
* routines
|
|
* --------
|
|
* genGetCurDir
|
|
* genGetWinDir
|
|
* genBuildFileName
|
|
* genFindChar
|
|
* genFindCharDiff
|
|
* genFindRChar
|
|
* genWCFromMB
|
|
* genMBFromWC
|
|
* genItoA
|
|
*
|
|
* genIsWin9X
|
|
* genIdxCliPlatform
|
|
* genStrCliCab
|
|
* genStrCliEnvironment
|
|
* genStrCliOverride
|
|
* genValCliArchitecture
|
|
* genIdxCliVersion
|
|
* genStrCliVersion
|
|
* genValSvrArchitecture
|
|
*
|
|
*
|
|
* Copyright (C) 1996-1997 Microsoft Corporation
|
|
* Copyright (C) 1996-1997 Hewlett Packard
|
|
*
|
|
* history:
|
|
* 22-Nov-1996 <chriswil> created.
|
|
*
|
|
\*****************************************************************************/
|
|
|
|
#include "pch.h"
|
|
|
|
/*****************************************************************************\
|
|
* genGetCurDir
|
|
*
|
|
* Returns string indicating current-directory.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR genGetCurDir(VOID)
|
|
{
|
|
DWORD cbSize;
|
|
LPTSTR lpszDir = NULL;
|
|
|
|
|
|
cbSize = GetCurrentDirectory(0, NULL);
|
|
|
|
if (cbSize && (lpszDir = (LPTSTR)genGAlloc((cbSize * sizeof(TCHAR)))))
|
|
GetCurrentDirectory(cbSize, lpszDir);
|
|
|
|
return lpszDir;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genGetWinDir
|
|
*
|
|
* Returns string indicating the windows-directory.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR genGetWinDir(VOID)
|
|
{
|
|
DWORD cbSize;
|
|
LPTSTR lpszDir = NULL;
|
|
|
|
|
|
cbSize = GetWindowsDirectory(NULL, 0);
|
|
|
|
if (cbSize && (lpszDir = (LPTSTR)genGAlloc((cbSize * sizeof(TCHAR)))))
|
|
GetWindowsDirectory(lpszDir, cbSize);
|
|
|
|
return lpszDir;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genBuildFileName
|
|
*
|
|
* Takes path, name, extension strings and builds a fully-qualified
|
|
* string representing the file. This can also be used to build other
|
|
* names.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR genBuildFileName(
|
|
LPCTSTR lpszPath,
|
|
LPCTSTR lpszName,
|
|
LPCTSTR lpszExt)
|
|
{
|
|
DWORD cch;
|
|
LPTSTR lpszFull;
|
|
|
|
|
|
// Calculate the size necessary to hold the full-path filename.
|
|
//
|
|
cch = lstrlen(g_szBkSlash);
|
|
cch += (lpszPath ? lstrlen(lpszPath) : 0);
|
|
cch += (lpszName ? lstrlen(lpszName) : 0);
|
|
cch += (lpszExt ? lstrlen(lpszExt) : 0);
|
|
|
|
|
|
if (lpszFull = (LPTSTR)genGAlloc(((cch + 1) * sizeof(TCHAR)))) {
|
|
|
|
if (lpszPath) {
|
|
|
|
if (lpszExt)
|
|
cch = wsprintf(lpszFull, TEXT("%s\\%s%s"), lpszPath, lpszName, lpszExt);
|
|
else
|
|
cch = wsprintf(lpszFull, TEXT("%s\\%s"), lpszPath, lpszName);
|
|
|
|
} else {
|
|
|
|
if (lpszExt)
|
|
cch = wsprintf(lpszFull, TEXT("%s%s"), lpszName, lpszExt);
|
|
else
|
|
cch = wsprintf(lpszFull, TEXT("%s"), lpszName);
|
|
}
|
|
}
|
|
|
|
return lpszFull;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genFindCharDiff
|
|
*
|
|
* This routine returns a pointer to the location in DST, where the characters
|
|
* cease to match.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR genFindCharDiff(
|
|
LPTSTR lpszDst,
|
|
LPTSTR lpszSrc)
|
|
{
|
|
LPTSTR lpszCS;
|
|
LPTSTR lpszCD;
|
|
|
|
|
|
CharLower(lpszSrc);
|
|
CharLower(lpszDst);
|
|
|
|
|
|
lpszCS = lpszSrc;
|
|
lpszCD = lpszDst;
|
|
|
|
while (*lpszCS == *lpszCD) {
|
|
lpszCD++;
|
|
lpszCS++;
|
|
}
|
|
|
|
return (*lpszCD ? lpszCD : NULL);
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genFindChar
|
|
*
|
|
* Searches for the first occurence of (cch) in a string.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR genFindChar(
|
|
LPTSTR lpszStr,
|
|
TCHAR cch)
|
|
{
|
|
if (lpszStr) {
|
|
|
|
while ((*lpszStr != cch) && (*lpszStr != TEXT('\0')))
|
|
lpszStr++;
|
|
|
|
if (((cch != TEXT('\0')) && (*lpszStr != TEXT('\0'))) || (cch == TEXT('\0')))
|
|
return lpszStr;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genFindRChar
|
|
*
|
|
* Searches for the first occurence of (cch) in a string in reverse order.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR genFindRChar(
|
|
LPTSTR lpszStr,
|
|
TCHAR cch)
|
|
{
|
|
int nLimit;
|
|
|
|
if (nLimit = lstrlen(lpszStr)) {
|
|
|
|
lpszStr += nLimit;
|
|
|
|
while ((*lpszStr != cch) && nLimit--)
|
|
lpszStr--;
|
|
|
|
if (nLimit >= 0)
|
|
return lpszStr;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genWCFromMB
|
|
*
|
|
* This routine returns a buffer of wide-character representation of a
|
|
* ansi string. The caller is responsible for freeing this pointer returned
|
|
* by this function.
|
|
*
|
|
\*****************************************************************************/
|
|
LPWSTR genWCFromMB(
|
|
LPCSTR lpszStr)
|
|
{
|
|
DWORD cbSize;
|
|
LPWSTR lpwszBuf = NULL;
|
|
|
|
|
|
cbSize = genMBtoWC(NULL, lpszStr, 0);
|
|
|
|
if (cbSize && (lpwszBuf = (LPWSTR)genGAlloc(cbSize)))
|
|
genMBtoWC(lpwszBuf, lpszStr, cbSize);
|
|
|
|
return lpwszBuf;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genTCFromMB
|
|
*
|
|
* This routine returns a buffer of tchar representation of a
|
|
* ansi string. The caller is responsible for freeing this pointer returned
|
|
* by this function.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR genTCFromMB(
|
|
LPCSTR lpszStr)
|
|
{
|
|
|
|
#ifdef UNICODE
|
|
|
|
return genWCFromMB(lpszStr);
|
|
|
|
#else
|
|
|
|
return genGAllocStr(lpszStr);
|
|
|
|
#endif
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
* genTCFromWC
|
|
*
|
|
* This routine returns a buffer of tchar representation of a
|
|
* wide string. The caller is responsible for freeing this pointer returned
|
|
* by this function.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR genTCFromWC(
|
|
LPCWSTR lpszwStr)
|
|
{
|
|
|
|
#ifdef UNICODE
|
|
|
|
return genGAllocStr(lpszwStr);
|
|
|
|
#else
|
|
|
|
return genMBFromWC(lpszwStr);
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genMBFromWC
|
|
*
|
|
* This routine returns a buffer of byte-character representation of a
|
|
* wide-char string. The caller is responsible for freeing this pointer
|
|
* returned by this function.
|
|
*
|
|
\*****************************************************************************/
|
|
LPSTR genMBFromWC(
|
|
LPCWSTR lpwszStr)
|
|
{
|
|
DWORD cbSize;
|
|
LPSTR lpszBuf = NULL;
|
|
|
|
|
|
cbSize = genWCtoMB(NULL, lpwszStr, 0);
|
|
|
|
if (cbSize && (lpszBuf = (LPSTR)genGAlloc(cbSize)))
|
|
genWCtoMB(lpszBuf, lpwszStr, cbSize);
|
|
|
|
return lpszBuf;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genMBFromTC
|
|
*
|
|
* This routine returns a buffer of byte-character representation of a
|
|
* tchar string. The caller is responsible for freeing this pointer
|
|
* returned by this function.
|
|
*
|
|
\*****************************************************************************/
|
|
LPSTR genMBFromTC(
|
|
LPCTSTR lpszStr)
|
|
{
|
|
|
|
#ifdef UNICODE
|
|
|
|
return genMBFromWC(lpszStr);
|
|
|
|
#else
|
|
|
|
return genGAllocStr(lpszStr);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genItoA
|
|
*
|
|
* Convert integer to string.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR genItoA(
|
|
int nVal)
|
|
{
|
|
DWORD cch = 0;
|
|
LPTSTR lpszVal;
|
|
|
|
if (lpszVal = (LPTSTR)genGAlloc(INF_MIN_BUFFER))
|
|
cch = wsprintf(lpszVal, TEXT("%d"), nVal);
|
|
|
|
SPLASSERT((cch < INF_MIN_BUFFER));
|
|
|
|
return lpszVal;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* Client Platform Table.
|
|
*
|
|
* This table describes the various platforms/architectures. By refering
|
|
* to the index into the table, various platform information can be
|
|
* obtained.
|
|
*
|
|
* Members are as follows:
|
|
* a) CAB string. Used to denote the architecture in the cab-name.
|
|
* b) Environment string. Used to denote printer-environment.
|
|
* c) Platform string. Used for path override in setup api's.
|
|
* d) Architecture value. Used to denote platform of client.
|
|
*
|
|
\*****************************************************************************/
|
|
static PLTINFO s_PltTable[] = {
|
|
|
|
g_szCabX86, g_szEnvX86, g_szPltX86, PROCESSOR_ARCHITECTURE_INTEL, // IDX_X86
|
|
g_szCabMIP, g_szEnvMIP, g_szPltMIP, PROCESSOR_ARCHITECTURE_MIPS, // IDX_MIP
|
|
g_szCabAXP, g_szEnvAXP, g_szPltAXP, PROCESSOR_ARCHITECTURE_ALPHA, // IDX_AXP
|
|
g_szCabPPC, g_szEnvPPC, g_szPltPPC, PROCESSOR_ARCHITECTURE_PPC, // IDX_PPC
|
|
g_szCabW9X, g_szEnvW9X, g_szPltW9X, PROCESSOR_ARCHITECTURE_INTEL, // IDX_W9X
|
|
g_szCabI64, g_szEnvI64, g_szPltI64, PROCESSOR_ARCHITECTURE_IA64, // IDX_I64
|
|
g_szCabAMD64, g_szEnvAMD64, g_szPltAMD64, PROCESSOR_ARCHITECTURE_AMD64 // IDX_AMD64
|
|
};
|
|
|
|
|
|
/*****************************************************************************\
|
|
* Client Version Table.
|
|
*
|
|
* This table describes the spooler-versions which the client can request
|
|
* drivers for.
|
|
*
|
|
\*****************************************************************************/
|
|
static LPCTSTR s_VerTable[] = {
|
|
|
|
TEXT("\\0"), // Win NT 3.1 - IDX_SPLVER_0
|
|
TEXT("\\1"), // Win NT 3.51 - IDX_SPLVER_1
|
|
TEXT("\\2"), // Win NT 4.0 - IDX_SPLVER_2
|
|
TEXT("\\3") // Win NT 5.0 - IDX_SPLVER_3
|
|
};
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genIdxCliPlatform
|
|
*
|
|
* This routine returns a platform-index into the s_PltTable. The caller
|
|
* can use this index to refer to platform specific information about the
|
|
* client.
|
|
*
|
|
\*****************************************************************************/
|
|
DWORD genIdxCliPlatform(
|
|
DWORD dwCliInfo)
|
|
{
|
|
DWORD idx;
|
|
DWORD cEnv;
|
|
WORD wArch;
|
|
|
|
|
|
// If the platform is win9X, then set the index appropriately. Otherwise,
|
|
// continue on to determine the correct architecture for the NT case.
|
|
//
|
|
if (webGetOSPlatform(dwCliInfo) == VER_PLATFORM_WIN32_WINDOWS)
|
|
return IDX_W9X;
|
|
|
|
|
|
// Otherwise, the client is an NT platform.
|
|
//
|
|
cEnv = sizeof(s_PltTable) / sizeof(s_PltTable[0]);
|
|
wArch = webGetOSArch(dwCliInfo);
|
|
|
|
|
|
// Look for matching client-info for the NT case. The architecture
|
|
// values will match up in this case.
|
|
//
|
|
for (idx = 0; idx < cEnv; idx++) {
|
|
|
|
if (wArch == s_PltTable[idx].wArch)
|
|
return idx;
|
|
}
|
|
|
|
return IDX_UNKNOWN;
|
|
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
* genStrCliCab
|
|
*
|
|
* This routine returns a static-string representing the client-cabname.
|
|
*
|
|
\*****************************************************************************/
|
|
LPCTSTR genStrCliCab(
|
|
DWORD idxPlt)
|
|
{
|
|
return (idxPlt < (sizeof(s_PltTable) / sizeof(s_PltTable[0])) ? s_PltTable[idxPlt].lpszCab : NULL);
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genStrCliEnvironment
|
|
*
|
|
* This routine returns a static-string representing the client-platform. This
|
|
* string is used by the spooler API calls to specify environment.
|
|
*
|
|
\*****************************************************************************/
|
|
LPCTSTR genStrCliEnvironment(
|
|
DWORD idxPlt)
|
|
{
|
|
return (idxPlt < (sizeof(s_PltTable) / sizeof(s_PltTable[0])) ? s_PltTable[idxPlt].lpszEnv : NULL);
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genStrCliOverride
|
|
*
|
|
* This routines returns a static-string representing the client-path-override
|
|
* for the setup API.
|
|
*
|
|
\*****************************************************************************/
|
|
LPCTSTR genStrCliOverride(
|
|
DWORD idxPlt)
|
|
{
|
|
return (idxPlt < (sizeof(s_PltTable) / sizeof(s_PltTable[0])) ? s_PltTable[idxPlt].lpszPlt : NULL);
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genValCliArchitecture
|
|
*
|
|
* Returns the architecture platform of the client.
|
|
*
|
|
\*****************************************************************************/
|
|
WORD genValCliArchitecture(
|
|
DWORD idxPlt)
|
|
{
|
|
return (idxPlt < (sizeof(s_PltTable) / sizeof(s_PltTable[0])) ? s_PltTable[idxPlt].wArch : PROCESSOR_ARCHITECTURE_UNKNOWN);
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genValSvrArchitecture
|
|
*
|
|
* Returns the architecture platform of the server. The current architecture
|
|
* running this dll.
|
|
*
|
|
\*****************************************************************************/
|
|
WORD genValSvrArchitecture(VOID)
|
|
{
|
|
DWORD idxEnv;
|
|
|
|
#if defined(_X86_)
|
|
|
|
idxEnv = IDX_X86;
|
|
|
|
#elif defined(_AMD64_)
|
|
|
|
idxEnv = IDX_AMD64;
|
|
|
|
#elif defined(_IA64_)
|
|
|
|
idxEnv = IDX_I64;
|
|
|
|
#endif
|
|
|
|
return genValCliArchitecture(idxEnv);
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genIdxCliVersion
|
|
*
|
|
* This routine returns an index into the s_VerTable. The caller can refer
|
|
* to this index for the client-version information.
|
|
*
|
|
\*****************************************************************************/
|
|
DWORD genIdxCliVersion(
|
|
DWORD dwCliInfo)
|
|
{
|
|
DWORD dwPlt = webGetOSPlatform(dwCliInfo);
|
|
DWORD dwMaj = webGetOSMajorVer(dwCliInfo);
|
|
DWORD dwMin = webGetOSMinorVer(dwCliInfo);
|
|
|
|
|
|
if (dwMaj == 5)
|
|
return IDX_SPLVER_3;
|
|
|
|
if ((dwMaj == 4) && (dwPlt == VER_PLATFORM_WIN32_NT))
|
|
return IDX_SPLVER_2;
|
|
|
|
if ((dwMaj == 3) && (dwMin == 51))
|
|
return IDX_SPLVER_1;
|
|
|
|
if ((dwMaj == 4) && (dwPlt == VER_PLATFORM_WIN32_WINDOWS))
|
|
return IDX_SPLVER_0;
|
|
|
|
if ((dwMaj == 3) && (dwMin == 1))
|
|
return IDX_SPLVER_0;
|
|
|
|
return IDX_UNKNOWN;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genStrCliVersion
|
|
*
|
|
* Returns a string representing the spooler-version directory. This is
|
|
* the relative directory off the system32\spool\drivers\*\ path that contains
|
|
* the drivers.
|
|
*
|
|
\*****************************************************************************/
|
|
LPCTSTR genStrCliVersion(
|
|
DWORD idxVer)
|
|
{
|
|
return (idxVer < (sizeof(s_VerTable) / sizeof(s_VerTable[0])) ? s_VerTable[idxVer] : NULL);
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genIdxFromStrVersion
|
|
*
|
|
* Returns an index that matches the client-version-string.
|
|
*
|
|
\*****************************************************************************/
|
|
DWORD genIdxFromStrVersion(
|
|
LPCTSTR lpszVer)
|
|
{
|
|
DWORD idx;
|
|
DWORD cVer;
|
|
|
|
|
|
cVer = sizeof(s_VerTable) / sizeof(s_VerTable[0]);
|
|
|
|
for (idx = 0; idx < cVer; idx++) {
|
|
|
|
if (lstrcmpi(lpszVer, s_VerTable[idx]) == 0)
|
|
return idx;
|
|
}
|
|
|
|
return IDX_UNKNOWN;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genUpdIPAddr
|
|
*
|
|
* Updates the registry with the current IP-Addr of this machine. If there
|
|
* is already an entry in the registry and it's different than the one
|
|
* currently established for the machine, then we return FALSE, and update
|
|
* the entry.
|
|
*
|
|
\*****************************************************************************/
|
|
BOOL genUpdIPAddr(VOID)
|
|
{
|
|
HKEY hKey;
|
|
LRESULT lRet;
|
|
LPSTR lpszCmp;
|
|
DWORD cbData;
|
|
DWORD dwIpCmp;
|
|
DWORD dwIpReg;
|
|
DWORD dwVal;
|
|
BOOL bRet = TRUE;
|
|
|
|
|
|
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
g_szPrtReg,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
&hKey);
|
|
|
|
if (lRet == ERROR_SUCCESS) {
|
|
|
|
if (lpszCmp = genMBFromWC(g_szHttpServerName)) {
|
|
|
|
// Get the IP-Addr associated with this machine.
|
|
//
|
|
dwIpCmp = GetIPAddr(lpszCmp);
|
|
|
|
|
|
// Setup our registry-information so get/set a value.
|
|
//
|
|
dwVal = REG_DWORD;
|
|
cbData = sizeof(DWORD);
|
|
|
|
|
|
// Get what we already have stored there. If no value exists,
|
|
// the write it out.
|
|
//
|
|
lRet = RegQueryValueEx(hKey,
|
|
g_szIpAddr,
|
|
NULL,
|
|
&dwVal,
|
|
(LPBYTE)&dwIpReg,
|
|
&cbData);
|
|
|
|
if ((lRet != ERROR_SUCCESS) || (dwIpReg != dwIpCmp)) {
|
|
|
|
bRet = FALSE;
|
|
|
|
RegSetValueEx(hKey,
|
|
g_szIpAddr,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&dwIpCmp,
|
|
cbData);
|
|
}
|
|
|
|
genGFree(lpszCmp, genGSize(lpszCmp));
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genFrnName
|
|
*
|
|
* Returns a cluster-capable friendly-name.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR genFrnName(
|
|
LPCTSTR lpszFrnName)
|
|
{
|
|
DWORD cbSize;
|
|
LPTSTR lpszName = NULL;
|
|
|
|
|
|
// Calc size for friendly-name.
|
|
//
|
|
cbSize = lstrlen(lpszFrnName) + lstrlen(g_szPrintServerName) + 6;
|
|
|
|
|
|
// Build it.
|
|
//
|
|
if (lpszName = (LPTSTR)genGAlloc(cbSize * sizeof(TCHAR)))
|
|
wsprintf(lpszName, TEXT("\\\\%s\\%s"), g_szPrintServerName, lpszFrnName);
|
|
|
|
return lpszName;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* genChkSum (Local Routine)
|
|
*
|
|
* This routine checksums a string into a WORD value.
|
|
*
|
|
\*****************************************************************************/
|
|
|
|
#define CRC_HI(wHi) (((wHi << 1) | (wHi & 0x8000)) ? 0x0001 : 0)
|
|
#define CRC_LO(wLo) (((wLo >> 1) | (wLo & 0x0001)) ? 0x8000 : 0)
|
|
|
|
WORD genChkSum(
|
|
LPCTSTR lpszStr)
|
|
{
|
|
WORD wMask;
|
|
DWORD idx;
|
|
DWORD cLoop;
|
|
DWORD cbStr;
|
|
WORD wHi = 0;
|
|
WORD wLo = 0;
|
|
WORD wChkSum = 0;
|
|
|
|
|
|
if (lpszStr && (cbStr = lstrlen(lpszStr))) {
|
|
|
|
// Loop through the bytes (in WORD increments). This is an
|
|
// optimized method in cyclying through bits.
|
|
//
|
|
cLoop = (cbStr / sizeof(WORD));
|
|
|
|
for (idx = 0, wLo = 0, wHi = 0, wChkSum = 0; idx < cLoop; idx++) {
|
|
|
|
wChkSum += *(((PWORD)lpszStr) + idx);
|
|
|
|
wHi = CRC_HI(wHi) ^ wChkSum;
|
|
wLo = CRC_LO(wLo) ^ wChkSum;
|
|
}
|
|
|
|
|
|
// If there's any extra bytes left over, then include that
|
|
// in the checksum. Mask off any bytes that should be
|
|
// excluded from the checksum.
|
|
//
|
|
if (cbStr & 3) {
|
|
|
|
wMask = ((WORD)-1 >> ((sizeof(WORD) - (cbStr & 3)) * 8));
|
|
|
|
wChkSum += ((*((PWORD)lpszStr + cLoop)) & wMask);
|
|
|
|
wHi = CRC_HI(wHi) ^ wChkSum;
|
|
wLo = CRC_LO(wLo) ^ wChkSum;
|
|
}
|
|
}
|
|
|
|
return (wChkSum + wHi + wLo);
|
|
}
|