windows-nt/Source/XPSP1/NT/shell/ext/dsui/dsquery/qf_print.cpp
2020-09-26 16:20:57 +08:00

1975 lines
58 KiB
C++

#include "pch.h"
#pragma hdrstop
#include <initguid.h>
#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<LPTHREAD_START_ROUTINE>(CPrintQueryPage::_PhysicalLocationThread),
reinterpret_cast<LPVOID>( 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<CPrintQueryPage *>( 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<CPrintQueryPage *>(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<CPrintQueryPage *>(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<CPrintQueryPage *>(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<CPrintQueryPage *>(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<CPrintQueryPage *>(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<LONG_PTR>(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;
}