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.

1652 lines
36 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. All rights reserved.
  4. Module Name:
  5. prtprops.cxx
  6. Abstract:
  7. Printer Property Sheet
  8. Author:
  9. Steve Kiraly (SteveKi) 13-Feb-1996
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. #include "time.hxx"
  15. #include "psetup.hxx"
  16. #include "drvsetup.hxx"
  17. #include "instarch.hxx"
  18. #include "portslv.hxx"
  19. #include "driverif.hxx"
  20. #include "driverlv.hxx"
  21. #include "dsinterf.hxx"
  22. #include "prtprop.hxx"
  23. #include "prtshare.hxx"
  24. #include "drvsetup.hxx"
  25. #include "archlv.hxx"
  26. #include "detect.hxx"
  27. #include "setup.hxx"
  28. #include "propmgr.hxx"
  29. #include "prtprops.hxx"
  30. /********************************************************************
  31. All printer property sheet manager.
  32. ********************************************************************/
  33. /*++
  34. Routine Name:
  35. TPrinterPropertySheetManager
  36. Routine Description:
  37. Constructor.
  38. Arguments:
  39. Pointer to the printer data.
  40. Return Value:
  41. Nothing.
  42. --*/
  43. TPrinterPropertySheetManager::
  44. TPrinterPropertySheetManager(
  45. TPrinterData* pPrinterData
  46. ) : _General( pPrinterData ),
  47. _Ports( pPrinterData ),
  48. _JobScheduling( pPrinterData ),
  49. _Sharing( pPrinterData ),
  50. _pPrinterData( pPrinterData ),
  51. _hDrvPropSheet( NULL ),
  52. _bValid( TRUE ),
  53. _hwndParent( NULL )
  54. {
  55. }
  56. /*++
  57. Routine Name:
  58. ~TPrinterPropertySheetManager
  59. Routine Description:
  60. Destructor.
  61. Arguments:
  62. Pointer to the printer data.
  63. Return Value:
  64. Nothing.
  65. --*/
  66. TPrinterPropertySheetManager::
  67. ~TPrinterPropertySheetManager(
  68. )
  69. {
  70. DBGMSG( DBG_TRACE, ( "TPrinterPropertySheetManager::dtor.\n" ) );
  71. }
  72. /*++
  73. Routine Name:
  74. bValid
  75. Routine Description:
  76. Indicates if the object is in a valid state.
  77. Arguments:
  78. Nothing.
  79. Return Value:
  80. TRUE valid object, FALSE invalid object.
  81. --*/
  82. BOOL
  83. TPrinterPropertySheetManager::
  84. bValid(
  85. VOID
  86. )
  87. {
  88. return _General.bValid() && _Ports.bValid() &&
  89. _JobScheduling.bValid() && _Sharing.bValid() && _bValid;
  90. }
  91. /*++
  92. Routine Name:
  93. bDisplayPages
  94. Routine Description:
  95. Display the property sheet pages.
  96. Arguments:
  97. Nothing.
  98. Return Value:
  99. TRUE sheets displayed, FALSE error occurred.
  100. --*/
  101. BOOL
  102. TPrinterPropertySheetManager::
  103. bDisplayPages(
  104. VOID
  105. )
  106. {
  107. //
  108. // Load the printer data.
  109. //
  110. BOOL bStatus = _pPrinterData->bLoad();
  111. if( !bStatus ){
  112. iMessage( NULL,
  113. IDS_ERR_PRINTER_PROP_TITLE,
  114. IDS_ERR_PRINTER_PROP,
  115. MB_OK|MB_ICONSTOP|MB_SETFOREGROUND,
  116. kMsgGetLastError,
  117. NULL );
  118. }
  119. if( bStatus ){
  120. if( _pPrinterData->bNoAccess() ){
  121. //
  122. // Display the security tab.
  123. //
  124. bStatus = bDisplaySecurityTab( _pPrinterData->hwnd() );
  125. } else
  126. {
  127. //
  128. // Display the property sheets.
  129. //
  130. bStatus = TPropertySheetManager::bDisplayPages( _pPrinterData->hwnd() );
  131. }
  132. }
  133. return bStatus;
  134. }
  135. /*++
  136. Routine Name:
  137. bRefreshDriverPages
  138. Routine Description:
  139. This routine is called when the driver has been changed. It will
  140. release any previous driver pages and then build the new driver
  141. pages.
  142. Arguments:
  143. None.
  144. Return Value:
  145. TRUE if success, FALSE if error occurred.
  146. --*/
  147. BOOL
  148. TPrinterPropertySheetManager::
  149. bRefreshDriverPages(
  150. VOID
  151. )
  152. {
  153. DBGMSG( DBG_TRACE, ( "TPrinterPropertySheetManager bRefreshDriverPages\n") );
  154. //
  155. // Release the driver pages.
  156. //
  157. vReleaseDriverPages( &_CPSUIInfo );
  158. //
  159. // Release any shell extension pages.
  160. //
  161. _ShellExtPages.vDestroy( &_CPSUIInfo );
  162. //
  163. // Build any shell extension pages, if this fails it does not
  164. // constitute a failure. We still want to bring up our
  165. // property pages.
  166. //
  167. _ShellExtPages.bCreate( &_CPSUIInfo, _pPrinterData->strCurrentPrinterName() );
  168. //
  169. // Check to build the driver specific pages.
  170. //
  171. bCheckToBuildDriverPages( &_CPSUIInfo );
  172. //
  173. // Always TRUE.
  174. //
  175. return TRUE;
  176. }
  177. /*++
  178. Routine Name:
  179. bGetDriverPageHandle
  180. Routine Description:
  181. This routine is to get the property sheet handle of the first
  182. driver property sheet.
  183. Arguments:
  184. Pointer where to return the driver page handle.
  185. Return Value:
  186. TRUE if success, FALSE if error occurred.
  187. --*/
  188. BOOL
  189. TPrinterPropertySheetManager::
  190. bGetDriverPageHandle(
  191. IN HPROPSHEETPAGE *phPage
  192. )
  193. {
  194. TStatusB bStatus;
  195. DWORD cPages;
  196. HPROPSHEETPAGE *phPages;
  197. bStatus DBGCHK = bGetDriverPageHandles( &_CPSUIInfo, &cPages, &phPages );
  198. if( bStatus )
  199. {
  200. *phPage = phPages[0];
  201. delete [] phPages;
  202. }
  203. return bStatus;
  204. }
  205. /********************************************************************
  206. Private member functions.
  207. ********************************************************************/
  208. /*++
  209. Routine Name:
  210. bBuildsPages
  211. Routine Description:
  212. This routine is called from the compstui dispatch
  213. function in response to the REASON_INIT message. As a
  214. side issue this routine will bring up the printer
  215. property sheets if we have access to display the sheets. If
  216. access is denied on the security page will be shown.
  217. Arguments:
  218. pCPSUIInfo - pointer to compstui info header.
  219. Return Value:
  220. TRUE if success, FALSE if error occurred.
  221. --*/
  222. BOOL
  223. TPrinterPropertySheetManager::
  224. bBuildPages(
  225. IN PPROPSHEETUI_INFO pCPSUIInfo
  226. )
  227. {
  228. DBGMSG( DBG_TRACE, ( "TPrinterPropertySheetManager bBuildPages\n") );
  229. TStatusB bStatus;
  230. LONG_PTR hResult;
  231. UINT uPages[kMaxGroups];
  232. HANDLE hGroups[kMaxGroups];
  233. UINT cGroups = 0;
  234. //
  235. // Set the default activation context to be V6 prior calling into
  236. // compstui to create the pages. This will force V6 context unless
  237. // the callbacks which create the compstui pages specify otherwise
  238. // on a per page basis.
  239. //
  240. bStatus DBGCHK = (BOOL)pCPSUIInfo->pfnComPropSheet(
  241. pCPSUIInfo->hComPropSheet,
  242. CPSFUNC_SET_FUSION_CONTEXT,
  243. reinterpret_cast<LPARAM>(g_hActCtx),
  244. static_cast<LPARAM>(0));
  245. if( bStatus )
  246. {
  247. //
  248. // Build the spooler pages.
  249. //
  250. bStatus DBGCHK = bBuildSpoolerPages( pCPSUIInfo );
  251. if( bStatus && TPropertySheetManager::bValidCompstuiHandle( reinterpret_cast<LONG_PTR>(pCPSUIInfo->hComPropSheet) ) ){
  252. //
  253. // Collect the count of the spooler pages
  254. //
  255. hGroups[cGroups] = pCPSUIInfo->hComPropSheet;
  256. uPages[cGroups] = pCPSUIInfo->pfnComPropSheet( hGroups[cGroups],
  257. CPSFUNC_GET_PAGECOUNT,
  258. static_cast<LPARAM>(0),
  259. static_cast<LPARAM>(0));
  260. cGroups++;
  261. //
  262. // Build any shell extension property pages.
  263. //
  264. if( _ShellExtPages.bCreate( pCPSUIInfo, _pPrinterData->strPrinterName() ) ){
  265. //
  266. // Collect the count of the shell extention pages
  267. //
  268. hGroups[cGroups] = _ShellExtPages.hPropSheet();
  269. uPages[cGroups] = pCPSUIInfo->pfnComPropSheet( hGroups[cGroups],
  270. CPSFUNC_GET_PAGECOUNT,
  271. static_cast<LPARAM>(0),
  272. static_cast<LPARAM>(0));
  273. cGroups++;
  274. }
  275. //
  276. // Only load the driver pages if we have access.
  277. //
  278. if( !_pPrinterData->bNoAccess() ){
  279. //
  280. // Check to build the driver specific pages.
  281. //
  282. if( bCheckToBuildDriverPages( pCPSUIInfo ) && TPropertySheetManager::bValidCompstuiHandle( _hDrvPropSheet ) ){
  283. //
  284. // Collect the count of the driver UI pages
  285. //
  286. hGroups[cGroups] = reinterpret_cast<HANDLE>(_hDrvPropSheet);
  287. uPages[cGroups] = pCPSUIInfo->pfnComPropSheet( hGroups[cGroups],
  288. CPSFUNC_GET_PAGECOUNT,
  289. static_cast<LPARAM>(0),
  290. static_cast<LPARAM>(0));
  291. cGroups++;
  292. }
  293. }
  294. }
  295. if( bStatus ){
  296. //
  297. // Find the group to select the page to
  298. //
  299. UINT uGrp = 0;
  300. UINT uStartPage = _pPrinterData->uStartPage();
  301. while( uGrp < cGroups )
  302. {
  303. if( uStartPage < uPages[uGrp] )
  304. {
  305. break;
  306. }
  307. else
  308. {
  309. uStartPage -= uPages[uGrp];
  310. uGrp++;
  311. }
  312. }
  313. //
  314. // Set the start page. We can only set the start page
  315. // to one of our pages. If this fails it is not fatal.
  316. //
  317. if( uGrp < cGroups ){
  318. CAutoPtr<HPROPSHEETPAGE> sphPages = new HPROPSHEETPAGE[ uPages[uGrp] ];
  319. if( sphPages ){
  320. //
  321. // Get the property pages for the selected group.
  322. //
  323. UINT cPages = pCPSUIInfo->pfnComPropSheet( hGroups[uGrp],
  324. CPSFUNC_GET_HPSUIPAGES,
  325. reinterpret_cast<LPARAM>(sphPages.GetPtr()),
  326. static_cast<LPARAM>(uPages[uGrp]) );
  327. if( uStartPage < cPages ){
  328. //
  329. // Select the page in the appropriate group.
  330. //
  331. hResult = pCPSUIInfo->pfnComPropSheet( hGroups[uGrp],
  332. CPSFUNC_SET_HSTARTPAGE,
  333. reinterpret_cast<LPARAM>(sphPages.GetPtr()[uStartPage]),
  334. static_cast<LPARAM>(0) );
  335. //
  336. // Check to validate the result
  337. //
  338. if( !bValidCompstuiHandle( hResult ) ){
  339. DBGMSG( DBG_TRACE, ( "TPrinterPropertySheetManager CPSFUNC_SET_HSTARTPAGE failed with %d.\n", hResult ) );
  340. }
  341. }
  342. }
  343. } else {
  344. //
  345. // Set the start page. We can only set the start page
  346. // to one of our pages. If this fails it is not fatal.
  347. //
  348. if( !_pPrinterData->strSheetName().bEmpty() ){
  349. hResult = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
  350. CPSFUNC_SET_HSTARTPAGE,
  351. (LPARAM)0,
  352. (LPARAM)(LPCTSTR)_pPrinterData->strSheetName() );
  353. if( !bValidCompstuiHandle( hResult ) ){
  354. DBGMSG( DBG_TRACE, ( "TPrinterPropertySheetManager CPSFUNC_SET_HSTARTPAGE failed with %d.\n", hResult ) );
  355. }
  356. }
  357. }
  358. }
  359. }
  360. return TRUE;
  361. }
  362. /*++
  363. Routine Name:
  364. bBuildSpoolerPages
  365. Routine Description:
  366. Builds the spooler related pages.
  367. Arguments:
  368. pCPSUIInfo - pointer to compstui info header.
  369. Return Value:
  370. TRUE success, FALSE error occurred.
  371. --*/
  372. BOOL
  373. TPrinterPropertySheetManager::
  374. bBuildSpoolerPages(
  375. IN PPROPSHEETUI_INFO pCPSUIInfo
  376. )
  377. {
  378. TStatusB bStatus;
  379. bStatus DBGNOCHK = TRUE;
  380. LONG_PTR hResult;
  381. PROPSHEETPAGE psp;
  382. //
  383. // Build the printer property pages.
  384. //
  385. struct SheetInitializer {
  386. TPrinterProp* pSheet;
  387. INT iDialog;
  388. };
  389. SheetInitializer aSheetInit[] = {
  390. {&_General, DLG_PRINTER_GENERAL },
  391. {&_Sharing, DLG_PRINTER_SHARING },
  392. {&_Ports, DLG_PRINTER_PORTS },
  393. {&_JobScheduling, DLG_PRINTER_JOB_SCHEDULING },
  394. };
  395. ZeroMemory( &psp, sizeof( psp ) );
  396. for( UINT i = 0; i < COUNTOF( aSheetInit ); ++i ){
  397. //
  398. // Printers using the fax driver do not need the ports tab.
  399. //
  400. if( _pPrinterData->bIsFaxDriver() ){
  401. if( aSheetInit[i].iDialog == DLG_PRINTER_PORTS || aSheetInit[i].iDialog == DLG_PRINTER_JOB_SCHEDULING ){
  402. continue;
  403. }
  404. }
  405. psp.dwSize = sizeof( psp );
  406. psp.dwFlags = PSP_DEFAULT;
  407. psp.hInstance = ghInst;
  408. psp.pfnDlgProc = MGenericProp::SetupDlgProc;
  409. psp.pszTemplate = MAKEINTRESOURCE( aSheetInit[i].iDialog );
  410. psp.lParam = (LPARAM)(MGenericProp*)aSheetInit[i].pSheet;
  411. hResult = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
  412. CPSFUNC_ADD_PROPSHEETPAGE,
  413. (LPARAM)&psp,
  414. NULL );
  415. if( !bValidCompstuiHandle( hResult ) ){
  416. DBGMSG( DBG_TRACE, ( "TPrinterPropertySheetManager CPSFUNC_ADD_PROPSHEETPAGE failed with %d.\n", hResult ) );
  417. bStatus DBGNOCHK = FALSE;
  418. break;
  419. } else {
  420. DBGMSG( DBG_TRACE, ( "Page added %d %x.\n", i, hResult ) );
  421. //
  422. // Save the page handle.
  423. //
  424. _pPrinterData->_hPages[i] = hResult;
  425. }
  426. }
  427. return bStatus;
  428. }
  429. /*++
  430. Routine Name:
  431. bInstallDriverPage
  432. Routine Description:
  433. Installs the driver pages if they are not on this machine.
  434. Arguments:
  435. Nothing.
  436. Return Value:
  437. TRUE success, FALSE error occurred - driver pages we not loaded.
  438. --*/
  439. BOOL
  440. TPrinterPropertySheetManager::
  441. bInstallDriverPage(
  442. VOID
  443. )
  444. {
  445. //
  446. // Check if we have access on this machine to install a printer
  447. // driver. If we do then we ask the user if they want to install
  448. // the correct printer driver.
  449. //
  450. TStatus Status;
  451. DWORD dwAccess = SERVER_ALL_ACCESS;
  452. HANDLE hPrintServer = NULL;
  453. TStatusB bStatus;
  454. bStatus DBGNOCHK = FALSE;
  455. //
  456. // Open the print server
  457. //
  458. Status DBGCHK = TPrinter::sOpenPrinter( NULL, &dwAccess, &hPrintServer );
  459. //
  460. // If print server was opened and we do have access,
  461. // then let the user install the driver.
  462. //
  463. if( Status == ERROR_SUCCESS ){
  464. //
  465. // Ensure we close the printer handle.
  466. //
  467. ClosePrinter( hPrintServer );
  468. //
  469. // Driver load failed, display error message to user, indicating
  470. // the device option will not be displayed, and if they want
  471. // to install the driver.
  472. //
  473. if( IDYES == iMessage( _pPrinterData->hwnd(),
  474. IDS_ERR_PRINTER_PROP_TITLE,
  475. IDS_ERR_NO_DRIVER_INSTALLED,
  476. MB_YESNO|MB_ICONEXCLAMATION,
  477. kMsgNone,
  478. NULL,
  479. static_cast<LPCTSTR>(_pPrinterData->strDriverName()) ) ){
  480. TCHAR szDriverName[kPrinterBufMax];
  481. UINT cchDriverName = 0;
  482. _tcscpy( szDriverName, _pPrinterData->strDriverName() );
  483. //
  484. // The user indicated they would like to install the driver.
  485. // A null server name is passed because we want to install
  486. // the printer drivers on this machine not the remote.
  487. //
  488. bStatus DBGCHK = bPrinterSetup( _pPrinterData->hwnd(),
  489. MSP_NEWDRIVER,
  490. COUNTOF( szDriverName ),
  491. szDriverName,
  492. &cchDriverName,
  493. NULL );
  494. if( GetLastError() == ERROR_CANCELLED )
  495. {
  496. //
  497. // Indicates the driver pages we not loaded.
  498. //
  499. bStatus DBGNOCHK = FALSE;
  500. }
  501. else
  502. {
  503. bStatus DBGNOCHK = TRUE;
  504. }
  505. }
  506. } else {
  507. bStatus DBGNOCHK = FALSE;
  508. }
  509. return bStatus;
  510. }
  511. /*++
  512. Routine Name:
  513. bRefreshTitle
  514. Routine Description:
  515. Creates the property sheet title.
  516. Arguments:
  517. Nothing.
  518. Return Value:
  519. TRUE success, FALSE error occurred.
  520. --*/
  521. VOID
  522. TPrinterPropertySheetManager::
  523. vRefreshTitle(
  524. VOID
  525. )
  526. {
  527. //
  528. // Locates the dialog box with the title.
  529. //
  530. bCreateTitle();
  531. SPLASSERT( _hwndParent );
  532. //
  533. // Set the main dialogs title.
  534. //
  535. SetWindowText( _hwndParent, _strTitle );
  536. }
  537. /*++
  538. Routine Name:
  539. vSetParentHandle
  540. Routine Description:
  541. Set the parent window handle.
  542. Arguments:
  543. handle to parent window, main dialog.
  544. Return Value:
  545. Nothing.
  546. --*/
  547. VOID
  548. TPrinterPropertySheetManager::
  549. vSetParentHandle(
  550. IN HWND hwndParent
  551. )
  552. {
  553. _hwndParent = hwndParent;
  554. }
  555. /*++
  556. Routine Name:
  557. hGetParentHandle
  558. Routine Description:
  559. Get the parent window handle.
  560. Arguments:
  561. None
  562. Return Value:
  563. handle to parent window, main dialog
  564. --*/
  565. HWND
  566. TPrinterPropertySheetManager::
  567. hGetParentHandle(
  568. VOID
  569. ) const
  570. {
  571. return _hwndParent;
  572. }
  573. /*++
  574. Routine Name:
  575. bCreatePropertySheetTitle.
  576. Routine Description:
  577. Creates the property sheet title.
  578. Arguments:
  579. Nothing.
  580. Return Value:
  581. TRUE success, FALSE error occurred.
  582. --*/
  583. BOOL
  584. TPrinterPropertySheetManager::
  585. bCreateTitle(
  586. VOID
  587. )
  588. {
  589. TCHAR szBuffer[kStrMax+kPrinterBufMax];
  590. UINT nSize = COUNTOF( szBuffer );
  591. TString strProperties;
  592. TStatusB bStatus;
  593. //
  594. // Create the formated property sheet title.
  595. //
  596. bStatus DBGCHK = ConstructPrinterFriendlyName( (LPCTSTR)_pPrinterData->strCurrentPrinterName(), szBuffer, &nSize );
  597. //
  598. // Load the property word from the resource file.
  599. //
  600. bStatus DBGCHK = strProperties.bLoadString( ghInst, IDS_TEXT_PROPERTIES );
  601. //
  602. // Construct the property sheet title.
  603. //
  604. bStatus DBGCHK = bConstructMessageString( ghInst, _strTitle, IDS_PRINTER_PROPERTIES_TITLE_FORMAT, szBuffer, (LPCTSTR)strProperties );
  605. return bStatus;
  606. }
  607. /*++
  608. Routine Name:
  609. bDestroyPages
  610. Routine Description:
  611. Destroy any compstui specific data information.
  612. Arguments:
  613. pCPSUIInfo - Pointer to commonui property sheet info header,
  614. pSetResultInfo - Pointer to result info header
  615. Return Value:
  616. TRUE success, FALSE error occurred.
  617. --*/
  618. BOOL
  619. TPrinterPropertySheetManager::
  620. bDestroyPages(
  621. IN PPROPSHEETUI_INFO pPSUIInfo
  622. )
  623. {
  624. DBGMSG( DBG_TRACE, ( "TPrinterPropertySheetManager bDestroyPages\n") );
  625. UNREFERENCED_PARAMETER( pPSUIInfo );
  626. //
  627. // Release any shell extension information.
  628. //
  629. _ShellExtPages.vDestroy( NULL );
  630. return TRUE;
  631. }
  632. /*++
  633. Routine Name:
  634. bSetHeader
  635. Routine Description:
  636. Set the property sheet header information.
  637. Arguments:
  638. pCPSUIInfo - Pointer to common ui property sheet info header,
  639. pPSUIInfoHdr - Pointer to propetry sheet header
  640. Return Value:
  641. TRUE success, FALSE error occurred.
  642. --*/
  643. BOOL
  644. TPrinterPropertySheetManager::
  645. bSetHeader(
  646. IN PPROPSHEETUI_INFO pCPSUIInfo,
  647. IN PPROPSHEETUI_INFO_HEADER pPSUIInfoHdr
  648. )
  649. {
  650. DBGMSG( DBG_TRACE, ( "TPrinterPropertySheetManager bSetHeader\n") );
  651. UNREFERENCED_PARAMETER( pCPSUIInfo );
  652. //
  653. // Create the window title.
  654. //
  655. bCreateTitle();
  656. //
  657. // Set the property sheet header information.
  658. //
  659. pPSUIInfoHdr->cbSize = sizeof( PROPSHEETUI_INFO_HEADER );
  660. pPSUIInfoHdr->Flags = PSUIHDRF_USEHICON;
  661. pPSUIInfoHdr->pTitle = (LPTSTR)(LPCTSTR)_strTitle;
  662. pPSUIInfoHdr->hInst = ghInst;
  663. pPSUIInfoHdr->hIcon = _pPrinterData->shSmallIcon();
  664. pPSUIInfoHdr->hWndParent = _pPrinterData->hwnd();
  665. return TRUE;
  666. }
  667. /*++
  668. Routine Name:
  669. bBuildDriverPages
  670. Routine Description:
  671. Builds the driver defined property sheets. Also get the driver
  672. defined icon.
  673. Arguments:
  674. pCPSUIInfo - Pointer to common ui property sheet info header,
  675. Return Value:
  676. TRUE success, FALSE error occurred.
  677. --*/
  678. BOOL
  679. TPrinterPropertySheetManager::
  680. bBuildDriverPages(
  681. IN PPROPSHEETUI_INFO pCPSUIInfo
  682. )
  683. {
  684. //
  685. // Build the device header and instruct compstui to chain the
  686. // call to the printer driver ui.
  687. //
  688. ZeroMemory ( &_dph, sizeof( _dph ) );
  689. _dph.cbSize = sizeof( _dph );
  690. _dph.hPrinter = _pPrinterData->hPrinter();
  691. _dph.pszPrinterName = (LPTSTR)(LPCTSTR)_pPrinterData->strCurrentPrinterName();
  692. _dph.Flags = ( _pPrinterData->bAdministrator( ) ) ? (WORD)0 : (WORD)DPS_NOPERMISSION;
  693. //
  694. // Add the driver defined property sheets.
  695. //
  696. _hDrvPropSheet = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
  697. CPSFUNC_ADD_PFNPROPSHEETUI,
  698. (LPARAM)DevicePropertySheets,
  699. (LPARAM)&_dph );
  700. //
  701. // Validate the handle returned by compstui.
  702. //
  703. if( !bValidCompstuiHandle( _hDrvPropSheet ) ){
  704. DBGMSG( DBG_TRACE, ( "TPrinterPropertySheetManager CPSFUNC_ADD_PFNPROPSHEETUI failed with %d.\n", _hDrvPropSheet ) );
  705. return FALSE;
  706. }
  707. return TRUE;
  708. }
  709. /*++
  710. Routine Name:
  711. bCheckToBuildDriverPages
  712. Routine Description:
  713. Checks to build the driver pages and asks the user
  714. to install a driver locally if necessary.
  715. Arguments:
  716. pCPSUIInfo - pointer to compstui info header.
  717. Return Value:
  718. Nothing.
  719. --*/
  720. BOOL
  721. TPrinterPropertySheetManager::
  722. bCheckToBuildDriverPages(
  723. IN PPROPSHEETUI_INFO pCPSUIInfo
  724. )
  725. {
  726. //
  727. // Build the driver specific pages.
  728. //
  729. TStatusB bStatus;
  730. bStatus DBGCHK = bBuildDriverPages( pCPSUIInfo );
  731. if( !bStatus )
  732. {
  733. DWORD dwLastErr = GetLastError();
  734. if( ERROR_KM_DRIVER_BLOCKED == dwLastErr )
  735. {
  736. iMessage( _pPrinterData->hwnd(),
  737. IDS_ERR_PRINTER_PROP_TITLE,
  738. IDS_NODRIVERUI_BAD_KMDRIVER,
  739. MB_OK|MB_ICONINFORMATION,
  740. kMsgNone,
  741. NULL,
  742. static_cast<LPCTSTR>(_pPrinterData->strDriverName()) );
  743. }
  744. else
  745. {
  746. //
  747. // Assume the driver doesn't exists - ask the user if they want to install
  748. // the printer driver now.
  749. //
  750. bStatus DBGCHK = bInstallDriverPage();
  751. //
  752. // If the driver was installed attempt to load the
  753. // driver pages again. If this fails we silently fail, since
  754. // we told the user already that only spooler properties
  755. // will be displayed.
  756. //
  757. if( bStatus )
  758. {
  759. bStatus DBGCHK = bBuildDriverPages( pCPSUIInfo );
  760. } else
  761. {
  762. _pPrinterData->_bDriverPagesNotLoaded = TRUE;
  763. }
  764. }
  765. }
  766. return bStatus;
  767. }
  768. /*++
  769. Routine Name:
  770. bRelaseDriverPages
  771. Routine Description:
  772. Release any driver defined pages.
  773. Arguments:
  774. pCPSUIInfo - pointer to compstui info header.
  775. Return Value:
  776. Nothing.
  777. --*/
  778. VOID
  779. TPrinterPropertySheetManager::
  780. vReleaseDriverPages(
  781. IN PPROPSHEETUI_INFO pCPSUIInfo
  782. )
  783. {
  784. //
  785. // Insure we have a valid compstui handle.
  786. //
  787. if( bValidCompstuiHandle( _hDrvPropSheet ) ) {
  788. LONG_PTR lResult;
  789. DWORD dwPageCount;
  790. //
  791. // Delete the currently help driver pages.
  792. //
  793. lResult = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
  794. CPSFUNC_DELETE_HCOMPROPSHEET,
  795. (LPARAM)_hDrvPropSheet,
  796. (LPARAM)&dwPageCount );
  797. if( lResult <= 0 ){
  798. DBGMSG( DBG_TRACE, ( "TPrinterPropertySheetManager CPSFUNC_REMOVE_PROPSHEETPAGE failed with %d\n", lResult ) );
  799. } else {
  800. _hDrvPropSheet = 0;
  801. }
  802. }
  803. }
  804. /*++
  805. Routine Name:
  806. bGetDriverPageHandles
  807. Routine Description:
  808. Get the pages handle of the driver pages from common ui.
  809. Arguments:
  810. pCPSUIInfo - pointer to compstui info header.
  811. pcPages - pointer where to return the number of pages.
  812. pphPage - pointer where to return pointer to array of hpages.
  813. Return Value:
  814. TRUE success FALSE failure.
  815. --*/
  816. BOOL
  817. TPrinterPropertySheetManager::
  818. bGetDriverPageHandles(
  819. IN PPROPSHEETUI_INFO pCPSUIInfo,
  820. OUT DWORD *pcPages,
  821. OUT HPROPSHEETPAGE **pphPages
  822. )
  823. {
  824. DBGMSG( DBG_TRACE, ( "TPrinterPropertySheetManager::bGetDriverPageHandles.\n" ) );
  825. BOOL bStatus = FALSE;
  826. ULONG_PTR cPages;
  827. HPROPSHEETPAGE *phPages;
  828. cPages = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
  829. CPSFUNC_GET_PAGECOUNT,
  830. (LPARAM)_hDrvPropSheet,
  831. 0 );
  832. DBGMSG( DBG_TRACE, ( "bGetDriverPageHandles CPSFUNC_GET_PAGECOUNT pages %d.\n", cPages ) );
  833. if( cPages )
  834. {
  835. phPages = new HPROPSHEETPAGE[(UINT)cPages];
  836. SPLASSERT( phPages );
  837. if( phPages )
  838. {
  839. cPages = pCPSUIInfo->pfnComPropSheet( (HANDLE)_hDrvPropSheet,
  840. CPSFUNC_GET_HPSUIPAGES,
  841. (LPARAM)phPages,
  842. (LPARAM)cPages );
  843. DBGMSG( DBG_TRACE, ( "bGetDriverPageHandles CPSFUNC_GET_HPSUIPAGES pages %d First handle %x.\n", cPages, phPages[0] ) );
  844. if( cPages )
  845. {
  846. *pcPages = (UINT)cPages;
  847. *pphPages = phPages;
  848. bStatus = TRUE;
  849. }
  850. }
  851. }
  852. return bStatus;
  853. }
  854. /*++
  855. Routine Name:
  856. bDisplaySecurityTab
  857. Routine Description:
  858. Displayes only the security tab which is a shell extension.
  859. Arguments:
  860. hwnd - handle to the parent window.
  861. Return Value:
  862. Nothing.
  863. --*/
  864. BOOL
  865. TPrinterPropertySheetManager::
  866. bDisplaySecurityTab(
  867. IN HWND hwnd
  868. )
  869. {
  870. LPPROPSHEETHEADER pPropSheetHeader = NULL;
  871. BOOL bStatus = FALSE;
  872. //
  873. // Allocate a property sheet header to get any shell extension pages.
  874. //
  875. if( _ShellExtPages.bCreatePropSheetHeader( &pPropSheetHeader ) )
  876. {
  877. //
  878. // Fill in the property sheet header.
  879. //
  880. Printer_AddPrinterPropPages( _pPrinterData->strPrinterName(), pPropSheetHeader );
  881. //
  882. // Check if any pages were loaded. This should not happen, at
  883. // a minimum the security tab should be displayed.
  884. //
  885. if( pPropSheetHeader->nPages )
  886. {
  887. //
  888. // Warn the user they will only see the security tab.
  889. //
  890. iMessage( hwnd,
  891. IDS_ERR_PRINTER_PROP_TITLE,
  892. IDS_ERR_NO_DEVICE_SEC_OPTIONS,
  893. MB_OK|MB_ICONEXCLAMATION,
  894. kMsgNone,
  895. NULL );
  896. //
  897. // Create the property sheet title.
  898. //
  899. bCreateTitle();
  900. //
  901. // Set the property sheet header information.
  902. //
  903. pPropSheetHeader->dwSize = sizeof( *pPropSheetHeader );
  904. pPropSheetHeader->hwndParent = hwnd;
  905. pPropSheetHeader->dwFlags = 0;
  906. pPropSheetHeader->pszIcon = MAKEINTRESOURCE( IDI_PRINTER );
  907. pPropSheetHeader->nStartPage = 0;
  908. pPropSheetHeader->hInstance = ghInst;
  909. pPropSheetHeader->pszCaption = _strTitle;
  910. //
  911. // Display the property sheets.
  912. //
  913. if( PropertySheet( pPropSheetHeader ) != -1 )
  914. {
  915. bStatus = TRUE;
  916. }
  917. else
  918. {
  919. vShowResourceError( hwnd );
  920. }
  921. }
  922. else
  923. {
  924. //
  925. // Inform the user an error occurred showing printer properties.
  926. //
  927. iMessage( hwnd,
  928. IDS_ERR_PRINTER_PROP_TITLE,
  929. IDS_ERR_PRINTER_PROP,
  930. MB_OK|MB_ICONSTOP,
  931. kMsgGetLastError,
  932. NULL );
  933. }
  934. //
  935. // Ensure we release the property sheet header.
  936. //
  937. _ShellExtPages.vDestroyPropSheetHeader( pPropSheetHeader );
  938. }
  939. return bStatus;
  940. }
  941. /********************************************************************
  942. Shell Extension property pages - public functions.
  943. ********************************************************************/
  944. /*++
  945. Routine Name:
  946. TShellExtPages
  947. Routine Description:
  948. Constructor.
  949. Arguments:
  950. None.
  951. Return Value:
  952. Nothing.
  953. --*/
  954. TShellExtPages::
  955. TShellExtPages(
  956. VOID
  957. ) : _hGroupHandle( 0 )
  958. {
  959. DBGMSG( DBG_TRACE, ( "TShellExtPages ctor.\n" ) );
  960. }
  961. /*++
  962. Routine Name:
  963. TShellExtPages
  964. Routine Description:
  965. Destructor.
  966. Arguments:
  967. None.
  968. Return Value:
  969. Nothing.
  970. --*/
  971. TShellExtPages::
  972. ~TShellExtPages(
  973. VOID
  974. )
  975. {
  976. DBGMSG( DBG_TRACE, ( "TShellExtPages dtor.\n" ) );
  977. //
  978. // This should never happen.
  979. //
  980. SPLASSERT( !_hGroupHandle );
  981. }
  982. /*++
  983. Routine Name:
  984. bCreate
  985. Routine Description:
  986. Creates the shell extension property pages.
  987. Arguments:
  988. Pointer to common ui information structure.
  989. Pointer to printer name name to get sheets for.
  990. Return Value:
  991. TRUE if sheets found, FALSE no sheets found.
  992. --*/
  993. BOOL
  994. TShellExtPages::
  995. bCreate(
  996. IN PPROPSHEETUI_INFO pCPSUIInfo,
  997. IN const TString &strPrinterName
  998. )
  999. {
  1000. DBGMSG( DBG_TRACE, ( "TShellExtPages create.\n" ) );
  1001. BOOL bStatus = FALSE;
  1002. LPPROPSHEETHEADER pPropSheetHeader = NULL;
  1003. //
  1004. // Allocate a property sheet header to get any shell extension pages.
  1005. //
  1006. if( bCreatePropSheetHeader( &pPropSheetHeader ) ){
  1007. //
  1008. // Get the vender defined prop pages.
  1009. //
  1010. Printer_AddPrinterPropPages( strPrinterName, pPropSheetHeader );
  1011. //
  1012. // Add the shell extension property sheets pages.
  1013. //
  1014. bStatus = bCreatePages( pCPSUIInfo, pPropSheetHeader );
  1015. }
  1016. //
  1017. // Release the property sheet header. This can be destroyed, because common ui
  1018. // will store the property sheet handles under the concept of a group handle. See
  1019. // common ui header file for more details.
  1020. //
  1021. vDestroyPropSheetHeader( pPropSheetHeader );
  1022. return bStatus;
  1023. }
  1024. /*++
  1025. Routine Name:
  1026. vDestroy
  1027. Routine Description:
  1028. Destroys any information used by the TShellExt object.
  1029. Arguments:
  1030. Pointer to common ui information structure.
  1031. Return Value:
  1032. Nothing.
  1033. --*/
  1034. VOID
  1035. TShellExtPages::
  1036. vDestroy(
  1037. IN PPROPSHEETUI_INFO pCPSUIInfo
  1038. )
  1039. {
  1040. DBGMSG( DBG_TRACE, ( "TShellExtPages vDestroy.\n" ) );
  1041. vDestroyPages( pCPSUIInfo );
  1042. }
  1043. /*++
  1044. Routine Name:
  1045. hPropSheet
  1046. Routine Description:
  1047. Returns the prop sheet handle.
  1048. Arguments:
  1049. Nothing.
  1050. Return Value:
  1051. --*/
  1052. HANDLE
  1053. TShellExtPages::
  1054. hPropSheet(
  1055. VOID
  1056. ) const
  1057. {
  1058. return reinterpret_cast<HANDLE>(_hGroupHandle);
  1059. }
  1060. /********************************************************************
  1061. Shell Extension property pages - private functions.
  1062. ********************************************************************/
  1063. BOOL
  1064. TShellExtPages::
  1065. bCreatePropSheetHeader(
  1066. IN LPPROPSHEETHEADER *ppPropSheetHeader
  1067. )
  1068. {
  1069. DBGMSG( DBG_TRACE, ( "TShellExtPages bCreatePropSheetHeader.\n" ) );
  1070. PROPSHEETHEADER *pPropSheetHeader = NULL;
  1071. BOOL bStatus = FALSE;
  1072. UINT uHeaderSize = 0;
  1073. //
  1074. // Calculate the header size, Header size plus the max size of the array
  1075. // of property sheets handles.
  1076. //
  1077. uHeaderSize = sizeof( PROPSHEETHEADER ) + sizeof( HPROPSHEETPAGE ) * MAXPROPPAGES;
  1078. //
  1079. // Allocate the property sheet header and handle array.
  1080. //
  1081. pPropSheetHeader = (PROPSHEETHEADER *)AllocMem( uHeaderSize );
  1082. //
  1083. // If valid property sheet header and handle array was aquired, then
  1084. // clear the memory, and set up the handle arrary pointer.
  1085. //
  1086. if( pPropSheetHeader ){
  1087. ZeroMemory( pPropSheetHeader, uHeaderSize );
  1088. pPropSheetHeader->phpage = (HPROPSHEETPAGE *)(pPropSheetHeader+1);
  1089. *ppPropSheetHeader = pPropSheetHeader;
  1090. bStatus = TRUE;
  1091. }
  1092. return bStatus;
  1093. }
  1094. VOID
  1095. TShellExtPages::
  1096. vDestroyPropSheetHeader(
  1097. IN LPPROPSHEETHEADER pPropSheetHeader
  1098. )
  1099. {
  1100. DBGMSG( DBG_TRACE, ( "TShellExtPages vDestroyPropSheetHeader.\n" ) );
  1101. FreeMem( pPropSheetHeader );
  1102. }
  1103. BOOL
  1104. TShellExtPages::
  1105. bCreatePages(
  1106. IN PPROPSHEETUI_INFO pCPSUIInfo,
  1107. IN LPPROPSHEETHEADER pPropSheetHeader
  1108. )
  1109. {
  1110. DBGMSG( DBG_TRACE, ( "TShellExtPages bCreatePages.\n" ) );
  1111. BOOL bStatus = TRUE;
  1112. ULONG_PTR hResult;
  1113. INSERTPSUIPAGE_INFO InsertInfo;
  1114. //
  1115. // If there are no shell extenstion pages to create.
  1116. //
  1117. if( !pPropSheetHeader->nPages ){
  1118. DBGMSG( DBG_TRACE, ( "TShellExtPages no pages to create.\n" ) );
  1119. bStatus = FALSE;
  1120. }
  1121. if( bStatus ){
  1122. //
  1123. // Create the insert info.
  1124. //
  1125. InsertInfo.cbSize = sizeof( InsertInfo );
  1126. InsertInfo.Type = PSUIPAGEINSERT_GROUP_PARENT;
  1127. InsertInfo.Mode = INSPSUIPAGE_MODE_LAST_CHILD;
  1128. InsertInfo.dwData1 = 0;
  1129. InsertInfo.dwData2 = 0;
  1130. InsertInfo.dwData3 = 0;
  1131. //
  1132. // Create a group parent handle.
  1133. //
  1134. _hGroupHandle = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
  1135. CPSFUNC_INSERT_PSUIPAGE,
  1136. 0,
  1137. (LPARAM)&InsertInfo );
  1138. if( !TPropertySheetManager::bValidCompstuiHandle( _hGroupHandle ) ){
  1139. DBGMSG( DBG_WARN, ( "TShellExtPages PSUIPAGEINSERT_GROUP_PARENT failed with %d.\n", _hGroupHandle ) );
  1140. bStatus = FALSE;
  1141. }
  1142. }
  1143. if( bStatus ){
  1144. //
  1145. // Add all supplied shell extension property sheet pages.
  1146. //
  1147. for( UINT i = 0; i < pPropSheetHeader->nPages ; i++ ){
  1148. InsertInfo.Type = PSUIPAGEINSERT_HPROPSHEETPAGE;
  1149. InsertInfo.Mode = INSPSUIPAGE_MODE_LAST_CHILD;
  1150. InsertInfo.dwData1 = (ULONG_PTR)pPropSheetHeader->phpage[i];
  1151. hResult = pCPSUIInfo->pfnComPropSheet( (HANDLE)_hGroupHandle,
  1152. CPSFUNC_INSERT_PSUIPAGE,
  1153. 0,
  1154. (LPARAM)&InsertInfo );
  1155. if( !TPropertySheetManager::bValidCompstuiHandle( hResult ) ){
  1156. DBGMSG( DBG_WARN, ( "TShellExtPages PSUIPAGEINSERT_HPROPSHEETPAGE failed with %d.\n", hResult ) );
  1157. bStatus = FALSE;
  1158. break;
  1159. } else {
  1160. DBGMSG( DBG_TRACE, ( "TShellExtPages page added\n" ) );
  1161. }
  1162. }
  1163. }
  1164. //
  1165. // If the pages failed to create destroy any inconsistant resources.
  1166. //
  1167. if( !bStatus ){
  1168. vDestroyPages( pCPSUIInfo );
  1169. }
  1170. return bStatus;
  1171. }
  1172. VOID
  1173. TShellExtPages::
  1174. vDestroyPages(
  1175. IN PPROPSHEETUI_INFO pCPSUIInfo
  1176. )
  1177. {
  1178. DBGMSG( DBG_TRACE, ( "TShellExtPages vDestroyPages.\n" ) );
  1179. LONG_PTR lResult;
  1180. DWORD dwPageCount;
  1181. //
  1182. // If the vendor pages have not been created.
  1183. //
  1184. if( !_hGroupHandle ){
  1185. DBGMSG( DBG_TRACE, ( "TShellExtPages no pages.\n" ) );
  1186. return;
  1187. }
  1188. //
  1189. // Release the group handle.
  1190. //
  1191. if( pCPSUIInfo ){
  1192. lResult = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
  1193. CPSFUNC_DELETE_HCOMPROPSHEET,
  1194. (LPARAM)_hGroupHandle,
  1195. (LPARAM)&dwPageCount );
  1196. if( lResult <= 0 ){
  1197. DBGMSG( DBG_WARN, ( "TShellExtPages failed to delete hGroupHandle with %d.\n", lResult ) );
  1198. } else {
  1199. DBGMSG( DBG_TRACE, ( "TShellExtPages release %d pages.\n", dwPageCount ) );
  1200. }
  1201. }
  1202. //
  1203. // Mark the group handle as deleted.
  1204. //
  1205. _hGroupHandle = 0;
  1206. }