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.

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