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.

1844 lines
49 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. umpd.c
  5. Abstract:
  6. User-mode printer driver support
  7. Environment:
  8. Windows NT 5.0
  9. Revision History:
  10. 06/30/97 -davidx-
  11. Created it.
  12. 09/17/97 -davidx-
  13. Clean up km-um thunking.
  14. --*/
  15. extern "C"
  16. {
  17. #include "precomp.h"
  18. #include "winddi.h"
  19. #include "psapi.h"
  20. #include "proxyport.h"
  21. static PUMPD gCachedUMPDList = NULL; // cached list of user-mode printer drivers
  22. }
  23. #include "umpd.hxx"
  24. #define IA64_PAGE_SIZE 0x2000
  25. #define PP_SHAREDSECTION_SIZE IA64_PAGE_SIZE
  26. PVOID
  27. MyGetPrinterDriver(
  28. HANDLE hPrinter,
  29. DWORD dwLevel
  30. )
  31. /*++
  32. Routine Description:
  33. Wrapper function for spooler's GetPrinterDriver API
  34. Arguments:
  35. hPrinter - Handle to the printer
  36. dwLevel - Level of DRIVER_INFO_x structure the caller is interested in
  37. Return Value:
  38. Pointer to a DRIVER_INFO_x structure, NULL if there is an error
  39. --*/
  40. {
  41. DWORD cbNeeded;
  42. PVOID pv;
  43. INT retries = 0;
  44. //
  45. // Start with a default buffer size to avoid always
  46. // having to call GetPrinterDriver twice.
  47. //
  48. cbNeeded = 2 * MAX_PATH * sizeof(WCHAR);
  49. while (retries++ < 2)
  50. {
  51. if (! (pv = LOCALALLOC(cbNeeded)))
  52. {
  53. WARNING("Memory allocation failed.\n");
  54. return NULL;
  55. }
  56. if (fpGetPrinterDriverW(hPrinter, NULL, dwLevel, (LPBYTE)pv, cbNeeded, &cbNeeded))
  57. return pv;
  58. //
  59. // If GetPrinterDriver failed not for insufficient buffer,
  60. // skip the retry
  61. //
  62. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  63. retries++;
  64. LOCALFREE(pv);
  65. }
  66. WARNING("GetPrinterDriver failed.\n");
  67. return NULL;
  68. }
  69. PWSTR
  70. DuplicateString(
  71. PCWSTR pSrc
  72. )
  73. /*++
  74. Routine Description:
  75. Allocate memory and make a duplicate of the source string
  76. Arguments:
  77. pSrc - String to be duplicated
  78. Return Value:
  79. Pointer to the duplicated string
  80. NULL if there is an error
  81. --*/
  82. {
  83. PWSTR pDest;
  84. INT cb;
  85. ASSERTGDI(pSrc != NULL, "Duplicate NULL string!\n");
  86. cb = (wcslen(pSrc) + 1) * sizeof(WCHAR);
  87. if (pDest = (PWSTR) LOCALALLOC(cb))
  88. {
  89. CopyMemory(pDest, pSrc, cb);
  90. return pDest;
  91. }
  92. else
  93. {
  94. WARNING("DuplicateString: out-of-memory.\n");
  95. return NULL;
  96. }
  97. }
  98. PDRIVER_INFO_5W
  99. DuplicateDriverInfo5W(PDRIVER_INFO_5W inDriverInfo)
  100. {
  101. ULONG size = sizeof(DRIVER_INFO_5W);
  102. PDRIVER_INFO_5W pDriverInfo;
  103. PWSTR pStr;
  104. ULONG len;
  105. size += (inDriverInfo->pName == NULL ? 0 : (wcslen(inDriverInfo->pName) + 1) * sizeof(WCHAR));
  106. size += (inDriverInfo->pEnvironment == NULL ? 0 : (wcslen(inDriverInfo->pEnvironment) + 1) * sizeof(WCHAR));
  107. size += (inDriverInfo->pDriverPath == NULL ? 0 : (wcslen(inDriverInfo->pDriverPath) + 1) * sizeof(WCHAR));
  108. size += (inDriverInfo->pDataFile == NULL ? 0 : (wcslen(inDriverInfo->pDataFile) + 1) * sizeof(WCHAR));
  109. size += (inDriverInfo->pConfigFile == NULL ? 0 : (wcslen(inDriverInfo->pConfigFile) + 1) * sizeof(WCHAR));
  110. if(pDriverInfo = (PDRIVER_INFO_5W) LOCALALLOC(size))
  111. {
  112. *pDriverInfo = *inDriverInfo;
  113. pStr = (PWSTR) (pDriverInfo + 1);
  114. if(pDriverInfo->pName)
  115. {
  116. len = wcslen(pDriverInfo->pName) + 1;
  117. RtlCopyMemory(pStr, pDriverInfo->pName, len * sizeof(WCHAR));
  118. pDriverInfo->pName = pStr;
  119. pStr += len;
  120. }
  121. if(pDriverInfo->pEnvironment)
  122. {
  123. len = wcslen(pDriverInfo->pEnvironment) + 1;
  124. RtlCopyMemory(pStr, pDriverInfo->pEnvironment, len * sizeof(WCHAR));
  125. pDriverInfo->pEnvironment = pStr;
  126. pStr += len;
  127. }
  128. if(pDriverInfo->pDriverPath)
  129. {
  130. len = wcslen(pDriverInfo->pDriverPath) + 1;
  131. RtlCopyMemory(pStr, pDriverInfo->pDriverPath, len * sizeof(WCHAR));
  132. pDriverInfo->pDriverPath = pStr;
  133. pStr += len;
  134. }
  135. if(pDriverInfo->pDataFile)
  136. {
  137. len = wcslen(pDriverInfo->pDataFile) + 1;
  138. RtlCopyMemory(pStr, pDriverInfo->pDataFile, len * sizeof(WCHAR));
  139. pDriverInfo->pDataFile = pStr;
  140. pStr += len;
  141. }
  142. if(pDriverInfo->pConfigFile)
  143. {
  144. len = wcslen(pDriverInfo->pConfigFile) + 1;
  145. RtlCopyMemory(pStr, pDriverInfo->pConfigFile, len * sizeof(WCHAR));
  146. pDriverInfo->pConfigFile = pStr;
  147. pStr += len;
  148. }
  149. }
  150. return pDriverInfo;
  151. }
  152. PUMPD
  153. FindUserModePrinterDriver(
  154. PCWSTR pDriverDllName,
  155. DWORD dwDriverVersion,
  156. BOOL bUseVersion
  157. )
  158. /*++
  159. Routine Description:
  160. Search the cached list of user-mode printer drivers and
  161. see if the specified driver is found
  162. Arguments:
  163. pDriverDllName - Specifies the name of the driver DLL to be found
  164. dwDriverVersion - Current version number of the driver
  165. bUseVersion - Flag for using the version check
  166. Return Value:
  167. Pointer to the UMPD structure corresponding to the specified driver
  168. NULL if the specified driver is not in the cached list
  169. Note:
  170. This function must be called inside a critical section:
  171. ENTERCRITICALSECTION(&semUMPD);
  172. ...
  173. LEAVECRITICALSECTION(&semUMPD);
  174. --*/
  175. {
  176. PUMPD pUMPD = gCachedUMPDList;
  177. while (pUMPD != NULL &&
  178. pUMPD->pDriverInfo2 != NULL &&
  179. _wcsicmp(pDriverDllName, pUMPD->pDriverInfo2->pDriverPath) != 0)
  180. {
  181. pUMPD = pUMPD->pNext;
  182. }
  183. // Do the version check if neccesary
  184. if (bUseVersion && pUMPD)
  185. {
  186. if (dwDriverVersion != pUMPD->dwDriverVersion)
  187. {
  188. // We have a version mismatch. Remove artificial increments on this
  189. // driver.
  190. if (pUMPD->bArtificialIncrement)
  191. {
  192. pUMPD->bArtificialIncrement = FALSE;
  193. if (UnloadUserModePrinterDriver(pUMPD, FALSE, 0))
  194. {
  195. pUMPD = NULL;
  196. }
  197. }
  198. }
  199. }
  200. return pUMPD;
  201. }
  202. BOOL
  203. GdiArtificialDecrementDriver(
  204. LPWSTR pDriverDllName,
  205. DWORD dwDriverAttributes
  206. )
  207. /*++
  208. Routine Description:
  209. Remove the artificial increment on the driver, if any.
  210. Arguments:
  211. pDriverDllName - Specifies the name of the driver DLL to be found
  212. dwDriverAttributes - User/Kernel mode printer driver
  213. Return Value:
  214. TRUE if the driver file is no longer loaded in the spooler
  215. FALSE otherwise
  216. --*/
  217. {
  218. PUMPD pUMPD;
  219. BOOL bReturn = FALSE;
  220. if (!pDriverDllName || !*pDriverDllName)
  221. {
  222. // Nothing to unload
  223. return bReturn;
  224. }
  225. if (dwDriverAttributes & DRIVER_KERNELMODE)
  226. {
  227. // Unload kernel mode driver
  228. return NtGdiUnloadPrinterDriver(pDriverDllName,
  229. (wcslen(pDriverDllName) + 1) * sizeof(WCHAR));
  230. }
  231. ENTERCRITICALSECTION(&semUMPD);
  232. pUMPD = gCachedUMPDList;
  233. while (pUMPD != NULL &&
  234. _wcsicmp(pDriverDllName, pUMPD->pDriverInfo2->pDriverPath) != 0)
  235. {
  236. pUMPD = pUMPD->pNext;
  237. }
  238. if (pUMPD)
  239. {
  240. if (pUMPD->bArtificialIncrement)
  241. {
  242. pUMPD->bArtificialIncrement = FALSE;
  243. bReturn = UnloadUserModePrinterDriver(pUMPD, FALSE, 0);
  244. }
  245. }
  246. else
  247. {
  248. bReturn = TRUE;
  249. }
  250. LEAVECRITICALSECTION(&semUMPD);
  251. return bReturn;
  252. }
  253. BOOL
  254. LoadUserModePrinterDriverEx(
  255. PDRIVER_INFO_5W pDriverInfo5,
  256. LPWSTR pwstrPrinterName,
  257. PUMPD *ppUMPD,
  258. PRINTER_DEFAULTSW *pdefaults,
  259. HANDLE hPrinter
  260. )
  261. {
  262. PDRIVER_INFO_2W pDriverInfo2;
  263. HINSTANCE hInst = NULL;
  264. BOOL bResult = FALSE;
  265. PUMPD pUMPD = NULL;
  266. ProxyPort * pp = NULL;
  267. KERNEL_PVOID umpdCookie = NULL;
  268. BOOL bFreeDriverInfo2 = TRUE;
  269. if ((pDriverInfo2 = (PDRIVER_INFO_2W) DuplicateDriverInfo5W(pDriverInfo5)) == NULL)
  270. return FALSE;
  271. //
  272. // Check the list of cached user-mode printer drivers
  273. // and see if the requested printer driver is already loaded
  274. //
  275. ENTERCRITICALSECTION(&semUMPD);
  276. if (*ppUMPD = FindUserModePrinterDriver(pDriverInfo5->pDriverPath,
  277. pDriverInfo5->dwDriverVersion,
  278. TRUE))
  279. {
  280. if (gbWOW64)
  281. {
  282. pUMPD = *ppUMPD;
  283. ASSERTGDI(pUMPD->pp, "LoadUserModePrinterDriver NULL proxyport\n");
  284. PROXYPORT proxyport(pUMPD->pp);
  285. if (proxyport.bValid())
  286. {
  287. umpdCookie = proxyport.LoadDriver(pDriverInfo5, pwstrPrinterName, pdefaults, hPrinter);
  288. if (pUMPD->umpdCookie == umpdCookie)
  289. {
  290. // 64-bit UMPD matches the 32-bit one
  291. bResult = TRUE;
  292. }
  293. else
  294. {
  295. WARNING("LoadUserModePrinterDriveEx: umpdCookie doesn't match\n");
  296. }
  297. }
  298. else
  299. WARNING("LoadUserModePrinterDriverEx: invalid proxyport\n");
  300. }
  301. else
  302. {
  303. // x86 or native ia64 printing, don't need to anything
  304. bResult = TRUE;
  305. }
  306. }
  307. else
  308. {
  309. // Can't find UMPD, first time load the printer driver
  310. if (gbWOW64)
  311. {
  312. PROXYPORT proxyport(PP_SHAREDSECTION_SIZE);
  313. if (pp = proxyport.GetPort())
  314. {
  315. umpdCookie = proxyport.LoadDriver(pDriverInfo5, pwstrPrinterName, pdefaults, hPrinter);
  316. }
  317. }
  318. else
  319. {
  320. hInst = LoadLibraryExW(pDriverInfo2->pDriverPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
  321. }
  322. if (hInst || umpdCookie)
  323. {
  324. if (pUMPD = (PUMPD) LOCALALLOC(sizeof(UMPD)))
  325. {
  326. ZeroMemory(pUMPD, sizeof(UMPD));
  327. pUMPD->dwSignature = UMPD_SIGNATURE;
  328. pUMPD->hInst = hInst;
  329. pUMPD->pDriverInfo2 = pDriverInfo2;
  330. pUMPD->bArtificialIncrement = TRUE;
  331. pUMPD->dwDriverVersion = pDriverInfo5->dwDriverVersion;
  332. pUMPD->iRefCount = 1; // aritficial ref count to keep the printer driver around
  333. // till the process goes away
  334. pUMPD->pp = pp;
  335. pUMPD->umpdCookie = umpdCookie;
  336. *ppUMPD = pUMPD;
  337. bResult = TRUE;
  338. bFreeDriverInfo2 = FALSE;
  339. //
  340. // Add the newly loaded driver to the list of
  341. // cached user-mode printer drivers
  342. //
  343. pUMPD->pNext = gCachedUMPDList;
  344. gCachedUMPDList = pUMPD;
  345. }
  346. }
  347. if (!bResult)
  348. {
  349. if (pp)
  350. {
  351. PROXYPORT proxyport(pp);
  352. if (umpdCookie)
  353. proxyport.UnloadDriver(umpdCookie, 0, FALSE);
  354. proxyport.Close();
  355. }
  356. if (hInst)
  357. FreeLibrary(hInst);
  358. }
  359. }
  360. if (bResult)
  361. (*ppUMPD)->iRefCount++;
  362. LEAVECRITICALSECTION(&semUMPD);
  363. if (bFreeDriverInfo2)
  364. LOCALFREE(pDriverInfo2);
  365. if (!bResult)
  366. {
  367. WARNING("LoadUserModePrinterDriverEx failed\n");
  368. }
  369. return bResult;
  370. }
  371. BOOL
  372. LoadUserModePrinterDriver(
  373. HANDLE hPrinter,
  374. LPWSTR pwstrPrinterName,
  375. PUMPD *ppUMPD,
  376. PRINTER_DEFAULTSW *pdefaults
  377. )
  378. /*++
  379. Routine Description:
  380. Load user-mode printer driver DLL
  381. Arguments:
  382. hPrinter - Handle to the current printer
  383. ppUMPD - Return a pointer to a UMPD structure
  384. Return Value:
  385. TRUE if successful, FALSE if there is an error
  386. If the printer uses a user-mode printer driver, *ppUMPD will be a pointer
  387. to a UMPD structure. If the printer uses a kernel-mode printer driver,
  388. *ppUMPD will be NULL.
  389. --*/
  390. {
  391. PDRIVER_INFO_5W pDriverInfo5;
  392. BOOL bResult;
  393. HMODULE hModule;
  394. WCHAR moduleName[256];
  395. *ppUMPD = NULL;
  396. //
  397. // Get printer driver information
  398. //
  399. if ((pDriverInfo5 = (PDRIVER_INFO_5W)MyGetPrinterDriver(hPrinter, 5)) == NULL)
  400. return FALSE;
  401. if (pDriverInfo5->dwDriverAttributes & DRIVER_KERNELMODE)
  402. {
  403. LOCALFREE(pDriverInfo5);
  404. return TRUE;
  405. }
  406. bResult = LoadUserModePrinterDriverEx(pDriverInfo5, pwstrPrinterName, ppUMPD, pdefaults, hPrinter);
  407. LOCALFREE(pDriverInfo5);
  408. return bResult;
  409. }
  410. BOOL
  411. UnloadUserModePrinterDriver(
  412. PUMPD pUMPD,
  413. BOOL bNotifySpooler,
  414. HANDLE hPrinter
  415. )
  416. /*++
  417. Routine Description:
  418. Unload user-mode printer driver module and notify the spooler if necessary
  419. Arguments:
  420. pUMPD - Pointer to user-mode printer driver information
  421. bNotifySpooler - Call into the spooler to notify driver unloading
  422. Return Value:
  423. TRUE if the driver instance was freed (i.e ref cnt == 0)
  424. FALSE otherwise
  425. --*/
  426. {
  427. PUMPD *ppStartUMPD;
  428. ASSERTGDI(VALID_UMPD(pUMPD), "Corrupted UMPD structure.\n");
  429. ASSERTGDI(pUMPD->iRefCount > 0, "Bad UMPD reference count.\n");
  430. if (gbWOW64)
  431. {
  432. PROXYPORT proxyport(pUMPD->pp);
  433. if (proxyport.bValid())
  434. {
  435. proxyport.UnloadDriver(pUMPD->umpdCookie, hPrinter, bNotifySpooler);
  436. }
  437. }
  438. ENTERCRITICALSECTION(&semUMPD);
  439. if (pUMPD->iRefCount > 0)
  440. {
  441. pUMPD->iRefCount--;
  442. }
  443. if (pUMPD->iRefCount != 0 || pUMPD->pHandleList != NULL)
  444. {
  445. LEAVECRITICALSECTION(&semUMPD);
  446. return FALSE;
  447. }
  448. // Remove the UMPD node from umpd cache list
  449. for (ppStartUMPD = &gCachedUMPDList;
  450. *ppStartUMPD;
  451. ppStartUMPD = &((*ppStartUMPD)->pNext))
  452. {
  453. if (*ppStartUMPD == pUMPD)
  454. {
  455. *ppStartUMPD = pUMPD->pNext;
  456. break;
  457. }
  458. }
  459. LEAVECRITICALSECTION(&semUMPD);
  460. if (gbWOW64)
  461. {
  462. PROXYPORT proxyport(pUMPD->pp);
  463. if (proxyport.bValid())
  464. proxyport.Close();
  465. }
  466. else
  467. {
  468. PFN pfn = pUMPD->apfn[INDEX_DrvDisableDriver];
  469. if (pfn)
  470. {
  471. pfn();
  472. }
  473. FreeLibrary(pUMPD->hInst);
  474. }
  475. if (bNotifySpooler && pUMPD->pDriverInfo2->pDriverPath)
  476. {
  477. (*fpSplDriverUnloadComplete)(pUMPD->pDriverInfo2->pDriverPath);
  478. }
  479. LOCALFREE(pUMPD->pDriverInfo2);
  480. LOCALFREE(pUMPD);
  481. return TRUE;
  482. }
  483. PUMPD
  484. UMPDDrvEnableDriver(
  485. PWSTR pDriverDllName,
  486. ULONG iEngineVersion
  487. )
  488. /*++
  489. Routine Description:
  490. Client-side stub for DrvEnableDriver
  491. Arguments:
  492. iDriverDllName - Name of the user-mode printer driver DLL
  493. iEngineVersion - Same parameter as that for DrvEnableDriver
  494. Return Value:
  495. Pointer to the UMPD structure corresponding to the specified driver
  496. NULL if there is an error
  497. Note:
  498. The pointer value returned by this function will be passed back from
  499. the kernel-mode side to the user-mode side for each subsequent DDI call.
  500. --*/
  501. {
  502. PUMPD pUMPD;
  503. DRVENABLEDATA ded;
  504. ENTERCRITICALSECTION(&semUMPD);
  505. //
  506. // Find the specified user-mode printer driver
  507. //
  508. pUMPD = FindUserModePrinterDriver(pDriverDllName, 0, FALSE);
  509. if(pUMPD == NULL)
  510. {
  511. WARNING("failed to find printer driver\n");
  512. return NULL;
  513. }
  514. if(pUMPD->hInst == NULL)
  515. {
  516. WARNING("driver library not loaded\n");
  517. return NULL;
  518. }
  519. ASSERTGDI(pUMPD != NULL, "Non-existent user-mode printer driver.\n");
  520. if (! (pUMPD->dwFlags & UMPDFLAG_DRVENABLEDRIVER_CALLED))
  521. {
  522. PFN_DrvEnableDriver pfn;
  523. //
  524. // If we haven't called DrvEnableDriver for this driver, do it now
  525. //
  526. if ((pfn = (PFN_DrvEnableDriver) GetProcAddress(pUMPD->hInst, "DrvEnableDriver")) &&
  527. pfn(iEngineVersion, sizeof(ded), &ded))
  528. {
  529. PDRVFN pdrvfn;
  530. ULONG count;
  531. //
  532. // Convert driver entrypoint function table to a more convenient format
  533. //
  534. for (pdrvfn = ded.pdrvfn, count = ded.c; count--; pdrvfn++)
  535. {
  536. if (pdrvfn->iFunc < INDEX_LAST)
  537. pUMPD->apfn[pdrvfn->iFunc] = pdrvfn->pfn;
  538. else
  539. {
  540. WARNING("Unrecognized DDI entrypoint index.\n");
  541. }
  542. }
  543. pUMPD->dwFlags |= UMPDFLAG_DRVENABLEDRIVER_CALLED;
  544. }
  545. else
  546. {
  547. WARNING("DrvEnableDriver failed.\n");
  548. pUMPD = NULL;
  549. }
  550. }
  551. LEAVECRITICALSECTION(&semUMPD);
  552. return pUMPD;
  553. }
  554. extern "C"
  555. int DocumentEventEx(
  556. PUMPD pUMPD,
  557. HANDLE hPrinter,
  558. HDC hdc,
  559. int iEsc,
  560. ULONG cjIn,
  561. PVOID pvIn,
  562. ULONG cjOut,
  563. PVOID pvOut
  564. )
  565. {
  566. int iRet;
  567. if (WOW64PRINTING(pUMPD))
  568. {
  569. PROXYPORT proxyport(pUMPD->pp);
  570. iRet = proxyport.DocumentEvent(pUMPD->umpdCookie, hPrinter,
  571. hdc, iEsc, cjIn, pvIn, cjOut, pvOut);
  572. }
  573. else
  574. {
  575. iRet = (*fpDocumentEvent)(hPrinter, hdc, iEsc, cjIn, pvIn, cjOut, pvOut);
  576. }
  577. return iRet;
  578. }
  579. extern "C"
  580. DWORD StartDocPrinterWEx(
  581. PUMPD pUMPD,
  582. HANDLE hPrinter,
  583. DWORD level,
  584. LPBYTE pDocInfo)
  585. {
  586. if (WOW64PRINTING(pUMPD) && level == 1)
  587. {
  588. PROXYPORT proxyport(pUMPD->pp);
  589. return proxyport.StartDocPrinterW(pUMPD->umpdCookie,hPrinter, level, pDocInfo);
  590. }
  591. else
  592. return (*fpStartDocPrinterW)(hPrinter, level, pDocInfo);
  593. }
  594. extern "C"
  595. BOOL EndDocPrinterEx(PUMPD pUMPD, HANDLE hPrinter)
  596. {
  597. if (WOW64PRINTING(pUMPD))
  598. {
  599. PROXYPORT proxyport(pUMPD->pp);
  600. return proxyport.EndDocPrinter(pUMPD->umpdCookie, hPrinter);
  601. }
  602. else
  603. return (*fpEndDocPrinter)(hPrinter);
  604. }
  605. extern "C"
  606. BOOL StartPagePrinterEx(PUMPD pUMPD, HANDLE hPrinter)
  607. {
  608. if (WOW64PRINTING(pUMPD))
  609. {
  610. PROXYPORT proxyport(pUMPD->pp);
  611. return proxyport.StartPagePrinter(pUMPD->umpdCookie, hPrinter);
  612. }
  613. else
  614. return (*fpStartPagePrinter)(hPrinter);
  615. }
  616. extern "C"
  617. BOOL EndPagePrinterEx(PUMPD pUMPD, HANDLE hPrinter)
  618. {
  619. if (WOW64PRINTING(pUMPD))
  620. {
  621. PROXYPORT proxyport(pUMPD->pp);
  622. return proxyport.EndPagePrinter(pUMPD->umpdCookie, hPrinter);
  623. }
  624. else
  625. return (*fpEndPagePrinter)(hPrinter);
  626. }
  627. extern "C"
  628. BOOL AbortPrinterEx(PLDC pldc, BOOL bEMF)
  629. {
  630. if (!bEMF && WOW64PRINTING(pldc->pUMPD))
  631. {
  632. PROXYPORT proxyport(pldc->pUMPD->pp);
  633. return proxyport.AbortPrinter(pldc->pUMPD->umpdCookie, pldc->hSpooler);
  634. }
  635. else
  636. return (*fpAbortPrinter)(pldc->hSpooler);
  637. }
  638. extern "C"
  639. BOOL ResetPrinterWEx(PLDC pldc, PRINTER_DEFAULTSW *pPtrDef)
  640. {
  641. BOOL bRet = TRUE;
  642. if (WOW64PRINTING(pldc->pUMPD))
  643. {
  644. if (!(pldc->fl & LDC_META_PRINT))
  645. {
  646. // either RAW printing or
  647. // ResetDC called before StartDoc, don't know
  648. // whether it is going RAW or EMF yet
  649. PROXYPORT proxyport(pldc->pUMPD->pp);
  650. bRet = proxyport.ResetPrinterW(pldc->pUMPD->umpdCookie, pldc->hSpooler, pPtrDef);
  651. }
  652. if (bRet && !(pldc->fl & LDC_PRINT_DIRECT))
  653. {
  654. // either EMF printing or
  655. // ResetDC called before StartDoc, we need to
  656. // call ResetPrinter on both 32-bit and 64-bit
  657. // printer handles.
  658. bRet = (*fpResetPrinterW)(pldc->hSpooler, pPtrDef);
  659. }
  660. }
  661. else
  662. {
  663. bRet = (*fpResetPrinterW)(pldc->hSpooler, pPtrDef);
  664. }
  665. return bRet;
  666. }
  667. extern "C"
  668. BOOL
  669. QueryColorProfileEx(
  670. PLDC pldc,
  671. PDEVMODEW pDevMode,
  672. ULONG ulQueryMode,
  673. PVOID pvProfileData,
  674. ULONG * pcjProfileSize,
  675. FLONG * pflProfileFlag)
  676. {
  677. if (!(pldc->fl & LDC_META_PRINT) && WOW64PRINTING(pldc->pUMPD))
  678. {
  679. PROXYPORT proxyport(pldc->pUMPD->pp);
  680. return proxyport.QueryColorProfile(pldc->pUMPD->umpdCookie,
  681. pldc->hSpooler,
  682. pDevMode,
  683. ulQueryMode,
  684. pvProfileData,
  685. pcjProfileSize,
  686. pflProfileFlag);
  687. }
  688. else
  689. return (*fpQueryColorProfile)(pldc->hSpooler,
  690. pDevMode,
  691. ulQueryMode,
  692. pvProfileData,
  693. pcjProfileSize,
  694. pflProfileFlag);
  695. }
  696. PPORT_MESSAGE
  697. PROXYPORT::InitMsg(
  698. PPROXYMSG Msg,
  699. SERVERPTR pvIn,
  700. ULONG cjIn,
  701. SERVERPTR pvOut,
  702. ULONG cjOut
  703. )
  704. {
  705. Msg->h.u1.s1.DataLength = (short) (sizeof(*Msg) - sizeof(Msg->h));
  706. Msg->h.u1.s1.TotalLength = (short) (sizeof(*Msg));
  707. Msg->h.u2.ZeroInit = 0;
  708. if(pvOut == 0) cjOut = 0;
  709. Msg->cjIn = cjIn;
  710. Msg->pvIn = pvIn;
  711. Msg->cjOut = cjOut;
  712. Msg->pvOut = pvOut;
  713. return( (PPORT_MESSAGE)Msg );
  714. }
  715. BOOL
  716. PROXYPORT::CheckMsg(
  717. NTSTATUS Status,
  718. PPROXYMSG Msg,
  719. SERVERPTR pvOut,
  720. ULONG cjOut
  721. )
  722. {
  723. ULONG cbData = Msg->h.u1.s1.DataLength;
  724. if (cbData == (sizeof(*Msg) - sizeof(Msg->h)))
  725. {
  726. if(pvOut != Msg->pvOut)
  727. {
  728. return(FALSE);
  729. }
  730. if(cjOut != Msg->cjOut)
  731. {
  732. return(FALSE);
  733. }
  734. // do nothing
  735. }
  736. else
  737. {
  738. return(FALSE);
  739. }
  740. return( TRUE );
  741. }
  742. NTSTATUS
  743. PROXYPORT::SendRequest(
  744. SERVERPTR pvIn,
  745. ULONG cjIn,
  746. SERVERPTR pvOut,
  747. ULONG cjOut
  748. )
  749. {
  750. NTSTATUS Status;
  751. PROXYMSG Request;
  752. PROXYMSG Reply;
  753. InitMsg( &Request, pvIn, cjIn, pvOut, cjOut );
  754. Status = NtRequestWaitReplyPort( pp->PortHandle,
  755. (PPORT_MESSAGE)&Request,
  756. (PPORT_MESSAGE)&Reply
  757. );
  758. if (!NT_SUCCESS( Status ))
  759. {
  760. return( Status );
  761. }
  762. if (Reply.h.u2.s2.Type == LPC_REPLY)
  763. {
  764. if (!CheckMsg( Status, &Reply, pvOut, cjOut ))
  765. {
  766. return(STATUS_UNSUCCESSFUL);
  767. }
  768. }
  769. else
  770. {
  771. return(STATUS_UNSUCCESSFUL);
  772. }
  773. return( Status );
  774. }
  775. #define ALIGN_UMPD_BUFFER(cj) (((cj) + (sizeof(KERNEL_PVOID) -1)) & ~(sizeof(KERNEL_PVOID)-1))
  776. SERVERPTR
  777. PROXYPORT::HeapAlloc(ULONG inSize)
  778. {
  779. KPBYTE ptr;
  780. if(pp->ClientMemoryAllocSize + ALIGN_UMPD_BUFFER(inSize) > pp->ClientMemorySize)
  781. return 0;
  782. ptr = pp->ClientMemoryBase + pp->ClientMemoryAllocSize + pp->ServerMemoryDelta;
  783. pp->ClientMemoryAllocSize += ALIGN_UMPD_BUFFER(inSize);
  784. return (SERVERPTR) ptr;
  785. }
  786. PROXYPORT::PROXYPORT(ULONGLONG inMaxSize)
  787. {
  788. NTSTATUS Status;
  789. PORT_VIEW ClientView;
  790. ULONG MaxMessageLength;
  791. LARGE_INTEGER MaximumSize;
  792. UNICODE_STRING PortName;
  793. SECURITY_QUALITY_OF_SERVICE DynamicQos;
  794. WCHAR awcPortName[MAX_PATH] = {0};
  795. DWORD CurrSessionId;
  796. DWORD CurrProcessId = GetCurrentProcessId();
  797. ProcessIdToSessionId(CurrProcessId,&CurrSessionId);
  798. wsprintfW(awcPortName, L"%s_%x", L"\\RPC Control\\UmpdProxy", CurrSessionId);
  799. DynamicQos.Length = 0;
  800. DynamicQos.ImpersonationLevel = SecurityImpersonation;
  801. DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  802. DynamicQos.EffectiveOnly = TRUE;
  803. if ((pp = (ProxyPort *) LOCALALLOC(sizeof(ProxyPort))) == NULL ||
  804. !NT_SUCCESS((NTSTATUS)INITIALIZECRITICALSECTION(&pp->semPort)))
  805. {
  806. WARNING("PROXYPORT::PROXYPORT mem alloc OR critical section init failed\n");
  807. if (pp)
  808. LOCALFREE(pp);
  809. pp = NULL;
  810. return;
  811. }
  812. pp->ClientMemoryBase = 0;
  813. pp->ClientMemorySize = 0;
  814. pp->ClientMemoryAllocSize = 0;
  815. pp->PortHandle = NULL;
  816. pp->ServerMemoryBase = 0;
  817. pp->ServerMemoryDelta = 0;
  818. Status = STATUS_SUCCESS;
  819. RtlInitUnicodeString( &PortName, awcPortName );
  820. MaximumSize.QuadPart = inMaxSize;
  821. ZeroMemory(&ClientView.SectionHandle, sizeof(ClientView.SectionHandle));
  822. Status = NtCreateSection( (PHANDLE)&ClientView.SectionHandle,
  823. SECTION_MAP_READ | SECTION_MAP_WRITE,
  824. NULL,
  825. &MaximumSize,
  826. PAGE_READWRITE,
  827. SEC_COMMIT,
  828. NULL
  829. );
  830. if (NT_SUCCESS( Status ))
  831. {
  832. ClientView.Length = sizeof( ClientView );
  833. ClientView.SectionOffset = 0;
  834. ClientView.ViewSize = (LPC_SIZE_T) inMaxSize;
  835. ClientView.ViewBase = 0;
  836. ClientView.ViewRemoteBase = 0;
  837. if (BLOADSPOOLER &&
  838. (*fpLoadSplWow64)(NULL) == ERROR_SUCCESS)
  839. {
  840. Status = NtConnectPort( &pp->PortHandle,
  841. &PortName,
  842. &DynamicQos,
  843. &ClientView,
  844. NULL,
  845. (PULONG)&MaxMessageLength,
  846. NULL,
  847. 0
  848. );
  849. if (NT_SUCCESS( Status ))
  850. {
  851. pp->SectionHandle = (HANDLE)ClientView.SectionHandle;
  852. pp->ClientMemoryBase = (KPBYTE)ClientView.ViewBase;
  853. pp->ClientMemorySize = (SIZE_T)inMaxSize;
  854. pp->ServerMemoryBase = (KPBYTE)ClientView.ViewRemoteBase;
  855. pp->ServerMemoryDelta = pp->ServerMemoryBase -
  856. pp->ClientMemoryBase;
  857. NtRegisterThreadTerminatePort(pp->PortHandle);
  858. }
  859. else
  860. {
  861. WARNING("PROXYPORT::PROXYPORT: NtConnectPort failed\n");
  862. }
  863. }
  864. else
  865. {
  866. Status = STATUS_UNSUCCESSFUL;
  867. WARNING("PROXYPORT::PROXYPORT failed to load spooler or splwow64\n");
  868. }
  869. }
  870. else
  871. {
  872. WARNING("PROXYPORT::PROXYPORT: failed to create section\n");
  873. }
  874. if(!NT_SUCCESS( Status ))
  875. {
  876. if ((HANDLE)ClientView.SectionHandle)
  877. {
  878. NtClose((HANDLE)ClientView.SectionHandle);
  879. }
  880. DELETECRITICALSECTION(&pp->semPort);
  881. LOCALFREE(pp);
  882. pp = NULL;
  883. }
  884. else
  885. {
  886. // grab port access
  887. ENTERCRITICALSECTION(&pp->semPort);
  888. }
  889. }
  890. void
  891. PROXYPORT::Close()
  892. {
  893. if (pp->SectionHandle)
  894. {
  895. if (!CloseHandle(pp->SectionHandle))
  896. {
  897. WARNING("PROXYPORT::Close failed to close the section handle\n");
  898. }
  899. }
  900. if (pp->PortHandle != NULL)
  901. {
  902. if (!CloseHandle( pp->PortHandle ))
  903. {
  904. WARNING("PROXYPORT::Close failed to close the port handle\n");
  905. }
  906. }
  907. LEAVECRITICALSECTION(&pp->semPort);
  908. DELETECRITICALSECTION(&pp->semPort);
  909. LOCALFREE(pp);
  910. pp = NULL;
  911. }
  912. void vUMPDWow64Shutdown()
  913. {
  914. PUMPD pUMPD = gCachedUMPDList;
  915. while(pUMPD)
  916. {
  917. if (pUMPD->pp)
  918. {
  919. PROXYPORT proxyPort(pUMPD->pp);
  920. proxyPort.Shutdown();
  921. }
  922. pUMPD = pUMPD->pNext;
  923. }
  924. }
  925. BOOL
  926. PROXYPORT::ThunkMemBlock(
  927. KPBYTE * ptr,
  928. ULONG size)
  929. {
  930. BOOL bRet = TRUE;
  931. if (*ptr)
  932. {
  933. SERVERPTR sp = HeapAlloc(size);
  934. CLIENTPTR cp = ServerToClientPtr(sp);
  935. if (cp)
  936. {
  937. RtlCopyMemory((PVOID)cp, (PVOID)*ptr, size);
  938. *ptr = sp;
  939. }
  940. else
  941. bRet = FALSE;
  942. }
  943. return bRet;
  944. }
  945. BOOL
  946. PROXYPORT::ThunkStr(LPWSTR * ioLpstr)
  947. {
  948. BOOL bRet = TRUE;
  949. if(*ioLpstr != NULL)
  950. {
  951. bRet = ThunkMemBlock((KPBYTE *) ioLpstr, (wcslen(*ioLpstr) + 1) * sizeof(WCHAR));
  952. }
  953. return bRet;
  954. }
  955. KERNEL_PVOID
  956. PROXYPORT::LoadDriver(
  957. PDRIVER_INFO_5W pDriverInfo,
  958. LPWSTR pwstrPrinterName,
  959. PRINTER_DEFAULTSW* pdefaults,
  960. HANDLE hPrinter32
  961. )
  962. {
  963. NTSTATUS Status = STATUS_SUCCESS;
  964. SERVERPTR spInput;
  965. SERVERPTR spOutput;
  966. LOADDRIVERINPUT* pInput;
  967. KERNEL_PVOID umpdCookie = NULL;
  968. HeapInit();
  969. if (!(spInput = HeapAlloc(sizeof(LOADDRIVERINPUT))) ||
  970. !(spOutput = HeapAlloc(sizeof(KERNEL_PVOID))))
  971. return NULL;
  972. pInput = (LOADDRIVERINPUT *) ServerToClientPtr(spInput);
  973. pInput->driverInfo.cVersion = pDriverInfo->cVersion;
  974. pInput->driverInfo.pName = (KLPWSTR)pDriverInfo->pName;
  975. pInput->driverInfo.pEnvironment = (KLPWSTR)pDriverInfo->pEnvironment;
  976. pInput->driverInfo.pDriverPath = (KLPWSTR)pDriverInfo->pDriverPath;
  977. pInput->driverInfo.pDataFile = (KLPWSTR)pDriverInfo->pDataFile;
  978. pInput->driverInfo.pConfigFile = (KLPWSTR)pDriverInfo->pConfigFile;
  979. pInput->driverInfo.dwDriverAttributes = pDriverInfo->dwDriverAttributes;
  980. pInput->driverInfo.dwConfigVersion = pDriverInfo->dwConfigVersion;
  981. pInput->driverInfo.dwDriverVersion = pDriverInfo->dwDriverVersion;
  982. pInput->clientPid = GetCurrentProcessId();
  983. pInput->hPrinter32 = HandleToUlong(hPrinter32);
  984. pInput->pPrinterName = (KLPWSTR)pwstrPrinterName;
  985. pInput->defaults.pDatatype = (KLPWSTR)pdefaults->pDatatype;
  986. pInput->defaults.pDevMode = (KPBYTE)pdefaults->pDevMode;
  987. pInput->defaults.DesiredAccess = pdefaults->DesiredAccess;
  988. if (!ThunkStr((LPWSTR *)&pInput->driverInfo.pName) ||
  989. !ThunkStr((LPWSTR *)&pInput->driverInfo.pEnvironment) ||
  990. !ThunkStr((LPWSTR *)&pInput->driverInfo.pDriverPath) ||
  991. !ThunkStr((LPWSTR *)&pInput->driverInfo.pDataFile) ||
  992. !ThunkStr((LPWSTR *)&pInput->driverInfo.pConfigFile) ||
  993. !ThunkStr((LPWSTR *)&pInput->pPrinterName) ||
  994. !ThunkStr((LPWSTR *)&pInput->defaults.pDatatype) ||
  995. !ThunkMemBlock(&pInput->defaults.pDevMode, sizeof(DEVMODEW))
  996. )
  997. return NULL;
  998. pInput->umpdthdr.umthdr.ulType = INDEX_LoadUMPrinterDrv;
  999. Status = SendRequest(spInput, sizeof(LOADDRIVERINPUT),
  1000. spOutput, sizeof(KERNEL_PVOID));
  1001. if (NT_SUCCESS( Status ))
  1002. {
  1003. umpdCookie = *((KERNEL_PVOID *) ServerToClientPtr(spOutput));
  1004. }
  1005. return umpdCookie;
  1006. }
  1007. void
  1008. PROXYPORT::UnloadDriver(
  1009. KERNEL_PVOID umpdCookie,
  1010. HANDLE hPrinter32,
  1011. BOOL bNotifySpooler
  1012. )
  1013. {
  1014. NTSTATUS Status = STATUS_SUCCESS;
  1015. SERVERPTR spInput;
  1016. UNLOADDRIVERINPUT * pInput;
  1017. HeapInit();
  1018. if (spInput = HeapAlloc(sizeof(UNLOADDRIVERINPUT)))
  1019. {
  1020. pInput = (UNLOADDRIVERINPUT *) ServerToClientPtr(spInput);
  1021. pInput->umpdCookie = umpdCookie;
  1022. pInput->clientPid = GetCurrentProcessId();
  1023. pInput->hPrinter32 = HandleToUlong(hPrinter32);
  1024. pInput->bNotifySpooler = bNotifySpooler;
  1025. pInput->umpdthdr.umthdr.ulType = INDEX_UnloadUMPrinterDrv;
  1026. Status = SendRequest(spInput, sizeof(spInput), 0, 0);
  1027. }
  1028. }
  1029. int
  1030. PROXYPORT::DocumentEvent(
  1031. KERNEL_PVOID umpdCookie,
  1032. HANDLE hPrinter32,
  1033. HDC hdc,
  1034. INT iEsc,
  1035. ULONG cjIn,
  1036. PVOID pvIn,
  1037. ULONG cjOut,
  1038. PVOID pvOut
  1039. )
  1040. {
  1041. NTSTATUS Status = STATUS_SUCCESS;
  1042. SERVERPTR spInput;
  1043. SERVERPTR spOutput;
  1044. DOCUMENTEVENTINPUT* pInput;
  1045. CLIENTPTR cppvIn = NULL;
  1046. INT iRet = DOCUMENTEVENT_FAILURE;
  1047. ULONG cjAlloc = 0;
  1048. DEVMODEW *pdmCopy = NULL;
  1049. HeapInit();
  1050. if (!(spInput = HeapAlloc(sizeof(DOCUMENTEVENTINPUT))) ||
  1051. !(pInput = (DOCUMENTEVENTINPUT *) ServerToClientPtr(spInput)) ||
  1052. !(spOutput = HeapAlloc(sizeof(int))))
  1053. {
  1054. return DOCUMENTEVENT_FAILURE;
  1055. }
  1056. pInput->umpdthdr.umthdr.ulType = INDEX_DocumentEvent;
  1057. pInput->umpdthdr.umthdr.cjSize = sizeof(*pInput);
  1058. pInput->umpdCookie = umpdCookie;
  1059. pInput->clientPid = GetCurrentProcessId();
  1060. pInput->hPrinter32 = HandleToUlong(hPrinter32);
  1061. pInput->hdc = (KHDC)hdc;
  1062. pInput->iEsc = iEsc;
  1063. pInput->cjIn = cjIn;
  1064. pInput->pvIn = NULL;
  1065. pInput->cjOut = cjOut;
  1066. pInput->pvOut = NULL;
  1067. pInput->pdmCopy = NULL;
  1068. // thunk input data
  1069. if (cjIn && pvIn)
  1070. {
  1071. if (iEsc == DOCUMENTEVENT_CREATEDCPRE)
  1072. {
  1073. cjAlloc = sizeof(DOCEVENT_CREATEDCPRE_UMPD);
  1074. }
  1075. else if (iEsc == DOCUMENTEVENT_CREATEDCPOST ||
  1076. iEsc == DOCUMENTEVENT_RESETDCPRE ||
  1077. iEsc == DOCUMENTEVENT_RESETDCPOST ||
  1078. iEsc == DOCUMENTEVENT_STARTDOCPRE)
  1079. {
  1080. cjAlloc = sizeof(KPBYTE);
  1081. }
  1082. else if (iEsc == DOCUMENTEVENT_ESCAPE)
  1083. {
  1084. cjAlloc = sizeof(DOCEVENT_ESCAPE_UMPD);
  1085. }
  1086. // allocate heap
  1087. if (cjAlloc)
  1088. {
  1089. if (!(pInput->pvIn = HeapAlloc(cjAlloc)))
  1090. {
  1091. return DOCUMENTEVENT_FAILURE;
  1092. }
  1093. pInput->cjIn = cjAlloc;
  1094. cppvIn = ServerToClientPtr(pInput->pvIn);
  1095. }
  1096. switch (iEsc)
  1097. {
  1098. case DOCUMENTEVENT_CREATEDCPRE:
  1099. {
  1100. DOCEVENT_CREATEDCPRE_UMPD *pDocEvent = (DOCEVENT_CREATEDCPRE_UMPD*)cppvIn;
  1101. DOCEVENT_CREATEDCPRE *pDocEventIn = (DOCEVENT_CREATEDCPRE*)pvIn;
  1102. pDocEvent->pszDriver = (KPBYTE)0;
  1103. pDocEvent->pszDevice = (KPBYTE)pDocEventIn->pszDevice;
  1104. pDocEvent->pdm = (KPBYTE)pDocEventIn->pdm;
  1105. pDocEvent->bIC = pDocEventIn->bIC;
  1106. if (!ThunkStr((LPWSTR*)&pDocEvent->pszDevice) ||
  1107. !ThunkMemBlock(&pDocEvent->pdm, sizeof(DEVMODEW)))
  1108. {
  1109. return DOCUMENTEVENT_FAILURE;
  1110. }
  1111. }
  1112. break;
  1113. case DOCUMENTEVENT_RESETDCPRE:
  1114. {
  1115. *((KPBYTE*)cppvIn) = (KPBYTE)(*((DEVMODEW**)pvIn));
  1116. if (!ThunkMemBlock((KPBYTE*)cppvIn, sizeof(DEVMODEW)))
  1117. return DOCUMENTEVENT_FAILURE;
  1118. }
  1119. break;
  1120. case DOCUMENTEVENT_STARTDOCPRE:
  1121. {
  1122. SERVERPTR spTemp;
  1123. DOCINFOW_UMPD *pDocInfo;
  1124. DOCINFOW *pDocInfoIn = *((DOCINFOW**)pvIn);
  1125. if (!(spTemp = HeapAlloc(sizeof(DOCINFOW_UMPD))))
  1126. return DOCUMENTEVENT_FAILURE;
  1127. *((KPBYTE*)cppvIn) = spTemp;
  1128. pDocInfo = (DOCINFOW_UMPD*)ServerToClientPtr(spTemp);
  1129. pDocInfo->cbSize = pDocInfoIn->cbSize;
  1130. pDocInfo->lpszDocName = (KLPWSTR)pDocInfoIn->lpszDocName;
  1131. pDocInfo->lpszOutput = (KLPWSTR)pDocInfoIn->lpszOutput;
  1132. pDocInfo->lpszDatatype = (KLPWSTR)pDocInfoIn->lpszDatatype;
  1133. pDocInfo->fwType = pDocInfoIn->fwType;
  1134. if (!ThunkStr((LPWSTR*)&pDocInfo->lpszDocName) ||
  1135. !ThunkStr((LPWSTR*)&pDocInfo->lpszOutput) ||
  1136. !ThunkStr((LPWSTR*)&pDocInfo->lpszDatatype))
  1137. {
  1138. return DOCUMENTEVENT_FAILURE;
  1139. }
  1140. }
  1141. break;
  1142. case DOCUMENTEVENT_CREATEDCPOST:
  1143. case DOCUMENTEVENT_RESETDCPOST:
  1144. {
  1145. if (*((PDEVMODEW *)pvIn))
  1146. {
  1147. KPBYTE *ppdmDrv = (KPBYTE*)(*((PBYTE*)pvIn) + sizeof(DEVMODEW));
  1148. *((KPBYTE*)cppvIn) = *ppdmDrv;
  1149. LOCALFREE(*(PBYTE*)pvIn);
  1150. }
  1151. else
  1152. {
  1153. *((KPBYTE*)cppvIn) = NULL;
  1154. }
  1155. }
  1156. break;
  1157. case DOCUMENTEVENT_STARTDOCPOST:
  1158. {
  1159. pInput->pvIn = (KPBYTE)pvIn;
  1160. if (!ThunkMemBlock(&pInput->pvIn, sizeof(LONG)))
  1161. return DOCUMENTEVENT_FAILURE;
  1162. }
  1163. break;
  1164. case DOCUMENTEVENT_ESCAPE:
  1165. {
  1166. DOCEVENT_ESCAPE_UMPD *pEscape = (DOCEVENT_ESCAPE_UMPD*)cppvIn;
  1167. DOCEVENT_ESCAPE *pEscapeIn = (DOCEVENT_ESCAPE*)pvIn;
  1168. pEscape->iEscape = pEscapeIn->iEscape;
  1169. pEscape->cjInput = pEscapeIn->cjInput;
  1170. pEscape->pvInData = (KPBYTE)pEscapeIn->pvInData;
  1171. if (!ThunkMemBlock(&pEscape->pvInData, (ULONG)pEscapeIn->cjInput))
  1172. return DOCUMENTEVENT_FAILURE;
  1173. }
  1174. break;
  1175. default:
  1176. return DOCUMENTEVENT_FAILURE;
  1177. }
  1178. }
  1179. if (cjOut && pvOut)
  1180. {
  1181. if (iEsc == DOCUMENTEVENT_CREATEDCPRE || iEsc == DOCUMENTEVENT_RESETDCPRE)
  1182. {
  1183. if (!(pInput->pvOut = HeapAlloc(sizeof(KPBYTE))) ||
  1184. !(pInput->pdmCopy = HeapAlloc(sizeof(DEVMODEW))) ||
  1185. !(pdmCopy = (DEVMODEW*)LOCALALLOC(sizeof(DEVMODEW) + sizeof(KPBYTE))))
  1186. {
  1187. return DOCUMENTEVENT_FAILURE;
  1188. }
  1189. *((KPBYTE*)ServerToClientPtr(pInput->pvOut)) = 0;
  1190. pInput->cjOut = sizeof(KPBYTE);
  1191. }
  1192. else if (iEsc == DOCUMENTEVENT_ESCAPE)
  1193. {
  1194. if (!(pInput->pvOut = HeapAlloc(cjOut)))
  1195. return DOCUMENTEVENT_FAILURE;
  1196. }
  1197. }
  1198. Status = SendRequest(spInput, sizeof(DOCUMENTEVENTINPUT), spOutput, sizeof(int));
  1199. if (NT_SUCCESS( Status ))
  1200. {
  1201. iRet = *((int *) ServerToClientPtr(spOutput));
  1202. if (iRet != DOCUMENTEVENT_FAILURE)
  1203. {
  1204. if (iEsc == DOCUMENTEVENT_CREATEDCPRE || iEsc == DOCUMENTEVENT_RESETDCPRE)
  1205. {
  1206. PDEVMODEW *ppvOut = (PDEVMODEW*)pvOut;
  1207. KPBYTE kpdm = *((KPBYTE*)ServerToClientPtr(pInput->pvOut));
  1208. ASSERTGDI(pvOut, "ProxyPort::DocumentEvent pvOut NULL\n");
  1209. *ppvOut = kpdm ? pdmCopy : NULL;
  1210. if (kpdm)
  1211. {
  1212. RtlCopyMemory(pdmCopy, (PVOID)ServerToClientPtr(pInput->pdmCopy), sizeof(DEVMODEW));
  1213. KPBYTE *ppdmDrv = (KPBYTE*)((PBYTE)pdmCopy + sizeof(DEVMODEW));
  1214. *ppdmDrv = kpdm;
  1215. }
  1216. else
  1217. {
  1218. LOCALFREE(pdmCopy);
  1219. }
  1220. }
  1221. else if (iEsc == DOCUMENTEVENT_ESCAPE)
  1222. {
  1223. if (cjOut && pvOut)
  1224. RtlCopyMemory(pvOut, (PVOID)ServerToClientPtr(pInput->pvOut), cjOut);
  1225. }
  1226. }
  1227. else
  1228. {
  1229. WARNING("DocumentEvent failed \n");
  1230. }
  1231. }
  1232. if (iRet == DOCUMENTEVENT_FAILURE && pdmCopy)
  1233. {
  1234. LOCALFREE(pdmCopy);
  1235. }
  1236. return iRet;
  1237. }
  1238. DWORD
  1239. PROXYPORT::StartDocPrinterW(
  1240. KERNEL_PVOID umpdCookie,
  1241. HANDLE hPrinter32,
  1242. DWORD level,
  1243. LPBYTE pDocInfo
  1244. )
  1245. {
  1246. NTSTATUS Status = STATUS_SUCCESS;
  1247. SERVERPTR spInput;
  1248. SERVERPTR spOutput;
  1249. STARTDOCPRINTERWINPUT* pInput;
  1250. CLIENTPTR cppDocInfo;
  1251. HeapInit();
  1252. if (!(spInput = HeapAlloc(sizeof(STARTDOCPRINTERWINPUT))) ||
  1253. !(spOutput = HeapAlloc(sizeof(DWORD))))
  1254. return 0;
  1255. pInput = (STARTDOCPRINTERWINPUT *) ServerToClientPtr(spInput);
  1256. pInput->umpdthdr.umthdr.ulType = INDEX_StartDocPrinterW;
  1257. pInput->umpdthdr.umthdr.cjSize = sizeof(*pInput);
  1258. pInput->umpdCookie = umpdCookie;
  1259. pInput->clientPid = GetCurrentProcessId();
  1260. pInput->hPrinter32 = HandleToUlong(hPrinter32);
  1261. pInput->level = level;
  1262. pInput->lastError = 0;
  1263. pInput->docInfo.pDocName = (KLPWSTR)((DOC_INFO_1W*)pDocInfo)->pDocName;
  1264. pInput->docInfo.pOutputFile = (KLPWSTR)((DOC_INFO_1W*)pDocInfo)->pOutputFile;
  1265. pInput->docInfo.pDatatype = (KLPWSTR)((DOC_INFO_1W*)pDocInfo)->pDatatype;
  1266. // GDI only uses level 1 and level 3
  1267. if (level == 3)
  1268. pInput->docInfo.dwFlags = ((DOC_INFO_3W*)pDocInfo)->dwFlags;
  1269. else
  1270. pInput->docInfo.dwFlags = 0;
  1271. if (!ThunkStr((LPWSTR *)&pInput->docInfo.pDocName) ||
  1272. !ThunkStr((LPWSTR *)&pInput->docInfo.pOutputFile) ||
  1273. !ThunkStr((LPWSTR *)&pInput->docInfo.pDatatype))
  1274. return 0;
  1275. Status = SendRequest(spInput, sizeof(STARTDOCPRINTERWINPUT), spOutput, sizeof(DWORD));
  1276. if (!NT_SUCCESS( Status ))
  1277. return 0;
  1278. else
  1279. {
  1280. if (pInput->lastError)
  1281. GdiSetLastError(pInput->lastError);
  1282. return (*((DWORD *) ServerToClientPtr(spOutput)));
  1283. }
  1284. }
  1285. BOOL
  1286. PROXYPORT::StartPagePrinter(KERNEL_PVOID umpdCookie, HANDLE hPrinter32)
  1287. {
  1288. NTSTATUS Status = STATUS_SUCCESS;
  1289. SERVERPTR spInput;
  1290. SERVERPTR spOutput;
  1291. UMPDSIMPLEINPUT* pInput;
  1292. HeapInit();
  1293. if (!(spInput = HeapAlloc(sizeof(UMPDSIMPLEINPUT))) ||
  1294. !(spOutput = HeapAlloc(sizeof(BOOL))))
  1295. return FALSE;
  1296. pInput = (UMPDSIMPLEINPUT *) ServerToClientPtr(spInput);
  1297. pInput->umpdthdr.umthdr.ulType = INDEX_StartPagePrinter;
  1298. pInput->umpdthdr.umthdr.cjSize = sizeof(UMPDSIMPLEINPUT);
  1299. pInput->umpdCookie = umpdCookie;
  1300. pInput->clientPid = GetCurrentProcessId();
  1301. pInput->hPrinter32 = HandleToUlong(hPrinter32);
  1302. Status = SendRequest(spInput, sizeof(UMPDSIMPLEINPUT), spOutput, sizeof(BOOL));
  1303. if (!NT_SUCCESS( Status ))
  1304. return FALSE;
  1305. return (*((BOOL*)ServerToClientPtr(spOutput)));
  1306. }
  1307. BOOL
  1308. PROXYPORT::EndPagePrinter(KERNEL_PVOID umpdCookie, HANDLE hPrinter32)
  1309. {
  1310. NTSTATUS Status = STATUS_SUCCESS;
  1311. SERVERPTR spInput;
  1312. SERVERPTR spOutput;
  1313. UMPDSIMPLEINPUT* pInput;
  1314. HeapInit();
  1315. if (!(spInput = HeapAlloc(sizeof(UMPDSIMPLEINPUT))) ||
  1316. !(spOutput = HeapAlloc(sizeof(BOOL))))
  1317. return FALSE;
  1318. pInput = (UMPDSIMPLEINPUT *) ServerToClientPtr(spInput);
  1319. pInput->umpdthdr.umthdr.ulType = INDEX_EndPagePrinter;
  1320. pInput->umpdthdr.umthdr.cjSize = sizeof(UMPDSIMPLEINPUT);
  1321. pInput->umpdCookie = umpdCookie;
  1322. pInput->clientPid = GetCurrentProcessId();
  1323. pInput->hPrinter32 = HandleToUlong(hPrinter32);
  1324. Status = SendRequest(spInput, sizeof(UMPDSIMPLEINPUT), spOutput, sizeof(BOOL));
  1325. if (!NT_SUCCESS( Status ))
  1326. return FALSE;
  1327. return (*((BOOL*)ServerToClientPtr(spOutput)));
  1328. }
  1329. BOOL
  1330. PROXYPORT::EndDocPrinter(KERNEL_PVOID umpdCookie, HANDLE hPrinter32)
  1331. {
  1332. NTSTATUS Status = STATUS_SUCCESS;
  1333. SERVERPTR spInput;
  1334. SERVERPTR spOutput;
  1335. UMPDSIMPLEINPUT* pInput;
  1336. HeapInit();
  1337. if (!(spInput = HeapAlloc(sizeof(UMPDSIMPLEINPUT))) ||
  1338. !(spOutput = HeapAlloc(sizeof(BOOL))))
  1339. return FALSE;
  1340. pInput = (UMPDSIMPLEINPUT *) ServerToClientPtr(spInput);
  1341. pInput->umpdthdr.umthdr.ulType = INDEX_EndDocPrinter;
  1342. pInput->umpdthdr.umthdr.cjSize = sizeof(UMPDSIMPLEINPUT);
  1343. pInput->umpdCookie = umpdCookie;
  1344. pInput->clientPid = GetCurrentProcessId();
  1345. pInput->hPrinter32 = HandleToUlong(hPrinter32);
  1346. Status = SendRequest(spInput, sizeof(UMPDSIMPLEINPUT), spOutput, sizeof(BOOL));
  1347. if (!NT_SUCCESS( Status ))
  1348. return FALSE;
  1349. return (*((BOOL*)ServerToClientPtr(spOutput)));
  1350. }
  1351. BOOL
  1352. PROXYPORT::AbortPrinter(KERNEL_PVOID umpdCookie, HANDLE hPrinter32)
  1353. {
  1354. NTSTATUS Status = STATUS_SUCCESS;
  1355. SERVERPTR spInput;
  1356. SERVERPTR spOutput;
  1357. UMPDSIMPLEINPUT* pInput;
  1358. HeapInit();
  1359. if (!(spInput = HeapAlloc(sizeof(UMPDSIMPLEINPUT))) ||
  1360. !(spOutput = HeapAlloc(sizeof(BOOL))))
  1361. return FALSE;
  1362. pInput = (UMPDSIMPLEINPUT *) ServerToClientPtr(spInput);
  1363. pInput->umpdthdr.umthdr.ulType = INDEX_AbortPrinter;
  1364. pInput->umpdthdr.umthdr.cjSize = sizeof(UMPDSIMPLEINPUT);
  1365. pInput->umpdCookie = umpdCookie;
  1366. pInput->clientPid = GetCurrentProcessId();
  1367. pInput->hPrinter32 = HandleToUlong(hPrinter32);
  1368. Status = SendRequest(spInput, sizeof(UMPDSIMPLEINPUT), spOutput, sizeof(BOOL));
  1369. if (!NT_SUCCESS( Status ))
  1370. return FALSE;
  1371. return (*((BOOL*)ServerToClientPtr(spOutput)));
  1372. }
  1373. BOOL
  1374. PROXYPORT::ResetPrinterW(KERNEL_PVOID umpdCookie, HANDLE hPrinter32, PRINTER_DEFAULTSW *pPtrDef)
  1375. {
  1376. NTSTATUS Status = STATUS_SUCCESS;
  1377. SERVERPTR spInput;
  1378. SERVERPTR spOutput;
  1379. RESETPRINTERWINPUT* pInput;
  1380. HeapInit();
  1381. if (!(spInput = HeapAlloc(sizeof(RESETPRINTERWINPUT))) ||
  1382. !(spOutput = HeapAlloc(sizeof(BOOL))))
  1383. return FALSE;
  1384. pInput = (RESETPRINTERWINPUT *) ServerToClientPtr(spInput);
  1385. pInput->umpdthdr.umthdr.ulType = INDEX_ResetPrinterW;
  1386. pInput->umpdthdr.umthdr.cjSize = sizeof(RESETPRINTERWINPUT);
  1387. pInput->umpdCookie = umpdCookie;
  1388. pInput->clientPid = GetCurrentProcessId();
  1389. pInput->hPrinter32 = HandleToUlong(hPrinter32);
  1390. pInput->ptrDef.pDatatype = (KLPWSTR)pPtrDef->pDatatype;
  1391. pInput->ptrDef.pDevMode = (KPBYTE)pPtrDef->pDevMode;
  1392. pInput->ptrDef.DesiredAccess = pPtrDef->DesiredAccess;
  1393. if (!ThunkStr((LPWSTR *)&pInput->ptrDef.pDatatype) ||
  1394. !ThunkMemBlock(&pInput->ptrDef.pDevMode, sizeof(DEVMODEW)))
  1395. return FALSE;
  1396. Status = SendRequest(spInput, sizeof(RESETPRINTERWINPUT), spOutput, sizeof(BOOL));
  1397. if (!NT_SUCCESS( Status ))
  1398. return FALSE;
  1399. return (*((BOOL*)ServerToClientPtr(spOutput)));
  1400. }
  1401. BOOL
  1402. PROXYPORT::QueryColorProfile(
  1403. KERNEL_PVOID umpdCookie,
  1404. HANDLE hPrinter32,
  1405. PDEVMODEW pDevMode,
  1406. ULONG ulQueryMode,
  1407. PVOID pvProfileData,
  1408. ULONG* pcjProfileSize,
  1409. FLONG* pflProfileFlag
  1410. )
  1411. {
  1412. NTSTATUS Status = STATUS_SUCCESS;
  1413. SERVERPTR spInput;
  1414. SERVERPTR spOutput;
  1415. QUERYCOLORPROFILEINPUT* pInput;
  1416. HeapInit();
  1417. if (!(spInput = HeapAlloc(sizeof(QUERYCOLORPROFILEINPUT))) ||
  1418. !(spOutput = HeapAlloc(sizeof(BOOL))))
  1419. return -1;
  1420. pInput = (QUERYCOLORPROFILEINPUT*) ServerToClientPtr(spInput);
  1421. pInput->umpdthdr.umthdr.ulType = INDEX_QueryColorProfile;
  1422. pInput->umpdthdr.umthdr.cjSize = sizeof(QUERYCOLORPROFILEINPUT);
  1423. pInput->umpdCookie = umpdCookie;
  1424. pInput->clientPid = GetCurrentProcessId();
  1425. pInput->hPrinter32 = HandleToUlong(hPrinter32);
  1426. pInput->pDevMode = pDevMode;
  1427. pInput->ulQueryMode = ulQueryMode;
  1428. pInput->cjProfileSize = *pcjProfileSize;
  1429. pInput->flProfileFlag = *pflProfileFlag;
  1430. pInput->lastError = 0;
  1431. if (!(pInput->pvProfileData = HeapAlloc(*pcjProfileSize)) ||
  1432. !ThunkMemBlock((KPBYTE*)&pInput->pDevMode, sizeof(DEVMODEW)))
  1433. return -1;
  1434. Status = SendRequest(spInput, sizeof(QUERYCOLORPROFILEINPUT), spOutput, sizeof(BOOL));
  1435. if (!NT_SUCCESS( Status ))
  1436. return -1;
  1437. else
  1438. {
  1439. if (pInput->lastError)
  1440. GdiSetLastError(pInput->lastError);
  1441. return (*((BOOL*)ServerToClientPtr(spOutput)));
  1442. }
  1443. }