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.

630 lines
15 KiB

  1. /*****************************************************************************\
  2. * MODULE: spljob.c
  3. *
  4. * This module contains the routines to deal with spooling a job to file.
  5. *
  6. *
  7. * Copyright (C) 1996-1997 Microsoft Corporation
  8. * Copyright (C) 1996-1997 Hewlett Packard
  9. *
  10. * History:
  11. * 07-Oct-1996 HWP-Guys Initiated port from win95 to winNT
  12. * 14-Nov-1997 ChrisWil Added local-spooling functionality.
  13. *
  14. \*****************************************************************************/
  15. #include "precomp.h"
  16. #include "priv.h"
  17. /*****************************************************************************\
  18. * Spl_GetCurDir
  19. *
  20. * Returns string indicating current-directory.
  21. *
  22. \*****************************************************************************/
  23. LPTSTR Spl_GetCurDir(VOID)
  24. {
  25. DWORD cbSize;
  26. LPTSTR lpszDir = NULL;
  27. cbSize = GetCurrentDirectory(0, NULL);
  28. if (cbSize && (lpszDir = (LPTSTR)memAlloc((cbSize * sizeof(TCHAR)))))
  29. GetCurrentDirectory(cbSize, lpszDir);
  30. return lpszDir;
  31. }
  32. /*****************************************************************************\
  33. * Spl_GetDir
  34. *
  35. * Returns the spooler-directory where print-jobs are processed.
  36. *
  37. \*****************************************************************************/
  38. LPTSTR Spl_GetDir(VOID)
  39. {
  40. DWORD cbSize;
  41. LPTSTR lpszDir = NULL;
  42. if (*g_szDefSplDir)
  43. {
  44. size_t uSize = lstrlen (g_szDefSplDir) + 1;
  45. lpszDir = (LPTSTR) memAlloc(sizeof (TCHAR) * uSize);
  46. if (lpszDir)
  47. {
  48. StringCchCopy(lpszDir, uSize, g_szDefSplDir);
  49. }
  50. }
  51. return lpszDir;
  52. }
  53. /*****************************************************************************\
  54. * Spl_MemCheck (Local Routine)
  55. *
  56. * This routine checks for out-of-disk-space and out-of-memory conditions.
  57. *
  58. \*****************************************************************************/
  59. VOID Spl_MemCheck(
  60. LPCTSTR lpszDir)
  61. {
  62. ULARGE_INTEGER i64FreeBytesToCaller;
  63. ULARGE_INTEGER i64TotalBytes;
  64. LPTSTR lpszRoot;
  65. LPTSTR lpszPtr;
  66. // Look for out-of-diskspace
  67. //
  68. if (lpszRoot = memAllocStr(lpszDir)) {
  69. // Set the path to be only a root-drive-path.
  70. //
  71. if (lpszPtr = utlStrChr(lpszRoot, TEXT('\\'))) {
  72. lpszPtr++;
  73. if (*lpszPtr != TEXT('\0'))
  74. *lpszPtr = TEXT('\0');
  75. }
  76. // Get the drive-space information.
  77. //
  78. if (GetDiskFreeSpaceEx (lpszRoot, &i64FreeBytesToCaller, &i64TotalBytes, NULL)) {
  79. // We'll assume out-of-disk-space for anything less
  80. // then MIN_DISK_SPACE.
  81. //
  82. if (i64FreeBytesToCaller.QuadPart <= MIN_DISK_SPACE) {
  83. DBG_MSG(DBG_LEV_ERROR, (TEXT("Err : _inet_MemCheck : Out of disk space.")));
  84. SetLastError(ERROR_DISK_FULL);
  85. }
  86. }
  87. memFreeStr(lpszRoot);
  88. } else {
  89. DBG_MSG(DBG_LEV_ERROR, (TEXT("Err : _inet_MemCheck : Out of memory.")));
  90. SetLastError(ERROR_OUTOFMEMORY);
  91. }
  92. }
  93. /*****************************************************************************\
  94. * Spl_OpnFile (Local Routine)
  95. *
  96. * This routine creates/opens a spool-file.
  97. *
  98. \*****************************************************************************/
  99. HANDLE spl_OpnFile(
  100. LPCTSTR lpszFile)
  101. {
  102. HANDLE hFile;
  103. hFile = CreateFile(lpszFile,
  104. GENERIC_READ | GENERIC_WRITE,
  105. 0,
  106. NULL,
  107. CREATE_ALWAYS,
  108. FILE_ATTRIBUTE_NORMAL,
  109. NULL);
  110. return ((hFile && (hFile != INVALID_HANDLE_VALUE)) ? hFile : NULL);
  111. }
  112. /*****************************************************************************\
  113. * Spl_BldFile (Local Routine)
  114. *
  115. * This routine builds a spool-file-name. The returned file name is of the form.
  116. * c:\windows\system32\spool\printers\splnnn.tmp or
  117. * c:\windows\system32\spool\printers\tmpnnn.tmp
  118. *
  119. * The idJob argument is not used, it was previously used when the file
  120. * name was derived from the job id. This is not done anymore because it
  121. * leads to file name squatting issues in the spool directory.
  122. *
  123. \*****************************************************************************/
  124. LPTSTR spl_BldFile(
  125. DWORD idJob,
  126. DWORD dwType)
  127. {
  128. static CONST TCHAR s_szSpl[] = TEXT("spl");
  129. static CONST TCHAR s_szTmp[] = TEXT("tmp");
  130. HRESULT hRetval = E_FAIL;
  131. LPTSTR pszDir = NULL;
  132. LPTSTR pszFile = NULL;
  133. LPTSTR pszSplFile = NULL;
  134. UINT cchSize = 0;
  135. LPCTSTR pszPrefix = dwType == SPLFILE_TMP ? s_szTmp : s_szSpl;
  136. TCHAR szBuffer[MAX_PATH] = {0};
  137. pszDir = Spl_GetDir();
  138. hRetval = pszDir ? S_OK : GetLastErrorAsHResultAndFail();
  139. if (SUCCEEDED(hRetval))
  140. {
  141. hRetval = GetTempFileName(pszDir, pszPrefix, 0, szBuffer) ? S_OK : GetLastErrorAsHResult();
  142. }
  143. if (SUCCEEDED(hRetval))
  144. {
  145. cchSize = _tcslen(szBuffer) + 1;
  146. pszFile = (LPTSTR)memAlloc(cchSize * sizeof(TCHAR));
  147. hRetval = pszFile ? S_OK : E_OUTOFMEMORY;
  148. }
  149. if (SUCCEEDED(hRetval))
  150. {
  151. hRetval = StringCchCopy(pszFile, cchSize, szBuffer);
  152. }
  153. if (SUCCEEDED(hRetval))
  154. {
  155. pszSplFile = pszFile;
  156. pszFile = NULL;
  157. }
  158. if (pszFile)
  159. {
  160. memFreeStr(pszFile);
  161. }
  162. if (pszDir)
  163. {
  164. memFreeStr(pszDir);
  165. }
  166. if (FAILED(hRetval))
  167. {
  168. SetLastError(HRESULT_CODE(hRetval));
  169. }
  170. return pszSplFile;
  171. }
  172. /*****************************************************************************\
  173. * SplLock
  174. *
  175. * Open a stream interface to the spool file
  176. *
  177. \*****************************************************************************/
  178. CFileStream* SplLock(
  179. HANDLE hSpl)
  180. {
  181. PSPLFILE pSpl;
  182. CFileStream *pStream = NULL;
  183. if (pSpl = (PSPLFILE)hSpl) {
  184. pStream = new CFileStream (pSpl->hFile);
  185. pSpl->pStream = pStream;
  186. }
  187. return pStream;
  188. }
  189. /*****************************************************************************\
  190. * SplUnlock
  191. *
  192. * Close our file-mapping.
  193. *
  194. \*****************************************************************************/
  195. BOOL SplUnlock(
  196. HANDLE hSpl)
  197. {
  198. PSPLFILE pSpl;
  199. BOOL bRet = FALSE;
  200. if (pSpl = (PSPLFILE)hSpl) {
  201. if (pSpl->pStream) {
  202. delete pSpl->pStream;
  203. pSpl->pStream = NULL;
  204. }
  205. }
  206. return bRet;
  207. }
  208. /*****************************************************************************\
  209. * SplWrite
  210. *
  211. * Write data to our spool-file.
  212. *
  213. \*****************************************************************************/
  214. BOOL SplWrite(
  215. HANDLE hSpl,
  216. LPBYTE lpData,
  217. DWORD cbData,
  218. LPDWORD lpcbWr)
  219. {
  220. PSPLFILE pSpl;
  221. BOOL bRet = FALSE;
  222. HANDLE hToken = RevertToPrinterSelf();
  223. if (hToken) {
  224. if (pSpl = (PSPLFILE)hSpl) {
  225. // Write the data to our spool-file.
  226. //
  227. bRet = WriteFile(pSpl->hFile, lpData, cbData, lpcbWr, NULL);
  228. // If we failed, or our bytes written aren't what we
  229. // expected, then we need to check for out-of-memory.
  230. //
  231. if (!bRet || (cbData != *lpcbWr))
  232. Spl_MemCheck(pSpl->lpszFile);
  233. }
  234. if (!ImpersonatePrinterClient(hToken))
  235. {
  236. bRet = FALSE;
  237. }
  238. }
  239. return bRet;
  240. }
  241. /*****************************************************************************\
  242. * SplWrite
  243. *
  244. * Write data to our spool-file.
  245. *
  246. \*****************************************************************************/
  247. BOOL SplWrite(
  248. HANDLE hSpl,
  249. CStream *pStream)
  250. {
  251. PSPLFILE pSpl;
  252. BOOL bRet = FALSE;
  253. static DWORD cbBufSize = 32 * 1024; //Copy size is 32K
  254. PBYTE pBuf;
  255. DWORD cbTotal;
  256. HANDLE hToken = RevertToPrinterSelf();
  257. if (hToken) {
  258. if (pSpl = (PSPLFILE)hSpl) {
  259. pBuf = new BYTE[cbBufSize];
  260. if (pBuf && pStream->GetTotalSize (&cbTotal)) {
  261. DWORD cbRemain = cbTotal;
  262. while (cbRemain > 0 && bRet) {
  263. DWORD cbToRead = cbRemain > cbBufSize? cbBufSize:cbRemain;
  264. DWORD cbRead, cbWritten;
  265. if (pStream->Read (pBuf, cbToRead, &cbRead) && cbToRead == cbRead) {
  266. // Write the data to our spool-file.
  267. //
  268. bRet = WriteFile(pSpl->hFile, pBuf, cbRead, &cbWritten, NULL)
  269. && cbWritten == cbRead;
  270. if (bRet) {
  271. cbRemain -= cbToRead;
  272. }
  273. }
  274. else
  275. bRet = FALSE;
  276. }
  277. // If we failed, or our bytes written aren't what we
  278. // expected, then we need to check for out-of-memory.
  279. //
  280. if (!bRet)
  281. Spl_MemCheck(pSpl->lpszFile);
  282. }
  283. if (pBuf) {
  284. delete [] pBuf;
  285. }
  286. }
  287. if (!ImpersonatePrinterClient(hToken))
  288. {
  289. bRet = FALSE;
  290. }
  291. }
  292. return bRet;
  293. }
  294. BOOL PrivateSplFree(
  295. HANDLE hSpl)
  296. {
  297. BOOL bRet = FALSE;
  298. PSPLFILE pSpl;
  299. if (pSpl = (PSPLFILE)hSpl) {
  300. if (pSpl->pStream)
  301. delete pSpl->pStream;
  302. if (pSpl->hFile)
  303. CloseHandle(pSpl->hFile);
  304. bRet = DeleteFile(pSpl->lpszFile);
  305. if (pSpl->lpszFile)
  306. memFreeStr(pSpl->lpszFile);
  307. memFree(pSpl, sizeof(SPLFILE));
  308. }
  309. return bRet;
  310. }
  311. /*****************************************************************************\
  312. * SplFree (Local Routine)
  313. *
  314. * Free our spool-file. This will delete all information regarding the
  315. * file.
  316. *
  317. \*****************************************************************************/
  318. BOOL SplFree(
  319. HANDLE hSpl)
  320. {
  321. PSPLFILE pSpl;
  322. BOOL bRet = FALSE;
  323. HANDLE hToken = RevertToPrinterSelf();
  324. if (hToken) {
  325. bRet = PrivateSplFree (hSpl);
  326. if (!ImpersonatePrinterClient(hToken))
  327. {
  328. bRet = FALSE;
  329. }
  330. }
  331. return bRet;
  332. }
  333. /*****************************************************************************\
  334. * SplCreate (Local Routine)
  335. *
  336. * Create a unique file for processing our spool-file.
  337. *
  338. \*****************************************************************************/
  339. HANDLE SplCreate(
  340. DWORD idJob,
  341. DWORD dwType)
  342. {
  343. PSPLFILE pSpl = NULL;
  344. HANDLE hToken = RevertToPrinterSelf();
  345. if (hToken) {
  346. if (pSpl = (PSPLFILE) memAlloc(sizeof(SPLFILE))) {
  347. if (pSpl->lpszFile = spl_BldFile(idJob, dwType)) {
  348. if (pSpl->hFile = spl_OpnFile(pSpl->lpszFile)) {
  349. pSpl->pStream = NULL;
  350. } else {
  351. memFreeStr(pSpl->lpszFile);
  352. goto SplFail;
  353. }
  354. } else {
  355. SplFail:
  356. memFree(pSpl, sizeof(SPLFILE));
  357. pSpl = NULL;
  358. }
  359. }
  360. if (!ImpersonatePrinterClient(hToken))
  361. {
  362. (VOID)PrivateSplFree (pSpl);
  363. pSpl = NULL;
  364. }
  365. }
  366. return (HANDLE)pSpl;
  367. }
  368. /*****************************************************************************\
  369. * SplOpen (Local Routine)
  370. *
  371. * Open the handle to our spool-file.
  372. *
  373. \*****************************************************************************/
  374. BOOL SplOpen(
  375. HANDLE hSpl)
  376. {
  377. PSPLFILE pSpl;
  378. BOOL bRet = FALSE;
  379. HANDLE hToken = RevertToPrinterSelf();
  380. if (hToken) {
  381. if (pSpl = (PSPLFILE)hSpl) {
  382. if (pSpl->hFile == NULL) {
  383. // Open the file and store it in the object.
  384. //
  385. pSpl->hFile = CreateFile(pSpl->lpszFile,
  386. GENERIC_READ | GENERIC_WRITE,
  387. 0,
  388. NULL,
  389. OPEN_EXISTING,
  390. FILE_ATTRIBUTE_NORMAL,
  391. NULL);
  392. if (!pSpl->hFile || (pSpl->hFile == INVALID_HANDLE_VALUE))
  393. pSpl->hFile = NULL;
  394. else
  395. bRet = TRUE;
  396. } else {
  397. // Already open.
  398. //
  399. bRet = TRUE;
  400. }
  401. }
  402. if (!ImpersonatePrinterClient(hToken))
  403. {
  404. bRet = FALSE;
  405. }
  406. }
  407. return bRet;
  408. }
  409. /*****************************************************************************\
  410. * SplClose
  411. *
  412. * Close the spool-file.
  413. *
  414. \*****************************************************************************/
  415. BOOL SplClose(
  416. HANDLE hSpl)
  417. {
  418. PSPLFILE pSpl;
  419. BOOL bRet = FALSE;
  420. HANDLE hToken = RevertToPrinterSelf();
  421. if (hToken) {
  422. if (pSpl = (PSPLFILE)hSpl) {
  423. if (pSpl->hFile) {
  424. bRet = CloseHandle(pSpl->hFile);
  425. pSpl->hFile = NULL;
  426. } else {
  427. // Already closed.
  428. //
  429. bRet = TRUE;
  430. }
  431. }
  432. if (!ImpersonatePrinterClient(hToken))
  433. {
  434. bRet = FALSE;
  435. }
  436. }
  437. return bRet;
  438. }
  439. /*****************************************************************************\
  440. * SplClean
  441. *
  442. * Cleans out all spool-files in the spool-directory.
  443. *
  444. \*****************************************************************************/
  445. VOID SplClean(VOID)
  446. {
  447. LPTSTR lpszDir;
  448. LPTSTR lpszCur;
  449. LPTSTR lpszFiles;
  450. HANDLE hFind;
  451. DWORD cbSize;
  452. WIN32_FIND_DATA wfd;
  453. static CONST TCHAR s_szFmt[] = TEXT("%s\\%s*.*");
  454. // Get the spool-directory where our splipp files reside.
  455. //
  456. if (lpszDir = Spl_GetDir()) {
  457. if (lpszCur = Spl_GetCurDir()) {
  458. cbSize = utlStrSize(lpszDir) +
  459. utlStrSize(g_szSplPfx) +
  460. utlStrSize(s_szFmt);
  461. if (lpszFiles = (LPTSTR)memAlloc(cbSize)) {
  462. StringCbPrintf(lpszFiles, cbSize, s_szFmt, lpszDir, g_szSplPfx);
  463. if (SetCurrentDirectory(lpszDir)) {
  464. // Delete all the files that pertain to our criteria.
  465. //
  466. hFind = FindFirstFile(lpszFiles, &wfd);
  467. if (hFind && (hFind != INVALID_HANDLE_VALUE)) {
  468. do {
  469. DeleteFile(wfd.cFileName);
  470. } while (FindNextFile(hFind, &wfd));
  471. FindClose(hFind);
  472. }
  473. SetCurrentDirectory(lpszCur);
  474. }
  475. memFreeStr(lpszFiles);
  476. }
  477. memFreeStr(lpszCur);
  478. }
  479. memFreeStr(lpszDir);
  480. }
  481. }