windows-nt/Source/XPSP1/NT/net/mmc/mprsnap/qryfrm.cpp
2020-09-26 16:20:57 +08:00

570 lines
17 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: qryfrm.cpp
//
//--------------------------------------------------------------------------
// QryFrm.cpp : Implementation of CRRASQueryForm
#include "stdafx.h"
#include <cmnquryp.h>
#include "QryFrm.h"
#include "dlggen.h"
#include "dlgadv.h"
COLUMNINFO RRASColumn[] =
{
{0, 40, IDS_QRY_COL_CN, 0, ATTR_NAME_DN},
{0, 30, IDS_QRY_COL_OBJECTCLASS, 1, ATTR_NAME_OBJECTCLASS},
{0, 30, IDS_QRY_COL_RRASATTRIBUTE, 2, ATTR_NAME_RRASATTRIBUTE},
};
int cRRASColumn = 3;
/////////////////////////////////////////////////////////////////////////////
// CRRASQueryForm
//=========================================================================
// IQueryForm methods
HRESULT PageProc(LPCQPAGE pPage, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HRESULT GetQueryParams(HWND hWnd, LPDSQUERYPARAMS* ppDsQueryParams);
STDMETHODIMP CRRASQueryForm::Initialize(HKEY hkForm)
{
// This method is called to initialize the query form object, it is called before
// any pages are added. hkForm should be ignored, in the future however it
// will be a way to persist form state.
HRESULT hr = S_OK;
return hr;
}
STDMETHODIMP CRRASQueryForm::AddForms(LPCQADDFORMSPROC pAddFormsProc, LPARAM lParam)
{
CQFORM cqf;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// This method is called to allow the form handler to register its query form(s),
// each form is identifiered by a CLSID and registered via the pAddFormProc. Here
// we are going to register a test form.
// When registering a form which is only applicable to a specific task, eg. Find a Domain
// object, it is advised that the form be marked as hidden (CQFF_ISNEVERLISTED) which
// will cause it not to appear in the form picker control. Then when the
// client wants to use this form, they specify the form identifier and ask for the
// picker control to be hidden.
if ( !pAddFormsProc )
return E_INVALIDARG;
cqf.cbStruct = sizeof(cqf);
cqf.dwFlags = CQFF_NOGLOBALPAGES | CQFF_ISNEVERLISTED;
cqf.clsid = CLSID_RRASQueryForm;
cqf.hIcon = NULL;
CString title;
title.LoadString(IDS_QRY_TITLE_RRASQUERYFORM);
cqf.pszTitle = (LPCTSTR)title;
return pAddFormsProc(lParam, &cqf);
}
STDMETHODIMP CRRASQueryForm::AddPages(LPCQADDPAGESPROC pAddPagesProc, LPARAM lParam)
{
HRESULT hr = S_OK;
CQPAGE cqp;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// AddPages is called after AddForms, it allows us to add the pages for the
// forms we have registered. Each page is presented on a seperate tab within
// the dialog. A form is a dialog with a DlgProc and a PageProc.
//
// When registering a page the entire structure passed to the callback is copied,
// the amount of data to be copied is defined by the cbStruct field, therefore
// a page implementation can grow this structure to store extra information. When
// the page dialog is constructed via CreateDialog the CQPAGE strucuture is passed
// as the create param.
if ( !pAddPagesProc )
return E_INVALIDARG;
cqp.cbStruct = sizeof(cqp);
cqp.dwFlags = 0x0;
cqp.pPageProc = PageProc;
cqp.hInstance = _Module.m_hInst;
cqp.idPageName = IDS_QRY_TITLE_GENERALPAGE;
cqp.idPageTemplate = IDD_QRY_GENERAL;
cqp.pDlgProc = DlgProc;
cqp.lParam = (LPARAM)new CDlgGeneral();
hr = pAddPagesProc(lParam, CLSID_RRASQueryForm, &cqp);
if(hr != S_OK)
return hr;
cqp.dwFlags = 0x0;
cqp.pPageProc = PageProc;
cqp.hInstance = _Module.m_hInst;
cqp.idPageName = IDS_QRY_TITLE_ADVANCEDPAGE;
cqp.idPageTemplate = IDD_QRY_ADVANCED;
cqp.pDlgProc = DlgProc;
cqp.lParam = (LPARAM)new CDlgAdvanced();
return pAddPagesProc(lParam, CLSID_RRASQueryForm, &cqp);
}
/*---------------------------------------------------------------------------*/
// The PageProc is used to perform general house keeping and communicate between
// the frame and the page.
//
// All un-handled, or unknown reasons should result in an E_NOIMPL response
// from the proc.
//
// In:
// pPage -> CQPAGE structure (copied from the original passed to pAddPagesProc)
// hwnd = handle of the dialog for the page
// uMsg, wParam, lParam = message parameters for this event
//
// Out:
// HRESULT
//
// uMsg reasons:
// ------------
// CQPM_INIIIALIZE
// CQPM_RELEASE
// These are issued as a result of the page being declared or freed, they
// allow the caller to AddRef, Release or perform basic initialization
// of the form object.
//
// CQPM_ENABLE
// Enable is when the query form needs to enable or disable the controls
// on its page. wParam contains TRUE/FALSE indicating the state that
// is required.
//
// CQPM_GETPARAMETERS
// To collect the parameters for the query each page on the active form
// receives this event. lParam is an LPVOID* which is set to point to the
// parameter block to pass to the handler, if the pointer is non-NULL
// on entry the form needs to appened its query information to it. The
// parameter block is handler specific.
//
// Returning S_FALSE from this event causes the query to be canceled.
//
// CQPM_CLEARFORM
// When the page window is created for the first time, or the user clicks
// the clear search the page receives a CQPM_CLEARFORM notification, at
// which point it needs to clear out the edit controls it has and
// return to a default state.
//
// CQPM_PERSIST:
// When loading of saving a query, each page is called with an IPersistQuery
// interface which allows them to read or write the configuration information
// to save or restore their state. lParam is a pointer to the IPersistQuery object,
// and wParam is TRUE/FALSE indicating read or write accordingly.
HRESULT PageProc(LPCQPAGE pQueryPage, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HRESULT hr = S_OK;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CQryDialog* pDialog = (CQryDialog*)pQueryPage->lParam;
ASSERT(pDialog);
switch ( uMsg )
{
// Initialize so AddRef the object we are associated with so that
// we don't get unloaded.
case CQPM_INITIALIZE:
break;
// Changed from qform sample to detach the hwnd, and delete the CDialog
// ensure correct destruction etc.
case CQPM_RELEASE:
pDialog->Detach();
SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM)0);
delete pDialog;
break;
// Enable so fix the state of our two controls within the window.
case CQPM_ENABLE:
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:
hr = pDialog->GetQueryParams((LPDSQUERYPARAMS*)lParam);
break;
// Clear form, therefore set the window text for these two controls
// to zero.
case CQPM_CLEARFORM:
hr = pDialog->ClearForm();
break;
// persistance is not currently supported by this form.
case CQPM_PERSIST:
{
BOOL fRead = (BOOL)wParam;
IPersistQuery* pPersistQuery = (IPersistQuery*)lParam;
if ( !pPersistQuery )
return E_INVALIDARG;
hr = pDialog->Persist(pPersistQuery, fRead);
break;
}
default:
hr = E_NOTIMPL;
break;
}
return hr;
}
/*---------------------------------------------------------------------------*/
// The DlgProc is a standard Win32 dialog proc associated with the form
// window.
INT_PTR CALLBACK DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPCQPAGE pQueryPage;
CQryDialog* pDialog;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if ( uMsg == WM_INITDIALOG )
{
// changed from qForm sample to save CDialog pointer
// in the DWL_USER field of the dialog box instance.
pQueryPage = (LPCQPAGE)lParam;
pDialog = (CQryDialog*)pQueryPage->lParam;
pDialog->Attach(hwnd);
SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM)pDialog);
return pDialog->OnInitDialog();
}
else
{
// CDialog pointer is stored in DWL_USER
// dialog structure, note however that in some cases this will
// be NULL as it is set on WM_INITDIALOG.
pDialog = (CQryDialog*)GetWindowLongPtr(hwnd, DWLP_USER);
}
if(!pDialog)
return FALSE;
else
return AfxCallWndProc(pDialog, hwnd, uMsg, wParam, lParam);
}
/*---------------------------------------------------------------------------*/
// Build a parameter block to pass to the query handler. Each page is called
// with a pointer to a pointer which it must update with the revised query
// block. For the first page this pointer is NULL, for subsequent pages
// the pointer is non-zero and the page must append its data into the
// allocation.
//
// Returning either and error or S_FALSE stops the query. An error is
// reported to the user, S_FALSE stops silently.
HRESULT BuildQueryParams(LPDSQUERYPARAMS* ppDsQueryParams, LPWSTR pQuery)
{
ASSERT(pQuery);
if(*ppDsQueryParams)
return QueryParamsAddQueryString(ppDsQueryParams, pQuery);
else
return QueryParamsAlloc(ppDsQueryParams, pQuery, cRRASColumn, RRASColumn);
}
/*-----------------------------------------------------------------------------
/ QueryParamsAlloc
/ ----------------
/ Construct a block we can pass to the DS query handler which contains
/ all the parameters for the query.
/
/ In:
/ ppDsQueryParams -> receives the parameter block
/ pQuery -> LDAP query string to be used
/ iColumns = number of columns
/ pColumnInfo -> column info structure to use
/
/ Out:
/ HRESULT
/----------------------------------------------------------------------------*/
HRESULT QueryParamsAlloc(LPDSQUERYPARAMS* ppDsQueryParams, LPWSTR pQuery, LONG iColumns, LPCOLUMNINFO aColumnInfo)
{
HRESULT hr;
LPDSQUERYPARAMS pDsQueryParams = NULL;
LONG cbStruct;
LONG i;
ASSERT(!*ppDsQueryParams);
TRACE(L"QueryParamsAlloc");
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if ( !pQuery || !iColumns || !ppDsQueryParams )
ExitGracefully(hr, E_INVALIDARG, "Failed to build query parameter block");
// Compute the size of the structure we need to be using
cbStruct = sizeof(DSQUERYPARAMS) + (sizeof(DSCOLUMN)*iColumns);
cbStruct += StringByteSizeW(pQuery);
for ( i = 0 ; i < iColumns ; i++ )
{
if ( aColumnInfo[i].pPropertyName )
cbStruct += StringByteSizeW(aColumnInfo[i].pPropertyName);
}
pDsQueryParams = (LPDSQUERYPARAMS)CoTaskMemAlloc(cbStruct);
if ( !pDsQueryParams )
ExitGracefully(hr, E_OUTOFMEMORY, "Failed to allocate parameter block");
// Structure allocated so lets fill it with data
pDsQueryParams->cbStruct = cbStruct;
pDsQueryParams->dwFlags = 0;
pDsQueryParams->hInstance = _Module.m_hInst;
pDsQueryParams->iColumns = iColumns;
pDsQueryParams->dwReserved = 0;
cbStruct = sizeof(DSQUERYPARAMS) + (sizeof(DSCOLUMN)*iColumns);
pDsQueryParams->offsetQuery = cbStruct;
StringByteCopyW(pDsQueryParams, cbStruct, pQuery);
cbStruct += StringByteSizeW(pQuery);
for ( i = 0 ; i < iColumns ; i++ )
{
pDsQueryParams->aColumns[i].dwFlags = 0;
pDsQueryParams->aColumns[i].fmt = aColumnInfo[i].fmt;
pDsQueryParams->aColumns[i].cx = aColumnInfo[i].cx;
pDsQueryParams->aColumns[i].idsName = aColumnInfo[i].idsName;
pDsQueryParams->aColumns[i].dwReserved = 0;
if ( aColumnInfo[i].pPropertyName )
{
pDsQueryParams->aColumns[i].offsetProperty = cbStruct;
StringByteCopyW(pDsQueryParams, cbStruct, aColumnInfo[i].pPropertyName);
cbStruct += StringByteSizeW(aColumnInfo[i].pPropertyName);
}
else
{
pDsQueryParams->aColumns[i].offsetProperty = aColumnInfo[i].iPropertyIndex;
}
}
hr = S_OK; // success
exit_gracefully:
if ( FAILED(hr) && pDsQueryParams )
{
CoTaskMemFree(pDsQueryParams);
pDsQueryParams = NULL;
}
*ppDsQueryParams = pDsQueryParams;
return hr;
}
/*-----------------------------------------------------------------------------
/ QueryParamsAddQueryString
/ -------------------------
/ Given an existing DS query block appened the given LDAP query string into
/ it. We assume that the query block has been allocated by IMalloc (or CoTaskMemAlloc).
/
/ In:
/ ppDsQueryParams -> receives the parameter block
/ pQuery -> LDAP query string to be appended
/
/ Out:
/ HRESULT
/----------------------------------------------------------------------------*/
HRESULT QueryParamsAddQueryString(LPDSQUERYPARAMS* ppDsQueryParams, LPWSTR pQuery)
{
HRESULT hr;
LPWSTR pOriginalQuery = NULL;
LPDSQUERYPARAMS pDsQuery = *ppDsQueryParams;
INT cbQuery, i;
LPVOID pv;
ASSERT(*ppDsQueryParams);
TRACE(_T("QueryParamsAddQueryString"));
if ( pQuery )
{
if ( !pDsQuery )
ExitGracefully(hr, E_INVALIDARG, "No query to append to");
// Work out the size of the bits we are adding, take a copy of the
// query string and finally re-alloc the query block (which may cause it
// to move).
cbQuery = StringByteSizeW(pQuery) + StringByteSizeW(L"(&)");
TRACE(_T("DSQUERYPARAMS being resized by %d bytes"));
i = (wcslen((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery)) + 1) * sizeof(WCHAR);
pOriginalQuery = (WCHAR*)_alloca(i);
lstrcpyW(pOriginalQuery, (LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery));
pv = CoTaskMemRealloc(*ppDsQueryParams, pDsQuery->cbStruct+cbQuery);
if ( pv == NULL )
ExitGracefully(hr, E_OUTOFMEMORY, "Failed to re-alloc control block");
*ppDsQueryParams = (LPDSQUERYPARAMS) pv;
pDsQuery = *ppDsQueryParams; // if may have moved
// Now move everything above the query string up, and fix all the
// offsets that reference those items (probably the property table),
// finally adjust the size to reflect the change
MoveMemory(ByteOffset(pDsQuery, pDsQuery->offsetQuery+cbQuery),
ByteOffset(pDsQuery, pDsQuery->offsetQuery),
(pDsQuery->cbStruct - pDsQuery->offsetQuery));
for ( i = 0 ; i < pDsQuery->iColumns ; i++ )
{
if ( pDsQuery->aColumns[i].offsetProperty > pDsQuery->offsetQuery )
{
pDsQuery->aColumns[i].offsetProperty += cbQuery;
}
}
wcscpy((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), L"(&");
wcscat((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), pOriginalQuery);
wcscat((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), pQuery);
wcscat((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), L")");
pDsQuery->cbStruct += cbQuery;
}
hr = S_OK;
exit_gracefully:
return hr;
}
// Get the list of values in the dictionary, the variant is expected to be SARRY
HRESULT QueryRRASAdminDictionary(VARIANT* pVar)
{
ASSERT(pVar);
USES_CONVERSION;
CString str, str1;
IADs* pIADs = NULL;
// enumerate EAP list
// retieve the list of EAPTypes in the DS
// get ROOTDSE
HRESULT hr = S_OK;
CHECK_HR(hr = ADsGetObject(L"LDAP://RootDSE", IID_IADs, (void**)&pIADs));
ASSERT(pIADs);
VariantClear(pVar);
CHECK_HR(hr = pIADs->Get(L"configurationNamingContext", pVar));
str1 = V_BSTR(pVar);
pIADs->Release();
pIADs = NULL;
str = L"LDAP://";
str += CN_DICTIONARY;
str += str1;
// Dictionary Object
CHECK_HR(hr = ADsGetObject(T2W((LPTSTR)(LPCTSTR)str), IID_IADs, (void**)&pIADs));
ASSERT(pIADs);
VariantClear(pVar);
CHECK_HR(hr = pIADs->GetEx(ATTR_NAME_RRASDICENTRY, pVar));
goto L_EXIT;
L_ERR:
VariantClear(pVar);
L_EXIT:
if(pIADs)
pIADs->Release();
return hr;
}
HRESULT GetGeneralPageAttributes(CStrArray& array)
{
HRESULT hr = S_OK;
CString* pStr = NULL;
/*
#define ATTR_VAL_LANtoLAN L"311:6:601"
#define ATTR_VAL_RAS L"311:6:602"
#define ATTR_VAL_DEMANDDIAL L"311:6:603"
*/
try
{
pStr = new CString(ATTR_VAL_LANtoLAN);
array.Add(pStr);
pStr = new CString(ATTR_VAL_RAS);
array.Add(pStr);
pStr = new CString(ATTR_VAL_DEMANDDIAL);
array.Add(pStr);
}
catch(CMemoryException&)
{
hr = E_OUTOFMEMORY;
}
return hr;
}