windows-nt/Source/XPSP1/NT/printscan/print/spooler/inetsrv/genutil.cxx
2020-09-26 16:20:57 +08:00

747 lines
19 KiB
C++

/*****************************************************************************\
* 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);
}