Source code of Windows XP (NT5)
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

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