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