|
|
//
// Copyright 1997 - Microsoft
//
//
// SERVERQY.CPP - The RIS server query form
//
#include "pch.h"
#include "serverqy.h"
#include "mangdlg.h"
DEFINE_MODULE("IMADMUI") DEFINE_THISCLASS("CRISrvQueryForm") #define THISCLASS CRISrvQueryForm
#define LPTHISCLASS LPCRISrvQueryForm
#define FILTER_QUERY_SERVER L"(&(objectClass=computer)(netbootSCPBL=*)(CN=%s))"
#define StringByteCopy(pDest, iOffset, sz) \
{ memcpy(&(((LPBYTE)pDest)[iOffset]), sz, StringByteSize(sz)); }
#define StringByteSize(sz) \
((wcslen(sz)+1)*sizeof(WCHAR))
DWORD aSrvQueryHelpMap[] = { IDC_E_SERVER, HIDC_E_SERVER, NULL, NULL };
//
// CRISrvQueryForm_CreateInstance( )
//
LPVOID CRISrvQueryForm_CreateInstance( void ) { TraceFunc( "CRISrvQueryForm_CreateInstance()\n" );
LPTHISCLASS lpcc = new THISCLASS( ); if ( !lpcc ) { RETURN(lpcc); }
HRESULT hr = THR( lpcc->Init( ) ); if ( FAILED(hr) ) { delete lpcc; RETURN(NULL); }
RETURN(lpcc); }
//
// Constructor
//
THISCLASS::THISCLASS( ) { TraceClsFunc( "CRISrvQueryForm( )\n" );
InterlockIncrement( g_cObjects );
TraceFuncExit(); }
//
// Init( )
//
HRESULT THISCLASS::Init( ) { TraceClsFunc( "Init( )\n" );
HRESULT hr;
// IUnknown stuff
BEGIN_QITABLE_IMP( CRISrvQueryForm, IQueryForm ); QITABLE_IMP( IQueryForm ); END_QITABLE_IMP( CRISrvQueryForm ); Assert( _cRef == 0); AddRef( );
hr = CheckClipboardFormats( );
HRETURN(hr); }
//
// Destructor
//
THISCLASS::~THISCLASS( ) { TraceClsFunc( "~CRISrvQueryForm( )\n" );
InterlockDecrement( g_cObjects );
TraceFuncExit(); }
// ************************************************************************
//
// IUnknown
//
// ************************************************************************
//
// QueryInterface()
//
STDMETHODIMP THISCLASS::QueryInterface( REFIID riid, LPVOID *ppv ) { TraceClsFunc( "" );
HRESULT hr = ::QueryInterface( this, _QITable, riid, ppv );
QIRETURN( hr, riid ); }
//
// AddRef()
//
STDMETHODIMP_(ULONG) THISCLASS::AddRef( void ) { TraceClsFunc( "[IUnknown] AddRef( )\n" );
InterlockIncrement( _cRef );
RETURN(_cRef); }
//
// Release()
//
STDMETHODIMP_(ULONG) THISCLASS::Release( void ) { TraceClsFunc( "[IUnknown] Release( )\n" );
InterlockDecrement( _cRef );
if ( _cRef ) RETURN(_cRef);
TraceDo( delete this );
RETURN(0); }
// ************************************************************************
//
// IQueryForm
//
// ************************************************************************
//
// Initialize( )
//
STDMETHODIMP THISCLASS::Initialize( HKEY hkForm) { TraceClsFunc( "[IQueryForm] Initialize( )\n" );
HRETURN(S_OK); }
//
// SetObject( )
//
STDMETHODIMP THISCLASS::AddForms( LPCQADDFORMSPROC pAddFormsProc, LPARAM lParam ) { TraceClsFunc( "[IQueryForm] AddForms(" ); TraceMsg( TF_FUNC, " pAddFormsProc = 0x%p, lParam = 0x%p )\n", pAddFormsProc, lParam );
if ( !pAddFormsProc ) HRETURN(E_INVALIDARG);
HRESULT hr = S_OK; CQFORM cqf; WCHAR szTitle[ 255 ]; DWORD dw;
if (!LoadString( g_hInstance, IDS_REMOTE_INSTALL_SERVERS, szTitle, ARRAYSIZE(szTitle))) { HRETURN(HRESULT_FROM_WIN32(GetLastError())); }
ZeroMemory( &cqf, sizeof(cqf) ); cqf.cbStruct = sizeof(cqf); cqf.dwFlags = CQFF_ISOPTIONAL; cqf.clsid = CLSID_RISrvQueryForm; cqf.pszTitle = szTitle;
hr = THR( pAddFormsProc(lParam, &cqf) );
HRETURN(hr); }
//
// AddPages( )
//
STDMETHODIMP THISCLASS::AddPages( LPCQADDPAGESPROC pAddPagesProc, LPARAM lParam) { TraceClsFunc( "[IQueryForm] AddPages(" ); TraceMsg( TF_FUNC, " pAddPagesProc = 0x%p, lParam = 0x%p )\n", pAddPagesProc, lParam );
if ( !pAddPagesProc ) HRETURN(E_INVALIDARG);
HRESULT hr = S_OK; CQPAGE cqp;
cqp.cbStruct = sizeof(cqp); cqp.dwFlags = 0x0; cqp.pPageProc = (LPCQPAGEPROC) PropSheetPageProc; cqp.hInstance = g_hInstance; cqp.idPageName = IDS_REMOTE_INSTALL_SERVERS; cqp.idPageTemplate = IDD_SERVER_QUERY_FORM; cqp.pDlgProc = PropSheetDlgProc; cqp.lParam = (LPARAM)this;
hr = THR( pAddPagesProc(lParam, CLSID_RISrvQueryForm, &cqp) );
HRETURN(hr); }
// ************************************************************************
//
// Property Sheet Functions
//
// ************************************************************************
//
// PropSheetDlgProc()
//
INT_PTR CALLBACK THISCLASS::PropSheetDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { //TraceMsg( L"PropSheetDlgProc(" );
//TraceMsg( TF_FUNC, L" hDlg = 0x%p, uMsg = 0x%p, wParam = 0x%p, lParam = 0x%p )\n",
// hDlg, uMsg, wParam, lParam );
LPTHISCLASS pcc = (LPTHISCLASS) GetWindowLongPtr( hDlg, GWLP_USERDATA );
if ( uMsg == WM_INITDIALOG ) { TraceMsg( TF_WM, L"WM_INITDIALOG\n");
CQPAGE * pcqp = (CQPAGE *) lParam; SetWindowLongPtr( hDlg, GWLP_USERDATA, pcqp->lParam ); pcc = (LPTHISCLASS) pcqp->lParam; pcc->_InitDialog( hDlg, lParam ); }
if (pcc) { Assert( hDlg == pcc->_hDlg );
switch ( uMsg ) {
case WM_HELP:// F1
{ LPHELPINFO phelp = (LPHELPINFO) lParam; WinHelp( (HWND) phelp->hItemHandle, g_cszHelpFile, HELP_WM_HELP, (DWORD_PTR) &aSrvQueryHelpMap ); } break; case WM_CONTEXTMENU: // right mouse click
WinHelp((HWND) wParam, g_cszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR) &aSrvQueryHelpMap ); break; } }
return FALSE; }
//
// PropSheetPageProc()
//
HRESULT CALLBACK THISCLASS::PropSheetPageProc( LPCQPAGE pQueryPage, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { TraceClsFunc( "PropSheetPageProc( " ); TraceMsg( TF_FUNC, L"pQueryPage = 0x%p, hwnd = 0x%p, uMsg = 0x%p, wParam= 0x%p, lParam = 0x%p )\n", pQueryPage, hwnd, uMsg, wParam, lParam );
HRESULT hr = E_NOTIMPL; Assert( pQueryPage ); LPTHISCLASS pQueryForm = (LPTHISCLASS )pQueryPage->lParam; Assert( pQueryForm );
switch ( uMsg ) { // Initialize so AddRef the object we are associated with so that
// we don't get unloaded.
case CQPM_INITIALIZE: TraceMsg( TF_WM, "CQPM_INITIALIZE\n" ); pQueryForm->AddRef(); hr = S_OK; break;
// Release, therefore Release the object we are associated with to
// ensure correct destruction etc.
case CQPM_RELEASE: TraceMsg( TF_WM, "CQPM_RELEASE\n" ); SetWindowLongPtr( pQueryForm->_hDlg, GWLP_USERDATA, NULL ); pQueryForm->Release(); hr = S_OK; break;
// Enable so fix the state of our two controls within the window.
case CQPM_ENABLE: TraceMsg( TF_WM, "CQPM_ENABLE\n" ); EnableWindow( GetDlgItem( hwnd, IDC_E_SERVER ), (BOOL)wParam ); hr = S_OK; break;
// Fill out the parameter structure to return to the caller, this is
// handler specific. In our case we constructure a query of the CN
// and objectClass properties, and we show a columns displaying both
// of these. For further information about the DSQUERYPARAMs structure
// see dsquery.h
case CQPM_GETPARAMETERS: TraceMsg( TF_WM, "CQPM_GETPARAMETERS\n" ); hr = pQueryForm->_GetQueryParams( hwnd, (LPDSQUERYPARAMS*)lParam ); break;
// Clear form, therefore set the window text for these two controls
// to zero.
case CQPM_CLEARFORM: TraceMsg( TF_WM, "CQPM_CLEARFORM\n" ); SetDlgItemText( hwnd, IDC_E_SERVER, L"" ); hr = S_OK; break;
case CQPM_SETDEFAULTPARAMETERS: TraceMsg( TF_WM, "CQPM_SETDEFAULTPARAMETERS: wParam = %s lParam = 0x%p\n", BOOLTOSTRING(wParam), lParam ); SetDlgItemText( hwnd, IDC_E_SERVER, L"*" ); hr = S_OK; break;
default: TraceMsg( TF_WM, "CQPM_message 0x%08x *** NOT IMPL ***\n", uMsg ); hr = E_NOTIMPL; break; }
RETURN(hr); }
//
// _OnPSPCB_Create( )
//
HRESULT THISCLASS::_OnPSPCB_Create( ) { TraceClsFunc( "_OnPSPCB_Create( )\n" );
HRETURN(S_OK); } //
// _InitDialog( )
//
HRESULT THISCLASS::_InitDialog( HWND hDlg, LPARAM lParam ) { TraceClsFunc( "_InitDialog( )\n" );
_hDlg = hDlg; Edit_LimitText( GetDlgItem( _hDlg, IDC_E_SERVER), DNS_MAX_NAME_LENGTH );
HRETURN(S_OK); }
struct { INT fmt; INT cx; INT uID; PCWSTR pDisplayProperty; } srvcolumns[] = { 0, 20, IDS_NAME, L"cn", };
//
// _GetQueryParams( )
//
HRESULT THISCLASS::_GetQueryParams( HWND hWnd, LPDSQUERYPARAMS* ppdsqp ) { TraceClsFunc( "_GetQueryParams( )\n" );
if ( !ppdsqp ) HRETURN(E_POINTER);
HRESULT hr = S_OK; INT i; WCHAR szServer[DNS_MAX_NAME_BUFFER_LENGTH]; WCHAR szFilter[ARRAYSIZE(FILTER_QUERY_SERVER)+ARRAYSIZE(szServer)]; ULONG offset; BOOL CallerSpecifiedQuery; BOOL CallerQueryStartsWithAmpersand = FALSE; ULONG cbStruct = 0; LPDSQUERYPARAMS pDsQueryParams = NULL;
#if 0
if ( *ppdsqp ) { // This page doesn't support appending its query data to an
// existing DSQUERYPARAMS strucuture, only creating a new block,
// therefore bail if we see the pointer is not NULL.
hr = THR(E_INVALIDARG); goto Error; } #endif
if (!GetDlgItemText( hWnd, IDC_E_SERVER, szServer, ARRAYSIZE(szServer))) { wcscpy( szServer, L"*"); }
if (_snwprintf( szFilter, ARRAYSIZE(szFilter), FILTER_QUERY_SERVER, szServer) < 0) { hr = THR(E_INVALIDARG); goto Error; }
szFilter[ARRAYSIZE(szFilter) -1] = L'\0'; DebugMsg( "RI Filter: %s\n", szFilter );
// compute the size of the new query block
// Did they hand in a query that we need to modify?
if ( !*ppdsqp ) { CallerSpecifiedQuery = FALSE; //bugbug arraysize(srvcolumns)-1) == 0?
offset = cbStruct = sizeof(DSQUERYPARAMS) + ((ARRAYSIZE(srvcolumns)-1)*sizeof(DSCOLUMN)); cbStruct += StringByteSize(szFilter); for ( i = 0; i < ARRAYSIZE(srvcolumns); i++ ) { cbStruct += StringByteSize(srvcolumns[i].pDisplayProperty); } } else { CallerSpecifiedQuery = TRUE; LPWSTR pszQuery = (LPWSTR) ((LPBYTE)(*ppdsqp) + (*ppdsqp)->offsetQuery); offset = (*ppdsqp)->cbStruct; //
// save off the size that we're gonna need.
// note that when we concatenate the current query with our query,
// we need to make sure the query starts with "(&". If it doesn't
// already, then we make this the case -- the buffer szFilter contains
// these bytes, which ensures that cbStruct is large enough. If the current
// query contains these strings, then the allocated buffer is a little
// bigger than it needs to be.
cbStruct = (*ppdsqp)->cbStruct + StringByteSize( pszQuery ) + StringByteSize( szFilter ); //
// do some extra query validation.
// does the query start with "(&"?
//
if (pszQuery[0] == L'(' && pszQuery[1] == L'&' ) { CallerQueryStartsWithAmpersand = TRUE; //
// we're assuming below that if the specified query
// doesn't start with "(&", that it will end with ")".
// If that's not the case then bail out.
//
Assert( pszQuery[ wcslen( pszQuery ) - 1 ] == L')' ); if (pszQuery[ wcslen( pszQuery ) - 1 ] != L')' ) { hr = E_INVALIDARG; goto Error; } } else { //
// conversely, if the query doesn't start with '(&', then
// we assume that the query doesn't end with ')', and if it
// does, we bail
//
CallerQueryStartsWithAmpersand = FALSE; Assert( pszQuery[ wcslen( pszQuery ) - 1 ] != L')' ); if (pszQuery[ wcslen( pszQuery ) - 1 ] == L')' ) { hr = E_INVALIDARG; goto Error; } } }
// Allocate it and populate it with the data, the header is fixed
// but the strings are referenced by offset.
pDsQueryParams = (LPDSQUERYPARAMS)CoTaskMemAlloc(cbStruct); if ( !pDsQueryParams ) { hr = E_OUTOFMEMORY; goto Error; }
// Did they hand in a query that we need to modify?
if ( !CallerSpecifiedQuery) { // no... create our own query
pDsQueryParams->cbStruct = cbStruct; pDsQueryParams->dwFlags = 0; pDsQueryParams->hInstance = g_hInstance; pDsQueryParams->offsetQuery = offset; pDsQueryParams->iColumns = ARRAYSIZE(srvcolumns);
// Copy the filter string and bump the offset
StringByteCopy(pDsQueryParams, offset, szFilter); offset += StringByteSize(szFilter);
// Fill in the array of columns to dispaly, the cx is a percentage of the
// current view, the propertie names to display are UNICODE strings and
// are referenced by offset, therefore we bump the offset as we copy
// each one.
for ( i = 0 ; i < ARRAYSIZE(srvcolumns); i++ ) { pDsQueryParams->aColumns[i].fmt = srvcolumns[i].fmt; pDsQueryParams->aColumns[i].cx = srvcolumns[i].cx; pDsQueryParams->aColumns[i].idsName = srvcolumns[i].uID; pDsQueryParams->aColumns[i].offsetProperty = offset;
StringByteCopy(pDsQueryParams, offset, srvcolumns[i].pDisplayProperty); offset += StringByteSize(srvcolumns[i].pDisplayProperty); } } else { // yes, caller specified a query... add our parameters to the query
LPWSTR pszQuery; LPWSTR pszNewQuery; INT n;
// duplicate the existing query
Assert( offset == (*ppdsqp)->cbStruct ); CopyMemory( pDsQueryParams, *ppdsqp, offset ); pDsQueryParams->cbStruct = cbStruct;
// new query location
pDsQueryParams->offsetQuery = offset; pszQuery = (LPWSTR) ((LPBYTE)(*ppdsqp) + (*ppdsqp)->offsetQuery); pszNewQuery = (LPWSTR) ((LPBYTE)pDsQueryParams + offset); Assert( pszQuery );
// append to their query
if ( CallerQueryStartsWithAmpersand ) { //
// remove ")" from current query so that we can
// add in our additional filter. We've got the trailing ")" in our
// filter.
// Also note that we can't really fail at this point, and we're
// about to free the caller's memory so it's ok for us to overwrite their
// query text.
//
Assert( pszQuery[ wcslen( pszQuery ) - 1 ] == L')' ); pszQuery[ wcslen( pszQuery ) - 1 ] = L'\0'; // remove ")"
// start with their query
wcscpy(pszNewQuery, pszQuery);
//
// put it back to be a good citizen ")"
//
pszQuery[ wcslen( pszQuery )] = L')';
//
// now tack on our query, skipping the "(&" part
//
wcscat(pszNewQuery,&szFilter[2]);
} else { Assert( pszQuery[ wcslen( pszQuery ) - 1 ] != L')' ); wcscpy( pszNewQuery, L"(&" ); // add "(&" to begining of query
wcscat( pszNewQuery, pszQuery ); // add their query
wcscat( pszNewQuery, &szFilter[2] ); // add our query starting after the "(&"
}
offset += StringByteSize( pszNewQuery ); // compute new offset
DebugMsg( "New Query String: %s\n", pszNewQuery );
// Cleanup
CoTaskMemFree( *ppdsqp ); }
// Success
*ppdsqp = pDsQueryParams; Assert( hr == S_OK );
Cleanup: HRETURN(hr); Error: if ( pDsQueryParams ) CoTaskMemFree( pDsQueryParams );
// If we aren't modifying the query and there wasn't
// a query handed into us, indicate failure instead.
if ( hr == S_FALSE && !*ppdsqp ) { Assert(FALSE); // how did we get here?
hr = E_FAIL; } goto Cleanup; }
|