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.

681 lines
14 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. libutil.c
  5. Abstract:
  6. Utility functions
  7. Environment:
  8. Windows NT printer drivers
  9. Revision History:
  10. 08/13/96 -davidx-
  11. Added CopyString functions and moved SPRINTF functions.
  12. 08/13/96 -davidx-
  13. Added devmode conversion routine and spooler API wrapper functions.
  14. 03/13/96 -davidx-
  15. Created it.
  16. --*/
  17. #include "lib.h"
  18. //
  19. // Digit characters used for converting numbers to ASCII
  20. //
  21. const CHAR gstrDigitString[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  22. //
  23. // Variable to control the amount of debug messages generated
  24. //
  25. #if DBG
  26. INT giDebugLevel = DBG_WARNING;
  27. #endif
  28. DWORD
  29. HashKeyword(
  30. LPCSTR pKeywordStr
  31. )
  32. /*++
  33. Routine Description:
  34. Generate a hash value for the given string.
  35. Arguments:
  36. pKeywordStr - The string to generate the hash value for,
  37. single byte ANSI null terminated.
  38. Return Value:
  39. Hash value.
  40. --*/
  41. {
  42. LPBYTE pbuf = (LPBYTE) pKeywordStr;
  43. DWORD dwHashValue = 0;
  44. //
  45. // Note that only the last 32 characters of the keyword string are significant.
  46. //
  47. while (*pbuf)
  48. dwHashValue = (dwHashValue << 1) ^ *pbuf++;
  49. return(dwHashValue);
  50. }
  51. PTSTR
  52. DuplicateString(
  53. IN LPCTSTR ptstrSrc
  54. )
  55. /*++
  56. Routine Description:
  57. Make a duplicate of the specified character string
  58. Arguments:
  59. ptstrSrc - Specifies the source string to be duplicated
  60. Return Value:
  61. Pointer to the duplicated string, NULL if there is an error
  62. --*/
  63. {
  64. PTSTR ptstrDest;
  65. INT iSize;
  66. if (ptstrSrc == NULL)
  67. return NULL;
  68. iSize = SIZE_OF_STRING(ptstrSrc);
  69. if (ptstrDest = MemAlloc(iSize))
  70. CopyMemory(ptstrDest, ptstrSrc, iSize);
  71. else
  72. ERR(("Couldn't duplicate string: %ws\n", ptstrSrc));
  73. return ptstrDest;
  74. }
  75. VOID
  76. CopyStringW(
  77. OUT PWSTR pwstrDest,
  78. IN PCWSTR pwstrSrc,
  79. IN INT iDestSize
  80. )
  81. /*++
  82. Routine Description:
  83. Copy Unicode string from source to destination
  84. Arguments:
  85. pwstrDest - Points to the destination buffer
  86. pwstrSrc - Points to source string
  87. iDestSize - Size of destination buffer (in characters)
  88. Return Value:
  89. NONE
  90. Note:
  91. If the source string is shorter than the destination buffer,
  92. unused chars in the destination buffer is filled with NUL.
  93. --*/
  94. {
  95. PWSTR pwstrEnd;
  96. ASSERT(pwstrDest && pwstrSrc && iDestSize > 0);
  97. pwstrEnd = pwstrDest + (iDestSize - 1);
  98. while ((pwstrDest < pwstrEnd) && ((*pwstrDest++ = *pwstrSrc++) != NUL))
  99. NULL;
  100. while (pwstrDest <= pwstrEnd)
  101. *pwstrDest++ = NUL;
  102. }
  103. VOID
  104. CopyStringA(
  105. OUT PSTR pstrDest,
  106. IN PCSTR pstrSrc,
  107. IN INT iDestSize
  108. )
  109. /*++
  110. Routine Description:
  111. Copy ANSI string from source to destination
  112. Arguments:
  113. pstrDest - Points to the destination buffer
  114. pstrSrc - Points to source string
  115. iDestSize - Size of destination buffer (in characters)
  116. Return Value:
  117. NONE
  118. Note:
  119. If the source string is shorter than the destination buffer,
  120. unused chars in the destination buffer is filled with NUL.
  121. --*/
  122. {
  123. PSTR pstrEnd;
  124. ASSERT(pstrDest && pstrSrc && iDestSize > 0);
  125. pstrEnd = pstrDest + (iDestSize - 1);
  126. while ((pstrDest < pstrEnd) && (*pstrDest++ = *pstrSrc++) != NUL)
  127. NULL;
  128. while (pstrDest <= pstrEnd)
  129. *pstrDest++ = NUL;
  130. }
  131. PVOID
  132. MyGetPrinter(
  133. IN HANDLE hPrinter,
  134. IN DWORD dwLevel
  135. )
  136. /*++
  137. Routine Description:
  138. Wrapper function for GetPrinter spooler API
  139. Arguments:
  140. hPrinter - Identifies the printer in question
  141. dwLevel - Specifies the level of PRINTER_INFO_x structure requested
  142. Return Value:
  143. Pointer to a PRINTER_INFO_x structure, NULL if there is an error
  144. --*/
  145. {
  146. PVOID pv = NULL;
  147. DWORD dwBytesNeeded;
  148. if (!GetPrinter(hPrinter, dwLevel, NULL, 0, &dwBytesNeeded) &&
  149. GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  150. (pv = MemAlloc(dwBytesNeeded)) &&
  151. GetPrinter(hPrinter, dwLevel, pv, dwBytesNeeded, &dwBytesNeeded))
  152. {
  153. return pv;
  154. }
  155. ERR(("GetPrinter failed: %d\n", GetLastError()));
  156. MemFree(pv);
  157. return NULL;
  158. }
  159. PVOID
  160. MyEnumForms(
  161. IN HANDLE hPrinter,
  162. IN DWORD dwLevel,
  163. OUT PDWORD pdwFormsReturned
  164. )
  165. /*++
  166. Routine Description:
  167. Wrapper function for EnumForms spooler API
  168. Arguments:
  169. hPrinter - Identifies the printer in question
  170. dwLevel - Specifies the level of FORM_INFO_x structure requested
  171. pdwFormsReturned - Returns the number of FORM_INFO_x structures enumerated
  172. Return Value:
  173. Pointer to an array of FORM_INFO_x structures,
  174. NULL if there is an error
  175. --*/
  176. {
  177. PVOID pv = NULL;
  178. DWORD dwBytesNeeded;
  179. if (!EnumForms(hPrinter, dwLevel, NULL, 0, &dwBytesNeeded, pdwFormsReturned) &&
  180. GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  181. (pv = MemAlloc(dwBytesNeeded)) &&
  182. EnumForms(hPrinter, dwLevel, pv, dwBytesNeeded, &dwBytesNeeded, pdwFormsReturned))
  183. {
  184. return pv;
  185. }
  186. ERR(("EnumForms failed: %d\n", GetLastError()));
  187. MemFree(pv);
  188. *pdwFormsReturned = 0;
  189. return NULL;
  190. }
  191. #ifndef KERNEL_MODE
  192. PVOID
  193. MyGetForm(
  194. IN HANDLE hPrinter,
  195. IN PTSTR ptstrFormName,
  196. IN DWORD dwLevel
  197. )
  198. /*++
  199. Routine Description:
  200. Wrapper function for GetForm spooler API
  201. Arguments:
  202. hPrinter - Identifies the printer in question
  203. ptstrFormName - Specifies the name of interested form
  204. dwLevel - Specifies the level of FORM_INFO_x structure requested
  205. Return Value:
  206. Pointer to a FORM_INFO_x structures, NULL if there is an error
  207. --*/
  208. {
  209. PVOID pv = NULL;
  210. DWORD cb;
  211. if (!GetForm(hPrinter, ptstrFormName, dwLevel, NULL, 0, &cb) &&
  212. GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  213. (pv = MemAlloc(cb)) &&
  214. GetForm(hPrinter, ptstrFormName, dwLevel, pv, cb, &cb))
  215. {
  216. return pv;
  217. }
  218. ERR(("GetForm failed: %d\n", GetLastError()));
  219. MemFree(pv);
  220. return NULL;
  221. }
  222. #endif // !KERNEL_MODE
  223. PVOID
  224. MyGetPrinterDriver(
  225. IN HANDLE hPrinter,
  226. IN HDEV hDev,
  227. IN DWORD dwLevel
  228. )
  229. /*++
  230. Routine Description:
  231. Wrapper function for GetPrinterDriver spooler API
  232. Arguments:
  233. hPrinter - Identifies the printer in question
  234. hDev - GDI handle to current printer device context
  235. dwLevel - Specifies the level of DRIVER_INFO_x structure requested
  236. Return Value:
  237. Pointer to a DRIVER_INFO_x structure, NULL if there is an error
  238. --*/
  239. {
  240. #if !defined(WINNT_40) || !defined(KERNEL_MODE)
  241. PVOID pv = NULL;
  242. DWORD dwBytesNeeded;
  243. if (!GetPrinterDriver(hPrinter, NULL, dwLevel, NULL, 0, &dwBytesNeeded) &&
  244. GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  245. (pv = MemAlloc(dwBytesNeeded)) &&
  246. GetPrinterDriver(hPrinter, NULL, dwLevel, pv, dwBytesNeeded, &dwBytesNeeded))
  247. {
  248. return pv;
  249. }
  250. ERR(("GetPrinterDriver failed: %d\n", GetLastError()));
  251. MemFree(pv);
  252. #else // WINNT_40 && KERNEL_MODE
  253. PDRIVER_INFO_3 pDriverInfo3 = NULL;
  254. ASSERT(hDev != NULL);
  255. if (hDev)
  256. {
  257. //
  258. // hDev is available, so we can use Eng-calls to get driver_info_3 fields.
  259. //
  260. PWSTR pwstrDriverFile, pwstrDataFile;
  261. INT iDriverNameSize, iDataNameSize;
  262. PWSTR pwstrDepFiles;
  263. DWORD dwDepSize, dwDepSizeWithPath;
  264. PTSTR ptstrDriverDir = NULL;
  265. //
  266. // EngGetPrinterDriver is not available on NT4. So we'll fake a
  267. // DRIVER_INFO_3 structure and fill in pDriverPath and pDataFile fields.
  268. //
  269. pwstrDriverFile = EngGetDriverName(hDev);
  270. pwstrDataFile = EngGetPrinterDataFileName(hDev);
  271. if (!pwstrDriverFile || !pwstrDataFile)
  272. {
  273. RIP(("Driver and/or data filename is NULL\n"));
  274. return NULL;
  275. }
  276. //
  277. // The pDependentFiles field is currently only used by PS driver.
  278. //
  279. pwstrDepFiles = PtstrGetPrinterDataString(hPrinter, REGVAL_DEPFILES, &dwDepSize);
  280. if (pwstrDepFiles && !BVerifyMultiSZ(pwstrDepFiles, dwDepSize))
  281. {
  282. RIP(("Dependent file list is not in MULTI_SZ format\n"));
  283. MemFree(pwstrDepFiles);
  284. pwstrDepFiles = NULL;
  285. }
  286. if (pwstrDepFiles && ((ptstrDriverDir = PtstrGetDriverDirectory((LPCTSTR)pwstrDriverFile)) == NULL))
  287. {
  288. RIP(("Can't get driver directory from driver file name\n"));
  289. MemFree(pwstrDepFiles);
  290. pwstrDepFiles = NULL;
  291. }
  292. iDriverNameSize = SIZE_OF_STRING(pwstrDriverFile);
  293. iDataNameSize = SIZE_OF_STRING(pwstrDataFile);
  294. if (pwstrDepFiles == NULL)
  295. dwDepSizeWithPath = 0;
  296. else
  297. dwDepSizeWithPath = dwDepSize + DwCountStringsInMultiSZ((LPCTSTR)pwstrDepFiles)
  298. * _tcslen(ptstrDriverDir) * sizeof(TCHAR);
  299. pDriverInfo3 = MemAllocZ(sizeof(DRIVER_INFO_3) + iDriverNameSize+iDataNameSize+dwDepSizeWithPath);
  300. if (pDriverInfo3 == NULL)
  301. {
  302. ERR(("Memory allocation failed\n"));
  303. MemFree(pwstrDepFiles);
  304. MemFree(ptstrDriverDir);
  305. return NULL;
  306. }
  307. pDriverInfo3->cVersion = 3;
  308. pDriverInfo3->pDriverPath = (PWSTR) ((PBYTE) pDriverInfo3 + sizeof(DRIVER_INFO_3));
  309. pDriverInfo3->pDataFile = (PWSTR) ((PBYTE) pDriverInfo3->pDriverPath + iDriverNameSize);
  310. CopyMemory(pDriverInfo3->pDriverPath, pwstrDriverFile, iDriverNameSize);
  311. CopyMemory(pDriverInfo3->pDataFile, pwstrDataFile, iDataNameSize);
  312. if (pwstrDepFiles)
  313. {
  314. PTSTR ptstrSrc, ptstrDest;
  315. INT iDirLen;
  316. ptstrSrc = pwstrDepFiles;
  317. ptstrDest = pDriverInfo3->pDependentFiles = (PWSTR) ((PBYTE) pDriverInfo3->pDataFile + iDataNameSize);
  318. iDirLen = _tcslen(ptstrDriverDir);
  319. while (*ptstrSrc)
  320. {
  321. INT iNameLen;
  322. //
  323. // Copy the driver dir path (the last char is '\')
  324. //
  325. CopyMemory(ptstrDest, ptstrDriverDir, iDirLen * sizeof(TCHAR));
  326. ptstrDest += iDirLen;
  327. //
  328. // Copy the dependent file name
  329. //
  330. iNameLen = _tcslen(ptstrSrc);
  331. CopyMemory(ptstrDest, ptstrSrc, iNameLen * sizeof(TCHAR));
  332. ptstrDest += iNameLen + 1;
  333. ptstrSrc += iNameLen + 1;
  334. }
  335. }
  336. MemFree(pwstrDepFiles);
  337. MemFree(ptstrDriverDir);
  338. return((PVOID)pDriverInfo3);
  339. }
  340. #endif // WINNT_40 && KERNEL_MODE
  341. return NULL;
  342. }
  343. VOID
  344. VGetSpoolerEmfCaps(
  345. IN HANDLE hPrinter,
  346. OUT PBOOL pbNupOption,
  347. OUT PBOOL pbReversePrint,
  348. IN DWORD cbOut,
  349. OUT PVOID pSplCaps
  350. )
  351. /*++
  352. Routine Description:
  353. Figure out what EMF features (such as N-up and reverse-order printing)
  354. the spooler can support
  355. Arguments:
  356. hPrinter - Handle to the current printer
  357. pbNupOption - Whether spooler supports N-up
  358. pbReversePrint - Whether spooler supports reverse-order printing
  359. cbOut - size in byte of output buffer pointed by pSplCaps
  360. pSplCaps - Get all spooler caps
  361. Return Value:
  362. NONE
  363. --*/
  364. #define REGVAL_EMFCAPS TEXT("PrintProcCaps_EMF")
  365. {
  366. PVOID pvData;
  367. DWORD dwSize, dwType, dwStatus;
  368. if (pbNupOption)
  369. *pbNupOption = FALSE;
  370. if (pbReversePrint)
  371. *pbReversePrint = FALSE;
  372. #if !defined(WINNT_40)
  373. pvData = NULL;
  374. dwStatus = GetPrinterData(hPrinter, REGVAL_EMFCAPS, &dwType, NULL, 0, &dwSize);
  375. if ((dwStatus == ERROR_MORE_DATA || dwStatus == ERROR_SUCCESS) &&
  376. (dwSize >= sizeof(PRINTPROCESSOR_CAPS_1)) &&
  377. (pvData = MemAlloc(dwSize)) &&
  378. (GetPrinterData(hPrinter, REGVAL_EMFCAPS, &dwType, pvData, dwSize, &dwSize) == ERROR_SUCCESS))
  379. {
  380. PPRINTPROCESSOR_CAPS_1 pEmfCaps = pvData;
  381. if (pbNupOption)
  382. *pbNupOption = (pEmfCaps->dwNupOptions & ~1) != 0;
  383. if (pbReversePrint)
  384. *pbReversePrint = (pEmfCaps->dwPageOrderFlags & REVERSE_PRINT) != 0;
  385. if (pSplCaps)
  386. {
  387. CopyMemory(pSplCaps,
  388. pEmfCaps,
  389. min(cbOut, sizeof(PRINTPROCESSOR_CAPS_1)));
  390. }
  391. }
  392. else
  393. {
  394. ERR(("GetPrinterData PrintProcCaps_EMF failed: %d\n", dwStatus));
  395. }
  396. MemFree(pvData);
  397. #endif // !WINNT_40
  398. }
  399. PCSTR
  400. StripDirPrefixA(
  401. IN PCSTR pstrFilename
  402. )
  403. /*++
  404. Routine Description:
  405. Strip the directory prefix off a filename (ANSI version)
  406. Arguments:
  407. pstrFilename - Pointer to filename string
  408. Return Value:
  409. Pointer to the last component of a filename (without directory prefix)
  410. --*/
  411. {
  412. PCSTR pstr;
  413. if (pstr = strrchr(pstrFilename, PATH_SEPARATOR))
  414. return pstr + 1;
  415. return pstrFilename;
  416. }
  417. #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
  418. PVOID
  419. MemRealloc(
  420. IN PVOID pvOldMem,
  421. IN DWORD cbOld,
  422. IN DWORD cbNew
  423. )
  424. /*++
  425. Routine Description:
  426. Change the size of a specified memory block. The size can increase
  427. or decrease.
  428. Arguments:
  429. pvOldMem - Pointer to the old memory block to be reallocated.
  430. cbOld - old size in bytes of the memory block
  431. cbNew - new size in bytes of the reallocated memory block
  432. Return Value:
  433. If succeeds, it returns pointer to the reallocated memory block.
  434. Otherwise, it returns NULL.
  435. --*/
  436. {
  437. PVOID pvNewMem;
  438. if (!(pvNewMem = MemAlloc(cbNew)))
  439. {
  440. ERR(("Memory allocation failed\n"));
  441. return NULL;
  442. }
  443. if (pvOldMem)
  444. {
  445. if (cbOld)
  446. {
  447. CopyMemory(pvNewMem, pvOldMem, min(cbOld, cbNew));
  448. }
  449. MemFree(pvOldMem);
  450. }
  451. return pvNewMem;
  452. }
  453. #endif // !KERNEL_MODE || USERMODE_DRIVER