Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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