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.

1402 lines
35 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. #if 0
  363. (VOID) IDisplayErrorMessageBox(
  364. NULL,
  365. 0,
  366. IDS_OEMERR_DLGTITLE,
  367. IDS_OEMERR_PROPSHEET,
  368. CURRENT_OEM_MODULE_NAME(pOemEntry));
  369. #endif
  370. }
  371. END_OEMPLUGIN_LOOP
  372. return TRUE;
  373. }
  374. BOOL
  375. APIENTRY
  376. BGetDriverSettingForOEM(
  377. PCOMMONINFO pci,
  378. PCSTR pFeatureKeyword,
  379. PVOID pOutput,
  380. DWORD cbSize,
  381. PDWORD pcbNeeded,
  382. PDWORD pdwOptionsReturned
  383. )
  384. /*++
  385. Routine Description:
  386. Provide OEM plugins access to driver private settings
  387. Arguments:
  388. pci - Points to basic printer information
  389. pFeatureKeyword - Specifies the keyword the caller is interested in
  390. pOutput - Points to output buffer
  391. cbSize - Size of output buffer
  392. pcbNeeded - Returns the expected size of output buffer
  393. pdwOptionsReturned - Returns the number of options selected
  394. Return Value:
  395. TRUE if successful, FALSE if there is an error
  396. --*/
  397. {
  398. ULONG_PTR dwIndex;
  399. BOOL bResult;
  400. ASSERT(pci->pvStartSign == pci);
  401. //
  402. // This is not very portable: If the pointer value for pFeatureKeyword
  403. // is less than 0x10000, we assume that the pointer value actually
  404. // specifies a predefined index.
  405. //
  406. //
  407. // Following ASSERT is removed for Win64
  408. //
  409. // ASSERT(sizeof(pFeatureKeyword) == sizeof(DWORD));
  410. //
  411. dwIndex = (ULONG_PTR)pFeatureKeyword;
  412. if (dwIndex >= OEMGDS_MIN_DOCSTICKY && dwIndex < OEMGDS_MIN_PRINTERSTICKY)
  413. {
  414. if (pci->pdm == NULL)
  415. goto setting_not_available;
  416. bResult = BGetDevmodeSettingForOEM(
  417. pci->pdm,
  418. (DWORD)dwIndex,
  419. pOutput,
  420. cbSize,
  421. pcbNeeded);
  422. if (bResult)
  423. *pdwOptionsReturned = 1;
  424. }
  425. else if (dwIndex >= OEMGDS_MIN_PRINTERSTICKY && dwIndex < OEMGDS_MAX)
  426. {
  427. if (pci->pPrinterData == NULL)
  428. goto setting_not_available;
  429. bResult = BGetPrinterDataSettingForOEM(
  430. pci->pPrinterData,
  431. (DWORD)dwIndex,
  432. pOutput,
  433. cbSize,
  434. pcbNeeded);
  435. if (bResult)
  436. *pdwOptionsReturned = 1;
  437. }
  438. else
  439. {
  440. if (pci->pCombinedOptions == NULL)
  441. goto setting_not_available;
  442. bResult = BGetGenericOptionSettingForOEM(
  443. pci->pUIInfo,
  444. pci->pCombinedOptions,
  445. pFeatureKeyword,
  446. pOutput,
  447. cbSize,
  448. pcbNeeded,
  449. pdwOptionsReturned);
  450. }
  451. return bResult;
  452. setting_not_available:
  453. WARNING(("Requested driver setting not available: %d\n", pFeatureKeyword));
  454. SetLastError(ERROR_NOT_SUPPORTED);
  455. return FALSE;
  456. }
  457. BOOL
  458. BUpdateUISettingForOEM(
  459. PCOMMONINFO pci,
  460. PVOID pOptItem,
  461. DWORD dwPreviousSelection,
  462. DWORD dwMode
  463. )
  464. /*++
  465. Routine Description:
  466. Update the UI settings in optionsarray for OEM.
  467. Arguments:
  468. pci - Points to basic printer information
  469. pOptItem - Points to the current OPTITEM
  470. Return Value:
  471. TRUE if successful, FALSE if there is an error such as conflict and
  472. user wants to cancel.
  473. --*/
  474. {
  475. POPTITEM pCurItem = pOptItem;
  476. PUIDATA pUiData = (PUIDATA)pci;
  477. if (ICheckConstraintsDlg(pUiData, pCurItem, 1, FALSE) == CONFLICT_CANCEL)
  478. {
  479. //
  480. // If there is a conflict and the user clicked
  481. // CANCEL to restore the original selection.
  482. // CONFLICT_CANCEL, restore the old setting
  483. //
  484. return FALSE;
  485. }
  486. if (dwMode == OEMCUIP_DOCPROP)
  487. {
  488. //
  489. // We use FLAG_WITHIN_PLUGINCALL to indicate we are within the UI helper
  490. // function call issued by OEM plugin. This is needed to fix bug #90923.
  491. //
  492. pUiData->ci.dwFlags |= FLAG_WITHIN_PLUGINCALL;
  493. VUnpackDocumentPropertiesItems(pUiData, pCurItem, 1);
  494. pUiData->ci.dwFlags &= ~FLAG_WITHIN_PLUGINCALL;
  495. VPropShowConstraints(pUiData, MODE_DOCANDPRINTER_STICKY);
  496. }
  497. else
  498. {
  499. VUpdateOptionsArrayWithSelection(pUiData, pCurItem);
  500. VPropShowConstraints(pUiData, MODE_PRINTER_STICKY);
  501. }
  502. //
  503. // Record the fact that one of our OPTITEM selection has been changed by plugin's
  504. // call of helper function DrvUpdateUISetting. This is necessary so that at the
  505. // APPLYNOW time we know constraints could exist even though user hasn't touched
  506. // any of our OPTITEMs.
  507. //
  508. pUiData->ci.dwFlags |= FLAG_PLUGIN_CHANGED_OPTITEM;
  509. return TRUE;
  510. }
  511. BOOL
  512. BUpgradeRegistrySettingForOEM(
  513. HANDLE hPrinter,
  514. PCSTR pFeatureKeyword,
  515. PCSTR pOptionKeyword
  516. )
  517. /*++
  518. Routine Description:
  519. Set the Feature.Option request to our options array. OEM will only
  520. call this function at OEMUpgradeDriver to upgrade their registry setttings
  521. into our optionsarray saved in our PRINTERDATA
  522. Arguments:
  523. hPrinter - Handle of the Printer
  524. pFeatureKeyword - Specifies the keyword the caller is interested in
  525. pOptionKeyword - Specifies the keyword the caller is interested in
  526. Return Value:
  527. TRUE if successful, FALSE if there is an error
  528. --*/
  529. {
  530. PFEATURE pFeature;
  531. POPTION pOption;
  532. DWORD dwFeatureCount, i, j;
  533. BOOL bFeatureFound, bOptionFound, bResult = FALSE;
  534. PCSTR pKeywordName;
  535. POPTSELECT pOptionsArray = NULL;
  536. PDRIVER_INFO_3 pDriverInfo3 = NULL;
  537. PRAWBINARYDATA pRawData = NULL;
  538. PINFOHEADER pInfoHeader = NULL;
  539. PUIINFO pUIInfo = NULL;
  540. PPRINTERDATA pPrinterData = NULL;
  541. OPTSELECT DocOptions[MAX_PRINTER_OPTIONS];
  542. //
  543. // Get information about the printer driver
  544. //
  545. bResult = bFeatureFound = bOptionFound = FALSE;
  546. if ((pDriverInfo3 = MyGetPrinterDriver(hPrinter, NULL, 3)) == NULL)
  547. {
  548. ERR(("Cannot get printer driver info: %d\n", GetLastError()));
  549. goto upgrade_registry_exit;
  550. }
  551. // ENTER_CRITICAL_SECTION();
  552. pRawData = LoadRawBinaryData(pDriverInfo3->pDataFile);
  553. // LEAVE_CRITICAL_SECTION();
  554. if (pRawData == NULL)
  555. goto upgrade_registry_exit;
  556. if (!(pPrinterData = MemAllocZ(sizeof(PRINTERDATA))) ||
  557. !( BGetPrinterProperties(hPrinter, pRawData, pPrinterData)))
  558. {
  559. ERR(("Cannot get printer data info: %d\n", GetLastError()));
  560. goto upgrade_registry_exit;
  561. }
  562. //
  563. // Allocate memory for combined optionsarray
  564. //
  565. if (!(pOptionsArray = MemAllocZ(MAX_COMBINED_OPTIONS * sizeof (OPTSELECT))))
  566. goto upgrade_registry_exit;
  567. if (! InitDefaultOptions(pRawData,
  568. DocOptions,
  569. MAX_PRINTER_OPTIONS,
  570. MODE_DOCUMENT_STICKY))
  571. {
  572. goto upgrade_registry_exit;
  573. }
  574. //
  575. // Combine doc sticky options with printer sticky items
  576. //
  577. CombineOptionArray(pRawData, pOptionsArray, MAX_COMBINED_OPTIONS, DocOptions, pPrinterData->aOptions);
  578. //
  579. // Get an updated instance of printer description data
  580. //
  581. pInfoHeader = InitBinaryData(pRawData,
  582. NULL,
  583. pOptionsArray);
  584. if (pInfoHeader == NULL)
  585. {
  586. ERR(("InitBinaryData failed\n"));
  587. goto upgrade_registry_exit;
  588. }
  589. if (!(pUIInfo = OFFSET_TO_POINTER(pInfoHeader, pInfoHeader->loUIInfoOffset)))
  590. goto upgrade_registry_exit;
  591. //
  592. // Look for feature.option index
  593. //
  594. pFeature = PGetIndexedFeature(pUIInfo, 0);
  595. dwFeatureCount = pRawData->dwDocumentFeatures + pRawData->dwPrinterFeatures;
  596. if (pFeature && dwFeatureCount)
  597. {
  598. for (i = 0; i < dwFeatureCount; i++)
  599. {
  600. pKeywordName = OFFSET_TO_POINTER(pUIInfo->pubResourceData, pFeature->loKeywordName);
  601. if (strcmp(pKeywordName, pFeatureKeyword) == EQUAL_STRING)
  602. {
  603. bFeatureFound = TRUE;
  604. break;
  605. }
  606. pFeature++;
  607. }
  608. }
  609. if (bFeatureFound)
  610. {
  611. pOption = PGetIndexedOption(pUIInfo, pFeature, 0);
  612. for (j = 0; j < pFeature->Options.dwCount; j++)
  613. {
  614. pKeywordName = OFFSET_TO_POINTER(pUIInfo->pubResourceData, pOption->loKeywordName);
  615. if (strcmp(pKeywordName, pOptionKeyword) == EQUAL_STRING)
  616. {
  617. bOptionFound = TRUE;
  618. break;
  619. }
  620. pOption++;
  621. }
  622. }
  623. if (bFeatureFound && bOptionFound)
  624. {
  625. pOptionsArray[i].ubCurOptIndex = (BYTE)j;
  626. //
  627. // Resolve conflicts
  628. //
  629. if (!ResolveUIConflicts( pRawData,
  630. pOptionsArray,
  631. MAX_COMBINED_OPTIONS,
  632. MODE_DOCANDPRINTER_STICKY))
  633. {
  634. VERBOSE(("Resolved conflicting printer feature selections.\n"));
  635. }
  636. SeparateOptionArray(pRawData,
  637. pOptionsArray,
  638. pPrinterData->aOptions,
  639. MAX_PRINTER_OPTIONS,
  640. MODE_PRINTER_STICKY
  641. );
  642. if (!BSavePrinterProperties(hPrinter, pRawData, pPrinterData, sizeof(PRINTERDATA)))
  643. {
  644. ERR(("BSavePrinterProperties failed\n"));
  645. bResult = FALSE;
  646. }
  647. else
  648. bResult = TRUE;
  649. }
  650. upgrade_registry_exit:
  651. if (pInfoHeader)
  652. FreeBinaryData(pInfoHeader);
  653. if (pRawData)
  654. UnloadRawBinaryData(pRawData);
  655. if (pPrinterData)
  656. MemFree(pPrinterData);
  657. if (pDriverInfo3)
  658. MemFree(pDriverInfo3);
  659. if (pOptionsArray)
  660. MemFree(pOptionsArray);
  661. return bResult;
  662. }
  663. #ifdef PSCRIPT
  664. #ifndef WINNT_40
  665. /*++
  666. Routine Name:
  667. HQuerySimulationSupport
  668. Routine Description:
  669. In the case of UI replacement, we allows IHV to query for print processor simulation
  670. support so they can provide simulated features on their UI.
  671. We won't enforce hooking out QueryJobAttribute w/o UI replacement here. We will do it
  672. at DrvQueryJobAttributes.
  673. Arguments:
  674. hPrinter - printer handle
  675. dwLevel - interested level of spooler simulation capability info structure
  676. pCaps - pointer to output buffer
  677. cbSize - size in bytes of output buffer
  678. pcbNeeded - buffer size in bytes needed to store the interested info structure
  679. Return Value:
  680. S_OK if succeeded
  681. E_OUTOFMEMORY if output buffer is not big enough
  682. E_NOTIMPL if the interested level is not supported
  683. E_FAIL if encountered other internal error
  684. Last Error:
  685. None
  686. --*/
  687. HRESULT
  688. HQuerySimulationSupport(
  689. IN HANDLE hPrinter,
  690. IN DWORD dwLevel,
  691. OUT PBYTE pCaps,
  692. IN DWORD cbSize,
  693. OUT PDWORD pcbNeeded
  694. )
  695. {
  696. PRINTPROCESSOR_CAPS_1 SplCaps;
  697. PSIMULATE_CAPS_1 pSimCaps;
  698. DWORD cbNeeded;
  699. //
  700. // currently only Level 1 is supported
  701. //
  702. if (dwLevel != 1)
  703. {
  704. return E_NOTIMPL;
  705. }
  706. cbNeeded = sizeof(SIMULATE_CAPS_1);
  707. if (pcbNeeded)
  708. {
  709. *pcbNeeded = cbNeeded;
  710. }
  711. if (!pCaps || cbSize < cbNeeded)
  712. {
  713. return E_OUTOFMEMORY;
  714. }
  715. //
  716. // Since VGetSpoolerEmfCaps doesn't return error code, we
  717. // are using the dwLevel field to detect if the call succeeds.
  718. // If succeeds, dwLevel should be set as 1.
  719. //
  720. SplCaps.dwLevel = 0;
  721. VGetSpoolerEmfCaps(hPrinter,
  722. NULL,
  723. NULL,
  724. sizeof(PRINTPROCESSOR_CAPS_1),
  725. &SplCaps
  726. );
  727. if (SplCaps.dwLevel != 1)
  728. {
  729. ERR(("VGetSpoolerEmfCaps failed\n"));
  730. return E_FAIL;
  731. }
  732. //
  733. // BUGBUG, we should get a new PRINTPROCESSOR_CAPS level to include all
  734. // these information instead of filling it out here. Need
  735. // new PRINTPROCESSOR_CAPS
  736. //
  737. pSimCaps = (PSIMULATE_CAPS_1)pCaps;
  738. pSimCaps->dwLevel = 1;
  739. pSimCaps->dwPageOrderFlags = SplCaps.dwPageOrderFlags;
  740. pSimCaps->dwNumberOfCopies = SplCaps.dwNumberOfCopies;
  741. pSimCaps->dwNupOptions = SplCaps.dwNupOptions;
  742. //
  743. // PRINTPROCESSOR_CAPS_1 is designed without an explicit field for
  744. // collate simulation. So before its CAPS_2 is introduced, we have
  745. // to assume that if reverse printing is supported, then collate
  746. // simulation is also supported.
  747. //
  748. if (SplCaps.dwPageOrderFlags & REVERSE_PRINT)
  749. {
  750. pSimCaps->dwCollate = 1;
  751. }
  752. else
  753. {
  754. pSimCaps->dwCollate = 0;
  755. }
  756. return S_OK;
  757. }
  758. #endif // !WINNT_40
  759. /*++
  760. Routine Name:
  761. HEnumConstrainedOptions
  762. Routine Description:
  763. enumerate the constrained option keyword name list in the specified feature
  764. Arguments:
  765. poemuiobj - pointer to driver context object
  766. dwFlags - flags for the enumeration operation
  767. pszFeatureKeyword - feature keyword name
  768. pmszConstrainedOptionList - pointer to output data buffer
  769. cbSize - output data buffer size in bytes
  770. pcbNeeded - buffer size in bytes needed to store the output data
  771. Return Value:
  772. S_OK if succeeds
  773. E_OUTOFMEMORY if output data buffer size is not big enough
  774. E_INVALIDARG if feature keyword name is not recognized, or the feature's
  775. stickiness doesn't match current sticky-mode
  776. E_FAIL if other internal failures are encountered
  777. Last Error:
  778. None
  779. --*/
  780. HRESULT
  781. HEnumConstrainedOptions(
  782. IN POEMUIOBJ poemuiobj,
  783. IN DWORD dwFlags,
  784. IN PCSTR pszFeatureKeyword,
  785. OUT PSTR pmszConstrainedOptionList,
  786. IN DWORD cbSize,
  787. OUT PDWORD pcbNeeded
  788. )
  789. {
  790. PCOMMONINFO pci = (PCOMMONINFO)poemuiobj;
  791. PUIDATA pUiData;
  792. PFEATURE pFeature;
  793. POPTION pOption;
  794. DWORD dwFeatureIndex, dwIndex;
  795. PBOOL pabEnabledOptions = NULL;
  796. PSTR pCurrentOut;
  797. DWORD cbNeeded;
  798. INT cbRemain;
  799. HRESULT hr;
  800. pUiData = (PUIDATA)pci;
  801. if (!pszFeatureKeyword ||
  802. (pFeature = PGetNamedFeature(pci->pUIInfo, pszFeatureKeyword, &dwFeatureIndex)) == NULL)
  803. {
  804. WARNING(("HEnumConstrainedOptions: invalid feature\n"));
  805. //
  806. // Even though we could return right here, we still use goto to maintain single exit point.
  807. //
  808. hr = E_INVALIDARG;
  809. goto exit;
  810. }
  811. //
  812. // pUiData->iMode can have 2 modes: MODE_DOCUMENT_STICKY and MODE_PRINTER_STICKY. See PFillUiData().
  813. // In MODE_DOCUMENT_STICKY mode, we only support doc-sticky features.
  814. // In MODE_PRINTER_STICKY mode, we only support printer-sticky features.
  815. //
  816. // This is because in function PFillUiData(), it only fills devmode in MODE_DOCUMENT_STICKY mode.
  817. // Then in BCombineCommonInfoOptionsArray(), if devmode option array is not available, the PPD parser
  818. // will use OPTION_INDEX_ANY for any doc-sticky features.
  819. //
  820. if ((pUiData->iMode == MODE_DOCUMENT_STICKY && pFeature->dwFeatureType == FEATURETYPE_PRINTERPROPERTY) ||
  821. (pUiData->iMode == MODE_PRINTER_STICKY && pFeature->dwFeatureType != FEATURETYPE_PRINTERPROPERTY))
  822. {
  823. VERBOSE(("HEnumConstrainedOptions: mismatch iMode=%d, dwFeatureType=%d\n",
  824. pUiData->iMode, pFeature->dwFeatureType)) ;
  825. hr = E_INVALIDARG;
  826. goto exit;
  827. }
  828. if (pFeature->Options.dwCount)
  829. {
  830. if ((pabEnabledOptions = MemAllocZ(pFeature->Options.dwCount * sizeof(BOOL))) == NULL)
  831. {
  832. ERR(("HEnumConstrainedOptions: memory alloc failed\n"));
  833. hr = E_FAIL;
  834. goto exit;
  835. }
  836. //
  837. // Get the feature's enabled option list.
  838. //
  839. // See VPropShowConstraints() in docprop.c and prnprop.c for using different
  840. // modes to call EnumEnabledOptions().
  841. //
  842. if (pUiData->iMode == MODE_DOCUMENT_STICKY)
  843. {
  844. EnumEnabledOptions(pci->pRawData, pci->pCombinedOptions, dwFeatureIndex,
  845. pabEnabledOptions, MODE_DOCANDPRINTER_STICKY);
  846. }
  847. else
  848. {
  849. EnumEnabledOptions(pci->pRawData, pci->pCombinedOptions, dwFeatureIndex,
  850. pabEnabledOptions, MODE_PRINTER_STICKY);
  851. }
  852. }
  853. else
  854. {
  855. RIP(("HEnumConstrainedOptions: feature %s has no options\n", pszFeatureKeyword));
  856. //
  857. // continue so we will output the empty string with only the NUL character
  858. //
  859. }
  860. pCurrentOut = pmszConstrainedOptionList;
  861. cbNeeded = 0;
  862. cbRemain = (INT)cbSize;
  863. pOption = OFFSET_TO_POINTER(pci->pInfoHeader, pFeature->Options.loOffset);
  864. ASSERT(pOption || pFeature->Options.dwCount == 0);
  865. if (pOption == NULL && pFeature->Options.dwCount != 0)
  866. {
  867. hr = E_FAIL;
  868. goto exit;
  869. }
  870. for (dwIndex = 0; dwIndex < pFeature->Options.dwCount; dwIndex++)
  871. {
  872. if (!pabEnabledOptions[dwIndex])
  873. {
  874. DWORD dwNameSize;
  875. PSTR pszKeywordName;
  876. pszKeywordName = OFFSET_TO_POINTER(pci->pUIInfo->pubResourceData, pOption->loKeywordName);
  877. ASSERT(pszKeywordName);
  878. if (pszKeywordName == NULL)
  879. {
  880. hr = E_FAIL;
  881. goto exit;
  882. }
  883. //
  884. // count in the NUL character between constrained option keywords
  885. //
  886. dwNameSize = strlen(pszKeywordName) + 1;
  887. if (pCurrentOut && cbRemain >= (INT)dwNameSize)
  888. {
  889. CopyMemory(pCurrentOut, pszKeywordName, dwNameSize);
  890. pCurrentOut += dwNameSize;
  891. }
  892. cbRemain -= dwNameSize;
  893. cbNeeded += dwNameSize;
  894. }
  895. pOption = (POPTION)((PBYTE)pOption + pFeature->dwOptionSize);
  896. }
  897. //
  898. // remember the last NUL terminator for the MULTI_SZ output string
  899. //
  900. cbNeeded++;
  901. if (pcbNeeded)
  902. {
  903. *pcbNeeded = cbNeeded;
  904. }
  905. if (!pCurrentOut || cbRemain < 1)
  906. {
  907. hr = E_OUTOFMEMORY;
  908. goto exit;
  909. }
  910. *pCurrentOut = NUL;
  911. //
  912. // Succeeded
  913. //
  914. hr = S_OK;
  915. exit:
  916. MemFree(pabEnabledOptions);
  917. return hr;
  918. }
  919. /*++
  920. Routine Name:
  921. HWhyConstrained
  922. Routine Description:
  923. get feature/option keyword pair that constrains the given
  924. feature/option pair
  925. Arguments:
  926. poemuiobj - pointer to driver context object
  927. dwFlags - flags for this operation
  928. pszFeatureKeyword - feature keyword name
  929. pszOptionKeyword - option keyword name
  930. pmszReasonList - pointer to output data buffer
  931. cbSize - output data buffer size in bytes
  932. pcbNeeded - buffer size in bytes needed to store the output data
  933. Return Value:
  934. S_OK if succeeds
  935. E_OUTOFMEMORY if output data buffer size is not big enough
  936. E_INVALIDARG if the feature keyword name or option keyword name
  937. is not recognized, or the feature's stickiness
  938. doesn't match current sticky-mode
  939. Last Error:
  940. None
  941. --*/
  942. HRESULT
  943. HWhyConstrained(
  944. IN POEMUIOBJ poemuiobj,
  945. IN DWORD dwFlags,
  946. IN PCSTR pszFeatureKeyword,
  947. IN PCSTR pszOptionKeyword,
  948. OUT PSTR pmszReasonList,
  949. IN DWORD cbSize,
  950. OUT PDWORD pcbNeeded
  951. )
  952. {
  953. PCOMMONINFO pci = (PCOMMONINFO)poemuiobj;
  954. PUIDATA pUiData;
  955. PFEATURE pFeature;
  956. POPTION pOption;
  957. DWORD dwFeatureIndex, dwOptionIndex;
  958. CONFLICTPAIR ConflictPair;
  959. BOOL bConflictFound;
  960. PSTR pszConfFeatureName = NULL, pszConfOptionName = NULL;
  961. CHAR emptyString[1] = {0};
  962. DWORD cbConfFeatureKeySize = 0, cbConfOptionKeySize = 0;
  963. DWORD cbNeeded = 0;
  964. pUiData = (PUIDATA)pci;
  965. if (!pszFeatureKeyword ||
  966. (pFeature = PGetNamedFeature(pci->pUIInfo, pszFeatureKeyword, &dwFeatureIndex)) == NULL)
  967. {
  968. WARNING(("HWhyConstrained: invalid feature\n"));
  969. return E_INVALIDARG;
  970. }
  971. if (!pszOptionKeyword ||
  972. (pOption = PGetNamedOption(pci->pUIInfo, pFeature, pszOptionKeyword, &dwOptionIndex)) == NULL)
  973. {
  974. WARNING(("HWhyConstrained: invalid option\n"));
  975. return E_INVALIDARG;
  976. }
  977. //
  978. // See comments in HEnumConstrainedOptions() for following stickiness mode check.
  979. //
  980. if ((pUiData->iMode == MODE_DOCUMENT_STICKY && pFeature->dwFeatureType == FEATURETYPE_PRINTERPROPERTY) ||
  981. (pUiData->iMode == MODE_PRINTER_STICKY && pFeature->dwFeatureType != FEATURETYPE_PRINTERPROPERTY))
  982. {
  983. VERBOSE(("HWhyConstrained: mismatch iMode=%d, dwFeatureType=%d\n",pUiData->iMode, pFeature->dwFeatureType));
  984. return E_INVALIDARG;
  985. }
  986. //
  987. // Get the feature/option pair that constrains the feature/option pair client is querying for.
  988. //
  989. bConflictFound = EnumNewPickOneUIConflict(pci->pRawData,
  990. pci->pCombinedOptions,
  991. dwFeatureIndex,
  992. dwOptionIndex,
  993. &ConflictPair);
  994. if (bConflictFound)
  995. {
  996. PFEATURE pConfFeature;
  997. POPTION pConfOption;
  998. DWORD dwConfFeatureIndex, dwConfOptionIndex;
  999. //
  1000. // ConflictPair has the feature with higher priority as dwFeatureIndex1.
  1001. //
  1002. if (dwFeatureIndex == ConflictPair.dwFeatureIndex1)
  1003. {
  1004. dwConfFeatureIndex = ConflictPair.dwFeatureIndex2;
  1005. dwConfOptionIndex = ConflictPair.dwOptionIndex2;
  1006. }
  1007. else
  1008. {
  1009. dwConfFeatureIndex = ConflictPair.dwFeatureIndex1;
  1010. dwConfOptionIndex = ConflictPair.dwOptionIndex1;
  1011. }
  1012. pConfFeature = PGetIndexedFeature(pci->pUIInfo, dwConfFeatureIndex);
  1013. ASSERT(pConfFeature);
  1014. pConfOption = PGetIndexedOption(pci->pUIInfo, pConfFeature, dwConfOptionIndex);
  1015. //
  1016. // We don't expect pConfOption to be NULL here. Use the ASSERT to catch cases we missed.
  1017. //
  1018. ASSERT(pConfOption);
  1019. pszConfFeatureName = OFFSET_TO_POINTER(pci->pUIInfo->pubResourceData, pConfFeature->loKeywordName);
  1020. ASSERT(pszConfFeatureName);
  1021. if (pConfOption)
  1022. {
  1023. pszConfOptionName = OFFSET_TO_POINTER(pci->pUIInfo->pubResourceData, pConfOption->loKeywordName);
  1024. ASSERT(pszConfOptionName);
  1025. }
  1026. else
  1027. {
  1028. pszConfOptionName = &(emptyString[0]);
  1029. }
  1030. //
  1031. // count in the 2 NUL characters: one after feature name, one after option name.
  1032. //
  1033. cbConfFeatureKeySize = strlen(pszConfFeatureName) + 1;
  1034. cbConfOptionKeySize = strlen(pszConfOptionName) + 1;
  1035. }
  1036. //
  1037. // count in the last NUL characters at the end.
  1038. //
  1039. cbNeeded = cbConfFeatureKeySize + cbConfOptionKeySize + 1;
  1040. if (pcbNeeded)
  1041. {
  1042. *pcbNeeded = cbNeeded;
  1043. }
  1044. if (!pmszReasonList || cbSize < cbNeeded)
  1045. {
  1046. return E_OUTOFMEMORY;
  1047. }
  1048. if (bConflictFound)
  1049. {
  1050. ASSERT(pszConfFeatureName && pszConfOptionName);
  1051. CopyMemory(pmszReasonList, pszConfFeatureName, cbConfFeatureKeySize);
  1052. pmszReasonList += cbConfFeatureKeySize;
  1053. CopyMemory(pmszReasonList, pszConfOptionName, cbConfOptionKeySize);
  1054. pmszReasonList += cbConfOptionKeySize;
  1055. }
  1056. //
  1057. // Now the NUL at the end to finish the MULTI_SZ output string.
  1058. //
  1059. *pmszReasonList = NUL;
  1060. return S_OK;
  1061. }
  1062. #endif // PSCRIPT