You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2066 lines
55 KiB
2066 lines
55 KiB
//+----------------------------------------------------------------------------
|
|
//
|
|
// DS Administration MMC snapin.
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1999
|
|
//
|
|
// File: queryui.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "resource.h"
|
|
#include "queryui.h"
|
|
#include "dssnap.h"
|
|
#include "uiutil.h"
|
|
|
|
#include <cmnquery.h> // DSFind
|
|
#include <dsquery.h> // DSFind
|
|
#include <dsclient.h> // BrowseForContainer
|
|
|
|
#include <dsqueryp.h> // COLUMNINFO and QueryParamsAddQueryString, QueryParamsAlloc helpers
|
|
#include <cmnquryp.h> // CQFF_ISNEVERLISTED
|
|
#include <lmaccess.h> // UF_ACCOUNTDISABLE and UF_DONT_EXPIRE_PASSWD
|
|
#include <ntldap.h> // LDAP_MATCHING_RULE_BIT_AND_W
|
|
|
|
#include "ldaputil.h" // LdapEscape().
|
|
|
|
#define DSQF_LAST_LOGON_QUERY 0x00000001
|
|
#define DSQF_NON_EXPIRING_PWD_QUERY 0x00000004
|
|
|
|
//
|
|
// Used to set the maximum text length on fields in the new query dialog
|
|
//
|
|
#define MAX_QUERY_NAME_LENGTH 259
|
|
#define MAX_QUERY_DESC_LENGTH 1024
|
|
|
|
typedef struct
|
|
{
|
|
UINT nDisplayStringID;
|
|
PWSTR pszFormatString;
|
|
} QUERYSTRINGS, * PQUERYSTRINGS;
|
|
|
|
QUERYSTRINGS g_pQueryStrings[] = {
|
|
{ IDS_STARTSWITH, L"(%s=%s*)" },
|
|
{ IDS_ENDSWITH, L"(%s=*%s)" },
|
|
{ IDS_ISEXACTLY, L"(%s=%s)" },
|
|
{ IDS_ISNOT, L"(!%s=%s)" },
|
|
{ IDS_PRESENT, L"(%s=%s*)" }, // NOTE: the second string needs to be NULL here
|
|
{ IDS_NOTPRESENT, L"(!%s=%s*)" }, // NOTE: the second string needs to be NULL here
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const CString g_szUserAccountCtrlQuery = L"(userAccountControl:" + CString(LDAP_MATCHING_RULE_BIT_AND_W) + L":=%u)";
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
/ 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 = S_OK;
|
|
LPDSQUERYPARAMS pDsQueryParams = NULL;
|
|
size_t cbStruct;
|
|
LONG i;
|
|
|
|
ASSERT(!*ppDsQueryParams);
|
|
|
|
TRACE(L"QueryParamsAlloc");
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
if ( !pQuery || !iColumns || !ppDsQueryParams )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Compute the size of the structure we need to be using
|
|
//
|
|
cbStruct = sizeof(DSQUERYPARAMS) + (sizeof(DSCOLUMN)*iColumns);
|
|
cbStruct += (wcslen(pQuery) + 1) * sizeof(WCHAR);
|
|
|
|
for (i = 0; i < iColumns; i++)
|
|
{
|
|
if (aColumnInfo[i].pPropertyName)
|
|
{
|
|
cbStruct += (wcslen(aColumnInfo[i].pPropertyName) + 1) * sizeof(WCHAR);
|
|
}
|
|
}
|
|
|
|
pDsQueryParams = (LPDSQUERYPARAMS)CoTaskMemAlloc(cbStruct);
|
|
|
|
if (!pDsQueryParams)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
//
|
|
// Structure allocated so lets fill it with data
|
|
//
|
|
pDsQueryParams->cbStruct = static_cast<DWORD>(cbStruct);
|
|
pDsQueryParams->dwFlags = 0;
|
|
pDsQueryParams->hInstance = _Module.m_hInst;
|
|
pDsQueryParams->iColumns = iColumns;
|
|
pDsQueryParams->dwReserved = 0;
|
|
|
|
cbStruct = sizeof(DSQUERYPARAMS) + (sizeof(DSCOLUMN)*iColumns);
|
|
|
|
pDsQueryParams->offsetQuery = static_cast<LONG>(cbStruct);
|
|
CopyMemory(&(((LPBYTE)pDsQueryParams)[cbStruct]), pQuery, (wcslen(pQuery) + 1) * sizeof(WCHAR));
|
|
cbStruct += (wcslen(pQuery) + 1) * sizeof(WCHAR);
|
|
|
|
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 = static_cast<LONG>(cbStruct);
|
|
CopyMemory(&(((LPBYTE)pDsQueryParams)[cbStruct]), aColumnInfo[i].pPropertyName, (wcslen(aColumnInfo[i].pPropertyName) + 1) * sizeof(WCHAR));
|
|
cbStruct += (wcslen(aColumnInfo[i].pPropertyName) + 1) * sizeof(WCHAR);
|
|
}
|
|
else
|
|
{
|
|
pDsQueryParams->aColumns[i].offsetProperty = aColumnInfo[i].iPropertyIndex;
|
|
}
|
|
}
|
|
|
|
*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 = S_OK;
|
|
LPWSTR pOriginalQuery = NULL;
|
|
LPDSQUERYPARAMS pDsQuery = *ppDsQueryParams;
|
|
size_t cbQuery;
|
|
LONG i;
|
|
LPVOID pv;
|
|
|
|
//NTRAID#NTBUG9-567482-2002/03/10-jmessec Assertion not backed up by code (well, sorta is below in checking pDsQuery, but not obvious)
|
|
ASSERT(*ppDsQueryParams);
|
|
|
|
TRACE(_T("QueryParamsAddQueryString"));
|
|
|
|
if ( pQuery )
|
|
{
|
|
if (!pDsQuery)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// 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 = ((wcslen(pQuery) + 1) * sizeof(WCHAR));
|
|
TRACE(_T("DSQUERYPARAMS being resized by %d bytes"));
|
|
|
|
i = static_cast<LONG>((wcslen((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery)) + 1) * sizeof(WCHAR));
|
|
pOriginalQuery = (WCHAR*) new BYTE[i];
|
|
if (!pOriginalQuery)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
lstrcpyW(pOriginalQuery, (LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery));
|
|
|
|
pv = CoTaskMemRealloc(*ppDsQueryParams, pDsQuery->cbStruct+cbQuery);
|
|
if ( pv == NULL )
|
|
{
|
|
delete[] pOriginalQuery;
|
|
pOriginalQuery = 0;
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
*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 += static_cast<LONG>(cbQuery);
|
|
}
|
|
}
|
|
|
|
//NTRAID#NTBUG9-572009-2002/03/10-jmessec It appears that your struct is one sizeof(WCHAR) too large now, since
|
|
//you allocated enough extra for a whole other string, including terminating NULL,
|
|
//but you are appending the strings, thus eating a NULL; could this fowl up later
|
|
//struct size calculations and offsets?
|
|
wcscpy((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), pOriginalQuery);
|
|
wcscat((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), pQuery);
|
|
|
|
pDsQuery->cbStruct += static_cast<DWORD>(cbQuery);
|
|
|
|
delete[] pOriginalQuery;
|
|
pOriginalQuery = 0;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// AddQueryUnitWithModifier
|
|
|
|
HRESULT AddQueryUnitWithModifier(UINT nModifierStringID,
|
|
PCWSTR pszAttrName,
|
|
PCWSTR pszValue,
|
|
CString& szFilter)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
ASSERT(pszAttrName != NULL);
|
|
if (pszAttrName == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// Escape special characters used in LDAP from the value the
|
|
// user entered.
|
|
wstring escapedValue;
|
|
LdapEscape(
|
|
pszValue != NULL ? pszValue : L"",
|
|
escapedValue);
|
|
|
|
CString szNewFilter;
|
|
|
|
PQUERYSTRINGS pQueryStrings = g_pQueryStrings;
|
|
PWSTR pszFormatString = NULL;
|
|
while (pQueryStrings->nDisplayStringID != 0)
|
|
{
|
|
if (nModifierStringID == pQueryStrings->nDisplayStringID)
|
|
{
|
|
pszFormatString = pQueryStrings->pszFormatString;
|
|
break;
|
|
}
|
|
pQueryStrings++;
|
|
}
|
|
|
|
if (pszFormatString != NULL)
|
|
{
|
|
szNewFilter.Format(pszFormatString, pszAttrName, escapedValue.c_str());
|
|
szFilter += szNewFilter;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CQueryPageBase
|
|
BEGIN_MESSAGE_MAP(CQueryPageBase, CHelpDialog)
|
|
END_MESSAGE_MAP()
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CStdQueryPage
|
|
|
|
#define FILTER_PREFIX_USER L"(objectCategory=person)(objectClass=user)"
|
|
#define FILTER_PREFIX_COMPUTER L"(objectCategory=computer)"
|
|
#define FILTER_PREFIX_GROUP L"(objectCategory=group)"
|
|
|
|
#define ATTR_COL_NAME L"name"
|
|
#define ATTR_COL_DESC L"description"
|
|
|
|
COLUMNINFO UserColumn[] =
|
|
{
|
|
{ 0, 40, IDS_QUERY_COL_NAME, 0, ATTR_COL_NAME },
|
|
{ 0, 40, IDS_QUERY_COL_DESC, 0, ATTR_COL_DESC }
|
|
};
|
|
|
|
int cUserColumns = 2;
|
|
|
|
BEGIN_MESSAGE_MAP(CStdQueryPage, CQueryPageBase)
|
|
ON_CBN_SELCHANGE(IDC_NAME_COMBO, OnNameComboChange)
|
|
ON_CBN_SELCHANGE(IDC_DESCRIPTION_COMBO, OnDescriptionComboChange)
|
|
END_MESSAGE_MAP()
|
|
|
|
void CStdQueryPage::DoContextHelp(HWND hWndControl)
|
|
{
|
|
if (hWndControl)
|
|
{
|
|
::WinHelp(hWndControl,
|
|
DSADMIN_CONTEXT_HELP_FILE,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_QUERY_STD_PAGE);
|
|
}
|
|
}
|
|
|
|
BOOL CStdQueryPage::OnInitDialog()
|
|
{
|
|
CHelpDialog::OnInitDialog();
|
|
|
|
PQUERYSTRINGS pQueryStrings = g_pQueryStrings;
|
|
ASSERT(pQueryStrings != NULL);
|
|
|
|
//
|
|
// Fill in the combo boxes
|
|
//
|
|
while (pQueryStrings->nDisplayStringID != 0)
|
|
{
|
|
CString szComboString;
|
|
VERIFY(szComboString.LoadString(pQueryStrings->nDisplayStringID));
|
|
|
|
//
|
|
// Fill in the Name combo
|
|
//
|
|
LRESULT lRes = SendDlgItemMessage(IDC_NAME_COMBO, CB_ADDSTRING, 0, (LPARAM)(PCWSTR)szComboString);
|
|
if (lRes != CB_ERR)
|
|
{
|
|
lRes = SendDlgItemMessage(IDC_NAME_COMBO, CB_SETITEMDATA, (WPARAM)lRes, (LPARAM)pQueryStrings->nDisplayStringID);
|
|
ASSERT(lRes != CB_ERR);
|
|
}
|
|
|
|
//
|
|
// Fill in the Description combo
|
|
//
|
|
lRes = SendDlgItemMessage(IDC_DESCRIPTION_COMBO, CB_ADDSTRING, 0, (LPARAM)(PCWSTR)szComboString);
|
|
if (lRes != CB_ERR)
|
|
{
|
|
lRes = SendDlgItemMessage(IDC_DESCRIPTION_COMBO, CB_SETITEMDATA, (WPARAM)lRes, (LPARAM)pQueryStrings->nDisplayStringID);
|
|
ASSERT(lRes != CB_ERR);
|
|
}
|
|
|
|
pQueryStrings++;
|
|
}
|
|
|
|
//
|
|
// Insert an empty so that there is a way to undo changes
|
|
//
|
|
LRESULT lBlankName = SendDlgItemMessage(IDC_NAME_COMBO, CB_ADDSTRING, 0, (LPARAM)L"");
|
|
if (lBlankName != CB_ERR)
|
|
{
|
|
SendDlgItemMessage(IDC_NAME_COMBO, CB_SETITEMDATA, (WPARAM)lBlankName, (LPARAM)0);
|
|
}
|
|
|
|
//
|
|
// Insert an empty so that there is a way to undo changes
|
|
//
|
|
LRESULT lBlankDesc = SendDlgItemMessage(IDC_DESCRIPTION_COMBO, CB_ADDSTRING, 0, (LPARAM)L"");
|
|
if (lBlankDesc != CB_ERR)
|
|
{
|
|
SendDlgItemMessage(IDC_DESCRIPTION_COMBO, CB_SETITEMDATA, (WPARAM)lBlankDesc, (LPARAM)0);
|
|
}
|
|
|
|
//
|
|
// Force the UI to enable and disable controls related to the combo boxes
|
|
//
|
|
OnNameComboChange();
|
|
OnDescriptionComboChange();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void CStdQueryPage::OnNameComboChange()
|
|
{
|
|
LRESULT lRes = SendDlgItemMessage(IDC_NAME_COMBO, CB_GETCURSEL, 0, 0);
|
|
if (lRes != CB_ERR)
|
|
{
|
|
LRESULT lData = SendDlgItemMessage(IDC_NAME_COMBO, CB_GETITEMDATA, lRes, 0);
|
|
if (lData != CB_ERR)
|
|
{
|
|
if (lData == IDS_PRESENT || lData == IDS_NOTPRESENT || lData == 0)
|
|
{
|
|
GetDlgItem(IDC_NAME_EDIT)->EnableWindow(FALSE);
|
|
SetDlgItemText(IDC_NAME_EDIT, L"");
|
|
}
|
|
else
|
|
{
|
|
GetDlgItem(IDC_NAME_EDIT)->EnableWindow(TRUE);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GetDlgItem(IDC_NAME_EDIT)->EnableWindow(FALSE);
|
|
}
|
|
}
|
|
|
|
void CStdQueryPage::OnDescriptionComboChange()
|
|
{
|
|
LRESULT lRes = SendDlgItemMessage(IDC_DESCRIPTION_COMBO, CB_GETCURSEL, 0, 0);
|
|
if (lRes != CB_ERR)
|
|
{
|
|
LRESULT lData = SendDlgItemMessage(IDC_DESCRIPTION_COMBO, CB_GETITEMDATA, lRes, 0);
|
|
if (lData != CB_ERR)
|
|
{
|
|
if (lData == IDS_PRESENT || lData == IDS_NOTPRESENT || lData == 0)
|
|
{
|
|
GetDlgItem(IDC_DESCRIPTION_EDIT)->EnableWindow(FALSE);
|
|
SetDlgItemText(IDC_DESCRIPTION_EDIT, L"");
|
|
}
|
|
else
|
|
{
|
|
GetDlgItem(IDC_DESCRIPTION_EDIT)->EnableWindow(TRUE);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GetDlgItem(IDC_DESCRIPTION_EDIT)->EnableWindow(FALSE);
|
|
}
|
|
}
|
|
|
|
void CStdQueryPage::Init()
|
|
{
|
|
//
|
|
// Clear all controls
|
|
//
|
|
SetDlgItemText(IDC_NAME_EDIT, L"");
|
|
SetDlgItemText(IDC_DESCRIPTION_EDIT, L"");
|
|
|
|
//
|
|
// Reselect the blank string in the combo boxes
|
|
//
|
|
LRESULT lRes = SendDlgItemMessage(IDC_NAME_COMBO, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)L"");
|
|
if (lRes != CB_ERR)
|
|
{
|
|
SendDlgItemMessage(IDC_NAME_COMBO, CB_SETCURSEL, lRes, 0);
|
|
}
|
|
|
|
lRes = SendDlgItemMessage(IDC_DESCRIPTION_COMBO, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)L"");
|
|
if (lRes != CB_ERR)
|
|
{
|
|
SendDlgItemMessage(IDC_DESCRIPTION_COMBO, CB_SETCURSEL, lRes, 0);
|
|
}
|
|
}
|
|
|
|
HRESULT CStdQueryPage::GetQueryParams(LPDSQUERYPARAMS* ppDsQueryParams)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Build the filter string here
|
|
//
|
|
CString szFilter;
|
|
CString szName;
|
|
CString szDescription;
|
|
|
|
GetDlgItemText(IDC_NAME_EDIT, szName);
|
|
GetDlgItemText(IDC_DESCRIPTION_EDIT, szDescription);
|
|
|
|
//
|
|
// Get the selection of the modifier combo
|
|
//
|
|
LRESULT lSel = SendDlgItemMessage(IDC_NAME_COMBO, CB_GETCURSEL, 0, 0);
|
|
if (lSel != CB_ERR)
|
|
{
|
|
//
|
|
// Retrieve the associated string ID
|
|
//
|
|
LRESULT lData = SendDlgItemMessage(IDC_NAME_COMBO, CB_GETITEMDATA, lSel, 0);
|
|
if (lData != CB_ERR)
|
|
{
|
|
if (!szName.IsEmpty() || lData == IDS_PRESENT || lData == IDS_NOTPRESENT)
|
|
{
|
|
AddQueryUnitWithModifier(static_cast<UINT>(lData),
|
|
ATTR_COL_NAME,
|
|
szName,
|
|
szFilter);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the selection of the modifier combo
|
|
//
|
|
lSel = SendDlgItemMessage(IDC_DESCRIPTION_COMBO, CB_GETCURSEL, 0, 0);
|
|
if (lSel != CB_ERR)
|
|
{
|
|
//
|
|
// Retrieve the associated string ID
|
|
//
|
|
LRESULT lData = SendDlgItemMessage(IDC_DESCRIPTION_COMBO, CB_GETITEMDATA, lSel, 0);
|
|
if (lData != CB_ERR)
|
|
{
|
|
if (!szDescription.IsEmpty() || lData == IDS_PRESENT || lData == IDS_NOTPRESENT)
|
|
{
|
|
AddQueryUnitWithModifier(static_cast<UINT>(lData),
|
|
ATTR_COL_DESC,
|
|
szDescription,
|
|
szFilter);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!szFilter.IsEmpty())
|
|
{
|
|
szFilter = m_szFilterPrefix + szFilter;
|
|
hr = BuildQueryParams(ppDsQueryParams, (LPWSTR)(LPCWSTR)szFilter);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CStdQueryPage::BuildQueryParams(LPDSQUERYPARAMS* ppDsQueryParams, LPWSTR pQuery)
|
|
{
|
|
ASSERT(pQuery);
|
|
|
|
if(*ppDsQueryParams)
|
|
{
|
|
return QueryParamsAddQueryString(ppDsQueryParams, pQuery);
|
|
}
|
|
return QueryParamsAlloc(ppDsQueryParams, pQuery, cUserColumns, UserColumn);
|
|
}
|
|
|
|
HRESULT CStdQueryPage::Persist(IPersistQuery* pPersistQuery, BOOL fRead)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pPersistQuery == NULL)
|
|
{
|
|
ASSERT(FALSE);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (fRead)
|
|
{
|
|
//
|
|
// Read the Name combo value
|
|
//
|
|
int iData = 0;
|
|
hr = pPersistQuery->ReadInt(m_szFilterPrefix, L"NameCombo", &iData);
|
|
if (FAILED(hr))
|
|
{
|
|
TRACE(_T("Failed to read int \"NameCombo\" from stream: 0x%x\n"), hr);
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Select the appropriate list box item
|
|
//
|
|
SelectComboAssociatedWithData(IDC_NAME_COMBO, iData);
|
|
|
|
if (iData != 0 && iData != IDS_PRESENT && iData != IDS_NOTPRESENT)
|
|
{
|
|
//
|
|
// Read the name edit value
|
|
//
|
|
WCHAR szBuf[MAX_PATH] = {0};
|
|
hr = pPersistQuery->ReadString(m_szFilterPrefix, L"NameEdit", szBuf, MAX_PATH);
|
|
if (FAILED(hr))
|
|
{
|
|
TRACE(_T("Failed to read string \"NameEdit\" from stream: 0x%x\n"), hr);
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
|
|
if (szBuf != NULL)
|
|
{
|
|
SetDlgItemText(IDC_NAME_EDIT, szBuf);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GetDlgItem(IDC_NAME_EDIT)->EnableWindow(FALSE);
|
|
}
|
|
|
|
//
|
|
// Read the Description combo value
|
|
//
|
|
iData = 0;
|
|
hr = pPersistQuery->ReadInt(m_szFilterPrefix, L"DescCombo", &iData);
|
|
if (FAILED(hr))
|
|
{
|
|
TRACE(_T("Failed to read int \"DescCombo\" from stream: 0x%x\n"), hr);
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Select the appropriate list box item
|
|
//
|
|
SelectComboAssociatedWithData(IDC_DESCRIPTION_COMBO, iData);
|
|
|
|
if (iData != 0 && iData != IDS_PRESENT && iData != IDS_NOTPRESENT)
|
|
{
|
|
//
|
|
// Read the name edit value
|
|
//
|
|
WCHAR szBuf[MAX_PATH] = {0};
|
|
hr = pPersistQuery->ReadString(m_szFilterPrefix, L"DescEdit", szBuf, MAX_PATH);
|
|
if (FAILED(hr))
|
|
{
|
|
TRACE(_T("Failed to read string \"DescEdit\" from stream: 0x%x\n"), hr);
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
|
|
if (szBuf != NULL)
|
|
{
|
|
SetDlgItemText(IDC_DESCRIPTION_EDIT, szBuf);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GetDlgItem(IDC_DESCRIPTION_EDIT)->EnableWindow(FALSE);
|
|
}
|
|
OnNameComboChange();
|
|
OnDescriptionComboChange();
|
|
}
|
|
else // write
|
|
{
|
|
//
|
|
// Write out the name info
|
|
//
|
|
LRESULT lSel = SendDlgItemMessage(IDC_NAME_COMBO, CB_GETCURSEL, 0, 0);
|
|
if (lSel != CB_ERR)
|
|
{
|
|
//
|
|
// Retrieve the associated string ID
|
|
//
|
|
LRESULT lData = SendDlgItemMessage(IDC_NAME_COMBO, CB_GETITEMDATA, lSel, 0);
|
|
if (lData != CB_ERR)
|
|
{
|
|
hr = pPersistQuery->WriteInt(m_szFilterPrefix, L"NameCombo", static_cast<int>(lData));
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
|
|
if (lData != 0 && lData != IDS_PRESENT && lData != IDS_NOTPRESENT)
|
|
{
|
|
CString szName;
|
|
GetDlgItemText(IDC_NAME_EDIT, szName);
|
|
hr = pPersistQuery->WriteString(m_szFilterPrefix, L"NameEdit", szName);
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If there hasn't been a selection, write in the empty string value
|
|
//
|
|
hr = pPersistQuery->WriteInt(m_szFilterPrefix, L"NameCombo", 0);
|
|
}
|
|
|
|
|
|
//
|
|
// Write out the description info
|
|
//
|
|
lSel = SendDlgItemMessage(IDC_DESCRIPTION_COMBO, CB_GETCURSEL, 0, 0);
|
|
if (lSel != CB_ERR)
|
|
{
|
|
//
|
|
// Retrieve the associated string ID
|
|
//
|
|
LRESULT lData = SendDlgItemMessage(IDC_DESCRIPTION_COMBO, CB_GETITEMDATA, lSel, 0);
|
|
if (lData != CB_ERR)
|
|
{
|
|
hr = pPersistQuery->WriteInt(m_szFilterPrefix, L"DescCombo", static_cast<int>(lData));
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
|
|
if (lData != 0 && lData != IDS_PRESENT && lData != IDS_NOTPRESENT)
|
|
{
|
|
CString szDescription;
|
|
GetDlgItemText(IDC_DESCRIPTION_EDIT, szDescription);
|
|
hr = pPersistQuery->WriteString(m_szFilterPrefix, L"DescEdit", szDescription);
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If there hasn't been a selection, write in the empty string value
|
|
//
|
|
hr = pPersistQuery->WriteInt(m_szFilterPrefix, L"DescCombo", 0);
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
void CStdQueryPage::SelectComboAssociatedWithData(UINT nCtrlID, LRESULT lData)
|
|
{
|
|
//
|
|
// Selects the item with the associated data in a combo box
|
|
//
|
|
LRESULT lRes = SendDlgItemMessage(nCtrlID, CB_GETCOUNT, 0, 0);
|
|
if (lRes != CB_ERR)
|
|
{
|
|
for (int idx = 0; idx < static_cast<int>(lRes); idx++)
|
|
{
|
|
LRESULT lRetData = SendDlgItemMessage(nCtrlID, CB_GETITEMDATA, (WPARAM)idx, 0);
|
|
if (lRetData != CB_ERR)
|
|
{
|
|
if (lRetData == lData)
|
|
{
|
|
SendDlgItemMessage(nCtrlID, CB_SETCURSEL, (WPARAM)idx, 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CUserComputerQueryPage
|
|
|
|
BEGIN_MESSAGE_MAP(CUserComputerQueryPage, CStdQueryPage)
|
|
END_MESSAGE_MAP()
|
|
|
|
BOOL CUserComputerQueryPage::OnInitDialog()
|
|
{
|
|
return CStdQueryPage::OnInitDialog();
|
|
}
|
|
|
|
void CUserComputerQueryPage::DoContextHelp(HWND hWndControl)
|
|
{
|
|
if (hWndControl)
|
|
{
|
|
::WinHelp(hWndControl,
|
|
DSADMIN_CONTEXT_HELP_FILE,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_QUERY_USER_PAGE);
|
|
}
|
|
}
|
|
|
|
void CUserComputerQueryPage::Init()
|
|
{
|
|
//
|
|
// Clear all controls
|
|
//
|
|
CStdQueryPage::Init();
|
|
}
|
|
|
|
HRESULT CUserComputerQueryPage::GetQueryParams(LPDSQUERYPARAMS* ppDsQueryParams)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Build the filter string here
|
|
//
|
|
hr = CStdQueryPage::GetQueryParams(ppDsQueryParams);
|
|
|
|
CString szFilter;
|
|
BOOL bDisabledAccounts = FALSE;
|
|
|
|
//
|
|
// Get disabled accounts check
|
|
//
|
|
LRESULT lRes = SendDlgItemMessage(IDC_DISABLED_ACCOUNTS_CHECK, BM_GETCHECK, 0, 0);
|
|
if (lRes == BST_CHECKED)
|
|
{
|
|
bDisabledAccounts = TRUE;
|
|
}
|
|
|
|
|
|
if (bDisabledAccounts)
|
|
{
|
|
szFilter.Format(g_szUserAccountCtrlQuery, UF_ACCOUNTDISABLE);
|
|
szFilter = m_szFilterPrefix + szFilter;
|
|
|
|
hr = BuildQueryParams(ppDsQueryParams, (LPWSTR)(LPCWSTR)szFilter);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CUserComputerQueryPage::Persist(IPersistQuery* pPersistQuery, BOOL fRead)
|
|
{
|
|
HRESULT hr = CStdQueryPage::Persist(pPersistQuery, fRead);
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pPersistQuery == NULL)
|
|
{
|
|
ASSERT(FALSE);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (fRead)
|
|
{
|
|
//
|
|
// Read disabled accounts flag
|
|
//
|
|
int iData = 0;
|
|
hr = pPersistQuery->ReadInt(m_szFilterPrefix, L"DisableCheck", &iData);
|
|
if (FAILED(hr))
|
|
{
|
|
TRACE(_T("Failed to read int \"DisableCheck\" from stream: 0x%x\n"), hr);
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
SendDlgItemMessage(IDC_DISABLED_ACCOUNTS_CHECK, BM_SETCHECK, (iData > 0) ? BST_CHECKED : BST_UNCHECKED, 0);
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Write disabled accounts flag
|
|
//
|
|
LRESULT lRes = SendDlgItemMessage(IDC_DISABLED_ACCOUNTS_CHECK, BM_GETCHECK, 0, 0);
|
|
if (lRes != -1)
|
|
{
|
|
int iRes = (lRes == BST_CHECKED) ? 1 : 0;
|
|
hr = pPersistQuery->WriteInt(m_szFilterPrefix, L"DisableCheck", iRes);
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CUserQueryPage
|
|
|
|
BEGIN_MESSAGE_MAP(CUserQueryPage, CStdQueryPage)
|
|
END_MESSAGE_MAP()
|
|
|
|
BOOL CUserQueryPage::OnInitDialog()
|
|
{
|
|
return CUserComputerQueryPage::OnInitDialog();
|
|
}
|
|
|
|
void CUserQueryPage::DoContextHelp(HWND hWndControl)
|
|
{
|
|
if (hWndControl)
|
|
{
|
|
::WinHelp(hWndControl,
|
|
DSADMIN_CONTEXT_HELP_FILE,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_QUERY_USER_PAGE);
|
|
}
|
|
}
|
|
|
|
void CUserQueryPage::Init()
|
|
{
|
|
//
|
|
// Clear all controls
|
|
//
|
|
CUserComputerQueryPage::Init();
|
|
}
|
|
|
|
HRESULT CUserQueryPage::GetQueryParams(LPDSQUERYPARAMS* ppDsQueryParams)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Build the filter string here
|
|
//
|
|
hr = CUserComputerQueryPage::GetQueryParams(ppDsQueryParams);
|
|
|
|
CString szFilter;
|
|
BOOL bNonExpPwds = FALSE;
|
|
BOOL bLastLogon = FALSE;
|
|
DWORD dwLastLogonData = 0;
|
|
|
|
//
|
|
// Get non expiring password check
|
|
//
|
|
LRESULT lRes = SendDlgItemMessage(IDC_NON_EXPIRING_PWD_CHECK, BM_GETCHECK, 0, 0);
|
|
if (lRes == BST_CHECKED)
|
|
{
|
|
bNonExpPwds = TRUE;
|
|
}
|
|
|
|
//
|
|
// Get stale acccounts check
|
|
//
|
|
lRes = SendDlgItemMessage(IDC_LASTLOGON_COMBO, CB_GETCURSEL, 0, 0);
|
|
if (lRes == CB_ERR)
|
|
{
|
|
lRes = m_lLogonSelection;
|
|
}
|
|
|
|
if (lRes != CB_ERR)
|
|
{
|
|
LRESULT lTextLen = SendDlgItemMessage(IDC_LASTLOGON_COMBO, CB_GETLBTEXTLEN, (WPARAM)lRes, 0);
|
|
if (lTextLen != CB_ERR)
|
|
{
|
|
if (lTextLen > 0)
|
|
{
|
|
bLastLogon = TRUE;
|
|
|
|
WCHAR* pszData = new WCHAR[lTextLen + 1];
|
|
if (pszData != NULL)
|
|
{
|
|
LRESULT lData = SendDlgItemMessage(IDC_LASTLOGON_COMBO, CB_GETLBTEXT, (WPARAM)lRes, (LPARAM)pszData);
|
|
if (lData != CB_ERR)
|
|
{
|
|
dwLastLogonData = static_cast<DWORD>(_wtol(pszData));
|
|
// NTRAID#NTBUG9-449871-2001/09/20-lucios
|
|
// Adding the appropriate filter.
|
|
|
|
LARGE_INTEGER li;
|
|
GetCurrentTimeStampMinusInterval(dwLastLogonData, &li);
|
|
CString szTimeStamp;
|
|
litow(li, szTimeStamp);
|
|
CString szTempFilter;
|
|
szTempFilter.Format
|
|
(
|
|
L"%s(lastLogonTimestamp<=%s)",
|
|
szTempFilter,
|
|
szTimeStamp
|
|
);
|
|
szFilter = szTempFilter + szFilter;
|
|
}
|
|
delete[] pszData;
|
|
pszData = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bNonExpPwds || bLastLogon)
|
|
{
|
|
if (bNonExpPwds)
|
|
{
|
|
szFilter.Format(g_szUserAccountCtrlQuery, UF_DONT_EXPIRE_PASSWD);
|
|
}
|
|
szFilter = m_szFilterPrefix + szFilter;
|
|
|
|
hr = BuildQueryParams(ppDsQueryParams, (LPWSTR)(LPCWSTR)szFilter);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (bLastLogon)
|
|
{
|
|
(*ppDsQueryParams)->dwFlags |= DSQF_LAST_LOGON_QUERY;
|
|
(*ppDsQueryParams)->dwReserved = dwLastLogonData;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CUserQueryPage::Persist(IPersistQuery* pPersistQuery, BOOL fRead)
|
|
{
|
|
HRESULT hr = CUserComputerQueryPage::Persist(pPersistQuery, fRead);
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pPersistQuery == NULL)
|
|
{
|
|
ASSERT(FALSE);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (fRead)
|
|
{
|
|
//
|
|
// Read non expiring pwds flag
|
|
//
|
|
int iData = 0;
|
|
hr = pPersistQuery->ReadInt(m_szFilterPrefix, L"NonExpPwdCheck", &iData);
|
|
if (FAILED(hr))
|
|
{
|
|
TRACE(_T("Failed to read int \"NonExpPwdCheck\" from stream: 0x%x\n"), hr);
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
SendDlgItemMessage(IDC_NON_EXPIRING_PWD_CHECK, BM_SETCHECK, (iData > 0) ? BST_CHECKED : BST_UNCHECKED, 0);
|
|
|
|
iData = 0;
|
|
hr = pPersistQuery->ReadInt(m_szFilterPrefix, L"LastLogonCombo", &iData);
|
|
if (FAILED(hr))
|
|
{
|
|
TRACE(_T("Failed to read int \"LastLogonCombo\" from stream: 0x%x\n"), hr);
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
SendDlgItemMessage(IDC_LASTLOGON_COMBO, CB_SETCURSEL, (WPARAM)iData, 0);
|
|
m_lLogonSelection = iData;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Write non expiring pwd flag
|
|
//
|
|
LRESULT lRes = SendDlgItemMessage(IDC_NON_EXPIRING_PWD_CHECK, BM_GETCHECK, 0, 0);
|
|
if (lRes != -1)
|
|
{
|
|
int iRes = (lRes == BST_CHECKED) ? 1 : 0;
|
|
hr = pPersistQuery->WriteInt(m_szFilterPrefix, L"NonExpPwdCheck", iRes);
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Write last logon combo index
|
|
//
|
|
lRes = SendDlgItemMessage(IDC_LASTLOGON_COMBO, CB_GETCURSEL, 0, 0);
|
|
if (lRes == CB_ERR)
|
|
{
|
|
if (m_lLogonSelection != -1)
|
|
{
|
|
lRes = m_lLogonSelection;
|
|
}
|
|
else
|
|
{
|
|
lRes = 0;
|
|
}
|
|
}
|
|
hr = pPersistQuery->WriteInt(m_szFilterPrefix, L"LastLogonCombo", static_cast<int>(lRes));
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CQueryFormBase
|
|
|
|
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 CQueryFormBase::Initialize(HKEY)
|
|
{
|
|
// 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 CQueryFormBase::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;
|
|
cqf.clsid = CLSID_DSAdminQueryUIForm;
|
|
cqf.hIcon = NULL;
|
|
|
|
CString title;
|
|
title.LoadString(IDS_QUERY_TITLE_SAVEDQUERYFORM);
|
|
cqf.pszTitle = (LPCTSTR)title;
|
|
|
|
return pAddFormsProc(lParam, &cqf);
|
|
}
|
|
|
|
STDMETHODIMP CQueryFormBase::AddPages(LPCQADDPAGESPROC pAddPagesProc, LPARAM lParam)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CQPAGE cqp;
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
CThemeContextActivator activator;
|
|
|
|
// 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.GetModuleInstance();
|
|
cqp.pDlgProc = DlgProc;
|
|
|
|
//
|
|
// Add the user page
|
|
//
|
|
cqp.idPageName = IDS_QUERY_TITLE_USERPAGE;
|
|
cqp.idPageTemplate = IDD_QUERY_USER_PAGE;
|
|
cqp.lParam = (LPARAM)new CUserQueryPage(FILTER_PREFIX_USER);
|
|
hr = pAddPagesProc(lParam, CLSID_DSAdminQueryUIForm, &cqp);
|
|
|
|
//
|
|
// Add the computer page (this is just a std page)
|
|
//
|
|
cqp.idPageName = IDS_QUERY_TITLE_COMPUTER_PAGE;
|
|
cqp.idPageTemplate = IDD_QUERY_COMPUTER_PAGE;
|
|
cqp.lParam = (LPARAM)new CUserComputerQueryPage(IDD_QUERY_COMPUTER_PAGE, FILTER_PREFIX_COMPUTER);
|
|
hr = pAddPagesProc(lParam, CLSID_DSAdminQueryUIForm, &cqp);
|
|
|
|
//
|
|
// Add the group page (this is just a std page)
|
|
//
|
|
cqp.idPageName = IDS_QUERY_TITLE_GROUP_PAGE;
|
|
cqp.idPageTemplate = IDD_QUERY_STD_PAGE;
|
|
cqp.lParam = (LPARAM)new CStdQueryPage(IDD_QUERY_STD_PAGE, FILTER_PREFIX_GROUP);
|
|
hr = pAddPagesProc(lParam, CLSID_DSAdminQueryUIForm, &cqp);
|
|
|
|
//
|
|
// Add more pages here if needed
|
|
//
|
|
return hr;
|
|
}
|
|
#define ExitGracefully(hr, result, text) \
|
|
{ hr = result; goto exit_gracefully; }
|
|
|
|
|
|
#define StringByteSizeW(sz) ((sz) ? ((lstrlenW(sz)+1)*sizeof(WCHAR)):0)
|
|
|
|
//NTRAID#NTBUG9-572010-2002/03/10-jmessec Unsafe wrapper for CopyMemory; what if string is longer than destination buffer?
|
|
#define StringByteCopyW(pDest, iOffset, sz) \
|
|
{ CopyMemory(&(((LPBYTE)pDest)[iOffset]), sz, StringByteSizeW(sz)); }
|
|
|
|
|
|
STDAPI ClassListAlloc(LPDSQUERYCLASSLIST* ppDsQueryClassList, LPWSTR* aClassNames, INT cClassNames)
|
|
{
|
|
HRESULT hres;
|
|
DWORD cbStruct, offset;
|
|
LPDSQUERYCLASSLIST pDsQueryClassList = NULL;
|
|
INT i;
|
|
USES_CONVERSION;
|
|
|
|
if ( !ppDsQueryClassList || !aClassNames || !cClassNames )
|
|
ExitGracefully(hres, E_FAIL, "Bad parameters (no class list etc)");
|
|
|
|
// Walk the list of classes working out the size of the structure
|
|
// we are going to generate, this consists of the array of
|
|
// classes.
|
|
|
|
cbStruct = sizeof(DSQUERYCLASSLIST)+(cClassNames*sizeof(DWORD));
|
|
offset = cbStruct;
|
|
|
|
for ( i = 0 ; i < cClassNames ; i++ )
|
|
{
|
|
ASSERT(aClassNames[i]);
|
|
cbStruct += StringByteSizeW(aClassNames[i]);
|
|
}
|
|
|
|
// Allocate the structure using the task allocator, then fill
|
|
// it in copying all the strings into the data blob.
|
|
|
|
|
|
pDsQueryClassList = (LPDSQUERYCLASSLIST)CoTaskMemAlloc(cbStruct);
|
|
ASSERT(pDsQueryClassList);
|
|
|
|
if ( !pDsQueryClassList )
|
|
ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate class list structure");
|
|
|
|
pDsQueryClassList->cbStruct = cbStruct;
|
|
pDsQueryClassList->cClasses = cClassNames;
|
|
|
|
for ( i = 0 ; i < cClassNames ; i++ )
|
|
{
|
|
pDsQueryClassList->offsetClass[i] = offset;
|
|
StringByteCopyW(pDsQueryClassList, offset, aClassNames[i]);
|
|
offset += StringByteSizeW(aClassNames[i]);
|
|
}
|
|
|
|
hres = S_OK;
|
|
|
|
exit_gracefully:
|
|
|
|
ASSERT(pDsQueryClassList);
|
|
|
|
if (ppDsQueryClassList)
|
|
*ppDsQueryClassList = pDsQueryClassList;
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
// 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());
|
|
|
|
CQueryPageBase* pDialog = (CQueryPageBase*)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;
|
|
|
|
case DSQPM_GETCLASSLIST:
|
|
{
|
|
LPWSTR classes[]={L"user",L"computer",L"group"};
|
|
hr = ClassListAlloc((LPDSQUERYCLASSLIST*)lParam, classes, sizeof(classes)/sizeof(*classes));
|
|
break;
|
|
}
|
|
|
|
case DSQPM_HELPTOPICS:
|
|
{
|
|
HWND hwndFrame = (HWND)lParam;
|
|
HtmlHelp(hwndFrame, TEXT("omc.chm"), HH_HELP_FINDER, 0);
|
|
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:
|
|
SetFocus(GetDlgItem(hwnd, IDC_NAME_COMBO));
|
|
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;
|
|
CQueryPageBase* 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 = (CQueryPageBase*)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 = (CQueryPageBase*)GetWindowLongPtr(hwnd, DWLP_USER);
|
|
}
|
|
|
|
if(!pDialog)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return AfxCallWndProc(pDialog, hwnd, uMsg, wParam, lParam);
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CQueryDialog
|
|
|
|
CQueryDialog::CQueryDialog(CSavedQueryNode* pQueryNode,
|
|
CFavoritesNode* pFavNode,
|
|
CDSComponentData* pComponentData,
|
|
BOOL bNewQuery,
|
|
BOOL bImportQuery)
|
|
: CHelpDialog(IDD_CREATE_NEW_QUERY)
|
|
{
|
|
m_bInit = FALSE;
|
|
|
|
m_bNewQuery = bNewQuery;
|
|
m_bImportQuery = bImportQuery;
|
|
m_pComponentData = pComponentData;
|
|
m_pQueryNode = pQueryNode;
|
|
m_pFavNode = pFavNode;
|
|
m_szName = pQueryNode->GetName();
|
|
m_szOriginalName = pQueryNode->GetName();
|
|
m_szDescription = pQueryNode->GetDesc();
|
|
m_szQueryRoot = pQueryNode->GetRootPath();
|
|
m_szQueryFilter = pQueryNode->GetQueryString();
|
|
m_bMultiLevel = !pQueryNode->IsOneLevel();
|
|
|
|
m_bLastLogonFilter = pQueryNode->IsFilterLastLogon();
|
|
m_dwLastLogonData = pQueryNode->GetLastLogonDays();
|
|
|
|
m_pPersistQueryImpl = pQueryNode->GetQueryPersist();
|
|
if (m_pPersistQueryImpl != NULL)
|
|
{
|
|
m_pPersistQueryImpl->AddRef();
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Create the IPersistQuery object
|
|
//
|
|
CComObject<CDSAdminPersistQueryFilterImpl>::CreateInstance(&m_pPersistQueryImpl);
|
|
ASSERT(m_pPersistQueryImpl != NULL);
|
|
|
|
//
|
|
// created with zero refcount,need to AddRef() to one
|
|
//
|
|
m_pPersistQueryImpl->AddRef();
|
|
}
|
|
}
|
|
|
|
|
|
CQueryDialog::~CQueryDialog()
|
|
{
|
|
if (m_pPersistQueryImpl != NULL)
|
|
{
|
|
//
|
|
// go to refcount of zero, to destroy object
|
|
//
|
|
m_pPersistQueryImpl->Release();
|
|
}
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CQueryDialog, CHelpDialog)
|
|
ON_BN_CLICKED(IDC_BROWSE_BUTTON, OnBrowse)
|
|
ON_BN_CLICKED(IDC_EDIT_BUTTON, OnEditQuery)
|
|
ON_BN_CLICKED(IDC_MULTI_LEVEL_CHECK, OnMultiLevelChange)
|
|
ON_EN_CHANGE(IDC_NAME_EDIT, OnNameChange)
|
|
ON_EN_CHANGE(IDC_DESCRIPTION_EDIT, OnDescriptionChange)
|
|
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnNeedToolTipText)
|
|
END_MESSAGE_MAP()
|
|
|
|
void CQueryDialog::DoContextHelp(HWND hWndControl)
|
|
{
|
|
if (hWndControl)
|
|
{
|
|
::WinHelp(hWndControl,
|
|
DSADMIN_CONTEXT_HELP_FILE,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_CREATE_NEW_QUERY);
|
|
}
|
|
}
|
|
|
|
BOOL CQueryDialog::OnInitDialog()
|
|
{
|
|
CHelpDialog::OnInitDialog();
|
|
|
|
if (m_pQueryNode == NULL)
|
|
{
|
|
ASSERT(FALSE);
|
|
EndDialog(IDCANCEL);
|
|
}
|
|
|
|
|
|
//
|
|
// Change the title for editing queries
|
|
//
|
|
if (!m_bNewQuery)
|
|
{
|
|
CString szTitle;
|
|
VERIFY(szTitle.LoadString(IDS_SAVED_QUERIES_EDIT_TITLE));
|
|
SetWindowText(szTitle);
|
|
}
|
|
|
|
//
|
|
// Initialize the controls with data
|
|
//
|
|
SetDlgItemText(IDC_NAME_EDIT, m_szName);
|
|
SendDlgItemMessage(IDC_NAME_EDIT, EM_SETLIMITTEXT, MAX_QUERY_NAME_LENGTH, 0);
|
|
SetDlgItemText(IDC_DESCRIPTION_EDIT, m_szDescription);
|
|
SendDlgItemMessage(IDC_DESCRIPTION_EDIT, EM_SETLIMITTEXT, MAX_QUERY_DESC_LENGTH, 0);
|
|
SendDlgItemMessage(IDC_MULTI_LEVEL_CHECK, BM_SETCHECK, (m_bMultiLevel) ? BST_CHECKED : BST_UNCHECKED, 0);
|
|
SetQueryFilterDisplay();
|
|
|
|
EnableToolTips(TRUE);
|
|
SetQueryRoot(m_szQueryRoot);
|
|
|
|
SetDirty();
|
|
m_bInit = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
void CQueryDialog::SetDirty(BOOL bDirty)
|
|
{
|
|
if (m_bInit || m_bImportQuery)
|
|
{
|
|
m_szName.TrimLeft();
|
|
m_szName.TrimRight();
|
|
if (m_szName.IsEmpty() ||
|
|
m_szQueryRoot.IsEmpty() ||
|
|
m_szQueryFilter.IsEmpty())
|
|
{
|
|
m_bDirty = FALSE;
|
|
}
|
|
else
|
|
{
|
|
m_bDirty = bDirty;
|
|
}
|
|
GetDlgItem(IDOK)->EnableWindow(m_bDirty);
|
|
}
|
|
}
|
|
|
|
void CQueryDialog::OnOK()
|
|
{
|
|
CThemeContextActivator activator;
|
|
|
|
if (m_bDirty)
|
|
{
|
|
if (m_pQueryNode != NULL)
|
|
{
|
|
GetDlgItemText(IDC_NAME_EDIT, m_szName);
|
|
GetDlgItemText(IDC_DESCRIPTION_EDIT, m_szDescription);
|
|
LRESULT lRes = SendDlgItemMessage(IDC_MULTI_LEVEL_CHECK, BM_GETCHECK, 0, 0);
|
|
if (lRes == BST_CHECKED)
|
|
{
|
|
m_bMultiLevel = TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_bMultiLevel = FALSE;
|
|
}
|
|
|
|
//
|
|
// Trim white space
|
|
//
|
|
m_szName.TrimLeft();
|
|
m_szName.TrimRight();
|
|
|
|
if (wcscmp(m_szOriginalName, m_szName) != 0 || m_bImportQuery)
|
|
{
|
|
CUINode* pDupNode = NULL;
|
|
if (!m_pFavNode->IsUniqueName(m_szName, &pDupNode))
|
|
{
|
|
CString szFormatMsg;
|
|
VERIFY(szFormatMsg.LoadString(IDS_ERRMSG_NOT_UNIQUE_QUERY_NAME));
|
|
|
|
CString szErrMsg;
|
|
szErrMsg.Format(szFormatMsg, m_szName);
|
|
|
|
CString szTitle;
|
|
VERIFY(szTitle.LoadString(IDS_DSSNAPINNAME));
|
|
|
|
MessageBox(szErrMsg, szTitle, MB_OK | MB_ICONSTOP);
|
|
|
|
//
|
|
// Set the focus to the name field and select all the text
|
|
//
|
|
GetDlgItem(IDC_NAME_EDIT)->SetFocus();
|
|
SendDlgItemMessage(IDC_NAME_EDIT, EM_SETSEL, 0, -1);
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
if (m_bLastLogonFilter)
|
|
{
|
|
m_pQueryNode->SetLastLogonQuery(m_dwLastLogonData);
|
|
}
|
|
else
|
|
{
|
|
m_pQueryNode->SetLastLogonQuery(static_cast<DWORD>(-1));
|
|
}
|
|
|
|
m_pQueryNode->SetQueryString(m_szQueryFilter);
|
|
m_pQueryNode->SetName(m_szName);
|
|
m_pQueryNode->SetDesc(m_szDescription);
|
|
m_pQueryNode->SetRootPath(m_szQueryRoot);
|
|
m_pQueryNode->SetOneLevel((m_bMultiLevel == BST_CHECKED) ? FALSE : TRUE);
|
|
m_pQueryNode->SetQueryPersist(m_pPersistQueryImpl);
|
|
}
|
|
}
|
|
CHelpDialog::OnOK();
|
|
}
|
|
|
|
BOOL CQueryDialog::OnNeedToolTipText(UINT, NMHDR* pTTTStruct, LRESULT* /*ignored*/)
|
|
{
|
|
BOOL bRes = FALSE;
|
|
TOOLTIPTEXT* pTTText = reinterpret_cast<TOOLTIPTEXT*>(pTTTStruct);
|
|
if (pTTText != NULL)
|
|
{
|
|
if (pTTText->uFlags & TTF_IDISHWND)
|
|
{
|
|
UINT nCtrlID = ::GetDlgCtrlID((HWND)pTTText->hdr.idFrom);
|
|
if (nCtrlID == IDC_ROOT_EDIT)
|
|
{
|
|
pTTText->lpszText = (LPWSTR)(LPCWSTR)m_szQueryRoot;
|
|
bRes = TRUE;
|
|
}
|
|
}
|
|
}
|
|
return bRes;
|
|
}
|
|
|
|
void CQueryDialog::OnEditQuery()
|
|
{
|
|
CWaitCursor wait;
|
|
|
|
CLIPFORMAT cfDsQueryParams = (CLIPFORMAT)::RegisterClipboardFormat(CFSTR_DSQUERYPARAMS);
|
|
|
|
//
|
|
// create a query object
|
|
//
|
|
HRESULT hr;
|
|
CComPtr<ICommonQuery> spCommonQuery;
|
|
hr = ::CoCreateInstance(CLSID_CommonQuery, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ICommonQuery, (PVOID *)&spCommonQuery);
|
|
if (FAILED(hr))
|
|
{
|
|
ReportMessageEx(GetSafeHwnd(), IDS_ERRMSG_NO_DSQUERYUI);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// setup structs to make the query
|
|
//
|
|
DSQUERYINITPARAMS dqip;
|
|
OPENQUERYWINDOW oqw;
|
|
ZeroMemory(&dqip, sizeof(DSQUERYINITPARAMS));
|
|
ZeroMemory(&oqw, sizeof(OPENQUERYWINDOW));
|
|
|
|
dqip.cbStruct = sizeof(dqip);
|
|
dqip.dwFlags = DSQPF_NOSAVE | DSQPF_SHOWHIDDENOBJECTS |
|
|
DSQPF_ENABLEADMINFEATURES;
|
|
dqip.pDefaultScope = NULL;
|
|
|
|
CString szServerName = m_pComponentData->GetBasePathsInfo()->GetServerName();
|
|
if (!szServerName.IsEmpty())
|
|
{
|
|
dqip.dwFlags |= DSQPF_HASCREDENTIALS;
|
|
dqip.pServer = (PWSTR)(PCWSTR)szServerName;
|
|
}
|
|
|
|
oqw.cbStruct = sizeof(oqw);
|
|
oqw.dwFlags = OQWF_OKCANCEL | OQWF_DEFAULTFORM | OQWF_SHOWOPTIONAL | /*OQWF_REMOVEFORMS |*/
|
|
OQWF_REMOVESCOPES | OQWF_SAVEQUERYONOK | OQWF_HIDEMENUS | OQWF_HIDESEARCHUI;
|
|
|
|
if (!m_pPersistQueryImpl->IsEmpty())
|
|
{
|
|
oqw.dwFlags |= OQWF_LOADQUERY;
|
|
}
|
|
|
|
oqw.clsidHandler = CLSID_DsQuery;
|
|
oqw.pHandlerParameters = &dqip;
|
|
oqw.clsidDefaultForm = CLSID_DSAdminQueryUIForm;
|
|
|
|
//
|
|
// set the IPersistQuery pointer (smart pointer)
|
|
//
|
|
CComPtr<IPersistQuery> spIPersistQuery;
|
|
hr = m_pPersistQueryImpl->QueryInterface(IID_IPersistQuery, (void**)&spIPersistQuery);
|
|
if (FAILED(hr))
|
|
{
|
|
int iRes = ReportMessageEx(GetSafeHwnd(), IDS_ERRMSG_NO_PERSIST_QUERYUI, MB_OKCANCEL | MB_ICONINFORMATION);
|
|
if (iRes == IDCANCEL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// now smart pointer has refcount=1 for it lifetime
|
|
//
|
|
oqw.pPersistQuery = spIPersistQuery;
|
|
|
|
//
|
|
// Get the HWND of the current dialog
|
|
//
|
|
HWND hWnd = GetSafeHwnd();
|
|
|
|
//
|
|
// make the call to get the query displayed
|
|
//
|
|
CComPtr<IDataObject> spQueryResultDataObject;
|
|
hr = spCommonQuery->OpenQueryWindow(hWnd, &oqw, &spQueryResultDataObject);
|
|
if (SUCCEEDED(hr) && spQueryResultDataObject != NULL)
|
|
{
|
|
//
|
|
// retrieve the query string from the data object
|
|
//
|
|
FORMATETC fmte = {cfDsQueryParams, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
|
|
STGMEDIUM medium = {TYMED_NULL, NULL, NULL};
|
|
hr = spQueryResultDataObject->GetData(&fmte, &medium);
|
|
|
|
if (SUCCEEDED(hr)) // we have data
|
|
{
|
|
//
|
|
// get the query string
|
|
//
|
|
LPDSQUERYPARAMS pDsQueryParams = (LPDSQUERYPARAMS)medium.hGlobal;
|
|
LPWSTR pwszFilter = (LPWSTR)ByteOffset(pDsQueryParams, pDsQueryParams->offsetQuery);
|
|
|
|
CString szTempFilter = pwszFilter;
|
|
|
|
//
|
|
// Check to see if we received a "special" query string
|
|
//
|
|
if (pDsQueryParams->dwFlags & DSQF_LAST_LOGON_QUERY)
|
|
{
|
|
m_bLastLogonFilter = TRUE;
|
|
m_dwLastLogonData = pDsQueryParams->dwReserved;
|
|
|
|
LARGE_INTEGER li;
|
|
GetCurrentTimeStampMinusInterval(m_dwLastLogonData, &li);
|
|
|
|
CString szTimeStamp;
|
|
litow(li, szTimeStamp);
|
|
|
|
szTempFilter.Format(L"%s(lastLogonTimestamp<=%s)", szTempFilter, szTimeStamp);
|
|
}
|
|
else
|
|
{
|
|
m_bLastLogonFilter = FALSE;
|
|
m_dwLastLogonData = 0;
|
|
}
|
|
|
|
::ReleaseStgMedium(&medium);
|
|
|
|
// REVIEW_MARCOC: this is a hack waiting for Diz to fix it...
|
|
// the query string should be a well formed expression. Period
|
|
// the query string is in the form (<foo>)(<bar>)...
|
|
// if more of one token, need to wrap as (& (<foo>)(<bar>)...)
|
|
PWSTR pChar = (LPWSTR)(LPCWSTR)szTempFilter;
|
|
int nLeftPar = 0;
|
|
while (*pChar != NULL)
|
|
{
|
|
if (*pChar == TEXT('('))
|
|
{
|
|
nLeftPar++;
|
|
if (nLeftPar > 1)
|
|
break;
|
|
}
|
|
pChar++;
|
|
}
|
|
if (nLeftPar > 1)
|
|
{
|
|
m_szQueryFilter.Format(_T("(&%s)"), (LPCWSTR)szTempFilter);
|
|
}
|
|
else
|
|
{
|
|
m_szQueryFilter = szTempFilter;
|
|
}
|
|
|
|
SetDirty();
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The user removed all query data from DSQUERYUI
|
|
//
|
|
|
|
//
|
|
// Remove filter data
|
|
//
|
|
m_szQueryFilter = L"";
|
|
m_bLastLogonFilter = FALSE;
|
|
m_dwLastLogonData = 0;
|
|
SetDirty();
|
|
}
|
|
}
|
|
SetQueryFilterDisplay();
|
|
return;
|
|
}
|
|
|
|
void CQueryDialog::SetQueryFilterDisplay()
|
|
{
|
|
if (m_bLastLogonFilter)
|
|
{
|
|
CString szTemp;
|
|
szTemp.LoadString(IDS_HIDE_LASTLOGON_QUERY);
|
|
SetDlgItemText(IDC_QUERY_STRING_EDIT, szTemp);
|
|
}
|
|
else
|
|
{
|
|
SetDlgItemText(IDC_QUERY_STRING_EDIT, m_szQueryFilter);
|
|
}
|
|
}
|
|
|
|
int SavedQueriesBrowseCallback(HWND, UINT uMsg, LPARAM lParam, LPARAM /*lpData*/)
|
|
{
|
|
int ret = 0;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case DSBM_HELP:
|
|
{
|
|
TRACE(L"Browse Callback: msg is DSBM_HELP.\n");
|
|
LPHELPINFO pHelp = (LPHELPINFO) lParam;
|
|
TRACE(_T("CtrlId = %d, ContextId = 0x%x\n"),
|
|
pHelp->iCtrlId, pHelp->dwContextId);
|
|
if (!pHelp ||
|
|
pHelp->iCtrlId != DSBID_CONTAINERLIST)
|
|
{
|
|
ret = 0; // not handled
|
|
break;
|
|
}
|
|
::WinHelp((HWND)pHelp->hItemHandle,
|
|
DSADMIN_CONTEXT_HELP_FILE,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_BROWSE_CONTAINER);
|
|
ret = 1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ret = 0;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void CQueryDialog::OnBrowse()
|
|
{
|
|
DWORD result;
|
|
|
|
CString szBrowseTitle;
|
|
VERIFY(szBrowseTitle.LoadString(IDS_QUERY_BROWSE_TITLE));
|
|
|
|
CString szBrowseCaption;
|
|
VERIFY(szBrowseCaption.LoadString(IDS_QUERY_BROWSE_CAPTION));
|
|
|
|
WCHAR szPath[2 * MAX_PATH+1];
|
|
|
|
//
|
|
// Get the root of the console
|
|
CString szDNC = m_pComponentData->GetBasePathsInfo()->GetDefaultRootNamingContext();
|
|
CString szRootPath;
|
|
m_pComponentData->GetBasePathsInfo()->ComposeADsIPath(szRootPath, szDNC);
|
|
|
|
DSBROWSEINFO dsbi;
|
|
::ZeroMemory( &dsbi, sizeof(dsbi) );
|
|
|
|
dsbi.hwndOwner = GetSafeHwnd();
|
|
dsbi.cbStruct = sizeof (DSBROWSEINFO);
|
|
dsbi.pszCaption = (LPWSTR)((LPCWSTR)szBrowseTitle);
|
|
dsbi.pszTitle = (LPWSTR)((LPCWSTR)szBrowseCaption);
|
|
dsbi.pszRoot = szRootPath;
|
|
dsbi.pszPath = szPath;
|
|
dsbi.cchPath = ((2 * MAX_PATH + 1) / sizeof(WCHAR));
|
|
dsbi.dwFlags = DSBI_INCLUDEHIDDEN | DSBI_RETURN_FORMAT;
|
|
dsbi.pfnCallback = SavedQueriesBrowseCallback;
|
|
dsbi.lParam = 0;
|
|
dsbi.dwReturnFormat = ADS_FORMAT_X500;
|
|
|
|
result = DsBrowseForContainer( &dsbi );
|
|
|
|
if ( result == IDOK )
|
|
{
|
|
//
|
|
// returns -1, 0, IDOK or IDCANCEL
|
|
// get path from BROWSEINFO struct, put in text edit field
|
|
//
|
|
TRACE(_T("returned from DS Browse successfully with:\n %s\n"),
|
|
dsbi.pszPath);
|
|
|
|
CPathCracker pathCracker;
|
|
HRESULT hr = pathCracker.Set(CComBSTR(dsbi.pszPath), ADS_SETTYPE_FULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pathCracker.SetDisplayType(ADS_DISPLAY_FULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComBSTR bstrDN;
|
|
hr = pathCracker.Retrieve(ADS_FORMAT_X500_DN, &bstrDN);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SetQueryRoot(bstrDN);
|
|
SetDirty();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CQueryDialog::SetQueryRoot(PCWSTR pszPath)
|
|
{
|
|
m_szQueryRoot = pszPath;
|
|
|
|
CPathCracker pathCracker;
|
|
HRESULT hr = pathCracker.Set(CComBSTR(m_szQueryRoot), ADS_SETTYPE_DN);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pathCracker.SetDisplayType(ADS_DISPLAY_VALUE_ONLY);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComBSTR bstrDisplayPath;
|
|
hr = pathCracker.GetElement(0, &bstrDisplayPath);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CString szDisplayString;
|
|
szDisplayString.Format(L"...\\%s", bstrDisplayPath);
|
|
SetDlgItemText(IDC_ROOT_EDIT, szDisplayString);
|
|
}
|
|
else
|
|
{
|
|
SetDlgItemText(IDC_ROOT_EDIT, m_szQueryRoot);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetDlgItemText(IDC_ROOT_EDIT, m_szQueryRoot);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetDlgItemText(IDC_ROOT_EDIT, m_szQueryRoot);
|
|
}
|
|
}
|
|
|
|
void CQueryDialog::OnMultiLevelChange()
|
|
{
|
|
SetDirty();
|
|
}
|
|
|
|
void CQueryDialog::OnNameChange()
|
|
{
|
|
GetDlgItemText(IDC_NAME_EDIT, m_szName);
|
|
if (m_szName.IsEmpty())
|
|
{
|
|
SetDirty(FALSE);
|
|
}
|
|
else
|
|
{
|
|
SetDirty();
|
|
}
|
|
}
|
|
|
|
void CQueryDialog::OnDescriptionChange()
|
|
{
|
|
SetDirty();
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// CFavoritesNodePropertyPage
|
|
BEGIN_MESSAGE_MAP(CFavoritesNodePropertyPage, CHelpPropertyPage)
|
|
ON_EN_CHANGE(IDC_DESCRIPTION_EDIT, OnDescriptionChange)
|
|
ON_WM_DESTROY()
|
|
END_MESSAGE_MAP()
|
|
|
|
void CFavoritesNodePropertyPage::DoContextHelp(HWND hWndControl)
|
|
{
|
|
if (hWndControl)
|
|
{
|
|
::WinHelp(hWndControl,
|
|
DSADMIN_CONTEXT_HELP_FILE,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_FAVORITES_PROPERTY_PAGE);
|
|
}
|
|
}
|
|
|
|
BOOL CFavoritesNodePropertyPage::OnInitDialog()
|
|
{
|
|
CHelpPropertyPage::OnInitDialog();
|
|
|
|
m_szOldDescription = m_pFavNode->GetDesc();
|
|
SetDlgItemText(IDC_CN, m_pFavNode->GetName());
|
|
SetDlgItemText(IDC_DESCRIPTION_EDIT, m_szOldDescription);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void CFavoritesNodePropertyPage::OnDescriptionChange()
|
|
{
|
|
CString szNewDescription;
|
|
GetDlgItemText(IDC_DESCRIPTION_EDIT, szNewDescription);
|
|
|
|
if (szNewDescription == m_szOldDescription)
|
|
{
|
|
SetModified(FALSE);
|
|
}
|
|
else
|
|
{
|
|
SetModified(TRUE);
|
|
}
|
|
}
|
|
|
|
BOOL CFavoritesNodePropertyPage::OnApply()
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
CString szNewDescription;
|
|
GetDlgItemText(IDC_DESCRIPTION_EDIT, szNewDescription);
|
|
if (szNewDescription == m_szOldDescription)
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_pFavNode->SetDesc(szNewDescription);
|
|
|
|
if (m_lNotifyHandle != NULL && m_pDataObject != NULL)
|
|
{
|
|
MMCPropertyChangeNotify(m_lNotifyHandle, (LPARAM)m_pDataObject);
|
|
}
|
|
}
|
|
|
|
m_szOldDescription = szNewDescription;
|
|
return bRet;
|
|
}
|
|
|
|
void CFavoritesNodePropertyPage::OnDestroy()
|
|
{
|
|
m_pComponentData->SheetUnlockCookie(m_pFavNode);
|
|
}
|