Leaked source code of windows server 2003
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.

752 lines
19 KiB

  1. /*****************************************************************************\
  2. * MODULE: genutil.c
  3. *
  4. * Various common routines used throughout the gen* files.
  5. *
  6. * routines
  7. * --------
  8. * genGetCurDir
  9. * genGetWinDir
  10. * genBuildFileName
  11. * genFindChar
  12. * genFindCharDiff
  13. * genFindRChar
  14. * genWCFromMB
  15. * genMBFromWC
  16. * genItoA
  17. *
  18. * genIsWin9X
  19. * genIdxCliPlatform
  20. * genStrCliCab
  21. * genStrCliEnvironment
  22. * genStrCliOverride
  23. * genValCliArchitecture
  24. * genIdxCliVersion
  25. * genStrCliVersion
  26. * genValSvrArchitecture
  27. *
  28. *
  29. * Copyright (C) 1996-1997 Microsoft Corporation
  30. * Copyright (C) 1996-1997 Hewlett Packard
  31. *
  32. * history:
  33. * 22-Nov-1996 <chriswil> created.
  34. *
  35. \*****************************************************************************/
  36. #include "pch.h"
  37. /*****************************************************************************\
  38. * genGetCurDir
  39. *
  40. * Returns string indicating current-directory.
  41. *
  42. \*****************************************************************************/
  43. LPTSTR genGetCurDir(VOID)
  44. {
  45. DWORD cbSize;
  46. LPTSTR lpszDir = NULL;
  47. cbSize = GetCurrentDirectory(0, NULL);
  48. if (cbSize && (lpszDir = (LPTSTR)genGAlloc((cbSize * sizeof(TCHAR)))))
  49. GetCurrentDirectory(cbSize, lpszDir);
  50. return lpszDir;
  51. }
  52. /*****************************************************************************\
  53. * genGetWinDir
  54. *
  55. * Returns string indicating the windows-directory.
  56. *
  57. \*****************************************************************************/
  58. LPTSTR genGetWinDir(VOID)
  59. {
  60. DWORD cbSize;
  61. LPTSTR lpszDir = NULL;
  62. cbSize = GetWindowsDirectory(NULL, 0);
  63. if (cbSize && (lpszDir = (LPTSTR)genGAlloc((cbSize * sizeof(TCHAR)))))
  64. GetWindowsDirectory(lpszDir, cbSize);
  65. return lpszDir;
  66. }
  67. /*****************************************************************************\
  68. * genBuildFileName
  69. *
  70. * Takes path, name, extension strings and builds a fully-qualified
  71. * string representing the file. This can also be used to build other
  72. * names.
  73. *
  74. \*****************************************************************************/
  75. LPTSTR genBuildFileName(
  76. LPCTSTR lpszPath,
  77. LPCTSTR lpszName,
  78. LPCTSTR lpszExt)
  79. {
  80. DWORD cch;
  81. LPTSTR lpszFull;
  82. HRESULT hr = S_OK;
  83. // Calculate the size necessary to hold the full-path filename.
  84. //
  85. cch = lstrlen(g_szBkSlash);
  86. cch += (lpszPath ? lstrlen(lpszPath) : 0);
  87. cch += (lpszName ? lstrlen(lpszName) : 0);
  88. cch += (lpszExt ? lstrlen(lpszExt) : 0);
  89. if (lpszFull = (LPTSTR)genGAlloc(((cch + 1) * sizeof(TCHAR)))) {
  90. if (lpszPath) {
  91. if (lpszExt)
  92. hr = StringCchPrintf(lpszFull, cch+1, TEXT("%s\\%s%s"), lpszPath, lpszName, lpszExt);
  93. else
  94. hr = StringCchPrintf(lpszFull, cch+1, TEXT("%s\\%s"), lpszPath, lpszName);
  95. } else {
  96. if (lpszExt)
  97. hr = StringCchPrintf(lpszFull, cch+1, TEXT("%s%s"), lpszName, lpszExt);
  98. else
  99. hr = StringCchPrintf(lpszFull, cch+1, TEXT("%s"), lpszName);
  100. }
  101. if (FAILED(hr))
  102. {
  103. genGFree(lpszFull, genGSize(lpszFull));
  104. lpszFull = NULL;
  105. }
  106. }
  107. return lpszFull;
  108. }
  109. /*****************************************************************************\
  110. * genFindCharDiff
  111. *
  112. * This routine returns a pointer to the location in DST, where the characters
  113. * cease to match.
  114. *
  115. \*****************************************************************************/
  116. LPTSTR genFindCharDiff(
  117. LPTSTR lpszDst,
  118. LPTSTR lpszSrc)
  119. {
  120. LPTSTR lpszCS;
  121. LPTSTR lpszCD;
  122. CharLower(lpszSrc);
  123. CharLower(lpszDst);
  124. lpszCS = lpszSrc;
  125. lpszCD = lpszDst;
  126. while (*lpszCS == *lpszCD) {
  127. lpszCD++;
  128. lpszCS++;
  129. }
  130. return (*lpszCD ? lpszCD : NULL);
  131. }
  132. /*****************************************************************************\
  133. * genFindChar
  134. *
  135. * Searches for the first occurence of (cch) in a string.
  136. *
  137. \*****************************************************************************/
  138. LPTSTR genFindChar(
  139. LPTSTR lpszStr,
  140. TCHAR cch)
  141. {
  142. if (lpszStr) {
  143. while ((*lpszStr != cch) && (*lpszStr != TEXT('\0')))
  144. lpszStr++;
  145. if (((cch != TEXT('\0')) && (*lpszStr != TEXT('\0'))) || (cch == TEXT('\0')))
  146. return lpszStr;
  147. }
  148. return NULL;
  149. }
  150. /*****************************************************************************\
  151. * genFindRChar
  152. *
  153. * Searches for the first occurence of (cch) in a string in reverse order.
  154. *
  155. \*****************************************************************************/
  156. LPTSTR genFindRChar(
  157. LPTSTR lpszStr,
  158. TCHAR cch)
  159. {
  160. int nLimit;
  161. if (nLimit = lstrlen(lpszStr)) {
  162. lpszStr += nLimit;
  163. while ((*lpszStr != cch) && nLimit--)
  164. lpszStr--;
  165. if (nLimit >= 0)
  166. return lpszStr;
  167. }
  168. return NULL;
  169. }
  170. /*****************************************************************************\
  171. * genWCFromMB
  172. *
  173. * This routine returns a buffer of wide-character representation of a
  174. * ansi string. The caller is responsible for freeing this pointer returned
  175. * by this function.
  176. *
  177. \*****************************************************************************/
  178. LPWSTR genWCFromMB(
  179. LPCSTR lpszStr)
  180. {
  181. DWORD cbSize;
  182. LPWSTR lpwszBuf = NULL;
  183. cbSize = genMBtoWC(NULL, lpszStr, 0);
  184. if (cbSize && (lpwszBuf = (LPWSTR)genGAlloc(cbSize)))
  185. genMBtoWC(lpwszBuf, lpszStr, cbSize);
  186. return lpwszBuf;
  187. }
  188. /*****************************************************************************\
  189. * genTCFromMB
  190. *
  191. * This routine returns a buffer of tchar representation of a
  192. * ansi string. The caller is responsible for freeing this pointer returned
  193. * by this function.
  194. *
  195. \*****************************************************************************/
  196. LPTSTR genTCFromMB(
  197. LPCSTR lpszStr)
  198. {
  199. #ifdef UNICODE
  200. return genWCFromMB(lpszStr);
  201. #else
  202. return genGAllocStr(lpszStr);
  203. #endif
  204. }
  205. /*****************************************************************************\
  206. * genTCFromWC
  207. *
  208. * This routine returns a buffer of tchar representation of a
  209. * wide string. The caller is responsible for freeing this pointer returned
  210. * by this function.
  211. *
  212. \*****************************************************************************/
  213. LPTSTR genTCFromWC(
  214. LPCWSTR lpszwStr)
  215. {
  216. #ifdef UNICODE
  217. return genGAllocStr(lpszwStr);
  218. #else
  219. return genMBFromWC(lpszwStr);
  220. #endif
  221. }
  222. /*****************************************************************************\
  223. * genMBFromWC
  224. *
  225. * This routine returns a buffer of byte-character representation of a
  226. * wide-char string. The caller is responsible for freeing this pointer
  227. * returned by this function.
  228. *
  229. \*****************************************************************************/
  230. LPSTR genMBFromWC(
  231. LPCWSTR lpwszStr)
  232. {
  233. DWORD cbSize;
  234. LPSTR lpszBuf = NULL;
  235. cbSize = genWCtoMB(NULL, lpwszStr, 0);
  236. if (cbSize && (lpszBuf = (LPSTR)genGAlloc(cbSize)))
  237. genWCtoMB(lpszBuf, lpwszStr, cbSize);
  238. return lpszBuf;
  239. }
  240. /*****************************************************************************\
  241. * genMBFromTC
  242. *
  243. * This routine returns a buffer of byte-character representation of a
  244. * tchar string. The caller is responsible for freeing this pointer
  245. * returned by this function.
  246. *
  247. \*****************************************************************************/
  248. LPSTR genMBFromTC(
  249. LPCTSTR lpszStr)
  250. {
  251. #ifdef UNICODE
  252. return genMBFromWC(lpszStr);
  253. #else
  254. return genGAllocStr(lpszStr);
  255. #endif
  256. }
  257. /*****************************************************************************\
  258. * genItoA
  259. *
  260. * Convert integer to string.
  261. *
  262. \*****************************************************************************/
  263. LPTSTR genItoA(
  264. int nVal)
  265. {
  266. LPTSTR lpszVal;
  267. if (lpszVal = (LPTSTR)genGAlloc(INF_MIN_BUFFER))
  268. {
  269. if (FAILED(StringCbPrintf(lpszVal, INF_MIN_BUFFER, TEXT("%d"), nVal)))
  270. {
  271. genGFree(lpszVal, genGSize(lpszVal));
  272. lpszVal = NULL;
  273. }
  274. }
  275. return lpszVal;
  276. }
  277. /*****************************************************************************\
  278. * Client Platform Table.
  279. *
  280. * This table describes the various platforms/architectures. By refering
  281. * to the index into the table, various platform information can be
  282. * obtained.
  283. *
  284. * Members are as follows:
  285. * a) CAB string. Used to denote the architecture in the cab-name.
  286. * b) Environment string. Used to denote printer-environment.
  287. * c) Platform string. Used for path override in setup api's.
  288. * d) Architecture value. Used to denote platform of client.
  289. *
  290. \*****************************************************************************/
  291. static PLTINFO s_PltTable[] = {
  292. g_szCabX86, g_szEnvX86, g_szPltX86, PROCESSOR_ARCHITECTURE_INTEL, // IDX_X86
  293. g_szCabW9X, g_szEnvW9X, g_szPltW9X, PROCESSOR_ARCHITECTURE_INTEL, // IDX_W9X
  294. g_szCabI64, g_szEnvI64, g_szPltI64, PROCESSOR_ARCHITECTURE_IA64, // IDX_I64
  295. g_szCabAMD64, g_szEnvAMD64, g_szPltAMD64, PROCESSOR_ARCHITECTURE_AMD64 // IDX_AMD64
  296. };
  297. /*****************************************************************************\
  298. * Client Version Table.
  299. *
  300. * This table describes the spooler-versions which the client can request
  301. * drivers for.
  302. *
  303. \*****************************************************************************/
  304. static LPCTSTR s_VerTable[] = {
  305. TEXT("\\0"), // Win9x - IDX_SPLVER_0
  306. TEXT("\\2"), // Win NT 4.0 - IDX_SPLVER_2
  307. TEXT("\\3") // Win NT 5.0 - IDX_SPLVER_3
  308. };
  309. /*****************************************************************************\
  310. * genIdxCliPlatform
  311. *
  312. * This routine returns a platform-index into the s_PltTable. The caller
  313. * can use this index to refer to platform specific information about the
  314. * client.
  315. *
  316. \*****************************************************************************/
  317. DWORD genIdxCliPlatform(
  318. DWORD dwCliInfo)
  319. {
  320. DWORD idx;
  321. DWORD cEnv;
  322. WORD wArch;
  323. // If the platform is win9X, then set the index appropriately. Otherwise,
  324. // continue on to determine the correct architecture for the NT case.
  325. //
  326. if (webGetOSPlatform(dwCliInfo) == VER_PLATFORM_WIN32_WINDOWS)
  327. return IDX_W9X;
  328. // Otherwise, the client is an NT platform.
  329. //
  330. cEnv = sizeof(s_PltTable) / sizeof(s_PltTable[0]);
  331. wArch = webGetOSArch(dwCliInfo);
  332. // Look for matching client-info for the NT case. The architecture
  333. // values will match up in this case.
  334. //
  335. for (idx = 0; idx < cEnv; idx++) {
  336. if (wArch == s_PltTable[idx].wArch)
  337. return idx;
  338. }
  339. return IDX_UNKNOWN;
  340. }
  341. /*****************************************************************************\
  342. * genStrCliCab
  343. *
  344. * This routine returns a static-string representing the client-cabname.
  345. *
  346. \*****************************************************************************/
  347. LPCTSTR genStrCliCab(
  348. DWORD idxPlt)
  349. {
  350. return (idxPlt < (sizeof(s_PltTable) / sizeof(s_PltTable[0])) ? s_PltTable[idxPlt].lpszCab : NULL);
  351. }
  352. /*****************************************************************************\
  353. * genStrCliEnvironment
  354. *
  355. * This routine returns a static-string representing the client-platform. This
  356. * string is used by the spooler API calls to specify environment.
  357. *
  358. \*****************************************************************************/
  359. LPCTSTR genStrCliEnvironment(
  360. DWORD idxPlt)
  361. {
  362. return (idxPlt < (sizeof(s_PltTable) / sizeof(s_PltTable[0])) ? s_PltTable[idxPlt].lpszEnv : NULL);
  363. }
  364. /*****************************************************************************\
  365. * genStrCliOverride
  366. *
  367. * This routines returns a static-string representing the client-path-override
  368. * for the setup API.
  369. *
  370. \*****************************************************************************/
  371. LPCTSTR genStrCliOverride(
  372. DWORD idxPlt)
  373. {
  374. return (idxPlt < (sizeof(s_PltTable) / sizeof(s_PltTable[0])) ? s_PltTable[idxPlt].lpszPlt : NULL);
  375. }
  376. /*****************************************************************************\
  377. * genValCliArchitecture
  378. *
  379. * Returns the architecture platform of the client.
  380. *
  381. \*****************************************************************************/
  382. WORD genValCliArchitecture(
  383. DWORD idxPlt)
  384. {
  385. return (idxPlt < (sizeof(s_PltTable) / sizeof(s_PltTable[0])) ? s_PltTable[idxPlt].wArch : PROCESSOR_ARCHITECTURE_UNKNOWN);
  386. }
  387. /*****************************************************************************\
  388. * genValSvrArchitecture
  389. *
  390. * Returns the architecture platform of the server. The current architecture
  391. * running this dll.
  392. *
  393. \*****************************************************************************/
  394. WORD genValSvrArchitecture(VOID)
  395. {
  396. DWORD idxEnv;
  397. #if defined(_X86_)
  398. idxEnv = IDX_X86;
  399. #elif defined(_AMD64_)
  400. idxEnv = IDX_AMD64;
  401. #elif defined(_IA64_)
  402. idxEnv = IDX_I64;
  403. #endif
  404. return genValCliArchitecture(idxEnv);
  405. }
  406. /*****************************************************************************\
  407. * genIdxCliVersion
  408. *
  409. * This routine returns an index into the s_VerTable. The caller can refer
  410. * to this index for the client-version information.
  411. *
  412. \*****************************************************************************/
  413. DWORD genIdxCliVersion(
  414. DWORD dwCliInfo)
  415. {
  416. DWORD dwPlt = webGetOSPlatform(dwCliInfo);
  417. DWORD dwMaj = webGetOSMajorVer(dwCliInfo);
  418. DWORD dwMin = webGetOSMinorVer(dwCliInfo);
  419. if (dwMaj == 5)
  420. return IDX_SPLVER_3;
  421. if ((dwMaj == 4) && (dwPlt == VER_PLATFORM_WIN32_NT))
  422. return IDX_SPLVER_2;
  423. if ((dwMaj == 4) && (dwPlt == VER_PLATFORM_WIN32_WINDOWS))
  424. return IDX_SPLVER_0;
  425. return IDX_UNKNOWN;
  426. }
  427. /*****************************************************************************\
  428. * genStrCliVersion
  429. *
  430. * Returns a string representing the spooler-version directory. This is
  431. * the relative directory off the system32\spool\drivers\*\ path that contains
  432. * the drivers.
  433. *
  434. \*****************************************************************************/
  435. LPCTSTR genStrCliVersion(
  436. DWORD idxVer)
  437. {
  438. return (idxVer < (sizeof(s_VerTable) / sizeof(s_VerTable[0])) ? s_VerTable[idxVer] : NULL);
  439. }
  440. /*****************************************************************************\
  441. * genIdxFromStrVersion
  442. *
  443. * Returns an index that matches the client-version-string.
  444. *
  445. \*****************************************************************************/
  446. DWORD genIdxFromStrVersion(
  447. LPCTSTR lpszVer)
  448. {
  449. DWORD idx;
  450. DWORD cVer;
  451. cVer = sizeof(s_VerTable) / sizeof(s_VerTable[0]);
  452. for (idx = 0; idx < cVer; idx++) {
  453. if (lstrcmpi(lpszVer, s_VerTable[idx]) == 0)
  454. return idx;
  455. }
  456. return IDX_UNKNOWN;
  457. }
  458. /*****************************************************************************\
  459. * genUpdIPAddr
  460. *
  461. * Updates the registry with the current IP-Addr of this machine. If there
  462. * is already an entry in the registry and it's different than the one
  463. * currently established for the machine, then we return FALSE, and update
  464. * the entry.
  465. *
  466. \*****************************************************************************/
  467. BOOL genUpdIPAddr(VOID)
  468. {
  469. HKEY hKey;
  470. LRESULT lRet;
  471. LPSTR lpszCmp;
  472. DWORD cbData;
  473. DWORD dwIpCmp;
  474. DWORD dwIpReg;
  475. DWORD dwVal;
  476. BOOL bRet = TRUE;
  477. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  478. g_szPrtReg,
  479. 0,
  480. KEY_READ | KEY_WRITE,
  481. &hKey);
  482. if (lRet == ERROR_SUCCESS) {
  483. if (lpszCmp = genMBFromWC(g_szHttpServerName)) {
  484. // Get the IP-Addr associated with this machine.
  485. //
  486. dwIpCmp = GetIPAddr(lpszCmp);
  487. // Setup our registry-information so get/set a value.
  488. //
  489. dwVal = REG_DWORD;
  490. cbData = sizeof(DWORD);
  491. // Get what we already have stored there. If no value exists,
  492. // the write it out.
  493. //
  494. lRet = RegQueryValueEx(hKey,
  495. g_szIpAddr,
  496. NULL,
  497. &dwVal,
  498. (LPBYTE)&dwIpReg,
  499. &cbData);
  500. if ((lRet != ERROR_SUCCESS) || (dwIpReg != dwIpCmp)) {
  501. bRet = FALSE;
  502. RegSetValueEx(hKey,
  503. g_szIpAddr,
  504. 0,
  505. REG_DWORD,
  506. (LPBYTE)&dwIpCmp,
  507. cbData);
  508. }
  509. genGFree(lpszCmp, genGSize(lpszCmp));
  510. }
  511. RegCloseKey(hKey);
  512. }
  513. return bRet;
  514. }
  515. /*****************************************************************************\
  516. * genFrnName
  517. *
  518. * Returns a cluster-capable friendly-name.
  519. *
  520. \*****************************************************************************/
  521. LPTSTR genFrnName(
  522. LPCTSTR lpszFrnName)
  523. {
  524. DWORD cbSize;
  525. LPTSTR lpszName = NULL;
  526. // Calc size for friendly-name.
  527. //
  528. cbSize = lstrlen(lpszFrnName) + lstrlen(g_szPrintServerName) + 6;
  529. // Build it.
  530. //
  531. if (lpszName = (LPTSTR)genGAlloc(cbSize * sizeof(TCHAR)))
  532. {
  533. if (FAILED(StringCchPrintf(lpszName, cbSize, TEXT("\\\\%s\\%s"), g_szPrintServerName, lpszFrnName)))
  534. {
  535. genGFree(lpszName, genGSize(lpszName));
  536. lpszName = NULL;
  537. }
  538. }
  539. return lpszName;
  540. }
  541. /*****************************************************************************\
  542. * genChkSum (Local Routine)
  543. *
  544. * This routine checksums a string into a WORD value.
  545. *
  546. \*****************************************************************************/
  547. #define CRC_HI(wHi) (((wHi << 1) | (wHi & 0x8000)) ? 0x0001 : 0)
  548. #define CRC_LO(wLo) (((wLo >> 1) | (wLo & 0x0001)) ? 0x8000 : 0)
  549. WORD genChkSum(
  550. LPCTSTR lpszStr)
  551. {
  552. WORD wMask;
  553. DWORD idx;
  554. DWORD cLoop;
  555. DWORD cbStr;
  556. WORD wHi = 0;
  557. WORD wLo = 0;
  558. WORD wChkSum = 0;
  559. if (lpszStr && (cbStr = lstrlen(lpszStr))) {
  560. // Loop through the bytes (in WORD increments). This is an
  561. // optimized method in cyclying through bits.
  562. //
  563. cLoop = (cbStr / sizeof(WORD));
  564. for (idx = 0, wLo = 0, wHi = 0, wChkSum = 0; idx < cLoop; idx++) {
  565. wChkSum += *(((PWORD)lpszStr) + idx);
  566. wHi = CRC_HI(wHi) ^ wChkSum;
  567. wLo = CRC_LO(wLo) ^ wChkSum;
  568. }
  569. // If there's any extra bytes left over, then include that
  570. // in the checksum. Mask off any bytes that should be
  571. // excluded from the checksum.
  572. //
  573. if (cbStr & 3) {
  574. wMask = ((WORD)-1 >> ((sizeof(WORD) - (cbStr & 3)) * 8));
  575. wChkSum += ((*((PWORD)lpszStr + cLoop)) & wMask);
  576. wHi = CRC_HI(wHi) ^ wChkSum;
  577. wLo = CRC_LO(wLo) ^ wChkSum;
  578. }
  579. }
  580. return (wChkSum + wHi + wLo);
  581. }