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.

1974 lines
58 KiB

  1. #include "pch.h"
  2. #pragma hdrstop
  3. #include <initguid.h>
  4. #include "winprtp.h"
  5. /*-----------------------------------------------------------------------------
  6. / Local functions / data
  7. /----------------------------------------------------------------------------*/
  8. static TCHAR c_szColor[] = TEXT("color");
  9. static TCHAR c_szDuplex[] = TEXT("duplex");
  10. static TCHAR c_szStaple[] = TEXT("stapling");
  11. static TCHAR c_szResolution[] = TEXT("resolution");
  12. static TCHAR c_szSpeed[] = TEXT("speed");
  13. static TCHAR c_szPaperSize[] = TEXT("size");
  14. static TCHAR c_szPrintPaperSize[] = TEXT("(printMediaReady=%s*)");
  15. static TCHAR c_szPrintResolution[] = TEXT("(printMaxResolutionSupported>=%s)");
  16. static TCHAR c_szPrintSpeed[] = TEXT("(printPagesPerMinute>=%d)");
  17. static TCHAR c_szLocationQuery[] = TEXT("(location=%s*)");
  18. static TCHAR c_szLocationQueryComplex[] = TEXT("(|(location=%s/*)(location=%s))");
  19. static TCHAR c_szBlank[] = TEXT("");
  20. static TCHAR c_szLocationTag[] = TEXT("Location");
  21. static TCHAR c_szDynamicTag[] = TEXT("$DynamicLocation$");
  22. static TCHAR c_szPrinterPolicy[] = TEXT("Software\\Policies\\Microsoft\\Windows NT\\Printers");
  23. static TCHAR c_szPhysicalLocationFeature[] = TEXT("PhysicalLocationSupport");
  24. static WCHAR c_szPrinterName[] = L"printerName";
  25. static WCHAR c_szServerName[] = L"serverName";
  26. static WCHAR c_szQueryPrefix[] = L"(uncName=*)(objectCategory=printQueue)";
  27. static WCHAR c_szPrintColor[] = L"(printColor=TRUE)";
  28. static WCHAR c_szPrintDuplex[] = L"(printDuplexSupported=TRUE)";
  29. static WCHAR c_szPrintStapling[] = L"(printStaplingSupported=TRUE)";
  30. static WCHAR c_szPrintModelProp[] = L"driverName";
  31. #define MAX_LOCATION_WAIT_TIME 30000
  32. #define MAX_LOCATION_MSG_WAIT_TIME 60000
  33. #define MAX_LOCATION MAX_PATH
  34. static LPWSTR c_szClassList[] =
  35. {
  36. L"printQueue",
  37. };
  38. static PAGECTRL ctrls1[] =
  39. {
  40. IDC_PRINTNAME, c_szPrinterName, FILTER_CONTAINS,
  41. IDC_PRINTMODEL, c_szPrintModelProp, FILTER_CONTAINS,
  42. };
  43. static COLUMNINFO columns[] =
  44. {
  45. 0, 0, IDS_CN, 0, c_szPrinterName,
  46. 0, 0, IDS_LOCATION, 0, c_szLocation,
  47. 0, 0, IDS_MODEL, 0, c_szPrintModelProp,
  48. 0, 0, IDS_SERVERNAME, 0, c_szServerName,
  49. 0, DEFAULT_WIDTH_DESCRIPTION, IDS_COMMENT, 0, c_szDescription,
  50. };
  51. static struct
  52. {
  53. INT idString;
  54. LPCTSTR szString;
  55. }
  56. Resolutions [] =
  57. {
  58. IDS_ANY, NULL,
  59. IDS_72, TEXT("72"),
  60. IDS_144, TEXT("144"),
  61. IDS_300, TEXT("300"),
  62. IDS_600, TEXT("600"),
  63. IDS_1200, TEXT("1200"),
  64. IDS_2400, TEXT("2400"),
  65. IDS_4800, TEXT("4800"),
  66. IDS_9600, TEXT("9600"),
  67. IDS_32000, TEXT("32000"),
  68. };
  69. #define IDH_NOHELP ((DWORD)-1) // Disables Help for a control
  70. static const DWORD aFormHelpIDs[]=
  71. {
  72. IDC_PRINTNAME, IDH_PRINTER_NAME,
  73. IDC_PRINTLOCATION, IDH_PRINTER_LOCATION,
  74. IDC_PRINTBROWSE, IDH_PRINTER_LOCATION,
  75. IDC_PRINTMODEL, IDH_PRINTER_MODEL,
  76. IDC_PRINTDUPLEX, IDH_DOUBLE_SIDED,
  77. IDC_PRINTSTAPLE, IDH_STAPLE,
  78. IDC_PRINTCOLOR, IDH_PRINT_COLOR,
  79. IDC_PRINTPAGESIZE, IDH_PAPER_SIZE,
  80. IDC_PRINTRES, IDH_RESOLUTION,
  81. IDC_PRINTRES_POSTFIX, IDH_RESOLUTION,
  82. IDC_PRINTSPEED, IDH_SPEED,
  83. IDC_PRINTSPEED_UPDN,IDH_SPEED,
  84. IDC_PRINTSPEED_POSTFIX, IDH_SPEED,
  85. IDC_SEPLINE, IDH_NOHELP,
  86. 0, 0,
  87. };
  88. /*-----------------------------------------------------------------------------
  89. / CPrintQueryPage class
  90. /----------------------------------------------------------------------------*/
  91. class CPrintQueryPage
  92. {
  93. public:
  94. CPrintQueryPage( HWND hwnd );
  95. ~CPrintQueryPage();
  96. HRESULT Initialize( HWND hwnd, BOOL bSynchronous );
  97. LPCTSTR GetSearchText( VOID );
  98. UINT AddRef( VOID );
  99. UINT Release( VOID );
  100. VOID TimerExpire();
  101. VOID EnableLocationEditText( HWND hwnd, BOOL bEnable );
  102. VOID LocationEditTextChanged( HWND hwnd );
  103. VOID BrowseForLocation( HWND hwnd );
  104. HRESULT PersistLocation(HWND hwnd, IPersistQuery* pPersistQuery, BOOL fRead);
  105. VOID OnInitDialog( HWND hwnd );
  106. private:
  107. CPrintQueryPage( CPrintQueryPage &rhs );
  108. CPrintQueryPage & operator=( CPrintQueryPage &rhs );
  109. VOID WaitForLocation( HWND hwnd );
  110. DWORD Discovery( VOID );
  111. VOID TimerCreate( VOID );
  112. VOID TimerRelease( VOID );
  113. VOID SetLocationText( HWND hCtrl, LPCTSTR pszString, BOOL fReadOnly, BOOL fIgnoreWorkingText );
  114. static DWORD WINAPI _PhysicalLocationThread( PVOID pVoid );
  115. IPhysicalLocation *m_pPhysicalLocation;
  116. LPTSTR m_pszPhysicalLocation;
  117. LONG m_cRef;
  118. HWND m_hCtrl;
  119. BOOL m_fThreadCreated;
  120. BOOL m_fComplete;
  121. BOOL m_fLocationEnableState;
  122. BOOL m_fLocationUserModified;
  123. BOOL m_bValid;
  124. HWND m_hwnd;
  125. UINT_PTR m_hTimer;
  126. HANDLE m_hComplete;
  127. LPTSTR m_pszWorkingText;
  128. };
  129. /*-----------------------------------------------------------------------------
  130. / CPrintQueryPage
  131. / ---------------------
  132. / Constructor, creates the IPhysicalLocation object. If we are returned
  133. / a good interface pointer indicates the class is valid.
  134. /
  135. / In:
  136. / None.
  137. /
  138. / Out:
  139. / Nothing.
  140. /----------------------------------------------------------------------------*/
  141. CPrintQueryPage::CPrintQueryPage( HWND hwnd )
  142. : m_pPhysicalLocation( NULL ),
  143. m_pszPhysicalLocation( NULL ),
  144. m_cRef( 1 ),
  145. m_hCtrl( NULL ),
  146. m_fThreadCreated( FALSE ),
  147. m_fComplete( FALSE ),
  148. m_hwnd( hwnd ),
  149. m_hTimer( NULL ),
  150. m_fLocationEnableState( TRUE ),
  151. m_fLocationUserModified( FALSE ),
  152. m_hComplete( NULL ),
  153. m_pszWorkingText( NULL ),
  154. m_bValid( FALSE )
  155. {
  156. TraceEnter(TRACE_FORMS, "CPrintQueryPage::CPrintQueryPage");
  157. //
  158. // The physical location feature can be disable using a group
  159. // policy setting. If the feature is disabled we will just
  160. // fail to aquire the physical location interface and continue
  161. // operation with out pre-populating the location edit control.
  162. //
  163. HRESULT hr = CoCreateInstance( CLSID_PrintUIShellExtension,
  164. 0,
  165. CLSCTX_INPROC_SERVER,
  166. IID_IPhysicalLocation,
  167. (VOID**)&m_pPhysicalLocation );
  168. if (SUCCEEDED( hr ))
  169. {
  170. //
  171. // Check if the physical location policy is enabled.
  172. //
  173. if (SUCCEEDED(m_pPhysicalLocation->ShowPhysicalLocationUI()))
  174. {
  175. TimerCreate();
  176. m_hComplete = CreateEvent( NULL, TRUE, FALSE, NULL );
  177. if (m_hComplete)
  178. {
  179. //
  180. // Attempt to fetch the working text from the resource file.
  181. //
  182. TCHAR szBuffer[MAX_PATH] = {0};
  183. if (LoadString(GLOBAL_HINSTANCE, IDS_PRINT_WORKING_TEXT, szBuffer, ARRAYSIZE(szBuffer)))
  184. {
  185. hr = LocalAllocString (&m_pszWorkingText, szBuffer);
  186. }
  187. else
  188. {
  189. TraceAssert(FALSE);
  190. }
  191. //
  192. // Indicate the class is in a valid state, i.e. usable.
  193. //
  194. m_bValid = TRUE;
  195. }
  196. }
  197. }
  198. TraceLeave();
  199. }
  200. /*-----------------------------------------------------------------------------
  201. / ~CPrintQueryPage
  202. / ---------------------
  203. / Destructor, release the IPhysicalLocation object and the location string.
  204. /
  205. / In:
  206. / None.
  207. /
  208. / Out:
  209. / Nothing.
  210. /----------------------------------------------------------------------------*/
  211. CPrintQueryPage::~CPrintQueryPage()
  212. {
  213. TraceEnter(TRACE_FORMS, "CPrintQueryPage::~CPrintQueryPage");
  214. if (m_pPhysicalLocation)
  215. {
  216. m_pPhysicalLocation->Release();
  217. }
  218. LocalFreeString(&m_pszPhysicalLocation);
  219. //
  220. // Only release the string if it was allocated and it is not the null string.
  221. //
  222. if (m_pszWorkingText && (m_pszWorkingText != c_szBlank))
  223. {
  224. LocalFreeString(&m_pszWorkingText);
  225. }
  226. TimerRelease();
  227. if (m_hComplete)
  228. {
  229. CloseHandle( m_hComplete );
  230. }
  231. TraceLeave();
  232. }
  233. /*-----------------------------------------------------------------------------
  234. / AddRef
  235. / ---------------------
  236. / Increases the reference count of this object. This is method is used to
  237. / control the life time of this class when a backgroud thread is used to fetch
  238. / the physical location string.
  239. /
  240. / In:
  241. / None.
  242. /
  243. / Out:
  244. / New object refrence count.
  245. /----------------------------------------------------------------------------*/
  246. UINT CPrintQueryPage::AddRef( VOID )
  247. {
  248. return InterlockedIncrement(&m_cRef);
  249. }
  250. /*-----------------------------------------------------------------------------
  251. / Release
  252. / ---------------------
  253. / Decreases the reference count of this object. This is method is used to
  254. / control the life time of this class when a backgroud thread is used to fetch
  255. / the physical location string.
  256. /
  257. / In:
  258. / None.
  259. /
  260. / Out:
  261. / New object refrence count.
  262. /----------------------------------------------------------------------------*/
  263. UINT CPrintQueryPage::Release (VOID)
  264. {
  265. if (!InterlockedDecrement(&m_cRef))
  266. {
  267. delete this;
  268. return 0;
  269. }
  270. return m_cRef;
  271. }
  272. /*-----------------------------------------------------------------------------
  273. / GetSearchText
  274. / ---------------------
  275. / Returns a pointer to the current search text. The search text is the
  276. / physical location path returned from the IPhysicalLocation object. If either
  277. / the search text does not exist or not found this routine will return a
  278. / NULL string.
  279. /
  280. / In:
  281. / None.
  282. /
  283. / Out:
  284. / Ponter to the search text or the NULL string.
  285. /----------------------------------------------------------------------------*/
  286. LPCTSTR CPrintQueryPage::GetSearchText( VOID )
  287. {
  288. return m_pszPhysicalLocation ? m_pszPhysicalLocation : c_szBlank;
  289. }
  290. /*-----------------------------------------------------------------------------
  291. / Initialize
  292. / ---------------------
  293. / Creates the background thread and calls the physical location discovery
  294. / method.
  295. /
  296. / In:
  297. / Edit control window handle where to place text when done.
  298. / bSynchronous flag TRUE use backgroud thread, FALSE call synchronously.
  299. /
  300. / Out:
  301. / HRESULT hr.
  302. /----------------------------------------------------------------------------*/
  303. HRESULT CPrintQueryPage::Initialize( HWND hwnd, BOOL bSynchronous )
  304. {
  305. TraceEnter(TRACE_FORMS, "CPrintQueryPage::Initialize");
  306. HRESULT hr = S_OK;
  307. DWORD dwThreadID = 0;
  308. HANDLE hThread = NULL;
  309. //
  310. // If we have a valid physical location interface and the thread was not created,
  311. // then create it now and call the discovery method.
  312. //
  313. if (m_bValid && !m_fThreadCreated)
  314. {
  315. //
  316. // Bump the objects refrence count, needed for the async thread.
  317. //
  318. AddRef();
  319. //
  320. // Save the window handle in the class so the background thread
  321. // knows what window to set the location text to.
  322. //
  323. m_hCtrl = hwnd;
  324. //
  325. // Increase this libraries object refcount, ole will not unload until
  326. // we hit zeor and DllCanUnloadNow returns true.
  327. //
  328. DllAddRef();
  329. //
  330. // Only create the thread once.
  331. //
  332. m_fThreadCreated = TRUE;
  333. //
  334. // If we are requested to do a synchronous call then just call the
  335. // thread proc directly.
  336. //
  337. if (bSynchronous)
  338. {
  339. hr = (_PhysicalLocationThread( this ) == ERROR_SUCCESS) ? S_OK : E_FAIL;
  340. }
  341. else
  342. {
  343. //
  344. // Create the background thread.
  345. //
  346. hThread = CreateThread( NULL,
  347. 0,
  348. reinterpret_cast<LPTHREAD_START_ROUTINE>(CPrintQueryPage::_PhysicalLocationThread),
  349. reinterpret_cast<LPVOID>( this ),
  350. 0,
  351. &dwThreadID);
  352. TraceAssert(hThread);
  353. //
  354. // If the thread failed creation clean up the dll refrence count
  355. // and the object refrence and the thread created flag.
  356. //
  357. if (!hThread)
  358. {
  359. m_fThreadCreated = FALSE;
  360. DllRelease();
  361. Release();
  362. hr = E_FAIL;
  363. }
  364. else
  365. {
  366. //
  367. // Thread is running just close the handle, we let the thread die
  368. // on its own normally.
  369. //
  370. CloseHandle(hThread);
  371. //
  372. // Indicate the request is pending.
  373. //
  374. hr = HRESULT_FROM_WIN32 (ERROR_IO_PENDING);
  375. }
  376. }
  377. }
  378. //
  379. // If we have a valid interface pointer and the background thread
  380. // has not completed then indicated the data is still pending.
  381. //
  382. else if(m_bValid && !m_fComplete)
  383. {
  384. //
  385. // Indicate the request is pending.
  386. //
  387. hr = HRESULT_FROM_WIN32 (ERROR_IO_PENDING);
  388. }
  389. //
  390. // If we failed with IO_PENDING then set the working text.
  391. //
  392. if (FAILED(hr) && HRESULT_CODE(hr) == ERROR_IO_PENDING)
  393. {
  394. //
  395. // Set the new location text.
  396. //
  397. SetLocationText (hwnd, m_pszWorkingText, TRUE, TRUE);
  398. PostMessage (m_hCtrl, EM_SETSEL, 0, 0);
  399. }
  400. TraceLeaveResult(hr);
  401. }
  402. /*-----------------------------------------------------------------------------
  403. / _PhysicalLocationThread
  404. / ---------------------
  405. / This routine is the backgroud thread thunk. It accepts the CPrintQueryPage
  406. / this pointer and then calles the actual discovery method. The purpose of
  407. / this routine is simple to capture the this pointer after the thread was
  408. / created and then invoke a method.
  409. /
  410. / In:
  411. / Pointer to PrintQueryPage class.
  412. /
  413. / Out:
  414. / TRUE success, FALSE error occurred.
  415. /----------------------------------------------------------------------------*/
  416. DWORD WINAPI CPrintQueryPage::_PhysicalLocationThread( PVOID pVoid )
  417. {
  418. DWORD dwRetval = ERROR_OUTOFMEMORY;
  419. if ( SUCCEEDED(CoInitialize(NULL)) )
  420. {
  421. //
  422. // Get a pointer to this class.
  423. //
  424. CPrintQueryPage *pPrintQueryPage = reinterpret_cast<CPrintQueryPage *>( pVoid );
  425. //
  426. // Invoke the location discovery process.
  427. //
  428. dwRetval = pPrintQueryPage->Discovery();
  429. //
  430. // Set the completion event, in case someone is waiting.
  431. //
  432. SetEvent(pPrintQueryPage->m_hComplete);
  433. //
  434. // Indicate the discovery process completed.
  435. //
  436. pPrintQueryPage->m_fComplete = TRUE;
  437. //
  438. // Release the timer
  439. //
  440. pPrintQueryPage->TimerRelease();
  441. //
  442. // Release the refrence to the PrintQueryPage class.
  443. //
  444. pPrintQueryPage->Release();
  445. //
  446. // COM no longer needed
  447. //
  448. CoUninitialize();
  449. }
  450. DllRelease();
  451. return dwRetval;
  452. }
  453. /*-----------------------------------------------------------------------------
  454. / Discovery
  455. / ---------
  456. / This routine is the backgroud thread discovery process. Since the act
  457. / of figuring out the physical location of this machin must hit the net
  458. / it can take a significant amount of time. Hence we do this in a separate
  459. / thread.
  460. /
  461. / In:
  462. / Nothing.
  463. /
  464. / Out:
  465. / TRUE success, FALSE error occurred.
  466. /----------------------------------------------------------------------------*/
  467. DWORD CPrintQueryPage::Discovery( VOID )
  468. {
  469. TraceEnter(TRACE_FORMS, "CPrintQueryPage::Discovery");
  470. //
  471. // Start the discovery process for finding the physical location search text
  472. // for this machine.
  473. //
  474. HRESULT hr = m_pPhysicalLocation->DiscoverPhysicalLocation();
  475. if (SUCCEEDED( hr ))
  476. {
  477. BSTR pbsPhysicalLocation = NULL;
  478. //
  479. // Get the physical location search text.
  480. //
  481. hr = m_pPhysicalLocation->GetSearchPhysicalLocation( &pbsPhysicalLocation );
  482. //
  483. // If the error indicates the length was returned then allocate the text buffer.
  484. //
  485. if (SUCCEEDED( hr ) && pbsPhysicalLocation)
  486. {
  487. //
  488. // Release the previous string if any.
  489. //
  490. if (m_pszPhysicalLocation)
  491. {
  492. LocalFreeString(&m_pszPhysicalLocation);
  493. }
  494. //
  495. // Convert the BSTR location string to a TSTR string.
  496. //
  497. hr = LocalAllocStringW2T( &m_pszPhysicalLocation, pbsPhysicalLocation );
  498. }
  499. //
  500. // Release the physical location string if it was allocated.
  501. //
  502. if( pbsPhysicalLocation )
  503. {
  504. SysFreeString( pbsPhysicalLocation );
  505. }
  506. }
  507. //
  508. // Set the new location text.
  509. //
  510. SetLocationText( m_hCtrl, GetSearchText(), FALSE, FALSE );
  511. TraceLeaveValue(SUCCEEDED( hr ) ? ERROR_SUCCESS : ERROR_OUTOFMEMORY);
  512. }
  513. /*-----------------------------------------------------------------------------
  514. / WaitForLocation
  515. / ---------------------
  516. / Wait for the printer location information.
  517. /
  518. / In:
  519. / hwnd parent window handle.
  520. /
  521. / Out:
  522. / BOOL TRUE if success, FALSE if error.
  523. /----------------------------------------------------------------------------*/
  524. VOID CPrintQueryPage::WaitForLocation( HWND hwnd )
  525. {
  526. TraceEnter(TRACE_FORMS, "CPrintQueryPage::WaitForLocation");
  527. //
  528. // Only wait if we have a valid location interface pointer and
  529. // completion event handle was created and the thread is running.
  530. //
  531. if (m_bValid && m_hComplete && m_fThreadCreated)
  532. {
  533. //
  534. // Keep waiting until the physical location is avaialble or a timeout.
  535. //
  536. for (BOOL fExit = FALSE; !fExit; )
  537. {
  538. switch (MsgWaitForMultipleObjects(1, &m_hComplete, FALSE, MAX_LOCATION_MSG_WAIT_TIME, QS_ALLINPUT))
  539. {
  540. case WAIT_OBJECT_0:
  541. fExit = TRUE;
  542. break;
  543. case WAIT_TIMEOUT:
  544. fExit = TRUE;
  545. break;
  546. default:
  547. {
  548. //
  549. // Process any message now.
  550. //
  551. MSG msg;
  552. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  553. {
  554. TranslateMessage(&msg);
  555. DispatchMessage(&msg);
  556. }
  557. break;
  558. }
  559. }
  560. }
  561. }
  562. TraceLeave();
  563. }
  564. /*-----------------------------------------------------------------------------
  565. / TimerCreate
  566. / ---------------------
  567. / Create the timer event to detect if the discovery method is taking too long.
  568. /
  569. / In:
  570. /
  571. / Out:
  572. /----------------------------------------------------------------------------*/
  573. VOID CPrintQueryPage::TimerCreate( VOID )
  574. {
  575. TraceEnter(TRACE_FORMS, "CPrintQueryPage::TimerCreate");
  576. if (!m_hTimer)
  577. {
  578. m_hTimer = SetTimer(m_hwnd, WM_USER, MAX_LOCATION_WAIT_TIME, NULL);
  579. }
  580. TraceLeave();
  581. }
  582. /*-----------------------------------------------------------------------------
  583. / TimerRelease
  584. / ---------------------
  585. / Release the timer event.
  586. /
  587. / In:
  588. /
  589. / Out:
  590. /----------------------------------------------------------------------------*/
  591. VOID CPrintQueryPage::TimerRelease( VOID )
  592. {
  593. TraceEnter(TRACE_FORMS, "CPrintQueryPage::TimerRelease");
  594. if (m_hTimer)
  595. {
  596. KillTimer(m_hwnd, m_hTimer);
  597. m_hTimer = NULL;
  598. }
  599. TraceLeave();
  600. }
  601. /*-----------------------------------------------------------------------------
  602. / TimerExpire
  603. / ---------------------
  604. /
  605. / In:
  606. /
  607. / Out:
  608. /----------------------------------------------------------------------------*/
  609. VOID CPrintQueryPage::TimerExpire( VOID )
  610. {
  611. TraceEnter(TRACE_FORMS, "CPrintQueryPage::TimerExpire");
  612. //
  613. // The search data is not complete
  614. //
  615. if (!m_fComplete)
  616. {
  617. //
  618. // Blank out the location text, it took too long to find.
  619. //
  620. SetLocationText(m_hCtrl, c_szBlank, FALSE, TRUE);
  621. //
  622. // Set the completion event, in case someone is waiting.
  623. //
  624. SetEvent(m_hComplete);
  625. //
  626. // Indicate the discovery process completed.
  627. //
  628. m_fComplete = TRUE;
  629. }
  630. //
  631. // Release the timer, the time is a one shot notification.
  632. //
  633. TimerRelease();
  634. TraceLeave();
  635. }
  636. /*-----------------------------------------------------------------------------
  637. / EnableLocationEditText
  638. / ---------------------
  639. / Enabled or disable the location edit text only if it is does not contain
  640. / the pending text.
  641. /
  642. / In:
  643. / hwnd parent window handle.
  644. /
  645. / Out:
  646. / BOOL TRUE if success, FALSE if error.
  647. /----------------------------------------------------------------------------*/
  648. VOID CPrintQueryPage::EnableLocationEditText( HWND hwnd, BOOL bEnable )
  649. {
  650. TraceEnter(TRACE_FORMS, "CPrintQueryPage::EnableLocationEditText");
  651. HWND hCtrl = GetDlgItem(hwnd, IDC_PRINTLOCATION);
  652. HWND hBrowseCtrl = GetDlgItem(hwnd, IDC_PRINTBROWSE);
  653. //
  654. // If the CPrintQueryPage is valid then handle the location
  655. // edit control differently.
  656. //
  657. if (m_bValid)
  658. {
  659. TCHAR szBuffer[MAX_LOCATION] = {0};
  660. //
  661. // Save the previous location enable state.
  662. //
  663. m_fLocationEnableState = bEnable;
  664. //
  665. // Get the current location text.
  666. //
  667. GetWindowText(hCtrl, szBuffer, ARRAYSIZE(szBuffer));
  668. //
  669. // Do not change the location edit control enable state when the
  670. // working text is there. The reason for this is the text
  671. // is hard to read when the control is disabled, but when the
  672. // control is just read only the text is black not gray hence
  673. // eaiser to read.
  674. //
  675. if (!_tcscmp(szBuffer, m_pszWorkingText))
  676. {
  677. //
  678. // For an unknown reason the control with the location
  679. // text has the input focus, the default input focus
  680. // should be on the printer name therefore I will
  681. // set the focus here.
  682. //
  683. SetFocus(GetDlgItem(hwnd, IDC_PRINTNAME));
  684. }
  685. else
  686. {
  687. EnableWindow(hBrowseCtrl, bEnable);
  688. EnableWindow(hCtrl, bEnable);
  689. }
  690. }
  691. else
  692. {
  693. EnableWindow(hBrowseCtrl, bEnable);
  694. EnableWindow(hCtrl, bEnable);
  695. }
  696. TraceLeave();
  697. }
  698. /*-----------------------------------------------------------------------------
  699. / LocationEditTextChanged
  700. / ---------------------
  701. /
  702. / In:
  703. / hwnd parent window handle.
  704. /
  705. / Out:
  706. / BOOL TRUE if success, FALSE if error.
  707. /----------------------------------------------------------------------------*/
  708. VOID CPrintQueryPage::LocationEditTextChanged( HWND hwnd )
  709. {
  710. TraceEnter(TRACE_FORMS, "CPrintQueryPage::LocationEditTextChanged");
  711. //
  712. // The search data is complete
  713. //
  714. if (m_fComplete)
  715. {
  716. m_fLocationUserModified = TRUE;
  717. }
  718. TraceLeave();
  719. }
  720. /*-----------------------------------------------------------------------------
  721. / PersistLocation
  722. / ---------------------
  723. /
  724. / In:
  725. / hwnd parent window handle.
  726. /
  727. / Out:
  728. / BOOL TRUE if success, FALSE if error.
  729. /----------------------------------------------------------------------------*/
  730. HRESULT CPrintQueryPage::PersistLocation(HWND hwnd, IPersistQuery* pPersistQuery, BOOL fRead)
  731. {
  732. TraceEnter(TRACE_FORMS, "CPrintQueryPage::PersistLocation");
  733. HRESULT hr = S_OK;
  734. TCHAR szBuffer[MAX_LOCATION] = {0};
  735. //
  736. // Get the control handle for the location edit control
  737. //
  738. HWND hCtrl = GetDlgItem(hwnd, IDC_PRINTLOCATION);
  739. //
  740. // Are we to read the persisted query string.
  741. //
  742. if (fRead)
  743. {
  744. //
  745. // Read the persisted location string.
  746. //
  747. hr = pPersistQuery->ReadString( c_szMsPrintersMore, c_szLocationTag, szBuffer, ARRAYSIZE( szBuffer ) );
  748. FailGracefully(hr, "Failed to read location state");
  749. //
  750. // Assume this is the exact string.
  751. //
  752. LPCTSTR pLocation = szBuffer;
  753. //
  754. // If the dynamic sentinal was found then wait for the dynamic location
  755. // text to be avaiable.
  756. //
  757. if (!_tcscmp(szBuffer, c_szDynamicTag))
  758. {
  759. WaitForLocation(hwnd);
  760. pLocation = GetSearchText();
  761. }
  762. //
  763. // Set the persisted location string in the query form.
  764. //
  765. SetLocationText(hCtrl, pLocation, FALSE, TRUE);
  766. }
  767. else
  768. {
  769. //
  770. // If the user modified the location text then save this text, otherwize
  771. // save a sentinal string which indicates we are to determine the location
  772. // dynamically when the persisted query is read back.
  773. //
  774. if (m_fLocationUserModified)
  775. {
  776. GetWindowText(hCtrl, szBuffer, ARRAYSIZE(szBuffer));
  777. hr = pPersistQuery->WriteString( c_szMsPrintersMore, c_szLocationTag, szBuffer );
  778. FailGracefully(hr, "Failed to write location state");
  779. }
  780. else
  781. {
  782. hr = pPersistQuery->WriteString( c_szMsPrintersMore, c_szLocationTag, c_szDynamicTag );
  783. FailGracefully(hr, "Failed to write location working state");
  784. }
  785. }
  786. exit_gracefully:
  787. TraceLeaveResult(hr);
  788. }
  789. /*-----------------------------------------------------------------------------
  790. / SetLocationText
  791. / ---------------------
  792. /
  793. / In:
  794. / hwnd parent window handle.
  795. /
  796. / Out:
  797. / BOOL TRUE if success, FALSE if error.
  798. /----------------------------------------------------------------------------*/
  799. VOID CPrintQueryPage::SetLocationText( HWND hCtrl, LPCTSTR pszString, BOOL fReadOnly, BOOL fIgnoreWorkingText )
  800. {
  801. TraceEnter(TRACE_FORMS, "CPrintQueryPage::SetLocationText");
  802. if (IsWindow(hCtrl))
  803. {
  804. //
  805. // Is the CPrintQueryPage in a valid state.
  806. //
  807. if (m_bValid)
  808. {
  809. TCHAR szBuffer[MAX_LOCATION];
  810. //
  811. // Read the current location text.
  812. //
  813. GetWindowText(hCtrl, szBuffer, ARRAYSIZE(szBuffer));
  814. //
  815. // Stick the location string in the edit control if it contains working.
  816. //
  817. if (!_tcscmp(szBuffer, m_pszWorkingText) || fIgnoreWorkingText)
  818. {
  819. SetWindowText(hCtrl, pszString);
  820. }
  821. //
  822. // Reset the control to non read only state.
  823. //
  824. SendMessage(hCtrl, EM_SETREADONLY, fReadOnly, 0);
  825. //
  826. // Enable the control if the read only is disabled.
  827. //
  828. if (!fReadOnly)
  829. {
  830. //
  831. // Enable the edit control.
  832. //
  833. EnableWindow(hCtrl, m_fLocationEnableState);
  834. }
  835. //
  836. // Only enable the browse button when we have a location string
  837. // and the then control is not in read only mode.
  838. //
  839. EnableWindow(GetDlgItem(m_hwnd, IDC_PRINTBROWSE), !fReadOnly && m_fLocationEnableState);
  840. }
  841. else
  842. {
  843. //
  844. // If we are not using the location interface, just set the location text.
  845. //
  846. SetWindowText(hCtrl, pszString);
  847. }
  848. }
  849. TraceLeave();
  850. }
  851. /*-----------------------------------------------------------------------------
  852. / BrowseForLocation
  853. / ---------------------
  854. / Starts the browse for location tree view and populates the edit control
  855. / with a valid selection.
  856. /
  857. / In:
  858. / hwnd parent window handle.
  859. /
  860. / Out:
  861. / Nothing.
  862. /----------------------------------------------------------------------------*/
  863. VOID CPrintQueryPage::BrowseForLocation( HWND hwnd )
  864. {
  865. TraceEnter(TRACE_FORMS, "CPrintQueryPage::BrowseForLocation");
  866. if (m_bValid)
  867. {
  868. BSTR pbPhysicalLocation = NULL;
  869. BSTR pbDefaultLocation = NULL;
  870. LPTSTR pszPhysicalLocation = NULL;
  871. HRESULT hr = E_FAIL;
  872. TCHAR szText[MAX_LOCATION]= {0};
  873. //
  874. // Convert the physical location to a BSTR for the IPhysicalLocation
  875. // object can pre-expand the browse tree.
  876. //
  877. if (GetWindowText(GetDlgItem(hwnd, IDC_PRINTLOCATION), szText, ARRAYSIZE(szText)))
  878. {
  879. pbDefaultLocation = T2BSTR(szText);
  880. }
  881. else
  882. {
  883. pbDefaultLocation = T2BSTR(m_pszPhysicalLocation);
  884. }
  885. //
  886. // Display the location tree.
  887. //
  888. hr = m_pPhysicalLocation->BrowseForLocation(hwnd, pbDefaultLocation, &pbPhysicalLocation);
  889. if(SUCCEEDED(hr) && pbPhysicalLocation)
  890. {
  891. //
  892. // Convert the BSTR location string to a TSTR string.
  893. //
  894. hr = LocalAllocStringW2T(&pszPhysicalLocation, pbPhysicalLocation);
  895. if(SUCCEEDED(hr))
  896. {
  897. //
  898. // Set the location text.
  899. //
  900. SetLocationText(m_hCtrl, pszPhysicalLocation, FALSE, TRUE);
  901. }
  902. //
  903. // Release the TCHAR physical location string.
  904. //
  905. LocalFreeString(&pszPhysicalLocation);
  906. //
  907. // Release the physical location string.
  908. //
  909. SysFreeString(pbPhysicalLocation);
  910. }
  911. //
  912. // Release the default locatin string.
  913. //
  914. SysFreeString(pbDefaultLocation);
  915. }
  916. TraceLeave();
  917. }
  918. /*-----------------------------------------------------------------------------
  919. / OnInitDialog
  920. / ---------------------
  921. / Set the UI's initial state, on down level machines the browse button is
  922. / removed and the edit control is stetched to match the size of the other
  923. / edit controls, i.e. name, model.
  924. /
  925. / In:
  926. / hwnd parent window handle.
  927. /
  928. / Out:
  929. / Nothing.
  930. /----------------------------------------------------------------------------*/
  931. VOID CPrintQueryPage::OnInitDialog( HWND hwnd )
  932. {
  933. TraceEnter(TRACE_FORMS, "CPrintQueryPage::OnInitDialog");
  934. if (!m_bValid)
  935. {
  936. //
  937. // If the IPhysicalLocation interface is not available, hide the browse
  938. // button and extend the location edit control appropriately
  939. //
  940. RECT rcName = {0};
  941. RECT rcLocation = {0};
  942. GetWindowRect (GetDlgItem (hwnd, IDC_PRINTNAME), &rcName);
  943. GetWindowRect (GetDlgItem (hwnd, IDC_PRINTLOCATION), &rcLocation);
  944. SetWindowPos (GetDlgItem (hwnd, IDC_PRINTLOCATION),
  945. NULL,
  946. 0,0,
  947. rcName.right - rcName.left,
  948. rcLocation.bottom - rcLocation.top,
  949. SWP_NOMOVE|SWP_NOZORDER);
  950. ShowWindow (GetDlgItem (hwnd, IDC_PRINTBROWSE), SW_HIDE);
  951. }
  952. TraceLeave();
  953. }
  954. /*-----------------------------------------------------------------------------
  955. / PopulateLocationEditText
  956. / ---------------------
  957. / Populates the location edit control with the default location of this
  958. / machine.
  959. /
  960. / In:
  961. / hwnd parent window handle.
  962. /
  963. / Out:
  964. / BOOL TRUE if success, FALSE if error.
  965. /----------------------------------------------------------------------------*/
  966. BOOL PopulateLocationEditText( HWND hwnd, BOOL bClearField )
  967. {
  968. TraceEnter(TRACE_FORMS, "PopulateLocationEditText");
  969. CPrintQueryPage *pPrintQueryPage = reinterpret_cast<CPrintQueryPage *>(GetWindowLongPtr(hwnd, DWLP_USER));
  970. if (pPrintQueryPage)
  971. {
  972. HWND hCtrl = GetDlgItem(hwnd, IDC_PRINTLOCATION);
  973. HRESULT hr = pPrintQueryPage->Initialize( hCtrl, FALSE );
  974. if (SUCCEEDED( hr ))
  975. {
  976. if( bClearField )
  977. {
  978. SetWindowText( hCtrl, c_szBlank);
  979. }
  980. else
  981. {
  982. SetWindowText( hCtrl, pPrintQueryPage->GetSearchText( ));
  983. }
  984. }
  985. }
  986. TraceLeaveValue(TRUE);
  987. }
  988. /*-----------------------------------------------------------------------------
  989. / bEnumForms
  990. / ----------
  991. / Enumerates the forms on the printer identified by the handle.
  992. /
  993. / In:
  994. / IN HANDLE hPrinter,
  995. / IN DWORD dwLevel,
  996. / IN PBYTE *ppBuff,
  997. / IN PDWORD pcReturned
  998. /
  999. / Out:
  1000. / Pointer to forms array and count of forms in the array if
  1001. / success, NULL ponter and zero number of forms if failure.
  1002. / BOOL TRUE if success, FALSE if error.
  1003. /----------------------------------------------------------------------------*/
  1004. BOOL
  1005. bEnumForms(
  1006. IN HANDLE hPrinter,
  1007. IN DWORD dwLevel,
  1008. IN PFORM_INFO_1 *ppFormInfo,
  1009. IN PDWORD pcReturned
  1010. )
  1011. {
  1012. BOOL bReturn = FALSE;
  1013. DWORD dwReturned = 0;
  1014. DWORD dwNeeded = 0;
  1015. PBYTE p = NULL;
  1016. BOOL bStatus = FALSE;
  1017. //
  1018. // Get buffer size for enum forms.
  1019. //
  1020. bStatus = EnumForms( hPrinter, dwLevel, NULL, 0, &dwNeeded, &dwReturned );
  1021. //
  1022. // Check if the function returned the buffer size.
  1023. //
  1024. if( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  1025. {
  1026. goto Cleanup;
  1027. }
  1028. //
  1029. // If buffer allocation fails.
  1030. //
  1031. p = (PBYTE)LocalAlloc( LPTR, dwNeeded );
  1032. if( p == NULL )
  1033. {
  1034. goto Cleanup;
  1035. }
  1036. //
  1037. // Get the forms enumeration
  1038. //
  1039. bStatus = EnumForms( hPrinter, dwLevel, p, dwNeeded, &dwNeeded, &dwReturned );
  1040. //
  1041. // Copy back the buffer pointer and count.
  1042. //
  1043. if( bStatus )
  1044. {
  1045. bReturn = TRUE;
  1046. *ppFormInfo = (PFORM_INFO_1)p;
  1047. *pcReturned = dwReturned;
  1048. }
  1049. Cleanup:
  1050. if( bReturn == FALSE )
  1051. {
  1052. //
  1053. // Indicate failure.
  1054. //
  1055. *ppFormInfo = NULL;
  1056. *pcReturned = 0;
  1057. //
  1058. // Release any allocated memory.
  1059. //
  1060. if ( p )
  1061. {
  1062. LocalFree( p );
  1063. }
  1064. }
  1065. return bReturn;
  1066. }
  1067. /*-----------------------------------------------------------------------------
  1068. / PopulatePrintPageSize
  1069. / ----------------
  1070. / Eumerates all the pages size from this machine's print spooler. This allows
  1071. / a user to choose from a list of available forms rather than remembering the
  1072. / name of the particular form.
  1073. /
  1074. / In:
  1075. / hwnd parent window handle.
  1076. /
  1077. / Out:
  1078. / BOOL TRUE if success, FALSE if error.
  1079. /----------------------------------------------------------------------------*/
  1080. BOOL PopulatePrintPageSize( HWND hwnd )
  1081. {
  1082. HANDLE hServer = NULL;
  1083. PFORM_INFO_1 pFormInfo = NULL;
  1084. DWORD FormCount = 0;
  1085. BOOL bRetval = FALSE;
  1086. TCHAR szBuffer[MAX_PATH];
  1087. //
  1088. // Open the local print server with default access.
  1089. //
  1090. BOOL bStatus = OpenPrinter( NULL, &hServer, NULL );
  1091. if( bStatus )
  1092. {
  1093. //
  1094. // Enumerate the forms.
  1095. //
  1096. bStatus = bEnumForms( hServer, 1, &pFormInfo, &FormCount );
  1097. }
  1098. if( bStatus && pFormInfo )
  1099. {
  1100. //
  1101. // Fill the combo box.
  1102. //
  1103. for( UINT i = 0; i < FormCount; i++ )
  1104. {
  1105. ComboBox_AddString( GetDlgItem( hwnd, IDC_PRINTPAGESIZE ), pFormInfo[i].pName );
  1106. }
  1107. //
  1108. // Set the limit text in the form name edit control
  1109. //
  1110. ComboBox_LimitText( GetDlgItem( hwnd, IDC_PRINTPAGESIZE ), CCHFORMNAME-1 );
  1111. //
  1112. // Return success.
  1113. //
  1114. bRetval = TRUE;
  1115. }
  1116. if( pFormInfo )
  1117. {
  1118. //
  1119. // Release the forms buffer if it was allocated.
  1120. //
  1121. LocalFree( pFormInfo );
  1122. }
  1123. if ( hServer )
  1124. {
  1125. ClosePrinter(hServer);
  1126. }
  1127. return bRetval;
  1128. }
  1129. /*-----------------------------------------------------------------------------
  1130. / PopulatePrintSpeed
  1131. / ----------------
  1132. / Set the print speed up down arrow control with an upper and lower
  1133. / bound range.
  1134. /
  1135. / In:
  1136. / hwnd parent window handle
  1137. /
  1138. / Out:
  1139. / BOOL TRUE if success, FALSE if error.
  1140. /----------------------------------------------------------------------------*/
  1141. BOOL PopulatePrintSpeed( HWND hwnd )
  1142. {
  1143. //
  1144. // Set the print speed up down arrow range.
  1145. //
  1146. SendMessage( GetDlgItem( hwnd, IDC_PRINTSPEED_UPDN ), UDM_SETRANGE, 0, MAKELPARAM( 9999, 1 ) );
  1147. Edit_LimitText(GetDlgItem(hwnd, IDC_PRINTSPEED), 4);
  1148. return TRUE;
  1149. }
  1150. /*-----------------------------------------------------------------------------
  1151. / PopulateResolution
  1152. / ----------------
  1153. / Fill the print resolution contrl with valid resolution information.
  1154. /
  1155. / In:
  1156. / hwnd
  1157. /
  1158. / Out:
  1159. / BOOL TRUE if success, FALSE if error.
  1160. /----------------------------------------------------------------------------*/
  1161. BOOL PopulatePrintResolution( HWND hwnd )
  1162. {
  1163. TCHAR szBuffer[MAX_PATH];
  1164. //
  1165. // Fill in the print resolution combo-box.
  1166. //
  1167. for( INT i = 0; i < ARRAYSIZE( Resolutions ); i++ )
  1168. {
  1169. if( !LoadString(GLOBAL_HINSTANCE, Resolutions[i].idString, szBuffer, ARRAYSIZE(szBuffer)))
  1170. {
  1171. TraceAssert(FALSE);
  1172. }
  1173. ComboBox_AddString( GetDlgItem( hwnd, IDC_PRINTRES ), szBuffer );
  1174. }
  1175. return TRUE;
  1176. }
  1177. /*-----------------------------------------------------------------------------
  1178. / GetPrinterMoreParameters.
  1179. / ----------------
  1180. / Build the query string from the controls on the printer more page.
  1181. /
  1182. / In:
  1183. / hwnd parent window handle.
  1184. / pLen pointer to length of query string.
  1185. / pszBuffer pointer to buffer where to return the query string.
  1186. /
  1187. / Out:
  1188. / Nothing.
  1189. /----------------------------------------------------------------------------*/
  1190. VOID GetPrinterMoreParameters( HWND hwnd, UINT *puLen, LPWSTR pszBuffer )
  1191. {
  1192. USES_CONVERSION;
  1193. TCHAR szScratch[MAX_PATH] = {0};
  1194. TCHAR szText[MAX_PATH] = {0};
  1195. INT i = 0;
  1196. //
  1197. // Read the check box states and build the query string.
  1198. //
  1199. if( Button_GetCheck( GetDlgItem( hwnd, IDC_PRINTDUPLEX ) ) == BST_CHECKED )
  1200. PutStringElementW(pszBuffer, puLen, c_szPrintDuplex);
  1201. if( Button_GetCheck( GetDlgItem( hwnd, IDC_PRINTCOLOR ) ) == BST_CHECKED )
  1202. PutStringElementW(pszBuffer, puLen, c_szPrintColor);
  1203. if( Button_GetCheck( GetDlgItem( hwnd, IDC_PRINTSTAPLE ) ) == BST_CHECKED )
  1204. PutStringElementW(pszBuffer, puLen, c_szPrintStapling);
  1205. //
  1206. // Read the paper size setting.
  1207. //
  1208. ComboBox_GetText( GetDlgItem( hwnd, IDC_PRINTPAGESIZE ), szText, ARRAYSIZE( szText ) );
  1209. if( lstrlen( szText ) )
  1210. {
  1211. wsprintf( szScratch, c_szPrintPaperSize, szText );
  1212. PutStringElementW(pszBuffer, puLen, T2W(szScratch));
  1213. }
  1214. //
  1215. // Read the printer resolution setting
  1216. //
  1217. i = ComboBox_GetCurSel( GetDlgItem( hwnd, IDC_PRINTRES ) );
  1218. if( i > 0 && i < ARRAYSIZE( Resolutions ) )
  1219. {
  1220. wsprintf( szScratch, c_szPrintResolution, Resolutions[i].szString );
  1221. PutStringElementW(pszBuffer, puLen, T2W(szScratch));
  1222. }
  1223. //
  1224. // Read the printer speed setting
  1225. //
  1226. i = (LONG)SendMessage( GetDlgItem( hwnd, IDC_PRINTSPEED_UPDN ), UDM_GETPOS, 0, 0 );
  1227. if( LOWORD(i) > 1 && i != -1 )
  1228. {
  1229. wsprintf( szScratch, c_szPrintSpeed, i );
  1230. PutStringElementW(pszBuffer, puLen, T2W(szScratch));
  1231. }
  1232. }
  1233. /*-----------------------------------------------------------------------------
  1234. / GetPrinterLocationParameter.
  1235. / ----------------
  1236. / Build the query string from the location control on the printer page.
  1237. /
  1238. / In:
  1239. / hwnd parent window handle.
  1240. / pLen pointer to length of query string.
  1241. / pszBuffer pointer to buffer where to return the query string.
  1242. /
  1243. / Out:
  1244. / Nothing.
  1245. /----------------------------------------------------------------------------*/
  1246. VOID GetPrinterLocationParameter( HWND hwnd, UINT *puLen, LPWSTR pszBuffer )
  1247. {
  1248. USES_CONVERSION;
  1249. TCHAR szScratch[MAX_PATH*2] = {0};
  1250. TCHAR szText[MAX_PATH] = {0};
  1251. TCHAR szWorkingText[MAX_PATH] = {0};
  1252. DWORD dwLocationLength = 0;
  1253. HWND hCtrl = GetDlgItem(hwnd, IDC_PRINTLOCATION);
  1254. if ( hCtrl != NULL )
  1255. {
  1256. dwLocationLength = GetWindowText(hCtrl, szText, ARRAYSIZE(szText));
  1257. if (dwLocationLength != 0)
  1258. {
  1259. if (LoadString(GLOBAL_HINSTANCE, IDS_PRINT_WORKING_TEXT, szWorkingText, ARRAYSIZE(szWorkingText)))
  1260. {
  1261. if (_tcscmp(szText, szWorkingText))
  1262. {
  1263. BOOL fUseMoreComplexSearch = FALSE;
  1264. //
  1265. // If we have a location that ends in a forward slash,
  1266. // we'll trim that off and use a slightly more complex
  1267. // search parameter so that we can pick up locations
  1268. // that either match the location parameter exactly or
  1269. // start with the parameter and have a slash immediately
  1270. // following.
  1271. //
  1272. if ( dwLocationLength > 1 )
  1273. {
  1274. if ( szText[dwLocationLength-1] == TEXT('/') )
  1275. {
  1276. szText[dwLocationLength-1] = TEXT('\0');
  1277. fUseMoreComplexSearch = TRUE;
  1278. }
  1279. }
  1280. if ( fUseMoreComplexSearch )
  1281. {
  1282. wsprintf(szScratch, c_szLocationQueryComplex, szText, szText);
  1283. }
  1284. else
  1285. {
  1286. wsprintf(szScratch, c_szLocationQuery, szText);
  1287. }
  1288. PutStringElementW(pszBuffer, puLen, T2W(szScratch));
  1289. }
  1290. else
  1291. {
  1292. //
  1293. // We are not going to wait the location field if the search process
  1294. // has been kicked off. Just hit the expire timer to cancel the location
  1295. // thread. This will ensure that the result list and the query params
  1296. // will be consistent.
  1297. //
  1298. CPrintQueryPage *pPrintQueryPage = reinterpret_cast<CPrintQueryPage *>(GetWindowLongPtr(hwnd, DWLP_USER));
  1299. if (pPrintQueryPage)
  1300. {
  1301. pPrintQueryPage->TimerExpire();
  1302. }
  1303. }
  1304. }
  1305. else
  1306. {
  1307. TraceAssert(FALSE);
  1308. }
  1309. }
  1310. }
  1311. else
  1312. {
  1313. // GetDlgItem() returned NULL for the location control.
  1314. TraceAssert(FALSE);
  1315. }
  1316. }
  1317. /*-----------------------------------------------------------------------------
  1318. / Query Page: Printers
  1319. /----------------------------------------------------------------------------*/
  1320. /*-----------------------------------------------------------------------------
  1321. / PageProc_Printer
  1322. / ----------------
  1323. / PageProc for handling the messages for this object.
  1324. /
  1325. / In:
  1326. / pPage -> instance data for this form
  1327. / hwnd = window handle for the form dialog
  1328. / uMsg, wParam, lParam = message parameters
  1329. /
  1330. / Out:
  1331. / HRESULT (E_NOTIMPL) if not handled
  1332. /----------------------------------------------------------------------------*/
  1333. HRESULT CALLBACK PageProc_Printers(LPCQPAGE pPage, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1334. {
  1335. HRESULT hr = S_OK;
  1336. LPWSTR pQuery = NULL;
  1337. UINT uLen = 0;
  1338. TraceEnter(TRACE_FORMS, "PageProc_Printers");
  1339. switch ( uMsg )
  1340. {
  1341. case CQPM_INITIALIZE:
  1342. case CQPM_RELEASE:
  1343. break;
  1344. case CQPM_ENABLE:
  1345. {
  1346. CPrintQueryPage *pPrintQueryPage = reinterpret_cast<CPrintQueryPage *>(GetWindowLongPtr(hwnd, DWLP_USER));
  1347. if (pPrintQueryPage)
  1348. {
  1349. pPrintQueryPage->EnableLocationEditText( hwnd, (BOOL)wParam );
  1350. }
  1351. // Enable the form controls,
  1352. EnablePageControls(hwnd, ctrls1, ARRAYSIZE(ctrls1), (BOOL)wParam);
  1353. break;
  1354. }
  1355. case CQPM_GETPARAMETERS:
  1356. {
  1357. //
  1358. // Get the printer name and model paramters.
  1359. //
  1360. hr = GetQueryString(&pQuery, c_szQueryPrefix, hwnd, ctrls1, ARRAYSIZE(ctrls1));
  1361. if ( SUCCEEDED(hr) )
  1362. {
  1363. hr = QueryParamsAlloc((LPDSQUERYPARAMS*)lParam, pQuery, GLOBAL_HINSTANCE, ARRAYSIZE(columns), columns);
  1364. LocalFreeStringW(&pQuery);
  1365. }
  1366. //
  1367. // Get the location parameter.
  1368. //
  1369. GetPrinterLocationParameter( hwnd, &uLen, NULL );
  1370. if (uLen)
  1371. {
  1372. hr = LocalAllocStringLenW(&pQuery, uLen);
  1373. if ( SUCCEEDED(hr) )
  1374. {
  1375. GetPrinterLocationParameter( hwnd, &uLen, pQuery );
  1376. hr = QueryParamsAddQueryString((LPDSQUERYPARAMS*)lParam, pQuery );
  1377. LocalFreeStringW(&pQuery);
  1378. }
  1379. }
  1380. FailGracefully(hr, "PageProc_Printers: Failed to build DS argument block");
  1381. break;
  1382. }
  1383. case CQPM_CLEARFORM:
  1384. {
  1385. // Reset the form controls.
  1386. PopulateLocationEditText( hwnd, TRUE );
  1387. ResetPageControls(hwnd, ctrls1, ARRAYSIZE(ctrls1));
  1388. break;
  1389. }
  1390. case CQPM_PERSIST:
  1391. {
  1392. BOOL fRead = (BOOL)wParam;
  1393. IPersistQuery* pPersistQuery = (IPersistQuery*)lParam;
  1394. CPrintQueryPage *pPrintQueryPage = reinterpret_cast<CPrintQueryPage *>(GetWindowLongPtr(hwnd, DWLP_USER));
  1395. if (pPrintQueryPage)
  1396. {
  1397. hr = pPrintQueryPage->PersistLocation(hwnd, pPersistQuery, fRead);
  1398. }
  1399. if (SUCCEEDED(hr))
  1400. {
  1401. // Read the standard controls from the page,
  1402. hr = PersistQuery(pPersistQuery, fRead, c_szMsPrinters, hwnd, ctrls1, ARRAYSIZE(ctrls1));
  1403. }
  1404. FailGracefully(hr, "Failed to persist page");
  1405. break;
  1406. }
  1407. case CQPM_SETDEFAULTPARAMETERS:
  1408. {
  1409. //
  1410. // so that the caller can pass parameters to the form we support an IPropertyBag in the
  1411. // OPENQUERYWINDOW structure. If wParam == TRUE, and lParam is non-zero then we
  1412. // assume we should decode this structure to get the information we need from it.
  1413. //
  1414. if ( wParam && lParam )
  1415. {
  1416. OPENQUERYWINDOW *poqw = (OPENQUERYWINDOW*)lParam;
  1417. if ( poqw->dwFlags & OQWF_PARAMISPROPERTYBAG )
  1418. {
  1419. IPropertyBag *ppb = poqw->ppbFormParameters;
  1420. SetDlgItemFromProperty(ppb, L"printName", hwnd, IDC_PRINTNAME, NULL);
  1421. SetDlgItemFromProperty(ppb, L"printLocation", hwnd, IDC_PRINTLOCATION, NULL);
  1422. SetDlgItemFromProperty(ppb, L"printModel", hwnd, IDC_PRINTMODEL, NULL);
  1423. }
  1424. }
  1425. break;
  1426. }
  1427. case CQPM_HELP:
  1428. {
  1429. LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
  1430. WinHelp((HWND)pHelpInfo->hItemHandle,
  1431. DSQUERY_HELPFILE,
  1432. HELP_WM_HELP,
  1433. (DWORD_PTR)aFormHelpIDs);
  1434. break;
  1435. }
  1436. case DSQPM_GETCLASSLIST:
  1437. {
  1438. hr = ClassListAlloc((LPDSQUERYCLASSLIST*)lParam, c_szClassList, ARRAYSIZE(c_szClassList));
  1439. FailGracefully(hr, "Failed to allocate class list");
  1440. break;
  1441. }
  1442. case DSQPM_HELPTOPICS:
  1443. {
  1444. HWND hwndFrame = (HWND)lParam;
  1445. TraceMsg("About to display help topics for find printers - ocm.chm");
  1446. HtmlHelp(hwndFrame, TEXT("omc.chm"), HH_HELP_FINDER, 0);
  1447. break;
  1448. }
  1449. default:
  1450. hr = E_NOTIMPL;
  1451. break;
  1452. }
  1453. exit_gracefully:
  1454. TraceLeaveResult(hr);
  1455. }
  1456. /*-----------------------------------------------------------------------------
  1457. / DlgProc_Printers
  1458. / ----------------
  1459. / Standard dialog proc for the form, handle any special buttons and other
  1460. / such nastyness we must here.
  1461. /
  1462. / In:
  1463. / hwnd, uMsg, wParam, lParam = standard parameters
  1464. /
  1465. / Out:
  1466. / BOOL
  1467. /----------------------------------------------------------------------------*/
  1468. INT_PTR CALLBACK DlgProc_Printers(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1469. {
  1470. INT_PTR fResult = TRUE;
  1471. CPrintQueryPage *pPrintQueryPage = reinterpret_cast<CPrintQueryPage *>(GetWindowLongPtr(hwnd, DWLP_USER));
  1472. switch ( uMsg )
  1473. {
  1474. case WM_INITDIALOG:
  1475. {
  1476. Edit_LimitText(GetDlgItem(hwnd, IDC_PRINTNAME), MAX_PATH-1);
  1477. Edit_LimitText(GetDlgItem(hwnd, IDC_PRINTLOCATION), MAX_LOCATION-1);
  1478. Edit_LimitText(GetDlgItem(hwnd, IDC_PRINTMODEL), MAX_PATH-1);
  1479. pPrintQueryPage = new CPrintQueryPage(hwnd);
  1480. if (pPrintQueryPage)
  1481. {
  1482. SetWindowLongPtr(hwnd, DWLP_USER, reinterpret_cast<LONG_PTR>(pPrintQueryPage));
  1483. pPrintQueryPage->OnInitDialog(hwnd);
  1484. PopulateLocationEditText(hwnd, FALSE);
  1485. }
  1486. else
  1487. {
  1488. fResult = FALSE;
  1489. }
  1490. break;
  1491. }
  1492. case WM_CONTEXTMENU:
  1493. {
  1494. WinHelp((HWND)wParam, DSQUERY_HELPFILE, HELP_CONTEXTMENU, (DWORD_PTR)aFormHelpIDs);
  1495. break;
  1496. }
  1497. case WM_NCDESTROY:
  1498. {
  1499. if (pPrintQueryPage)
  1500. {
  1501. pPrintQueryPage->Release();
  1502. }
  1503. SetWindowLongPtr(hwnd, DWLP_USER, NULL);
  1504. break;
  1505. }
  1506. case WM_TIMER:
  1507. {
  1508. if (pPrintQueryPage)
  1509. {
  1510. pPrintQueryPage->TimerExpire();
  1511. }
  1512. break;
  1513. }
  1514. case WM_COMMAND:
  1515. {
  1516. if((GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) &&
  1517. (GET_WM_COMMAND_ID(wParam, lParam) == IDC_PRINTLOCATION))
  1518. {
  1519. if (pPrintQueryPage)
  1520. {
  1521. pPrintQueryPage->LocationEditTextChanged(hwnd);
  1522. }
  1523. }
  1524. else if((GET_WM_COMMAND_ID(wParam, lParam) == IDC_PRINTBROWSE))
  1525. {
  1526. if (pPrintQueryPage)
  1527. {
  1528. pPrintQueryPage->BrowseForLocation(hwnd);
  1529. }
  1530. }
  1531. else
  1532. {
  1533. fResult = FALSE;
  1534. }
  1535. break;
  1536. }
  1537. default:
  1538. {
  1539. fResult = FALSE;
  1540. break;
  1541. }
  1542. }
  1543. return fResult;
  1544. }
  1545. /*-----------------------------------------------------------------------------
  1546. / PageProc_PrintersMore
  1547. / ---------------------
  1548. / PageProc for handling the messages for this object.
  1549. /
  1550. / In:
  1551. / pPage -> instance data for this form
  1552. / hwnd = window handle for the form dialog
  1553. / uMsg, wParam, lParam = message parameters
  1554. /
  1555. / Out:
  1556. / HRESULT (E_NOTIMPL) if not handled
  1557. /----------------------------------------------------------------------------*/
  1558. HRESULT CALLBACK PageProc_PrintersMore(LPCQPAGE pPage, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1559. {
  1560. HRESULT hr = S_OK;
  1561. TraceEnter(TRACE_FORMS, "PageProc_PrintersMore");
  1562. switch ( uMsg )
  1563. {
  1564. case CQPM_INITIALIZE:
  1565. case CQPM_RELEASE:
  1566. break;
  1567. case CQPM_ENABLE:
  1568. EnableWindow( GetDlgItem( hwnd, IDC_PRINTPAGESIZE ), (BOOL)wParam );
  1569. EnableWindow( GetDlgItem( hwnd, IDC_PRINTRES ), (BOOL)wParam );
  1570. EnableWindow( GetDlgItem( hwnd, IDC_PRINTSPEED ), (BOOL)wParam );
  1571. EnableWindow( GetDlgItem( hwnd, IDC_PRINTSPEED_UPDN ), (BOOL)wParam );
  1572. EnableWindow( GetDlgItem( hwnd, IDC_PRINTDUPLEX ), (BOOL)wParam );
  1573. EnableWindow( GetDlgItem( hwnd, IDC_PRINTCOLOR ), (BOOL)wParam );
  1574. EnableWindow( GetDlgItem( hwnd, IDC_PRINTSTAPLE ), (BOOL)wParam );
  1575. break;
  1576. case CQPM_GETPARAMETERS:
  1577. {
  1578. LPWSTR pszBuffer = NULL;
  1579. UINT uLen = 0;
  1580. // Format the parameters for the 2nd page of the query form, this builds
  1581. // an LDAP string and then appends it to the string we have in the
  1582. // existing query parameter block.
  1583. GetPrinterMoreParameters( hwnd, &uLen, NULL );
  1584. if ( uLen )
  1585. {
  1586. hr = LocalAllocStringLenW(&pszBuffer, uLen);
  1587. if ( SUCCEEDED(hr) )
  1588. {
  1589. GetPrinterMoreParameters( hwnd, &uLen, pszBuffer );
  1590. hr = QueryParamsAddQueryString((LPDSQUERYPARAMS*)lParam, pszBuffer );
  1591. LocalFreeStringW(&pszBuffer);
  1592. }
  1593. FailGracefully(hr, "PageProc_PrintersMore: Failed to build DS argument block");
  1594. }
  1595. break;
  1596. }
  1597. case CQPM_CLEARFORM:
  1598. SetDlgItemText( hwnd, IDC_PRINTPAGESIZE, TEXT("") );
  1599. ComboBox_SetCurSel( GetDlgItem( hwnd, IDC_PRINTRES ), 0 );
  1600. SendMessage( GetDlgItem( hwnd, IDC_PRINTSPEED_UPDN ), UDM_SETPOS, 0, MAKELPARAM( 1, 0 ) );
  1601. Button_SetCheck( GetDlgItem( hwnd, IDC_PRINTDUPLEX ), BST_UNCHECKED );
  1602. Button_SetCheck( GetDlgItem( hwnd, IDC_PRINTCOLOR ), BST_UNCHECKED );
  1603. Button_SetCheck( GetDlgItem( hwnd, IDC_PRINTSTAPLE ), BST_UNCHECKED );
  1604. break;
  1605. case CQPM_PERSIST:
  1606. {
  1607. IPersistQuery* pPersistQuery = (IPersistQuery*)lParam;
  1608. BOOL fRead = (BOOL)wParam;
  1609. INT i = 0;
  1610. TCHAR szBuffer[MAX_PATH];
  1611. if ( fRead )
  1612. {
  1613. hr = pPersistQuery->ReadInt( c_szMsPrintersMore, c_szColor, &i );
  1614. FailGracefully(hr, "Failed to read color state");
  1615. Button_SetCheck( GetDlgItem( hwnd, IDC_PRINTCOLOR ), i ? BST_CHECKED : BST_UNCHECKED );
  1616. hr = pPersistQuery->ReadInt( c_szMsPrintersMore, c_szDuplex, &i );
  1617. FailGracefully(hr, "Failed to read duplex state");
  1618. Button_SetCheck( GetDlgItem( hwnd, IDC_PRINTDUPLEX ), i ? BST_CHECKED : BST_UNCHECKED );
  1619. hr = pPersistQuery->ReadInt( c_szMsPrintersMore, c_szStaple, &i );
  1620. FailGracefully(hr, "Failed to read staple state");
  1621. Button_SetCheck( GetDlgItem( hwnd, IDC_PRINTSTAPLE ), i ? BST_CHECKED : BST_UNCHECKED );
  1622. hr = pPersistQuery->ReadInt( c_szMsPrintersMore, c_szResolution, &i );
  1623. FailGracefully(hr, "Failed to read resolution state");
  1624. ComboBox_SetCurSel( GetDlgItem( hwnd, IDC_PRINTRES ), i );
  1625. hr = pPersistQuery->ReadInt( c_szMsPrintersMore, c_szSpeed, &i );
  1626. FailGracefully(hr, "Failed to read speed state");
  1627. SendMessage( GetDlgItem( hwnd, IDC_PRINTSPEED_UPDN ), UDM_SETPOS, 0, MAKELPARAM( i, 0 ) );
  1628. hr = pPersistQuery->ReadString( c_szMsPrintersMore, c_szPaperSize, szBuffer, ARRAYSIZE( szBuffer ) );
  1629. FailGracefully(hr, "Failed to read paper size state");
  1630. ComboBox_SetText( GetDlgItem( hwnd, IDC_PRINTPAGESIZE ), szBuffer );
  1631. }
  1632. else
  1633. {
  1634. i = Button_GetCheck( GetDlgItem( hwnd, IDC_PRINTCOLOR ) ) == BST_CHECKED ? TRUE : FALSE;
  1635. hr = pPersistQuery->WriteInt( c_szMsPrintersMore, c_szColor, i );
  1636. FailGracefully(hr, "Failed to write color state");
  1637. i = Button_GetCheck( GetDlgItem( hwnd, IDC_PRINTDUPLEX ) ) == BST_CHECKED ? TRUE : FALSE;
  1638. hr = pPersistQuery->WriteInt( c_szMsPrintersMore, c_szDuplex, i );
  1639. FailGracefully(hr, "Failed to write duplex state");
  1640. i = Button_GetCheck( GetDlgItem( hwnd, IDC_PRINTSTAPLE ) ) == BST_CHECKED ? TRUE : FALSE;
  1641. hr = pPersistQuery->WriteInt( c_szMsPrintersMore, c_szStaple, i );
  1642. FailGracefully(hr, "Failed to write staple state");
  1643. i = (INT)ComboBox_GetCurSel( GetDlgItem( hwnd, IDC_PRINTRES ) );
  1644. hr = pPersistQuery->WriteInt( c_szMsPrintersMore, c_szResolution, i );
  1645. FailGracefully(hr, "Failed to write resolution state");
  1646. i = (INT)SendMessage( GetDlgItem( hwnd, IDC_PRINTSPEED_UPDN ), UDM_GETPOS, 0, 0 );
  1647. hr = pPersistQuery->WriteInt( c_szMsPrintersMore, c_szSpeed, LOWORD(i) );
  1648. FailGracefully(hr, "Failed to write speed state");
  1649. ComboBox_GetText( GetDlgItem( hwnd, IDC_PRINTPAGESIZE ), szBuffer, ARRAYSIZE( szBuffer ) );
  1650. hr = pPersistQuery->WriteString( c_szMsPrintersMore, c_szPaperSize, szBuffer );
  1651. FailGracefully(hr, "Failed to write paper size state");
  1652. }
  1653. FailGracefully(hr, "Failed to persist page");
  1654. break;
  1655. }
  1656. case CQPM_HELP:
  1657. {
  1658. LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
  1659. WinHelp((HWND)pHelpInfo->hItemHandle,
  1660. DSQUERY_HELPFILE,
  1661. HELP_WM_HELP,
  1662. (DWORD_PTR)aFormHelpIDs);
  1663. break;
  1664. }
  1665. case DSQPM_GETCLASSLIST:
  1666. // the PageProc_Printers will have already handled this, no need to do it again! (daviddv, 19jun98)
  1667. break;
  1668. default:
  1669. hr = E_NOTIMPL;
  1670. break;
  1671. }
  1672. exit_gracefully:
  1673. TraceLeaveResult(hr);
  1674. }
  1675. /*-----------------------------------------------------------------------------
  1676. / DlgProc_Printers
  1677. / ----------------
  1678. / Standard dialog proc for the form, handle any special buttons and other
  1679. / such nastyness we must here.
  1680. /
  1681. / In:
  1682. / hwnd, uMsg, wParam, lParam = standard parameters
  1683. /
  1684. / Out:
  1685. / INT_PTR
  1686. /----------------------------------------------------------------------------*/
  1687. INT_PTR CALLBACK DlgProc_PrintersMore(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1688. {
  1689. INT_PTR fResult = FALSE;
  1690. LPCQPAGE pQueryPage = NULL;
  1691. if ( uMsg == WM_INITDIALOG )
  1692. {
  1693. pQueryPage = (LPCQPAGE)lParam;
  1694. SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)pQueryPage);
  1695. //
  1696. // Fill in the printer forms combo-box.
  1697. //
  1698. PopulatePrintPageSize( hwnd );
  1699. //
  1700. // Fill in the print speed combo-box.
  1701. //
  1702. PopulatePrintSpeed( hwnd );
  1703. //
  1704. // Fill in the print speed combo-box.
  1705. //
  1706. PopulatePrintResolution( hwnd );
  1707. }
  1708. else if ( uMsg == WM_CONTEXTMENU )
  1709. {
  1710. WinHelp((HWND)wParam, DSQUERY_HELPFILE, HELP_CONTEXTMENU, (DWORD_PTR)aFormHelpIDs);
  1711. fResult = TRUE;
  1712. }
  1713. return fResult;
  1714. }