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.

1480 lines
36 KiB

  1. /*++
  2. Copyright (c) 1990 - 1995 Microsoft Corporation
  3. Module Name:
  4. winspool.c
  5. Abstract:
  6. This module provides all the public exported APIs relating to Printer
  7. and Job management for the Print Providor Routing layer
  8. Author:
  9. Dave Snipp (DaveSn) 15-Mar-1991
  10. [Notes:]
  11. optional-notes
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include "local.h"
  17. //
  18. // Globals
  19. //
  20. LPPROVIDOR pLocalProvidor;
  21. MODULE_DEBUG_INIT( DBG_ERROR, DBG_ERROR );
  22. LPWSTR szRegistryProvidors = L"System\\CurrentControlSet\\Control\\Print\\Providers";
  23. LPWSTR szPrintKey = L"System\\CurrentControlSet\\Control\\Print";
  24. LPWSTR szLocalSplDll = L"localspl.dll";
  25. LPWSTR szOrder = L"Order";
  26. LPWSTR szEnvironment = LOCAL_ENVIRONMENT;
  27. //
  28. // Strings for handling the AddPrinterDrivers policy
  29. //
  30. LPWSTR szLanManProvider = L"LanMan Print Services";
  31. LPWSTR szAPDRelPath = L"LanMan Print Services\\Servers";
  32. LPWSTR szAPDValueName = L"AddPrinterDrivers";
  33. BOOL
  34. AddPrinterDriverW(
  35. LPWSTR pName,
  36. DWORD Level,
  37. LPBYTE pDriverInfo
  38. )
  39. {
  40. LPPROVIDOR pProvidor;
  41. WaitForSpoolerInitialization();
  42. pProvidor = pLocalProvidor;
  43. while (pProvidor) {
  44. if ((*pProvidor->PrintProvidor.fpAddPrinterDriver) (pName, Level, pDriverInfo)) {
  45. return TRUE;
  46. } else if (GetLastError() != ERROR_INVALID_NAME) {
  47. return FALSE;
  48. }
  49. pProvidor = pProvidor->pNext;
  50. }
  51. SetLastError(ERROR_INVALID_PARAMETER);
  52. return FALSE;
  53. }
  54. BOOL
  55. AddPrinterDriverExW(
  56. LPWSTR pName,
  57. DWORD Level,
  58. LPBYTE pDriverInfo,
  59. DWORD dwFileCopyFlags
  60. )
  61. {
  62. LPPROVIDOR pProvidor;
  63. WaitForSpoolerInitialization();
  64. pProvidor = pLocalProvidor;
  65. while (pProvidor) {
  66. if ((*pProvidor->PrintProvidor.fpAddPrinterDriverEx) (pName,
  67. Level,
  68. pDriverInfo,
  69. dwFileCopyFlags)) {
  70. return TRUE;
  71. } else if (GetLastError() != ERROR_INVALID_NAME) {
  72. return FALSE;
  73. }
  74. pProvidor = pProvidor->pNext;
  75. }
  76. SetLastError(ERROR_INVALID_PARAMETER);
  77. return FALSE;
  78. }
  79. BOOL
  80. AddDriverCatalog(
  81. HANDLE hPrinter,
  82. DWORD dwLevel,
  83. VOID *pvDriverInfCatInfo,
  84. DWORD dwCatalogCopyFlags
  85. )
  86. {
  87. HRESULT hRetval = E_FAIL;
  88. LPPRINTHANDLE pPrintHandle = (LPPRINTHANDLE)hPrinter;
  89. hRetval = pPrintHandle && (PRINTHANDLE_SIGNATURE == pPrintHandle->signature) ? S_OK : HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE);
  90. if (SUCCEEDED(hRetval))
  91. {
  92. hRetval = (*pPrintHandle->pProvidor->PrintProvidor.fpAddDriverCatalog) (pPrintHandle->hPrinter,
  93. dwLevel, pvDriverInfCatInfo, dwCatalogCopyFlags);
  94. }
  95. if (FAILED(hRetval))
  96. {
  97. SetLastError(HRESULT_CODE(hRetval));
  98. }
  99. return hRetval;
  100. }
  101. BOOL
  102. EnumPrinterDriversW(
  103. LPWSTR pName,
  104. LPWSTR pEnvironment,
  105. DWORD Level,
  106. LPBYTE pDrivers,
  107. DWORD cbBuf,
  108. LPDWORD pcbNeeded,
  109. LPDWORD pcReturned
  110. )
  111. {
  112. PROVIDOR *pProvidor;
  113. if ((pDrivers == NULL) && (cbBuf != 0)) {
  114. SetLastError(ERROR_INVALID_USER_BUFFER);
  115. return FALSE;
  116. }
  117. WaitForSpoolerInitialization();
  118. if (!pEnvironment || !*pEnvironment)
  119. pEnvironment = szEnvironment;
  120. pProvidor = pLocalProvidor;
  121. while (pProvidor) {
  122. if (!(*pProvidor->PrintProvidor.fpEnumPrinterDrivers) (pName, pEnvironment, Level,
  123. pDrivers, cbBuf,
  124. pcbNeeded, pcReturned)) {
  125. if (GetLastError() != ERROR_INVALID_NAME)
  126. return FALSE;
  127. } else
  128. return TRUE;
  129. pProvidor = pProvidor->pNext;
  130. }
  131. SetLastError(ERROR_INVALID_PARAMETER);
  132. return FALSE;
  133. }
  134. BOOL
  135. GetPrinterDriverDirectoryW(
  136. LPWSTR pName,
  137. LPWSTR pEnvironment,
  138. DWORD Level,
  139. LPBYTE pDriverInfo,
  140. DWORD cbBuf,
  141. LPDWORD pcbNeeded
  142. )
  143. {
  144. LPPROVIDOR pProvidor;
  145. DWORD Error;
  146. if ((pDriverInfo == NULL) && (cbBuf != 0)) {
  147. SetLastError(ERROR_INVALID_USER_BUFFER);
  148. return FALSE;
  149. }
  150. WaitForSpoolerInitialization();
  151. if (!pEnvironment || !*pEnvironment)
  152. pEnvironment = szEnvironment;
  153. pProvidor = pLocalProvidor;
  154. while (pProvidor) {
  155. if ((*pProvidor->PrintProvidor.fpGetPrinterDriverDirectory)
  156. (pName, pEnvironment, Level, pDriverInfo,
  157. cbBuf, pcbNeeded)) {
  158. return TRUE;
  159. } else if ((Error=GetLastError()) != ERROR_INVALID_NAME) {
  160. return FALSE;
  161. }
  162. pProvidor = pProvidor->pNext;
  163. }
  164. return FALSE;
  165. }
  166. BOOL
  167. DeletePrinterDriverW(
  168. LPWSTR pName,
  169. LPWSTR pEnvironment,
  170. LPWSTR pDriverName
  171. )
  172. {
  173. LPPROVIDOR pProvidor;
  174. DWORD Error;
  175. WaitForSpoolerInitialization();
  176. if (!pEnvironment || !*pEnvironment)
  177. pEnvironment = szEnvironment;
  178. pProvidor = pLocalProvidor;
  179. while (pProvidor) {
  180. if ((*pProvidor->PrintProvidor.fpDeletePrinterDriver)
  181. (pName, pEnvironment, pDriverName)) {
  182. return TRUE;
  183. } else if ((Error=GetLastError()) != ERROR_INVALID_NAME) {
  184. return FALSE;
  185. }
  186. pProvidor = pProvidor->pNext;
  187. }
  188. return FALSE;
  189. }
  190. BOOL
  191. DeletePrinterDriverExW(
  192. LPWSTR pName,
  193. LPWSTR pEnvironment,
  194. LPWSTR pDriverName,
  195. DWORD dwDeleteFlag,
  196. DWORD dwVersionNum
  197. )
  198. {
  199. LPPROVIDOR pProvidor;
  200. WaitForSpoolerInitialization();
  201. if (!pEnvironment || !*pEnvironment)
  202. pEnvironment = szEnvironment;
  203. pProvidor = pLocalProvidor;
  204. while (pProvidor) {
  205. if ((*pProvidor->PrintProvidor.fpDeletePrinterDriverEx)
  206. (pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionNum)) {
  207. return TRUE;
  208. }
  209. if (GetLastError() != ERROR_INVALID_NAME) {
  210. return FALSE;
  211. }
  212. pProvidor = pProvidor->pNext;
  213. }
  214. return FALSE;
  215. }
  216. BOOL
  217. AddPrintProcessorW(
  218. LPWSTR pName,
  219. LPWSTR pEnvironment,
  220. LPWSTR pPathName,
  221. LPWSTR pPrintProcessorName
  222. )
  223. {
  224. LPPROVIDOR pProvidor;
  225. WaitForSpoolerInitialization();
  226. if (!pEnvironment || !*pEnvironment)
  227. pEnvironment = szEnvironment;
  228. pProvidor = pLocalProvidor;
  229. while (pProvidor) {
  230. if ((*pProvidor->PrintProvidor.fpAddPrintProcessor) (pName, pEnvironment,
  231. pPathName,
  232. pPrintProcessorName)) {
  233. return TRUE;
  234. } else if (GetLastError() != ERROR_INVALID_NAME) {
  235. return FALSE;
  236. }
  237. pProvidor = pProvidor->pNext;
  238. }
  239. SetLastError(ERROR_INVALID_PARAMETER);
  240. return FALSE;
  241. }
  242. BOOL
  243. EnumPrintProcessorsW(
  244. LPWSTR pName,
  245. LPWSTR pEnvironment,
  246. DWORD Level,
  247. LPBYTE pPrintProcessors,
  248. DWORD cbBuf,
  249. LPDWORD pcbNeeded,
  250. LPDWORD pcReturned
  251. )
  252. {
  253. LPPROVIDOR pProvidor;
  254. if ((pPrintProcessors == NULL) && (cbBuf != 0)) {
  255. SetLastError(ERROR_INVALID_USER_BUFFER);
  256. return FALSE;
  257. }
  258. WaitForSpoolerInitialization();
  259. if (!pEnvironment || !*pEnvironment)
  260. pEnvironment = szEnvironment;
  261. pProvidor = pLocalProvidor;
  262. while (pProvidor) {
  263. if (!(*pProvidor->PrintProvidor.fpEnumPrintProcessors) (pName, pEnvironment, Level,
  264. pPrintProcessors, cbBuf,
  265. pcbNeeded, pcReturned)) {
  266. if (GetLastError() != ERROR_INVALID_NAME)
  267. return FALSE;
  268. } else
  269. return TRUE;
  270. pProvidor = pProvidor->pNext;
  271. }
  272. SetLastError(ERROR_INVALID_PARAMETER);
  273. return FALSE;
  274. }
  275. BOOL
  276. GetPrintProcessorDirectoryW(
  277. LPWSTR pName,
  278. LPWSTR pEnvironment,
  279. DWORD Level,
  280. LPBYTE pPrintProcessorInfo,
  281. DWORD cbBuf,
  282. LPDWORD pcbNeeded
  283. )
  284. {
  285. LPPROVIDOR pProvidor;
  286. DWORD Error;
  287. if ((pPrintProcessorInfo == NULL) && (cbBuf != 0)) {
  288. SetLastError(ERROR_INVALID_USER_BUFFER);
  289. return FALSE;
  290. }
  291. WaitForSpoolerInitialization();
  292. if (!pEnvironment || !*pEnvironment)
  293. pEnvironment = szEnvironment;
  294. pProvidor = pLocalProvidor;
  295. while (pProvidor) {
  296. if ((*pProvidor->PrintProvidor.fpGetPrintProcessorDirectory)
  297. (pName, pEnvironment, Level,
  298. pPrintProcessorInfo,
  299. cbBuf, pcbNeeded)) {
  300. return TRUE;
  301. } else if ((Error=GetLastError()) != ERROR_INVALID_NAME) {
  302. return FALSE;
  303. }
  304. pProvidor = pProvidor->pNext;
  305. }
  306. SetLastError(ERROR_INVALID_PARAMETER);
  307. return FALSE;
  308. }
  309. BOOL
  310. EnumPrintProcessorDatatypesW(
  311. LPWSTR pName,
  312. LPWSTR pPrintProcessorName,
  313. DWORD Level,
  314. LPBYTE pDatatypes,
  315. DWORD cbBuf,
  316. LPDWORD pcbNeeded,
  317. LPDWORD pcReturned
  318. )
  319. {
  320. LPPROVIDOR pProvidor;
  321. if ((pDatatypes == NULL) && (cbBuf != 0)) {
  322. SetLastError(ERROR_INVALID_USER_BUFFER);
  323. return FALSE;
  324. }
  325. WaitForSpoolerInitialization();
  326. pProvidor = pLocalProvidor;
  327. while (pProvidor) {
  328. if (!(*pProvidor->PrintProvidor.fpEnumPrintProcessorDatatypes)
  329. (pName, pPrintProcessorName,
  330. Level, pDatatypes, cbBuf,
  331. pcbNeeded, pcReturned)) {
  332. if (GetLastError() != ERROR_INVALID_NAME)
  333. return FALSE;
  334. } else
  335. return TRUE;
  336. pProvidor = pProvidor->pNext;
  337. }
  338. SetLastError(ERROR_INVALID_PARAMETER);
  339. return FALSE;
  340. }
  341. BOOL
  342. AddFormW(
  343. HANDLE hPrinter,
  344. DWORD Level,
  345. LPBYTE pForm
  346. )
  347. {
  348. LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
  349. if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
  350. SetLastError(ERROR_INVALID_HANDLE);
  351. return FALSE;
  352. }
  353. return (*pPrintHandle->pProvidor->PrintProvidor.fpAddForm) (pPrintHandle->hPrinter,
  354. Level, pForm);
  355. }
  356. BOOL
  357. DeleteFormW(
  358. HANDLE hPrinter,
  359. LPWSTR pFormName
  360. )
  361. {
  362. LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
  363. if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
  364. SetLastError(ERROR_INVALID_HANDLE);
  365. return FALSE;
  366. }
  367. return (*pPrintHandle->pProvidor->PrintProvidor.fpDeleteForm) (pPrintHandle->hPrinter,
  368. pFormName);
  369. }
  370. BOOL
  371. GetFormW(
  372. HANDLE hPrinter,
  373. LPWSTR pFormName,
  374. DWORD Level,
  375. LPBYTE pForm,
  376. DWORD cbBuf,
  377. LPDWORD pcbNeeded
  378. )
  379. {
  380. LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
  381. if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
  382. SetLastError(ERROR_INVALID_HANDLE);
  383. return FALSE;
  384. }
  385. if ((pForm == NULL) && (cbBuf != 0)) {
  386. SetLastError(ERROR_INVALID_USER_BUFFER);
  387. return FALSE;
  388. }
  389. return (*pPrintHandle->pProvidor->PrintProvidor.fpGetForm) (pPrintHandle->hPrinter,
  390. pFormName, Level, pForm,
  391. cbBuf, pcbNeeded);
  392. }
  393. BOOL
  394. SetFormW(
  395. HANDLE hPrinter,
  396. LPWSTR pFormName,
  397. DWORD Level,
  398. LPBYTE pForm
  399. )
  400. {
  401. LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
  402. if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
  403. SetLastError(ERROR_INVALID_HANDLE);
  404. return FALSE;
  405. }
  406. return (*pPrintHandle->pProvidor->PrintProvidor.fpSetForm) (pPrintHandle->hPrinter,
  407. pFormName, Level, pForm);
  408. }
  409. BOOL
  410. EnumFormsW(
  411. HANDLE hPrinter,
  412. DWORD Level,
  413. LPBYTE pForm,
  414. DWORD cbBuf,
  415. LPDWORD pcbNeeded,
  416. LPDWORD pcReturned
  417. )
  418. {
  419. LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
  420. if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
  421. SetLastError(ERROR_INVALID_HANDLE);
  422. return FALSE;
  423. }
  424. if ((pForm == NULL) && (cbBuf != 0)) {
  425. SetLastError(ERROR_INVALID_USER_BUFFER);
  426. return FALSE;
  427. }
  428. return (*pPrintHandle->pProvidor->PrintProvidor.fpEnumForms) (pPrintHandle->hPrinter,
  429. Level, pForm, cbBuf,
  430. pcbNeeded, pcReturned);
  431. }
  432. BOOL
  433. DeletePrintProcessorW(
  434. LPWSTR pName,
  435. LPWSTR pEnvironment,
  436. LPWSTR pPrintProcessorName
  437. )
  438. {
  439. LPPROVIDOR pProvidor;
  440. DWORD Error;
  441. WaitForSpoolerInitialization();
  442. if (!pEnvironment || !*pEnvironment)
  443. pEnvironment = szEnvironment;
  444. pProvidor = pLocalProvidor;
  445. while (pProvidor) {
  446. if ((*pProvidor->PrintProvidor.fpDeletePrintProcessor)
  447. (pName, pEnvironment, pPrintProcessorName)) {
  448. return TRUE;
  449. } else if ((Error=GetLastError()) != ERROR_INVALID_NAME) {
  450. return FALSE;
  451. }
  452. pProvidor = pProvidor->pNext;
  453. }
  454. return FALSE;
  455. }
  456. LPPROVIDOR FindProvidor(
  457. HKEY hProvidors,
  458. LPWSTR pName
  459. )
  460. /*++
  461. Function Description: Retrieves providor struct for a providor name.
  462. Parameters: hProvidors - handle to the Providors key
  463. pName - name of the providor
  464. Return Values: pProvidor if one is found; NULL otherwise
  465. --*/
  466. {
  467. LPPROVIDOR pProvidor;
  468. WCHAR szDllName[MAX_PATH];
  469. DWORD dwError;
  470. DWORD cbDllName;
  471. HKEY hProvidor = NULL;
  472. szDllName[0] = L'\0';
  473. cbDllName = COUNTOF(szDllName);
  474. // Search the registry for the DLL Name to compare with lpName
  475. if ((dwError = RegOpenKeyEx(hProvidors, pName, 0, KEY_READ, &hProvidor)) ||
  476. (dwError = RegQueryValueEx(hProvidor, L"Name", NULL, NULL,
  477. (LPBYTE)szDllName, &cbDllName)))
  478. {
  479. SetLastError(dwError);
  480. if (hProvidor)
  481. {
  482. RegCloseKey(hProvidor);
  483. }
  484. return NULL;
  485. }
  486. RegCloseKey(hProvidor);
  487. // Loop thru the list of providors for the name of the dll
  488. for (pProvidor = pLocalProvidor;
  489. pProvidor;
  490. pProvidor = pProvidor->pNext)
  491. {
  492. if (!_wcsicmp(pProvidor->lpName, szDllName))
  493. {
  494. break;
  495. }
  496. }
  497. return pProvidor;
  498. }
  499. // Struct to maintain the new order of the providors
  500. typedef struct _ProvidorList {
  501. struct _ProvidorList *pNext;
  502. LPPROVIDOR pProvidor;
  503. } ProvidorList;
  504. BOOL AddNodeToProvidorList(
  505. LPPROVIDOR pProvidor,
  506. ProvidorList **pStart
  507. )
  508. /*++
  509. Function Description: Adds a node to the list of providors. Avoids duplicate entries in
  510. the list
  511. Parameters: pProvidor - providor to be added
  512. pStart - pointer to the pointer to the start of the list
  513. Return Values: TRUE if successful; FALSE otherwise
  514. --*/
  515. {
  516. BOOL bReturn = FALSE;
  517. ProvidorList **pTemp, *pNew;
  518. // No providor found
  519. if (!pProvidor) {
  520. goto CleanUp;
  521. }
  522. for (pTemp = pStart; *pTemp; pTemp = &((*pTemp)->pNext))
  523. {
  524. if ((*pTemp)->pProvidor == pProvidor)
  525. {
  526. // Duplicates in the order string is an error
  527. goto CleanUp;
  528. }
  529. }
  530. // Add new node
  531. if (pNew = AllocSplMem(sizeof(ProvidorList)))
  532. {
  533. pNew->pNext = NULL;
  534. pNew->pProvidor = pProvidor;
  535. *pTemp = pNew;
  536. bReturn = TRUE;
  537. }
  538. CleanUp:
  539. return bReturn;
  540. }
  541. BOOL UpdateProvidorOrder(
  542. HKEY hProvidors,
  543. LPWSTR pOrder
  544. )
  545. /*++
  546. Function Description: Updates the order of the providors in spooler and the registry.
  547. Parameters: hProvidors - handle to Providors registry key
  548. pOrder - multisz order of providors
  549. Return Values: TRUE if successful; FALSE otherwise
  550. --*/
  551. {
  552. BOOL bReturn = FALSE, bRegChange = FALSE;
  553. DWORD dwError, dwRequired, dwBytes, dwOldCount, dwNewCount;
  554. LPWSTR pOldOrder = NULL, pStr;
  555. LPPROVIDOR pProvidor;
  556. // Maintain a list of the new order, so that error recovery is quick
  557. ProvidorList *pStart = NULL, *pTemp;
  558. // Loop thru the providor names in the new order
  559. for (pStr = pOrder, dwBytes = 0;
  560. pStr && *pStr;
  561. pStr += (wcslen(pStr) + 1))
  562. {
  563. pProvidor = FindProvidor(hProvidors, pStr);
  564. if (!AddNodeToProvidorList(pProvidor, &pStart)) {
  565. goto CleanUp;
  566. }
  567. dwBytes += (wcslen(pStr) + 1) * sizeof(WCHAR);
  568. }
  569. // Add the sizeof the last NULL char
  570. dwBytes += sizeof(WCHAR);
  571. // Make sure that all the providors are present in the list
  572. for (dwOldCount = 0, pProvidor = pLocalProvidor;
  573. pProvidor;
  574. ++dwOldCount, pProvidor = pProvidor->pNext) ;
  575. // Add 1 for the local providor which does not appear on the list
  576. for (dwNewCount = 1, pTemp = pStart;
  577. pTemp;
  578. ++dwNewCount, pTemp = pTemp->pNext) ;
  579. if (dwNewCount == dwOldCount) {
  580. // Update the registry
  581. if (dwError = RegSetValueEx(hProvidors, szOrder, 0,
  582. REG_MULTI_SZ, (LPBYTE)pOrder, dwBytes))
  583. {
  584. SetLastError(dwError);
  585. goto CleanUp;
  586. }
  587. // Change the order in the spooler structure
  588. for (pTemp = pStart, pProvidor = pLocalProvidor;
  589. pTemp;
  590. pTemp = pTemp->pNext, pProvidor = pProvidor->pNext)
  591. {
  592. pProvidor->pNext = pTemp->pProvidor;
  593. }
  594. pProvidor->pNext = NULL;
  595. bReturn = TRUE;
  596. } else {
  597. // All the providors are not listed in the order
  598. SetLastError(ERROR_INVALID_PARAMETER);
  599. }
  600. CleanUp:
  601. // Free the temp list
  602. while (pTemp = pStart) {
  603. pStart = pTemp->pNext;
  604. FreeSplMem(pTemp);
  605. }
  606. return bReturn;
  607. }
  608. BOOL AddNewProvidor(
  609. HKEY hProvidors,
  610. PPROVIDOR_INFO_1W pProvidorInfo
  611. )
  612. /*++
  613. Function Description: This function updates the registry with the new providor info and the
  614. new providor order. The new providor is appended to the current order.
  615. This order can be changed by calling AddPrintProvidor with
  616. Providor_info_2. The providor is immediately used for routing.
  617. Parameters: hProvidors - providors registry key
  618. pProvidorInfo - ProvidorInfo1 struct
  619. Return Values: TRUE if successful; FALSE otherwise
  620. --*/
  621. {
  622. BOOL bReturn = FALSE, bOrderUpdated = FALSE, bPresent = FALSE;
  623. DWORD dwError, dwRequired, dwReturned, dwOldSize, dwDisposition = 0;
  624. WCHAR szProvidorName[MAX_PATH+COUNTOF(szRegistryProvidors)];
  625. LPWSTR pOldOrder = NULL, pNewOrder = NULL;
  626. HKEY hNewProvidor = NULL;
  627. LPPROVIDOR pNewProvidor, pProvidor, pLastProvidor;
  628. if (!pProvidorInfo->pName || !pProvidorInfo->pDLLName ||
  629. !(*pProvidorInfo->pName) || !(*pProvidorInfo->pDLLName)) {
  630. SetLastError(ERROR_INVALID_PARAMETER);
  631. goto CleanUp;
  632. }
  633. for (pProvidor = pLocalProvidor; // Local Providor is always present
  634. pProvidor;
  635. pProvidor = pProvidor->pNext)
  636. {
  637. pLastProvidor = pProvidor;
  638. if (!lstrcmpi(pProvidor->lpName, pProvidorInfo->pDLLName))
  639. {
  640. //
  641. // This should return error, but it breaks some programs that
  642. // assume they can always add a provider
  643. //
  644. //SetLastError(ERROR_ALREADY_EXISTS);
  645. bReturn = TRUE;
  646. goto CleanUp;
  647. }
  648. }
  649. // Update the registry with new providor key
  650. if ((dwError = RegCreateKeyEx(hProvidors, pProvidorInfo->pName, 0, NULL, 0,
  651. KEY_ALL_ACCESS, NULL, &hNewProvidor, &dwDisposition)) ||
  652. (dwError = RegSetValueEx(hNewProvidor, L"Name", 0, REG_SZ,
  653. (LPBYTE)pProvidorInfo->pDLLName,
  654. (wcslen(pProvidorInfo->pDLLName)+1) * sizeof(WCHAR))))
  655. {
  656. SetLastError(dwError);
  657. goto CleanUp;
  658. }
  659. // Close the handle
  660. RegCloseKey(hNewProvidor);
  661. hNewProvidor = NULL;
  662. // Append to the order value
  663. dwRequired = 0;
  664. dwError = RegQueryValueEx(hProvidors, szOrder, NULL, NULL, NULL, &dwRequired);
  665. switch (dwError) {
  666. case ERROR_SUCCESS:
  667. if ((dwOldSize = dwRequired) &&
  668. (pOldOrder = AllocSplMem(dwRequired)) &&
  669. !(dwError = RegQueryValueEx(hProvidors, szOrder, NULL, NULL,
  670. (LPBYTE) pOldOrder, &dwRequired)))
  671. {
  672. break;
  673. }
  674. else
  675. {
  676. if (dwError) {
  677. SetLastError(dwError);
  678. }
  679. goto CleanUp;
  680. }
  681. case ERROR_FILE_NOT_FOUND:
  682. break;
  683. default:
  684. SetLastError(dwError);
  685. goto CleanUp;
  686. }
  687. // Append the new providor to the current order
  688. pNewOrder = (LPWSTR)AppendOrderEntry(pOldOrder, dwRequired,
  689. pProvidorInfo->pName, &dwReturned);
  690. if (!pNewOrder ||
  691. (dwError = RegSetValueEx(hProvidors, szOrder, 0,
  692. REG_MULTI_SZ, (LPBYTE)pNewOrder, dwReturned)))
  693. {
  694. if (dwError) {
  695. SetLastError(dwError);
  696. }
  697. goto CleanUp;
  698. }
  699. bOrderUpdated = TRUE;
  700. // Initialize the providor and update the spooler structure
  701. wsprintf(szProvidorName, L"%ws\\%ws", szRegistryProvidors, pProvidorInfo->pName);
  702. pNewProvidor = InitializeProvidor(pProvidorInfo->pDLLName, szProvidorName);
  703. if (pNewProvidor)
  704. {
  705. pNewProvidor->pNext = NULL;
  706. pLastProvidor->pNext = pNewProvidor;
  707. bReturn = TRUE;
  708. }
  709. CleanUp:
  710. // Roll back if anything fails
  711. if (!bReturn)
  712. {
  713. // Remove the new providor key if it was created
  714. if (dwDisposition == REG_CREATED_NEW_KEY)
  715. {
  716. DeleteSubKeyTree(hProvidors, pProvidorInfo->pName);
  717. RegDeleteKey(hProvidors, pProvidorInfo->pName);
  718. }
  719. // Restore the old order if it has been changed
  720. if (bOrderUpdated) {
  721. if (pOldOrder)
  722. {
  723. RegSetValueEx(hProvidors, szOrder, 0,
  724. REG_MULTI_SZ, (LPBYTE)pOldOrder, dwOldSize);
  725. }
  726. else
  727. {
  728. RegDeleteValue(hProvidors, szOrder);
  729. }
  730. }
  731. }
  732. // Free allocated memory
  733. if (pOldOrder) {
  734. FreeSplMem(pOldOrder);
  735. }
  736. if (pNewOrder) {
  737. FreeSplMem(pNewOrder);
  738. }
  739. if (hNewProvidor) {
  740. RegCloseKey(hNewProvidor);
  741. }
  742. return bReturn;
  743. }
  744. BOOL AddPrintProvidorW(
  745. LPWSTR pName,
  746. DWORD dwLevel,
  747. LPBYTE pProvidorInfo
  748. )
  749. /*++
  750. Function Description: This function adds and initializes a print providor. It also updates the
  751. registry and the order of print providors.
  752. Parameters: pName - server name for routing (currently ignored)
  753. dwLevel - providor info level
  754. pProvidorInfo - providor info buffer
  755. Return Values: TRUE if successful; FALSE otherwise
  756. --*/
  757. {
  758. BOOL bReturn = FALSE;
  759. DWORD dwError = ERROR_SUCCESS;
  760. HANDLE hToken;
  761. HKEY hProvidors = NULL;
  762. WaitForSpoolerInitialization();
  763. EnterRouterSem();
  764. // Revert to spooler security context before accessing the registry
  765. //
  766. // This is a really bad idea, as it enables any user to get system
  767. // priveleges without even trying.
  768. //
  769. // hToken = RevertToPrinterSelf();
  770. // Check for invalid parameters
  771. if (!pProvidorInfo)
  772. {
  773. SetLastError(ERROR_INVALID_PARAMETER);
  774. goto CleanUp;
  775. }
  776. if (dwError = RegCreateKeyEx(HKEY_LOCAL_MACHINE, szRegistryProvidors, 0,
  777. NULL, 0, KEY_ALL_ACCESS, NULL, &hProvidors, NULL))
  778. {
  779. SetLastError(dwError);
  780. goto CleanUp;
  781. }
  782. switch (dwLevel) {
  783. case 1:
  784. bReturn = AddNewProvidor(hProvidors,
  785. (PPROVIDOR_INFO_1W) pProvidorInfo);
  786. break;
  787. case 2:
  788. bReturn = UpdateProvidorOrder(hProvidors,
  789. ((PPROVIDOR_INFO_2W) pProvidorInfo)->pOrder);
  790. break;
  791. default:
  792. SetLastError(ERROR_INVALID_LEVEL);
  793. break;
  794. }
  795. CleanUp:
  796. if (hProvidors) {
  797. RegCloseKey(hProvidors);
  798. }
  799. if (!bReturn && !GetLastError()) {
  800. // Last error should be set by individual functions. In the event that something
  801. // is not already set, return a placeholder error code
  802. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  803. }
  804. LeaveRouterSem();
  805. // ImpersonatePrinterClient(hToken);
  806. return bReturn;
  807. }
  808. BOOL DeletePrintProvidorW(
  809. LPWSTR pName,
  810. LPWSTR pEnvironment,
  811. LPWSTR pProvidorName
  812. )
  813. /*++
  814. Function Description: Deletes a print providor by updating the registry and the
  815. removing it from the list of routing providors.
  816. Parameters: pName - server name for routing (currently ignored)
  817. pEnvironment - environment name (currently ignored)
  818. pProvidorName - providor name
  819. Return Values: TRUE if successful; FALSE otherwise
  820. --*/
  821. {
  822. BOOL bReturn = FALSE;
  823. DWORD dwError = ERROR_SUCCESS, dwRequired, dwReturned;
  824. LPWSTR pOldOrder = NULL, pNewOrder = NULL;
  825. HANDLE hToken;
  826. HKEY hProvidors = NULL;
  827. BOOL bSaveAPDPolicy = FALSE;
  828. DWORD APDValue;
  829. LPPROVIDOR pProvidor, pTemp;
  830. WaitForSpoolerInitialization();
  831. EnterRouterSem();
  832. // Revert to spooler security context before accessing the registry
  833. //
  834. // Or rather, Don't.
  835. //
  836. //hToken = RevertToPrinterSelf();
  837. // Check for invalid parameters
  838. if (!pProvidorName || !*pProvidorName)
  839. {
  840. SetLastError(ERROR_INVALID_PARAMETER);
  841. goto CleanUp;
  842. }
  843. if (dwError = RegCreateKeyEx(HKEY_LOCAL_MACHINE, szRegistryProvidors, 0,
  844. NULL, 0, KEY_ALL_ACCESS, NULL, &hProvidors, NULL))
  845. {
  846. SetLastError(dwError);
  847. goto CleanUp;
  848. }
  849. // Save the pProvidor before deleting the registry entry
  850. if (!(pProvidor = FindProvidor(hProvidors, pProvidorName)))
  851. {
  852. goto CleanUp;
  853. }
  854. // Update the order
  855. dwRequired = 0;
  856. if (dwError = RegQueryValueEx(hProvidors, szOrder, NULL, NULL, NULL, &dwRequired))
  857. {
  858. SetLastError(dwError);
  859. goto CleanUp;
  860. }
  861. if (!dwRequired ||
  862. !(pOldOrder = AllocSplMem(dwRequired)) ||
  863. (dwError = RegQueryValueEx(hProvidors, szOrder, NULL, NULL,
  864. (LPBYTE) pOldOrder, &dwRequired)))
  865. {
  866. if (dwError) {
  867. SetLastError(dwError);
  868. }
  869. goto CleanUp;
  870. }
  871. // Remove the providor from the current order
  872. pNewOrder = (LPWSTR)RemoveOrderEntry(pOldOrder, dwRequired,
  873. pProvidorName, &dwReturned);
  874. if (!pNewOrder ||
  875. (dwError = RegSetValueEx(hProvidors, szOrder, 0,
  876. REG_MULTI_SZ, (LPBYTE)pNewOrder, dwReturned)))
  877. {
  878. if (dwError) {
  879. SetLastError(dwError);
  880. }
  881. goto CleanUp;
  882. }
  883. //
  884. // The AddPrinterDrivers policy has the registry value in the wrong place
  885. // under the lanman print services key. The lanman provider is deleted
  886. // during upgrade from Windows 2000 to XP. We save the AddPrinterDrivers
  887. // value and restore it after we delete the registry tree for the provider.
  888. //
  889. if (!_wcsicmp(szLanManProvider, pProvidorName))
  890. {
  891. bSaveAPDPolicy = GetAPDPolicy(hProvidors,
  892. szAPDRelPath,
  893. szAPDValueName,
  894. &APDValue) == ERROR_SUCCESS;
  895. }
  896. //
  897. // Delete the registry key
  898. //
  899. DeleteSubKeyTree(hProvidors, pProvidorName);
  900. //
  901. // Restore the AddPrinterDrivers policy if needed.
  902. //
  903. if (bSaveAPDPolicy)
  904. {
  905. SetAPDPolicy(hProvidors,
  906. szAPDRelPath,
  907. szAPDValueName,
  908. APDValue);
  909. }
  910. // Remove from the linked list of providors for routing
  911. for (pTemp = pLocalProvidor;
  912. pTemp->pNext; // Local Providor is always present and cant be deleted
  913. pTemp = pTemp->pNext)
  914. {
  915. if (pTemp->pNext == pProvidor) {
  916. // dont release the library and the struct since they may be used in
  917. // other threads
  918. pTemp->pNext = pProvidor->pNext;
  919. break;
  920. }
  921. }
  922. bReturn = TRUE;
  923. CleanUp:
  924. if (!bReturn && !GetLastError()) {
  925. // Last error should be set by individual functions. In the event that something
  926. // is not already set, return a placeholder error code
  927. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  928. }
  929. // Free allocated memory
  930. if (pOldOrder) {
  931. FreeSplMem(pOldOrder);
  932. }
  933. if (pNewOrder) {
  934. FreeSplMem(pNewOrder);
  935. }
  936. if (hProvidors) {
  937. RegCloseKey(hProvidors);
  938. }
  939. LeaveRouterSem();
  940. // ImpersonatePrinterClient(hToken);
  941. return bReturn;
  942. }
  943. BOOL
  944. OldGetPrinterDriverW(
  945. HANDLE hPrinter,
  946. LPWSTR pEnvironment,
  947. DWORD Level,
  948. LPBYTE pDriverInfo,
  949. DWORD cbBuf,
  950. LPDWORD pcbNeeded
  951. )
  952. {
  953. LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
  954. if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
  955. SetLastError(ERROR_INVALID_HANDLE);
  956. return FALSE;
  957. }
  958. if ((pDriverInfo == NULL) && (cbBuf != 0)) {
  959. SetLastError(ERROR_INVALID_USER_BUFFER);
  960. return FALSE;
  961. }
  962. if (!pEnvironment || !*pEnvironment)
  963. pEnvironment = szEnvironment;
  964. return (*pPrintHandle->pProvidor->PrintProvidor.fpGetPrinterDriver)
  965. (pPrintHandle->hPrinter, pEnvironment,
  966. Level, pDriverInfo, cbBuf, pcbNeeded);
  967. }
  968. BOOL
  969. GetPrinterDriverExW(
  970. HANDLE hPrinter,
  971. LPWSTR pEnvironment,
  972. DWORD Level,
  973. LPBYTE pDriverInfo,
  974. DWORD cbBuf,
  975. LPDWORD pcbNeeded,
  976. DWORD dwClientMajorVersion,
  977. DWORD dwClientMinorVersion,
  978. PDWORD pdwServerMajorVersion,
  979. PDWORD pdwServerMinorVersion
  980. )
  981. {
  982. LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
  983. if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
  984. SetLastError(ERROR_INVALID_HANDLE);
  985. return FALSE;
  986. }
  987. if ((pDriverInfo == NULL) && (cbBuf != 0)) {
  988. SetLastError(ERROR_INVALID_USER_BUFFER);
  989. return FALSE;
  990. }
  991. if (!pEnvironment || !*pEnvironment)
  992. pEnvironment = szEnvironment;
  993. if (pPrintHandle->pProvidor->PrintProvidor.fpGetPrinterDriverEx) {
  994. DBGMSG(DBG_TRACE, ("Calling the fpGetPrinterDriverEx function\n"));
  995. return (*pPrintHandle->pProvidor->PrintProvidor.fpGetPrinterDriverEx)
  996. (pPrintHandle->hPrinter, pEnvironment,
  997. Level, pDriverInfo, cbBuf, pcbNeeded,
  998. dwClientMajorVersion, dwClientMinorVersion,
  999. pdwServerMajorVersion, pdwServerMinorVersion);
  1000. } else {
  1001. //
  1002. // The print providor does not support versioning of drivers
  1003. //
  1004. DBGMSG(DBG_TRACE, ("Calling the fpGetPrinterDriver function\n"));
  1005. *pdwServerMajorVersion = 0;
  1006. *pdwServerMinorVersion = 0;
  1007. return (*pPrintHandle->pProvidor->PrintProvidor.fpGetPrinterDriver)
  1008. (pPrintHandle->hPrinter, pEnvironment,
  1009. Level, pDriverInfo, cbBuf, pcbNeeded);
  1010. }
  1011. }
  1012. BOOL
  1013. GetPrinterDriverW(
  1014. HANDLE hPrinter,
  1015. LPWSTR pEnvironment,
  1016. DWORD Level,
  1017. LPBYTE pDriverInfo,
  1018. DWORD cbBuf,
  1019. LPDWORD pcbNeeded
  1020. )
  1021. {
  1022. DWORD dwServerMajorVersion;
  1023. DWORD dwServerMinorVersion;
  1024. return GetPrinterDriverExW( hPrinter,
  1025. pEnvironment,
  1026. Level,
  1027. pDriverInfo,
  1028. cbBuf,
  1029. pcbNeeded,
  1030. (DWORD)-1,
  1031. (DWORD)-1,
  1032. &dwServerMajorVersion,
  1033. &dwServerMinorVersion );
  1034. }
  1035. BOOL
  1036. XcvDataW(
  1037. HANDLE hXcv,
  1038. PCWSTR pszDataName,
  1039. PBYTE pInputData,
  1040. DWORD cbInputData,
  1041. PBYTE pOutputData,
  1042. DWORD cbOutputData,
  1043. PDWORD pcbOutputNeeded,
  1044. PDWORD pdwStatus
  1045. )
  1046. {
  1047. LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hXcv;
  1048. if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
  1049. SetLastError(ERROR_INVALID_HANDLE);
  1050. return FALSE;
  1051. }
  1052. return (*pPrintHandle->pProvidor->PrintProvidor.fpXcvData)( pPrintHandle->hPrinter,
  1053. pszDataName,
  1054. pInputData,
  1055. cbInputData,
  1056. pOutputData,
  1057. cbOutputData,
  1058. pcbOutputNeeded,
  1059. pdwStatus);
  1060. }
  1061. /*++
  1062. Routine Name:
  1063. GetJobAttributes
  1064. Routine Description:
  1065. GetJobAttributes gets information about the job.
  1066. This includes nup and reverse printing options.
  1067. Arguments:
  1068. pPrinterName -- name of the printer.
  1069. pDevmode -- Devmode to be passed to the driver
  1070. pAttributeInfo -- buffer to place information about the job
  1071. Return Value:
  1072. TRUE if successful, FALSE otherwise.
  1073. --*/
  1074. BOOL
  1075. GetJobAttributes(
  1076. LPWSTR pPrinterName,
  1077. LPDEVMODEW pDevmode,
  1078. PATTRIBUTE_INFO_3 pAttributeInfo
  1079. )
  1080. {
  1081. HANDLE hDrvPrinter = NULL;
  1082. BOOL bReturn = FALSE, bDefault = FALSE;
  1083. FARPROC pfnDrvQueryJobAttributes;
  1084. HINSTANCE hDrvLib = NULL;
  1085. fnWinSpoolDrv fnList;
  1086. // Get the pointer to the client side functions from the router
  1087. if (!SplInitializeWinSpoolDrv(&fnList)) {
  1088. return FALSE;
  1089. }
  1090. // Get a client side printer handle to pass to the driver
  1091. if (!(* (fnList.pfnOpenPrinter))(pPrinterName, &hDrvPrinter, NULL)) {
  1092. //ODS(("Open printer failed\nPrinter %ws\n",pPrinterName));
  1093. goto CleanUp;
  1094. }
  1095. // Load the driver config file
  1096. if (!(hDrvLib = (* (fnList.pfnLoadPrinterDriver))(hDrvPrinter))) {
  1097. //ODS(("DriverDLL could not be loaded\n"));
  1098. goto CleanUp;
  1099. }
  1100. // Call the DrvQueryJobAtributes function in the driver
  1101. if (pfnDrvQueryJobAttributes = GetProcAddress(hDrvLib, "DrvQueryJobAttributes")) {
  1102. if (!(* pfnDrvQueryJobAttributes) (hDrvPrinter,
  1103. pDevmode,
  1104. 3,
  1105. (LPBYTE) pAttributeInfo)) {
  1106. if (!(* pfnDrvQueryJobAttributes) (hDrvPrinter,
  1107. pDevmode,
  1108. 2,
  1109. (LPBYTE) pAttributeInfo)) {
  1110. if (!(* pfnDrvQueryJobAttributes) (hDrvPrinter,
  1111. pDevmode,
  1112. 1,
  1113. (LPBYTE) pAttributeInfo)) {
  1114. bDefault = TRUE;
  1115. } else {
  1116. pAttributeInfo->dwColorOptimization = 0;
  1117. }
  1118. } else {
  1119. pAttributeInfo->dmPrintQuality = pDevmode->dmPrintQuality;
  1120. pAttributeInfo->dmYResolution = pDevmode->dmYResolution;
  1121. }
  1122. }
  1123. } else {
  1124. bDefault = TRUE;
  1125. }
  1126. if (bDefault) {
  1127. // Set default values for old drivers that don't export the function
  1128. pAttributeInfo->dwJobNumberOfPagesPerSide = 1;
  1129. pAttributeInfo->dwDrvNumberOfPagesPerSide = 1;
  1130. pAttributeInfo->dwNupBorderFlags = 0;
  1131. pAttributeInfo->dwJobPageOrderFlags = 0;
  1132. pAttributeInfo->dwDrvPageOrderFlags = 0;
  1133. pAttributeInfo->dwJobNumberOfCopies = pDevmode->dmCopies;
  1134. pAttributeInfo->dwDrvNumberOfCopies = pDevmode->dmCopies;
  1135. pAttributeInfo->dwColorOptimization = 0;
  1136. }
  1137. bReturn = TRUE;
  1138. CleanUp:
  1139. if (hDrvPrinter) {
  1140. (* (fnList.pfnClosePrinter))(hDrvPrinter);
  1141. }
  1142. if (hDrvLib) {
  1143. (* (fnList.pfnRefCntUnloadDriver))(hDrvLib, TRUE);
  1144. }
  1145. return bReturn;
  1146. }