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.

1292 lines
26 KiB

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