741 lines
18 KiB
C++
741 lines
18 KiB
C++
//
|
|
// Copyright 1997 - Microsoft
|
|
//
|
|
|
|
//
|
|
// DPGUIDQY.CPP - The duplicate GUID query form
|
|
//
|
|
|
|
#include "pch.h"
|
|
|
|
#include "dpguidqy.h"
|
|
#include "mangdlg.h"
|
|
|
|
DEFINE_MODULE("IMADMUI")
|
|
DEFINE_THISCLASS("CRIQueryForm")
|
|
#define THISCLASS CRIQueryForm
|
|
#define LPTHISCLASS LPCRIQueryForm
|
|
|
|
#define FILTER_QUERY_BOTH L"(&(objectClass=computer)(netbootGUID=%ws*)(netbootMachineFilePath=%s))"
|
|
#define FILTER_QUERY_GUID_ONLY L"(&(objectClass=computer)(netbootGUID=%ws*))"
|
|
#define FILTER_QUERY_SERVER_ONLY L"(&(objectClass=computer)(netbootMachineFilePath=%s))"
|
|
|
|
#define StringByteCopy(pDest, iOffset, sz) \
|
|
{ memcpy(&(((LPBYTE)pDest)[iOffset]), sz, StringByteSize(sz)); }
|
|
|
|
#define StringByteSize(sz) \
|
|
((lstrlen(sz)+1)*sizeof(TCHAR))
|
|
|
|
|
|
DWORD aQueryHelpMap[] = {
|
|
IDC_E_SERVER, HIDC_E_SERVER,
|
|
IDC_E_GUID, HIDC_E_GUID,
|
|
NULL, NULL
|
|
};
|
|
|
|
//
|
|
// CRIQueryForm_CreateInstance( )
|
|
//
|
|
LPVOID
|
|
CRIQueryForm_CreateInstance( void )
|
|
{
|
|
TraceFunc( "CRIQueryForm_CreateInstance()\n" );
|
|
|
|
LPTHISCLASS lpcc = new THISCLASS( );
|
|
if ( !lpcc ) {
|
|
RETURN(lpcc);
|
|
}
|
|
|
|
HRESULT hr = THR( lpcc->Init( ) );
|
|
if ( hr )
|
|
{
|
|
delete lpcc;
|
|
RETURN(NULL);
|
|
}
|
|
|
|
RETURN(lpcc);
|
|
}
|
|
|
|
//
|
|
// Constructor
|
|
//
|
|
THISCLASS::THISCLASS( )
|
|
{
|
|
TraceClsFunc( "CRIQueryForm( )\n" );
|
|
|
|
InterlockIncrement( g_cObjects );
|
|
|
|
TraceFuncExit();
|
|
}
|
|
|
|
//
|
|
// Init( )
|
|
//
|
|
HRESULT
|
|
THISCLASS::Init( )
|
|
{
|
|
TraceClsFunc( "Init( )\n" );
|
|
|
|
HRESULT hr;
|
|
|
|
// IUnknown stuff
|
|
BEGIN_QITABLE_IMP( CRIQueryForm, IQueryForm );
|
|
QITABLE_IMP( IQueryForm );
|
|
END_QITABLE_IMP( CRIQueryForm );
|
|
Assert( _cRef == 0);
|
|
AddRef( );
|
|
|
|
hr = CheckClipboardFormats( );
|
|
|
|
HRETURN(hr);
|
|
}
|
|
|
|
//
|
|
// Destructor
|
|
//
|
|
THISCLASS::~THISCLASS( )
|
|
{
|
|
TraceClsFunc( "~CRIQueryForm( )\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;
|
|
|
|
dw = LoadString( g_hInstance, IDS_REMOTE_INSTALL_CLIENTS, szTitle, ARRAYSIZE(szTitle) );
|
|
Assert(dw);
|
|
|
|
ZeroMemory( &cqf, sizeof(cqf) );
|
|
cqf.cbStruct = sizeof(cqf);
|
|
cqf.dwFlags = CQFF_ISOPTIONAL;
|
|
cqf.clsid = CLSID_RIQueryForm;
|
|
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_CLIENTS;
|
|
cqp.idPageTemplate = IDD_GUID_QUERY_FORM;
|
|
cqp.pDlgProc = PropSheetDlgProc;
|
|
cqp.lParam = (LPARAM)this;
|
|
|
|
hr = THR( pAddPagesProc(lParam, CLSID_RIQueryForm, &cqp) );
|
|
|
|
HRETURN(hr);
|
|
}
|
|
|
|
// ************************************************************************
|
|
//
|
|
// Property Sheet Functions
|
|
//
|
|
// ************************************************************************
|
|
|
|
//
|
|
// PropSheetDlgProc()
|
|
//
|
|
INT_PTR CALLBACK
|
|
THISCLASS::PropSheetDlgProc(
|
|
HWND hDlg,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam )
|
|
{
|
|
//TraceMsg( TEXT("PropSheetDlgProc(") );
|
|
//TraceMsg( TF_FUNC, TEXT(" 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, TEXT("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_NOTIFY:
|
|
TraceMsg( TF_WM, TEXT("WM_NOTIFY\n") );
|
|
return pcc->_OnNotify( wParam, lParam );
|
|
|
|
case WM_COMMAND:
|
|
TraceMsg( TF_WM, TEXT("WM_COMMAND\n") );
|
|
return pcc->_OnCommand( wParam, lParam );
|
|
|
|
case WM_HELP:// F1
|
|
{
|
|
LPHELPINFO phelp = (LPHELPINFO) lParam;
|
|
WinHelp( (HWND) phelp->hItemHandle, g_cszHelpFile, HELP_WM_HELP, (DWORD_PTR) &aQueryHelpMap );
|
|
}
|
|
break;
|
|
|
|
case WM_CONTEXTMENU: // right mouse click
|
|
WinHelp((HWND) wParam, g_cszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR) &aQueryHelpMap );
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// PropSheetPageProc()
|
|
//
|
|
HRESULT CALLBACK
|
|
THISCLASS::PropSheetPageProc(
|
|
LPCQPAGE pQueryPage,
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
TraceClsFunc( "PropSheetPageProc( " );
|
|
TraceMsg( TF_FUNC, TEXT("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_GUID ), (BOOL)wParam );
|
|
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_GUID, L"" );
|
|
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 );
|
|
if ( wParam && lParam )
|
|
{
|
|
VARIANT var;
|
|
LPOPENQUERYWINDOW poqwi = (LPOPENQUERYWINDOW) lParam;
|
|
IPropertyBag * ppb = poqwi->ppbFormParameters;
|
|
Assert( ppb );
|
|
VariantInit( &var );
|
|
|
|
hr = ppb->Read( L"ServerName", &var, NULL );
|
|
if (SUCCEEDED( hr ))
|
|
{
|
|
SetDlgItemText( hwnd, IDC_E_SERVER, V_BSTR( &var ) );
|
|
VariantClear( &var );
|
|
}
|
|
|
|
hr = ppb->Read( L"ClientGuid", &var, NULL );
|
|
if (SUCCEEDED( hr ))
|
|
{
|
|
SetDlgItemText( hwnd, IDC_E_GUID, V_BSTR( &var ) );
|
|
VariantClear( &var );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebugMsg( "No default parameters given.\n" );
|
|
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_GUID ), MAX_INPUT_GUID_STRING - 1 );
|
|
Edit_LimitText( GetDlgItem( _hDlg, IDC_E_SERVER), DNS_MAX_NAME_LENGTH );
|
|
|
|
HRETURN(S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// _OnCommand( )
|
|
//
|
|
INT
|
|
THISCLASS::_OnCommand( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
TraceClsFunc( "_OnCommand( " );
|
|
TraceMsg( TF_FUNC, "wParam = 0x%p, lParam = 0x%p )\n", wParam, lParam );
|
|
|
|
#if 0
|
|
switch ( LOWORD(wParam) )
|
|
{
|
|
}
|
|
#endif
|
|
|
|
RETURN(FALSE);
|
|
}
|
|
|
|
//
|
|
// _OnNotify( )
|
|
//
|
|
INT
|
|
THISCLASS::_OnNotify(
|
|
WPARAM wParam,
|
|
LPARAM lParam )
|
|
{
|
|
TraceClsFunc( "_OnNotify( " );
|
|
TraceMsg( TF_FUNC, "wParam = 0x%p, lParam = 0x%p )\n", wParam, lParam );
|
|
|
|
LPNMHDR lpnmhdr = (LPNMHDR) lParam;
|
|
TraceMsg( TF_WM, "NMHDR: HWND = 0x%p, idFrom = 0x%08x, code = 0x%08x\n",
|
|
lpnmhdr->hwndFrom, lpnmhdr->idFrom, lpnmhdr->code );
|
|
|
|
#if 0
|
|
switch( lpnmhdr->code )
|
|
{
|
|
}
|
|
#endif
|
|
|
|
RETURN(FALSE);
|
|
}
|
|
|
|
struct
|
|
{
|
|
INT fmt;
|
|
INT cx;
|
|
INT uID;
|
|
LPCTSTR pDisplayProperty;
|
|
}
|
|
columns[] =
|
|
{
|
|
0, 20, IDS_NAME, TEXT("cn"),
|
|
0, 50, IDS_GUID, TEXT("netbootGuid"),
|
|
};
|
|
|
|
//
|
|
// _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 szGuid[MAX_INPUT_GUID_STRING * 2]; // room for escaped GUID
|
|
WCHAR szFilter[ARRAYSIZE(szGuid)+ARRAYSIZE(szServer)+ARRAYSIZE(FILTER_QUERY_BOTH)];
|
|
BYTE uGuid[ 16 ];
|
|
DWORD uGuidLength;
|
|
ULONG offset;
|
|
BOOL fIncludeGuid = FALSE, fIncludeServer = 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
|
|
|
|
//
|
|
// This is how searches are done:
|
|
// - if both guid and server are left blank, search for all
|
|
// accounts with netbootGuid specified (all managed computers).
|
|
// - if either or both are specified, search for all computers
|
|
// that match.
|
|
// - if guid is specified as '*', treat it the same as if it had
|
|
// been left blank (searches for all accounts with netbootGUID).
|
|
//
|
|
// Note that currently any account with a server in netbootMachineFilePath
|
|
// will also have netbootGUID specified, because prestaging a
|
|
// remote install computer always puts netbootGUID, and that is
|
|
// the only way that netbootMachineFilePath will be set. So if the
|
|
// user specifies a server but no guid, we don't need to include
|
|
// netbootGUID=* in our ldap filter.
|
|
//
|
|
|
|
// Compute the size of the argument block
|
|
if ( GetDlgItemText( hWnd, IDC_E_GUID, szGuid, ARRAYSIZE(szGuid)) )
|
|
{
|
|
//
|
|
// Allow only a * as the GUID, to search for all machines with
|
|
// a GUID.
|
|
//
|
|
|
|
if (wcscmp(szGuid, L"*") != 0)
|
|
{
|
|
if ( ValidateGuid(szGuid,uGuid,&uGuidLength) == E_FAIL || !uGuidLength ) {
|
|
MessageBoxFromStrings( hWnd,
|
|
IDS_INVALID_GUID_CAPTION,
|
|
IDS_INVALID_PARTIAL_GUID_TEXT,
|
|
MB_OK );
|
|
hr = E_INVALIDARG;
|
|
goto Error;
|
|
}
|
|
|
|
ZeroMemory( szGuid, sizeof(szGuid) );
|
|
ldap_escape_filter_element((PCHAR)uGuid, uGuidLength, szGuid, sizeof(szGuid) );
|
|
}
|
|
else
|
|
{
|
|
szGuid[0] = L'\0'; // the filter adds a *, and "**" doesn't work, so blank it here
|
|
}
|
|
|
|
fIncludeGuid = TRUE;
|
|
|
|
}
|
|
|
|
if ( GetDlgItemText( hWnd, IDC_E_SERVER, szServer, ARRAYSIZE(szServer)) )
|
|
{
|
|
fIncludeServer = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If no server or guid was specified, search for any guid.
|
|
//
|
|
if (!fIncludeGuid)
|
|
{
|
|
szGuid[0] = L'\0';
|
|
fIncludeGuid = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( fIncludeGuid && fIncludeServer )
|
|
{
|
|
wsprintf( szFilter, FILTER_QUERY_BOTH, szGuid, szServer );
|
|
}
|
|
else if ( fIncludeGuid )
|
|
{
|
|
wsprintf( szFilter, FILTER_QUERY_GUID_ONLY, szGuid );
|
|
}
|
|
else if ( fIncludeServer )
|
|
{
|
|
wsprintf( szFilter, FILTER_QUERY_SERVER_ONLY, szServer );
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
{
|
|
AssertMsg( 0, "How did we get here?\n" );
|
|
szFilter[0] = L'\0';
|
|
}
|
|
#endif // DEBUG
|
|
|
|
DebugMsg( "RI Filter: %s\n", szFilter );
|
|
|
|
// compute the size of the new query block
|
|
if ( !*ppdsqp )
|
|
{
|
|
offset = cbStruct = sizeof(DSQUERYPARAMS) + ((ARRAYSIZE(columns)-1)*sizeof(DSCOLUMN));
|
|
cbStruct += StringByteSize(szFilter);
|
|
for ( i = 0; i < ARRAYSIZE(columns); i++ )
|
|
{
|
|
cbStruct += StringByteSize(columns[i].pDisplayProperty);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LPWSTR pszQuery;
|
|
pszQuery = (LPWSTR) ((LPBYTE)(*ppdsqp) + (*ppdsqp)->offsetQuery);
|
|
offset = (*ppdsqp)->cbStruct;
|
|
cbStruct = (*ppdsqp)->cbStruct + StringByteSize( pszQuery ) + StringByteSize( szFilter );
|
|
}
|
|
|
|
// 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 ( !*ppdsqp)
|
|
{ // no... create our own query
|
|
pDsQueryParams->cbStruct = cbStruct;
|
|
pDsQueryParams->dwFlags = 0;
|
|
pDsQueryParams->hInstance = g_hInstance;
|
|
pDsQueryParams->offsetQuery = offset;
|
|
pDsQueryParams->iColumns = ARRAYSIZE(columns);
|
|
|
|
// 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(columns); i++ )
|
|
{
|
|
pDsQueryParams->aColumns[i].fmt = columns[i].fmt;
|
|
pDsQueryParams->aColumns[i].cx = columns[i].cx;
|
|
pDsQueryParams->aColumns[i].idsName = columns[i].uID;
|
|
pDsQueryParams->aColumns[i].offsetProperty = offset;
|
|
|
|
StringByteCopy(pDsQueryParams, offset, columns[i].pDisplayProperty);
|
|
offset += StringByteSize(columns[i].pDisplayProperty);
|
|
}
|
|
}
|
|
else
|
|
{ // yes... 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;
|
|
|
|
#if 0
|
|
// add our columns
|
|
for ( i = 0 ; i < ARRAYSIZE(columns); i++ )
|
|
{
|
|
pDsQueryParams->aColumns[n+i].fmt = columns[i].fmt;
|
|
pDsQueryParams->aColumns[n+i].cx = columns[i].cx;
|
|
pDsQueryParams->aColumns[n+i].idsName = columns[i].uID;
|
|
pDsQueryParams->aColumns[n+i].offsetProperty = offset;
|
|
|
|
StringByteCopy(pDsQueryParams, offset, columns[i].pDisplayProperty);
|
|
offset += StringByteSize(columns[i].pDisplayProperty);
|
|
}
|
|
#endif
|
|
// new query location
|
|
pDsQueryParams->offsetQuery = offset;
|
|
pszQuery = (LPWSTR) ((LPBYTE)(*ppdsqp) + (*ppdsqp)->offsetQuery);
|
|
pszNewQuery = (LPWSTR) ((LPBYTE)pDsQueryParams + offset);
|
|
Assert( pszQuery );
|
|
|
|
// append to their query
|
|
if ( StrCmpN( pszQuery, L"(&", 2 ) == 0 )
|
|
{
|
|
pszQuery[ wcslen( pszQuery ) - 1 ] = L'\0'; // remove ")"
|
|
}
|
|
else
|
|
{
|
|
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 )
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
goto Cleanup;
|
|
}
|