#include "pch.h" #pragma hdrstop #include #include "winprtp.h" /*----------------------------------------------------------------------------- / Local functions / data /----------------------------------------------------------------------------*/ static TCHAR c_szColor[] = TEXT("color"); static TCHAR c_szDuplex[] = TEXT("duplex"); static TCHAR c_szStaple[] = TEXT("stapling"); static TCHAR c_szResolution[] = TEXT("resolution"); static TCHAR c_szSpeed[] = TEXT("speed"); static TCHAR c_szPaperSize[] = TEXT("size"); static TCHAR c_szPrintPaperSize[] = TEXT("(printMediaReady=%s*)"); static TCHAR c_szPrintResolution[] = TEXT("(printMaxResolutionSupported>=%s)"); static TCHAR c_szPrintSpeed[] = TEXT("(printPagesPerMinute>=%d)"); static TCHAR c_szLocationQuery[] = TEXT("(location=%s*)"); static TCHAR c_szLocationQueryComplex[] = TEXT("(|(location=%s/*)(location=%s))"); static TCHAR c_szBlank[] = TEXT(""); static TCHAR c_szLocationTag[] = TEXT("Location"); static TCHAR c_szDynamicTag[] = TEXT("$DynamicLocation$"); static TCHAR c_szPrinterPolicy[] = TEXT("Software\\Policies\\Microsoft\\Windows NT\\Printers"); static TCHAR c_szPhysicalLocationFeature[] = TEXT("PhysicalLocationSupport"); static WCHAR c_szPrinterName[] = L"printerName"; static WCHAR c_szServerName[] = L"serverName"; static WCHAR c_szQueryPrefix[] = L"(uncName=*)(objectCategory=printQueue)"; static WCHAR c_szPrintColor[] = L"(printColor=TRUE)"; static WCHAR c_szPrintDuplex[] = L"(printDuplexSupported=TRUE)"; static WCHAR c_szPrintStapling[] = L"(printStaplingSupported=TRUE)"; static WCHAR c_szPrintModelProp[] = L"driverName"; #define MAX_LOCATION_WAIT_TIME 30000 #define MAX_LOCATION_MSG_WAIT_TIME 60000 #define MAX_LOCATION MAX_PATH static LPWSTR c_szClassList[] = { L"printQueue", }; static PAGECTRL ctrls1[] = { IDC_PRINTNAME, c_szPrinterName, FILTER_CONTAINS, IDC_PRINTMODEL, c_szPrintModelProp, FILTER_CONTAINS, }; static COLUMNINFO columns[] = { 0, 0, IDS_CN, 0, c_szPrinterName, 0, 0, IDS_LOCATION, 0, c_szLocation, 0, 0, IDS_MODEL, 0, c_szPrintModelProp, 0, 0, IDS_SERVERNAME, 0, c_szServerName, 0, DEFAULT_WIDTH_DESCRIPTION, IDS_COMMENT, 0, c_szDescription, }; static struct { INT idString; LPCTSTR szString; } Resolutions [] = { IDS_ANY, NULL, IDS_72, TEXT("72"), IDS_144, TEXT("144"), IDS_300, TEXT("300"), IDS_600, TEXT("600"), IDS_1200, TEXT("1200"), IDS_2400, TEXT("2400"), IDS_4800, TEXT("4800"), IDS_9600, TEXT("9600"), IDS_32000, TEXT("32000"), }; #define IDH_NOHELP ((DWORD)-1) // Disables Help for a control static const DWORD aFormHelpIDs[]= { IDC_PRINTNAME, IDH_PRINTER_NAME, IDC_PRINTLOCATION, IDH_PRINTER_LOCATION, IDC_PRINTBROWSE, IDH_PRINTER_LOCATION, IDC_PRINTMODEL, IDH_PRINTER_MODEL, IDC_PRINTDUPLEX, IDH_DOUBLE_SIDED, IDC_PRINTSTAPLE, IDH_STAPLE, IDC_PRINTCOLOR, IDH_PRINT_COLOR, IDC_PRINTPAGESIZE, IDH_PAPER_SIZE, IDC_PRINTRES, IDH_RESOLUTION, IDC_PRINTRES_POSTFIX, IDH_RESOLUTION, IDC_PRINTSPEED, IDH_SPEED, IDC_PRINTSPEED_UPDN,IDH_SPEED, IDC_PRINTSPEED_POSTFIX, IDH_SPEED, IDC_SEPLINE, IDH_NOHELP, 0, 0, }; /*----------------------------------------------------------------------------- / CPrintQueryPage class /----------------------------------------------------------------------------*/ class CPrintQueryPage { public: CPrintQueryPage( HWND hwnd ); ~CPrintQueryPage(); HRESULT Initialize( HWND hwnd, BOOL bSynchronous ); LPCTSTR GetSearchText( VOID ); UINT AddRef( VOID ); UINT Release( VOID ); VOID TimerExpire(); VOID EnableLocationEditText( HWND hwnd, BOOL bEnable ); VOID LocationEditTextChanged( HWND hwnd ); VOID BrowseForLocation( HWND hwnd ); HRESULT PersistLocation(HWND hwnd, IPersistQuery* pPersistQuery, BOOL fRead); VOID OnInitDialog( HWND hwnd ); private: CPrintQueryPage( CPrintQueryPage &rhs ); CPrintQueryPage & operator=( CPrintQueryPage &rhs ); VOID WaitForLocation( HWND hwnd ); DWORD Discovery( VOID ); VOID TimerCreate( VOID ); VOID TimerRelease( VOID ); VOID SetLocationText( HWND hCtrl, LPCTSTR pszString, BOOL fReadOnly, BOOL fIgnoreWorkingText ); static DWORD WINAPI _PhysicalLocationThread( PVOID pVoid ); IPhysicalLocation *m_pPhysicalLocation; LPTSTR m_pszPhysicalLocation; LONG m_cRef; HWND m_hCtrl; BOOL m_fThreadCreated; BOOL m_fComplete; BOOL m_fLocationEnableState; BOOL m_fLocationUserModified; BOOL m_bValid; HWND m_hwnd; UINT_PTR m_hTimer; HANDLE m_hComplete; LPTSTR m_pszWorkingText; }; /*----------------------------------------------------------------------------- / CPrintQueryPage / --------------------- / Constructor, creates the IPhysicalLocation object. If we are returned / a good interface pointer indicates the class is valid. / / In: / None. / / Out: / Nothing. /----------------------------------------------------------------------------*/ CPrintQueryPage::CPrintQueryPage( HWND hwnd ) : m_pPhysicalLocation( NULL ), m_pszPhysicalLocation( NULL ), m_cRef( 1 ), m_hCtrl( NULL ), m_fThreadCreated( FALSE ), m_fComplete( FALSE ), m_hwnd( hwnd ), m_hTimer( NULL ), m_fLocationEnableState( TRUE ), m_fLocationUserModified( FALSE ), m_hComplete( NULL ), m_pszWorkingText( NULL ), m_bValid( FALSE ) { TraceEnter(TRACE_FORMS, "CPrintQueryPage::CPrintQueryPage"); // // The physical location feature can be disable using a group // policy setting. If the feature is disabled we will just // fail to aquire the physical location interface and continue // operation with out pre-populating the location edit control. // HRESULT hr = CoCreateInstance( CLSID_PrintUIShellExtension, 0, CLSCTX_INPROC_SERVER, IID_IPhysicalLocation, (VOID**)&m_pPhysicalLocation ); if (SUCCEEDED( hr )) { // // Check if the physical location policy is enabled. // if (SUCCEEDED(m_pPhysicalLocation->ShowPhysicalLocationUI())) { TimerCreate(); m_hComplete = CreateEvent( NULL, TRUE, FALSE, NULL ); if (m_hComplete) { // // Attempt to fetch the working text from the resource file. // TCHAR szBuffer[MAX_PATH] = {0}; if (LoadString(GLOBAL_HINSTANCE, IDS_PRINT_WORKING_TEXT, szBuffer, ARRAYSIZE(szBuffer))) { hr = LocalAllocString (&m_pszWorkingText, szBuffer); } else { TraceAssert(FALSE); } // // Indicate the class is in a valid state, i.e. usable. // m_bValid = TRUE; } } } TraceLeave(); } /*----------------------------------------------------------------------------- / ~CPrintQueryPage / --------------------- / Destructor, release the IPhysicalLocation object and the location string. / / In: / None. / / Out: / Nothing. /----------------------------------------------------------------------------*/ CPrintQueryPage::~CPrintQueryPage() { TraceEnter(TRACE_FORMS, "CPrintQueryPage::~CPrintQueryPage"); if (m_pPhysicalLocation) { m_pPhysicalLocation->Release(); } LocalFreeString(&m_pszPhysicalLocation); // // Only release the string if it was allocated and it is not the null string. // if (m_pszWorkingText && (m_pszWorkingText != c_szBlank)) { LocalFreeString(&m_pszWorkingText); } TimerRelease(); if (m_hComplete) { CloseHandle( m_hComplete ); } TraceLeave(); } /*----------------------------------------------------------------------------- / AddRef / --------------------- / Increases the reference count of this object. This is method is used to / control the life time of this class when a backgroud thread is used to fetch / the physical location string. / / In: / None. / / Out: / New object refrence count. /----------------------------------------------------------------------------*/ UINT CPrintQueryPage::AddRef( VOID ) { return InterlockedIncrement(&m_cRef); } /*----------------------------------------------------------------------------- / Release / --------------------- / Decreases the reference count of this object. This is method is used to / control the life time of this class when a backgroud thread is used to fetch / the physical location string. / / In: / None. / / Out: / New object refrence count. /----------------------------------------------------------------------------*/ UINT CPrintQueryPage::Release (VOID) { if (!InterlockedDecrement(&m_cRef)) { delete this; return 0; } return m_cRef; } /*----------------------------------------------------------------------------- / GetSearchText / --------------------- / Returns a pointer to the current search text. The search text is the / physical location path returned from the IPhysicalLocation object. If either / the search text does not exist or not found this routine will return a / NULL string. / / In: / None. / / Out: / Ponter to the search text or the NULL string. /----------------------------------------------------------------------------*/ LPCTSTR CPrintQueryPage::GetSearchText( VOID ) { return m_pszPhysicalLocation ? m_pszPhysicalLocation : c_szBlank; } /*----------------------------------------------------------------------------- / Initialize / --------------------- / Creates the background thread and calls the physical location discovery / method. / / In: / Edit control window handle where to place text when done. / bSynchronous flag TRUE use backgroud thread, FALSE call synchronously. / / Out: / HRESULT hr. /----------------------------------------------------------------------------*/ HRESULT CPrintQueryPage::Initialize( HWND hwnd, BOOL bSynchronous ) { TraceEnter(TRACE_FORMS, "CPrintQueryPage::Initialize"); HRESULT hr = S_OK; DWORD dwThreadID = 0; HANDLE hThread = NULL; // // If we have a valid physical location interface and the thread was not created, // then create it now and call the discovery method. // if (m_bValid && !m_fThreadCreated) { // // Bump the objects refrence count, needed for the async thread. // AddRef(); // // Save the window handle in the class so the background thread // knows what window to set the location text to. // m_hCtrl = hwnd; // // Increase this libraries object refcount, ole will not unload until // we hit zeor and DllCanUnloadNow returns true. // DllAddRef(); // // Only create the thread once. // m_fThreadCreated = TRUE; // // If we are requested to do a synchronous call then just call the // thread proc directly. // if (bSynchronous) { hr = (_PhysicalLocationThread( this ) == ERROR_SUCCESS) ? S_OK : E_FAIL; } else { // // Create the background thread. // hThread = CreateThread( NULL, 0, reinterpret_cast(CPrintQueryPage::_PhysicalLocationThread), reinterpret_cast( this ), 0, &dwThreadID); TraceAssert(hThread); // // If the thread failed creation clean up the dll refrence count // and the object refrence and the thread created flag. // if (!hThread) { m_fThreadCreated = FALSE; DllRelease(); Release(); hr = E_FAIL; } else { // // Thread is running just close the handle, we let the thread die // on its own normally. // CloseHandle(hThread); // // Indicate the request is pending. // hr = HRESULT_FROM_WIN32 (ERROR_IO_PENDING); } } } // // If we have a valid interface pointer and the background thread // has not completed then indicated the data is still pending. // else if(m_bValid && !m_fComplete) { // // Indicate the request is pending. // hr = HRESULT_FROM_WIN32 (ERROR_IO_PENDING); } // // If we failed with IO_PENDING then set the working text. // if (FAILED(hr) && HRESULT_CODE(hr) == ERROR_IO_PENDING) { // // Set the new location text. // SetLocationText (hwnd, m_pszWorkingText, TRUE, TRUE); PostMessage (m_hCtrl, EM_SETSEL, 0, 0); } TraceLeaveResult(hr); } /*----------------------------------------------------------------------------- / _PhysicalLocationThread / --------------------- / This routine is the backgroud thread thunk. It accepts the CPrintQueryPage / this pointer and then calles the actual discovery method. The purpose of / this routine is simple to capture the this pointer after the thread was / created and then invoke a method. / / In: / Pointer to PrintQueryPage class. / / Out: / TRUE success, FALSE error occurred. /----------------------------------------------------------------------------*/ DWORD WINAPI CPrintQueryPage::_PhysicalLocationThread( PVOID pVoid ) { DWORD dwRetval = ERROR_OUTOFMEMORY; if ( SUCCEEDED(CoInitialize(NULL)) ) { // // Get a pointer to this class. // CPrintQueryPage *pPrintQueryPage = reinterpret_cast( pVoid ); // // Invoke the location discovery process. // dwRetval = pPrintQueryPage->Discovery(); // // Set the completion event, in case someone is waiting. // SetEvent(pPrintQueryPage->m_hComplete); // // Indicate the discovery process completed. // pPrintQueryPage->m_fComplete = TRUE; // // Release the timer // pPrintQueryPage->TimerRelease(); // // Release the refrence to the PrintQueryPage class. // pPrintQueryPage->Release(); // // COM no longer needed // CoUninitialize(); } DllRelease(); return dwRetval; } /*----------------------------------------------------------------------------- / Discovery / --------- / This routine is the backgroud thread discovery process. Since the act / of figuring out the physical location of this machin must hit the net / it can take a significant amount of time. Hence we do this in a separate / thread. / / In: / Nothing. / / Out: / TRUE success, FALSE error occurred. /----------------------------------------------------------------------------*/ DWORD CPrintQueryPage::Discovery( VOID ) { TraceEnter(TRACE_FORMS, "CPrintQueryPage::Discovery"); // // Start the discovery process for finding the physical location search text // for this machine. // HRESULT hr = m_pPhysicalLocation->DiscoverPhysicalLocation(); if (SUCCEEDED( hr )) { BSTR pbsPhysicalLocation = NULL; // // Get the physical location search text. // hr = m_pPhysicalLocation->GetSearchPhysicalLocation( &pbsPhysicalLocation ); // // If the error indicates the length was returned then allocate the text buffer. // if (SUCCEEDED( hr ) && pbsPhysicalLocation) { // // Release the previous string if any. // if (m_pszPhysicalLocation) { LocalFreeString(&m_pszPhysicalLocation); } // // Convert the BSTR location string to a TSTR string. // hr = LocalAllocStringW2T( &m_pszPhysicalLocation, pbsPhysicalLocation ); } // // Release the physical location string if it was allocated. // if( pbsPhysicalLocation ) { SysFreeString( pbsPhysicalLocation ); } } // // Set the new location text. // SetLocationText( m_hCtrl, GetSearchText(), FALSE, FALSE ); TraceLeaveValue(SUCCEEDED( hr ) ? ERROR_SUCCESS : ERROR_OUTOFMEMORY); } /*----------------------------------------------------------------------------- / WaitForLocation / --------------------- / Wait for the printer location information. / / In: / hwnd parent window handle. / / Out: / BOOL TRUE if success, FALSE if error. /----------------------------------------------------------------------------*/ VOID CPrintQueryPage::WaitForLocation( HWND hwnd ) { TraceEnter(TRACE_FORMS, "CPrintQueryPage::WaitForLocation"); // // Only wait if we have a valid location interface pointer and // completion event handle was created and the thread is running. // if (m_bValid && m_hComplete && m_fThreadCreated) { // // Keep waiting until the physical location is avaialble or a timeout. // for (BOOL fExit = FALSE; !fExit; ) { switch (MsgWaitForMultipleObjects(1, &m_hComplete, FALSE, MAX_LOCATION_MSG_WAIT_TIME, QS_ALLINPUT)) { case WAIT_OBJECT_0: fExit = TRUE; break; case WAIT_TIMEOUT: fExit = TRUE; break; default: { // // Process any message now. // MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } break; } } } } TraceLeave(); } /*----------------------------------------------------------------------------- / TimerCreate / --------------------- / Create the timer event to detect if the discovery method is taking too long. / / In: / / Out: /----------------------------------------------------------------------------*/ VOID CPrintQueryPage::TimerCreate( VOID ) { TraceEnter(TRACE_FORMS, "CPrintQueryPage::TimerCreate"); if (!m_hTimer) { m_hTimer = SetTimer(m_hwnd, WM_USER, MAX_LOCATION_WAIT_TIME, NULL); } TraceLeave(); } /*----------------------------------------------------------------------------- / TimerRelease / --------------------- / Release the timer event. / / In: / / Out: /----------------------------------------------------------------------------*/ VOID CPrintQueryPage::TimerRelease( VOID ) { TraceEnter(TRACE_FORMS, "CPrintQueryPage::TimerRelease"); if (m_hTimer) { KillTimer(m_hwnd, m_hTimer); m_hTimer = NULL; } TraceLeave(); } /*----------------------------------------------------------------------------- / TimerExpire / --------------------- / / In: / / Out: /----------------------------------------------------------------------------*/ VOID CPrintQueryPage::TimerExpire( VOID ) { TraceEnter(TRACE_FORMS, "CPrintQueryPage::TimerExpire"); // // The search data is not complete // if (!m_fComplete) { // // Blank out the location text, it took too long to find. // SetLocationText(m_hCtrl, c_szBlank, FALSE, TRUE); // // Set the completion event, in case someone is waiting. // SetEvent(m_hComplete); // // Indicate the discovery process completed. // m_fComplete = TRUE; } // // Release the timer, the time is a one shot notification. // TimerRelease(); TraceLeave(); } /*----------------------------------------------------------------------------- / EnableLocationEditText / --------------------- / Enabled or disable the location edit text only if it is does not contain / the pending text. / / In: / hwnd parent window handle. / / Out: / BOOL TRUE if success, FALSE if error. /----------------------------------------------------------------------------*/ VOID CPrintQueryPage::EnableLocationEditText( HWND hwnd, BOOL bEnable ) { TraceEnter(TRACE_FORMS, "CPrintQueryPage::EnableLocationEditText"); HWND hCtrl = GetDlgItem(hwnd, IDC_PRINTLOCATION); HWND hBrowseCtrl = GetDlgItem(hwnd, IDC_PRINTBROWSE); // // If the CPrintQueryPage is valid then handle the location // edit control differently. // if (m_bValid) { TCHAR szBuffer[MAX_LOCATION] = {0}; // // Save the previous location enable state. // m_fLocationEnableState = bEnable; // // Get the current location text. // GetWindowText(hCtrl, szBuffer, ARRAYSIZE(szBuffer)); // // Do not change the location edit control enable state when the // working text is there. The reason for this is the text // is hard to read when the control is disabled, but when the // control is just read only the text is black not gray hence // eaiser to read. // if (!_tcscmp(szBuffer, m_pszWorkingText)) { // // For an unknown reason the control with the location // text has the input focus, the default input focus // should be on the printer name therefore I will // set the focus here. // SetFocus(GetDlgItem(hwnd, IDC_PRINTNAME)); } else { EnableWindow(hBrowseCtrl, bEnable); EnableWindow(hCtrl, bEnable); } } else { EnableWindow(hBrowseCtrl, bEnable); EnableWindow(hCtrl, bEnable); } TraceLeave(); } /*----------------------------------------------------------------------------- / LocationEditTextChanged / --------------------- / / In: / hwnd parent window handle. / / Out: / BOOL TRUE if success, FALSE if error. /----------------------------------------------------------------------------*/ VOID CPrintQueryPage::LocationEditTextChanged( HWND hwnd ) { TraceEnter(TRACE_FORMS, "CPrintQueryPage::LocationEditTextChanged"); // // The search data is complete // if (m_fComplete) { m_fLocationUserModified = TRUE; } TraceLeave(); } /*----------------------------------------------------------------------------- / PersistLocation / --------------------- / / In: / hwnd parent window handle. / / Out: / BOOL TRUE if success, FALSE if error. /----------------------------------------------------------------------------*/ HRESULT CPrintQueryPage::PersistLocation(HWND hwnd, IPersistQuery* pPersistQuery, BOOL fRead) { TraceEnter(TRACE_FORMS, "CPrintQueryPage::PersistLocation"); HRESULT hr = S_OK; TCHAR szBuffer[MAX_LOCATION] = {0}; // // Get the control handle for the location edit control // HWND hCtrl = GetDlgItem(hwnd, IDC_PRINTLOCATION); // // Are we to read the persisted query string. // if (fRead) { // // Read the persisted location string. // hr = pPersistQuery->ReadString( c_szMsPrintersMore, c_szLocationTag, szBuffer, ARRAYSIZE( szBuffer ) ); FailGracefully(hr, "Failed to read location state"); // // Assume this is the exact string. // LPCTSTR pLocation = szBuffer; // // If the dynamic sentinal was found then wait for the dynamic location // text to be avaiable. // if (!_tcscmp(szBuffer, c_szDynamicTag)) { WaitForLocation(hwnd); pLocation = GetSearchText(); } // // Set the persisted location string in the query form. // SetLocationText(hCtrl, pLocation, FALSE, TRUE); } else { // // If the user modified the location text then save this text, otherwize // save a sentinal string which indicates we are to determine the location // dynamically when the persisted query is read back. // if (m_fLocationUserModified) { GetWindowText(hCtrl, szBuffer, ARRAYSIZE(szBuffer)); hr = pPersistQuery->WriteString( c_szMsPrintersMore, c_szLocationTag, szBuffer ); FailGracefully(hr, "Failed to write location state"); } else { hr = pPersistQuery->WriteString( c_szMsPrintersMore, c_szLocationTag, c_szDynamicTag ); FailGracefully(hr, "Failed to write location working state"); } } exit_gracefully: TraceLeaveResult(hr); } /*----------------------------------------------------------------------------- / SetLocationText / --------------------- / / In: / hwnd parent window handle. / / Out: / BOOL TRUE if success, FALSE if error. /----------------------------------------------------------------------------*/ VOID CPrintQueryPage::SetLocationText( HWND hCtrl, LPCTSTR pszString, BOOL fReadOnly, BOOL fIgnoreWorkingText ) { TraceEnter(TRACE_FORMS, "CPrintQueryPage::SetLocationText"); if (IsWindow(hCtrl)) { // // Is the CPrintQueryPage in a valid state. // if (m_bValid) { TCHAR szBuffer[MAX_LOCATION]; // // Read the current location text. // GetWindowText(hCtrl, szBuffer, ARRAYSIZE(szBuffer)); // // Stick the location string in the edit control if it contains working. // if (!_tcscmp(szBuffer, m_pszWorkingText) || fIgnoreWorkingText) { SetWindowText(hCtrl, pszString); } // // Reset the control to non read only state. // SendMessage(hCtrl, EM_SETREADONLY, fReadOnly, 0); // // Enable the control if the read only is disabled. // if (!fReadOnly) { // // Enable the edit control. // EnableWindow(hCtrl, m_fLocationEnableState); } // // Only enable the browse button when we have a location string // and the then control is not in read only mode. // EnableWindow(GetDlgItem(m_hwnd, IDC_PRINTBROWSE), !fReadOnly && m_fLocationEnableState); } else { // // If we are not using the location interface, just set the location text. // SetWindowText(hCtrl, pszString); } } TraceLeave(); } /*----------------------------------------------------------------------------- / BrowseForLocation / --------------------- / Starts the browse for location tree view and populates the edit control / with a valid selection. / / In: / hwnd parent window handle. / / Out: / Nothing. /----------------------------------------------------------------------------*/ VOID CPrintQueryPage::BrowseForLocation( HWND hwnd ) { TraceEnter(TRACE_FORMS, "CPrintQueryPage::BrowseForLocation"); if (m_bValid) { BSTR pbPhysicalLocation = NULL; BSTR pbDefaultLocation = NULL; LPTSTR pszPhysicalLocation = NULL; HRESULT hr = E_FAIL; TCHAR szText[MAX_LOCATION]= {0}; // // Convert the physical location to a BSTR for the IPhysicalLocation // object can pre-expand the browse tree. // if (GetWindowText(GetDlgItem(hwnd, IDC_PRINTLOCATION), szText, ARRAYSIZE(szText))) { pbDefaultLocation = T2BSTR(szText); } else { pbDefaultLocation = T2BSTR(m_pszPhysicalLocation); } // // Display the location tree. // hr = m_pPhysicalLocation->BrowseForLocation(hwnd, pbDefaultLocation, &pbPhysicalLocation); if(SUCCEEDED(hr) && pbPhysicalLocation) { // // Convert the BSTR location string to a TSTR string. // hr = LocalAllocStringW2T(&pszPhysicalLocation, pbPhysicalLocation); if(SUCCEEDED(hr)) { // // Set the location text. // SetLocationText(m_hCtrl, pszPhysicalLocation, FALSE, TRUE); } // // Release the TCHAR physical location string. // LocalFreeString(&pszPhysicalLocation); // // Release the physical location string. // SysFreeString(pbPhysicalLocation); } // // Release the default locatin string. // SysFreeString(pbDefaultLocation); } TraceLeave(); } /*----------------------------------------------------------------------------- / OnInitDialog / --------------------- / Set the UI's initial state, on down level machines the browse button is / removed and the edit control is stetched to match the size of the other / edit controls, i.e. name, model. / / In: / hwnd parent window handle. / / Out: / Nothing. /----------------------------------------------------------------------------*/ VOID CPrintQueryPage::OnInitDialog( HWND hwnd ) { TraceEnter(TRACE_FORMS, "CPrintQueryPage::OnInitDialog"); if (!m_bValid) { // // If the IPhysicalLocation interface is not available, hide the browse // button and extend the location edit control appropriately // RECT rcName = {0}; RECT rcLocation = {0}; GetWindowRect (GetDlgItem (hwnd, IDC_PRINTNAME), &rcName); GetWindowRect (GetDlgItem (hwnd, IDC_PRINTLOCATION), &rcLocation); SetWindowPos (GetDlgItem (hwnd, IDC_PRINTLOCATION), NULL, 0,0, rcName.right - rcName.left, rcLocation.bottom - rcLocation.top, SWP_NOMOVE|SWP_NOZORDER); ShowWindow (GetDlgItem (hwnd, IDC_PRINTBROWSE), SW_HIDE); } TraceLeave(); } /*----------------------------------------------------------------------------- / PopulateLocationEditText / --------------------- / Populates the location edit control with the default location of this / machine. / / In: / hwnd parent window handle. / / Out: / BOOL TRUE if success, FALSE if error. /----------------------------------------------------------------------------*/ BOOL PopulateLocationEditText( HWND hwnd, BOOL bClearField ) { TraceEnter(TRACE_FORMS, "PopulateLocationEditText"); CPrintQueryPage *pPrintQueryPage = reinterpret_cast(GetWindowLongPtr(hwnd, DWLP_USER)); if (pPrintQueryPage) { HWND hCtrl = GetDlgItem(hwnd, IDC_PRINTLOCATION); HRESULT hr = pPrintQueryPage->Initialize( hCtrl, FALSE ); if (SUCCEEDED( hr )) { if( bClearField ) { SetWindowText( hCtrl, c_szBlank); } else { SetWindowText( hCtrl, pPrintQueryPage->GetSearchText( )); } } } TraceLeaveValue(TRUE); } /*----------------------------------------------------------------------------- / bEnumForms / ---------- / Enumerates the forms on the printer identified by the handle. / / In: / IN HANDLE hPrinter, / IN DWORD dwLevel, / IN PBYTE *ppBuff, / IN PDWORD pcReturned / / Out: / Pointer to forms array and count of forms in the array if / success, NULL ponter and zero number of forms if failure. / BOOL TRUE if success, FALSE if error. /----------------------------------------------------------------------------*/ BOOL bEnumForms( IN HANDLE hPrinter, IN DWORD dwLevel, IN PFORM_INFO_1 *ppFormInfo, IN PDWORD pcReturned ) { BOOL bReturn = FALSE; DWORD dwReturned = 0; DWORD dwNeeded = 0; PBYTE p = NULL; BOOL bStatus = FALSE; // // Get buffer size for enum forms. // bStatus = EnumForms( hPrinter, dwLevel, NULL, 0, &dwNeeded, &dwReturned ); // // Check if the function returned the buffer size. // if( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) { goto Cleanup; } // // If buffer allocation fails. // p = (PBYTE)LocalAlloc( LPTR, dwNeeded ); if( p == NULL ) { goto Cleanup; } // // Get the forms enumeration // bStatus = EnumForms( hPrinter, dwLevel, p, dwNeeded, &dwNeeded, &dwReturned ); // // Copy back the buffer pointer and count. // if( bStatus ) { bReturn = TRUE; *ppFormInfo = (PFORM_INFO_1)p; *pcReturned = dwReturned; } Cleanup: if( bReturn == FALSE ) { // // Indicate failure. // *ppFormInfo = NULL; *pcReturned = 0; // // Release any allocated memory. // if ( p ) { LocalFree( p ); } } return bReturn; } /*----------------------------------------------------------------------------- / PopulatePrintPageSize / ---------------- / Eumerates all the pages size from this machine's print spooler. This allows / a user to choose from a list of available forms rather than remembering the / name of the particular form. / / In: / hwnd parent window handle. / / Out: / BOOL TRUE if success, FALSE if error. /----------------------------------------------------------------------------*/ BOOL PopulatePrintPageSize( HWND hwnd ) { HANDLE hServer = NULL; PFORM_INFO_1 pFormInfo = NULL; DWORD FormCount = 0; BOOL bRetval = FALSE; TCHAR szBuffer[MAX_PATH]; // // Open the local print server with default access. // BOOL bStatus = OpenPrinter( NULL, &hServer, NULL ); if( bStatus ) { // // Enumerate the forms. // bStatus = bEnumForms( hServer, 1, &pFormInfo, &FormCount ); } if( bStatus && pFormInfo ) { // // Fill the combo box. // for( UINT i = 0; i < FormCount; i++ ) { ComboBox_AddString( GetDlgItem( hwnd, IDC_PRINTPAGESIZE ), pFormInfo[i].pName ); } // // Set the limit text in the form name edit control // ComboBox_LimitText( GetDlgItem( hwnd, IDC_PRINTPAGESIZE ), CCHFORMNAME-1 ); // // Return success. // bRetval = TRUE; } if( pFormInfo ) { // // Release the forms buffer if it was allocated. // LocalFree( pFormInfo ); } if ( hServer ) { ClosePrinter(hServer); } return bRetval; } /*----------------------------------------------------------------------------- / PopulatePrintSpeed / ---------------- / Set the print speed up down arrow control with an upper and lower / bound range. / / In: / hwnd parent window handle / / Out: / BOOL TRUE if success, FALSE if error. /----------------------------------------------------------------------------*/ BOOL PopulatePrintSpeed( HWND hwnd ) { // // Set the print speed up down arrow range. // SendMessage( GetDlgItem( hwnd, IDC_PRINTSPEED_UPDN ), UDM_SETRANGE, 0, MAKELPARAM( 9999, 1 ) ); Edit_LimitText(GetDlgItem(hwnd, IDC_PRINTSPEED), 4); return TRUE; } /*----------------------------------------------------------------------------- / PopulateResolution / ---------------- / Fill the print resolution contrl with valid resolution information. / / In: / hwnd / / Out: / BOOL TRUE if success, FALSE if error. /----------------------------------------------------------------------------*/ BOOL PopulatePrintResolution( HWND hwnd ) { TCHAR szBuffer[MAX_PATH]; // // Fill in the print resolution combo-box. // for( INT i = 0; i < ARRAYSIZE( Resolutions ); i++ ) { if( !LoadString(GLOBAL_HINSTANCE, Resolutions[i].idString, szBuffer, ARRAYSIZE(szBuffer))) { TraceAssert(FALSE); } ComboBox_AddString( GetDlgItem( hwnd, IDC_PRINTRES ), szBuffer ); } return TRUE; } /*----------------------------------------------------------------------------- / GetPrinterMoreParameters. / ---------------- / Build the query string from the controls on the printer more page. / / In: / hwnd parent window handle. / pLen pointer to length of query string. / pszBuffer pointer to buffer where to return the query string. / / Out: / Nothing. /----------------------------------------------------------------------------*/ VOID GetPrinterMoreParameters( HWND hwnd, UINT *puLen, LPWSTR pszBuffer ) { USES_CONVERSION; TCHAR szScratch[MAX_PATH] = {0}; TCHAR szText[MAX_PATH] = {0}; INT i = 0; // // Read the check box states and build the query string. // if( Button_GetCheck( GetDlgItem( hwnd, IDC_PRINTDUPLEX ) ) == BST_CHECKED ) PutStringElementW(pszBuffer, puLen, c_szPrintDuplex); if( Button_GetCheck( GetDlgItem( hwnd, IDC_PRINTCOLOR ) ) == BST_CHECKED ) PutStringElementW(pszBuffer, puLen, c_szPrintColor); if( Button_GetCheck( GetDlgItem( hwnd, IDC_PRINTSTAPLE ) ) == BST_CHECKED ) PutStringElementW(pszBuffer, puLen, c_szPrintStapling); // // Read the paper size setting. // ComboBox_GetText( GetDlgItem( hwnd, IDC_PRINTPAGESIZE ), szText, ARRAYSIZE( szText ) ); if( lstrlen( szText ) ) { wsprintf( szScratch, c_szPrintPaperSize, szText ); PutStringElementW(pszBuffer, puLen, T2W(szScratch)); } // // Read the printer resolution setting // i = ComboBox_GetCurSel( GetDlgItem( hwnd, IDC_PRINTRES ) ); if( i > 0 && i < ARRAYSIZE( Resolutions ) ) { wsprintf( szScratch, c_szPrintResolution, Resolutions[i].szString ); PutStringElementW(pszBuffer, puLen, T2W(szScratch)); } // // Read the printer speed setting // i = (LONG)SendMessage( GetDlgItem( hwnd, IDC_PRINTSPEED_UPDN ), UDM_GETPOS, 0, 0 ); if( LOWORD(i) > 1 && i != -1 ) { wsprintf( szScratch, c_szPrintSpeed, i ); PutStringElementW(pszBuffer, puLen, T2W(szScratch)); } } /*----------------------------------------------------------------------------- / GetPrinterLocationParameter. / ---------------- / Build the query string from the location control on the printer page. / / In: / hwnd parent window handle. / pLen pointer to length of query string. / pszBuffer pointer to buffer where to return the query string. / / Out: / Nothing. /----------------------------------------------------------------------------*/ VOID GetPrinterLocationParameter( HWND hwnd, UINT *puLen, LPWSTR pszBuffer ) { USES_CONVERSION; TCHAR szScratch[MAX_PATH*2] = {0}; TCHAR szText[MAX_PATH] = {0}; TCHAR szWorkingText[MAX_PATH] = {0}; DWORD dwLocationLength = 0; HWND hCtrl = GetDlgItem(hwnd, IDC_PRINTLOCATION); if ( hCtrl != NULL ) { dwLocationLength = GetWindowText(hCtrl, szText, ARRAYSIZE(szText)); if (dwLocationLength != 0) { if (LoadString(GLOBAL_HINSTANCE, IDS_PRINT_WORKING_TEXT, szWorkingText, ARRAYSIZE(szWorkingText))) { if (_tcscmp(szText, szWorkingText)) { BOOL fUseMoreComplexSearch = FALSE; // // If we have a location that ends in a forward slash, // we'll trim that off and use a slightly more complex // search parameter so that we can pick up locations // that either match the location parameter exactly or // start with the parameter and have a slash immediately // following. // if ( dwLocationLength > 1 ) { if ( szText[dwLocationLength-1] == TEXT('/') ) { szText[dwLocationLength-1] = TEXT('\0'); fUseMoreComplexSearch = TRUE; } } if ( fUseMoreComplexSearch ) { wsprintf(szScratch, c_szLocationQueryComplex, szText, szText); } else { wsprintf(szScratch, c_szLocationQuery, szText); } PutStringElementW(pszBuffer, puLen, T2W(szScratch)); } else { // // We are not going to wait the location field if the search process // has been kicked off. Just hit the expire timer to cancel the location // thread. This will ensure that the result list and the query params // will be consistent. // CPrintQueryPage *pPrintQueryPage = reinterpret_cast(GetWindowLongPtr(hwnd, DWLP_USER)); if (pPrintQueryPage) { pPrintQueryPage->TimerExpire(); } } } else { TraceAssert(FALSE); } } } else { // GetDlgItem() returned NULL for the location control. TraceAssert(FALSE); } } /*----------------------------------------------------------------------------- / Query Page: Printers /----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------- / PageProc_Printer / ---------------- / PageProc for handling the messages for this object. / / In: / pPage -> instance data for this form / hwnd = window handle for the form dialog / uMsg, wParam, lParam = message parameters / / Out: / HRESULT (E_NOTIMPL) if not handled /----------------------------------------------------------------------------*/ HRESULT CALLBACK PageProc_Printers(LPCQPAGE pPage, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { HRESULT hr = S_OK; LPWSTR pQuery = NULL; UINT uLen = 0; TraceEnter(TRACE_FORMS, "PageProc_Printers"); switch ( uMsg ) { case CQPM_INITIALIZE: case CQPM_RELEASE: break; case CQPM_ENABLE: { CPrintQueryPage *pPrintQueryPage = reinterpret_cast(GetWindowLongPtr(hwnd, DWLP_USER)); if (pPrintQueryPage) { pPrintQueryPage->EnableLocationEditText( hwnd, (BOOL)wParam ); } // Enable the form controls, EnablePageControls(hwnd, ctrls1, ARRAYSIZE(ctrls1), (BOOL)wParam); break; } case CQPM_GETPARAMETERS: { // // Get the printer name and model paramters. // hr = GetQueryString(&pQuery, c_szQueryPrefix, hwnd, ctrls1, ARRAYSIZE(ctrls1)); if ( SUCCEEDED(hr) ) { hr = QueryParamsAlloc((LPDSQUERYPARAMS*)lParam, pQuery, GLOBAL_HINSTANCE, ARRAYSIZE(columns), columns); LocalFreeStringW(&pQuery); } // // Get the location parameter. // GetPrinterLocationParameter( hwnd, &uLen, NULL ); if (uLen) { hr = LocalAllocStringLenW(&pQuery, uLen); if ( SUCCEEDED(hr) ) { GetPrinterLocationParameter( hwnd, &uLen, pQuery ); hr = QueryParamsAddQueryString((LPDSQUERYPARAMS*)lParam, pQuery ); LocalFreeStringW(&pQuery); } } FailGracefully(hr, "PageProc_Printers: Failed to build DS argument block"); break; } case CQPM_CLEARFORM: { // Reset the form controls. PopulateLocationEditText( hwnd, TRUE ); ResetPageControls(hwnd, ctrls1, ARRAYSIZE(ctrls1)); break; } case CQPM_PERSIST: { BOOL fRead = (BOOL)wParam; IPersistQuery* pPersistQuery = (IPersistQuery*)lParam; CPrintQueryPage *pPrintQueryPage = reinterpret_cast(GetWindowLongPtr(hwnd, DWLP_USER)); if (pPrintQueryPage) { hr = pPrintQueryPage->PersistLocation(hwnd, pPersistQuery, fRead); } if (SUCCEEDED(hr)) { // Read the standard controls from the page, hr = PersistQuery(pPersistQuery, fRead, c_szMsPrinters, hwnd, ctrls1, ARRAYSIZE(ctrls1)); } FailGracefully(hr, "Failed to persist page"); break; } case CQPM_SETDEFAULTPARAMETERS: { // // so that the caller can pass parameters to the form we support an IPropertyBag in the // OPENQUERYWINDOW structure. If wParam == TRUE, and lParam is non-zero then we // assume we should decode this structure to get the information we need from it. // if ( wParam && lParam ) { OPENQUERYWINDOW *poqw = (OPENQUERYWINDOW*)lParam; if ( poqw->dwFlags & OQWF_PARAMISPROPERTYBAG ) { IPropertyBag *ppb = poqw->ppbFormParameters; SetDlgItemFromProperty(ppb, L"printName", hwnd, IDC_PRINTNAME, NULL); SetDlgItemFromProperty(ppb, L"printLocation", hwnd, IDC_PRINTLOCATION, NULL); SetDlgItemFromProperty(ppb, L"printModel", hwnd, IDC_PRINTMODEL, NULL); } } break; } case CQPM_HELP: { LPHELPINFO pHelpInfo = (LPHELPINFO)lParam; WinHelp((HWND)pHelpInfo->hItemHandle, DSQUERY_HELPFILE, HELP_WM_HELP, (DWORD_PTR)aFormHelpIDs); break; } case DSQPM_GETCLASSLIST: { hr = ClassListAlloc((LPDSQUERYCLASSLIST*)lParam, c_szClassList, ARRAYSIZE(c_szClassList)); FailGracefully(hr, "Failed to allocate class list"); break; } case DSQPM_HELPTOPICS: { HWND hwndFrame = (HWND)lParam; TraceMsg("About to display help topics for find printers - ocm.chm"); HtmlHelp(hwndFrame, TEXT("omc.chm"), HH_HELP_FINDER, 0); break; } default: hr = E_NOTIMPL; break; } exit_gracefully: TraceLeaveResult(hr); } /*----------------------------------------------------------------------------- / DlgProc_Printers / ---------------- / Standard dialog proc for the form, handle any special buttons and other / such nastyness we must here. / / In: / hwnd, uMsg, wParam, lParam = standard parameters / / Out: / BOOL /----------------------------------------------------------------------------*/ INT_PTR CALLBACK DlgProc_Printers(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR fResult = TRUE; CPrintQueryPage *pPrintQueryPage = reinterpret_cast(GetWindowLongPtr(hwnd, DWLP_USER)); switch ( uMsg ) { case WM_INITDIALOG: { Edit_LimitText(GetDlgItem(hwnd, IDC_PRINTNAME), MAX_PATH-1); Edit_LimitText(GetDlgItem(hwnd, IDC_PRINTLOCATION), MAX_LOCATION-1); Edit_LimitText(GetDlgItem(hwnd, IDC_PRINTMODEL), MAX_PATH-1); pPrintQueryPage = new CPrintQueryPage(hwnd); if (pPrintQueryPage) { SetWindowLongPtr(hwnd, DWLP_USER, reinterpret_cast(pPrintQueryPage)); pPrintQueryPage->OnInitDialog(hwnd); PopulateLocationEditText(hwnd, FALSE); } else { fResult = FALSE; } break; } case WM_CONTEXTMENU: { WinHelp((HWND)wParam, DSQUERY_HELPFILE, HELP_CONTEXTMENU, (DWORD_PTR)aFormHelpIDs); break; } case WM_NCDESTROY: { if (pPrintQueryPage) { pPrintQueryPage->Release(); } SetWindowLongPtr(hwnd, DWLP_USER, NULL); break; } case WM_TIMER: { if (pPrintQueryPage) { pPrintQueryPage->TimerExpire(); } break; } case WM_COMMAND: { if((GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) && (GET_WM_COMMAND_ID(wParam, lParam) == IDC_PRINTLOCATION)) { if (pPrintQueryPage) { pPrintQueryPage->LocationEditTextChanged(hwnd); } } else if((GET_WM_COMMAND_ID(wParam, lParam) == IDC_PRINTBROWSE)) { if (pPrintQueryPage) { pPrintQueryPage->BrowseForLocation(hwnd); } } else { fResult = FALSE; } break; } default: { fResult = FALSE; break; } } return fResult; } /*----------------------------------------------------------------------------- / PageProc_PrintersMore / --------------------- / PageProc for handling the messages for this object. / / In: / pPage -> instance data for this form / hwnd = window handle for the form dialog / uMsg, wParam, lParam = message parameters / / Out: / HRESULT (E_NOTIMPL) if not handled /----------------------------------------------------------------------------*/ HRESULT CALLBACK PageProc_PrintersMore(LPCQPAGE pPage, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { HRESULT hr = S_OK; TraceEnter(TRACE_FORMS, "PageProc_PrintersMore"); switch ( uMsg ) { case CQPM_INITIALIZE: case CQPM_RELEASE: break; case CQPM_ENABLE: EnableWindow( GetDlgItem( hwnd, IDC_PRINTPAGESIZE ), (BOOL)wParam ); EnableWindow( GetDlgItem( hwnd, IDC_PRINTRES ), (BOOL)wParam ); EnableWindow( GetDlgItem( hwnd, IDC_PRINTSPEED ), (BOOL)wParam ); EnableWindow( GetDlgItem( hwnd, IDC_PRINTSPEED_UPDN ), (BOOL)wParam ); EnableWindow( GetDlgItem( hwnd, IDC_PRINTDUPLEX ), (BOOL)wParam ); EnableWindow( GetDlgItem( hwnd, IDC_PRINTCOLOR ), (BOOL)wParam ); EnableWindow( GetDlgItem( hwnd, IDC_PRINTSTAPLE ), (BOOL)wParam ); break; case CQPM_GETPARAMETERS: { LPWSTR pszBuffer = NULL; UINT uLen = 0; // Format the parameters for the 2nd page of the query form, this builds // an LDAP string and then appends it to the string we have in the // existing query parameter block. GetPrinterMoreParameters( hwnd, &uLen, NULL ); if ( uLen ) { hr = LocalAllocStringLenW(&pszBuffer, uLen); if ( SUCCEEDED(hr) ) { GetPrinterMoreParameters( hwnd, &uLen, pszBuffer ); hr = QueryParamsAddQueryString((LPDSQUERYPARAMS*)lParam, pszBuffer ); LocalFreeStringW(&pszBuffer); } FailGracefully(hr, "PageProc_PrintersMore: Failed to build DS argument block"); } break; } case CQPM_CLEARFORM: SetDlgItemText( hwnd, IDC_PRINTPAGESIZE, TEXT("") ); ComboBox_SetCurSel( GetDlgItem( hwnd, IDC_PRINTRES ), 0 ); SendMessage( GetDlgItem( hwnd, IDC_PRINTSPEED_UPDN ), UDM_SETPOS, 0, MAKELPARAM( 1, 0 ) ); Button_SetCheck( GetDlgItem( hwnd, IDC_PRINTDUPLEX ), BST_UNCHECKED ); Button_SetCheck( GetDlgItem( hwnd, IDC_PRINTCOLOR ), BST_UNCHECKED ); Button_SetCheck( GetDlgItem( hwnd, IDC_PRINTSTAPLE ), BST_UNCHECKED ); break; case CQPM_PERSIST: { IPersistQuery* pPersistQuery = (IPersistQuery*)lParam; BOOL fRead = (BOOL)wParam; INT i = 0; TCHAR szBuffer[MAX_PATH]; if ( fRead ) { hr = pPersistQuery->ReadInt( c_szMsPrintersMore, c_szColor, &i ); FailGracefully(hr, "Failed to read color state"); Button_SetCheck( GetDlgItem( hwnd, IDC_PRINTCOLOR ), i ? BST_CHECKED : BST_UNCHECKED ); hr = pPersistQuery->ReadInt( c_szMsPrintersMore, c_szDuplex, &i ); FailGracefully(hr, "Failed to read duplex state"); Button_SetCheck( GetDlgItem( hwnd, IDC_PRINTDUPLEX ), i ? BST_CHECKED : BST_UNCHECKED ); hr = pPersistQuery->ReadInt( c_szMsPrintersMore, c_szStaple, &i ); FailGracefully(hr, "Failed to read staple state"); Button_SetCheck( GetDlgItem( hwnd, IDC_PRINTSTAPLE ), i ? BST_CHECKED : BST_UNCHECKED ); hr = pPersistQuery->ReadInt( c_szMsPrintersMore, c_szResolution, &i ); FailGracefully(hr, "Failed to read resolution state"); ComboBox_SetCurSel( GetDlgItem( hwnd, IDC_PRINTRES ), i ); hr = pPersistQuery->ReadInt( c_szMsPrintersMore, c_szSpeed, &i ); FailGracefully(hr, "Failed to read speed state"); SendMessage( GetDlgItem( hwnd, IDC_PRINTSPEED_UPDN ), UDM_SETPOS, 0, MAKELPARAM( i, 0 ) ); hr = pPersistQuery->ReadString( c_szMsPrintersMore, c_szPaperSize, szBuffer, ARRAYSIZE( szBuffer ) ); FailGracefully(hr, "Failed to read paper size state"); ComboBox_SetText( GetDlgItem( hwnd, IDC_PRINTPAGESIZE ), szBuffer ); } else { i = Button_GetCheck( GetDlgItem( hwnd, IDC_PRINTCOLOR ) ) == BST_CHECKED ? TRUE : FALSE; hr = pPersistQuery->WriteInt( c_szMsPrintersMore, c_szColor, i ); FailGracefully(hr, "Failed to write color state"); i = Button_GetCheck( GetDlgItem( hwnd, IDC_PRINTDUPLEX ) ) == BST_CHECKED ? TRUE : FALSE; hr = pPersistQuery->WriteInt( c_szMsPrintersMore, c_szDuplex, i ); FailGracefully(hr, "Failed to write duplex state"); i = Button_GetCheck( GetDlgItem( hwnd, IDC_PRINTSTAPLE ) ) == BST_CHECKED ? TRUE : FALSE; hr = pPersistQuery->WriteInt( c_szMsPrintersMore, c_szStaple, i ); FailGracefully(hr, "Failed to write staple state"); i = (INT)ComboBox_GetCurSel( GetDlgItem( hwnd, IDC_PRINTRES ) ); hr = pPersistQuery->WriteInt( c_szMsPrintersMore, c_szResolution, i ); FailGracefully(hr, "Failed to write resolution state"); i = (INT)SendMessage( GetDlgItem( hwnd, IDC_PRINTSPEED_UPDN ), UDM_GETPOS, 0, 0 ); hr = pPersistQuery->WriteInt( c_szMsPrintersMore, c_szSpeed, LOWORD(i) ); FailGracefully(hr, "Failed to write speed state"); ComboBox_GetText( GetDlgItem( hwnd, IDC_PRINTPAGESIZE ), szBuffer, ARRAYSIZE( szBuffer ) ); hr = pPersistQuery->WriteString( c_szMsPrintersMore, c_szPaperSize, szBuffer ); FailGracefully(hr, "Failed to write paper size state"); } FailGracefully(hr, "Failed to persist page"); break; } case CQPM_HELP: { LPHELPINFO pHelpInfo = (LPHELPINFO)lParam; WinHelp((HWND)pHelpInfo->hItemHandle, DSQUERY_HELPFILE, HELP_WM_HELP, (DWORD_PTR)aFormHelpIDs); break; } case DSQPM_GETCLASSLIST: // the PageProc_Printers will have already handled this, no need to do it again! (daviddv, 19jun98) break; default: hr = E_NOTIMPL; break; } exit_gracefully: TraceLeaveResult(hr); } /*----------------------------------------------------------------------------- / DlgProc_Printers / ---------------- / Standard dialog proc for the form, handle any special buttons and other / such nastyness we must here. / / In: / hwnd, uMsg, wParam, lParam = standard parameters / / Out: / INT_PTR /----------------------------------------------------------------------------*/ INT_PTR CALLBACK DlgProc_PrintersMore(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR fResult = FALSE; LPCQPAGE pQueryPage = NULL; if ( uMsg == WM_INITDIALOG ) { pQueryPage = (LPCQPAGE)lParam; SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)pQueryPage); // // Fill in the printer forms combo-box. // PopulatePrintPageSize( hwnd ); // // Fill in the print speed combo-box. // PopulatePrintSpeed( hwnd ); // // Fill in the print speed combo-box. // PopulatePrintResolution( hwnd ); } else if ( uMsg == WM_CONTEXTMENU ) { WinHelp((HWND)wParam, DSQUERY_HELPFILE, HELP_CONTEXTMENU, (DWORD_PTR)aFormHelpIDs); fResult = TRUE; } return fResult; }