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.

1409 lines
36 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. oemui.c
  5. Abstract:
  6. Support for OEM plugin UI modules
  7. Environment:
  8. Windows NT printer driver
  9. Revision History:
  10. 02/13/97 -davidx-
  11. Created it.
  12. --*/
  13. #include "precomp.h"
  14. //
  15. // User mode helper functions for OEM plugins
  16. //
  17. const OEMUIPROCS OemUIHelperFuncs = {
  18. (PFN_DrvGetDriverSetting) BGetDriverSettingForOEM,
  19. (PFN_DrvUpdateUISetting) BUpdateUISettingForOEM,
  20. };
  21. BOOL
  22. BPackOemPluginItems(
  23. PUIDATA pUiData
  24. )
  25. /*++
  26. Routine Description:
  27. Call OEM plugin UI modules to let them add their OPTITEMs
  28. Arguments:
  29. pUiData - Points to UIDATA structure
  30. Return Value:
  31. TRUE if successful, FALSE if there is an error
  32. --*/
  33. {
  34. PCOMMONINFO pci;
  35. PFN_OEMCommonUIProp pfnOEMCommonUIProp;
  36. POEMCUIPPARAM pOemCUIPParam;
  37. POPTITEM pOptItem;
  38. DWORD dwOptItem;
  39. //
  40. // Check if we're being called for the first time.
  41. // We assume all OEM plugin items are always packed at the end.
  42. //
  43. if (pUiData->pOptItem == NULL)
  44. pUiData->dwDrvOptItem = pUiData->dwOptItem;
  45. else if (pUiData->dwDrvOptItem != pUiData->dwOptItem)
  46. {
  47. RIP(("Inconsistent OPTITEM count for driver items\n"));
  48. return FALSE;
  49. }
  50. //
  51. // Quick exit for no OEM plugin case
  52. //
  53. pci = (PCOMMONINFO) pUiData;
  54. if (pci->pOemPlugins->dwCount == 0)
  55. return TRUE;
  56. pOptItem = pUiData->pOptItem;
  57. FOREACH_OEMPLUGIN_LOOP(pci)
  58. if (!HAS_COM_INTERFACE(pOemEntry) &&
  59. !(pfnOEMCommonUIProp = GET_OEM_ENTRYPOINT(pOemEntry, OEMCommonUIProp)))
  60. continue;
  61. //
  62. // Compose the input parameter for calling OEMCommonUI
  63. //
  64. pOemCUIPParam = pOemEntry->pParam;
  65. if (pOemCUIPParam == NULL)
  66. {
  67. //
  68. // Allocate memory for an OEMUI_PARAM structure
  69. // during the first pass
  70. //
  71. if (pOptItem != NULL)
  72. continue;
  73. if (! (pOemCUIPParam = HEAPALLOC(pci->hHeap, sizeof(OEMCUIPPARAM))))
  74. {
  75. ERR(("Memory allocation failed\n"));
  76. return FALSE;
  77. }
  78. pOemEntry->pParam = pOemCUIPParam;
  79. pOemCUIPParam->cbSize = sizeof(OEMCUIPPARAM);
  80. pOemCUIPParam->poemuiobj = pci->pOemPlugins->pdriverobj;
  81. pOemCUIPParam->hPrinter = pci->hPrinter;
  82. pOemCUIPParam->pPrinterName = pci->pPrinterName;
  83. pOemCUIPParam->hModule = pOemEntry->hInstance;
  84. pOemCUIPParam->hOEMHeap = pci->hHeap;
  85. pOemCUIPParam->pPublicDM = pci->pdm;
  86. pOemCUIPParam->pOEMDM = pOemEntry->pOEMDM;
  87. }
  88. pOemCUIPParam->pDrvOptItems = pUiData->pDrvOptItem;
  89. pOemCUIPParam->cDrvOptItems = pUiData->dwDrvOptItem;
  90. pOemCUIPParam->pOEMOptItems = pOptItem;
  91. dwOptItem = pOemCUIPParam->cOEMOptItems;
  92. //
  93. // Actually call OEMCommonUI entrypoint
  94. //
  95. if (HAS_COM_INTERFACE(pOemEntry))
  96. {
  97. HRESULT hr;
  98. hr = HComOEMCommonUIProp(
  99. pOemEntry,
  100. (pUiData->iMode == MODE_DOCUMENT_STICKY) ? OEMCUIP_DOCPROP : OEMCUIP_PRNPROP,
  101. pOemCUIPParam);
  102. if (hr == E_NOTIMPL)
  103. {
  104. HeapFree(pci->hHeap, 0, pOemCUIPParam);
  105. pOemEntry->pParam = NULL;
  106. continue;
  107. }
  108. if (FAILED(hr))
  109. {
  110. ERR(("OEMCommonUI failed for '%ws': %d\n",
  111. CURRENT_OEM_MODULE_NAME(pOemEntry),
  112. GetLastError()));
  113. //
  114. // OEM failure during the first pass is recoverable:
  115. // we'll simply ignore OEM plugin items
  116. //
  117. if (pOptItem == NULL)
  118. {
  119. HeapFree(pci->hHeap, 0, pOemCUIPParam);
  120. pOemEntry->pParam = NULL;
  121. continue;
  122. }
  123. return FALSE;
  124. }
  125. }
  126. else
  127. {
  128. if (!pfnOEMCommonUIProp(
  129. (pUiData->iMode == MODE_DOCUMENT_STICKY) ? OEMCUIP_DOCPROP : OEMCUIP_PRNPROP,
  130. pOemCUIPParam))
  131. {
  132. ERR(("OEMCommonUI failed for '%ws': %d\n",
  133. CURRENT_OEM_MODULE_NAME(pOemEntry),
  134. GetLastError()));
  135. #if 0
  136. (VOID) IDisplayErrorMessageBox(
  137. NULL,
  138. 0,
  139. IDS_OEMERR_DLGTITLE,
  140. IDS_OEMERR_OPTITEM,
  141. CURRENT_OEM_MODULE_NAME(pOemEntry));
  142. #endif
  143. //
  144. // OEM failure during the first pass is recoverable:
  145. // we'll simply ignore OEM plugin items
  146. //
  147. if (pOptItem == NULL)
  148. {
  149. HeapFree(pci->hHeap, 0, pOemCUIPParam);
  150. pOemEntry->pParam = NULL;
  151. continue;
  152. }
  153. return FALSE;
  154. }
  155. }
  156. if (pOptItem != NULL)
  157. {
  158. //
  159. // second pass - ensure the number of items is consistent
  160. //
  161. if (dwOptItem != pOemCUIPParam->cOEMOptItems)
  162. {
  163. RIP(("Inconsistent OPTITEM count reported by OEM plugin: %ws\n",
  164. CURRENT_OEM_MODULE_NAME(pOemEntry),
  165. GetLastError()));
  166. return FALSE;
  167. }
  168. pOptItem += pOemCUIPParam->cOEMOptItems;
  169. pUiData->pOptItem += pOemCUIPParam->cOEMOptItems;
  170. }
  171. pUiData->dwOptItem += pOemCUIPParam->cOEMOptItems;
  172. END_OEMPLUGIN_LOOP
  173. return TRUE;
  174. }
  175. LONG
  176. LInvokeOemPluginCallbacks(
  177. PUIDATA pUiData,
  178. PCPSUICBPARAM pCallbackParam,
  179. LONG lRet
  180. )
  181. /*++
  182. Routine Description:
  183. Call OEM plugin module's callback function
  184. Arguments:
  185. pUiData - Points to UIDATA structure
  186. pCallbackParam - Points to callback parameter from compstui
  187. lRet - Return value after the driver has processed the callback
  188. Return Value:
  189. Return value for compstui
  190. --*/
  191. {
  192. PCOMMONINFO pci = (PCOMMONINFO) pUiData;
  193. POEMCUIPPARAM pOemCUIPParam;
  194. LONG lNewResult;
  195. //
  196. // Quick exit for no OEM plugin case
  197. //
  198. if (pci->pOemPlugins->dwCount == 0)
  199. return lRet;
  200. //
  201. // Go through each OEM plugin UI module
  202. //
  203. FOREACH_OEMPLUGIN_LOOP(pci)
  204. //
  205. // Stop when anyone says don't exit
  206. //
  207. if (lRet == CPSUICB_ACTION_NO_APPLY_EXIT)
  208. {
  209. ASSERT(pCallbackParam->Reason == CPSUICB_REASON_APPLYNOW);
  210. break;
  211. }
  212. //
  213. // Get the address of OEM callback function and call it
  214. //
  215. pOemCUIPParam = pOemEntry->pParam;
  216. if (pOemCUIPParam == NULL || pOemCUIPParam->OEMCUIPCallback == NULL)
  217. continue;
  218. lNewResult = pOemCUIPParam->OEMCUIPCallback(pCallbackParam, pOemCUIPParam);
  219. //
  220. // Merge the new result with the existing result
  221. //
  222. switch (lNewResult)
  223. {
  224. case CPSUICB_ACTION_ITEMS_APPLIED:
  225. case CPSUICB_ACTION_NO_APPLY_EXIT:
  226. ASSERT(pCallbackParam->Reason == CPSUICB_REASON_APPLYNOW);
  227. lRet = lNewResult;
  228. break;
  229. case CPSUICB_ACTION_REINIT_ITEMS:
  230. ASSERT(pCallbackParam->Reason != CPSUICB_REASON_APPLYNOW);
  231. lRet = lNewResult;
  232. break;
  233. case CPSUICB_ACTION_OPTIF_CHANGED:
  234. ASSERT(pCallbackParam->Reason != CPSUICB_REASON_APPLYNOW);
  235. if (lRet == CPSUICB_ACTION_NONE)
  236. lRet = lNewResult;
  237. break;
  238. case CPSUICB_ACTION_NONE:
  239. break;
  240. default:
  241. RIP(("Invalid return value from OEM callback: '%ws'\n",
  242. CURRENT_OEM_MODULE_NAME(pOemEntry),
  243. GetLastError()));
  244. break;
  245. }
  246. END_OEMPLUGIN_LOOP
  247. return lRet;
  248. }
  249. LRESULT
  250. OEMDocumentPropertySheets(
  251. PPROPSHEETUI_INFO pPSUIInfo,
  252. LPARAM lParam
  253. )
  254. {
  255. HRESULT hr;
  256. POEM_PLUGIN_ENTRY pOemEntry;
  257. pOemEntry = ((POEMUIPSPARAM)(pPSUIInfo->lParamInit))->pOemEntry;
  258. hr = HComOEMDocumentPropertySheets(pOemEntry,
  259. pPSUIInfo,
  260. lParam);
  261. if (SUCCEEDED(hr))
  262. return 1;
  263. return -1;
  264. }
  265. LRESULT
  266. OEMDevicePropertySheets(
  267. PPROPSHEETUI_INFO pPSUIInfo,
  268. LPARAM lParam
  269. )
  270. {
  271. HRESULT hr;
  272. POEM_PLUGIN_ENTRY pOemEntry;
  273. pOemEntry = ((POEMUIPSPARAM)(pPSUIInfo->lParamInit))->pOemEntry;
  274. hr = HComOEMDevicePropertySheets(pOemEntry,
  275. pPSUIInfo,
  276. lParam);
  277. if (SUCCEEDED(hr))
  278. return 1;
  279. return -1;
  280. }
  281. BOOL
  282. BAddOemPluginPages(
  283. PUIDATA pUiData,
  284. DWORD dwFlags
  285. )
  286. /*++
  287. Routine Description:
  288. Call OEM plugin UI modules to let them add their own property sheet pages
  289. Arguments:
  290. pUiData - Points to UIDATA structure
  291. dwFlags - Flags from DOCUMENTPROPERTYHEADER or DEVICEPROPERTYHEADER
  292. Return Value:
  293. TRUE if successful, FALSE if there is an error
  294. --*/
  295. {
  296. PCOMMONINFO pci = (PCOMMONINFO) pUiData;
  297. FARPROC pfnOEMPropertySheets;
  298. POEMUIPSPARAM pOemUIPSParam;
  299. //
  300. // Quick exit for no OEM plugin case
  301. //
  302. if (pci->pOemPlugins->dwCount == 0)
  303. return TRUE;
  304. //
  305. // Add the property sheet for each OEM plugin UI module
  306. //
  307. FOREACH_OEMPLUGIN_LOOP(pci)
  308. //
  309. // get the address of appropriate OEM entrypoint
  310. //
  311. if (HAS_COM_INTERFACE(pOemEntry))
  312. {
  313. if (pUiData->iMode == MODE_DOCUMENT_STICKY)
  314. pfnOEMPropertySheets = (FARPROC)OEMDocumentPropertySheets;
  315. else
  316. pfnOEMPropertySheets = (FARPROC)OEMDevicePropertySheets;
  317. }
  318. else
  319. {
  320. if (pUiData->iMode == MODE_DOCUMENT_STICKY)
  321. {
  322. pfnOEMPropertySheets = (FARPROC)
  323. GET_OEM_ENTRYPOINT(pOemEntry, OEMDocumentPropertySheets);
  324. }
  325. else
  326. {
  327. pfnOEMPropertySheets = (FARPROC)
  328. GET_OEM_ENTRYPOINT(pOemEntry, OEMDevicePropertySheets);
  329. }
  330. if (pfnOEMPropertySheets == NULL)
  331. continue;
  332. }
  333. //
  334. // Collect input parameters to be passed to OEM plugin
  335. //
  336. if ((pOemUIPSParam = HEAPALLOC(pci->hHeap, sizeof(OEMUIPSPARAM))) == NULL)
  337. {
  338. ERR(("Memory allocation failed\n"));
  339. return FALSE;
  340. }
  341. pOemUIPSParam->cbSize = sizeof(OEMUIPSPARAM);
  342. pOemUIPSParam->poemuiobj = pci->pOemPlugins->pdriverobj;
  343. pOemUIPSParam->hPrinter = pci->hPrinter;
  344. pOemUIPSParam->pPrinterName = pci->pPrinterName;
  345. pOemUIPSParam->hModule = pOemEntry->hInstance;
  346. pOemUIPSParam->hOEMHeap = pci->hHeap;
  347. pOemUIPSParam->pPublicDM = pci->pdm;
  348. pOemUIPSParam->pOEMDM = pOemEntry->pOEMDM;
  349. pOemUIPSParam->dwFlags = dwFlags;
  350. pOemUIPSParam->pOemEntry = pOemEntry;
  351. //
  352. // call compstui to add the OEM plugin property sheets
  353. //
  354. if (pUiData->pfnComPropSheet(pUiData->hComPropSheet,
  355. CPSFUNC_ADD_PFNPROPSHEETUI,
  356. (LPARAM) pfnOEMPropertySheets,
  357. (LPARAM) pOemUIPSParam) <= 0)
  358. {
  359. VERBOSE(("Couldn't add property sheet pages for '%ws'\n",
  360. CURRENT_OEM_MODULE_NAME(pOemEntry),
  361. GetLastError()));
  362. }
  363. END_OEMPLUGIN_LOOP
  364. return TRUE;
  365. }
  366. BOOL
  367. APIENTRY
  368. BGetDriverSettingForOEM(
  369. PCOMMONINFO pci,
  370. PCSTR pFeatureKeyword,
  371. PVOID pOutput,
  372. DWORD cbSize,
  373. PDWORD pcbNeeded,
  374. PDWORD pdwOptionsReturned
  375. )
  376. /*++
  377. Routine Description:
  378. Provide OEM plugins access to driver private settings
  379. Arguments:
  380. pci - Points to basic printer information
  381. pFeatureKeyword - Specifies the keyword the caller is interested in
  382. pOutput - Points to output buffer
  383. cbSize - Size of output buffer
  384. pcbNeeded - Returns the expected size of output buffer
  385. pdwOptionsReturned - Returns the number of options selected
  386. Return Value:
  387. TRUE if successful, FALSE if there is an error
  388. --*/
  389. {
  390. ULONG_PTR dwIndex;
  391. BOOL bResult;
  392. ASSERT(pci->pvStartSign == pci);
  393. if ((pci == NULL) || (pci->pvStartSign != pci))
  394. {
  395. WARNING(("BGetDriverSettingForOEM: invalid pci"));
  396. SetLastError(ERROR_INVALID_PARAMETER);
  397. return FALSE;
  398. }
  399. //
  400. // This is not very portable: If the pointer value for pFeatureKeyword
  401. // is less than 0x10000, we assume that the pointer value actually
  402. // specifies a predefined index.
  403. //
  404. //
  405. // Following ASSERT is removed for Win64
  406. //
  407. // ASSERT(sizeof(pFeatureKeyword) == sizeof(DWORD));
  408. //
  409. dwIndex = (ULONG_PTR)pFeatureKeyword;
  410. if (dwIndex >= OEMGDS_MIN_DOCSTICKY && dwIndex < OEMGDS_MIN_PRINTERSTICKY)
  411. {
  412. if (pci->pdm == NULL)
  413. goto setting_not_available;
  414. bResult = BGetDevmodeSettingForOEM(
  415. pci->pdm,
  416. (DWORD)dwIndex,
  417. pOutput,
  418. cbSize,
  419. pcbNeeded);
  420. if (bResult)
  421. *pdwOptionsReturned = 1;
  422. }
  423. else if (dwIndex >= OEMGDS_MIN_PRINTERSTICKY && dwIndex < OEMGDS_MAX)
  424. {
  425. if (pci->pPrinterData == NULL)
  426. goto setting_not_available;
  427. bResult = BGetPrinterDataSettingForOEM(
  428. pci->pPrinterData,
  429. (DWORD)dwIndex,
  430. pOutput,
  431. cbSize,
  432. pcbNeeded);
  433. if (bResult)
  434. *pdwOptionsReturned = 1;
  435. }
  436. else
  437. {
  438. if (pci->pCombinedOptions == NULL)
  439. goto setting_not_available;
  440. bResult = BGetGenericOptionSettingForOEM(
  441. pci->pUIInfo,
  442. pci->pCombinedOptions,
  443. pFeatureKeyword,
  444. pOutput,
  445. cbSize,
  446. pcbNeeded,
  447. pdwOptionsReturned);
  448. }
  449. return bResult;
  450. setting_not_available:
  451. WARNING(("Requested driver setting not available: %d\n", pFeatureKeyword));
  452. SetLastError(ERROR_NOT_SUPPORTED);
  453. return FALSE;
  454. }
  455. BOOL
  456. BUpdateUISettingForOEM(
  457. PCOMMONINFO pci,
  458. PVOID pOptItem,
  459. DWORD dwPreviousSelection,
  460. DWORD dwMode
  461. )
  462. /*++
  463. Routine Description:
  464. Update the UI settings in optionsarray for OEM.
  465. Arguments:
  466. pci - Points to basic printer information
  467. pOptItem - Points to the current OPTITEM
  468. Return Value:
  469. TRUE if successful, FALSE if there is an error such as conflict and
  470. user wants to cancel.
  471. --*/
  472. {
  473. POPTITEM pCurItem = pOptItem;
  474. PUIDATA pUiData = (PUIDATA)pci;
  475. ASSERT(pci->pvStartSign == pci);
  476. if ((pci == NULL) || (pci->pvStartSign != pci))
  477. {
  478. WARNING(("BUpdateUISettingForOEM: invalid pci"));
  479. return FALSE;
  480. }
  481. if (ICheckConstraintsDlg(pUiData, pCurItem, 1, FALSE) == CONFLICT_CANCEL)
  482. {
  483. //
  484. // If there is a conflict and the user clicked
  485. // CANCEL to restore the original selection.
  486. // CONFLICT_CANCEL, restore the old setting
  487. //
  488. return FALSE;
  489. }
  490. if (dwMode == OEMCUIP_DOCPROP)
  491. {
  492. //
  493. // We use FLAG_WITHIN_PLUGINCALL to indicate we are within the UI helper
  494. // function call issued by OEM plugin. This is needed to fix bug #90923.
  495. //
  496. pUiData->ci.dwFlags |= FLAG_WITHIN_PLUGINCALL;
  497. VUnpackDocumentPropertiesItems(pUiData, pCurItem, 1);
  498. pUiData->ci.dwFlags &= ~FLAG_WITHIN_PLUGINCALL;
  499. VPropShowConstraints(pUiData, MODE_DOCANDPRINTER_STICKY);
  500. }
  501. else
  502. {
  503. VUpdateOptionsArrayWithSelection(pUiData, pCurItem);
  504. VPropShowConstraints(pUiData, MODE_PRINTER_STICKY);
  505. }
  506. //
  507. // Record the fact that one of our OPTITEM selection has been changed by plugin's
  508. // call of helper function DrvUpdateUISetting. This is necessary so that at the
  509. // APPLYNOW time we know constraints could exist even though user hasn't touched
  510. // any of our OPTITEMs.
  511. //
  512. pUiData->ci.dwFlags |= FLAG_PLUGIN_CHANGED_OPTITEM;
  513. return TRUE;
  514. }
  515. BOOL
  516. BUpgradeRegistrySettingForOEM(
  517. HANDLE hPrinter,
  518. PCSTR pFeatureKeyword,
  519. PCSTR pOptionKeyword
  520. )
  521. /*++
  522. Routine Description:
  523. Set the Feature.Option request to our options array. OEM will only
  524. call this function at OEMUpgradeDriver to upgrade their registry setttings
  525. into our optionsarray saved in our PRINTERDATA
  526. Arguments:
  527. hPrinter - Handle of the Printer
  528. pFeatureKeyword - Specifies the keyword the caller is interested in
  529. pOptionKeyword - Specifies the keyword the caller is interested in
  530. Return Value:
  531. TRUE if successful, FALSE if there is an error
  532. --*/
  533. {
  534. PFEATURE pFeature;
  535. POPTION pOption;
  536. DWORD dwFeatureCount, i, j;
  537. BOOL bFeatureFound, bOptionFound, bResult = FALSE;
  538. PCSTR pKeywordName;
  539. POPTSELECT pOptionsArray = NULL;
  540. PDRIVER_INFO_3 pDriverInfo3 = NULL;
  541. PRAWBINARYDATA pRawData = NULL;
  542. PINFOHEADER pInfoHeader = NULL;
  543. PUIINFO pUIInfo = NULL;
  544. PPRINTERDATA pPrinterData = NULL;
  545. OPTSELECT DocOptions[MAX_PRINTER_OPTIONS];
  546. //
  547. // Get information about the printer driver
  548. //
  549. bResult = bFeatureFound = bOptionFound = FALSE;
  550. if ((pDriverInfo3 = MyGetPrinterDriver(hPrinter, NULL, 3)) == NULL)
  551. {
  552. ERR(("Cannot get printer driver info: %d\n", GetLastError()));
  553. goto upgrade_registry_exit;
  554. }
  555. // ENTER_CRITICAL_SECTION();
  556. pRawData = LoadRawBinaryData(pDriverInfo3->pDataFile);
  557. // LEAVE_CRITICAL_SECTION();
  558. if (pRawData == NULL)
  559. goto upgrade_registry_exit;
  560. if (!(pPrinterData = MemAllocZ(sizeof(PRINTERDATA))) ||
  561. !( BGetPrinterProperties(hPrinter, pRawData, pPrinterData)))
  562. {
  563. ERR(("Cannot get printer data info: %d\n", GetLastError()));
  564. goto upgrade_registry_exit;
  565. }
  566. //
  567. // Allocate memory for combined optionsarray
  568. //
  569. if (!(pOptionsArray = MemAllocZ(MAX_COMBINED_OPTIONS * sizeof (OPTSELECT))))
  570. goto upgrade_registry_exit;
  571. if (! InitDefaultOptions(pRawData,
  572. DocOptions,
  573. MAX_PRINTER_OPTIONS,
  574. MODE_DOCUMENT_STICKY))
  575. {
  576. goto upgrade_registry_exit;
  577. }
  578. //
  579. // Combine doc sticky options with printer sticky items
  580. //
  581. CombineOptionArray(pRawData, pOptionsArray, MAX_COMBINED_OPTIONS, DocOptions, pPrinterData->aOptions);
  582. //
  583. // Get an updated instance of printer description data
  584. //
  585. pInfoHeader = InitBinaryData(pRawData,
  586. NULL,
  587. pOptionsArray);
  588. if (pInfoHeader == NULL)
  589. {
  590. ERR(("InitBinaryData failed\n"));
  591. goto upgrade_registry_exit;
  592. }
  593. if (!(pUIInfo = OFFSET_TO_POINTER(pInfoHeader, pInfoHeader->loUIInfoOffset)))
  594. goto upgrade_registry_exit;
  595. //
  596. // Look for feature.option index
  597. //
  598. pFeature = PGetIndexedFeature(pUIInfo, 0);
  599. dwFeatureCount = pRawData->dwDocumentFeatures + pRawData->dwPrinterFeatures;
  600. if (pFeature && dwFeatureCount)
  601. {
  602. for (i = 0; i < dwFeatureCount; i++)
  603. {
  604. pKeywordName = OFFSET_TO_POINTER(pUIInfo->pubResourceData, pFeature->loKeywordName);
  605. if (strcmp(pKeywordName, pFeatureKeyword) == EQUAL_STRING)
  606. {
  607. bFeatureFound = TRUE;
  608. break;
  609. }
  610. pFeature++;
  611. }
  612. }
  613. if (bFeatureFound)
  614. {
  615. pOption = PGetIndexedOption(pUIInfo, pFeature, 0);
  616. for (j = 0; j < pFeature->Options.dwCount; j++)
  617. {
  618. pKeywordName = OFFSET_TO_POINTER(pUIInfo->pubResourceData, pOption->loKeywordName);
  619. if (strcmp(pKeywordName, pOptionKeyword) == EQUAL_STRING)
  620. {
  621. bOptionFound = TRUE;
  622. break;
  623. }
  624. pOption++;
  625. }
  626. }
  627. if (bFeatureFound && bOptionFound)
  628. {
  629. pOptionsArray[i].ubCurOptIndex = (BYTE)j;
  630. //
  631. // Resolve conflicts
  632. //
  633. if (!ResolveUIConflicts( pRawData,
  634. pOptionsArray,
  635. MAX_COMBINED_OPTIONS,
  636. MODE_DOCANDPRINTER_STICKY))
  637. {
  638. VERBOSE(("Resolved conflicting printer feature selections.\n"));
  639. }
  640. SeparateOptionArray(pRawData,
  641. pOptionsArray,
  642. pPrinterData->aOptions,
  643. MAX_PRINTER_OPTIONS,
  644. MODE_PRINTER_STICKY
  645. );
  646. if (!BSavePrinterProperties(hPrinter, pRawData, pPrinterData, sizeof(PRINTERDATA)))
  647. {
  648. ERR(("BSavePrinterProperties failed\n"));
  649. bResult = FALSE;
  650. }
  651. else
  652. bResult = TRUE;
  653. }
  654. upgrade_registry_exit:
  655. if (pInfoHeader)
  656. FreeBinaryData(pInfoHeader);
  657. if (pRawData)
  658. UnloadRawBinaryData(pRawData);
  659. if (pPrinterData)
  660. MemFree(pPrinterData);
  661. if (pDriverInfo3)
  662. MemFree(pDriverInfo3);
  663. if (pOptionsArray)
  664. MemFree(pOptionsArray);
  665. return bResult;
  666. }
  667. #ifdef PSCRIPT
  668. #ifndef WINNT_40
  669. /*++
  670. Routine Name:
  671. HQuerySimulationSupport
  672. Routine Description:
  673. In the case of UI replacement, we allows IHV to query for print processor simulation
  674. support so they can provide simulated features on their UI.
  675. We won't enforce hooking out QueryJobAttribute w/o UI replacement here. We will do it
  676. at DrvQueryJobAttributes.
  677. Arguments:
  678. hPrinter - printer handle
  679. dwLevel - interested level of spooler simulation capability info structure
  680. pCaps - pointer to output buffer
  681. cbSize - size in bytes of output buffer
  682. pcbNeeded - buffer size in bytes needed to store the interested info structure
  683. Return Value:
  684. S_OK if succeeded
  685. E_OUTOFMEMORY if output buffer is not big enough
  686. E_NOTIMPL if the interested level is not supported
  687. E_FAIL if encountered other internal error
  688. Last Error:
  689. None
  690. --*/
  691. HRESULT
  692. HQuerySimulationSupport(
  693. IN HANDLE hPrinter,
  694. IN DWORD dwLevel,
  695. OUT PBYTE pCaps,
  696. IN DWORD cbSize,
  697. OUT PDWORD pcbNeeded
  698. )
  699. {
  700. PRINTPROCESSOR_CAPS_1 SplCaps;
  701. PSIMULATE_CAPS_1 pSimCaps;
  702. DWORD cbNeeded;
  703. //
  704. // currently only Level 1 is supported
  705. //
  706. if (dwLevel != 1)
  707. {
  708. return E_NOTIMPL;
  709. }
  710. cbNeeded = sizeof(SIMULATE_CAPS_1);
  711. if (pcbNeeded)
  712. {
  713. *pcbNeeded = cbNeeded;
  714. }
  715. if (!pCaps || cbSize < cbNeeded)
  716. {
  717. return E_OUTOFMEMORY;
  718. }
  719. //
  720. // Since VGetSpoolerEmfCaps doesn't return error code, we
  721. // are using the dwLevel field to detect if the call succeeds.
  722. // If succeeds, dwLevel should be set as 1.
  723. //
  724. SplCaps.dwLevel = 0;
  725. VGetSpoolerEmfCaps(hPrinter,
  726. NULL,
  727. NULL,
  728. sizeof(PRINTPROCESSOR_CAPS_1),
  729. &SplCaps
  730. );
  731. if (SplCaps.dwLevel != 1)
  732. {
  733. ERR(("VGetSpoolerEmfCaps failed\n"));
  734. return E_FAIL;
  735. }
  736. //
  737. // BUGBUG, we should get a new PRINTPROCESSOR_CAPS level to include all
  738. // these information instead of filling it out here. Need
  739. // new PRINTPROCESSOR_CAPS
  740. //
  741. pSimCaps = (PSIMULATE_CAPS_1)pCaps;
  742. pSimCaps->dwLevel = 1;
  743. pSimCaps->dwPageOrderFlags = SplCaps.dwPageOrderFlags;
  744. pSimCaps->dwNumberOfCopies = SplCaps.dwNumberOfCopies;
  745. pSimCaps->dwNupOptions = SplCaps.dwNupOptions;
  746. //
  747. // PRINTPROCESSOR_CAPS_1 is designed without an explicit field for
  748. // collate simulation. So before its CAPS_2 is introduced, we have
  749. // to assume that if reverse printing is supported, then collate
  750. // simulation is also supported.
  751. //
  752. if (SplCaps.dwPageOrderFlags & REVERSE_PRINT)
  753. {
  754. pSimCaps->dwCollate = 1;
  755. }
  756. else
  757. {
  758. pSimCaps->dwCollate = 0;
  759. }
  760. return S_OK;
  761. }
  762. #endif // !WINNT_40
  763. /*++
  764. Routine Name:
  765. HEnumConstrainedOptions
  766. Routine Description:
  767. enumerate the constrained option keyword name list in the specified feature
  768. Arguments:
  769. poemuiobj - pointer to driver context object
  770. dwFlags - flags for the enumeration operation
  771. pszFeatureKeyword - feature keyword name
  772. pmszConstrainedOptionList - pointer to output data buffer
  773. cbSize - output data buffer size in bytes
  774. pcbNeeded - buffer size in bytes needed to store the output data
  775. Return Value:
  776. S_OK if succeeds
  777. E_OUTOFMEMORY if output data buffer size is not big enough
  778. E_INVALIDARG if feature keyword name is not recognized, or the feature's
  779. stickiness doesn't match current sticky-mode
  780. E_FAIL if other internal failures are encountered
  781. Last Error:
  782. None
  783. --*/
  784. HRESULT
  785. HEnumConstrainedOptions(
  786. IN POEMUIOBJ poemuiobj,
  787. IN DWORD dwFlags,
  788. IN PCSTR pszFeatureKeyword,
  789. OUT PSTR pmszConstrainedOptionList,
  790. IN DWORD cbSize,
  791. OUT PDWORD pcbNeeded
  792. )
  793. {
  794. PCOMMONINFO pci = (PCOMMONINFO)poemuiobj;
  795. PUIDATA pUiData;
  796. PFEATURE pFeature;
  797. POPTION pOption;
  798. DWORD dwFeatureIndex, dwIndex;
  799. PBOOL pabEnabledOptions = NULL;
  800. PSTR pCurrentOut;
  801. DWORD cbNeeded;
  802. INT cbRemain;
  803. HRESULT hr;
  804. pUiData = (PUIDATA)pci;
  805. if (!pszFeatureKeyword ||
  806. (pFeature = PGetNamedFeature(pci->pUIInfo, pszFeatureKeyword, &dwFeatureIndex)) == NULL)
  807. {
  808. WARNING(("HEnumConstrainedOptions: invalid feature\n"));
  809. //
  810. // Even though we could return right here, we still use goto to maintain single exit point.
  811. //
  812. hr = E_INVALIDARG;
  813. goto exit;
  814. }
  815. //
  816. // pUiData->iMode can have 2 modes: MODE_DOCUMENT_STICKY and MODE_PRINTER_STICKY. See PFillUiData().
  817. // In MODE_DOCUMENT_STICKY mode, we only support doc-sticky features.
  818. // In MODE_PRINTER_STICKY mode, we only support printer-sticky features.
  819. //
  820. // This is because in function PFillUiData(), it only fills devmode in MODE_DOCUMENT_STICKY mode.
  821. // Then in BCombineCommonInfoOptionsArray(), if devmode option array is not available, the PPD parser
  822. // will use OPTION_INDEX_ANY for any doc-sticky features.
  823. //
  824. if ((pUiData->iMode == MODE_DOCUMENT_STICKY && pFeature->dwFeatureType == FEATURETYPE_PRINTERPROPERTY) ||
  825. (pUiData->iMode == MODE_PRINTER_STICKY && pFeature->dwFeatureType != FEATURETYPE_PRINTERPROPERTY))
  826. {
  827. VERBOSE(("HEnumConstrainedOptions: mismatch iMode=%d, dwFeatureType=%d\n",
  828. pUiData->iMode, pFeature->dwFeatureType)) ;
  829. hr = E_INVALIDARG;
  830. goto exit;
  831. }
  832. if (pFeature->Options.dwCount)
  833. {
  834. if ((pabEnabledOptions = MemAllocZ(pFeature->Options.dwCount * sizeof(BOOL))) == NULL)
  835. {
  836. ERR(("HEnumConstrainedOptions: memory alloc failed\n"));
  837. hr = E_FAIL;
  838. goto exit;
  839. }
  840. //
  841. // Get the feature's enabled option list.
  842. //
  843. // See VPropShowConstraints() in docprop.c and prnprop.c for using different
  844. // modes to call EnumEnabledOptions().
  845. //
  846. if (pUiData->iMode == MODE_DOCUMENT_STICKY)
  847. {
  848. EnumEnabledOptions(pci->pRawData, pci->pCombinedOptions, dwFeatureIndex,
  849. pabEnabledOptions, MODE_DOCANDPRINTER_STICKY);
  850. }
  851. else
  852. {
  853. EnumEnabledOptions(pci->pRawData, pci->pCombinedOptions, dwFeatureIndex,
  854. pabEnabledOptions, MODE_PRINTER_STICKY);
  855. }
  856. }
  857. else
  858. {
  859. RIP(("HEnumConstrainedOptions: feature %s has no options\n", pszFeatureKeyword));
  860. //
  861. // continue so we will output the empty string with only the NUL character
  862. //
  863. }
  864. pCurrentOut = pmszConstrainedOptionList;
  865. cbNeeded = 0;
  866. cbRemain = (INT)cbSize;
  867. pOption = OFFSET_TO_POINTER(pci->pInfoHeader, pFeature->Options.loOffset);
  868. ASSERT(pOption || pFeature->Options.dwCount == 0);
  869. if (pOption == NULL && pFeature->Options.dwCount != 0)
  870. {
  871. hr = E_FAIL;
  872. goto exit;
  873. }
  874. for (dwIndex = 0; dwIndex < pFeature->Options.dwCount; dwIndex++)
  875. {
  876. if (!pabEnabledOptions[dwIndex])
  877. {
  878. DWORD dwNameSize;
  879. PSTR pszKeywordName;
  880. pszKeywordName = OFFSET_TO_POINTER(pci->pUIInfo->pubResourceData, pOption->loKeywordName);
  881. ASSERT(pszKeywordName);
  882. if (pszKeywordName == NULL)
  883. {
  884. hr = E_FAIL;
  885. goto exit;
  886. }
  887. //
  888. // count in the NUL character between constrained option keywords
  889. //
  890. dwNameSize = strlen(pszKeywordName) + 1;
  891. if (pCurrentOut && cbRemain >= (INT)dwNameSize)
  892. {
  893. CopyMemory(pCurrentOut, pszKeywordName, dwNameSize);
  894. pCurrentOut += dwNameSize;
  895. }
  896. cbRemain -= dwNameSize;
  897. cbNeeded += dwNameSize;
  898. }
  899. pOption = (POPTION)((PBYTE)pOption + pFeature->dwOptionSize);
  900. }
  901. //
  902. // remember the last NUL terminator for the MULTI_SZ output string
  903. //
  904. cbNeeded++;
  905. if (pcbNeeded)
  906. {
  907. *pcbNeeded = cbNeeded;
  908. }
  909. if (!pCurrentOut || cbRemain < 1)
  910. {
  911. hr = E_OUTOFMEMORY;
  912. goto exit;
  913. }
  914. *pCurrentOut = NUL;
  915. //
  916. // Succeeded
  917. //
  918. hr = S_OK;
  919. exit:
  920. MemFree(pabEnabledOptions);
  921. return hr;
  922. }
  923. /*++
  924. Routine Name:
  925. HWhyConstrained
  926. Routine Description:
  927. get feature/option keyword pair that constrains the given
  928. feature/option pair
  929. Arguments:
  930. poemuiobj - pointer to driver context object
  931. dwFlags - flags for this operation
  932. pszFeatureKeyword - feature keyword name
  933. pszOptionKeyword - option keyword name
  934. pmszReasonList - pointer to output data buffer
  935. cbSize - output data buffer size in bytes
  936. pcbNeeded - buffer size in bytes needed to store the output data
  937. Return Value:
  938. S_OK if succeeds
  939. E_OUTOFMEMORY if output data buffer size is not big enough
  940. E_INVALIDARG if the feature keyword name or option keyword name
  941. is not recognized, or the feature's stickiness
  942. doesn't match current sticky-mode
  943. Last Error:
  944. None
  945. --*/
  946. HRESULT
  947. HWhyConstrained(
  948. IN POEMUIOBJ poemuiobj,
  949. IN DWORD dwFlags,
  950. IN PCSTR pszFeatureKeyword,
  951. IN PCSTR pszOptionKeyword,
  952. OUT PSTR pmszReasonList,
  953. IN DWORD cbSize,
  954. OUT PDWORD pcbNeeded
  955. )
  956. {
  957. PCOMMONINFO pci = (PCOMMONINFO)poemuiobj;
  958. PUIDATA pUiData;
  959. PFEATURE pFeature;
  960. POPTION pOption;
  961. DWORD dwFeatureIndex, dwOptionIndex;
  962. CONFLICTPAIR ConflictPair;
  963. BOOL bConflictFound;
  964. PSTR pszConfFeatureName = NULL, pszConfOptionName = NULL;
  965. CHAR emptyString[1] = {0};
  966. DWORD cbConfFeatureKeySize = 0, cbConfOptionKeySize = 0;
  967. DWORD cbNeeded = 0;
  968. pUiData = (PUIDATA)pci;
  969. if (!pszFeatureKeyword ||
  970. (pFeature = PGetNamedFeature(pci->pUIInfo, pszFeatureKeyword, &dwFeatureIndex)) == NULL)
  971. {
  972. WARNING(("HWhyConstrained: invalid feature\n"));
  973. return E_INVALIDARG;
  974. }
  975. if (!pszOptionKeyword ||
  976. (pOption = PGetNamedOption(pci->pUIInfo, pFeature, pszOptionKeyword, &dwOptionIndex)) == NULL)
  977. {
  978. WARNING(("HWhyConstrained: invalid option\n"));
  979. return E_INVALIDARG;
  980. }
  981. //
  982. // See comments in HEnumConstrainedOptions() for following stickiness mode check.
  983. //
  984. if ((pUiData->iMode == MODE_DOCUMENT_STICKY && pFeature->dwFeatureType == FEATURETYPE_PRINTERPROPERTY) ||
  985. (pUiData->iMode == MODE_PRINTER_STICKY && pFeature->dwFeatureType != FEATURETYPE_PRINTERPROPERTY))
  986. {
  987. VERBOSE(("HWhyConstrained: mismatch iMode=%d, dwFeatureType=%d\n",pUiData->iMode, pFeature->dwFeatureType));
  988. return E_INVALIDARG;
  989. }
  990. //
  991. // Get the feature/option pair that constrains the feature/option pair client is querying for.
  992. //
  993. bConflictFound = EnumNewPickOneUIConflict(pci->pRawData,
  994. pci->pCombinedOptions,
  995. dwFeatureIndex,
  996. dwOptionIndex,
  997. &ConflictPair);
  998. if (bConflictFound)
  999. {
  1000. PFEATURE pConfFeature;
  1001. POPTION pConfOption;
  1002. DWORD dwConfFeatureIndex, dwConfOptionIndex;
  1003. //
  1004. // ConflictPair has the feature with higher priority as dwFeatureIndex1.
  1005. //
  1006. if (dwFeatureIndex == ConflictPair.dwFeatureIndex1)
  1007. {
  1008. dwConfFeatureIndex = ConflictPair.dwFeatureIndex2;
  1009. dwConfOptionIndex = ConflictPair.dwOptionIndex2;
  1010. }
  1011. else
  1012. {
  1013. dwConfFeatureIndex = ConflictPair.dwFeatureIndex1;
  1014. dwConfOptionIndex = ConflictPair.dwOptionIndex1;
  1015. }
  1016. pConfFeature = PGetIndexedFeature(pci->pUIInfo, dwConfFeatureIndex);
  1017. ASSERT(pConfFeature);
  1018. pConfOption = PGetIndexedOption(pci->pUIInfo, pConfFeature, dwConfOptionIndex);
  1019. //
  1020. // We don't expect pConfOption to be NULL here. Use the ASSERT to catch cases we missed.
  1021. //
  1022. ASSERT(pConfOption);
  1023. pszConfFeatureName = OFFSET_TO_POINTER(pci->pUIInfo->pubResourceData, pConfFeature->loKeywordName);
  1024. ASSERT(pszConfFeatureName);
  1025. if (pConfOption)
  1026. {
  1027. pszConfOptionName = OFFSET_TO_POINTER(pci->pUIInfo->pubResourceData, pConfOption->loKeywordName);
  1028. ASSERT(pszConfOptionName);
  1029. }
  1030. else
  1031. {
  1032. pszConfOptionName = &(emptyString[0]);
  1033. }
  1034. //
  1035. // count in the 2 NUL characters: one after feature name, one after option name.
  1036. //
  1037. cbConfFeatureKeySize = strlen(pszConfFeatureName) + 1;
  1038. cbConfOptionKeySize = strlen(pszConfOptionName) + 1;
  1039. }
  1040. //
  1041. // count in the last NUL characters at the end.
  1042. //
  1043. cbNeeded = cbConfFeatureKeySize + cbConfOptionKeySize + 1;
  1044. if (pcbNeeded)
  1045. {
  1046. *pcbNeeded = cbNeeded;
  1047. }
  1048. if (!pmszReasonList || cbSize < cbNeeded)
  1049. {
  1050. return E_OUTOFMEMORY;
  1051. }
  1052. if (bConflictFound)
  1053. {
  1054. ASSERT(pszConfFeatureName && pszConfOptionName);
  1055. CopyMemory(pmszReasonList, pszConfFeatureName, cbConfFeatureKeySize);
  1056. pmszReasonList += cbConfFeatureKeySize;
  1057. CopyMemory(pmszReasonList, pszConfOptionName, cbConfOptionKeySize);
  1058. pmszReasonList += cbConfOptionKeySize;
  1059. }
  1060. //
  1061. // Now the NUL at the end to finish the MULTI_SZ output string.
  1062. //
  1063. *pmszReasonList = NUL;
  1064. return S_OK;
  1065. }
  1066. #endif // PSCRIPT