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

1974 lines
60 KiB

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