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.

6014 lines
150 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. All rights reserved.
  4. Module Name:
  5. prtprop.cxx
  6. Abstract:
  7. Holds Printer properties.
  8. Author:
  9. Albert Ting (AlbertT) 15-Aug-1995
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. #include "lmerr.h"
  15. #include "prshtp.h"
  16. #include "time.hxx"
  17. #include "psetup.hxx"
  18. #include "drvsetup.hxx"
  19. #include "instarch.hxx"
  20. #include "portdlg.hxx"
  21. #include "sepdlg.hxx"
  22. #include "procdlg.hxx"
  23. #include "portslv.hxx"
  24. #include "driverif.hxx"
  25. #include "driverlv.hxx"
  26. #include "dsinterf.hxx"
  27. #include "prtprop.hxx"
  28. #include "propmgr.hxx"
  29. #include "prtprops.hxx"
  30. #include "drvsetup.hxx"
  31. #include "archlv.hxx"
  32. #include "detect.hxx"
  33. #include "setup.hxx"
  34. #include "tstpage.hxx"
  35. #include "prtshare.hxx"
  36. #include "drvver.hxx"
  37. #include "docdef.hxx"
  38. #include "persist.hxx"
  39. #include "prndata.hxx"
  40. #include "physloc.hxx"
  41. #include "findloc.hxx"
  42. #include <shgina.h> // ILocalMachine, ILogonUser
  43. #if DBG
  44. //#define DBG_PROPSINFO DBG_INFO
  45. #define DBG_PROPSINFO DBG_NONE
  46. #endif
  47. /********************************************************************
  48. Message map used after a set printer call.
  49. ********************************************************************/
  50. MSG_ERRMAP gaMsgErrMapSetPrinter[] = {
  51. ERROR_INVALID_PRINTER_STATE, IDS_ERR_INVALID_PRINTER_STATE,
  52. NERR_DuplicateShare, IDS_ERR_DUPLICATE_SHARE,
  53. ERROR_INVALID_SHARENAME, IDS_ERR_INVALID_SHARENAME,
  54. ERROR_ALREADY_EXISTS, IDS_ERR_DUPLICATED_DS_ITEM,
  55. ERROR_IO_PENDING, IDS_ERR_LIST_IN_DIRECTORY,
  56. 0, 0
  57. };
  58. /********************************************************************
  59. Forward Decl.
  60. ********************************************************************/
  61. INT_PTR
  62. WarningDlgProc(
  63. IN HWND hWnd,
  64. IN UINT msg,
  65. IN WPARAM wParam,
  66. IN LPARAM lParam
  67. );
  68. /********************************************************************
  69. Public interface.
  70. ********************************************************************/
  71. VOID
  72. vPrinterPropPagesWOW64(
  73. IN HWND hwnd,
  74. IN LPCTSTR pszPrinterName,
  75. IN INT nCmdShow,
  76. IN LPARAM lParam
  77. )
  78. /*++
  79. Routine Description:
  80. WOW64 version.
  81. see vPrinterPropPages below.
  82. Arguments:
  83. see vPrinterPropPages below.
  84. Return Value:
  85. --*/
  86. {
  87. //
  88. // This function potentially may load the driver UI so we call a private API
  89. // exported by winspool.drv, which will RPC the call to a special 64 bit surrogate
  90. // process where the 64 bit driver can be loaded.
  91. //
  92. CDllLoader dll(TEXT("winspool.drv"));
  93. ptr_PrintUIPrinterPropPages pfnPrintUIPrinterPropPages =
  94. (ptr_PrintUIPrinterPropPages )dll.GetProcAddress(ord_PrintUIPrinterPropPages);
  95. if( pfnPrintUIPrinterPropPages )
  96. {
  97. pfnPrintUIPrinterPropPages( hwnd, pszPrinterName, nCmdShow, lParam );
  98. }
  99. }
  100. VOID
  101. vPrinterPropPagesNative(
  102. IN HWND hwnd,
  103. IN LPCTSTR pszPrinterName,
  104. IN INT nCmdShow,
  105. IN LPARAM lParam
  106. )
  107. /*++
  108. Routine Description:
  109. Native version.
  110. see vPrinterPropPages below.
  111. Arguments:
  112. see vPrinterPropPages below.
  113. Return Value:
  114. --*/
  115. {
  116. BOOL bModal = FALSE;
  117. DWORD dwSheetIndex = (DWORD)-1;
  118. LPCTSTR pszSheetName = NULL;
  119. //
  120. // If this page was launched by name then the lParam points to the tab name.
  121. //
  122. if( HIWORD( lParam ) )
  123. {
  124. pszSheetName = (LPCTSTR)lParam;
  125. }
  126. //
  127. // Only if the sheet is launched by index can optionaly be modal.
  128. //
  129. else
  130. {
  131. dwSheetIndex = LOWORD( lParam ) & 0x00FF;
  132. bModal = LOWORD( lParam ) & 0xFF00;
  133. }
  134. (VOID)dwPrinterPropPagesInternal( hwnd,
  135. pszPrinterName,
  136. pszSheetName,
  137. dwSheetIndex,
  138. nCmdShow,
  139. bModal,
  140. NULL );
  141. }
  142. VOID
  143. vPrinterPropPages(
  144. IN HWND hwnd,
  145. IN LPCTSTR pszPrinterName,
  146. IN INT nCmdShow,
  147. IN LPARAM lParam
  148. )
  149. /*++
  150. Routine Description:
  151. This function opens the property sheet of specified printer.
  152. We can't guarentee that this propset will perform all lengthy
  153. operations in a worker thread (we synchronously call things like
  154. ConfigurePort). Therefore, we spawn off a separate thread to
  155. handle printer properties.
  156. Arguments:
  157. hWnd - Specifies the parent window for errors on creation.
  158. pszPrinter - Specifies the printer name (e.g., "My HP LaserJet IIISi").
  159. nCmdShow -
  160. lParam - Specified either a sheet number or sheet name to open. If the high
  161. word of this parameter is non zero it is assumed that this parameter
  162. is a pointer the name of the sheet to open. Otherwize the this
  163. parameter is the zero based index of which sheet to open.
  164. Return Value:
  165. --*/
  166. {
  167. if( IsRunningWOW64() )
  168. {
  169. vPrinterPropPagesWOW64( hwnd, pszPrinterName, nCmdShow, lParam );
  170. }
  171. else
  172. {
  173. vPrinterPropPagesNative( hwnd, pszPrinterName, nCmdShow, lParam );
  174. }
  175. }
  176. /*++
  177. Routine Description:
  178. This function opens the property sheet of specified printer.
  179. We can't guarentee that this propset will perform all lengthy
  180. operations in a worker thread (we synchronously call things like
  181. ConfigurePort). Therefore, we spawn off a separate thread to
  182. handle printer properties.
  183. Arguments:
  184. hWnd - Specifies the parent window for errors on creation.
  185. pDataObject - Pointer to an IDataObject passed to my the caller.
  186. Return Value:
  187. ERROR_SUCCESS UI displayed, ERROR_ACCESS_DENIED failure occurred not UI.
  188. --*/
  189. DWORD
  190. dwPrinterPropPages(
  191. IN HWND hwnd,
  192. IN IDataObject *pDataObject,
  193. IN PBOOL pbDisplayed
  194. )
  195. {
  196. FORMATETC fmte = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  197. STGMEDIUM medium = { TYMED_NULL, NULL, NULL };
  198. UINT cfDsObjectNames = 0;
  199. LPDSOBJECTNAMES pObjectNames = NULL;
  200. DWORD dwReturn = ERROR_ACCESS_DENIED;
  201. TString strName;
  202. //
  203. // Get the DS object clipboard format.
  204. //
  205. fmte.cfFormat = static_cast<USHORT>( RegisterClipboardFormat( CFSTR_DSOBJECTNAMES ) );
  206. //
  207. // Get the data from the provided IDataObject
  208. //
  209. if( SUCCEEDED(pDataObject->GetData(&fmte, &medium)) )
  210. {
  211. //
  212. // Fetch the object name
  213. //
  214. pObjectNames = (LPDSOBJECTNAMES)medium.hGlobal;
  215. if( pObjectNames )
  216. {
  217. for( UINT i = 0 ; i < pObjectNames->cItems ; i++ )
  218. {
  219. TStatusB bStatus;
  220. //
  221. // Get the Ds object path.
  222. //
  223. bStatus DBGCHK = strName.bUpdate( (LPTSTR)(((LPBYTE)pObjectNames)+pObjectNames->aObjects[i].offsetName) );
  224. if( bStatus )
  225. {
  226. TStatus Status;
  227. //
  228. // Bring up printer properties.
  229. //
  230. Status DBGCHK = dwPrinterPropPages( hwnd, strName, NULL );
  231. //
  232. // Set the return value.
  233. //
  234. dwReturn = Status;
  235. }
  236. }
  237. }
  238. //
  239. // Release the storage medium.
  240. //
  241. ReleaseStgMedium( &medium );
  242. }
  243. return dwReturn;
  244. }
  245. /*++
  246. Routine Description:
  247. This function opens the property sheet of specified printer.
  248. We can't guarentee that this propset will perform all lengthy
  249. operations in a worker thread (we synchronously call things like
  250. ConfigurePort). Therefore, we spawn off a separate thread to
  251. handle printer properties.
  252. Arguments:
  253. hWnd - Specifies the parent window for errors on creation.
  254. pDataObject - Pointer to an IDataObject passed to my the caller.
  255. Return Value:
  256. ERROR_SUCCESS UI displayed, ERROR_ACCESS_DENIED failure occurred not UI.
  257. --*/
  258. DWORD
  259. dwPrinterPropPages(
  260. IN HWND hwnd,
  261. IN LPCTSTR pszDsPath,
  262. IN PBOOL pbDisplayed
  263. )
  264. {
  265. SPLASSERT( pszDsPath );
  266. VARIANT Variant;
  267. TDirectoryService Di;
  268. IADs *pDsObject = NULL;
  269. HRESULT hr = E_FAIL;
  270. DWORD dwReturn = ERROR_ACCESS_DENIED;
  271. //
  272. // Initialize the displayed flag.
  273. //
  274. if( pbDisplayed )
  275. {
  276. *pbDisplayed = FALSE;
  277. }
  278. if( VALID_OBJ( Di ) )
  279. {
  280. //
  281. // Get the ads object interface pointer.
  282. //
  283. hr = Di.ADsGetObject( const_cast<LPTSTR>( pszDsPath ),
  284. IID_IADs,
  285. reinterpret_cast<LPVOID*>( &pDsObject ) );
  286. if( SUCCEEDED( hr ) )
  287. {
  288. //
  289. // Initialize the variant for getting the object UNC property.
  290. //
  291. VariantInit(&Variant);
  292. //
  293. // Get the objects uNCName
  294. //
  295. hr = pDsObject->Get( SPLDS_UNC_NAME, &Variant );
  296. if( SUCCEEDED( hr ) && Variant.vt == VT_BSTR && Variant.bstrVal && Variant.bstrVal[0] )
  297. {
  298. VARIANT versionVariant;
  299. VariantInit(&versionVariant);
  300. //
  301. // Get the objects uNCName
  302. //
  303. hr = pDsObject->Get( TEXT("versionNumber"), &versionVariant );
  304. DBGMSG( DBG_TRACE, ( "dwPrinterPropPages: printerObject vesrion %d.\n", versionVariant.lVal ) );
  305. if( SUCCEEDED( hr ) && versionVariant.vt == VT_I4 && versionVariant.lVal >= 2 )
  306. {
  307. //
  308. // At this point we know we will display some UI, either the dialog or an error message.
  309. //
  310. if( pbDisplayed )
  311. {
  312. *pbDisplayed = TRUE;
  313. }
  314. //
  315. // Attempt to display the dialog.
  316. //
  317. dwReturn = dwPrinterPropPagesInternal( hwnd, Variant.bstrVal, 0, 0, SW_SHOW, FALSE, pszDsPath );
  318. }
  319. else
  320. {
  321. //
  322. // If the caller has requested information as to wether we can display
  323. // printer properties then indicate we cannot at this point, otherwise
  324. // let the user know with a message box.
  325. //
  326. if( pbDisplayed )
  327. {
  328. dwReturn = ERROR_SUCCESS;
  329. }
  330. else
  331. {
  332. //
  333. // Display an error message indicating that properties cannot be displayed.
  334. //
  335. iMessage( hwnd,
  336. IDS_ERR_PRINTER_PROP_TITLE,
  337. IDS_ERR_PRINTER_PROP_NONE,
  338. MB_OK|MB_ICONSTOP,
  339. kMsgNone,
  340. NULL );
  341. }
  342. }
  343. //
  344. // Release the version variant.
  345. //
  346. VariantClear( &versionVariant );
  347. }
  348. //
  349. // Release the variant.
  350. //
  351. VariantClear( &Variant );
  352. }
  353. }
  354. //
  355. // Note this routine could fail and still display UI.
  356. // For example an an error message generated by printer properties
  357. // because the thread could not start.
  358. //
  359. return dwReturn;
  360. }
  361. /********************************************************************
  362. Private internal interface.
  363. ********************************************************************/
  364. DWORD
  365. dwPrinterPropPagesInternal(
  366. IN HWND hwnd,
  367. IN LPCTSTR pszPrinterName,
  368. IN LPCTSTR pszSheetName,
  369. IN DWORD dwSheetIndex,
  370. IN INT nCmdShow,
  371. IN BOOL bModal,
  372. IN LPCTSTR pszDsPath
  373. )
  374. {
  375. LPCTSTR pszServer;
  376. LPCTSTR pszPrinter;
  377. TCHAR szScratch[kPrinterBufMax];
  378. //
  379. // Split the printer name into its components.
  380. //
  381. vPrinterSplitFullName( szScratch,
  382. pszPrinterName,
  383. &pszServer,
  384. &pszPrinter );
  385. //
  386. // Get the local machine name.
  387. //
  388. TString strMachineName;
  389. TStatusB bStatus;
  390. bStatus DBGCHK = bGetMachineName( strMachineName );
  391. //
  392. // If the server name matches this machine name then strip off the
  393. // server name form the printer name, when creating the singleton window.
  394. //
  395. if( !_tcsicmp( pszServer, strMachineName ) ) {
  396. pszPrinterName = pszPrinter;
  397. }
  398. TPrinterData* pPrinterData = new TPrinterData( pszPrinterName,
  399. nCmdShow,
  400. pszSheetName,
  401. dwSheetIndex,
  402. hwnd,
  403. bModal,
  404. pszDsPath );
  405. if( !VALID_PTR( pPrinterData )){
  406. goto Fail;
  407. }
  408. //
  409. // If lparam is greater than 64k then dialog is modal.
  410. //
  411. if( bModal ) {
  412. TPrinterProp::iPrinterPropPagesProc( pPrinterData );
  413. return ERROR_SUCCESS;
  414. }
  415. //
  416. // Create the thread which handles the UI. vPrinterPropPages adopts
  417. // pPrinterData.
  418. //
  419. DWORD dwIgnore;
  420. HANDLE hThread;
  421. hThread = TSafeThread::Create( NULL,
  422. 0,
  423. (LPTHREAD_START_ROUTINE)TPrinterProp::iPrinterPropPagesProc,
  424. pPrinterData,
  425. 0,
  426. &dwIgnore );
  427. if( !hThread ){
  428. goto Fail;
  429. }
  430. CloseHandle( hThread );
  431. return ERROR_SUCCESS;
  432. Fail:
  433. if( !pPrinterData ){
  434. vShowResourceError( hwnd );
  435. } else {
  436. iMessage( hwnd,
  437. IDS_ERR_PRINTER_PROP_TITLE,
  438. IDS_ERR_PRINTER_PROP,
  439. MB_OK|MB_ICONSTOP,
  440. kMsgGetLastError,
  441. NULL );
  442. }
  443. delete pPrinterData;
  444. return ERROR_ACCESS_DENIED;
  445. }
  446. /********************************************************************
  447. Worker thread that handles printer properties.
  448. ********************************************************************/
  449. INT
  450. TPrinterProp::
  451. iPrinterPropPagesProc(
  452. IN TPrinterData* pPrinterData ADOPT
  453. )
  454. {
  455. BOOL bStatus = FALSE;
  456. INT Status = ERROR_SUCCESS;
  457. //
  458. // Register the link window class
  459. //
  460. if (LinkWindow_RegisterClass())
  461. {
  462. //
  463. // We are going to use ole.
  464. //
  465. CoInitialize( NULL );
  466. //
  467. // Increment our reference count.
  468. //
  469. pPrinterData->vIncRef();
  470. //
  471. // Register this windows with the shell's unique window handler.
  472. //
  473. bStatus = pPrinterData->bRegisterWindow( PRINTER_PIDL_TYPE_PROPERTIES );
  474. if( bStatus ){
  475. //
  476. // If the windows is already present.
  477. //
  478. if( pPrinterData->bIsWindowPresent() ){
  479. DBGMSG( DBG_TRACE, ( "iPrinterPropPagesProc: currently running.\n" ) );
  480. Status = ERROR_SUCCESS;
  481. bStatus = FALSE;
  482. }
  483. }
  484. if( bStatus ){
  485. //
  486. // Create the printer sheets and check if valid.
  487. //
  488. TPrinterPropertySheetManager *pPrinterSheets = new TPrinterPropertySheetManager( pPrinterData );
  489. if( pPrinterSheets ) {
  490. //
  491. // Save the pointer to the property sheet manager.
  492. //
  493. pPrinterData->pPrinterPropertySheetManager() = pPrinterSheets;
  494. //
  495. // Check if we have a valid object.
  496. //
  497. if( VALID_PTR( pPrinterSheets )) {
  498. //
  499. // Note: Display Pages will show any errors message.
  500. //
  501. bStatus = pPrinterSheets->bDisplayPages();
  502. } else {
  503. vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
  504. Status = GetLastError();
  505. }
  506. } else {
  507. vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
  508. Status = GetLastError();
  509. }
  510. }
  511. //
  512. // Ensure we release the printer data.
  513. //
  514. pPrinterData->cDecRef();
  515. //
  516. // Balance the CoInitalize
  517. //
  518. CoUninitialize();
  519. //
  520. // Unregister the link window class
  521. //
  522. LinkWindow_UnregisterClass(ghInst);
  523. }
  524. else
  525. {
  526. //
  527. // unable to register the link window class - this is fatal, so we just bail
  528. //
  529. DBGMSG(DBG_WARN, ("LinkWindow_RegisterClass() failed - unable to register link window class\n"));
  530. vShowResourceError(pPrinterData->hwnd());
  531. }
  532. return Status;
  533. }
  534. /********************************************************************
  535. TPrinterData.
  536. ********************************************************************/
  537. TPrinterData::
  538. TPrinterData(
  539. IN LPCTSTR pszPrinterName,
  540. IN INT nCmdShow,
  541. IN LPCTSTR pszSheetName,
  542. IN DWORD dwSheetIndex,
  543. IN HWND hwnd,
  544. IN BOOL bModal,
  545. IN LPCTSTR pszDsPath
  546. ) : MSingletonWin( pszPrinterName, hwnd, bModal ),
  547. _pDevMode( NULL ),
  548. _bNoAccess( FALSE ),
  549. _bValid( FALSE ),
  550. _bErrorSaving( FALSE ),
  551. _uStartPage( dwSheetIndex ),
  552. _pszServerName( NULL ),
  553. _pPrinterPropertySheetManager( NULL ),
  554. _hPrinter( NULL ),
  555. _ePrinterPublishState( kUnInitalized ),
  556. _dwAttributes( 0 ),
  557. _dwPriority( 0 ),
  558. _dwStartTime( 0 ),
  559. _dwUntilTime( 0 ),
  560. _dwStatus( 0 ),
  561. _strStartPage( pszSheetName ),
  562. _bIsFaxDriver( FALSE ),
  563. _bHideSharingUI( FALSE ),
  564. _strDsPath( pszDsPath ),
  565. _eDsAvailableState( kDsUnInitalized ),
  566. _uMaxActiveCount( 0 ),
  567. _uActiveCount( 0 ),
  568. _dwAction( 0 ),
  569. _bGlobalDevMode( FALSE ),
  570. _strSheetName( pszSheetName ),
  571. _bDriverPagesNotLoaded( FALSE ),
  572. _bApplyEnableState( TRUE ),
  573. _bPooledPrinting( FALSE ),
  574. _bServerFullAccess( FALSE ),
  575. _hwndLastPageSelected( NULL )
  576. {
  577. DBGMSG( DBG_TRACE, ( "TPrinterData::ctor.\n" ) );
  578. //
  579. // Initialize the handle array.
  580. //
  581. memset( _hPages, 0, COUNTOF( _hPages ) );
  582. //
  583. // Initialize the page hwnd array.
  584. //
  585. memset( _hwndPages, 0, COUNTOF( _hwndPages ) );
  586. //
  587. // Validate the singleton window.
  588. //
  589. _bValid = MSingletonWin::bValid() && _strDsPath.bValid();
  590. //
  591. // Check whether it is the default printer state
  592. //
  593. _bDefaultPrinter = CheckDefaultPrinter( pszPrinterName ) == kDefault;
  594. }
  595. TPrinterData::
  596. ~TPrinterData(
  597. VOID
  598. )
  599. {
  600. DBGMSG( DBG_TRACE, ( "TPrinterData::dtor.\n" ) );
  601. //
  602. // Release the printer property sheet manager.
  603. //
  604. delete _pPrinterPropertySheetManager;
  605. //
  606. // This may catch anyone trying to use the PropertySheetManager after destruction.
  607. //
  608. _pPrinterPropertySheetManager = NULL;
  609. //
  610. // Unload the printer data.
  611. //
  612. vUnload();
  613. }
  614. /*++
  615. Routine Name:
  616. bRefZeroed
  617. Routine Description:
  618. Called when the reference count drops to zero.
  619. Arguments:
  620. Nothing.
  621. Return Value:
  622. Nothing.
  623. --*/
  624. VOID
  625. TPrinterData::
  626. vRefZeroed(
  627. VOID
  628. )
  629. {
  630. DBGMSG( DBG_TRACE, ( "TPrinterData::vRefZeroed.\n" ) );
  631. //
  632. // Since we are reference counting the printer data object
  633. // we know that it is safe to delete ourselves now.
  634. //
  635. delete this;
  636. }
  637. BOOL
  638. TPrinterData::
  639. bAdministrator(
  640. VOID
  641. )
  642. {
  643. return _dwAccess == PRINTER_ALL_ACCESS;
  644. }
  645. BOOL
  646. TPrinterData::
  647. bLoad(
  648. VOID
  649. )
  650. /*++
  651. Routine Description:
  652. Load printer information. This call can fail because of access
  653. denied, in which case only the security page should be added
  654. to the propset.
  655. Arguments:
  656. Return Value:
  657. --*/
  658. {
  659. //
  660. // Retrieve icons.
  661. //
  662. LoadPrinterIcons(_strPrinterName, &_shLargeIcon, &_shSmallIcon);
  663. SPLASSERT( _shLargeIcon );
  664. SPLASSERT( _shSmallIcon );
  665. //
  666. // Open the printer.
  667. //
  668. TStatusB bStatus( DBG_WARN, ERROR_ACCESS_DENIED );
  669. bStatus DBGNOCHK = FALSE;
  670. PPRINTER_INFO_2 pInfo2 = NULL;
  671. DWORD cbInfo2 = 0;
  672. PPRINTER_INFO_7 pInfo7 = NULL;
  673. DWORD cbInfo7 = 0;
  674. PPRINTER_INFO_8 pInfo8 = NULL;
  675. DWORD cbInfo8 = 0;
  676. PPRINTER_INFO_9 pInfo9 = NULL;
  677. DWORD cbInfo9 = 0;
  678. TStatus Status( DBG_WARN );
  679. _dwAccess = 0;
  680. //
  681. // Open the printer.
  682. //
  683. Status DBGCHK = TPrinter::sOpenPrinter( _strPrinterName,
  684. &_dwAccess,
  685. &_hPrinter );
  686. if( Status ){
  687. _hPrinter = NULL;
  688. goto Fail;
  689. }
  690. //
  691. // Gather the information.
  692. //
  693. bStatus DBGCHK = VDataRefresh::bGetPrinter( _hPrinter,
  694. 2,
  695. (PVOID*)&pInfo2,
  696. &cbInfo2 );
  697. (VOID)_PrinterInfo.bUpdate( pInfo2 );
  698. if( !bStatus ){
  699. goto Fail;
  700. }
  701. //
  702. // If we are loading global document default data.
  703. //
  704. if( _bGlobalDevMode )
  705. {
  706. //
  707. // Get the global dev mode.
  708. //
  709. bStatus DBGCHK = VDataRefresh::bGetPrinter( _hPrinter, 8, (PVOID*)&pInfo8, &cbInfo8 );
  710. if( bStatus )
  711. {
  712. DBGMSG( DBG_TRACE, ("Info level 8\n") );
  713. pInfo2->pDevMode = pInfo8->pDevMode;
  714. }
  715. }
  716. else
  717. {
  718. //
  719. // Get the per user dev mode.
  720. //
  721. bStatus DBGCHK = VDataRefresh::bGetPrinter( _hPrinter, 9, (PVOID*)&pInfo9, &cbInfo9 );
  722. if( bStatus )
  723. {
  724. DBGMSG( DBG_TRACE, ("Info level 9\n") );
  725. pInfo2->pDevMode = pInfo9->pDevMode;
  726. }
  727. //
  728. // Ignore failure here, this allows printer properties
  729. // to work on a downlevel machine.
  730. //
  731. else
  732. {
  733. bStatus DBGNOCHK = TRUE;
  734. }
  735. }
  736. //
  737. // Make a copy of the devmode.
  738. //
  739. if( pInfo2->pDevMode ){
  740. COUNTB cbDevMode = pInfo2->pDevMode->dmSize + pInfo2->pDevMode->dmDriverExtra;
  741. _pDevMode = (PDEVMODE)AllocMem( cbDevMode );
  742. if( !_pDevMode ){
  743. DBGMSG( DBG_WARN, ( "PrinterData.bLoad: failed to alloc dm %d: %d\n", cbDevMode, GetLastError( )));
  744. bStatus DBGNOCHK = FALSE;
  745. goto Fail;
  746. }
  747. CopyMemory( _pDevMode, pInfo2->pDevMode, cbDevMode );
  748. }
  749. _dwAttributes = pInfo2->Attributes;
  750. _dwPriority = pInfo2->Priority;
  751. _dwStartTime = pInfo2->StartTime;
  752. _dwUntilTime = pInfo2->UntilTime;
  753. _dwStatus = pInfo2->Status;
  754. //
  755. // Run through printer_info_2.
  756. // Check strings for allocation.
  757. //
  758. if( !_strPrinterName.bUpdate( pInfo2->pPrinterName ) ||
  759. !_strCurrentPrinterName.bUpdate( _strPrinterName ) ||
  760. !_strServerName.bUpdate( pInfo2->pServerName ) ||
  761. !_strShareName.bUpdate( pInfo2->pShareName ) ||
  762. !_strDriverName.bUpdate( pInfo2->pDriverName ) ||
  763. !_strComment.bUpdate( pInfo2->pComment ) ||
  764. !_strLocation.bUpdate( pInfo2->pLocation ) ||
  765. !_strPortName.bUpdate( pInfo2->pPortName ) ||
  766. !_strSepFile.bUpdate( pInfo2->pSepFile ) ||
  767. !_strPrintProcessor.bUpdate( pInfo2->pPrintProcessor ) ||
  768. !_strDatatype.bUpdate( pInfo2->pDatatype )){
  769. DBGMSG( DBG_WARN, ( "PrinterProp.bLoad: String update failed %x %d\n", this, GetLastError( )));
  770. bStatus DBGNOCHK = FALSE;
  771. }
  772. //
  773. // check whether pool printing is enabled
  774. //
  775. _bPooledPrinting = _PrinterInfo._bPooledPrinting;
  776. //
  777. // Make a pointer to the server name. A Null pointer
  778. // indicates the local machine.
  779. //
  780. if( _strServerName.bEmpty() ){
  781. _pszServerName = NULL;
  782. } else {
  783. _pszServerName = (LPCTSTR)_strServerName;
  784. }
  785. //
  786. // Get the current environment string and version number.
  787. //
  788. if( !bGetCurrentDriver( _strServerName, &_dwDriverVersion ) ||
  789. !bGetDriverEnv( _dwDriverVersion, _strDriverEnv ) ){
  790. DBGMSG( DBG_WARN, ( "Get Driver version and environment failed.\n" ) );
  791. bStatus DBGNOCHK = FALSE;
  792. goto Fail;
  793. }
  794. DBGMSG( DBG_TRACE, ( "Driver Version %d Environment " TSTR "\n", _dwDriverVersion, (LPCTSTR)_strDriverEnv ) );
  795. if( bStatus )
  796. {
  797. //
  798. // Get special information about this print queue.
  799. //
  800. vGetSpecialInformation();
  801. //
  802. // Get the current DS printer state.
  803. //
  804. bStatus DBGNOCHK = VDataRefresh::bGetPrinter( _hPrinter,
  805. 7,
  806. (PVOID*)&pInfo7,
  807. &cbInfo7 );
  808. if( bStatus )
  809. {
  810. DBGMSG( DBG_TRACE, ("Info level 7 dwAction %x\n", pInfo7->dwAction ) );
  811. (VOID)_PrinterInfo.bUpdate( pInfo7 );
  812. bStatus DBGCHK = _strObjectGUID.bUpdate( pInfo7->pszObjectGUID );
  813. _dwAction = pInfo7->dwAction;
  814. }
  815. //
  816. // We do not fail the bLoad if we cannont get the info level 7 data.
  817. // This is necessary to support the downlevel case.
  818. //
  819. bStatus DBGNOCHK = TRUE;
  820. }
  821. if( bStatus )
  822. {
  823. //
  824. // Check whether the user has full priviledge to access the server, the return value
  825. // will be used when we are trying to install a printer driver
  826. //
  827. HANDLE hPrinter = NULL;
  828. DWORD dwAccess = SERVER_ALL_ACCESS;
  829. //
  830. // Open the printer.
  831. //
  832. TPrinter::sOpenPrinter( _strServerName,
  833. &dwAccess,
  834. &hPrinter );
  835. _bServerFullAccess = hPrinter ? TRUE : FALSE;
  836. if( hPrinter )
  837. {
  838. ClosePrinter( hPrinter );
  839. }
  840. }
  841. Fail:
  842. FreeMem( pInfo2 );
  843. FreeMem( pInfo7 );
  844. FreeMem( pInfo8 );
  845. FreeMem( pInfo9 );
  846. //
  847. // If we've failed because access was denied, then return
  848. // success but set the bNoAccess flag. This allows the
  849. // user to see the security tab.
  850. //
  851. if( !bStatus && ERROR_ACCESS_DENIED == GetLastError( )){
  852. _bNoAccess = TRUE;
  853. return TRUE;
  854. }
  855. return bStatus;
  856. }
  857. VOID
  858. TPrinterData::
  859. vUnload(
  860. VOID
  861. )
  862. /*++
  863. Routine Description:
  864. Free associated data in this, so that this can be freed or
  865. loaded again.
  866. Arguments:
  867. Return Value:
  868. --*/
  869. {
  870. DBGMSG( DBG_TRACE, ( "TPrinterData::vUnload.\n" ) );
  871. //
  872. // Release the deve mode.
  873. //
  874. FreeMem( _pDevMode );
  875. _pDevMode = NULL;
  876. //
  877. // Close the printer
  878. //
  879. if( _hPrinter ){
  880. ClosePrinter( _hPrinter );
  881. _hPrinter = NULL;
  882. }
  883. }
  884. BOOL
  885. TPrinterData::
  886. bSave(
  887. BOOL bUpdateDevMode
  888. )
  889. /*++
  890. Routine Description:
  891. Save the data store in this.
  892. Arguments:
  893. bUpdateDevmode flag indicates we should update the devmode.
  894. Return Value:
  895. TRUE success, FLASE error occurred.
  896. --*/
  897. {
  898. //
  899. // If bErrorSaving is set, then somewhere we had an error reading
  900. // from the dialogs. This should be very rare.
  901. //
  902. if( bErrorSaving( ))
  903. {
  904. //
  905. // Tell the user that we can't save the dialogs.
  906. // Then just exit?
  907. //
  908. return FALSE;
  909. }
  910. //
  911. // Display the wait cursor setprinter may take awhile
  912. //
  913. TWaitCursor Cursor;
  914. //
  915. // Setup the INFO_2 structure. First read it, modify it, then
  916. // free it.
  917. //
  918. TStatusB bStatus;
  919. bStatus DBGNOCHK = TRUE;
  920. //
  921. // If we are updating the devmode.
  922. //
  923. if( bUpdateDevMode )
  924. {
  925. //
  926. // If we are updating the global devmode.
  927. //
  928. if( _bGlobalDevMode )
  929. {
  930. return bUpdateGlobalDevMode();
  931. }
  932. else
  933. {
  934. return bUpdatePerUserDevMode();
  935. }
  936. }
  937. //
  938. // If a printer info 2 change occurred do a set printer.
  939. //
  940. if( bCheckForChange( 2 ) )
  941. {
  942. TString strNewName, strTemp;
  943. BOOL bDriverHasChanged = FALSE;
  944. PPRINTER_INFO_2 pInfo2 = NULL;
  945. DWORD cbInfo2 = 0;
  946. bStatus DBGCHK = VDataRefresh::bGetPrinter( _hPrinter, 2, (PVOID*)&pInfo2, &cbInfo2 );
  947. if( bStatus )
  948. {
  949. // assume the default printer name
  950. strNewName.bUpdate(_strPrinterName);
  951. //
  952. // Check if the driver has changed. If the driver has chaned then
  953. // the printer name may have to change if the current printer name
  954. // is a generated name i.e. similar to the driver name.
  955. //
  956. if( _tcsicmp( _strDriverName, _PrinterInfo._strDriverName ) )
  957. {
  958. //
  959. // Indicate the driver changed.
  960. //
  961. bDriverHasChanged = TRUE;
  962. //
  963. // Turn on BIDI since the spooler enables this if a
  964. // language monitor is present. If it isn't it will
  965. // be ignored by the spooler.
  966. //
  967. _dwAttributes |= PRINTER_ATTRIBUTE_ENABLE_BIDI;
  968. //
  969. // Update the printer name if neccessary.
  970. //
  971. bStatus DBGCHK = bDriverChangedGenPrinterName(&strNewName);
  972. }
  973. //
  974. // If the attributes indicate to allways spool raw then the
  975. // datatype must also be raw else the printe will not print.
  976. //
  977. if( _dwAttributes & PRINTER_ATTRIBUTE_RAW_ONLY )
  978. {
  979. DBGMSG( DBG_TRACE, ( "Forcing datatype to raw.\n" ) );
  980. _strDatatype.bUpdate( _T("RAW") );
  981. }
  982. //
  983. // Transfer pPrinterData to pInfo2.
  984. //
  985. pInfo2->pPrinterName = (LPTSTR)pGetAdjustedPrinterName(
  986. static_cast<LPCTSTR>(strNewName),
  987. strTemp);
  988. pInfo2->pShareName = (LPTSTR)(LPCTSTR)_strShareName;
  989. pInfo2->pDriverName = (LPTSTR)(LPCTSTR)_strDriverName;
  990. pInfo2->pComment = (LPTSTR)(LPCTSTR)_strComment;
  991. pInfo2->pLocation = (LPTSTR)(LPCTSTR)_strLocation;
  992. pInfo2->pPortName = (LPTSTR)(LPCTSTR)_strPortName;
  993. pInfo2->pSepFile = (LPTSTR)(LPCTSTR)_strSepFile;
  994. pInfo2->pPrintProcessor = (LPTSTR)(LPCTSTR)_strPrintProcessor;
  995. pInfo2->pDatatype = (LPTSTR)(LPCTSTR)_strDatatype;
  996. pInfo2->Attributes = _dwAttributes;
  997. pInfo2->Priority = _dwPriority;
  998. pInfo2->StartTime = _dwStartTime;
  999. pInfo2->UntilTime = _dwUntilTime;
  1000. //
  1001. // Another piece of trivia: the security descriptor must be set
  1002. // to NULL since it might not be the owner.
  1003. //
  1004. pInfo2->pSecurityDescriptor = NULL;
  1005. if( bStatus )
  1006. {
  1007. //
  1008. // Set the printer information.
  1009. //
  1010. bStatus DBGCHK = SetPrinter( _hPrinter, 2, (PBYTE)pInfo2, 0 );
  1011. }
  1012. //
  1013. // Update the _strCurrentPrinterName here because it is needed
  1014. // to updated before calling bRefreshDriverPages() below.
  1015. //
  1016. if( bStatus )
  1017. {
  1018. //
  1019. // Update the local printer info 2 copy ( needed for the apply button )
  1020. //
  1021. _PrinterInfo.bUpdate( pInfo2 );
  1022. _bPooledPrinting = _PrinterInfo._bPooledPrinting;
  1023. _strCurrentPrinterName.bUpdate( pInfo2->pPrinterName );
  1024. _strPrinterName.bUpdate( pInfo2->pPrinterName );
  1025. }
  1026. //
  1027. // Reload the driver pages.
  1028. //
  1029. if( bStatus && bDriverHasChanged )
  1030. {
  1031. //
  1032. // We are about to insert/remove the dynamic pages - these are
  1033. // the driver pages + shell extension pages, so we need to check
  1034. // if we are currently in one of them. If we are, then we have to
  1035. // switch to one of the static pages. It is not mandatory to switch
  1036. // to the General page one, but it seems reasonable.
  1037. //
  1038. HWND hwndCurPage = PropSheet_GetCurrentPageHwnd(
  1039. pPrinterPropertySheetManager()->hGetParentHandle() );
  1040. if( _hwndLastPageSelected != hwndCurPage )
  1041. {
  1042. //
  1043. // If we are currently in one of the dynamic pages just switch to the
  1044. // general page.
  1045. //
  1046. PropSheet_SetCurSel( pPrinterPropertySheetManager()->hGetParentHandle(), NULL, 0 );
  1047. }
  1048. //
  1049. // Turn on BIDI bit if it's needed. Update all the dwAttributes members
  1050. // simultaneousely because otherwise the logic which enable/disable the
  1051. // Apply button will be broken.
  1052. //
  1053. if( bSupportBidi() )
  1054. {
  1055. _dwAttributes |= PRINTER_ATTRIBUTE_ENABLE_BIDI;
  1056. pInfo2->Attributes |= PRINTER_ATTRIBUTE_ENABLE_BIDI;
  1057. _PrinterInfo._dwAttributes |= PRINTER_ATTRIBUTE_ENABLE_BIDI;
  1058. }
  1059. else
  1060. {
  1061. _dwAttributes &= ~PRINTER_ATTRIBUTE_ENABLE_BIDI;
  1062. pInfo2->Attributes &= ~PRINTER_ATTRIBUTE_ENABLE_BIDI;
  1063. _PrinterInfo._dwAttributes &= ~PRINTER_ATTRIBUTE_ENABLE_BIDI;
  1064. }
  1065. //
  1066. // Reload the driver pages.
  1067. //
  1068. bStatus DBGCHK = _pPrinterPropertySheetManager->bRefreshDriverPages();
  1069. //
  1070. // If the driver pages were loaded then, set the new title.
  1071. //
  1072. if( bStatus )
  1073. {
  1074. _pPrinterPropertySheetManager->vRefreshTitle();
  1075. }
  1076. //
  1077. // Recalc the property sheet size in case of
  1078. // monolitic drivers insert a pages with
  1079. // a non-standard size
  1080. //
  1081. PropSheet_RecalcPageSizes( pPrinterPropertySheetManager()->hGetParentHandle() );
  1082. }
  1083. }
  1084. FreeMem( pInfo2 );
  1085. }
  1086. //
  1087. // Update the DS properties if needed
  1088. //
  1089. if( bStatus && bCheckForChange( 7 ) && bIsDsAvailable() )
  1090. {
  1091. PPRINTER_INFO_7 pInfo7 = NULL;
  1092. DWORD cbInfo7 = 0;
  1093. bStatus DBGCHK = VDataRefresh::bGetPrinter( _hPrinter, 7, (PVOID*)&pInfo7, &cbInfo7 );
  1094. if( bStatus )
  1095. {
  1096. //
  1097. // If we need to publish this printer into the directory.
  1098. //
  1099. switch ( ePrinterPublishState() )
  1100. {
  1101. case kPublish:
  1102. if( _dwAttributes & PRINTER_ATTRIBUTE_SHARED )
  1103. {
  1104. DBGMSG( DBG_TRACE, ( "Publish printer - Publish.\n" ) );
  1105. pInfo7->dwAction = DSPRINT_PUBLISH;
  1106. bStatus DBGCHK = SetPrinter( _hPrinter, 7, (PBYTE)pInfo7, 0 );
  1107. }
  1108. break;
  1109. case kUnPublish:
  1110. {
  1111. DBGMSG( DBG_TRACE, ( "Publish printer - UnPublish.\n" ) );
  1112. pInfo7->dwAction = DSPRINT_UNPUBLISH;
  1113. bStatus DBGCHK = SetPrinter( _hPrinter, 7, (PBYTE)pInfo7, 0 );
  1114. }
  1115. break;
  1116. default:
  1117. DBGMSG( DBG_TRACE, ( "Publish printer - NoAction.\n" ) );
  1118. break;
  1119. }
  1120. //
  1121. // If set printer failed with an any error remap the error
  1122. // to a DS friendly message. If the error is io pending the spooler
  1123. // will publish in the background therefore we will silently fail.
  1124. //
  1125. if( !bStatus )
  1126. {
  1127. DBGMSG( DBG_TRACE, ( "SetPrinter Info 7 returned %d with %d\n", bStatus, GetLastError() ) );
  1128. if( GetLastError() == ERROR_IO_PENDING )
  1129. {
  1130. bStatus DBGNOCHK = TRUE;
  1131. pInfo7->dwAction |= DSPRINT_PENDING;
  1132. _dwAction |= DSPRINT_PENDING;
  1133. }
  1134. else
  1135. {
  1136. SetLastError( ERROR_IO_PENDING );
  1137. }
  1138. }
  1139. else
  1140. {
  1141. //
  1142. // Set printer info 7 succeede with out an error, then clear
  1143. // the pending status indicator bit in both our copy and
  1144. // the previous copy.
  1145. //
  1146. pInfo7->dwAction &= ~DSPRINT_PENDING;
  1147. _dwAction &= ~DSPRINT_PENDING;
  1148. }
  1149. if( bStatus )
  1150. {
  1151. //
  1152. // Update the local printer info 7 copy ( needed for the apply button )
  1153. //
  1154. _PrinterInfo.bUpdate( pInfo7 );
  1155. }
  1156. FreeMem( pInfo7 );
  1157. }
  1158. }
  1159. return bStatus;
  1160. }
  1161. LPCTSTR
  1162. TPrinterData::
  1163. pGetAdjustedPrinterName(
  1164. IN LPCTSTR pszPrinterName,
  1165. OUT TString &strTempPrinterName
  1166. ) const
  1167. /*++
  1168. Routine Description:
  1169. This routine adjusts the printer name in the case of a masq printer or a
  1170. network printer. If the printer is a msaq printer or a network printer we must
  1171. retain the current server name part of the name. Preserving the name is necessary
  1172. for the masq printer in order to continue displaying the masq printer
  1173. as a network connection. The print folder code looks at the leading \\ to determine
  1174. if the printer should be displayed as a network printer, it does this because
  1175. reading the printers attributes is slow.
  1176. Arguments:
  1177. Temp buffer where to store the new printer name, if this is a masq printer.
  1178. Return Value:
  1179. Pointer to the adjusted printer name. The name is not modified if this printer
  1180. is not a masq printer.
  1181. --*/
  1182. {
  1183. TStatusB bStatus;
  1184. // if this is a masq printer do not change the name.
  1185. if( _dwAttributes & PRINTER_ATTRIBUTE_NETWORK && _dwAttributes & PRINTER_ATTRIBUTE_LOCAL )
  1186. {
  1187. bStatus DBGCHK = strTempPrinterName.bUpdate(_strCurrentPrinterName);
  1188. }
  1189. else if( _dwAttributes & PRINTER_ATTRIBUTE_NETWORK )
  1190. {
  1191. // if this is a network printer then preserve the server name part of the name.
  1192. LPCTSTR pszServer1 = NULL, pszPrinter1 = NULL;
  1193. TCHAR szScratch1[kPrinterBufMax];
  1194. LPCTSTR pszServer2 = NULL, pszPrinter2 = NULL;
  1195. TCHAR szScratch2[kPrinterBufMax];
  1196. // split the printer names into their components.
  1197. vPrinterSplitFullName(szScratch1, _strCurrentPrinterName, &pszServer1, &pszPrinter1);
  1198. vPrinterSplitFullName(szScratch2, pszPrinterName, &pszServer2, &pszPrinter2);
  1199. // if we have wacks in the printer name then it's either an
  1200. // invalid printer name or it's a connection to a masq printer
  1201. // in which case we must revert to the original printer name.
  1202. if( pszServer2 && _tcslen(pszServer2) )
  1203. {
  1204. bStatus DBGCHK = strTempPrinterName.bUpdate(_strCurrentPrinterName);
  1205. }
  1206. else
  1207. {
  1208. bStatus DBGCHK = strTempPrinterName.bUpdate(pszServer1) &&
  1209. strTempPrinterName.bCat(gszWack) &&
  1210. strTempPrinterName.bCat(pszPrinter2);
  1211. }
  1212. }
  1213. else
  1214. {
  1215. // normal local printer, i.e. not a masq local printer then just use the name as is.
  1216. bStatus DBGCHK = strTempPrinterName.bUpdate(pszPrinterName);
  1217. }
  1218. return strTempPrinterName;
  1219. }
  1220. BOOL
  1221. TPrinterData::
  1222. bDriverChangedGenPrinterName(
  1223. TString *pstrNewName
  1224. ) const
  1225. /*++
  1226. Routine Description:
  1227. bDriverChangedGenPrinterName
  1228. Arguments:
  1229. pstrNewName - pointer where to put the new name.
  1230. Return Value:
  1231. TRUE success, FALSE failure.
  1232. --*/
  1233. {
  1234. TStatusB bStatus;
  1235. ASSERT(pstrNewName);
  1236. //
  1237. // Check if the printer name should change. We change the printer name if
  1238. // the driver name is a sub string of the current printer name, and it is
  1239. // not a remote printer connection. There is not an explicit check if it
  1240. // is a remote printer connection since a remote printer connection will have
  1241. // the \\machine\printer name and therefore will never match.
  1242. //
  1243. if( !_tcsnicmp( _strPrinterName, _PrinterInfo._strDriverName, _tcslen( _PrinterInfo._strDriverName ) ) )
  1244. {
  1245. TCHAR szNewName[kPrinterBufMax];
  1246. //
  1247. // Create a new unique printer name.
  1248. //
  1249. if( NewFriendlyName( static_cast<LPCTSTR>( _strServerName ),
  1250. const_cast<LPTSTR>( static_cast<LPCTSTR>( _strDriverName ) ),
  1251. szNewName ) )
  1252. {
  1253. bStatus DBGCHK = pstrNewName->bUpdate( szNewName );
  1254. }
  1255. else
  1256. {
  1257. //
  1258. // if NewFriendlyName fails that means the passed name is
  1259. // unique itself. i.e. in this case just use the passed
  1260. // name (the newly selected driver name)
  1261. //
  1262. bStatus DBGCHK = pstrNewName->bUpdate( _strDriverName );
  1263. }
  1264. }
  1265. //
  1266. // we didn't really updated the name - the default would be
  1267. // to use user's choice - i.e. _strPrinterName
  1268. //
  1269. if( 0 == pstrNewName->uLen() )
  1270. {
  1271. bStatus DBGCHK = pstrNewName->bUpdate( _strPrinterName );
  1272. }
  1273. return bStatus;
  1274. }
  1275. BOOL
  1276. TPrinterData::
  1277. bSupportBidi(
  1278. VOID
  1279. )
  1280. /*++
  1281. Routine Description:
  1282. Check whether the current printer supports bidi. Assumes there
  1283. is a valid hPrinter available.
  1284. Note: this returns false if it can't make the determination.
  1285. Arguments:
  1286. Return Value:
  1287. TRUE - Bidi supported.
  1288. FALSE - Failed or bidi not supported.
  1289. --*/
  1290. {
  1291. BOOL bSupport = FALSE;
  1292. PDRIVER_INFO_3 pInfo3 = NULL;
  1293. DWORD dwInfo3 = 0;
  1294. //
  1295. // Get the printer driver information.
  1296. //
  1297. if( VDataRefresh::bGetPrinterDriver( _hPrinter,
  1298. (LPTSTR)(LPCTSTR)_strDriverEnv,
  1299. 3,
  1300. (PVOID*)&pInfo3,
  1301. &dwInfo3 )){
  1302. bSupport = pInfo3->pMonitorName && pInfo3->pMonitorName[0];
  1303. FreeMem( pInfo3 );
  1304. }
  1305. return bSupport;
  1306. }
  1307. TPrinterData::EPublishState
  1308. TPrinterData::
  1309. ePrinterPublishState(
  1310. TPrinterData::EPublishState eNewPublishState
  1311. )
  1312. /*++
  1313. Routine Description:
  1314. Sets and Gets the publish state.
  1315. Arguments:
  1316. None
  1317. Return Value:
  1318. The current publish state.
  1319. --*/
  1320. {
  1321. //
  1322. // If the publish state is being set.
  1323. //
  1324. if( eNewPublishState != kUnInitalized )
  1325. {
  1326. _ePrinterPublishState = eNewPublishState;
  1327. }
  1328. else
  1329. {
  1330. //
  1331. // If the printer publish state has not been initialized.
  1332. //
  1333. if( _ePrinterPublishState == kUnInitalized )
  1334. {
  1335. //
  1336. // If we are talking to a downlevel server the ds is not available.
  1337. //
  1338. if( ( GetDriverVersion( _dwDriverVersion ) > 2 ) && bIsDsAvailable( ) )
  1339. {
  1340. if( ( _dwAction & DSPRINT_PUBLISH ) || ( _dwAction & DSPRINT_UPDATE ) )
  1341. {
  1342. _ePrinterPublishState = kPublished;
  1343. }
  1344. else
  1345. {
  1346. _ePrinterPublishState = kNotPublished;
  1347. }
  1348. }
  1349. else
  1350. {
  1351. _ePrinterPublishState = kNoDsAvailable;
  1352. }
  1353. }
  1354. }
  1355. return _ePrinterPublishState;
  1356. }
  1357. BOOL
  1358. TPrinterData::
  1359. bIsDsAvailable(
  1360. VOID
  1361. )
  1362. /*++
  1363. Routine Description:
  1364. Sets and Gets the publish state.
  1365. Arguments:
  1366. None
  1367. Return Value:
  1368. The current publish state.
  1369. --*/
  1370. {
  1371. if( _eDsAvailableState == kDsUnInitalized )
  1372. {
  1373. //
  1374. // Display the wait cursor the DS may take a long time to respond.
  1375. //
  1376. TWaitCursor Cursor;
  1377. TDirectoryService ds;
  1378. _eDsAvailableState = ds.bIsDsAvailable(_strServerName) ? kDsAvailable : kDsNotAvailable;
  1379. }
  1380. return _eDsAvailableState == kDsAvailable;
  1381. }
  1382. BOOL
  1383. TPrinterData::
  1384. bCheckForChange(
  1385. IN UINT uLevel
  1386. )
  1387. /*++
  1388. Routine Description:
  1389. Checkes the data set if it has changed.
  1390. Arguments:
  1391. None
  1392. Return Value:
  1393. TRUE data has changed, FALSE data is the same.
  1394. --*/
  1395. {
  1396. DBGMSG( DBG_TRACE, ( "TPrinterData::bCheckForChange\n" ) );
  1397. //
  1398. // If we are not an administrator nothing should change
  1399. // This is a performance optimization, when the user
  1400. // is just looking at the printer.
  1401. //
  1402. if( !bAdministrator() )
  1403. {
  1404. return FALSE;
  1405. }
  1406. BOOL bStatus = FALSE;
  1407. //
  1408. // Assume the data is different.
  1409. //
  1410. if( !bStatus && uLevel == -1 || uLevel == 2 )
  1411. {
  1412. //
  1413. // We check all values with a case sensitive check. The spooler
  1414. // can determine if upper and lower case characters warrent
  1415. // a printer change event.
  1416. //
  1417. if( !_tcscmp( _strServerName, _PrinterInfo._strServerName ) &&
  1418. !ComparePrinterName( _strPrinterName, _PrinterInfo._strPrinterName ) &&
  1419. !_tcscmp( _strDriverName, _PrinterInfo._strDriverName ) &&
  1420. !_tcscmp( _strComment, _PrinterInfo._strComment ) &&
  1421. !_tcscmp( _strLocation, _PrinterInfo._strLocation ) &&
  1422. !_tcscmp( _strPortName, _PrinterInfo._strPortName ) &&
  1423. !_tcscmp( _strSepFile, _PrinterInfo._strSepFile ) &&
  1424. !_tcscmp( _strPrintProcessor, _PrinterInfo._strPrintProcessor ) &&
  1425. !_tcscmp( _strDatatype, _PrinterInfo._strDatatype ) &&
  1426. _dwAttributes == _PrinterInfo._dwAttributes &&
  1427. _dwPriority == _PrinterInfo._dwPriority &&
  1428. _dwStartTime == _PrinterInfo._dwStartTime &&
  1429. _dwUntilTime == _PrinterInfo._dwUntilTime &&
  1430. _bPooledPrinting == _PrinterInfo._bPooledPrinting )
  1431. {
  1432. //
  1433. // Ignore the printer share name if not shared.
  1434. //
  1435. if( uLevel == 2 || _dwAttributes & PRINTER_ATTRIBUTE_SHARED )
  1436. {
  1437. bStatus = _tcscmp( _strShareName, _PrinterInfo._strShareName );
  1438. }
  1439. }
  1440. else
  1441. {
  1442. bStatus = TRUE;
  1443. }
  1444. }
  1445. //
  1446. // If the data is the same and it is our level
  1447. // then check if the data is different.
  1448. //
  1449. if( !bStatus && uLevel == -1 || uLevel == 7 )
  1450. {
  1451. //
  1452. // Ignore the DS action if not shared.
  1453. //
  1454. if( uLevel == 7 || _dwAttributes & PRINTER_ATTRIBUTE_SHARED )
  1455. {
  1456. //
  1457. // Ignore the ds pending bit.
  1458. //
  1459. if( ( _dwAction & ~DSPRINT_PENDING ) == ( _PrinterInfo._dwAction & ~DSPRINT_PENDING ) )
  1460. {
  1461. bStatus = FALSE;
  1462. }
  1463. else
  1464. {
  1465. bStatus = TRUE;
  1466. }
  1467. }
  1468. }
  1469. #if DBG
  1470. if( bStatus )
  1471. DBGMSG( DBG_TRACE, ("Item changed:\n" ));
  1472. if( _tcscmp( _strServerName, _PrinterInfo._strServerName ) )
  1473. DBGMSG( DBG_TRACE, ("ServerName: "TSTR " " TSTR "\n", (LPCTSTR)_strServerName, (LPCTSTR)_PrinterInfo._strServerName ));
  1474. if( ComparePrinterName( _strPrinterName, _PrinterInfo._strPrinterName ) )
  1475. DBGMSG( DBG_TRACE, ("PrinterName: "TSTR " " TSTR "\n", (LPCTSTR)_strPrinterName, (LPCTSTR)_PrinterInfo._strPrinterName ));
  1476. if( _tcscmp( _strShareName, _PrinterInfo._strShareName ) )
  1477. DBGMSG( DBG_TRACE, ("ShareName: "TSTR " " TSTR "\n", (LPCTSTR)_strShareName, (LPCTSTR)_PrinterInfo._strShareName ));
  1478. if( _tcscmp( _strDriverName, _PrinterInfo._strDriverName ) )
  1479. DBGMSG( DBG_TRACE, ("DriverName: "TSTR " " TSTR "\n", (LPCTSTR)_strDriverName, (LPCTSTR)_PrinterInfo._strDriverName ));
  1480. if( _tcscmp( _strComment, _PrinterInfo._strComment ) )
  1481. DBGMSG( DBG_TRACE, ("CommentName: "TSTR " " TSTR "\n", (LPCTSTR)_strComment, (LPCTSTR)_PrinterInfo._strComment ));
  1482. if( _tcscmp( _strLocation, _PrinterInfo._strLocation ) )
  1483. DBGMSG( DBG_TRACE, ("LocationName: "TSTR " " TSTR "\n", (LPCTSTR)_strLocation, (LPCTSTR)_PrinterInfo._strLocation ));
  1484. if( _tcscmp( _strPortName, _PrinterInfo._strPortName ) )
  1485. DBGMSG( DBG_TRACE, ("PortName: "TSTR " " TSTR "\n", (LPCTSTR)_strPortName, (LPCTSTR)_PrinterInfo._strPortName ));
  1486. if( _tcscmp( _strSepFile, _PrinterInfo._strSepFile ) )
  1487. DBGMSG( DBG_TRACE, ("SepFile: "TSTR " " TSTR "\n", (LPCTSTR)_strSepFile, (LPCTSTR)_PrinterInfo._strSepFile ));
  1488. if( _tcscmp( _strDatatype, _PrinterInfo._strDatatype ) )
  1489. DBGMSG( DBG_TRACE, ("Datatype: "TSTR " " TSTR "\n", (LPCTSTR)_strDatatype, (LPCTSTR)_PrinterInfo._strDatatype ));
  1490. if( _tcscmp( _strPrintProcessor, _PrinterInfo._strPrintProcessor ) )
  1491. DBGMSG( DBG_TRACE, ("PrintProcessor: "TSTR " " TSTR "\n", (LPCTSTR)_strPrintProcessor, (LPCTSTR)_PrinterInfo._strPrintProcessor ));
  1492. if( _dwAttributes != _PrinterInfo._dwAttributes )
  1493. DBGMSG( DBG_TRACE, ("Attributes: %x %x\n", _dwAttributes, _PrinterInfo._dwAttributes ));
  1494. if( _dwPriority != _PrinterInfo._dwPriority )
  1495. DBGMSG( DBG_TRACE, ("Priority: %d %d\n", _dwPriority, _PrinterInfo._dwPriority ));
  1496. if( _dwStartTime != _PrinterInfo._dwStartTime )
  1497. DBGMSG( DBG_TRACE, ("StartTime: %d %d\n", _dwStartTime, _PrinterInfo._dwStartTime ));
  1498. if( _dwUntilTime != _PrinterInfo._dwUntilTime )
  1499. DBGMSG( DBG_TRACE, ("UntilTime: %d %d\n", _dwUntilTime, _PrinterInfo._dwUntilTime ));
  1500. if( _dwAction != _PrinterInfo._dwAction )
  1501. DBGMSG( DBG_TRACE, ("DsAction: %x %x\n", _dwAction, _PrinterInfo._dwAction ));
  1502. #endif
  1503. return bStatus;
  1504. }
  1505. INT
  1506. TPrinterData::
  1507. ComparePrinterName(
  1508. IN LPCTSTR pszPrinterName1,
  1509. IN LPCTSTR pszPrinterName2
  1510. )
  1511. /*++
  1512. Routine Description:
  1513. Compare printer name 1 to printer name 2. This routine will
  1514. strip the server name and any leading wacks when the comparison
  1515. is done.
  1516. Arguments:
  1517. pszPrinterName1 - Pointer to printer name string (can be fully qualified)
  1518. pszPrinterName2 - Pointer to printer name string (can be fully qualified)
  1519. Return Value:
  1520. 1 Printer name 1 is greater than printer name 2
  1521. 0 Printer name 1 and printer name 2 are equal.
  1522. -1 Printer name 1 is less than printer name 2
  1523. --*/
  1524. {
  1525. SPLASSERT( pszPrinterName1 );
  1526. SPLASSERT( pszPrinterName2 );
  1527. LPCTSTR pszServer1;
  1528. LPCTSTR pszPrinter1;
  1529. TCHAR szScratch1[kPrinterBufMax];
  1530. LPCTSTR pszServer2;
  1531. LPCTSTR pszPrinter2;
  1532. TCHAR szScratch2[kPrinterBufMax];
  1533. //
  1534. // Split the printer names into their components.
  1535. //
  1536. vPrinterSplitFullName( szScratch1, pszPrinterName1, &pszServer1, &pszPrinter1 );
  1537. vPrinterSplitFullName( szScratch2, pszPrinterName2, &pszServer2, &pszPrinter2 );
  1538. //
  1539. // Assume not equal.
  1540. //
  1541. INT iRetval = 1;
  1542. if( pszPrinter1 && pszPrinter2 )
  1543. {
  1544. iRetval = _tcscmp( pszPrinter1, pszPrinter2 );
  1545. }
  1546. return iRetval;
  1547. }
  1548. BOOL
  1549. TPrinterData::
  1550. bUpdateGlobalDevMode(
  1551. VOID
  1552. )
  1553. /*++
  1554. Routine Description:
  1555. Updates the global devmode using printer info 8.
  1556. Arguments:
  1557. None
  1558. Return Value:
  1559. TRUE data devmode updated, FALSE error occurred.
  1560. --*/
  1561. {
  1562. DBGMSG( DBG_TRACE, ( "TPrinterData::bUpdateGlobalDevMode\n" ) );
  1563. SPLASSERT( _pDevMode );
  1564. PRINTER_INFO_8 Info8 = {0};
  1565. DWORD cbInfo8 = 0;
  1566. TStatusB bStatus;
  1567. //
  1568. // Set the devmode in the printer info 8 structure.
  1569. //
  1570. Info8.pDevMode = _pDevMode;
  1571. //
  1572. // Set the global dev mode.
  1573. //
  1574. bStatus DBGCHK = SetPrinter( _hPrinter, 8, (PBYTE)&Info8, 0 );
  1575. return bStatus;
  1576. }
  1577. BOOL
  1578. TPrinterData::
  1579. bUpdatePerUserDevMode(
  1580. VOID
  1581. )
  1582. /*++
  1583. Routine Description:
  1584. Updates the global devmode using printer info 8.
  1585. Arguments:
  1586. None
  1587. Return Value:
  1588. TRUE data devmode updated, FALSE error occurred.
  1589. --*/
  1590. {
  1591. DBGMSG( DBG_TRACE, ( "TPrinterData::bUpdatePerUserDevMode\n" ) );
  1592. SPLASSERT( _pDevMode );
  1593. PRINTER_INFO_9 Info9 = {0};
  1594. DWORD cbInfo9 = 0;
  1595. TStatusB bStatus;
  1596. //
  1597. // Set the devmode in the printer info 8 structure.
  1598. //
  1599. Info9.pDevMode = _pDevMode;
  1600. //
  1601. // Set the global dev mode.
  1602. //
  1603. bStatus DBGCHK = SetPrinter( _hPrinter, 9, (PBYTE)&Info9, 0 );
  1604. return bStatus;
  1605. }
  1606. VOID
  1607. TPrinterData::
  1608. vGetSpecialInformation(
  1609. VOID
  1610. )
  1611. /*++
  1612. Routine Description:
  1613. Checked if this device is a fax printer, we read server
  1614. registry key to see if we should display the sharing UI
  1615. for this device.
  1616. Arguments:
  1617. None
  1618. Return Value:
  1619. Nothing.
  1620. --*/
  1621. {
  1622. DBGMSG( DBG_TRACE, ( "TPrinterData::vGetSpecialInformation\n" ) );
  1623. if( !_tcscmp( _strDriverName, FAX_DRIVER_NAME ) )
  1624. {
  1625. TStatusB bStatus;
  1626. //
  1627. // Save the fact this is a Fax printer.
  1628. //
  1629. _bIsFaxDriver = TRUE;
  1630. //
  1631. // Create the printer data access class.
  1632. //
  1633. TPrinterDataAccess Data( _strServerName, TPrinterDataAccess::kResourceServer, TPrinterDataAccess::kAccessRead );
  1634. //
  1635. // Relax the return type checking, the spooler just cannot get it right.
  1636. //
  1637. Data.RelaxReturnTypeCheck( TRUE );
  1638. //
  1639. // Initialize the data class.
  1640. //
  1641. bStatus DBGCHK = Data.Init();
  1642. if( bStatus )
  1643. {
  1644. //
  1645. // Assume remote fax is disabled.
  1646. //
  1647. DWORD dwRemoteFax = 1;
  1648. HRESULT hr = Data.Get( SPLREG_REMOTE_FAX, dwRemoteFax );
  1649. if( SUCCEEDED(hr) )
  1650. {
  1651. DBGMSG( DBG_TRACE, ( "TPrinterData::vGetSpecialInformation - RemoteFax %x\n" , dwRemoteFax ) );
  1652. _bHideSharingUI = dwRemoteFax ? FALSE : TRUE;
  1653. }
  1654. }
  1655. }
  1656. //
  1657. // If the printer is a masq printer connected to an http port then hide the sharingUI.
  1658. //
  1659. if( !_bHideSharingUI )
  1660. {
  1661. if( (dwAttributes() & PRINTER_ATTRIBUTE_LOCAL) && (dwAttributes() & PRINTER_ATTRIBUTE_NETWORK) )
  1662. {
  1663. _bHideSharingUI = !_tcsnicmp( _strPortName, gszHttpPrefix0, _tcslen(gszHttpPrefix0) ) ||
  1664. !_tcsnicmp( _strPortName, gszHttpPrefix1, _tcslen(gszHttpPrefix1) );
  1665. }
  1666. }
  1667. }
  1668. /********************************************************************
  1669. Printer info data classes.
  1670. ********************************************************************/
  1671. TPrinterData::TPrinterInfo::
  1672. TPrinterInfo(
  1673. VOID
  1674. ) : _dwAttributes( 0 ),
  1675. _dwPriority( 0 ),
  1676. _dwStartTime( 0 ),
  1677. _dwUntilTime( 0 ),
  1678. _dwAction( 0 ),
  1679. _bPooledPrinting( FALSE )
  1680. {
  1681. DBGMSG( DBG_TRACE, ( "TPrinterData::TPrinterInfo ctor\n" ) );
  1682. }
  1683. TPrinterData::TPrinterInfo::
  1684. ~TPrinterInfo(
  1685. VOID
  1686. )
  1687. {
  1688. DBGMSG( DBG_TRACE, ( "TPrinterData::TPrinterInfo dtor\n" ) );
  1689. }
  1690. BOOL
  1691. TPrinterData::TPrinterInfo::
  1692. bUpdate(
  1693. IN PPRINTER_INFO_2 pInfo
  1694. )
  1695. {
  1696. DBGMSG( DBG_TRACE, ( "TPrinterData::TPrinterInfo::bUpdate 2\n" ) );
  1697. TStatusB bStatus;
  1698. bStatus DBGNOCHK = FALSE;
  1699. if( pInfo )
  1700. {
  1701. bStatus DBGCHK = _strServerName.bUpdate( pInfo->pServerName ) &&
  1702. _strPrinterName.bUpdate( pInfo->pPrinterName ) &&
  1703. _strShareName.bUpdate( pInfo->pShareName ) &&
  1704. _strDriverName.bUpdate( pInfo->pDriverName ) &&
  1705. _strComment.bUpdate( pInfo->pComment ) &&
  1706. _strLocation.bUpdate( pInfo->pLocation ) &&
  1707. _strPortName.bUpdate( pInfo->pPortName ) &&
  1708. _strSepFile.bUpdate( pInfo->pSepFile ) &&
  1709. _strPrintProcessor.bUpdate( pInfo->pPrintProcessor ) &&
  1710. _strDatatype.bUpdate( pInfo->pDatatype );
  1711. //
  1712. // check whether pool printing is enabled
  1713. //
  1714. if( _tcschr( pInfo->pPortName, TEXT( ',' ) ) )
  1715. {
  1716. _bPooledPrinting = TRUE;
  1717. }
  1718. else
  1719. {
  1720. _bPooledPrinting = FALSE;
  1721. }
  1722. _dwAttributes = pInfo->Attributes;
  1723. _dwPriority = pInfo->Priority;
  1724. _dwStartTime = pInfo->StartTime;
  1725. _dwUntilTime = pInfo->UntilTime;
  1726. }
  1727. return bStatus;
  1728. }
  1729. BOOL
  1730. TPrinterData::TPrinterInfo::
  1731. bUpdate(
  1732. IN PPRINTER_INFO_7 pInfo
  1733. )
  1734. {
  1735. DBGMSG( DBG_TRACE, ( "TPrinterData::TPrinterInfo::bUpdate 7\n" ) );
  1736. TStatusB bStatus;
  1737. bStatus DBGNOCHK = FALSE;
  1738. if( pInfo )
  1739. {
  1740. bStatus DBGCHK = _strObjectGUID.bUpdate( pInfo->pszObjectGUID );
  1741. _dwAction = pInfo->dwAction;
  1742. }
  1743. return bStatus;
  1744. }
  1745. /********************************************************************
  1746. Printer property base class for generic services to
  1747. all property pages.
  1748. ********************************************************************/
  1749. TPrinterProp::
  1750. TPrinterProp(
  1751. TPrinterData* pPrinterData
  1752. ) : _pPrinterData( pPrinterData )
  1753. {
  1754. }
  1755. VOID
  1756. TPrinterProp::
  1757. vSetIconName(
  1758. VOID
  1759. )
  1760. /*++
  1761. Routine Description:
  1762. Sets the printer icon to the custom one.
  1763. Arguments:
  1764. hDlg - Modifies this dialog.
  1765. Return Value:
  1766. --*/
  1767. {
  1768. //
  1769. // Set the correct icon; destroy the previous one.
  1770. //
  1771. SendDlgItemMessage(_hDlg, IDC_PRINTER_ICON, STM_SETICON, (WPARAM)(HICON)_pPrinterData->shLargeIcon(), 0);
  1772. LPCTSTR pszServer;
  1773. LPCTSTR pszPrinter;
  1774. TCHAR szScratch[kPrinterBufMax];
  1775. //
  1776. // Split the printer name into its components.
  1777. //
  1778. vPrinterSplitFullName( szScratch,
  1779. _pPrinterData->strPrinterName( ),
  1780. &pszServer,
  1781. &pszPrinter );
  1782. //
  1783. // Set the printer name.
  1784. //
  1785. bSetEditText( _hDlg, IDC_NAME, pszPrinter );
  1786. }
  1787. VOID
  1788. TPrinterProp::
  1789. vReloadPages(
  1790. VOID
  1791. )
  1792. /*++
  1793. Routine Description:
  1794. Something changed (driver or security etc.) so we need to completely
  1795. refresh all printer pages.
  1796. Arguments:
  1797. None.
  1798. Return Value:
  1799. Nothing
  1800. Comments:
  1801. This is currently not implemented.
  1802. --*/
  1803. {
  1804. }
  1805. BOOL
  1806. TPrinterProp::
  1807. bHandleMessage(
  1808. IN UINT uMsg,
  1809. IN WPARAM wParam,
  1810. IN LPARAM lParam
  1811. )
  1812. /*++
  1813. Routine Description:
  1814. Front end for each sheets message handler.
  1815. Arguments:
  1816. uMsg - Window message
  1817. wParam - wParam
  1818. lParam - lParam
  1819. Return Value:
  1820. TRUE message handled, FALSE message not handled.
  1821. --*/
  1822. {
  1823. BOOL bStatus = TRUE;
  1824. switch( uMsg )
  1825. {
  1826. case WM_INITDIALOG:
  1827. bStatus = bHandle_InitDialog( wParam, lParam );
  1828. break;
  1829. case WM_NOTIFY:
  1830. bStatus = bHandle_Notify( wParam, lParam );
  1831. break;
  1832. case WM_SETTINGCHANGE:
  1833. bStatus = bHandle_SettingChange( wParam, lParam );
  1834. break;
  1835. default:
  1836. bStatus = FALSE;
  1837. break;
  1838. }
  1839. //
  1840. // Allow the derived classes to handle the message.
  1841. //
  1842. bStatus = _bHandleMessage( uMsg, wParam, lParam );
  1843. //
  1844. // We must remember the last non-dynamic page here in order
  1845. // to know whether we are in our page or one of the dynamic
  1846. // pages later - (the dynamic pages are the shell extention pages
  1847. // plus the driver pages).
  1848. //
  1849. if( WM_NOTIFY == uMsg )
  1850. {
  1851. LPNMHDR pnmh = (LPNMHDR)lParam;
  1852. if( PSN_SETACTIVE == pnmh->code && 0 == GetWindowLong( _hDlg, DWLP_MSGRESULT ) )
  1853. {
  1854. //
  1855. // If activation is accepted
  1856. //
  1857. _pPrinterData->_hwndLastPageSelected = _hDlg;
  1858. }
  1859. }
  1860. //
  1861. // If the message was handled check if the
  1862. // apply button should be enabled.
  1863. //
  1864. if( bStatus )
  1865. {
  1866. if( _pPrinterData->bCheckForChange() )
  1867. {
  1868. vPropSheetChangedAllPages();
  1869. }
  1870. else
  1871. {
  1872. vPropSheetUnChangedAllPages();
  1873. }
  1874. }
  1875. return bStatus;
  1876. }
  1877. VOID
  1878. TPrinterProp::
  1879. vPropSheetChangedAllPages(
  1880. VOID
  1881. )
  1882. /*++
  1883. Routine Description:
  1884. Indicate that something has changed, we change the state
  1885. for all of our pages since the property sheet code
  1886. stores changed state on a per sheet basis.
  1887. Arguments:
  1888. None.
  1889. Return Value:
  1890. Nothing.
  1891. --*/
  1892. {
  1893. if( _pPrinterData->_bApplyEnableState )
  1894. {
  1895. for ( UINT i = 0; i < COUNTOF( _pPrinterData->_hwndPages ); i++ )
  1896. {
  1897. if( _pPrinterData->_hwndPages[i] )
  1898. {
  1899. PropSheet_Changed( GetParent( _hDlg ), _pPrinterData->_hwndPages[i] );
  1900. }
  1901. }
  1902. }
  1903. }
  1904. VOID
  1905. TPrinterProp::
  1906. vPropSheetUnChangedAllPages(
  1907. VOID
  1908. )
  1909. /*++
  1910. Routine Description:
  1911. Indicate we are back in the original state we change the state
  1912. for all of our pages since the property sheet code
  1913. stores changed or unchanged state on a per sheet basis.
  1914. Arguments:
  1915. None.
  1916. Return Value:
  1917. Nothing.
  1918. --*/
  1919. {
  1920. if( _pPrinterData->_bApplyEnableState )
  1921. {
  1922. for ( UINT i = 0; i < COUNTOF( _pPrinterData->_hwndPages ); i++ )
  1923. {
  1924. if( _pPrinterData->_hwndPages[i] )
  1925. {
  1926. PropSheet_UnChanged( GetParent( _hDlg ), _pPrinterData->_hwndPages[i] );
  1927. }
  1928. }
  1929. }
  1930. }
  1931. VOID
  1932. TPrinterProp::
  1933. vSetApplyState(
  1934. IN BOOL bNewApplyState
  1935. )
  1936. /*++
  1937. Routine Description:
  1938. Sets the current apply state. If the apply state is disable
  1939. then the apply button is always disabled.
  1940. Arguments:
  1941. bNewApplyState - TRUE enabled, FALSE disabled.
  1942. Return Value:
  1943. Nothing.
  1944. --*/
  1945. {
  1946. //
  1947. // Save the current apply enable state.
  1948. //
  1949. _pPrinterData->_bApplyEnableState = bNewApplyState;
  1950. //
  1951. // Either enable or disable the apply state.
  1952. //
  1953. SendMessage( GetParent(_hDlg), bNewApplyState ? PSM_ENABLEAPPLY : PSM_DISABLEAPPLY, 0, 0);
  1954. }
  1955. BOOL
  1956. TPrinterProp::
  1957. bHandle_InitDialog(
  1958. IN WPARAM wParam,
  1959. IN LPARAM lParam
  1960. )
  1961. /*++
  1962. Routine Description:
  1963. Handles init dialog message.
  1964. Arguments:
  1965. wParam - wParam
  1966. lParam - lParam
  1967. Return Value:
  1968. TRUE message handled, FALSE message not handled.
  1969. --*/
  1970. {
  1971. //
  1972. // Save the handles to all the activated pages.
  1973. ///
  1974. _pPrinterData->_hwndPages[_pPrinterData->_uMaxActiveCount] = _hDlg;
  1975. //
  1976. // Count the activated pages.
  1977. //
  1978. ++_pPrinterData->_uMaxActiveCount;
  1979. ++_pPrinterData->_uActiveCount;
  1980. //
  1981. // Inform the property sheet manager what are parent handle is.
  1982. //
  1983. _pPrinterData->_pPrinterPropertySheetManager->vSetParentHandle( GetParent( _hDlg ) );
  1984. return TRUE;
  1985. }
  1986. BOOL
  1987. TPrinterProp::
  1988. bHandle_Notify(
  1989. IN WPARAM wParam,
  1990. IN LPARAM lParam
  1991. )
  1992. /*++
  1993. Routine Description:
  1994. Handles notify messages.
  1995. Arguments:
  1996. wParam - wParam
  1997. lParam - lParam
  1998. Return Value:
  1999. TRUE message handled, FALSE message not handled.
  2000. --*/
  2001. {
  2002. BOOL bStatus = TRUE;
  2003. LPNMHDR pnmh = (LPNMHDR)lParam;
  2004. switch( pnmh->code )
  2005. {
  2006. //
  2007. // The last chance apply message is sent in reverse order page n to page 0.
  2008. //
  2009. // We listen to this message when the apply button state is disabled due
  2010. // to the user changing the printer name. Since we are the first page
  2011. // in the set of property sheets we can gaurentee that the last PSN_LASTCHANCEAPPLY
  2012. // message will be the last message for all the pages, thus at this time it is
  2013. // safe to the printer.
  2014. //
  2015. case PSN_LASTCHANCEAPPLY:
  2016. DBGMSG( DBG_TRACE, ( "TPrinterProp::bHandleMessage PSN_LASTCHANCEAPPLY\n" ) );
  2017. if(!_pPrinterData->_bApplyEnableState)
  2018. {
  2019. vApplyChanges();
  2020. }
  2021. break;
  2022. //
  2023. // The apply message is sent in forward order page 0 to page n.
  2024. //
  2025. case PSN_APPLY:
  2026. DBGMSG( DBG_TRACE, ( "TPrinterProp::bHandleMessage PSN_APPLY\n" ) );
  2027. if(_pPrinterData->_bApplyEnableState)
  2028. {
  2029. vApplyChanges();
  2030. }
  2031. break;
  2032. default:
  2033. bStatus = FALSE;
  2034. break;
  2035. }
  2036. return bStatus;
  2037. }
  2038. BOOL
  2039. TPrinterProp::
  2040. bHandle_SettingChange(
  2041. IN WPARAM wParam,
  2042. IN LPARAM lParam
  2043. )
  2044. /*++
  2045. Routine Description:
  2046. Handles setting change message.
  2047. Arguments:
  2048. wParam - wParam
  2049. lParam - lParam
  2050. Return Value:
  2051. TRUE message handled, FALSE message not handled.
  2052. --*/
  2053. {
  2054. HWND hCtrl;
  2055. BOOL bDefaultPrinter;
  2056. //
  2057. // WM_SETTINGCHANGE is posted to every page but we only execute the function once. This
  2058. // is because we change _bDefaultPrinter only once.
  2059. //
  2060. bDefaultPrinter = CheckDefaultPrinter( _pPrinterData->strCurrentPrinterName() ) == kDefault;
  2061. if( _pPrinterData->bDefaultPrinter() ^ bDefaultPrinter )
  2062. {
  2063. //
  2064. // If the default printer setting is changed and it related to
  2065. // current printer, change the window icon
  2066. //
  2067. _pPrinterData->bDefaultPrinter() = bDefaultPrinter;
  2068. CAutoHandleIcon shIconLarge, shIconSmall;
  2069. LoadPrinterIcons(_pPrinterData->strCurrentPrinterName(), &shIconLarge, &shIconSmall);
  2070. if( shIconLarge && shIconSmall )
  2071. {
  2072. _pPrinterData->shLargeIcon() = shIconLarge.Detach();
  2073. _pPrinterData->shSmallIcon() = shIconSmall.Detach();
  2074. //
  2075. // Change the printer icon to each page which has printer icon control.
  2076. //
  2077. for ( UINT i = 0; i < COUNTOF( _pPrinterData->_hwndPages ); i++ )
  2078. {
  2079. if( _pPrinterData->_hwndPages[i] &&
  2080. (hCtrl = GetDlgItem( _pPrinterData->_hwndPages[i], IDC_PRINTER_ICON )) )
  2081. {
  2082. SendMessage(hCtrl, STM_SETICON, (WPARAM)(HICON)_pPrinterData->shLargeIcon(), 0);
  2083. InvalidateRect(hCtrl, NULL, FALSE);
  2084. }
  2085. }
  2086. }
  2087. }
  2088. return FALSE;
  2089. }
  2090. VOID
  2091. TPrinterProp::
  2092. vApplyChanges(
  2093. VOID
  2094. )
  2095. /*++
  2096. Routine Description:
  2097. This routine applies the changes if this is the last active page
  2098. or the caller specified a force flag to do the apply changes now.
  2099. Arguments:
  2100. bForceApplyNow - TRUE apply the changes now, FALSE wait for last active page.
  2101. Return Value:
  2102. Nothing.
  2103. --*/
  2104. {
  2105. if (!--_pPrinterData->_uActiveCount)
  2106. {
  2107. //
  2108. // Reset the active page count.
  2109. //
  2110. _pPrinterData->_uActiveCount = _pPrinterData->_uMaxActiveCount;
  2111. //
  2112. // Only save the options if we have rights to change settings.
  2113. //
  2114. if (_pPrinterData->bAdministrator())
  2115. {
  2116. //
  2117. // Save the printer data to the spooler.
  2118. //
  2119. BOOL bStatus = _pPrinterData->bSave();
  2120. if (!bStatus)
  2121. {
  2122. //
  2123. // Display error message to the user.
  2124. //
  2125. iMessage( _hDlg,
  2126. IDS_ERR_PRINTER_PROP_TITLE,
  2127. IDS_ERR_SAVE_PRINTER,
  2128. MB_OK|MB_ICONSTOP,
  2129. kMsgGetLastError,
  2130. gaMsgErrMapSetPrinter );
  2131. }
  2132. else
  2133. {
  2134. //
  2135. // Inform the active pages to refresh themselves.
  2136. //
  2137. vNotifyActivePagesToRefresh();
  2138. //
  2139. // Re-enable the apply state.
  2140. //
  2141. _pPrinterData->_bApplyEnableState = TRUE;
  2142. }
  2143. //
  2144. // If settings are saved successfully.
  2145. //
  2146. vSetDlgMsgResult( !bStatus ? PSNRET_INVALID_NOCHANGEPAGE : PSNRET_NOERROR );
  2147. }
  2148. }
  2149. }
  2150. VOID
  2151. TPrinterProp::
  2152. vNotifyActivePagesToRefresh(
  2153. VOID
  2154. )
  2155. /*++
  2156. Routine Description:
  2157. Notify the active pages that they should refresh themselves.
  2158. Arguments:
  2159. None.
  2160. Return Value:
  2161. Nothing.
  2162. --*/
  2163. {
  2164. for ( UINT i = 0; i < COUNTOF( _pPrinterData->_hwndPages ); i++ )
  2165. {
  2166. if( _pPrinterData->_hwndPages[i] )
  2167. {
  2168. PostMessage( _pPrinterData->_hwndPages[i], WM_APP, 0, 0 );
  2169. }
  2170. }
  2171. }
  2172. /*++
  2173. Routine Name:
  2174. vCancelToClose
  2175. Routine Description:
  2176. Change the cancel button to close, the user has basically
  2177. made a change that cannot be undone using the cancel button.
  2178. Arguments:
  2179. None.
  2180. Return Value:
  2181. Nothing.
  2182. --*/
  2183. VOID
  2184. TPrinterProp::
  2185. vCancelToClose(
  2186. VOID
  2187. )
  2188. {
  2189. PropSheet_CancelToClose( GetParent( _hDlg ) );
  2190. }
  2191. /********************************************************************
  2192. General.
  2193. ********************************************************************/
  2194. TPrinterGeneral::
  2195. TPrinterGeneral(
  2196. TPrinterData* pPrinterData
  2197. ) : TPrinterProp( pPrinterData ),
  2198. _bSetUIDone( FALSE ),
  2199. _pLocationDlg (NULL)
  2200. {
  2201. }
  2202. TPrinterGeneral::
  2203. ~TPrinterGeneral(
  2204. VOID
  2205. )
  2206. {
  2207. delete _pLocationDlg;
  2208. }
  2209. BOOL
  2210. TPrinterGeneral::
  2211. bValid(
  2212. VOID
  2213. )
  2214. {
  2215. return TPrinterProp::bValid();
  2216. }
  2217. BOOL
  2218. TPrinterGeneral::
  2219. bSetUI(
  2220. VOID
  2221. )
  2222. {
  2223. // subclass the edit control to workaround a bug
  2224. if( !m_wndComment.IsAttached() )
  2225. {
  2226. VERIFY(m_wndComment.Attach(GetDlgItem(hDlg(), IDC_COMMENT)));
  2227. }
  2228. //
  2229. // Update the fields.
  2230. //
  2231. bSetEditText( _hDlg, IDC_COMMENT, _pPrinterData->strComment());
  2232. bSetEditText( _hDlg, IDC_LOCATION, _pPrinterData->strLocation());
  2233. bSetEditText( _hDlg, IDC_MODEL_NAME, _pPrinterData->strDriverName());
  2234. //
  2235. // When we are not an administrator set the edit controls to read only
  2236. // rather and disabled. They are easier to read in read only mode.
  2237. //
  2238. SendDlgItemMessage( _hDlg, IDC_COMMENT, EM_SETREADONLY, !_pPrinterData->bAdministrator(), 0);
  2239. SendDlgItemMessage( _hDlg, IDC_LOCATION,EM_SETREADONLY, !_pPrinterData->bAdministrator(), 0);
  2240. SendDlgItemMessage( _hDlg, IDC_NAME, EM_SETREADONLY, !_pPrinterData->bAdministrator(), 0);
  2241. //
  2242. // We do not support renaming of masq printers, this is done because the leading \\ on
  2243. // masq printers is neccessary for the folder code to determine if the printer is the
  2244. // special masq printer case. The folder code does this check because to get the printer
  2245. // attributes for every printer would slow down the code excessivly.
  2246. //
  2247. if( _pPrinterData->_dwAttributes & PRINTER_ATTRIBUTE_LOCAL && _pPrinterData->_dwAttributes & PRINTER_ATTRIBUTE_NETWORK )
  2248. {
  2249. SendDlgItemMessage( _hDlg, IDC_NAME, EM_SETREADONLY, TRUE, 0);
  2250. }
  2251. else
  2252. {
  2253. vCheckForSharedMasqPrinter();
  2254. }
  2255. //
  2256. // Create the find dialog.
  2257. //
  2258. _pLocationDlg = new TFindLocDlg;
  2259. if (VALID_PTR(_pLocationDlg) && TPhysicalLocation::bLocationEnabled() && TDirectoryService::bIsDsAvailable())
  2260. {
  2261. EnableWindow (GetDlgItem (_hDlg, IDC_BROWSE_LOCATION), _pPrinterData->bAdministrator());
  2262. }
  2263. else
  2264. {
  2265. //
  2266. // If no DS is available, hide the Browse button and extend the location
  2267. // edit control appropriately
  2268. RECT rcComment;
  2269. RECT rcLocation;
  2270. HWND hLoc;
  2271. hLoc = GetDlgItem (_hDlg, IDC_LOCATION);
  2272. GetWindowRect (GetDlgItem (_hDlg, IDC_COMMENT), &rcComment);
  2273. GetWindowRect (hLoc, &rcLocation);
  2274. SetWindowPos (hLoc,
  2275. NULL,
  2276. 0,0,
  2277. rcComment.right-rcComment.left,
  2278. rcLocation.bottom-rcLocation.top,
  2279. SWP_NOMOVE|SWP_NOZORDER);
  2280. ShowWindow (GetDlgItem (_hDlg, IDC_BROWSE_LOCATION), SW_HIDE);
  2281. }
  2282. //
  2283. // Set the pinter name limit text.
  2284. //
  2285. SendDlgItemMessage( _hDlg, IDC_NAME, EM_SETLIMITTEXT, kPrinterLocalNameMax, 0 );
  2286. //
  2287. // Set the comment limit text to 255. A printer with a comment string
  2288. // longer than 255 characters cannot be shared.
  2289. //
  2290. SendDlgItemMessage( _hDlg, IDC_COMMENT, EM_SETLIMITTEXT, kPrinterCommentBufMax, 0 );
  2291. //
  2292. // What the heck lets be consistent and make the location string
  2293. // have a limit.
  2294. //
  2295. SendDlgItemMessage( _hDlg, IDC_LOCATION, EM_SETLIMITTEXT, kPrinterLocationBufMax, 0 );
  2296. //
  2297. // If the driver pages failed to load or the user did not
  2298. // want to load them then hide the devmode editor UI
  2299. // because you need a driver to show the dev mode editor.
  2300. //
  2301. if( _pPrinterData->_bDriverPagesNotLoaded )
  2302. {
  2303. ShowWindow( GetDlgItem( _hDlg, IDC_PER_USER_DOCUMENT_DEFAULTS ), SW_HIDE );
  2304. }
  2305. //
  2306. // The test page button does not apply for the fax printer.
  2307. //
  2308. if( _pPrinterData->_bIsFaxDriver )
  2309. {
  2310. WINDOWPLACEMENT wndpl;
  2311. wndpl.length = sizeof( wndpl );
  2312. GetWindowPlacement( GetDlgItem( _hDlg, IDC_TEST ), &wndpl );
  2313. SetWindowPlacement( GetDlgItem( _hDlg, IDC_PER_USER_DOCUMENT_DEFAULTS ), &wndpl );
  2314. ShowWindow( GetDlgItem( _hDlg, IDC_TEST ), SW_HIDE );
  2315. }
  2316. //
  2317. // Display the features information.
  2318. //
  2319. vReloadFeaturesInformation();
  2320. //
  2321. // There are a few UI elements that need to be set when
  2322. // we are activated, because of a driver change. We
  2323. // will artifically do it now.
  2324. //
  2325. vSetActive();
  2326. //
  2327. // Indicate SetUI is done. This is used to
  2328. // prevent ReadUI from reading junk since edit controls
  2329. // recieve EN_CHANGE messages while in WM_INITDIALOG
  2330. //
  2331. _bSetUIDone = TRUE;
  2332. return TRUE;
  2333. }
  2334. VOID
  2335. TPrinterGeneral::
  2336. vReloadFeaturesInformation(
  2337. VOID
  2338. )
  2339. {
  2340. TStatusB bStatus;
  2341. UINT uValidFeatureCount = 0;
  2342. //
  2343. // Create the printer data access class.
  2344. //
  2345. TPrinterDataAccess Data( _pPrinterData->_hPrinter );
  2346. //
  2347. // Relax the return type checking, BOOL are not REG_DWORD but REG_BINARY
  2348. //
  2349. Data.RelaxReturnTypeCheck( TRUE );
  2350. //
  2351. // Initialize the data class.
  2352. //
  2353. bStatus DBGCHK = Data.Init();
  2354. if( bStatus )
  2355. {
  2356. TString strYes;
  2357. TString strNo;
  2358. TString strTemp;
  2359. TString strTemp1;
  2360. TString strUnknown;
  2361. TString strPPM;
  2362. TString strDPI;
  2363. HRESULT hr;
  2364. BOOL bValue;
  2365. DWORD dwValue;
  2366. LPCTSTR pszString;
  2367. bStatus DBGCHK = strUnknown.bLoadString( ghInst, IDS_FEATURE_UNKNOWN );
  2368. bStatus DBGCHK = strYes.bLoadString( ghInst, IDS_YES );
  2369. bStatus DBGCHK = strNo.bLoadString( ghInst, IDS_NO );
  2370. bStatus DBGCHK = strPPM.bLoadString( ghInst, IDS_SPEED_UNITS );
  2371. bStatus DBGCHK = strDPI.bLoadString( ghInst, IDS_RESOLUTION_UNITS );
  2372. hr = Data.Get( SPLDS_DRIVER_KEY, SPLDS_PRINT_COLOR, bValue );
  2373. uValidFeatureCount = SUCCEEDED(hr) ? uValidFeatureCount+1 : uValidFeatureCount;
  2374. bStatus DBGCHK = strTemp.bLoadString( ghInst, IDS_COLOR );
  2375. bStatus DBGCHK = strTemp.bCat( gszSpace );
  2376. bStatus DBGCHK = strTemp.bCat( FAILED(hr) ? strUnknown : bValue ? strYes : strNo );
  2377. bStatus DBGCHK = bSetEditText( _hDlg, IDC_COLOR, strTemp );
  2378. hr = Data.Get( SPLDS_DRIVER_KEY, SPLDS_PRINT_DUPLEX_SUPPORTED, bValue );
  2379. uValidFeatureCount = SUCCEEDED(hr) ? uValidFeatureCount+1 : uValidFeatureCount;
  2380. bStatus DBGCHK = strTemp.bLoadString( ghInst, IDS_DUPLEX );
  2381. bStatus DBGCHK = strTemp.bCat( gszSpace );
  2382. bStatus DBGCHK = strTemp.bCat( FAILED(hr) ? strUnknown : bValue ? strYes : strNo );
  2383. bStatus DBGCHK = bSetEditText( _hDlg, IDC_DUPLEX, strTemp );
  2384. hr = Data.Get( SPLDS_DRIVER_KEY, SPLDS_PRINT_STAPLING_SUPPORTED, bValue );
  2385. uValidFeatureCount = SUCCEEDED(hr) ? uValidFeatureCount+1 : uValidFeatureCount;
  2386. bStatus DBGCHK = strTemp.bLoadString( ghInst, IDS_STAPLE );
  2387. bStatus DBGCHK = strTemp.bCat( gszSpace );
  2388. bStatus DBGCHK = strTemp.bCat( FAILED(hr) ? strUnknown : bValue ? strYes : strNo );
  2389. bSetEditText( _hDlg, IDC_STAPLE, strTemp );
  2390. hr = Data.Get( SPLDS_DRIVER_KEY, SPLDS_PRINT_PAGES_PER_MINUTE, dwValue );
  2391. uValidFeatureCount = SUCCEEDED(hr) ? uValidFeatureCount+1 : uValidFeatureCount;
  2392. bStatus DBGCHK = strTemp.bLoadString( ghInst, IDS_SPEED );
  2393. bStatus DBGCHK = strTemp.bCat( gszSpace );
  2394. bStatus DBGCHK = strTemp.bCat( FAILED(hr) ? strUnknown : strTemp1.bFormat( _T("%d %s"), dwValue, (LPCTSTR)strPPM ) ? strTemp1 : gszNULL );
  2395. bStatus DBGCHK = bSetEditText( _hDlg, IDC_SPEED, strTemp );
  2396. hr = Data.Get( SPLDS_DRIVER_KEY, SPLDS_PRINT_MAX_RESOLUTION_SUPPORTED, dwValue );
  2397. uValidFeatureCount = SUCCEEDED(hr) ? uValidFeatureCount+1 : uValidFeatureCount;
  2398. bStatus DBGCHK = strTemp.bLoadString( ghInst, IDS_RESOLUTION );
  2399. bStatus DBGCHK = strTemp.bCat( gszSpace );
  2400. bStatus DBGCHK = strTemp.bCat( FAILED(hr) ? strUnknown : strTemp1.bFormat( _T("%d %s"), dwValue, (LPCTSTR)strDPI ) ? strTemp1 : gszNULL );
  2401. bStatus DBGCHK = bSetEditText( _hDlg, IDC_RESOLUTION, strTemp );
  2402. TString *pStrings = NULL;
  2403. UINT nCount = 0;
  2404. hr = Data.Get( SPLDS_DRIVER_KEY, SPLDS_PRINT_MEDIA_READY, &pStrings, nCount );
  2405. uValidFeatureCount = SUCCEEDED(hr) ? uValidFeatureCount+1 : uValidFeatureCount;
  2406. TString strMediaReady;
  2407. if( SUCCEEDED(hr) )
  2408. {
  2409. for( UINT i = 0; i < nCount; i++ )
  2410. {
  2411. DBGMSG( DBG_TRACE, ( "Media ready " TSTR ".\n", (LPCTSTR)pStrings[i] ) );
  2412. bStatus DBGCHK = strMediaReady.bCat( pStrings[i] );
  2413. if( i != (nCount-1) )
  2414. {
  2415. //
  2416. // If it is not the last media type, add CRLF symbols at the end
  2417. //
  2418. bStatus DBGCHK = strMediaReady.bCat( _T("\r\n" ));
  2419. }
  2420. }
  2421. }
  2422. //
  2423. // We are updating the "Paper Available" regardless of whether
  2424. // the GetPrinterDataEx( ... ) succeeds or fails.
  2425. //
  2426. bStatus DBGCHK = bSetEditText( _hDlg, IDC_PAPER_SIZE_LIST, strMediaReady );
  2427. delete [] pStrings;
  2428. }
  2429. if( !uValidFeatureCount )
  2430. {
  2431. ShowWindow( GetDlgItem( _hDlg, IDC_COLOR ), SW_HIDE );
  2432. ShowWindow( GetDlgItem( _hDlg, IDC_DUPLEX ), SW_HIDE );
  2433. ShowWindow( GetDlgItem( _hDlg, IDC_STAPLE ), SW_HIDE );
  2434. ShowWindow( GetDlgItem( _hDlg, IDC_SPEED ), SW_HIDE );
  2435. ShowWindow( GetDlgItem( _hDlg, IDC_RESOLUTION ), SW_HIDE );
  2436. ShowWindow( GetDlgItem( _hDlg, IDC_PAPER_SIZE_LIST ), SW_HIDE );
  2437. ShowWindow( GetDlgItem( _hDlg, IDC_GBOX_FEATURES ), SW_HIDE );
  2438. ShowWindow( GetDlgItem( _hDlg, IDC_PAPER_SIZE ), SW_HIDE );
  2439. }
  2440. }
  2441. VOID
  2442. TPrinterGeneral::
  2443. vReadUI(
  2444. VOID
  2445. )
  2446. {
  2447. if( !bGetEditText( _hDlg, IDC_COMMENT, _pPrinterData->strComment( )) ||
  2448. !bGetEditText( _hDlg, IDC_LOCATION, _pPrinterData->strLocation( )) ||
  2449. !bGetEditText( _hDlg, IDC_NAME, _pPrinterData->strPrinterName( )))
  2450. {
  2451. //
  2452. // If we cannot read from any of the edit controls then set the
  2453. // error flag.
  2454. //
  2455. _pPrinterData->_bErrorSaving = FALSE;
  2456. //
  2457. // Unable to read the text.
  2458. //
  2459. vShowResourceError( _hDlg );
  2460. //
  2461. // Don't swith the page.
  2462. //
  2463. vSetDlgMsgResult( TRUE );
  2464. }
  2465. else
  2466. {
  2467. //
  2468. // Remove any trailing slashes from the location string
  2469. //
  2470. TPhysicalLocation::vTrimSlash (_pPrinterData->strLocation());
  2471. }
  2472. }
  2473. VOID
  2474. TPrinterGeneral::
  2475. vSetActive(
  2476. VOID
  2477. )
  2478. {
  2479. //
  2480. // Set the icon and printer name.
  2481. //
  2482. vSetIconName();
  2483. //
  2484. // Reload the features information.
  2485. //
  2486. vReloadFeaturesInformation();
  2487. //
  2488. // Set the new printer driver name.
  2489. //
  2490. bSetEditText( _hDlg, IDC_MODEL_NAME, _pPrinterData->strDriverName( ));
  2491. }
  2492. VOID
  2493. TPrinterGeneral::
  2494. vKillActive(
  2495. VOID
  2496. )
  2497. {
  2498. //
  2499. // Do not validate the printer name if IDC_NAME field is readonly,
  2500. // which means either one of the following:
  2501. //
  2502. // 1. The printer is masq printer
  2503. // 2. The printer is shared masq printer
  2504. //
  2505. if( ES_READONLY & GetWindowLong(GetDlgItem(_hDlg, IDC_NAME), GWL_STYLE) )
  2506. return;
  2507. //
  2508. // Only validate the printer name if we are an administrator
  2509. //
  2510. if( _pPrinterData->bAdministrator() )
  2511. {
  2512. //
  2513. // Strip any trailing white space.
  2514. //
  2515. vStripTrailWhiteSpace( (LPTSTR)(LPCTSTR)_pPrinterData->_strPrinterName );
  2516. //
  2517. // Check if the name is null.
  2518. //
  2519. if( _pPrinterData->_strPrinterName.bEmpty( ) ){
  2520. iMessage( _hDlg,
  2521. IDS_ERR_PRINTER_PROP_TITLE,
  2522. IDS_ERR_NO_PRINTER_NAME,
  2523. MB_OK|MB_ICONEXCLAMATION,
  2524. kMsgNone,
  2525. NULL );
  2526. vSetDlgMsgResult( TRUE );
  2527. return;
  2528. }
  2529. //
  2530. // Validate the printer name for any illegal characters.
  2531. //
  2532. if( !bIsLocalPrinterNameValid( _pPrinterData->strPrinterName( ) ) )
  2533. {
  2534. //
  2535. // Put up error explaining that at least one port must be
  2536. // selected.
  2537. //
  2538. iMessage( _hDlg,
  2539. IDS_ERR_PRINTER_PROP_TITLE,
  2540. IDS_ERR_BAD_PRINTER_NAME,
  2541. MB_OK|MB_ICONSTOP,
  2542. kMsgNone,
  2543. NULL );
  2544. //
  2545. // Don't swith the page.
  2546. //
  2547. vSetDlgMsgResult( TRUE );
  2548. }
  2549. }
  2550. }
  2551. VOID
  2552. TPrinterGeneral::
  2553. vCheckForSharedMasqPrinter(
  2554. VOID
  2555. )
  2556. {
  2557. //
  2558. // check if it is a shared masq printer - which means that the printer name may
  2559. // contains invalid symbols
  2560. //
  2561. LPCTSTR pszServer;
  2562. LPCTSTR pszPrinter;
  2563. TCHAR szScratch[kPrinterBufMax];
  2564. vPrinterSplitFullName( szScratch,
  2565. _pPrinterData->strPrinterName( ),
  2566. &pszServer,
  2567. &pszPrinter );
  2568. if( !bIsLocalPrinterNameValid( pszPrinter ) )
  2569. {
  2570. SendDlgItemMessage( _hDlg, IDC_NAME, EM_SETREADONLY, TRUE, 0);
  2571. }
  2572. }
  2573. BOOL
  2574. TPrinterGeneral::
  2575. _bHandleMessage(
  2576. IN UINT uMsg,
  2577. IN WPARAM wParam,
  2578. IN LPARAM lParam
  2579. )
  2580. {
  2581. TStatusB bStatus;
  2582. bStatus DBGNOCHK = TRUE;
  2583. switch( uMsg ){
  2584. case WM_INITDIALOG:
  2585. bStatus DBGCHK = bSetUI();
  2586. break;
  2587. case WM_HELP:
  2588. case WM_CONTEXTMENU:
  2589. bStatus DBGCHK = PrintUIHelp( uMsg, _hDlg, wParam, lParam );
  2590. break;
  2591. case WM_CLOSE:
  2592. //
  2593. // Multiline edit controls send WM_CLOSE to dismiss the dialog.
  2594. // Convert it to a property-page friendly message.
  2595. //
  2596. PropSheet_PressButton( GetParent( _hDlg ), PSBTN_CANCEL );
  2597. break;
  2598. case WM_APP:
  2599. vSetActive();
  2600. break;
  2601. case WM_COMMAND:
  2602. switch( GET_WM_COMMAND_ID( wParam, lParam )){
  2603. case IDC_COMMENT:
  2604. case IDC_LOCATION:
  2605. bStatus DBGNOCHK = GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE;
  2606. break;
  2607. case IDC_NAME:
  2608. {
  2609. bStatus DBGNOCHK = GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE;
  2610. //
  2611. // When the printer name changes we disable the apply button because
  2612. // we have no way to inform the extention tabs the printer name has changed.
  2613. //
  2614. TString str;
  2615. if( bGetEditText( _hDlg, IDC_NAME, str ) )
  2616. {
  2617. vSetApplyState( !_pPrinterData->ComparePrinterName( str, _pPrinterData->strCurrentPrinterName() ));
  2618. }
  2619. break;
  2620. }
  2621. case IDC_TEST:
  2622. {
  2623. //
  2624. // If this is a masq printer we do need to check the name
  2625. // for trailing spaces. In this case the original share name
  2626. // is actually the port name.
  2627. //
  2628. LPCTSTR pszOrigShareName = NULL;
  2629. if( _pPrinterData->_dwAttributes & PRINTER_ATTRIBUTE_NETWORK &&
  2630. _pPrinterData->_dwAttributes & PRINTER_ATTRIBUTE_LOCAL )
  2631. {
  2632. pszOrigShareName = _pPrinterData->strPortName();
  2633. }
  2634. bPrintTestPage( _hDlg, _pPrinterData->strCurrentPrinterName(), pszOrigShareName );
  2635. }
  2636. break;
  2637. case IDC_PER_USER_DOCUMENT_DEFAULTS:
  2638. vHandleDocumentDefaults( wParam, lParam );
  2639. break;
  2640. case IDC_BROWSE_LOCATION:
  2641. vHandleBrowseLocation();
  2642. break;
  2643. default:
  2644. bStatus DBGNOCHK = FALSE;
  2645. break;
  2646. }
  2647. break;
  2648. case WM_NOTIFY:
  2649. {
  2650. LPNMHDR pnmh = (LPNMHDR)lParam;
  2651. switch( pnmh->code ){
  2652. case PSN_KILLACTIVE:
  2653. vKillActive();
  2654. break;
  2655. default:
  2656. bStatus DBGNOCHK = FALSE;
  2657. break;
  2658. }
  2659. }
  2660. break;
  2661. default:
  2662. bStatus DBGNOCHK = FALSE;
  2663. break;
  2664. }
  2665. if( bStatus && _bSetUIDone )
  2666. {
  2667. vReadUI();
  2668. }
  2669. return bStatus;
  2670. }
  2671. VOID
  2672. TPrinterGeneral::
  2673. vHandleDocumentDefaults(
  2674. IN WPARAM wParam,
  2675. IN LPARAM lParam
  2676. )
  2677. /*++
  2678. Routine Description:
  2679. Handle launching document defaults dialog.
  2680. Arguments:
  2681. wParam - Parameter passed to by dialog proc.
  2682. lParam - Parameter passed to by dialog proc.
  2683. Return Value:
  2684. Nothing.
  2685. --*/
  2686. {
  2687. (VOID)dwDocumentDefaultsInternal( _hDlg,
  2688. _pPrinterData->strCurrentPrinterName(),
  2689. SW_SHOW,
  2690. 0,
  2691. 0,
  2692. FALSE );
  2693. }
  2694. VOID
  2695. TPrinterGeneral::
  2696. vHandleBrowseLocation(
  2697. VOID
  2698. )
  2699. /*++
  2700. Routine Description:
  2701. Handle displaying the location tree dialog.
  2702. Arguments:
  2703. wParam - Parameter passed to by dialog proc.
  2704. lParam - Parameter passed to by dialog proc.
  2705. Return Value:
  2706. Nothing.
  2707. --*/
  2708. {
  2709. TStatusB bStatus;
  2710. TString strDefault = _pPrinterData->strLocation();
  2711. //
  2712. // bDoModal returns FALSE on Cancel
  2713. //
  2714. bStatus DBGNOCHK = _pLocationDlg->bDoModal(_hDlg, &strDefault);
  2715. if (bStatus)
  2716. {
  2717. TString strLocation;
  2718. bStatus DBGCHK = _pLocationDlg->bGetLocation (strLocation);
  2719. if (bStatus && !strLocation.bEmpty())
  2720. {
  2721. //
  2722. // Check to append a trailing slash
  2723. //
  2724. UINT uLen = strLocation.uLen();
  2725. if( uLen && gchSeparator != static_cast<LPCTSTR>(strLocation)[uLen-1] )
  2726. {
  2727. static const TCHAR szSepStr[] = { gchSeparator };
  2728. bStatus DBGCHK = strLocation.bCat( szSepStr );
  2729. }
  2730. bStatus DBGCHK = bSetEditText (_hDlg, IDC_LOCATION, strLocation);
  2731. }
  2732. //
  2733. // Set focus to the edit control for location, even if setedittext failed
  2734. // Assumption is that user probably still wants to modify locations
  2735. //
  2736. SetFocus (GetDlgItem (_hDlg, IDC_LOCATION));
  2737. //
  2738. // Place the caret at the end of the text, for appending
  2739. //
  2740. SendDlgItemMessage (_hDlg, IDC_LOCATION, EM_SETSEL, strLocation.uLen(), (LPARAM)-1);
  2741. }
  2742. }
  2743. /********************************************************************
  2744. Printer Ports.
  2745. ********************************************************************/
  2746. TPrinterPorts::
  2747. TPrinterPorts(
  2748. TPrinterData* pPrinterData
  2749. ) : TPrinterProp( pPrinterData ),
  2750. _bAdminFlag( FALSE )
  2751. {
  2752. }
  2753. TPrinterPorts::
  2754. ~TPrinterPorts(
  2755. VOID
  2756. )
  2757. {
  2758. }
  2759. BOOL
  2760. TPrinterPorts::
  2761. bValid(
  2762. VOID
  2763. )
  2764. {
  2765. return _PortsLV.bValid();
  2766. }
  2767. BOOL
  2768. TPrinterPorts::
  2769. bSetUI(
  2770. VOID
  2771. )
  2772. {
  2773. //
  2774. // Initalize the class admin flag. We only allow administring ports
  2775. // on this printer if the user is an admin and the printer is not
  2776. // a masq printer. Masq printer cannot have their ports reassigned,
  2777. // spooler will fail the call, just to make the UI more user friendly
  2778. // we don't let the user do things that we know will fail.
  2779. //
  2780. _bAdminFlag = _pPrinterData->bAdministrator();
  2781. if( (_pPrinterData->dwAttributes() & PRINTER_ATTRIBUTE_LOCAL) && (_pPrinterData->dwAttributes() & PRINTER_ATTRIBUTE_NETWORK) )
  2782. {
  2783. _bAdminFlag = FALSE;
  2784. }
  2785. //
  2786. // Initialize the ports list view.
  2787. //
  2788. if( !_PortsLV.bSetUI( GetDlgItem( _hDlg, IDC_PORTS ), FALSE, TRUE, _bAdminFlag, _hDlg, 0, 0, IDC_PORT_DELETE ) )
  2789. {
  2790. return FALSE;
  2791. }
  2792. //
  2793. // If we do not have access then don't enumerate the ports
  2794. //
  2795. if( !_pPrinterData->bNoAccess() )
  2796. {
  2797. //
  2798. // Load the machine's ports into the listview.
  2799. //
  2800. if( !_PortsLV.bReloadPorts( _pPrinterData->pszServerName() ) )
  2801. {
  2802. return FALSE;
  2803. }
  2804. }
  2805. //
  2806. // Select the current printer's ports.
  2807. //
  2808. _PortsLV.vCheckPorts((LPTSTR)(LPCTSTR)_pPrinterData->strPortName( ));
  2809. //
  2810. // Set the ports list view to single selection mode,
  2811. //
  2812. _PortsLV.vSetSingleSelection( !_pPrinterData->bPooledPrinting() );
  2813. //
  2814. // Set the pooled printing mode on the UI.
  2815. //
  2816. vSetCheck( _hDlg, IDC_POOLED_PRINTING, _pPrinterData->bPooledPrinting() );
  2817. //
  2818. // If we do not have admin privilages or we are remotly
  2819. // administering a downlevel machine, then disable
  2820. // adding / deleting / configuring ports.
  2821. //
  2822. if( !_bAdminFlag || ( bIsRemote( _pPrinterData->pszServerName() ) &&
  2823. GetDriverVersion( _pPrinterData->dwDriverVersion() ) <= 2 ) )
  2824. {
  2825. //
  2826. // Disable things if not administrator.
  2827. //
  2828. vEnableCtl( _hDlg, IDC_PORT_CREATE, FALSE );
  2829. vEnableCtl( _hDlg, IDC_PORT_DELETE, FALSE );
  2830. vEnableCtl( _hDlg, IDC_PROPERTIES, FALSE );
  2831. }
  2832. //
  2833. // Disable bidi selection if not an administrator.
  2834. // Disable printer pooling if not an administrator.
  2835. //
  2836. vEnableCtl( _hDlg, IDC_ENABLE_BIDI, _bAdminFlag );
  2837. vEnableCtl( _hDlg, IDC_POOLED_PRINTING, _bAdminFlag );
  2838. //
  2839. // Enable Configure Port for HTTP printer only
  2840. //
  2841. if( (_pPrinterData->dwAttributes() & PRINTER_ATTRIBUTE_LOCAL) &&
  2842. (_pPrinterData->dwAttributes() & PRINTER_ATTRIBUTE_NETWORK) &&
  2843. (!_tcsnicmp( _pPrinterData->strPortName (), gszHttpPrefix0, _tcslen(gszHttpPrefix0) ) ||
  2844. !_tcsnicmp( _pPrinterData->strPortName (), gszHttpPrefix1, _tcslen(gszHttpPrefix1) )))
  2845. {
  2846. vEnableCtl( _hDlg, IDC_PROPERTIES, TRUE );
  2847. }
  2848. //
  2849. // There are a few UI elements that need to be set when
  2850. // we are activated, because of a driver change. We
  2851. // will artifically do it now.
  2852. //
  2853. vSetActive();
  2854. return TRUE;
  2855. }
  2856. VOID
  2857. TPrinterPorts::
  2858. vReadUI(
  2859. VOID
  2860. )
  2861. /*++
  2862. Routine Description:
  2863. Gets the ports from the listview and create the string.
  2864. Arguments:
  2865. Return Value:
  2866. --*/
  2867. {
  2868. //
  2869. // Read bidi options.
  2870. //
  2871. DWORD dwAttributes = _pPrinterData->dwAttributes();
  2872. if( BST_CHECKED == IsDlgButtonChecked( _hDlg, IDC_ENABLE_BIDI )){
  2873. dwAttributes |= PRINTER_ATTRIBUTE_ENABLE_BIDI;
  2874. } else {
  2875. dwAttributes &= ~PRINTER_ATTRIBUTE_ENABLE_BIDI;
  2876. }
  2877. _pPrinterData->_dwAttributes = dwAttributes;
  2878. //
  2879. // Build the ports string as long as we are an admin.
  2880. //
  2881. if( _bAdminFlag && !_PortsLV.bReadUI( _pPrinterData->_strPortName )){
  2882. _pPrinterData->_bErrorSaving = TRUE;
  2883. vShowResourceError( _hDlg );
  2884. }
  2885. return;
  2886. }
  2887. VOID
  2888. TPrinterPorts::
  2889. vSetActive(
  2890. VOID
  2891. )
  2892. {
  2893. //
  2894. // Set the icon and printer name.
  2895. //
  2896. vSetIconName();
  2897. BOOL bEnable = FALSE;
  2898. BOOL bCheck = FALSE;
  2899. //
  2900. // If the call fails or the monitor name is NULL/szNULL,
  2901. // then disable bidi.
  2902. //
  2903. if( _pPrinterData->bSupportBidi( )){
  2904. bEnable = TRUE;
  2905. //
  2906. // Only set the checkbox if a language monitor is present.
  2907. // (When we change drivers, we always set this attribute
  2908. // bit, even if bidi isn't supported. The spooler and UI
  2909. // ignore it in this case.)
  2910. //
  2911. bCheck = _pPrinterData->dwAttributes() & PRINTER_ATTRIBUTE_ENABLE_BIDI;
  2912. }
  2913. //
  2914. // Set bidi options.
  2915. //
  2916. vSetCheck( _hDlg, IDC_ENABLE_BIDI, bCheck );
  2917. //
  2918. // If we are an administrator and this is the local
  2919. // machine, we can enable the bidi control.
  2920. //
  2921. if( _pPrinterData->bAdministrator( ) ){
  2922. vEnableCtl( _hDlg, IDC_ENABLE_BIDI, bEnable );
  2923. }
  2924. //
  2925. // If the ports list needs to refreshed.
  2926. //
  2927. _PortsLV.bReloadPorts( _pPrinterData->pszServerName(), TRUE );
  2928. }
  2929. BOOL
  2930. TPrinterPorts::
  2931. bKillActive(
  2932. VOID
  2933. )
  2934. /*++
  2935. Routine Description:
  2936. Validate that the printer page is in a consistent state.
  2937. Arguments:
  2938. Return Value:
  2939. TRUE - Ok to kill active, FALSE = can't kill active, UI displayed.
  2940. --*/
  2941. {
  2942. COUNT cPorts;
  2943. //
  2944. // If we do not have access or we are not an administrator
  2945. // do not validate the port selection.
  2946. //
  2947. if( _pPrinterData->bNoAccess() || !_bAdminFlag ){
  2948. return TRUE;
  2949. }
  2950. cPorts = _PortsLV.cSelectedPorts();
  2951. //
  2952. // Validate that at least 1 port is selected.
  2953. // Validate more than 1 port is selected if pooled printing is
  2954. // enabled.
  2955. //
  2956. if( cPorts == 0 )
  2957. {
  2958. //
  2959. // Put up error explaining that at least one port must be
  2960. // selected.
  2961. //
  2962. iMessage( _hDlg,
  2963. IDS_ERR_PRINTER_PROP_TITLE,
  2964. IDS_ERR_NO_PORTS,
  2965. MB_OK|MB_ICONSTOP,
  2966. kMsgNone,
  2967. NULL );
  2968. _PortsLV.vSetFocus();
  2969. //
  2970. // Don't swith the page.
  2971. //
  2972. vSetDlgMsgResult( TRUE );
  2973. }
  2974. else if ( (cPorts == 1) && !_PortsLV.bGetSingleSelection() )
  2975. {
  2976. INT iStatus = iMessage( _hDlg,
  2977. IDS_ERR_PRINTER_PROP_TITLE,
  2978. IDS_ERR_ONLY_ONE_PORT,
  2979. MB_OKCANCEL | MB_ICONWARNING,
  2980. kMsgNone,
  2981. NULL );
  2982. //
  2983. // If user wants to cancel pool printing.
  2984. //
  2985. if( iStatus == IDOK )
  2986. {
  2987. vSetCheck( _hDlg, IDC_POOLED_PRINTING, FALSE );
  2988. _PortsLV.vSetSingleSelection(TRUE);
  2989. _pPrinterData->bPooledPrinting() = FALSE;
  2990. //
  2991. // Read UI data.
  2992. //
  2993. vReadUI();
  2994. }
  2995. else
  2996. {
  2997. _PortsLV.vSetFocus();
  2998. //
  2999. // Don't swith the page.
  3000. //
  3001. vSetDlgMsgResult( TRUE );
  3002. }
  3003. }
  3004. else {
  3005. //
  3006. // Read UI data.
  3007. //
  3008. vReadUI();
  3009. }
  3010. //
  3011. // Routine must return true to see DlgMsgResult corretly.
  3012. //
  3013. return TRUE;
  3014. }
  3015. BOOL
  3016. TPrinterPorts::
  3017. _bHandleMessage(
  3018. IN UINT uMsg,
  3019. IN WPARAM wParam,
  3020. IN LPARAM lParam
  3021. )
  3022. /*++
  3023. Routine Description:
  3024. Handle message.
  3025. Arguments:
  3026. Return Value:
  3027. --*/
  3028. {
  3029. TStatusB bStatus;
  3030. bStatus DBGNOCHK = TRUE;
  3031. switch( uMsg ){
  3032. case WM_INITDIALOG:
  3033. bStatus DBGCHK = bSetUI();
  3034. break;
  3035. case WM_APP:
  3036. vSetActive();
  3037. break;
  3038. case WM_HELP:
  3039. case WM_CONTEXTMENU:
  3040. PrintUIHelp( uMsg, _hDlg, wParam, lParam );
  3041. break;
  3042. case WM_COMMAND:
  3043. switch( GET_WM_COMMAND_ID( wParam, lParam )){
  3044. case IDC_PORT_DELETE:
  3045. {
  3046. //
  3047. // Delete the selected port.
  3048. //
  3049. HWND hwnd = GetDlgItem( _hDlg, IDC_PORT_DELETE );
  3050. //
  3051. // We will only delete the port if the button is enabled, this check is
  3052. // necessary if the user uses the delete key on the keyboard to delete
  3053. // the port.
  3054. //
  3055. if( IsWindowEnabled( hwnd ) )
  3056. {
  3057. bStatus DBGNOCHK = _PortsLV.bDeletePorts( _hDlg, _pPrinterData->pszServerName( ));
  3058. if( bStatus )
  3059. {
  3060. SetFocus( hwnd );
  3061. vCancelToClose();
  3062. }
  3063. }
  3064. }
  3065. break;
  3066. case IDC_PROPERTIES:
  3067. //
  3068. // Configure the selected port.
  3069. //
  3070. bStatus DBGNOCHK = _PortsLV.bConfigurePort( _hDlg, _pPrinterData->pszServerName( ));
  3071. SetFocus( GetDlgItem( _hDlg, IDC_PROPERTIES ) );
  3072. if( bStatus )
  3073. {
  3074. vCancelToClose();
  3075. }
  3076. break;
  3077. case IDC_PORT_CREATE:
  3078. {
  3079. //
  3080. // Create add ports class.
  3081. //
  3082. TAddPort AddPort( _hDlg,
  3083. _pPrinterData->pszServerName(),
  3084. _pPrinterData->bAdministrator() );
  3085. //
  3086. // Insure the add port was created successfully.
  3087. //
  3088. bStatus DBGNOCHK = VALID_OBJ( AddPort );
  3089. if( !bStatus ){
  3090. vShowUnexpectedError( _hDlg, TAddPort::kErrorMessage );
  3091. } else {
  3092. //
  3093. // Display the add port, add monitor UI.
  3094. //
  3095. bStatus DBGNOCHK = AddPort.bDoModal();
  3096. if( bStatus ){
  3097. //
  3098. // Refresh ports listview.
  3099. //
  3100. bStatus DBGNOCHK = _PortsLV.bReloadPorts( _pPrinterData->pszServerName(), TRUE );
  3101. if( bStatus ){
  3102. //
  3103. // A port was added and the list view was reloaded, since this
  3104. // action cannot be undone we will change the cancel button to
  3105. // close.
  3106. //
  3107. vCancelToClose();
  3108. }
  3109. }
  3110. }
  3111. }
  3112. break;
  3113. case IDC_POOLED_PRINTING:
  3114. {
  3115. //
  3116. // Get the current selection state.
  3117. //
  3118. BOOL bSingleSelection; // status of the new state
  3119. bSingleSelection = ( BST_CHECKED == IsDlgButtonChecked( _hDlg, IDC_POOLED_PRINTING ) ? FALSE : TRUE );
  3120. //
  3121. // If we are going from pooled printing to non-pooled printing
  3122. // and the printer is currently being used by multiple ports, inform
  3123. // the user all the port selection will be lost.
  3124. //
  3125. if( bSingleSelection &&
  3126. _PortsLV.cSelectedPorts() > 1 ){
  3127. INT iStatus = iMessage( _hDlg,
  3128. IDS_ERR_PRINTER_PROP_TITLE,
  3129. IDS_ERR_PORT_SEL_CHANGE,
  3130. MB_YESNO|MB_ICONEXCLAMATION,
  3131. kMsgNone,
  3132. NULL );
  3133. //
  3134. // If user does not want to do this.
  3135. //
  3136. if( iStatus != IDYES ){
  3137. vSetCheck( _hDlg, IDC_POOLED_PRINTING, TRUE );
  3138. bSingleSelection = FALSE;
  3139. } else {
  3140. //
  3141. // Remove all the port selections.
  3142. //
  3143. _PortsLV.vRemoveAllChecks();
  3144. }
  3145. }
  3146. //
  3147. // Set the new selection state.
  3148. //
  3149. _PortsLV.vSetSingleSelection( bSingleSelection );
  3150. _pPrinterData->bPooledPrinting() = !bSingleSelection;
  3151. }
  3152. break;
  3153. case IDC_ENABLE_BIDI:
  3154. break;
  3155. default:
  3156. bStatus DBGNOCHK = FALSE;
  3157. break;
  3158. }
  3159. break;
  3160. case WM_NOTIFY:
  3161. //
  3162. // Handle clicking of check boxes in ports listview.
  3163. //
  3164. switch( wParam ){
  3165. case IDC_PORTS:
  3166. //
  3167. // Handle any ports list view messages.
  3168. //
  3169. bStatus DBGNOCHK = _PortsLV.bHandleNotifyMessage( lParam );
  3170. break;
  3171. case 0:
  3172. {
  3173. LPNMHDR pnmh = (LPNMHDR)lParam;
  3174. switch( pnmh->code ){
  3175. case PSN_KILLACTIVE:
  3176. bStatus DBGNOCHK = bKillActive();
  3177. break;
  3178. case PSN_APPLY:
  3179. bStatus DBGNOCHK = FALSE;
  3180. break;
  3181. default:
  3182. bStatus DBGNOCHK = FALSE;
  3183. break;
  3184. }
  3185. }
  3186. break;
  3187. default:
  3188. bStatus DBGNOCHK = FALSE;
  3189. break;
  3190. }
  3191. break;
  3192. default:
  3193. bStatus DBGNOCHK = FALSE;
  3194. break;
  3195. }
  3196. //
  3197. // If the message was handled then read the UI to detect
  3198. // if there were any changes.
  3199. //
  3200. if( bStatus )
  3201. {
  3202. vReadUI();
  3203. }
  3204. return bStatus;
  3205. }
  3206. /********************************************************************
  3207. JobScheduling.
  3208. ********************************************************************/
  3209. TPrinterJobScheduling::
  3210. TPrinterJobScheduling(
  3211. TPrinterData* pPrinterData
  3212. ) : TPrinterProp( pPrinterData ),
  3213. _bSetUIDone( FALSE )
  3214. {
  3215. }
  3216. TPrinterJobScheduling::
  3217. ~TPrinterJobScheduling(
  3218. VOID
  3219. )
  3220. {
  3221. }
  3222. BOOL
  3223. TPrinterJobScheduling::
  3224. bValid(
  3225. VOID
  3226. )
  3227. {
  3228. return TRUE;
  3229. }
  3230. VOID
  3231. TPrinterJobScheduling::
  3232. vEnableAvailable(
  3233. IN BOOL bEnable
  3234. )
  3235. {
  3236. vEnableCtl( _hDlg, IDC_START_TIME, bEnable );
  3237. vEnableCtl( _hDlg, IDC_UNTIL_TIME, bEnable );
  3238. vEnableCtl( _hDlg, IDC_TO_TEXT, bEnable );
  3239. }
  3240. VOID
  3241. TPrinterJobScheduling::
  3242. vSetActive(
  3243. VOID
  3244. )
  3245. /*++
  3246. Routine Description:
  3247. Routine called when the pages is set active. This routine
  3248. will refresh the time control if were any local changes.
  3249. Arguments:
  3250. None.
  3251. Return Value:
  3252. Nothing.
  3253. --*/
  3254. {
  3255. (VOID)bSetStartAndUntilTime();
  3256. }
  3257. BOOL
  3258. TPrinterJobScheduling::
  3259. bSetStartAndUntilTime(
  3260. VOID
  3261. )
  3262. {
  3263. TString strFormatString;
  3264. TStatusB bStatus;
  3265. //
  3266. // Get the time format string without seconds.
  3267. //
  3268. bStatus DBGCHK = bGetTimeFormatString( strFormatString );
  3269. //
  3270. // If we have retrived a valid time format string then use it,
  3271. // else use the default format string implemented by common control.
  3272. //
  3273. if( bStatus )
  3274. {
  3275. DateTime_SetFormat(GetDlgItem( _hDlg, IDC_START_TIME ), static_cast<LPCTSTR>( strFormatString ) );
  3276. DateTime_SetFormat(GetDlgItem( _hDlg, IDC_UNTIL_TIME ), static_cast<LPCTSTR>( strFormatString ) );
  3277. }
  3278. //
  3279. // If the printer is always available.
  3280. //
  3281. BOOL bAlways = ( _pPrinterData->dwStartTime() == _pPrinterData->dwUntilTime( ));
  3282. //
  3283. // Set the start time.
  3284. //
  3285. SYSTEMTIME StartTime = { 0 };
  3286. DWORD dwLocalStartTime = 0;
  3287. GetLocalTime( &StartTime );
  3288. dwLocalStartTime = ( !bAlways ) ? SystemTimeToLocalTime( _pPrinterData->_dwStartTime ) : 0;
  3289. StartTime.wHour = static_cast<WORD>( dwLocalStartTime / 60 );
  3290. StartTime.wMinute = static_cast<WORD>( dwLocalStartTime % 60 );
  3291. DateTime_SetSystemtime(GetDlgItem( _hDlg, IDC_START_TIME ), GDT_VALID, &StartTime );
  3292. //
  3293. // Set the until time.
  3294. //
  3295. SYSTEMTIME UntilTime = { 0 };
  3296. DWORD dwLocalUntilTime = 0;
  3297. GetLocalTime( &UntilTime );
  3298. dwLocalUntilTime = ( !bAlways ) ? SystemTimeToLocalTime( _pPrinterData->_dwUntilTime ) : 0;
  3299. UntilTime.wHour = static_cast<WORD>( dwLocalUntilTime / 60 );
  3300. UntilTime.wMinute = static_cast<WORD>( dwLocalUntilTime % 60 );
  3301. DateTime_SetSystemtime(GetDlgItem( _hDlg, IDC_UNTIL_TIME ), GDT_VALID, &UntilTime );
  3302. return TRUE;
  3303. }
  3304. BOOL
  3305. TPrinterJobScheduling::
  3306. bSetUI(
  3307. VOID
  3308. )
  3309. {
  3310. //
  3311. // Fill the drivers list.
  3312. //
  3313. bFillAndSelectDrivers();
  3314. //
  3315. // Set bAlways flag.
  3316. //
  3317. BOOL bAlways = ( _pPrinterData->dwStartTime() == _pPrinterData->dwUntilTime( ));
  3318. //
  3319. // Set the start and until times.
  3320. //
  3321. (VOID)bSetStartAndUntilTime();
  3322. //
  3323. // Set Availability radio buttons.
  3324. //
  3325. CheckRadioButton( _hDlg, IDC_ALWAYS, IDC_START,
  3326. bAlways ? IDC_ALWAYS : IDC_START );
  3327. if( !_pPrinterData->bAdministrator( )){
  3328. vEnableAvailable( FALSE );
  3329. } else {
  3330. vEnableAvailable( !bAlways );
  3331. }
  3332. //
  3333. // Set the current priority.
  3334. //
  3335. SendDlgItemMessage( _hDlg, IDC_PRIORITY, EM_SETLIMITTEXT, 2, 0 );
  3336. SendDlgItemMessage( _hDlg, IDC_PRIORITY_UPDOWN, UDM_SETRANGE, 0, MAKELPARAM( 99, 1 ));
  3337. SendDlgItemMessage( _hDlg, IDC_PRIORITY_UPDOWN, UDM_SETPOS, 0, MAKELPARAM( _pPrinterData->dwPriority(), 0 ) );
  3338. //
  3339. // Set the attribte bit UI.
  3340. //
  3341. DWORD dwAttributes = _pPrinterData->dwAttributes();
  3342. vSetCheck( _hDlg,
  3343. IDC_DEVQUERYPRINT,
  3344. dwAttributes & PRINTER_ATTRIBUTE_ENABLE_DEVQ );
  3345. vSetCheck( _hDlg,
  3346. IDC_PRINT_SPOOLED_FIRST,
  3347. dwAttributes & PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST );
  3348. vSetCheck( _hDlg,
  3349. IDC_KEEP_PRINTED_JOBS,
  3350. dwAttributes & PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS );
  3351. vSetCheck( _hDlg,
  3352. IDC_SPOOL_DATATYPE,
  3353. !(dwAttributes & PRINTER_ATTRIBUTE_RAW_ONLY) );
  3354. //
  3355. // Set spool radio buttons.
  3356. // bQueued -> Spool entire document.
  3357. // both -> Spool entire document.
  3358. // neither -> Spool and print after first page.
  3359. // bDirect -> Direct.
  3360. //
  3361. BOOL bSpool = !( dwAttributes & PRINTER_ATTRIBUTE_DIRECT ) ||
  3362. ( dwAttributes & PRINTER_ATTRIBUTE_QUEUED );
  3363. CheckRadioButton( _hDlg, IDC_SPOOL, IDC_PRINT_DIRECT,
  3364. bSpool ? IDC_SPOOL : IDC_PRINT_DIRECT );
  3365. CheckRadioButton( _hDlg, IDC_SPOOL_ALL, IDC_SPOOL_PRINT_FASTER,
  3366. ( dwAttributes & PRINTER_ATTRIBUTE_QUEUED ) ? IDC_SPOOL_ALL : IDC_SPOOL_PRINT_FASTER );
  3367. vEnableCtl( _hDlg, IDC_SPOOL_ALL, bSpool );
  3368. vEnableCtl( _hDlg, IDC_SPOOL_PRINT_FASTER, bSpool );
  3369. vEnableCtl( _hDlg, IDC_PRINT_SPOOLED_FIRST, bSpool );
  3370. vEnableCtl( _hDlg, IDC_DEVQUERYPRINT, bSpool );
  3371. vEnableCtl( _hDlg, IDC_KEEP_PRINTED_JOBS, bSpool );
  3372. vEnableCtl( _hDlg, IDC_SPOOL_DATATYPE, bSpool );
  3373. //
  3374. // Enable appropriately.
  3375. //
  3376. static UINT auControl[] = {
  3377. IDC_ALWAYS,
  3378. IDC_START,
  3379. IDC_SPOOL,
  3380. IDC_SPOOL_ALL,
  3381. IDC_SPOOL_PRINT_FASTER,
  3382. IDC_PRINT_DIRECT,
  3383. IDC_DEVQUERYPRINT,
  3384. IDC_PRINT_SPOOLED_FIRST,
  3385. IDC_KEEP_PRINTED_JOBS,
  3386. IDC_SPOOL_DATATYPE,
  3387. IDC_SEPARATOR,
  3388. IDC_PRINT_PROC,
  3389. IDC_GLOBAL_DOCUMENT_DEFAULTS,
  3390. IDC_TEXT_PRIORITY,
  3391. IDC_PRIORITY,
  3392. IDC_PRIORITY_UPDOWN,
  3393. IDC_TEXT_DRIVER,
  3394. IDC_DRIVER_NAME,
  3395. IDC_DRIVER_NEW,
  3396. 0
  3397. };
  3398. COUNT i;
  3399. if( !_pPrinterData->bAdministrator( )){
  3400. for( i=0; auControl[i]; ++i ){
  3401. vEnableCtl( _hDlg, auControl[i], FALSE );
  3402. }
  3403. }
  3404. //
  3405. // Set the "New Drivers..." button depending on the value of _bServerFullAccess
  3406. //
  3407. vEnableCtl( _hDlg, IDC_DRIVER_NEW, _pPrinterData->bServerFullAccess() );
  3408. if( _pPrinterData->_bDriverPagesNotLoaded )
  3409. {
  3410. ShowWindow( GetDlgItem( _hDlg, IDC_GLOBAL_DOCUMENT_DEFAULTS ), SW_HIDE );
  3411. }
  3412. //
  3413. // Indicate SetUI is done. This is used to
  3414. // prevent ReadUI from reading junk since edit controls
  3415. // recieve EN_CHANGE messages while in WM_INITDIALOG
  3416. //
  3417. _bSetUIDone = TRUE;
  3418. return TRUE;
  3419. }
  3420. VOID
  3421. TPrinterJobScheduling::
  3422. vReadUI(
  3423. VOID
  3424. )
  3425. {
  3426. TStatusB bStatus;
  3427. //
  3428. // Read the priority setting.
  3429. //
  3430. _pPrinterData->_dwPriority = (DWORD)SendDlgItemMessage( _hDlg, IDC_PRIORITY_UPDOWN, UDM_GETPOS, 0, 0 );
  3431. //
  3432. // Get the current attribute.
  3433. //
  3434. DWORD dwAttributes = _pPrinterData->dwAttributes();
  3435. //
  3436. // Mask out attributes we are going to read back.
  3437. //
  3438. dwAttributes &= ~( PRINTER_ATTRIBUTE_ENABLE_DEVQ |
  3439. PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST |
  3440. PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS |
  3441. PRINTER_ATTRIBUTE_QUEUED |
  3442. PRINTER_ATTRIBUTE_DIRECT );
  3443. if( BST_CHECKED == IsDlgButtonChecked( _hDlg, IDC_DEVQUERYPRINT )){
  3444. dwAttributes |= PRINTER_ATTRIBUTE_ENABLE_DEVQ;
  3445. }
  3446. if( BST_CHECKED == IsDlgButtonChecked( _hDlg, IDC_PRINT_SPOOLED_FIRST )){
  3447. dwAttributes |= PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST;
  3448. }
  3449. if( BST_CHECKED == IsDlgButtonChecked( _hDlg, IDC_KEEP_PRINTED_JOBS )){
  3450. dwAttributes |= PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS;
  3451. }
  3452. if( BST_CHECKED == IsDlgButtonChecked( _hDlg, IDC_SPOOL_DATATYPE )){
  3453. dwAttributes &= ~PRINTER_ATTRIBUTE_RAW_ONLY;
  3454. }else{
  3455. dwAttributes |= PRINTER_ATTRIBUTE_RAW_ONLY;
  3456. }
  3457. //
  3458. // Get radio buttons. If direct is selected, then ignore
  3459. // all the other spool fields.
  3460. //
  3461. if( BST_CHECKED == IsDlgButtonChecked( _hDlg, IDC_PRINT_DIRECT )){
  3462. //
  3463. // Direct, no spooling options selected.
  3464. //
  3465. dwAttributes |= PRINTER_ATTRIBUTE_DIRECT;
  3466. } else {
  3467. //
  3468. // Spool, print after last page -> QUEUED.
  3469. // Spool, print after first page -> neither.
  3470. //
  3471. if( BST_CHECKED == IsDlgButtonChecked( _hDlg, IDC_SPOOL_ALL )){
  3472. dwAttributes |= PRINTER_ATTRIBUTE_QUEUED;
  3473. }
  3474. }
  3475. _pPrinterData->_dwAttributes = dwAttributes;
  3476. //
  3477. // Get availability time if the printer is always
  3478. // available then set the time to no time restriction.
  3479. //
  3480. if( bGetCheck( _hDlg, IDC_ALWAYS ) ){
  3481. _pPrinterData->_dwStartTime = 0;
  3482. _pPrinterData->_dwUntilTime = 0;
  3483. } else {
  3484. //
  3485. // Get the Start time.
  3486. //
  3487. SYSTEMTIME StartTime;
  3488. DateTime_GetSystemtime( GetDlgItem( _hDlg, IDC_START_TIME ), &StartTime );
  3489. _pPrinterData->_dwStartTime = LocalTimeToSystemTime( StartTime.wHour * 60 + StartTime.wMinute );
  3490. //
  3491. // Get the Until time.
  3492. //
  3493. SYSTEMTIME UntilTime;
  3494. DateTime_GetSystemtime( GetDlgItem( _hDlg, IDC_UNTIL_TIME ), &UntilTime );
  3495. _pPrinterData->_dwUntilTime = LocalTimeToSystemTime( UntilTime.wHour * 60 + UntilTime.wMinute );
  3496. //
  3497. // If the printer start and until time are the same this is
  3498. // exactly the same as always available.
  3499. //
  3500. if( _pPrinterData->_dwStartTime == _pPrinterData->_dwUntilTime )
  3501. {
  3502. _pPrinterData->_dwStartTime = 0;
  3503. _pPrinterData->_dwUntilTime = 0;
  3504. }
  3505. }
  3506. //
  3507. // Read the driver name
  3508. //
  3509. bStatus DBGCHK = bGetEditText( _hDlg, IDC_DRIVER_NAME, _pPrinterData->strDriverName());
  3510. if( !bStatus )
  3511. {
  3512. _pPrinterData->_bErrorSaving = TRUE;
  3513. vShowResourceError( _hDlg );
  3514. }
  3515. }
  3516. BOOL
  3517. TPrinterJobScheduling::
  3518. _bHandleMessage(
  3519. IN UINT uMsg,
  3520. IN WPARAM wParam,
  3521. IN LPARAM lParam
  3522. )
  3523. {
  3524. TStatusB bStatus;
  3525. bStatus DBGNOCHK = TRUE;
  3526. switch( uMsg ){
  3527. case WM_INITDIALOG:
  3528. bStatus DBGCHK = bSetUI();
  3529. break;
  3530. case WM_APP:
  3531. vSetActive();
  3532. break;
  3533. case WM_HELP:
  3534. case WM_CONTEXTMENU:
  3535. PrintUIHelp( uMsg, _hDlg, wParam, lParam );
  3536. break;
  3537. case WM_WININICHANGE:
  3538. vSetActive();
  3539. break;
  3540. case WM_COMMAND:
  3541. switch( GET_WM_COMMAND_ID( wParam, lParam )){
  3542. case IDC_SPOOL:
  3543. vEnableCtl( _hDlg, IDC_SPOOL_ALL, TRUE );
  3544. vEnableCtl( _hDlg, IDC_SPOOL_PRINT_FASTER, TRUE );
  3545. vEnableCtl( _hDlg, IDC_PRINT_SPOOLED_FIRST, TRUE );
  3546. vEnableCtl( _hDlg, IDC_DEVQUERYPRINT, TRUE );
  3547. vEnableCtl( _hDlg, IDC_KEEP_PRINTED_JOBS, TRUE );
  3548. vEnableCtl( _hDlg, IDC_SPOOL_DATATYPE, TRUE );
  3549. break;
  3550. case IDC_PRINT_DIRECT:
  3551. vEnableCtl( _hDlg, IDC_SPOOL_ALL, FALSE );
  3552. vEnableCtl( _hDlg, IDC_SPOOL_PRINT_FASTER, FALSE );
  3553. vEnableCtl( _hDlg, IDC_PRINT_SPOOLED_FIRST, FALSE );
  3554. vEnableCtl( _hDlg, IDC_DEVQUERYPRINT, FALSE );
  3555. vEnableCtl( _hDlg, IDC_KEEP_PRINTED_JOBS, FALSE );
  3556. vEnableCtl( _hDlg, IDC_SPOOL_DATATYPE, FALSE );
  3557. break;
  3558. case IDC_ALWAYS:
  3559. vEnableAvailable( FALSE );
  3560. break;
  3561. case IDC_START:
  3562. vEnableAvailable( TRUE );
  3563. break;
  3564. case IDC_DEVQUERYPRINT:
  3565. case IDC_PRINT_SPOOLED_FIRST:
  3566. case IDC_KEEP_PRINTED_JOBS:
  3567. case IDC_SPOOL_ALL:
  3568. case IDC_SPOOL_PRINT_FASTER:
  3569. case IDC_SPOOL_DATATYPE:
  3570. case IDC_DRIVER_NAME:
  3571. break;
  3572. case IDC_PRIORITY:
  3573. bStatus DBGNOCHK = GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE;
  3574. break;
  3575. case IDC_SEPARATOR:
  3576. vSeparatorPage();
  3577. break;
  3578. case IDC_PRINT_PROC:
  3579. vPrintProcessor();
  3580. break;
  3581. case IDC_GLOBAL_DOCUMENT_DEFAULTS:
  3582. vHandleGlobalDocumentDefaults( wParam, lParam );
  3583. break;
  3584. case IDC_DRIVER_NEW:
  3585. vHandleNewDriver( wParam, lParam );
  3586. break;
  3587. default:
  3588. bStatus DBGNOCHK = FALSE;
  3589. break;
  3590. }
  3591. break;
  3592. case WM_NOTIFY:
  3593. {
  3594. LPNMHDR pnmh = (LPNMHDR)lParam;
  3595. switch( wParam )
  3596. {
  3597. case 0:
  3598. {
  3599. switch( pnmh->code )
  3600. {
  3601. case PSN_KILLACTIVE:
  3602. vReadUI();
  3603. break;
  3604. case PSN_SETACTIVE:
  3605. vSetActive();
  3606. break;
  3607. default:
  3608. bStatus DBGNOCHK = FALSE;
  3609. break;
  3610. }
  3611. }
  3612. break;
  3613. case IDC_START_TIME:
  3614. case IDC_UNTIL_TIME:
  3615. {
  3616. switch( pnmh->code )
  3617. {
  3618. case DTN_DATETIMECHANGE:
  3619. break;
  3620. default:
  3621. bStatus DBGNOCHK = FALSE;
  3622. break;
  3623. }
  3624. }
  3625. break;
  3626. default:
  3627. bStatus DBGNOCHK = FALSE;
  3628. break;
  3629. }
  3630. }
  3631. break;
  3632. default:
  3633. bStatus DBGNOCHK = FALSE;
  3634. break;
  3635. }
  3636. //
  3637. // If a message was handled read the ui from the dialog
  3638. //
  3639. if( bStatus && _bSetUIDone )
  3640. {
  3641. vReadUI();
  3642. }
  3643. return bStatus;
  3644. }
  3645. VOID
  3646. TPrinterJobScheduling::
  3647. vSeparatorPage(
  3648. VOID
  3649. )
  3650. {
  3651. //
  3652. // Create separator page dialog.
  3653. //
  3654. TSeparatorPage SeparatorPage( _hDlg,
  3655. _pPrinterData->strSepFile(),
  3656. _pPrinterData->bAdministrator(),
  3657. _pPrinterData->strServerName().bEmpty() );
  3658. //
  3659. // Check if separator page dialog created ok.
  3660. //
  3661. if( !VALID_OBJ( SeparatorPage )){
  3662. iMessage( _hDlg,
  3663. IDS_ERR_PRINTER_PROP_TITLE,
  3664. TSeparatorPage::kErrorMessage,
  3665. MB_OK|MB_ICONHAND,
  3666. kMsgNone,
  3667. NULL );
  3668. return;
  3669. }
  3670. //
  3671. // Interact with the separator page.
  3672. //
  3673. if( SeparatorPage.bDoModal() ){
  3674. //
  3675. // Assign back the separator page.
  3676. //
  3677. if( !_pPrinterData->strSepFile().bUpdate( SeparatorPage.strSeparatorPage() ) ){
  3678. vShowResourceError( _hDlg );
  3679. }
  3680. }
  3681. }
  3682. VOID
  3683. TPrinterJobScheduling::
  3684. vPrintProcessor(
  3685. VOID
  3686. )
  3687. {
  3688. //
  3689. // Create print processor dialog.
  3690. //
  3691. TPrintProcessor PrintProcessor( _hDlg,
  3692. _pPrinterData->strServerName(),
  3693. _pPrinterData->strPrintProcessor(),
  3694. _pPrinterData->strDatatype(),
  3695. _pPrinterData->bAdministrator() );
  3696. //
  3697. // Check if print processor dialog was created ok.
  3698. //
  3699. if( !VALID_OBJ( PrintProcessor )){
  3700. iMessage( _hDlg,
  3701. IDS_ERR_PRINTER_PROP_TITLE,
  3702. TPrintProcessor::kErrorMessage,
  3703. MB_OK|MB_ICONHAND,
  3704. kMsgNone,
  3705. NULL );
  3706. return;
  3707. }
  3708. //
  3709. // Interact with the print processor page.
  3710. //
  3711. if( PrintProcessor.bDoModal() ){
  3712. //
  3713. // Assign back the print proccesor and data type.
  3714. //
  3715. if( !_pPrinterData->strPrintProcessor().bUpdate( PrintProcessor.strPrintProcessor() ) ||
  3716. !_pPrinterData->strDatatype().bUpdate( PrintProcessor.strDatatype() ) ){
  3717. vShowResourceError( _hDlg );
  3718. }
  3719. }
  3720. }
  3721. VOID
  3722. TPrinterJobScheduling::
  3723. vHandleGlobalDocumentDefaults(
  3724. IN WPARAM wParam,
  3725. IN LPARAM lParam
  3726. )
  3727. /*++
  3728. Routine Description:
  3729. Handle launching global document defaults dialog.
  3730. Arguments:
  3731. wParam - Parameter passed to by dialog proc.
  3732. lParam - Parameter passed to by dialog proc.
  3733. Return Value:
  3734. Nothing.
  3735. --*/
  3736. {
  3737. (VOID)dwDocumentDefaultsInternal( _hDlg,
  3738. _pPrinterData->strCurrentPrinterName(),
  3739. SW_SHOW,
  3740. 0,
  3741. 0,
  3742. TRUE );
  3743. }
  3744. BOOL
  3745. TPrinterJobScheduling::
  3746. bFillAndSelectDrivers(
  3747. VOID
  3748. )
  3749. {
  3750. TStatusB bStatus;
  3751. PDRIVER_INFO_2 pDriverInfo2 = NULL;
  3752. DWORD cDrivers = 0;
  3753. DWORD cbDriverInfo2 = 0;
  3754. HWND hCtlDrivers = NULL;
  3755. //
  3756. // Enum the printer drivers on this machine.
  3757. //
  3758. bStatus DBGCHK = VDataRefresh::bEnumDrivers( _pPrinterData->pszServerName(),
  3759. _pPrinterData->strDriverEnv(),
  3760. 2,
  3761. (PVOID *)&pDriverInfo2,
  3762. &cbDriverInfo2,
  3763. &cDrivers );
  3764. if( !bStatus ){
  3765. DBGMSG( DBG_WARN, ( "bFillAndSelectDrivers bEnumDriver failed with %d\n", GetLastError() ));
  3766. return FALSE;
  3767. }
  3768. //
  3769. // Fill in the driver information.
  3770. //
  3771. hCtlDrivers = GetDlgItem( _hDlg, IDC_DRIVER_NAME );
  3772. ComboBox_ResetContent( hCtlDrivers );
  3773. for( UINT i = 0; i < cDrivers; ++i ){
  3774. //
  3775. // Add only compatible driver versions.
  3776. //
  3777. if( bIsCompatibleDriverVersion( _pPrinterData->dwDriverVersion(), pDriverInfo2[i].cVersion ) )
  3778. {
  3779. //
  3780. // Never add the fax driver, we do not permit user to switch from a printer
  3781. // driver to a fax driver.
  3782. //
  3783. if( _tcscmp( pDriverInfo2[i].pName, FAX_DRIVER_NAME ) )
  3784. {
  3785. //
  3786. // Filter out duplicates. There could be a version 2 and version 3 etc drivers installed.
  3787. // The spooler SetPrinter api does not make a distiction between different
  3788. // driver versions, since it only accepts a printer driver name.
  3789. //
  3790. if( SendMessage( hCtlDrivers, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pDriverInfo2[i].pName ) == CB_ERR )
  3791. {
  3792. ComboBox_AddString( hCtlDrivers, pDriverInfo2[i].pName );
  3793. }
  3794. }
  3795. }
  3796. }
  3797. //
  3798. // Release the driver information.
  3799. //
  3800. FreeMem( pDriverInfo2 );
  3801. INT iStatus = ComboBox_SelectString( hCtlDrivers,
  3802. -1,
  3803. _pPrinterData->strDriverName( ));
  3804. //
  3805. // The problem here is that the server many not have the driver
  3806. // for the client enviroment, so we need to jam in the extra driver
  3807. // name if iStatus is -1 (failure case).
  3808. //
  3809. if( iStatus == -1 ){
  3810. DBGMSG( DBG_PROPSINFO, ( "bFillAndSelectDrivers: driver "TSTR" not on server\n", (LPCTSTR)_pPrinterData->strDriverName() ));
  3811. ComboBox_AddString( hCtlDrivers, _pPrinterData->strDriverName( ));
  3812. INT iSelectResult = ComboBox_SelectString( hCtlDrivers,
  3813. -1,
  3814. _pPrinterData->strDriverName( ));
  3815. if( iSelectResult < 0 ){
  3816. DBGMSG( DBG_WARN,( "bFillAndSelectDrivers: driver "TSTR" select failed %d\n", (LPCTSTR)_pPrinterData->strDriverName(), iSelectResult ));
  3817. }
  3818. }
  3819. return TRUE;
  3820. }
  3821. VOID
  3822. TPrinterJobScheduling::
  3823. vHandleNewDriver(
  3824. IN WPARAM wParam,
  3825. IN LPARAM lParam
  3826. )
  3827. {
  3828. TStatusB bStatus;
  3829. TCHAR szDriverName[MAX_PATH];
  3830. UINT cchDriverNameSize = 0;
  3831. //
  3832. // Setup a new driver.
  3833. //
  3834. bStatus DBGCHK = bPrinterSetup( _hDlg,
  3835. MSP_NEWDRIVER,
  3836. COUNTOF( szDriverName ),
  3837. szDriverName,
  3838. &cchDriverNameSize,
  3839. _pPrinterData->pszServerName() );
  3840. //
  3841. // If new driver installed ok update the combo box.
  3842. //
  3843. if( bStatus )
  3844. {
  3845. //
  3846. // If a new driver was added, check if it already exists in the
  3847. // the list of drivers.
  3848. //
  3849. if( SendDlgItemMessage( _hDlg,
  3850. IDC_DRIVER_NAME,
  3851. CB_FINDSTRINGEXACT,
  3852. (WPARAM)-1,
  3853. (LPARAM)szDriverName ) == CB_ERR )
  3854. {
  3855. //
  3856. // Add the the new driver to the combo box.
  3857. //
  3858. ComboBox_AddString( GetDlgItem( _hDlg, IDC_DRIVER_NAME ), szDriverName );
  3859. }
  3860. //
  3861. // Select this newly added driver.
  3862. //
  3863. ComboBox_SelectString( GetDlgItem( _hDlg, IDC_DRIVER_NAME ), -1, szDriverName );
  3864. }
  3865. }
  3866. /********************************************************************
  3867. Sharing.
  3868. ********************************************************************/
  3869. TPrinterSharing::
  3870. TPrinterSharing(
  3871. TPrinterData* pPrinterData
  3872. ) : TPrinterProp( pPrinterData ),
  3873. _pPrtShare( NULL ),
  3874. _bHideListed( TRUE ),
  3875. _bSetUIDone( FALSE ),
  3876. _bAcceptInvalidDosShareName( FALSE ),
  3877. _bDefaultPublishState( TRUE ),
  3878. _bSharingEnabled( TRUE )
  3879. {
  3880. }
  3881. TPrinterSharing::
  3882. ~TPrinterSharing(
  3883. VOID
  3884. )
  3885. {
  3886. delete _pPrtShare;
  3887. }
  3888. BOOL
  3889. TPrinterSharing::
  3890. bValid(
  3891. VOID
  3892. )
  3893. {
  3894. return TPrinterProp::bValid();
  3895. }
  3896. VOID
  3897. TPrinterSharing::
  3898. vSharePrinter(
  3899. VOID
  3900. )
  3901. /*++
  3902. Routine Description:
  3903. User clicked share radio button. Change the UI appropriately.
  3904. Arguments:
  3905. Return Value:
  3906. --*/
  3907. {
  3908. //
  3909. // Set radio button and possibly enable window.
  3910. //
  3911. CheckRadioButton( _hDlg, IDC_SHARED_OFF, IDC_SHARED, IDC_SHARED );
  3912. if( _pPrinterData->bAdministrator()){
  3913. //
  3914. // Set the default share name.
  3915. //
  3916. vSetDefaultShareName();
  3917. vEnableCtl( _hDlg, IDC_DS_OPERATION_PENDING, TRUE );
  3918. vEnableCtl( _hDlg, IDC_LABEL_SHARENAME, TRUE );
  3919. vEnableCtl( _hDlg, IDC_SHARED_NAME, TRUE );
  3920. vEnableCtl( _hDlg, IDC_PUBLISHED, TRUE );
  3921. //
  3922. // Set the focus to the edit control.
  3923. //
  3924. SetFocus( GetDlgItem( _hDlg, IDC_SHARED_NAME ) );
  3925. //
  3926. // Select the share name exit text.
  3927. //
  3928. Edit_SetSel( GetDlgItem( _hDlg, IDC_SHARED_NAME ), 0, -1 );
  3929. //
  3930. // Set the published check box.
  3931. //
  3932. if( !_bHideListed )
  3933. {
  3934. vSetCheck( _hDlg, IDC_PUBLISHED, _bDefaultPublishState );
  3935. }
  3936. }
  3937. }
  3938. VOID
  3939. TPrinterSharing::
  3940. vUnsharePrinter(
  3941. VOID
  3942. )
  3943. /*++
  3944. Routine Description:
  3945. User clicked don't share radio button. Change the UI appropriately.
  3946. Arguments:
  3947. Return Value:
  3948. --*/
  3949. {
  3950. //
  3951. // Set radio button and disable window.
  3952. //
  3953. CheckRadioButton( _hDlg, IDC_SHARED_OFF, IDC_SHARED, IDC_SHARED_OFF );
  3954. vEnableCtl( _hDlg, IDC_DS_OPERATION_PENDING, FALSE );
  3955. vEnableCtl( _hDlg, IDC_LABEL_SHARENAME, FALSE );
  3956. vEnableCtl( _hDlg, IDC_SHARED_NAME, FALSE );
  3957. vEnableCtl( _hDlg, IDC_PUBLISHED, FALSE );
  3958. //
  3959. // Clear the published check box.
  3960. //
  3961. if( !_bHideListed )
  3962. {
  3963. vSetCheck( _hDlg, IDC_PUBLISHED, FALSE );
  3964. }
  3965. }
  3966. VOID
  3967. TPrinterSharing::
  3968. vSetDefaultShareName(
  3969. VOID
  3970. )
  3971. /*++
  3972. Routine Description:
  3973. Sets the default share name if use has choosen to share
  3974. this printer. We will update the share name if
  3975. this is the first time setting the share name.
  3976. Arguments:
  3977. None.
  3978. Return Value:
  3979. Nothing.
  3980. --*/
  3981. {
  3982. TStatusB bStatus;
  3983. TString strShareName;
  3984. //
  3985. // Read the current contents of the edit control.
  3986. //
  3987. bStatus DBGCHK = bGetEditText( _hDlg, IDC_SHARED_NAME, strShareName );
  3988. DBGMSG( DBG_TRACE, ( "strShareName " TSTR "\n", (LPCTSTR)strShareName ) );
  3989. //
  3990. // Create a share name if the current edit field is empty.
  3991. //
  3992. if( strShareName.bEmpty() ){
  3993. //
  3994. // If the share object has not be constructed, then
  3995. // construct it.
  3996. //
  3997. if( !_pPrtShare ){
  3998. _pPrtShare = new TPrtShare( _pPrinterData->pszServerName() );
  3999. }
  4000. //
  4001. // Ensure the share object is still valid.
  4002. //
  4003. if( VALID_PTR( _pPrtShare ) ){
  4004. //
  4005. // Get just the printer name.
  4006. //
  4007. LPCTSTR pszServer;
  4008. LPCTSTR pszPrinter;
  4009. TCHAR szScratch[kPrinterBufMax];
  4010. vPrinterSplitFullName( szScratch,
  4011. _pPrinterData->strPrinterName( ),
  4012. &pszServer,
  4013. &pszPrinter );
  4014. //
  4015. // Create valid unique share name.
  4016. //
  4017. bStatus DBGNOCHK = _pPrtShare->bNewShareName( strShareName, pszPrinter );
  4018. //
  4019. // Set the default share name.
  4020. //
  4021. bStatus DBGCHK = bSetEditText( _hDlg, IDC_SHARED_NAME, strShareName );
  4022. }
  4023. }
  4024. }
  4025. BOOL
  4026. TPrinterSharing::
  4027. bSetUI(
  4028. VOID
  4029. )
  4030. {
  4031. //
  4032. // Set of controls on this page.
  4033. //
  4034. static UINT auShared[] = { IDC_SHARED_NAME,
  4035. IDC_SHARED,
  4036. IDC_SHARED_OFF,
  4037. IDC_PUBLISHED,
  4038. IDC_SERVER_PROPERTIES,
  4039. IDC_LABEL_SHARENAME,
  4040. IDC_SHARING_ENABLED_GROUPBOX,
  4041. IDC_SHARING_INFOTEXT,
  4042. 0 };
  4043. static UINT auSharingNotSupported[] = { IDC_NAME,
  4044. IDC_SHARING_DISABLED,
  4045. IDC_DIVIDER6,
  4046. IDC_ENABLE_SHARING,
  4047. 0 };
  4048. TStatusB bStatus;
  4049. TString strText;
  4050. TString strDirName;
  4051. BOOL bSharingNotSupported = FALSE;
  4052. if( FALSE == _bSharingEnabled && FALSE == _pPrinterData->bHideSharingUI() ) {
  4053. //
  4054. // Change the text of the link control to point the user to the
  4055. // home networking wizard (HNW)
  4056. //
  4057. TString strText;
  4058. bStatus DBGCHK = strText.bLoadString(ghInst, IDS_TEXT_SHARING_NOT_ENABLED);
  4059. if (bStatus) {
  4060. bSetEditText(_hDlg, IDC_SHARING_DISABLED, strText);
  4061. }
  4062. } else {
  4063. //
  4064. // If we're here sharing is either enabled or not supported for
  4065. // the selected printer. Sharing may not be supported for some
  4066. // special type of printers like fax printers and/or masq
  4067. // printers (http printers or downlevel printers like win9x,
  4068. // Novell, Solaris, Linux, etc...)
  4069. //
  4070. bSharingNotSupported = TRUE;
  4071. }
  4072. //
  4073. // If the sharing UI is to be hidded then remove all the controls.
  4074. //
  4075. if( FALSE == _bSharingEnabled || _pPrinterData->bHideSharingUI() ){
  4076. //
  4077. // Hide the sharing controls.
  4078. //
  4079. for( UINT i=0; auShared[i]; ++i ){
  4080. ShowWindow( GetDlgItem( _hDlg, auShared[i] ), SW_HIDE );
  4081. }
  4082. //
  4083. // Show the sharing not supported/enabled controls.
  4084. //
  4085. for( UINT i=0; auSharingNotSupported[i]; ++i ){
  4086. if( bSharingNotSupported && IDC_ENABLE_SHARING == auSharingNotSupported[i] ) {
  4087. //
  4088. // Skip enabling this control.
  4089. //
  4090. continue;
  4091. }
  4092. ShowWindow( GetDlgItem( _hDlg, auSharingNotSupported[i] ), SW_NORMAL );
  4093. }
  4094. //
  4095. // Hide a few controls that are not in the array.
  4096. //
  4097. ShowWindow( GetDlgItem( _hDlg, IDC_SHARING_GBOX ), SW_HIDE );
  4098. ShowWindow( GetDlgItem( _hDlg, IDC_ADDITIONAL_DRIVERS_TEXT2 ), SW_HIDE );
  4099. }
  4100. else
  4101. {
  4102. //
  4103. // Show the sharing controls.
  4104. //
  4105. for( UINT i=0; auShared[i]; ++i ){
  4106. ShowWindow( GetDlgItem( _hDlg, auShared[i] ), SW_NORMAL );
  4107. }
  4108. //
  4109. // Hide the sharing not supported/enabled controls.
  4110. //
  4111. for( UINT i=0; auSharingNotSupported[i]; ++i ){
  4112. ShowWindow( GetDlgItem( _hDlg, auSharingNotSupported[i] ), SW_HIDE );
  4113. }
  4114. //
  4115. // Show a few controls that are not in the array.
  4116. //
  4117. ShowWindow( GetDlgItem( _hDlg, IDC_SHARING_GBOX ), SW_NORMAL );
  4118. ShowWindow( GetDlgItem( _hDlg, IDC_ADDITIONAL_DRIVERS_TEXT2 ), SW_NORMAL );
  4119. }
  4120. //
  4121. // Save the origianal share name.
  4122. //
  4123. bStatus DBGCHK = _strShareName.bUpdate( _pPrinterData->strShareName() );
  4124. //
  4125. // Set the printer share name limit. The limit in win9x is
  4126. // 8.3 == 12+1 chars (including NULL terminator). The Winnt limit
  4127. // is defined as NNLEN;
  4128. //
  4129. SendDlgItemMessage( _hDlg, IDC_SHARED_NAME, EM_SETLIMITTEXT, kPrinterShareNameMax, 0 );
  4130. //
  4131. // Update the fields.
  4132. //
  4133. bSetEditText( _hDlg, IDC_SHARED_NAME, _pPrinterData->strShareName( ));
  4134. //
  4135. // Get the flag that indicates we need to display the listed in the directory
  4136. // check box.
  4137. //
  4138. _bHideListed = _pPrinterData->ePrinterPublishState() == TPrinterData::kNoDsAvailable;
  4139. //
  4140. // If this is a masq printer do not show the publish UI, we do not allow publishing
  4141. // of masq printer. The definition of a masq printer is a printer connection that
  4142. // happens to be implemented as a local printer with a re-directed port. So masq
  4143. // printer should be treated like printer connections a per user resouce.
  4144. //
  4145. if( _pPrinterData->_dwAttributes & PRINTER_ATTRIBUTE_NETWORK && _pPrinterData->_dwAttributes & PRINTER_ATTRIBUTE_LOCAL )
  4146. {
  4147. _bHideListed = TRUE;
  4148. }
  4149. //
  4150. // If we have decided not to hide the listed in the directory then check
  4151. // if the spooler policy bit will allow the user to actually publish the
  4152. // printer.
  4153. //
  4154. if( !_bHideListed )
  4155. {
  4156. //
  4157. // Check this policy only if we are administering a
  4158. // local printer. Otherwise show the publishing UI would
  4159. //
  4160. if( !_pPrinterData->_pszServerName )
  4161. {
  4162. //
  4163. // Read the per machine policy bit that the spooler uses for
  4164. // controlling printer publishing.
  4165. //
  4166. TPersist SpoolerPolicy( gszSpoolerPolicy, TPersist::kOpen|TPersist::kRead, HKEY_LOCAL_MACHINE );
  4167. if( VALID_OBJ( SpoolerPolicy ) )
  4168. {
  4169. BOOL bCanPublish;
  4170. bStatus DBGNOCHK = SpoolerPolicy.bRead( gszSpoolerPublish, bCanPublish );
  4171. if( bStatus )
  4172. {
  4173. _bHideListed = !bCanPublish;
  4174. }
  4175. }
  4176. }
  4177. //
  4178. // Read the per user default publish policy bit.
  4179. //
  4180. TPersist Policy( gszAddPrinterWizardPolicy, TPersist::kOpen|TPersist::kRead, HKEY_LOCAL_MACHINE );
  4181. if( VALID_OBJ( Policy ) )
  4182. {
  4183. bStatus DBGNOCHK = Policy.bRead( gszAPWPublish, _bDefaultPublishState );
  4184. }
  4185. }
  4186. //
  4187. // Hide the publish controls if the DS is not loaded or we are viewing
  4188. // a downlevel spooler.
  4189. //
  4190. if( _bHideListed ){
  4191. //
  4192. // Hide the publish check box.
  4193. //
  4194. ShowWindow( GetDlgItem( _hDlg, IDC_PUBLISHED ), SW_HIDE );
  4195. ShowWindow( GetDlgItem( _hDlg, IDC_DS_OPERATION_PENDING ), SW_HIDE );
  4196. } else {
  4197. //
  4198. // Load the pending string.
  4199. //
  4200. bStatus DBGCHK = _strPendingText.bLoadString( ghInst, IDS_DS_PENDING_TEXT );
  4201. }
  4202. //
  4203. // Select correct radio button.
  4204. //
  4205. if( _pPrinterData->dwAttributes() & PRINTER_ATTRIBUTE_SHARED ){
  4206. vSharePrinter();
  4207. } else {
  4208. vUnsharePrinter();
  4209. }
  4210. //
  4211. // Check the published check box if the printer is published.
  4212. //
  4213. if( _pPrinterData->dwAttributes() & PRINTER_ATTRIBUTE_PUBLISHED ){
  4214. vSetCheck( _hDlg, IDC_PUBLISHED, TRUE );
  4215. } else {
  4216. vSetCheck( _hDlg, IDC_PUBLISHED, FALSE );
  4217. }
  4218. //
  4219. // If not an administrator, or the network is not installed
  4220. // disable the edit controls.
  4221. //
  4222. if( !_pPrinterData->bAdministrator( ) || !TPrtShare::bNetworkInstalled() ){
  4223. for( UINT i=0; auShared[i]; ++i ){
  4224. vEnableCtl( _hDlg, auShared[i], FALSE );
  4225. }
  4226. }
  4227. //
  4228. // Set the "Additional Drivers..." button depending on the value of _bServerFullAccess
  4229. //
  4230. vEnableCtl( _hDlg, IDC_SHARING_GBOX, _pPrinterData->bServerFullAccess() );
  4231. vEnableCtl( _hDlg, IDC_ADDITIONAL_DRIVERS_TEXT2, _pPrinterData->bServerFullAccess() );
  4232. vEnableCtl( _hDlg, IDC_SERVER_PROPERTIES, _pPrinterData->bServerFullAccess() );
  4233. //
  4234. // Special case the share name if we are not an administrator make the share name
  4235. // a read only control rather than a grayed out edit control.
  4236. //
  4237. if( !_pPrinterData->bAdministrator( ) || !TPrtShare::bNetworkInstalled() ){
  4238. SendDlgItemMessage( _hDlg, IDC_SHARED_NAME, EM_SETREADONLY, TRUE, 0);
  4239. vEnableCtl( _hDlg, IDC_SHARED_NAME, TRUE );
  4240. }
  4241. //
  4242. // There are a few UI elements that need to be set when
  4243. // we are activated, because of a driver change. We
  4244. // will artifically do it now.
  4245. //
  4246. vSetActive();
  4247. // Indicate SetUI is done. This is used to
  4248. // prevent ReadUI from reading junk since edit controls
  4249. // can recieve EN_CHANGE messages before WM_INITDIALOG
  4250. //
  4251. _bSetUIDone = TRUE;
  4252. return TRUE;
  4253. }
  4254. VOID
  4255. TPrinterSharing::
  4256. vReadUI(
  4257. VOID
  4258. )
  4259. {
  4260. TStatusB bStatus;
  4261. //
  4262. // Check if the printer has been shared.
  4263. //
  4264. if( BST_CHECKED == IsDlgButtonChecked( _hDlg, IDC_SHARED_OFF )){
  4265. //
  4266. // Indicate the printer is not share.
  4267. //
  4268. _pPrinterData->dwAttributes() &= ~PRINTER_ATTRIBUTE_SHARED;
  4269. } else {
  4270. //
  4271. // Indicate printer is shared.
  4272. //
  4273. _pPrinterData->dwAttributes() |= PRINTER_ATTRIBUTE_SHARED;
  4274. }
  4275. //
  4276. // Do nothing with the publish state if the DS is not available.
  4277. //
  4278. if( _pPrinterData->ePrinterPublishState() != TPrinterData::kNoDsAvailable ){
  4279. //
  4280. // Check the current publish state.
  4281. //
  4282. TPrinterData::EPublishState bSelectedPublisheState = bGetCheck( _hDlg, IDC_PUBLISHED ) ?
  4283. TPrinterData::kPublished : TPrinterData::kNotPublished;
  4284. //
  4285. // If the printer is not shared then indicate the seleceted state is not
  4286. // published. This will either result in no action or a unpublish.
  4287. //
  4288. if( !( _pPrinterData->dwAttributes() & PRINTER_ATTRIBUTE_SHARED ) ){
  4289. bSelectedPublisheState = TPrinterData::kNotPublished;
  4290. }
  4291. //
  4292. // If the publish state matched the current state then do nothing.
  4293. //
  4294. if( bSelectedPublisheState == _pPrinterData->ePrinterPublishState() ){
  4295. _pPrinterData->ePrinterPublishState( TPrinterData::kNoAction );
  4296. } else {
  4297. //
  4298. // Update the publish action.
  4299. //
  4300. if( bSelectedPublisheState == TPrinterData::kPublished ){
  4301. _pPrinterData->ePrinterPublishState( TPrinterData::kPublish );
  4302. } else {
  4303. _pPrinterData->ePrinterPublishState( TPrinterData::kUnPublish );
  4304. }
  4305. }
  4306. //
  4307. // Set the new publish action.
  4308. //
  4309. switch ( _pPrinterData->ePrinterPublishState() )
  4310. {
  4311. case TPrinterData::kPublish:
  4312. _pPrinterData->_dwAction = DSPRINT_PUBLISH | _pPrinterData->_dwAction & DSPRINT_PENDING;
  4313. break;
  4314. case TPrinterData::kUnPublish:
  4315. _pPrinterData->_dwAction = DSPRINT_UNPUBLISH | _pPrinterData->_dwAction & DSPRINT_PENDING;
  4316. break;
  4317. case TPrinterData::kNoAction:
  4318. default:
  4319. break;
  4320. }
  4321. }
  4322. //
  4323. // Get the share name from the edit control.
  4324. //
  4325. bStatus DBGCHK = bGetEditText( _hDlg, IDC_SHARED_NAME, _pPrinterData->strShareName() );
  4326. if( !bStatus )
  4327. {
  4328. _pPrinterData->_bErrorSaving = TRUE;
  4329. vShowResourceError( _hDlg );
  4330. }
  4331. }
  4332. BOOL
  4333. TPrinterSharing::
  4334. bKillActive(
  4335. VOID
  4336. )
  4337. /*++
  4338. Routine Description:
  4339. Validate that the share page is in a consistent state.
  4340. Arguments:
  4341. None.
  4342. Return Value:
  4343. TRUE - Ok to kill active, FALSE = can't kill active, UI displayed.
  4344. --*/
  4345. {
  4346. BOOL bStatus = TRUE;
  4347. //
  4348. // Read the UI in to the printer data.
  4349. //
  4350. vReadUI();
  4351. //
  4352. // If not shared then just return success.
  4353. //
  4354. if( !( _pPrinterData->_dwAttributes & PRINTER_ATTRIBUTE_SHARED ) )
  4355. {
  4356. return bStatus;
  4357. }
  4358. //
  4359. // If the share name has not changed then do nothing.
  4360. //
  4361. if( _strShareName == _pPrinterData->_strShareName )
  4362. {
  4363. return bStatus;
  4364. }
  4365. //
  4366. // If the share object has not been constructed, then create it.
  4367. //
  4368. if( !_pPrtShare )
  4369. {
  4370. //
  4371. // Construct the share object.
  4372. //
  4373. _pPrtShare = new TPrtShare( _pPrinterData->pszServerName() );
  4374. //
  4375. // Ensure we have a valid share object.
  4376. //
  4377. bStatus = VALID_PTR( _pPrtShare );
  4378. }
  4379. if( bStatus )
  4380. {
  4381. //
  4382. // If the share name is empty.
  4383. //
  4384. if( _pPrinterData->_strShareName.bEmpty() )
  4385. {
  4386. iMessage( _hDlg,
  4387. IDS_ERR_PRINTER_PROP_TITLE,
  4388. IDS_ERR_NO_SHARE_NAME,
  4389. MB_OK|MB_ICONSTOP,
  4390. kMsgNone,
  4391. NULL );
  4392. bStatus = FALSE;
  4393. }
  4394. }
  4395. if( bStatus )
  4396. {
  4397. //
  4398. // If share name is not a valid NT share name, put error message.
  4399. //
  4400. if( _pPrtShare->iIsValidNtShare( _pPrinterData->_strShareName ) != TPrtShare::kSuccess )
  4401. {
  4402. iMessage( _hDlg,
  4403. IDS_ERR_PRINTER_PROP_TITLE,
  4404. IDS_ERR_INVALID_CHAR_SHARENAME,
  4405. MB_OK|MB_ICONSTOP,
  4406. kMsgNone,
  4407. NULL );
  4408. bStatus = FALSE;
  4409. }
  4410. }
  4411. if( bStatus )
  4412. {
  4413. //
  4414. // Check if the share name is a valid DOS share.
  4415. //
  4416. if( !_bAcceptInvalidDosShareName && ( _pPrtShare->iIsValidDosShare( _pPrinterData->_strShareName ) != TPrtShare::kSuccess ) )
  4417. {
  4418. INT iStatus = iMessage( _hDlg,
  4419. IDS_ERR_PRINTER_PROP_TITLE,
  4420. IDS_ERR_SHARE_NAME_NOT_DOS,
  4421. MB_YESNO|MB_ICONEXCLAMATION,
  4422. kMsgNone,
  4423. NULL );
  4424. if( iStatus != IDYES )
  4425. {
  4426. bStatus = FALSE;
  4427. }
  4428. else
  4429. {
  4430. _bAcceptInvalidDosShareName = TRUE;
  4431. }
  4432. }
  4433. }
  4434. if( bStatus )
  4435. {
  4436. //
  4437. // If the share name confilcts with an existing name.
  4438. // If the previous name was ours and we were shared,
  4439. // do not display the error message.
  4440. //
  4441. if( !_pPrtShare->bIsValidShareNameForThisPrinter( _pPrinterData->_strShareName,
  4442. _pPrinterData->strPrinterName() ))
  4443. {
  4444. iMessage( _hDlg,
  4445. IDS_ERR_PRINTER_PROP_TITLE,
  4446. IDS_ERR_DUPLICATE_SHARE,
  4447. MB_OK|MB_ICONSTOP,
  4448. kMsgNone,
  4449. NULL );
  4450. bStatus = FALSE;
  4451. }
  4452. }
  4453. //
  4454. // Check if it is ok to loose the focus.
  4455. //
  4456. if( !bStatus )
  4457. {
  4458. //
  4459. // Set the focus to the shared as text.
  4460. //
  4461. SetFocus( GetDlgItem( _hDlg, IDC_SHARED_NAME ));
  4462. //
  4463. // Don't switch pages.
  4464. //
  4465. vSetDlgMsgResult( TRUE );
  4466. //
  4467. // Must return true to acknowledge the SetDlgMsgResult error.
  4468. //
  4469. bStatus = TRUE;
  4470. }
  4471. return bStatus;
  4472. }
  4473. VOID
  4474. TPrinterSharing::
  4475. vSetActive(
  4476. VOID
  4477. )
  4478. /*++
  4479. Routine Description:
  4480. Routine called when the pages is set active. This routine
  4481. will refresh the icon if it has changed.
  4482. Arguments:
  4483. None.
  4484. Return Value:
  4485. Nothing.
  4486. --*/
  4487. {
  4488. //
  4489. // Set the icon and printer name.
  4490. //
  4491. vSetIconName();
  4492. //
  4493. // Set the pending status.
  4494. //
  4495. if( _pPrinterData->_dwAction & DSPRINT_PENDING && !_bHideListed )
  4496. {
  4497. bSetEditText( _hDlg, IDC_DS_OPERATION_PENDING, _strPendingText );
  4498. }
  4499. else
  4500. {
  4501. bSetEditText( _hDlg, IDC_DS_OPERATION_PENDING, gszNULL );
  4502. }
  4503. }
  4504. VOID
  4505. TPrinterSharing::
  4506. vAdditionalDrivers(
  4507. IN WPARAM wParam,
  4508. IN LPARAM lParam
  4509. )
  4510. /*++
  4511. Routine Description:
  4512. Handle launching server prperties dialog.
  4513. Arguments:
  4514. wParam - Parameter passed to by dialog proc.
  4515. lParam - Parameter passed to by dialog proc.
  4516. Return Value:
  4517. Nothing.
  4518. --*/
  4519. {
  4520. BOOL bStatus = FALSE;
  4521. //
  4522. // Create additional drivers dialog.
  4523. //
  4524. TAdditionalDrivers Drivers( _hDlg,
  4525. _pPrinterData->strServerName(),
  4526. _pPrinterData->strPrinterName(),
  4527. _pPrinterData->strDriverName(),
  4528. _pPrinterData->bAdministrator() );
  4529. //
  4530. // Check if print processor dialog was created ok.
  4531. //
  4532. if( VALID_OBJ( Drivers ))
  4533. {
  4534. bStatus = TRUE;
  4535. if( Drivers.bDoModal() == IDOK )
  4536. {
  4537. vCancelToClose();
  4538. }
  4539. }
  4540. //
  4541. // If an error occurred then display an error message.
  4542. //
  4543. if( !bStatus )
  4544. {
  4545. iMessage( _hDlg,
  4546. IDS_ERR_PRINTER_PROP_TITLE,
  4547. IDS_ERR_ADD_DRV_ERROR,
  4548. MB_OK|MB_ICONHAND,
  4549. kMsgGetLastError,
  4550. NULL );
  4551. }
  4552. }
  4553. BOOL
  4554. TPrinterSharing::
  4555. _bHandleMessage(
  4556. IN UINT uMsg,
  4557. IN WPARAM wParam,
  4558. IN LPARAM lParam
  4559. )
  4560. {
  4561. TStatusB bStatus;
  4562. bStatus DBGNOCHK = TRUE;
  4563. switch (uMsg)
  4564. {
  4565. case WM_INITDIALOG:
  4566. {
  4567. //
  4568. // First we need to check if sharing is enabled. If sharing isn't
  4569. // enabled then we direct the user to the home networking wizard
  4570. // (HNW) to enable sharing.
  4571. //
  4572. BOOL bSharingEnabled;
  4573. if (SUCCEEDED(IsSharingEnabled(&bSharingEnabled)))
  4574. {
  4575. _bSharingEnabled = bSharingEnabled;
  4576. }
  4577. //
  4578. // Load the UI now...
  4579. //
  4580. bSetUI();
  4581. }
  4582. break;
  4583. case WM_SETTINGCHANGE:
  4584. {
  4585. //
  4586. // The home networking wizard (HNW) will send WM_SETTINGCHANGE when
  4587. // sharing options change. We need to check here and reload the UI
  4588. // if necessary.
  4589. //
  4590. BOOL bSharingEnabled;
  4591. if (SUCCEEDED(IsSharingEnabled(&bSharingEnabled)))
  4592. {
  4593. if (_bSharingEnabled != bSharingEnabled)
  4594. {
  4595. //
  4596. // The setting has changed - refresh the state and reload the UI.
  4597. //
  4598. _bSharingEnabled = bSharingEnabled;
  4599. bSetUI();
  4600. }
  4601. }
  4602. }
  4603. break;
  4604. case WM_APP:
  4605. vSetActive();
  4606. break;
  4607. case WM_HELP:
  4608. case WM_CONTEXTMENU:
  4609. PrintUIHelp(uMsg, _hDlg, wParam, lParam);
  4610. break;
  4611. case WM_COMMAND:
  4612. switch (GET_WM_COMMAND_ID(wParam, lParam))
  4613. {
  4614. case IDC_SHARED_NAME:
  4615. bStatus DBGNOCHK = GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE;
  4616. //
  4617. // When we change the content of share name, we need to check dos-validate share name again
  4618. //
  4619. if (bStatus)
  4620. {
  4621. _bAcceptInvalidDosShareName = FALSE;
  4622. }
  4623. break;
  4624. case IDC_SHARED_OFF:
  4625. vUnsharePrinter();
  4626. break;
  4627. case IDC_SHARED:
  4628. vSharePrinter();
  4629. break;
  4630. case IDC_SERVER_PROPERTIES:
  4631. vAdditionalDrivers(wParam, lParam);
  4632. break;
  4633. case IDC_PUBLISHED:
  4634. break;
  4635. default:
  4636. bStatus DBGNOCHK = FALSE;
  4637. break;
  4638. }
  4639. break;
  4640. case WM_NOTIFY:
  4641. {
  4642. LPNMHDR pnmh = (LPNMHDR)lParam;
  4643. switch (pnmh->code)
  4644. {
  4645. case PSN_KILLACTIVE:
  4646. bStatus DBGNOCHK = bKillActive();
  4647. break;
  4648. case NM_RETURN:
  4649. case NM_CLICK:
  4650. if (IDC_SHARING_DISABLED == wParam)
  4651. {
  4652. //
  4653. // Launch the home networking wizard (HNW) to enable sharing.
  4654. //
  4655. BOOL bRebootRequired = FALSE;
  4656. bStatus DBGCHK = SUCCEEDED(LaunchHomeNetworkingWizard(_hDlg, &bRebootRequired));
  4657. if (bStatus && bRebootRequired)
  4658. {
  4659. //
  4660. // Reboot was requested. Note that if the user has made changes in the UI
  4661. // and hasn't hit the apply button then he'll loose those changes, but
  4662. // that should be OK because he still has the option to choose [No],
  4663. // apply the changes and then restart.
  4664. //
  4665. RestartDialogEx(_hDlg, NULL, EWX_REBOOT,
  4666. SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_RECONFIG);
  4667. }
  4668. }
  4669. else if ( IDC_ENABLE_SHARING == wParam )
  4670. {
  4671. UINT iRet = DialogBox( ghInst, MAKEINTRESOURCE(IDD_SIMPLE_SHARE_ENABLE_WARNING), _hDlg, WarningDlgProc );
  4672. if ( IDC_RB_RUN_THE_WIZARD == iRet )
  4673. {
  4674. //
  4675. // Launch the home networking wizard (HNW) to enable sharing.
  4676. //
  4677. BOOL bRebootRequired = FALSE;
  4678. bStatus DBGCHK = SUCCEEDED(LaunchHomeNetworkingWizard(_hDlg, &bRebootRequired));
  4679. if (bStatus && bRebootRequired)
  4680. {
  4681. //
  4682. // Reboot was requested. Note that if the user has made changes in the UI
  4683. // and hasn't hit the apply button then he'll loose those changes, but
  4684. // that should be OK because he still has the option to choose [No],
  4685. // apply the changes and then restart.
  4686. //
  4687. RestartDialogEx(_hDlg, NULL, EWX_REBOOT,
  4688. SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_RECONFIG);
  4689. }
  4690. }
  4691. else if ( IDC_RB_ENABLE_FILE_SHARING == iRet )
  4692. {
  4693. ILocalMachine *pLM;
  4694. HRESULT hr = CoCreateInstance(CLSID_ShellLocalMachine, NULL, CLSCTX_INPROC_SERVER, IID_ILocalMachine, (void**)&pLM);
  4695. if (SUCCEEDED(hr))
  4696. {
  4697. hr = pLM->EnableGuest(ILM_GUEST_NETWORK_LOGON);
  4698. pLM->Release();
  4699. if ( HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr )
  4700. {
  4701. TString strTitle;
  4702. TString strMessage;
  4703. bStatus DBGCHK = strTitle.bLoadString( ghInst, IDS_ERR_ACCESS_DENIED );
  4704. bStatus DBGCHK = strMessage.bLoadString( ghInst, IDS_INSUFFICENT_PRIVILLEGE );
  4705. MessageBox( _hDlg, strMessage, strTitle, MB_OK );
  4706. }
  4707. //
  4708. // Let everybody else know we changed something.
  4709. //
  4710. SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0);
  4711. }
  4712. bStatus DBGNOCHK = SUCCEEDED(hr);
  4713. }
  4714. else
  4715. {
  4716. bStatus DBGNOCHK = FALSE;
  4717. }
  4718. }
  4719. else
  4720. {
  4721. bStatus DBGNOCHK = FALSE;
  4722. }
  4723. break;
  4724. default:
  4725. bStatus DBGNOCHK = FALSE;
  4726. break;
  4727. }
  4728. }
  4729. break;
  4730. default:
  4731. bStatus DBGNOCHK = FALSE;
  4732. break;
  4733. }
  4734. if (bStatus && _bSetUIDone)
  4735. {
  4736. vReadUI();
  4737. }
  4738. return bStatus;
  4739. }
  4740. /*++
  4741. Routine Description:
  4742. Dialog proc for the enabling sharing warning dialog.
  4743. Arguments:
  4744. Standard dialog message parameters.
  4745. Return Value:
  4746. EndDialog will return IDCANCEL if the user cancelled the dialog. EndDialog
  4747. will return IDC_RB_RUN_THE_WIZARD if the user selected to run the Wizard.
  4748. EndDialog will return IDC_RB_ENABLE_FILE_SHARING if the user selected to
  4749. bypass the wizard.
  4750. --*/
  4751. INT_PTR
  4752. WarningDlgProc(
  4753. IN HWND hWnd,
  4754. IN UINT msg,
  4755. IN WPARAM wParam,
  4756. IN LPARAM lParam
  4757. )
  4758. {
  4759. switch (msg)
  4760. {
  4761. case WM_INITDIALOG:
  4762. {
  4763. //
  4764. // Load warning icon from USER32.
  4765. //
  4766. HICON hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_WARNING));
  4767. if (hIcon)
  4768. {
  4769. SendDlgItemMessage(hWnd, IDC_ICON_INFO, STM_SETICON, (WPARAM )hIcon, 0L);
  4770. }
  4771. //
  4772. // Set default radio item.
  4773. //
  4774. SendDlgItemMessage(hWnd, IDC_RB_RUN_THE_WIZARD, BM_SETCHECK, BST_CHECKED, 0);
  4775. }
  4776. break;
  4777. case WM_COMMAND:
  4778. switch (LOWORD(wParam))
  4779. {
  4780. case IDOK:
  4781. if ( BN_CLICKED == HIWORD(wParam) )
  4782. {
  4783. UINT iRet = SendDlgItemMessage(hWnd, IDC_RB_RUN_THE_WIZARD, BM_GETCHECK, 0, 0 );
  4784. if ( BST_CHECKED == iRet )
  4785. {
  4786. EndDialog(hWnd, IDC_RB_RUN_THE_WIZARD );
  4787. }
  4788. else
  4789. {
  4790. EndDialog(hWnd, IDC_RB_ENABLE_FILE_SHARING );
  4791. }
  4792. }
  4793. break;
  4794. case IDCANCEL:
  4795. if ( BN_CLICKED == HIWORD(wParam) )
  4796. {
  4797. EndDialog(hWnd, IDCANCEL);
  4798. return TRUE;
  4799. }
  4800. break;
  4801. }
  4802. break;
  4803. }
  4804. return FALSE;
  4805. }