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.

1264 lines
26 KiB

  1. /*++
  2. Copyright (c) 1990-1996 Microsoft Corporation
  3. All rights reserved
  4. Module Name:
  5. kmspool.c
  6. Abstract:
  7. Spooler API entry points for Kernel Clients.
  8. Author:
  9. Steve Wilson (NT) (swilson) 1-Jun-95 (Ported from client\winspool.c)
  10. Environment:
  11. User Mode -Win32
  12. Revision History:
  13. Matthew Felton (mattfe) May-96 Driver Hooks
  14. --*/
  15. #include "precomp.h"
  16. #include "server.h"
  17. #include "client.h"
  18. #include "yspool.h"
  19. #include "kmspool.h"
  20. //
  21. // Globals
  22. //
  23. #define ENTER_WAIT_LIST() EnterCriticalSection(&ThreadCriticalSection)
  24. #define EXIT_WAIT_LIST() LeaveCriticalSection(&ThreadCriticalSection)
  25. LPWSTR szEnvironment = LOCAL_ENVIRONMENT;
  26. //
  27. // Printer Attributes
  28. //
  29. #define SPLPRINTER_USER_MODE_PRINTER_DRIVER TEXT("SPLUserModePrinterDriver")
  30. BOOL
  31. ValidatePrinterHandle(
  32. HANDLE hPrinter
  33. );
  34. BOOL
  35. DriverEndPageHook(
  36. PSPOOL pSpool
  37. );
  38. BOOL
  39. DriverStartPageHook(
  40. PSPOOL pSpool
  41. );
  42. BOOL
  43. DriverWritePrinterHook(
  44. PSPOOL pSpool,
  45. LPVOID pBuf,
  46. DWORD cbBuf,
  47. LPDWORD pcWritten
  48. );
  49. VOID
  50. DriverEndDocHook(
  51. PSPOOL pSpool
  52. );
  53. DWORD
  54. DriverStartDocHook(
  55. PSPOOL pSpool,
  56. DWORD JobId
  57. );
  58. VOID
  59. DriverClosePrinterHook(
  60. PSPOOL pSpool
  61. );
  62. VOID
  63. DriverAbortPrinterHook(
  64. PSPOOL pSpool
  65. );
  66. // Simple for Now !!!
  67. DWORD
  68. TranslateExceptionCode(
  69. DWORD ExceptionCode
  70. )
  71. {
  72. switch (ExceptionCode) {
  73. case EXCEPTION_ACCESS_VIOLATION:
  74. case EXCEPTION_DATATYPE_MISALIGNMENT:
  75. case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
  76. case EXCEPTION_FLT_DENORMAL_OPERAND:
  77. case EXCEPTION_FLT_DIVIDE_BY_ZERO:
  78. case EXCEPTION_FLT_INEXACT_RESULT:
  79. case EXCEPTION_FLT_INVALID_OPERATION:
  80. case EXCEPTION_FLT_OVERFLOW:
  81. case EXCEPTION_FLT_STACK_CHECK:
  82. case EXCEPTION_FLT_UNDERFLOW:
  83. case EXCEPTION_INT_DIVIDE_BY_ZERO:
  84. case EXCEPTION_INT_OVERFLOW:
  85. case EXCEPTION_PRIV_INSTRUCTION:
  86. case ERROR_NOACCESS:
  87. case RPC_S_INVALID_BOUND:
  88. return ERROR_INVALID_PARAMETER;
  89. break;
  90. default:
  91. return ExceptionCode;
  92. }
  93. }
  94. BOOL
  95. KMOpenPrinterW(
  96. LPWSTR pPrinterName,
  97. LPHANDLE phPrinter,
  98. LPPRINTER_DEFAULTS pDefault
  99. )
  100. {
  101. BOOL ReturnValue;
  102. DEVMODE_CONTAINER DevModeContainer;
  103. HANDLE hPrinter;
  104. PSPOOL pSpool;
  105. DWORD dwSize = 0;
  106. if (pDefault && pDefault->pDevMode)
  107. {
  108. dwSize = pDefault->pDevMode->dmSize + pDefault->pDevMode->dmDriverExtra;
  109. if (dwSize) {
  110. DevModeContainer.cbBuf = pDefault->pDevMode->dmSize +
  111. pDefault->pDevMode->dmDriverExtra;
  112. DevModeContainer.pDevMode = (LPBYTE)pDefault->pDevMode;
  113. } else {
  114. DevModeContainer.cbBuf = 0;
  115. DevModeContainer.pDevMode = NULL;
  116. }
  117. }
  118. else
  119. {
  120. DevModeContainer.cbBuf = 0;
  121. DevModeContainer.pDevMode = NULL;
  122. }
  123. try {
  124. if (ReturnValue = YOpenPrinter(pPrinterName, &hPrinter,
  125. pDefault ? pDefault->pDatatype : NULL,
  126. &DevModeContainer,
  127. pDefault ? pDefault->DesiredAccess : 0,
  128. NATIVE_CALL )) {
  129. SetLastError(ReturnValue);
  130. ReturnValue = FALSE;
  131. } else
  132. ReturnValue = TRUE;
  133. } except(1) {
  134. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  135. ReturnValue = FALSE;
  136. }
  137. if (ReturnValue) {
  138. pSpool = AllocSplMem(sizeof(SPOOL));
  139. if (pSpool) {
  140. memset(pSpool, 0, sizeof(SPOOL));
  141. pSpool->signature = SP_SIGNATURE;
  142. pSpool->hPrinter = hPrinter;
  143. pSpool->cThreads = -1;
  144. //
  145. // This is to fix passing a bad pHandle to OpenPrinter!!
  146. //
  147. try {
  148. *phPrinter = pSpool;
  149. } except(1) {
  150. YClosePrinter(&hPrinter, NATIVE_CALL);
  151. FreeSplMem(pSpool);
  152. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  153. return FALSE;
  154. }
  155. } else {
  156. YClosePrinter(&hPrinter, NATIVE_CALL);
  157. ReturnValue = FALSE;
  158. }
  159. }
  160. return ReturnValue;
  161. }
  162. BOOL
  163. KMGetFormW(
  164. HANDLE hPrinter,
  165. LPWSTR pFormName,
  166. DWORD Level,
  167. LPBYTE pForm,
  168. DWORD cbBuf,
  169. LPDWORD pcbNeeded
  170. )
  171. {
  172. BOOL ReturnValue;
  173. DWORD *pOffsets;
  174. PSPOOL pSpool = (PSPOOL)hPrinter;
  175. if (!ValidatePrinterHandle(hPrinter)) {
  176. return(FALSE);
  177. }
  178. switch (Level) {
  179. case 1:
  180. pOffsets = FormInfo1Offsets;
  181. break;
  182. default:
  183. SetLastError(ERROR_INVALID_LEVEL);
  184. return FALSE;
  185. }
  186. try {
  187. if (pForm)
  188. memset(pForm, 0, cbBuf);
  189. if (ReturnValue = YGetForm(pSpool->hPrinter, pFormName, Level, pForm,
  190. cbBuf, pcbNeeded, NATIVE_CALL)) {
  191. SetLastError(ReturnValue);
  192. ReturnValue = FALSE;
  193. } else {
  194. ReturnValue = TRUE;
  195. }
  196. } except(1) {
  197. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  198. ReturnValue = FALSE;
  199. }
  200. return ReturnValue;
  201. }
  202. BOOL
  203. KMEnumFormsW(
  204. HANDLE hPrinter,
  205. DWORD Level,
  206. LPBYTE pForm,
  207. DWORD cbBuf,
  208. LPDWORD pcbNeeded,
  209. LPDWORD pcReturned
  210. )
  211. {
  212. BOOL ReturnValue;
  213. DWORD cbStruct;
  214. DWORD *pOffsets;
  215. PSPOOL pSpool = (PSPOOL)hPrinter;
  216. if (!ValidatePrinterHandle(hPrinter)) {
  217. return(FALSE);
  218. }
  219. switch (Level) {
  220. case 1:
  221. pOffsets = FormInfo1Offsets;
  222. cbStruct = sizeof(FORM_INFO_1);
  223. break;
  224. default:
  225. SetLastError(ERROR_INVALID_LEVEL);
  226. return FALSE;
  227. }
  228. try {
  229. if (pForm)
  230. memset(pForm, 0, cbBuf);
  231. if (ReturnValue = YEnumForms(pSpool->hPrinter, Level, pForm, cbBuf,
  232. pcbNeeded, pcReturned, NATIVE_CALL)) {
  233. SetLastError(ReturnValue);
  234. ReturnValue = FALSE;
  235. } else {
  236. ReturnValue = TRUE;
  237. }
  238. } except(1) {
  239. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  240. ReturnValue = FALSE;
  241. }
  242. return ReturnValue;
  243. }
  244. BOOL
  245. KMGetPrinterW(
  246. HANDLE hPrinter,
  247. DWORD Level,
  248. LPBYTE pPrinter,
  249. DWORD cbBuf,
  250. LPDWORD pcbNeeded
  251. )
  252. {
  253. BOOL ReturnValue;
  254. DWORD *pOffsets;
  255. PSPOOL pSpool = (PSPOOL)hPrinter;
  256. if (!ValidatePrinterHandle(hPrinter)) {
  257. return(FALSE);
  258. }
  259. switch (Level) {
  260. case 1:
  261. pOffsets = PrinterInfo1Offsets;
  262. break;
  263. case 2:
  264. pOffsets = PrinterInfo2Offsets;
  265. break;
  266. case 3:
  267. pOffsets = PrinterInfo3Offsets;
  268. break;
  269. case 4:
  270. pOffsets = PrinterInfo4Offsets;
  271. break;
  272. case 5:
  273. pOffsets = PrinterInfo5Offsets;
  274. break;
  275. default:
  276. SetLastError(ERROR_INVALID_LEVEL);
  277. return FALSE;
  278. }
  279. try {
  280. if (pPrinter)
  281. memset(pPrinter, 0, cbBuf);
  282. if (ReturnValue = YGetPrinter(pSpool->hPrinter, Level, pPrinter, cbBuf, pcbNeeded, NATIVE_CALL)) {
  283. SetLastError(ReturnValue);
  284. ReturnValue = FALSE;
  285. } else {
  286. ReturnValue = TRUE;
  287. }
  288. } except(1) {
  289. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  290. ReturnValue = FALSE;
  291. }
  292. return ReturnValue;
  293. }
  294. BOOL
  295. KMGetPrinterDriverW(
  296. HANDLE hPrinter,
  297. LPWSTR pEnvironment,
  298. DWORD Level,
  299. LPBYTE pDriverInfo,
  300. DWORD cbBuf,
  301. LPDWORD pcbNeeded
  302. )
  303. {
  304. BOOL ReturnValue;
  305. PSPOOL pSpool = (PSPOOL)hPrinter;
  306. DWORD dwServerMajorVersion;
  307. DWORD dwServerMinorVersion;
  308. if (!ValidatePrinterHandle(hPrinter)) {
  309. return(FALSE);
  310. }
  311. if (Level < 1 || Level > 3) {
  312. SetLastError(ERROR_INVALID_LEVEL);
  313. return FALSE;
  314. }
  315. try {
  316. if (pDriverInfo)
  317. memset(pDriverInfo, 0, cbBuf);
  318. if (!pEnvironment || !*pEnvironment)
  319. pEnvironment = szEnvironment;
  320. if (ReturnValue = YGetPrinterDriver2(pSpool->hPrinter, pEnvironment,
  321. Level, pDriverInfo, cbBuf,
  322. pcbNeeded,
  323. (DWORD)-1, (DWORD)-1,
  324. &dwServerMajorVersion,
  325. &dwServerMinorVersion,
  326. NATIVE_CALL
  327. )) {
  328. SetLastError(ReturnValue);
  329. ReturnValue = FALSE;
  330. } else {
  331. ReturnValue = TRUE;
  332. }
  333. } except(1) {
  334. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  335. ReturnValue = FALSE;
  336. }
  337. return ReturnValue;
  338. }
  339. DWORD
  340. KMGetPrinterDataW(
  341. HANDLE hPrinter,
  342. LPWSTR pValueName,
  343. LPDWORD pType,
  344. LPBYTE pData,
  345. DWORD nSize,
  346. LPDWORD pcbNeeded
  347. )
  348. {
  349. DWORD ReturnValue = 0;
  350. PSPOOL pSpool = (PSPOOL)hPrinter;
  351. if (!ValidatePrinterHandle(hPrinter)) {
  352. return ERROR_INVALID_HANDLE;
  353. }
  354. //
  355. // The user should be able to pass in NULL for buffer, and
  356. // 0 for size. However, the RPC interface specifies a ref pointer,
  357. // so we must pass in a valid pointer. Pass in a pointer to
  358. // ReturnValue (this is just a dummy pointer).
  359. //
  360. if( !pData && !nSize ){
  361. pData = (PBYTE)&ReturnValue;
  362. }
  363. try {
  364. ReturnValue = YGetPrinterData(pSpool->hPrinter, pValueName, pType,
  365. pData, nSize, pcbNeeded, NATIVE_CALL);
  366. } except(1) {
  367. ReturnValue = TranslateExceptionCode(GetExceptionCode());
  368. }
  369. return ReturnValue;
  370. }
  371. DWORD
  372. KMSetPrinterDataW(
  373. HANDLE hPrinter,
  374. LPWSTR pValueName,
  375. DWORD Type,
  376. LPBYTE pData,
  377. DWORD cbData
  378. )
  379. {
  380. DWORD ReturnValue = 0;
  381. PSPOOL pSpool = (PSPOOL)hPrinter;
  382. if (!ValidatePrinterHandle(hPrinter)) {
  383. return ERROR_INVALID_HANDLE;
  384. }
  385. try {
  386. ReturnValue = YSetPrinterData(pSpool->hPrinter, pValueName, Type,
  387. pData, cbData, NATIVE_CALL);
  388. } except(1) {
  389. ReturnValue = TranslateExceptionCode(GetExceptionCode());
  390. }
  391. return ReturnValue;
  392. }
  393. DWORD
  394. KMStartDocPrinterW(
  395. HANDLE hPrinter,
  396. DWORD Level,
  397. LPBYTE pDocInfo
  398. )
  399. {
  400. BOOL ReturnValue;
  401. DWORD JobId;
  402. GENERIC_CONTAINER DocInfoContainer;
  403. PSPOOL pSpool = (PSPOOL)hPrinter;
  404. try {
  405. if (!ValidatePrinterHandle(hPrinter)) {
  406. return(FALSE);
  407. }
  408. DBGMSG(DBG_TRACE,("Entered KMStartDocPrinterW side hPrinter = %x\n", hPrinter));
  409. if (Level != 1) {
  410. SetLastError(ERROR_INVALID_LEVEL);
  411. return FALSE;
  412. }
  413. DocInfoContainer.Level = Level;
  414. DocInfoContainer.pData = pDocInfo;
  415. try {
  416. if (ReturnValue = YStartDocPrinter(pSpool->hPrinter,
  417. (LPDOC_INFO_CONTAINER)&DocInfoContainer,
  418. &JobId, NATIVE_CALL)) {
  419. SetLastError(ReturnValue);
  420. ReturnValue = FALSE;
  421. } else
  422. ReturnValue = JobId;
  423. } except(1) {
  424. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  425. ReturnValue = FALSE;
  426. }
  427. if (ReturnValue) {
  428. ReturnValue = DriverStartDocHook( pSpool, JobId );
  429. if ( ReturnValue )
  430. pSpool->Status |= SPOOL_STATUS_STARTDOC;
  431. }
  432. return ReturnValue;
  433. } except (1) {
  434. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  435. return(FALSE);
  436. }
  437. }
  438. BOOL
  439. KMEndDocPrinter(
  440. HANDLE hPrinter
  441. )
  442. {
  443. BOOL ReturnValue;
  444. PSPOOL pSpool = (PSPOOL)hPrinter;
  445. try {
  446. if (!ValidatePrinterHandle(hPrinter)) {
  447. return(FALSE);
  448. }
  449. pSpool->Status &= ~SPOOL_STATUS_STARTDOC;
  450. DriverEndDocHook( pSpool );
  451. try {
  452. if (ReturnValue = YEndDocPrinter(pSpool->hPrinter, NATIVE_CALL)) {
  453. SetLastError(ReturnValue);
  454. ReturnValue = FALSE;
  455. } else
  456. ReturnValue = TRUE;
  457. } except(1) {
  458. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  459. ReturnValue = FALSE;
  460. }
  461. DBGMSG(DBG_TRACE, ("Exit EndDocPrinter - client side hPrinter %x\n", hPrinter));
  462. return ReturnValue;
  463. } except (1) {
  464. SetLastError(ERROR_INVALID_HANDLE);
  465. return(FALSE);
  466. }
  467. }
  468. BOOL
  469. KMWritePrinter(
  470. HANDLE hPrinter,
  471. LPVOID pBuf,
  472. DWORD cbBuf,
  473. LPDWORD pcWritten
  474. )
  475. {
  476. BOOL ReturnValue = TRUE;
  477. PSPOOL pSpool = (PSPOOL)hPrinter;
  478. DBGMSG(DBG_TRACE, ("WritePrinter - hPrinter %x pBuf %x cbBuf %d pcWritten %x\n",
  479. hPrinter, pBuf, cbBuf, pcWritten));
  480. if (!ValidatePrinterHandle(hPrinter)) {
  481. return(FALSE);
  482. }
  483. *pcWritten = 0;
  484. if ( !(pSpool->Status & SPOOL_STATUS_STARTDOC) ) {
  485. SetLastError(ERROR_SPL_NO_STARTDOC);
  486. return FALSE;
  487. }
  488. //
  489. // Call Printer Drivers User Mode WritePrinter Hook
  490. //
  491. if ( pSpool->hDriver ) {
  492. return DriverWritePrinterHook( pSpool, pBuf, cbBuf, pcWritten );
  493. }
  494. try {
  495. if (ReturnValue = YWritePrinter(pSpool->hPrinter, (LPBYTE) pBuf, cbBuf, pcWritten, NATIVE_CALL)) {
  496. SetLastError(ReturnValue);
  497. ReturnValue = FALSE;
  498. DBGMSG(DBG_WARNING, ("KMWritePrinter - YWritePrinter Failed Error %d\n",GetLastError() ));
  499. } else {
  500. ReturnValue = TRUE;
  501. DBGMSG(DBG_TRACE, ("KMWritePrinter - YWritePrinter Success hPrinter %x pBuffer %x cbBuffer %x cbWritten %x\n",
  502. pSpool->hPrinter, (LPBYTE) pBuf, cbBuf, *pcWritten));
  503. }
  504. } except(1) {
  505. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  506. ReturnValue = FALSE;
  507. DBGMSG(DBG_WARNING, ("YWritePrinter Exception Error %d\n",GetLastError()));
  508. }
  509. // Return the number of bytes written.
  510. DBGMSG(DBG_TRACE, ("KMWritePrinter cbWritten %d ReturnValue %d\n",*pcWritten, ReturnValue));
  511. return ReturnValue;
  512. }
  513. BOOL
  514. KMStartPagePrinter(
  515. HANDLE hPrinter
  516. )
  517. {
  518. BOOL ReturnValue;
  519. PSPOOL pSpool = (PSPOOL)hPrinter;
  520. if (!ValidatePrinterHandle(hPrinter)) {
  521. return(FALSE);
  522. }
  523. try {
  524. ReturnValue = DriverStartPageHook( pSpool );
  525. if ( ReturnValue ) {
  526. if (ReturnValue = YStartPagePrinter(pSpool->hPrinter, NATIVE_CALL)) {
  527. SetLastError(ReturnValue);
  528. ReturnValue = FALSE;
  529. } else
  530. ReturnValue = TRUE;
  531. }
  532. } except(1) {
  533. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  534. ReturnValue = FALSE;
  535. }
  536. return ReturnValue;
  537. }
  538. BOOL
  539. KMEndPagePrinter(
  540. HANDLE hPrinter
  541. )
  542. {
  543. BOOL ReturnValue;
  544. PSPOOL pSpool = (PSPOOL)hPrinter;
  545. if (!ValidatePrinterHandle(hPrinter)) {
  546. return(FALSE);
  547. }
  548. try {
  549. ReturnValue = DriverEndPageHook( pSpool );
  550. if ( ReturnValue ) {
  551. if (ReturnValue = YEndPagePrinter(pSpool->hPrinter, NATIVE_CALL)) {
  552. SetLastError(ReturnValue);
  553. ReturnValue = FALSE;
  554. } else
  555. ReturnValue = TRUE;
  556. }
  557. } except(1) {
  558. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  559. ReturnValue = FALSE;
  560. }
  561. return ReturnValue;
  562. }
  563. BOOL
  564. KMAbortPrinter(
  565. HANDLE hPrinter
  566. )
  567. {
  568. BOOL ReturnValue;
  569. PSPOOL pSpool = (PSPOOL)hPrinter;
  570. DWORD dwNumWritten = 0;
  571. DWORD dwPointer = 0;
  572. if (!ValidatePrinterHandle(hPrinter)){
  573. return(FALSE);
  574. }
  575. pSpool->Status &= ~SPOOL_STATUS_STARTDOC;
  576. try {
  577. DriverAbortPrinterHook( pSpool );
  578. if (ReturnValue = YAbortPrinter(pSpool->hPrinter, NATIVE_CALL)) {
  579. SetLastError(ReturnValue);
  580. ReturnValue = FALSE;
  581. } else
  582. ReturnValue = TRUE;
  583. } except(1) {
  584. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  585. ReturnValue = FALSE;
  586. }
  587. return ReturnValue;
  588. }
  589. BOOL
  590. KMClosePrinter(
  591. HANDLE hPrinter)
  592. {
  593. BOOL ReturnValue;
  594. PSPOOL pSpool = (PSPOOL)hPrinter;
  595. HANDLE hPrinterKM;
  596. if (!ValidatePrinterHandle(hPrinter)) {
  597. return(FALSE);
  598. }
  599. try {
  600. DriverClosePrinterHook( pSpool );
  601. } except(1) {
  602. DBGMSG(DBG_WARNING, ("DrvClosePrinter Exception Error %d\n",TranslateExceptionCode(GetExceptionCode())));
  603. }
  604. ENTER_WAIT_LIST();
  605. hPrinterKM = pSpool->hPrinter;
  606. FreeSplMem(pSpool);
  607. EXIT_WAIT_LIST();
  608. try {
  609. if (ReturnValue = YClosePrinter(&hPrinterKM, NATIVE_CALL)) {
  610. SetLastError(ReturnValue);
  611. ReturnValue = FALSE;
  612. } else
  613. ReturnValue = TRUE;
  614. } except(1) {
  615. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  616. ReturnValue = FALSE;
  617. }
  618. return ReturnValue;
  619. }
  620. BOOL
  621. ValidatePrinterHandle(
  622. HANDLE hPrinter
  623. )
  624. {
  625. PSPOOL pSpool = hPrinter;
  626. BOOL bReturnValue = FALSE;
  627. try {
  628. if ( pSpool && (pSpool->signature == SP_SIGNATURE)) {
  629. bReturnValue = TRUE;
  630. }
  631. } except (1) {
  632. }
  633. if ( !bReturnValue ) {
  634. SetLastError( ERROR_INVALID_HANDLE );
  635. }
  636. return bReturnValue;
  637. }
  638. BOOL
  639. DriverWritePrinterHook(
  640. PSPOOL pSpool,
  641. LPVOID pBuf,
  642. DWORD cbBuf,
  643. LPDWORD pcWritten
  644. )
  645. {
  646. BOOL ReturnValue;
  647. // Some Printer Drivers want to push functionality out of kernel mode
  648. // to achieve that we allow them to hook the calls to writeprinter from
  649. // their Kernel Mode DLL to their User Mode Dll
  650. SPLASSERT( pSpool->hModule &&
  651. pSpool->pfnWrite &&
  652. pSpool->hDriver &&
  653. pSpool->hPrinter );
  654. try {
  655. ReturnValue = (*pSpool->pfnWrite)( pSpool->hDriver,
  656. pBuf,
  657. cbBuf,
  658. pcWritten );
  659. } except(1) {
  660. SetLastError(TranslateExceptionCode(GetExceptionCode()));
  661. ReturnValue = FALSE;
  662. DBGMSG(DBG_ERROR, ("DrvWritePrinter Exception Error %d pSpool %x\n",GetLastError(), pSpool));
  663. }
  664. if ( !ReturnValue ) {
  665. SPLASSERT( GetLastError() );
  666. }
  667. return ReturnValue;
  668. }
  669. HANDLE
  670. LoadPrinterDriver(
  671. PSPOOL pSpool,
  672. PWCHAR pUserModeDriverName
  673. )
  674. {
  675. PDRIVER_INFO_2 pDriverInfo;
  676. DWORD cbNeeded;
  677. HANDLE hModule = NULL;
  678. PWCHAR pFileName;
  679. fnWinSpoolDrv fnList;
  680. if (!GetPrinterDriver(pSpool->hPrinter, NULL, 2, NULL, 0, &cbNeeded)) {
  681. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  682. // Allow for the size of the string passed in.
  683. cbNeeded += ( wcslen( pUserModeDriverName ) + 1 )* sizeof(WCHAR);
  684. if (pDriverInfo = (PDRIVER_INFO_2)AllocSplMem( cbNeeded )) {
  685. if (GetPrinterDriver(pSpool->hPrinter, NULL, 2, (LPBYTE)pDriverInfo, cbNeeded, &cbNeeded)) {
  686. HRESULT hRes;
  687. //
  688. // Driver Info 2 doesn't have the fully Qualified Path
  689. // to the UserModePrinterDriver.
  690. // So form it by taking replacing the UI DLL name with the
  691. // UseModePrinterDriverName
  692. pFileName = wcsrchr( pDriverInfo->pConfigFile, L'\\');
  693. pFileName++;
  694. //
  695. // the line cbNeeded += ( wcslen( pUserModeDriverName ) + 1 )* sizeof(WCHAR);
  696. // makes sure that we have enough buffer to copy pUserModeDriverName
  697. //
  698. hRes = StringCchCopyW(pFileName, 1 + wcslen(pUserModeDriverName), pUserModeDriverName);
  699. if (SUCCEEDED(hRes)) {
  700. pFileName = pDriverInfo->pConfigFile;
  701. DBGMSG( DBG_WARNING, ("UserModeDriverPath %ws\n", pFileName ));
  702. if (SplInitializeWinSpoolDrv(&fnList)) {
  703. hModule = (* (fnList.pfnRefCntLoadDriver))(pFileName,
  704. LOAD_WITH_ALTERED_SEARCH_PATH,
  705. 0, FALSE);
  706. }
  707. if ( !hModule ) {
  708. DBGMSG( DBG_WARNING, ("Failed to load %ws error %d\n", pFileName, GetLastError() ));
  709. }
  710. }
  711. else {
  712. SetLastError(SCODE_CODE(hRes));
  713. }
  714. }
  715. FreeSplMem(pDriverInfo);
  716. }
  717. }
  718. }
  719. return hModule;
  720. }
  721. VOID
  722. UnloadPrinterDriver(
  723. PSPOOL pSpool
  724. )
  725. {
  726. fnWinSpoolDrv fnList;
  727. if ( pSpool->hModule ) {
  728. SPLASSERT( pSpool->hDriver == NULL );
  729. if (SplInitializeWinSpoolDrv(&fnList)) {
  730. (* (fnList.pfnRefCntUnloadDriver))(pSpool->hModule, TRUE);
  731. }
  732. pSpool->hModule = NULL;
  733. pSpool->pfnWrite = NULL;
  734. pSpool->pfnStartDoc = NULL;
  735. pSpool->pfnEndDoc = NULL;
  736. pSpool->pfnClose = NULL;
  737. pSpool->pfnStartPage = NULL;
  738. pSpool->pfnEndPage = NULL;
  739. }
  740. }
  741. DWORD
  742. DriverStartDocHook(
  743. PSPOOL pSpool,
  744. DWORD JobId
  745. )
  746. {
  747. DWORD dwReturn;
  748. WCHAR UserModeDriverName[MAX_PATH];
  749. DWORD dwNeeded;
  750. INT cDriverName;
  751. BOOL ReturnValue = FALSE;
  752. DWORD Type = 0;
  753. //
  754. // Determine if there is a UserMode Printer Driver
  755. //
  756. dwReturn = GetPrinterDataW( pSpool->hPrinter,
  757. SPLPRINTER_USER_MODE_PRINTER_DRIVER,
  758. &Type,
  759. (LPBYTE)&UserModeDriverName,
  760. MAX_PATH,
  761. &dwNeeded );
  762. if ( dwReturn != ERROR_SUCCESS ) {
  763. SPLASSERT( dwReturn != ERROR_INSUFFICIENT_BUFFER );
  764. ReturnValue = TRUE;
  765. goto Complete;
  766. }
  767. if ( Type != REG_SZ ) {
  768. SPLASSERT( Type == REG_SZ );
  769. goto Complete;
  770. }
  771. // No String treat as success
  772. cDriverName = wcslen( UserModeDriverName );
  773. if ( !cDriverName ) {
  774. ReturnValue = TRUE;
  775. goto Complete;
  776. }
  777. //
  778. // Load the UM Driver DLL
  779. //
  780. if ( pSpool->hModule == NULL ) {
  781. pSpool->hModule = LoadPrinterDriver( pSpool, UserModeDriverName );
  782. if ( pSpool->hModule == NULL ) goto Complete;
  783. }
  784. //
  785. // Get Function Pointers
  786. //
  787. // Required
  788. //
  789. pSpool->pfnWrite = (DWORD (*)()) GetProcAddress( pSpool->hModule, "DrvSplWritePrinter" );
  790. pSpool->pfnStartDoc = (HANDLE (*)()) GetProcAddress( pSpool->hModule, "DrvSplStartDoc" );
  791. pSpool->pfnClose = (VOID (*)()) GetProcAddress( pSpool->hModule, "DrvSplClose" );
  792. pSpool->pfnEndDoc = (VOID (*)()) GetProcAddress( pSpool->hModule, "DrvSplEndDoc" );
  793. // Optional
  794. //
  795. pSpool->pfnEndPage = (BOOL (*)()) GetProcAddress( pSpool->hModule, "DrvSplEndPage" );
  796. pSpool->pfnStartPage = (BOOL (*)()) GetProcAddress( pSpool->hModule, "DrvSplStartPage" );
  797. pSpool->pfnAbort = (VOID (*)()) GetProcAddress( pSpool->hModule, "DrvSplAbort" );
  798. if (!( pSpool->pfnWrite) ||
  799. !( pSpool->pfnStartDoc) ||
  800. !( pSpool->pfnClose) ||
  801. !( pSpool->pfnEndDoc)) {
  802. goto Complete;
  803. }
  804. //
  805. // Ask the Driver for a Handle for this print job
  806. //
  807. SPLASSERT( pSpool->hDriver == NULL );
  808. SPLASSERT( pSpool->hPrinter );
  809. SPLASSERT( JobId );
  810. pSpool->hDriver = (HANDLE)(*pSpool->pfnStartDoc)( pSpool->hPrinter, JobId );
  811. if ( pSpool->hDriver != NULL ) {
  812. ReturnValue = TRUE;
  813. }
  814. Complete:
  815. if (!ReturnValue) {
  816. UnloadPrinterDriver( pSpool );
  817. // Cancel the outstanding job
  818. //
  819. // In the direct case
  820. // AbortPrinter doesn't work
  821. // SetJob _CANCEL doesn't work
  822. // EndDocPrinter does work
  823. EndDocPrinter( pSpool->hPrinter );
  824. JobId = 0;
  825. }
  826. pSpool->JobId = JobId;
  827. return JobId;
  828. }
  829. VOID
  830. DriverEndDocHook(
  831. PSPOOL pSpool
  832. )
  833. {
  834. if ( pSpool->hDriver ) {
  835. (*pSpool->pfnEndDoc)( pSpool->hDriver );
  836. (*pSpool->pfnClose)(pSpool->hDriver );
  837. pSpool->hDriver = NULL;
  838. }
  839. }
  840. BOOL
  841. DriverStartPageHook(
  842. PSPOOL pSpool
  843. )
  844. {
  845. if ( pSpool->hDriver && pSpool->pfnStartPage ){
  846. return (*pSpool->pfnStartPage)( pSpool->hDriver );
  847. } else {
  848. return TRUE;
  849. }
  850. }
  851. BOOL
  852. DriverEndPageHook(
  853. PSPOOL pSpool
  854. )
  855. {
  856. if ( pSpool->hDriver && pSpool->pfnEndPage ){
  857. return (*pSpool->pfnEndPage)( pSpool->hDriver );
  858. } else {
  859. return TRUE;
  860. }
  861. }
  862. VOID
  863. DriverAbortPrinterHook(
  864. PSPOOL pSpool
  865. )
  866. {
  867. if ( pSpool->hDriver && pSpool->pfnAbort )
  868. (*pSpool->pfnAbort)( pSpool->hDriver );
  869. }
  870. VOID
  871. DriverClosePrinterHook(
  872. PSPOOL pSpool
  873. )
  874. {
  875. if ( pSpool->hDriver ) {
  876. SPLASSERT( pSpool->pfnClose );
  877. (*pSpool->pfnClose)(pSpool->hDriver);
  878. pSpool->hDriver = NULL;
  879. }
  880. UnloadPrinterDriver( pSpool );
  881. }