Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1575 lines
36 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. All rights reserved.
  4. Module Name:
  5. docprop.cxx
  6. Abstract:
  7. Job Properties
  8. Author:
  9. Steve Kiraly (SteveKi) 10/19/95
  10. Revision History:
  11. Lazar Ivanov (LazarI) - added DocumentPropertiesWrap (Nov-03-2000)
  12. --*/
  13. #include "precomp.hxx"
  14. #pragma hdrstop
  15. #include "time.hxx"
  16. #include "docdata.hxx"
  17. #include "propmgr.hxx"
  18. #include "docprop.hxx"
  19. /*++
  20. Routine Name:
  21. vDocPropSelections
  22. Routine Description:
  23. Displays Document property sheets for multiple selections.
  24. Arguments:
  25. TSelection - pointer to a list of document selections.
  26. Return Value:
  27. Nothing.
  28. --*/
  29. VOID
  30. vDocumentPropSelections(
  31. IN HWND hWnd,
  32. IN LPCTSTR pszPrinterName,
  33. IN TSelection *pSelection
  34. )
  35. {
  36. //
  37. // Get the selection information. We are in a loop to
  38. // handle the selection of multiple jobs.
  39. //
  40. for( UINT i = 0; i < pSelection->_cSelected; ++i ){
  41. //
  42. // Display the document property pages.
  43. //
  44. vDocumentPropPages(
  45. hWnd,
  46. pszPrinterName,
  47. pSelection->_pid[i],
  48. SW_SHOWNORMAL,
  49. 0 );
  50. }
  51. }
  52. /*++
  53. Routine Description:
  54. This function opens the property sheet of specified document.
  55. We can't guarentee that this propset will perform all lengthy
  56. operations in a worker thread (we synchronously call things like
  57. ConfigurePort). Therefore, we spawn off a separate thread to
  58. handle document properties.
  59. Arguments:
  60. hWnd - Specifies the parent window (optional).
  61. pszPrinter - Specifies the printer name
  62. nCmdShow - Initial show state
  63. lParam - May spcify a sheet specifc index to directly open.
  64. Return Value:
  65. --*/
  66. VOID
  67. vDocumentPropPages(
  68. IN HWND hWnd,
  69. IN LPCTSTR pszPrinterName,
  70. IN IDENT JobId,
  71. IN INT iCmdShow,
  72. IN LPARAM lParam
  73. )
  74. {
  75. HANDLE hThread;
  76. //
  77. // Create the document specific data
  78. //
  79. TDocumentData* pDocumentData = new TDocumentData( pszPrinterName,
  80. JobId,
  81. iCmdShow,
  82. lParam );
  83. //
  84. // If errors were encountered creating document data.
  85. //
  86. if( !VALID_PTR( pDocumentData )){
  87. goto Fail;
  88. }
  89. //
  90. // Create the thread which handles the UI. vPrinterPropPages adopts
  91. // pPrinterData, therefore only on thread creation failure do we
  92. // releae the document data back to the heap.
  93. //
  94. DWORD dwIgnore;
  95. hThread = TSafeThread::Create( NULL,
  96. 0,
  97. (LPTHREAD_START_ROUTINE)iDocumentPropPagesProc,
  98. pDocumentData,
  99. 0,
  100. &dwIgnore );
  101. //
  102. // Check thread creation.
  103. //
  104. if( !hThread ){
  105. //
  106. // Display error message, and release document data.
  107. //
  108. vShowResourceError( hWnd );
  109. delete pDocumentData;
  110. } else {
  111. CloseHandle( hThread );
  112. }
  113. return;
  114. Fail:
  115. //
  116. // Display the error message.
  117. //
  118. iMessage( hWnd,
  119. IDS_ERR_DOC_JOB_PROPERTY_TITLE,
  120. IDS_ERR_DOC_JOB_PROPERTY_JOB_NA,
  121. MB_OK|MB_ICONSTOP,
  122. kMsgGetLastError,
  123. NULL );
  124. delete pDocumentData;
  125. }
  126. /*++
  127. Routine Name:
  128. iDocumentPropPagesProc
  129. Routine Description:
  130. This is the routine called by the create thread call to display the
  131. document property sheets.
  132. Arguments:
  133. pDocumentData - Pointer to the document data needed for all property sheets.
  134. Return Value:
  135. TRUE - if the property sheets were displayed.
  136. FALSE - error creating and displaying property sheets.
  137. --*/
  138. INT
  139. iDocumentPropPagesProc(
  140. IN TDocumentData *pDocumentData ADOPT
  141. )
  142. {
  143. DBGMSG( DBG_TRACE, ( "iDocumentPropPagesProc\n") );
  144. BOOL bStatus;
  145. bStatus = pDocumentData->bRegisterWindow( PRINTER_PIDL_TYPE_JOBID |
  146. pDocumentData->JobId( ));
  147. if( bStatus ){
  148. //
  149. // Check if the window is already present. If it is, then
  150. // exit immediately.
  151. //
  152. if( !pDocumentData->hwnd( )){
  153. delete pDocumentData;
  154. return 0;
  155. }
  156. bStatus = pDocumentData->bLoad();
  157. }
  158. if( !bStatus ){
  159. iMessage( pDocumentData->hwnd(),
  160. IDS_ERR_DOC_JOB_PROPERTY_TITLE,
  161. IDS_ERR_DOC_JOB_PROPERTY_JOB_NA,
  162. MB_OK|MB_ICONSTOP|MB_SETFOREGROUND,
  163. kMsgGetLastError,
  164. NULL );
  165. delete pDocumentData;
  166. return 0;
  167. }
  168. //
  169. // Create the ducument property sheet windows.
  170. //
  171. TDocumentWindows DocumentWindows( pDocumentData );
  172. //
  173. // Were the document windows create
  174. //
  175. if( !VALID_OBJ( DocumentWindows ) ){
  176. vShowResourceError( pDocumentData->hwnd() );
  177. bStatus = FALSE;
  178. }
  179. //
  180. // Display the property pages.
  181. //
  182. if( bStatus ){
  183. if( !DocumentWindows.bDisplayPages( pDocumentData->hwnd() ) ){
  184. vShowResourceError( pDocumentData->hwnd() );
  185. bStatus = FALSE;
  186. }
  187. }
  188. //
  189. // Ensure we release the document data.
  190. // We have adopted pPrinterData, so we must free it.
  191. //
  192. delete pDocumentData;
  193. return bStatus;
  194. }
  195. /********************************************************************
  196. Document Prop Base Class
  197. ********************************************************************/
  198. /*++
  199. Routine Name:
  200. TDocumentProp
  201. Routine Description:
  202. Initialized the document property sheet base class
  203. Arguments:
  204. pDocumentData - Pointer to the document data needed for all property sheets.
  205. Return Value:
  206. None.
  207. --*/
  208. TDocumentProp::
  209. TDocumentProp(
  210. TDocumentData* pDocumentData
  211. ) : _pDocumentData( pDocumentData ),
  212. _bApplyData( FALSE )
  213. {
  214. }
  215. /*++
  216. Routine Name:
  217. ~TDocumentProp
  218. Routine Description:
  219. Base class desctuctor.
  220. Arguments:
  221. None.
  222. Return Value:
  223. Nothing.
  224. --*/
  225. TDocumentProp::
  226. ~TDocumentProp(
  227. )
  228. {
  229. }
  230. /*++
  231. Routine Name:
  232. bHandleMessage
  233. Routine Description:
  234. Base class message handler. This routine is called by
  235. derived classes who do not want to handle the message.
  236. Arguments:
  237. uMsg - Windows message
  238. wParam - Word parameter
  239. lParam - Long parameter
  240. Return Value:
  241. TRUE if message was handled, FALSE if message not handled.
  242. --*/
  243. BOOL
  244. TDocumentProp::
  245. bHandleMessage(
  246. IN UINT uMsg,
  247. IN WPARAM wParam,
  248. IN LPARAM lParam
  249. )
  250. {
  251. BOOL bStatus = TRUE;
  252. switch( uMsg ){
  253. //
  254. // Set the values on the UI.
  255. //
  256. case WM_INITDIALOG:
  257. bStatus = bSetUI();
  258. break;
  259. //
  260. // Handle help and context help.
  261. //
  262. case WM_HELP:
  263. case WM_CONTEXTMENU:
  264. bStatus = PrintUIHelp( uMsg, _hDlg, wParam, lParam );
  265. break;
  266. case WM_NOTIFY:
  267. switch( ((LPNMHDR)lParam)->code )
  268. {
  269. //
  270. // User switched to the next page.
  271. //
  272. case PSN_KILLACTIVE:
  273. bStatus = bReadUI();
  274. vSetDlgMsgResult( !bStatus ? TRUE : FALSE );
  275. break;
  276. //
  277. // User chiose the apply button.
  278. //
  279. case PSN_APPLY:
  280. _bApplyData = TRUE;
  281. bStatus = ( _bApplyData ) ? bSaveUI() : FALSE;
  282. if( !bStatus )
  283. {
  284. //
  285. // Switch to page with the error.
  286. //
  287. PropSheet_SetCurSelByID( GetParent( _hDlg ), DLG_DOC_JOB_GENERAL );
  288. }
  289. vSetDlgMsgResult( !bStatus ? PSNRET_INVALID_NOCHANGEPAGE : PSNRET_NOERROR );
  290. break;
  291. //
  292. // Indicate the use canceled the dialog.
  293. //
  294. case PSN_QUERYCANCEL:
  295. _bApplyData = FALSE;
  296. break;
  297. default:
  298. bStatus = FALSE;
  299. break;
  300. }
  301. break;
  302. default:
  303. bStatus = FALSE;
  304. break;
  305. }
  306. if( !bStatus )
  307. {
  308. //
  309. // Allow the derived classes to handle the message.
  310. //
  311. bStatus = _bHandleMessage( uMsg, wParam, lParam );
  312. }
  313. //
  314. // If the message was handled check if the
  315. // apply button should be enabled.
  316. //
  317. if( bStatus )
  318. {
  319. if( _pDocumentData->bCheckForChange() )
  320. {
  321. PropSheet_Changed( GetParent( _hDlg ), _hDlg );
  322. }
  323. else
  324. {
  325. PropSheet_UnChanged( GetParent( _hDlg), _hDlg );
  326. }
  327. }
  328. return bStatus;
  329. }
  330. /********************************************************************
  331. General Document Property Sheet.
  332. ********************************************************************/
  333. /*++
  334. Routine Name:
  335. TDocumentGeneral
  336. Routine Description:
  337. Document property sheet derived class.
  338. Arguments:
  339. None.
  340. Return Value:
  341. Nothing.
  342. --*/
  343. TDocumentGeneral::
  344. TDocumentGeneral(
  345. IN TDocumentData* pDocumentData
  346. ) : TDocumentProp( pDocumentData ),
  347. _bSetUIDone( FALSE )
  348. {
  349. }
  350. /*++
  351. Routine Name:
  352. ~TDocumentGeneral
  353. Routine Description:
  354. Document derived class destructor.
  355. Arguments:
  356. None.
  357. Return Value:
  358. Nothing.
  359. --*/
  360. TDocumentGeneral::
  361. ~TDocumentGeneral(
  362. )
  363. {
  364. }
  365. /*++
  366. Routine Name:
  367. bValid
  368. Routine Description:
  369. Document property sheet derived class valid object indicator.
  370. Arguments:
  371. None.
  372. Return Value:
  373. Returns the status of the base class.
  374. --*/
  375. BOOL
  376. TDocumentGeneral::
  377. bValid(
  378. VOID
  379. )
  380. {
  381. return TDocumentProp::bValid();
  382. }
  383. /*++
  384. Routine Name:
  385. bSetStartAndUntilTime
  386. Routine Description:
  387. Initialized the start and until time.
  388. Arguments:
  389. None.
  390. Return Value:
  391. TRUE time controls initialized, FALSE error occured.
  392. --*/
  393. BOOL
  394. TDocumentGeneral::
  395. bSetStartAndUntilTime(
  396. VOID
  397. )
  398. {
  399. TString strFormatString;
  400. TStatusB bStatus;
  401. //
  402. // Get the time format string without seconds.
  403. //
  404. bStatus DBGCHK = bGetTimeFormatString( strFormatString );
  405. //
  406. // If we have retrived a valid time format string then use it,
  407. // else use the default format string implemented by common control.
  408. //
  409. if( bStatus )
  410. {
  411. DateTime_SetFormat(GetDlgItem( _hDlg, IDC_DOC_JOB_START_TIME ), static_cast<LPCTSTR>( strFormatString ) );
  412. DateTime_SetFormat(GetDlgItem( _hDlg, IDC_DOC_JOB_UNTIL_TIME ), static_cast<LPCTSTR>( strFormatString ) );
  413. }
  414. //
  415. // If the printer is always available.
  416. //
  417. BOOL bAlways = ( _pDocumentData->pJobInfo()->StartTime == _pDocumentData->pJobInfo()->UntilTime );
  418. //
  419. // Set the start time.
  420. //
  421. SYSTEMTIME StartTime = { 0 };
  422. DWORD dwLocalStartTime = 0;
  423. GetLocalTime( &StartTime );
  424. dwLocalStartTime = ( !bAlways ) ? SystemTimeToLocalTime( _pDocumentData->pJobInfo()->StartTime ) : 0;
  425. StartTime.wHour = static_cast<WORD>( dwLocalStartTime / 60 );
  426. StartTime.wMinute = static_cast<WORD>( dwLocalStartTime % 60 );
  427. DateTime_SetSystemtime(GetDlgItem( _hDlg, IDC_DOC_JOB_START_TIME ), GDT_VALID, &StartTime );
  428. //
  429. // Set the until time.
  430. //
  431. SYSTEMTIME UntilTime = { 0 };
  432. DWORD dwLocalUntilTime = 0;
  433. GetLocalTime( &UntilTime );
  434. dwLocalUntilTime = ( !bAlways ) ? SystemTimeToLocalTime( _pDocumentData->pJobInfo()->UntilTime ) : 0;
  435. UntilTime.wHour = static_cast<WORD>( dwLocalUntilTime / 60 );
  436. UntilTime.wMinute = static_cast<WORD>( dwLocalUntilTime % 60 );
  437. DateTime_SetSystemtime(GetDlgItem( _hDlg, IDC_DOC_JOB_UNTIL_TIME ), GDT_VALID, &UntilTime );
  438. return TRUE;
  439. }
  440. /*++
  441. Routine Name:
  442. bSetUI
  443. Routine Description:
  444. Loads the property sheet dialog with the document data
  445. information.
  446. Arguments:
  447. None.
  448. Return Value:
  449. TRUE if data loaded successfully, FALSE if error occurred.
  450. --*/
  451. BOOL
  452. TDocumentGeneral::
  453. bSetUI(
  454. VOID
  455. )
  456. {
  457. //
  458. // Get the flag if always availble.
  459. //
  460. BOOL bAlways = ( _pDocumentData->pJobInfo()->StartTime ==
  461. _pDocumentData->pJobInfo()->UntilTime );
  462. //
  463. // Initialize the stat and until time controls.
  464. //
  465. if( !bSetStartAndUntilTime() )
  466. {
  467. DBGMSG( DBG_TRACE, ( "TDocumentGeneral::bSetStartAndUntilTime failed %d\n", GetLastError( )));
  468. }
  469. //
  470. // Read the job size format string.
  471. //
  472. TString strFormat;
  473. if( strFormat.bLoadString( ghInst, IDS_JOB_SIZE ) ){
  474. //
  475. // Set the size in byes of the job.
  476. //
  477. bSetEditTextFormat( _hDlg,
  478. IDC_DOC_JOB_SIZE,
  479. strFormat,
  480. _pDocumentData->pJobInfo()->Size );
  481. }
  482. //
  483. // Set the Number of pages in the job.
  484. //
  485. bSetEditTextFormat( _hDlg,
  486. IDC_DOC_JOB_PAGES,
  487. TEXT( "%d" ),
  488. _pDocumentData->pJobInfo()->TotalPages );
  489. //
  490. // Set the document text.
  491. //
  492. bSetEditText( _hDlg, IDC_DOC_JOB_TITLE, _pDocumentData->pJobInfo()->pDocument );
  493. bSetEditText( _hDlg, IDC_DOC_JOB_DATATYPE, _pDocumentData->pJobInfo()->pDatatype );
  494. bSetEditText( _hDlg, IDC_DOC_JOB_PROCCESSOR, _pDocumentData->pJobInfo()->pPrintProcessor );
  495. bSetEditText( _hDlg, IDC_DOC_JOB_OWNER, _pDocumentData->pJobInfo()->pUserName );
  496. bSetEditText( _hDlg, IDC_DOC_JOB_NOTIFY, _pDocumentData->pJobInfo()->pNotifyName );
  497. //
  498. // Set the Priority indicator.
  499. //
  500. bSetEditTextFormat( _hDlg,
  501. IDC_DOC_JOB_PRIORITY,
  502. TEXT( "%d" ),
  503. _pDocumentData->pJobInfo()->Priority );
  504. SendDlgItemMessage( _hDlg,
  505. IDC_DOC_JOB_PRIORITY_CONTROL,
  506. TBM_SETRANGE,
  507. FALSE,
  508. MAKELONG( TDocumentData::kPriorityLowerBound, TDocumentData::kPriorityUpperBound ));
  509. SendDlgItemMessage( _hDlg,
  510. IDC_DOC_JOB_PRIORITY_CONTROL,
  511. TBM_SETPOS,
  512. TRUE,
  513. _pDocumentData->pJobInfo()->Priority );
  514. //
  515. // Format the submitted time field.
  516. //
  517. TStatusB bStatus = FALSE;
  518. TCHAR szBuff[kStrMax] = {0};
  519. SYSTEMTIME LocalTime;
  520. //
  521. // Convert to local time.
  522. //
  523. bStatus DBGCHK = SystemTimeToTzSpecificLocalTime(
  524. NULL,
  525. &_pDocumentData->pJobInfo()->Submitted,
  526. &LocalTime );
  527. if( !bStatus ){
  528. DBGMSG( DBG_MIN, ( "SysTimeToTzSpecLocalTime failed %d\n", GetLastError( )));
  529. }
  530. if( bStatus ){
  531. //
  532. // Convert using local format information.
  533. //
  534. bStatus DBGCHK = GetTimeFormat( LOCALE_USER_DEFAULT,
  535. 0,
  536. &LocalTime,
  537. NULL,
  538. szBuff,
  539. COUNTOF( szBuff ));
  540. if( !bStatus ){
  541. DBGMSG( DBG_MIN, ( "No Time %d, ", GetLastError( )));
  542. }
  543. }
  544. if( bStatus ){
  545. //
  546. // Tack on space between time and date.
  547. //
  548. lstrcat( szBuff, TEXT(" ") );
  549. //
  550. // Get data format.
  551. //
  552. bStatus DBGCHK = GetDateFormat( LOCALE_USER_DEFAULT,
  553. 0,
  554. &LocalTime,
  555. NULL,
  556. szBuff + lstrlen( szBuff ),
  557. COUNTOF( szBuff ) - lstrlen( szBuff ) );
  558. if( !bStatus ){
  559. DBGMSG( DBG_MIN, ( "No Date %d\n", GetLastError( )));
  560. }
  561. }
  562. //
  563. // Set the submitted field
  564. //
  565. bStatus DBGCHK = bSetEditText( _hDlg, IDC_DOC_JOB_AT, szBuff );
  566. //
  567. // Set schedule radio buttons.
  568. //
  569. CheckRadioButton( _hDlg, IDC_DOC_JOB_START, IDC_DOC_JOB_ALWAYS,
  570. bAlways ? IDC_DOC_JOB_ALWAYS : IDC_DOC_JOB_START );
  571. vEnableAvailable( !bAlways );
  572. //
  573. // Disable all the controls if not an administrator.
  574. //
  575. if( !_pDocumentData->bAdministrator( )){
  576. //
  577. // Disable the time controls.
  578. //
  579. vEnableAvailable( FALSE );
  580. //
  581. // Disable things if not administrator.
  582. //
  583. static UINT auAvailable[] = {
  584. IDC_DOC_JOB_NOTIFY,
  585. IDC_DOC_JOB_PRIORITY_CONTROL,
  586. IDC_DOC_JOB_ALWAYS,
  587. IDC_DOC_JOB_START,
  588. };
  589. COUNT i;
  590. for( i = 0; i < COUNTOF( auAvailable ); ++i ){
  591. vEnableCtl( _hDlg, auAvailable[i], FALSE );
  592. }
  593. }
  594. _bSetUIDone = TRUE;
  595. return TRUE;
  596. }
  597. /*++
  598. Routine Name:
  599. bReadUI
  600. Routine Description:
  601. Stores the property information to the print server.
  602. Arguments:
  603. Nothing data is contained with in the class.
  604. Return Value:
  605. TRUE if data is stores successfully, FALSE if error occurred.
  606. --*/
  607. BOOL
  608. TDocumentGeneral::
  609. bReadUI(
  610. VOID
  611. )
  612. {
  613. DBGMSG( DBG_TRACE, ( "TDocumentGeneral::bReadUI\n") );
  614. //
  615. // Attempt to validate any UI changeable data.
  616. // Currently not much can be validated, since all the
  617. // controls have set constraints.
  618. //
  619. //
  620. // Extract the UI and save it into the Document Data.
  621. //
  622. _pDocumentData->pJobInfo()->Priority = (DWORD)SendDlgItemMessage( _hDlg,
  623. IDC_DOC_JOB_PRIORITY_CONTROL,
  624. TBM_GETPOS,
  625. 0,
  626. 0 );
  627. //
  628. // Get the notify name.
  629. //
  630. bGetEditText( _hDlg, IDC_DOC_JOB_NOTIFY, _pDocumentData->strNotifyName() );
  631. _pDocumentData->pJobInfo()->pNotifyName = (LPTSTR)(LPCTSTR)_pDocumentData->strNotifyName();
  632. //
  633. // If the Job always is set then indicate
  634. // not time restriction in the start time and until time.
  635. //
  636. if( bGetCheck( _hDlg, IDC_DOC_JOB_ALWAYS ) ){
  637. _pDocumentData->pJobInfo()->StartTime = 0;
  638. _pDocumentData->pJobInfo()->UntilTime = 0;
  639. } else {
  640. //
  641. // Get the Start time.
  642. //
  643. SYSTEMTIME StartTime;
  644. DateTime_GetSystemtime( GetDlgItem( _hDlg, IDC_DOC_JOB_START_TIME ), &StartTime );
  645. _pDocumentData->pJobInfo()->StartTime = LocalTimeToSystemTime( StartTime.wHour * 60 + StartTime.wMinute );
  646. //
  647. // Get the Until time.
  648. //
  649. SYSTEMTIME UntilTime;
  650. DateTime_GetSystemtime( GetDlgItem( _hDlg, IDC_DOC_JOB_UNTIL_TIME ), &UntilTime );
  651. _pDocumentData->pJobInfo()->UntilTime = LocalTimeToSystemTime( UntilTime.wHour * 60 + UntilTime.wMinute );
  652. //
  653. // If the printer start and until time are the same this is
  654. // exactly the same as always available.
  655. //
  656. if( _pDocumentData->pJobInfo()->StartTime == _pDocumentData->pJobInfo()->UntilTime )
  657. {
  658. _pDocumentData->pJobInfo()->StartTime = 0;
  659. _pDocumentData->pJobInfo()->UntilTime = 0;
  660. }
  661. }
  662. //
  663. // Set the job position to unspecified it may
  664. // have changed while this dialog was up.
  665. //
  666. _pDocumentData->pJobInfo()->Position = JOB_POSITION_UNSPECIFIED;
  667. return TRUE;
  668. }
  669. /*++
  670. Routine Name:
  671. bSaveUI
  672. Routine Description:
  673. Saves the UI data to some API call or print server.
  674. Arguments:
  675. Nothing data is contained with in the class.
  676. Return Value:
  677. TRUE if data is stores successfully, FALSE if error occurred.
  678. --*/
  679. BOOL
  680. TDocumentGeneral::
  681. bSaveUI(
  682. VOID
  683. )
  684. {
  685. DBGMSG( DBG_TRACE, ( "TDocumentGeneral::bSaveUI\n") );
  686. //
  687. // Clear the error saving flag.
  688. //
  689. _pDocumentData->bErrorSaving() = TRUE;
  690. //
  691. // Save the document data.
  692. //
  693. if( !_pDocumentData->bStore() ){
  694. DWORD dwLastError = GetLastError ();
  695. if( dwLastError == ERROR_INVALID_TIME ){
  696. _pDocumentData->iErrorMsgId() = IDS_ERR_DOC_JOB_PROPERTY_TIME;
  697. } else {
  698. _pDocumentData->iErrorMsgId() = IDS_ERR_DOC_JOB_PROPERTY_MODIFY;
  699. }
  700. _pDocumentData->bErrorSaving() = FALSE;
  701. }
  702. //
  703. // If there was an error saving the document data.
  704. //
  705. if( !_pDocumentData->bErrorSaving() ){
  706. //
  707. // Display the error message.
  708. //
  709. iMessage( _hDlg,
  710. IDS_ERR_DOC_JOB_PROPERTY_TITLE,
  711. _pDocumentData->iErrorMsgId(),
  712. MB_OK|MB_ICONSTOP|MB_SETFOREGROUND,
  713. kMsgNone,
  714. NULL );
  715. return FALSE;
  716. }
  717. return TRUE;
  718. }
  719. /*++
  720. Routine Name:
  721. vEanbleAvailablity
  722. Routine Description:
  723. Enables the time availabilty of the job
  724. Arguments:
  725. TRUE enable the availablity, FALSE disable time availablity.
  726. Return Value:
  727. Nothing.
  728. --*/
  729. VOID
  730. TDocumentGeneral::
  731. vEnableAvailable(
  732. IN BOOL bEnable
  733. )
  734. {
  735. vEnableCtl( _hDlg, IDC_DOC_JOB_START_TIME, bEnable );
  736. vEnableCtl( _hDlg, IDC_DOC_JOB_UNTIL_TIME, bEnable );
  737. }
  738. /*++
  739. Routine Name:
  740. bReadUI
  741. Routine Description:
  742. Stores the property information to the print server.
  743. Arguments:
  744. Nothing data is contained with in the class.
  745. Return Value:
  746. TRUE if data is stores successfully, FALSE if error occurred.
  747. --*/
  748. VOID
  749. TDocumentGeneral::
  750. vSetActive(
  751. VOID
  752. )
  753. {
  754. DBGMSG( DBG_TRACE, ( "TDocumentGeneral::vSetActive\n") );
  755. (VOID)bSetStartAndUntilTime();
  756. }
  757. /*++
  758. Routine Name:
  759. bHandleMessage
  760. Routine Description:
  761. Document property sheet message handler. This handler only
  762. handles events it wants and the base class handle will do the
  763. standard message handling.
  764. Arguments:
  765. uMsg - Windows message
  766. wParam - Word parameter
  767. lParam - Long parameter
  768. Return Value:
  769. TRUE if message was handled, FALSE if message not handled.
  770. --*/
  771. BOOL
  772. TDocumentGeneral::
  773. _bHandleMessage(
  774. IN UINT uMsg,
  775. IN WPARAM wParam,
  776. IN LPARAM lParam
  777. )
  778. {
  779. BOOL bStatus = TRUE;
  780. switch( uMsg )
  781. {
  782. case WM_HSCROLL:
  783. //
  784. // Check for slider notification.
  785. //
  786. if( GET_WM_HSCROLL_HWND( wParam, lParam ) == GetDlgItem(_hDlg, IDC_DOC_JOB_PRIORITY_CONTROL ) ){
  787. bSetEditTextFormat( _hDlg,
  788. IDC_DOC_JOB_PRIORITY,
  789. TEXT("%d"),
  790. SendDlgItemMessage( _hDlg,
  791. IDC_DOC_JOB_PRIORITY_CONTROL,
  792. TBM_GETPOS,
  793. 0,
  794. 0 ) );
  795. }
  796. break;
  797. case WM_COMMAND:
  798. switch( GET_WM_COMMAND_ID( wParam, lParam ))
  799. {
  800. case IDC_DOC_JOB_ALWAYS:
  801. vEnableAvailable( FALSE );
  802. PropSheet_Changed( GetParent( _hDlg ), _hDlg );
  803. break;
  804. case IDC_DOC_JOB_START:
  805. vEnableAvailable( TRUE );
  806. PropSheet_Changed( GetParent( _hDlg ), _hDlg );
  807. break;
  808. case IDC_DOC_JOB_NOTIFY:
  809. bStatus = GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE;
  810. break;
  811. default:
  812. bStatus = FALSE;
  813. break;
  814. }
  815. break;
  816. case WM_WININICHANGE:
  817. vSetActive();
  818. break;
  819. case WM_NOTIFY:
  820. {
  821. LPNMHDR pnmh = (LPNMHDR)lParam;
  822. switch( wParam )
  823. {
  824. case 0:
  825. {
  826. switch( pnmh->code )
  827. {
  828. case PSN_SETACTIVE:
  829. vSetActive();
  830. break;
  831. default:
  832. bStatus = FALSE;
  833. break;
  834. }
  835. }
  836. break;
  837. case IDC_DOC_JOB_START_TIME:
  838. case IDC_DOC_JOB_UNTIL_TIME:
  839. {
  840. switch( pnmh->code )
  841. {
  842. case DTN_DATETIMECHANGE:
  843. break;
  844. default:
  845. bStatus = FALSE;
  846. break;
  847. }
  848. }
  849. break;
  850. default:
  851. bStatus = FALSE;
  852. break;
  853. }
  854. }
  855. break;
  856. default:
  857. bStatus = FALSE;
  858. break;
  859. }
  860. //
  861. // If message handled look for change.
  862. //
  863. if( bStatus && _bSetUIDone )
  864. {
  865. (VOID)bReadUI();
  866. }
  867. return bStatus;
  868. }
  869. /********************************************************************
  870. Document property windows.
  871. ********************************************************************/
  872. /*++
  873. Routine Description:
  874. Document property windows.
  875. Arguments:
  876. pDocumentData - Document data to display.
  877. Return Value:
  878. TRUE - Success, FALSE - failure.
  879. --*/
  880. TDocumentWindows::
  881. TDocumentWindows(
  882. TDocumentData* pDocumentData
  883. ) : _pDocumentData( pDocumentData ),
  884. _General( pDocumentData )
  885. {
  886. DBGMSG( DBG_TRACE, ( "TDocumentWindows ctor\n") );
  887. }
  888. TDocumentWindows::
  889. ~TDocumentWindows(
  890. )
  891. {
  892. DBGMSG( DBG_TRACE, ( "TDocumentWindows dtor\n") );
  893. }
  894. /*++
  895. Routine Name:
  896. bBuildPages
  897. Routine Description:
  898. Builds the document property windows.
  899. Arguments:
  900. None - class specific.
  901. Return Value:
  902. TRUE pages built ok, FALSE failure building pages.
  903. --*/
  904. BOOL
  905. TDocumentWindows::
  906. bBuildPages(
  907. IN PPROPSHEETUI_INFO pCPSUIInfo
  908. )
  909. {
  910. TStatusB bStatus;
  911. DBGMSG( DBG_TRACE, ( "TDocumentWindows bBuildPages\n") );
  912. //
  913. // Set the default activation context to be V6 prior calling into
  914. // compstui to create the pages. This will force V6 context unless
  915. // the callbacks which create the compstui pages specify otherwise
  916. // on a per page basis.
  917. //
  918. bStatus DBGCHK = (BOOL)pCPSUIInfo->pfnComPropSheet(
  919. pCPSUIInfo->hComPropSheet,
  920. CPSFUNC_SET_FUSION_CONTEXT,
  921. reinterpret_cast<LPARAM>(g_hActCtx),
  922. static_cast<LPARAM>(0));
  923. if (bStatus)
  924. {
  925. PROPSHEETPAGE psp;
  926. ZeroMemory( &psp, sizeof( psp ) );
  927. psp.dwSize = sizeof( psp );
  928. psp.dwFlags = PSP_DEFAULT;
  929. psp.hInstance = ghInst;
  930. psp.pfnDlgProc = MGenericProp::SetupDlgProc;
  931. psp.pszTemplate = MAKEINTRESOURCE( DLG_DOC_JOB_GENERAL );
  932. psp.lParam = (LPARAM)(MGenericProp*)&_General;
  933. if( pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
  934. CPSFUNC_ADD_PROPSHEETPAGE,
  935. (LPARAM)&psp,
  936. NULL ) <= 0 )
  937. {
  938. DBGMSG( DBG_TRACE, ( "CPSFUNC_ADD_PROPSHEETPAGE failed.\n") );
  939. bStatus DBGCHK = FALSE;
  940. }
  941. if (bStatus)
  942. {
  943. //
  944. // If the dev mode is null don't display the
  945. // device property sheets.
  946. //
  947. if( _pDocumentData->pJobInfo()->pDevMode )
  948. {
  949. ZeroMemory( &_dph, sizeof( _dph ) );
  950. _dph.cbSize = sizeof( _dph );
  951. _dph.hPrinter = _pDocumentData->hPrinter();
  952. _dph.pszPrinterName = (LPTSTR)(LPCTSTR)_pDocumentData->strPrinterName();
  953. _dph.pdmOut = _pDocumentData->pJobInfo()->pDevMode;
  954. _dph.pdmIn = _pDocumentData->pJobInfo()->pDevMode;
  955. _dph.fMode = DM_IN_BUFFER | DM_PROMPT | DM_NOPERMISSION;
  956. if( pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
  957. CPSFUNC_ADD_PFNPROPSHEETUI,
  958. (LPARAM)DocumentPropertySheets,
  959. (LPARAM)&_dph ) <= 0 )
  960. {
  961. DBGMSG( DBG_TRACE, ( "CPSFUNC_ADD_PFNPROPSHEETUI failed.\n") );
  962. bStatus DBGCHK = FALSE;
  963. }
  964. }
  965. }
  966. }
  967. return bStatus;
  968. }
  969. BOOL
  970. TDocumentWindows::
  971. bSetHeader(
  972. IN PPROPSHEETUI_INFO pCPSUIInfo,
  973. IN PPROPSHEETUI_INFO_HEADER pPSUIInfoHdr
  974. )
  975. {
  976. DBGMSG( DBG_TRACE, ( "TDocumentWindows bSetHeader\n") );
  977. UNREFERENCED_PARAMETER( pCPSUIInfo );
  978. pPSUIInfoHdr->pTitle = _pDocumentData->pJobInfo()->pDocument;
  979. pPSUIInfoHdr->Flags = PSUIHDRF_PROPTITLE;
  980. pPSUIInfoHdr->hWndParent = _pDocumentData->hwnd();
  981. pPSUIInfoHdr->hInst = ghInst;
  982. pPSUIInfoHdr->IconID = IDI_DOCUMENT;
  983. return TRUE;
  984. }
  985. BOOL
  986. TDocumentWindows::
  987. bValid(
  988. VOID
  989. )
  990. {
  991. return _General.bValid();
  992. }
  993. /********************************************************************
  994. Document properties UI (driver UI)
  995. ********************************************************************/
  996. TDocumentProperties::
  997. TDocumentProperties(
  998. IN HWND hwnd,
  999. IN HANDLE hPrinter,
  1000. IN LPCTSTR pszPrinter,
  1001. IN PDEVMODE pDevModeIn,
  1002. OUT PDEVMODE pDevModeOut,
  1003. IN DWORD dwHideBits,
  1004. IN DWORD dwFlags
  1005. ):
  1006. _hwnd(hwnd),
  1007. _hPrinter(hPrinter),
  1008. _pszPrinter(pszPrinter),
  1009. _pDevModeIn(pDevModeIn),
  1010. _pDevModeOut(pDevModeOut),
  1011. _dwHideBits(dwHideBits),
  1012. _dwFlags(dwFlags),
  1013. _lResult(-1)
  1014. {
  1015. // nothing
  1016. }
  1017. LONG
  1018. TDocumentProperties::
  1019. lGetResult(
  1020. VOID
  1021. ) const
  1022. {
  1023. return _lResult;
  1024. }
  1025. BOOL
  1026. TDocumentProperties::
  1027. bBuildPages(
  1028. IN PPROPSHEETUI_INFO pCPSUIInfo
  1029. )
  1030. {
  1031. BOOL bRet = FALSE;
  1032. if( bValid() )
  1033. {
  1034. //
  1035. // Set the default activation context to be V6 prior calling into
  1036. // compstui to create the pages. This will force V6 context unless
  1037. // the callbacks which create the compstui pages specify otherwise
  1038. // on a per page basis.
  1039. //
  1040. bRet = (BOOL)pCPSUIInfo->pfnComPropSheet(
  1041. pCPSUIInfo->hComPropSheet,
  1042. CPSFUNC_SET_FUSION_CONTEXT,
  1043. reinterpret_cast<LPARAM>(g_hActCtx),
  1044. static_cast<LPARAM>(0));
  1045. if( bRet )
  1046. {
  1047. ZeroMemory(&_dph, sizeof(_dph));
  1048. _dph.cbSize = sizeof(_dph);
  1049. _dph.hPrinter = _hPrinter;
  1050. _dph.pszPrinterName = const_cast<LPTSTR>(_pszPrinter);
  1051. _dph.pdmIn = _pDevModeIn;
  1052. _dph.pdmOut = _pDevModeOut;
  1053. _dph.fMode = _dwFlags;
  1054. if( _dwHideBits )
  1055. {
  1056. _lResult = pCPSUIInfo->pfnComPropSheet(pCPSUIInfo->hComPropSheet,
  1057. CPSFUNC_SET_DMPUB_HIDEBITS, static_cast<LPARAM>(_dwHideBits), 0);
  1058. }
  1059. else
  1060. {
  1061. //
  1062. // If no bit is hided, The result value should be valid.
  1063. //
  1064. _lResult = 1;
  1065. }
  1066. if( _lResult > 0 )
  1067. {
  1068. _lResult = pCPSUIInfo->pfnComPropSheet(pCPSUIInfo->hComPropSheet,
  1069. CPSFUNC_ADD_PFNPROPSHEETUI, reinterpret_cast<LPARAM>(DocumentPropertySheets),
  1070. reinterpret_cast<LPARAM>(&_dph));
  1071. }
  1072. }
  1073. }
  1074. return (_lResult > 0);
  1075. }
  1076. BOOL
  1077. TDocumentProperties::
  1078. bSetHeader(
  1079. IN PPROPSHEETUI_INFO pCPSUIInfo,
  1080. IN PPROPSHEETUI_INFO_HEADER pPSUInfoHeader
  1081. )
  1082. {
  1083. // construct the title & setup the header
  1084. UNREFERENCED_PARAMETER(pCPSUIInfo);
  1085. if( 0 == _strTitle.uLen() )
  1086. {
  1087. _strTitle.bLoadString(ghInst, IDS_PRINTER_PREFERENCES);
  1088. }
  1089. pPSUInfoHeader->pTitle = const_cast<LPTSTR>(static_cast<LPCTSTR>(_strTitle));
  1090. pPSUInfoHeader->Flags = PSUIHDRF_EXACT_PTITLE | PSUIHDRF_NOAPPLYNOW;
  1091. pPSUInfoHeader->hWndParent = _hwnd;
  1092. pPSUInfoHeader->hInst = ghInst;
  1093. pPSUInfoHeader->IconID = IDI_PRINTER;
  1094. return TRUE;
  1095. }
  1096. // table to remap the devmode field selections to DMPUB_* ids.
  1097. static DWORD arrDmFlagMap[] =
  1098. {
  1099. DM_ORIENTATION, MAKE_DMPUB_HIDEBIT( DMPUB_ORIENTATION ),
  1100. DM_PAPERSIZE , MAKE_DMPUB_HIDEBIT( 0 ),
  1101. DM_PAPERLENGTH, MAKE_DMPUB_HIDEBIT( 0 ),
  1102. DM_PAPERWIDTH , MAKE_DMPUB_HIDEBIT( 0 ),
  1103. DM_SCALE , MAKE_DMPUB_HIDEBIT( DMPUB_SCALE ),
  1104. DM_COPIES , MAKE_DMPUB_HIDEBIT( DMPUB_COPIES_COLLATE ),
  1105. DM_DEFAULTSOURCE, MAKE_DMPUB_HIDEBIT( DMPUB_DEFSOURCE ),
  1106. DM_PRINTQUALITY, MAKE_DMPUB_HIDEBIT( DMPUB_PRINTQUALITY ),
  1107. DM_COLOR , MAKE_DMPUB_HIDEBIT( DMPUB_COLOR ),
  1108. DM_DUPLEX , MAKE_DMPUB_HIDEBIT( DMPUB_DUPLEX ),
  1109. DM_YRESOLUTION, MAKE_DMPUB_HIDEBIT( 0 ),
  1110. DM_TTOPTION , MAKE_DMPUB_HIDEBIT( DMPUB_TTOPTION ),
  1111. DM_COLLATE , MAKE_DMPUB_HIDEBIT( DMPUB_COPIES_COLLATE ),
  1112. DM_FORMNAME , MAKE_DMPUB_HIDEBIT( DMPUB_FORMNAME ),
  1113. DM_LOGPIXELS , MAKE_DMPUB_HIDEBIT( 0 ),
  1114. DM_BITSPERPEL , MAKE_DMPUB_HIDEBIT( 0 ),
  1115. DM_PELSWIDTH , MAKE_DMPUB_HIDEBIT( 0 ),
  1116. DM_PELSHEIGHT , MAKE_DMPUB_HIDEBIT( 0 ),
  1117. DM_DISPLAYFLAGS, MAKE_DMPUB_HIDEBIT( 0 ),
  1118. DM_DISPLAYFREQUENCY, MAKE_DMPUB_HIDEBIT( 0 ),
  1119. DM_ICMMETHOD , MAKE_DMPUB_HIDEBIT( DMPUB_ICMMETHOD ),
  1120. DM_ICMINTENT , MAKE_DMPUB_HIDEBIT( DMPUB_ICMINTENT ),
  1121. DM_MEDIATYPE , MAKE_DMPUB_HIDEBIT( DMPUB_MEDIATYPE ),
  1122. DM_DITHERTYPE , MAKE_DMPUB_HIDEBIT( DMPUB_DITHERTYPE ),
  1123. DM_PANNINGWIDTH, MAKE_DMPUB_HIDEBIT( 0 ),
  1124. DM_PANNINGHEIGHT, MAKE_DMPUB_HIDEBIT( 0 )
  1125. };
  1126. static DWORD
  1127. RemapExclusionFlags(DWORD fExclusionFlags)
  1128. {
  1129. // walk through to collect the exclusion bits from the table above.
  1130. DWORD dwFlags = 0;
  1131. for( UINT i = 0; i < ARRAYSIZE(arrDmFlagMap); i += 2 )
  1132. {
  1133. if( fExclusionFlags & arrDmFlagMap[i] )
  1134. {
  1135. dwFlags |= arrDmFlagMap[i+1];
  1136. }
  1137. }
  1138. return dwFlags;
  1139. }
  1140. LONG
  1141. DocumentPropertiesWrapNative(
  1142. HWND hwnd, // handle to parent window
  1143. HANDLE hPrinter, // handle to printer object
  1144. LPTSTR pDeviceName, // device name
  1145. PDEVMODE pDevModeOutput, // modified device mode
  1146. PDEVMODE pDevModeInput, // original device mode
  1147. DWORD fMode, // mode options
  1148. DWORD fExclusionFlags // exclusion flags
  1149. )
  1150. {
  1151. // lResult <= 0 means error, for more information see
  1152. // the description of DocumentProperties in SDK.
  1153. LONG lResult = (-1);
  1154. if( hPrinter && pDeviceName && pDevModeOutput && pDevModeInput )
  1155. {
  1156. if (fMode & DM_PROMPT)
  1157. {
  1158. // invoke compstui to show up the driver UI
  1159. TDocumentProperties props(hwnd, hPrinter, pDeviceName, pDevModeInput, pDevModeOutput,
  1160. RemapExclusionFlags(fExclusionFlags), fMode);
  1161. if( props.bDisplayPages(hwnd, &lResult) )
  1162. {
  1163. // convert the result to IDOK/IDCANCEL
  1164. lResult = (lResult == CPSUI_OK) ? IDOK : IDCANCEL;
  1165. }
  1166. else
  1167. {
  1168. // error occured.
  1169. lResult = (-1);
  1170. }
  1171. }
  1172. else
  1173. {
  1174. // this is no UI call - just invoke DocumentProperties.
  1175. lResult = DocumentProperties(hwnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
  1176. }
  1177. }
  1178. return lResult;
  1179. }
  1180. LONG
  1181. DocumentPropertiesWrapWOW64(
  1182. HWND hwnd, // handle to parent window
  1183. HANDLE hPrinter, // handle to printer object
  1184. LPTSTR pDeviceName, // device name
  1185. PDEVMODE pDevModeOutput, // modified device mode
  1186. PDEVMODE pDevModeInput, // original device mode
  1187. DWORD fMode, // mode options
  1188. DWORD fExclusionFlags // exclusion flags
  1189. )
  1190. {
  1191. CDllLoader dll(TEXT("winspool.drv"));
  1192. ptr_PrintUIDocumentPropertiesWrap pfnPrintUIDocumentPropertiesWrap =
  1193. (ptr_PrintUIDocumentPropertiesWrap )dll.GetProcAddress(ord_PrintUIDocumentPropertiesWrap);
  1194. LONG lResult = (-1);
  1195. if( pfnPrintUIDocumentPropertiesWrap )
  1196. {
  1197. lResult = pfnPrintUIDocumentPropertiesWrap(hwnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode, fExclusionFlags);
  1198. }
  1199. return lResult;
  1200. }
  1201. LONG
  1202. DocumentPropertiesWrap(
  1203. HWND hwnd, // handle to parent window
  1204. HANDLE hPrinter, // handle to printer object
  1205. LPTSTR pDeviceName, // device name
  1206. PDEVMODE pDevModeOutput, // modified device mode
  1207. PDEVMODE pDevModeInput, // original device mode
  1208. DWORD fMode, // mode options
  1209. DWORD fExclusionFlags // exclusion flags
  1210. )
  1211. {
  1212. // if running in WOW64 environment we need to call winspool.drv to remote the
  1213. // call into the surrogate 64bit process where the driver UI can be displayed.
  1214. LONG lResult = IsRunningWOW64() ?
  1215. DocumentPropertiesWrapWOW64(hwnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode, fExclusionFlags) :
  1216. DocumentPropertiesWrapNative(hwnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode, fExclusionFlags);
  1217. return lResult;
  1218. }