724 lines
22 KiB
C++
724 lines
22 KiB
C++
|
#include "pch.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ Helper functions
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
HRESULT _GetQueryString(LPWSTR pQuery, UINT* pLen, LPWSTR pPrefixQuery, HWND hDlg, LPPAGECTRL aCtrl, INT iCtrls);
|
||
|
HRESULT _GetFilterQueryString(LPWSTR pFilter, UINT* pLen, HWND hwndFilter, HDSA hdsaColumns);
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ Query paremeter helpers
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ ClassListAlloc
|
||
|
/ --------------
|
||
|
/ Construct a class list allocation based on the list of classes
|
||
|
/ we are given.
|
||
|
/
|
||
|
/ In:
|
||
|
/ ppClassList -> receives a class list
|
||
|
/ cClassList / cClassList = array of classes to allocat from
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
STDAPI ClassListAlloc(LPDSQUERYCLASSLIST* ppDsQueryClassList, LPWSTR* aClassNames, INT cClassNames)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
DWORD cbStruct, offset;
|
||
|
LPDSQUERYCLASSLIST pDsQueryClassList = NULL;
|
||
|
INT i;
|
||
|
USES_CONVERSION;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "ClassListAlloc");
|
||
|
|
||
|
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++ )
|
||
|
{
|
||
|
TraceAssert(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.
|
||
|
|
||
|
Trace(TEXT("Allocating class structure %d"), cbStruct);
|
||
|
|
||
|
pDsQueryClassList = (LPDSQUERYCLASSLIST)CoTaskMemAlloc(cbStruct);
|
||
|
TraceAssert(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++ )
|
||
|
{
|
||
|
Trace(TEXT("Adding class: %s"), W2T(aClassNames[i]));
|
||
|
pDsQueryClassList->offsetClass[i] = offset;
|
||
|
StringByteCopyW(pDsQueryClassList, offset, aClassNames[i]);
|
||
|
offset += StringByteSizeW(aClassNames[i]);
|
||
|
}
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceAssert(pDsQueryClassList);
|
||
|
|
||
|
if (ppDsQueryClassList)
|
||
|
*ppDsQueryClassList = pDsQueryClassList;
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ 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
|
||
|
/ hInstance = hInstance to write into parameter block
|
||
|
/ iColumns = number of columns
|
||
|
/ pColumnInfo -> column info structure to use
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
STDAPI QueryParamsAlloc(LPDSQUERYPARAMS* ppDsQueryParams, LPWSTR pQuery, HINSTANCE hInstance, LONG iColumns, LPCOLUMNINFO aColumnInfo)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
LPDSQUERYPARAMS pDsQueryParams = NULL;
|
||
|
LONG cbStruct;
|
||
|
LONG i;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "QueryParamsAlloc");
|
||
|
|
||
|
if ( !pQuery || !iColumns || !ppDsQueryParams )
|
||
|
ExitGracefully(hres, 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(hres, E_OUTOFMEMORY, "Failed to allocate parameter block");
|
||
|
|
||
|
// Structure allocated so lets fill it with data
|
||
|
|
||
|
pDsQueryParams->cbStruct = cbStruct;
|
||
|
pDsQueryParams->dwFlags = 0;
|
||
|
pDsQueryParams->hInstance = hInstance;
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hres = S_OK; // success
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
if ( FAILED(hres) && pDsQueryParams )
|
||
|
{
|
||
|
CoTaskMemFree(pDsQueryParams);
|
||
|
pDsQueryParams = NULL;
|
||
|
}
|
||
|
|
||
|
if (ppDsQueryParams)
|
||
|
*ppDsQueryParams = pDsQueryParams;
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ 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
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
STDAPI QueryParamsAddQueryString(LPDSQUERYPARAMS* ppDsQueryParams, LPWSTR pQuery)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
LPWSTR pOriginalQuery = NULL;
|
||
|
LPDSQUERYPARAMS pDsQuery = *ppDsQueryParams;
|
||
|
INT cbQuery, i;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "QueryParamsAddQueryString");
|
||
|
|
||
|
if ( pQuery )
|
||
|
{
|
||
|
if ( !pDsQuery )
|
||
|
ExitGracefully(hres, 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(TEXT("DSQUERYPARAMS being resized by %d bytes"), cbQuery);
|
||
|
|
||
|
hres = LocalAllocStringW(&pOriginalQuery, (LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery));
|
||
|
FailGracefully(hres, "Failed to take copy of original query string");
|
||
|
|
||
|
pDsQuery = (LPDSQUERYPARAMS)CoTaskMemRealloc(pDsQuery, pDsQuery->cbStruct+cbQuery);
|
||
|
if ( !pDsQuery )
|
||
|
ExitGracefully(hres, E_OUTOFMEMORY, "Failed to re-alloc control block");
|
||
|
|
||
|
*ppDsQueryParams = pDsQuery;
|
||
|
|
||
|
// 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 )
|
||
|
{
|
||
|
Trace(TEXT("Fixing offset of property at index %d"), i);
|
||
|
pDsQuery->aColumns[i].offsetProperty += cbQuery;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
StrCpyW((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), L"(&");
|
||
|
StrCatW((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), pOriginalQuery);
|
||
|
StrCatW((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), pQuery);
|
||
|
StrCatW((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), L")");
|
||
|
|
||
|
pDsQuery->cbStruct += cbQuery;
|
||
|
}
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
LocalFreeStringW(&pOriginalQuery);
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ Form to query string helper functions
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ GetQueryString
|
||
|
/ --------------
|
||
|
/ Build the form parmaeters into a LDAP query string using the given table.
|
||
|
/
|
||
|
/ In:
|
||
|
/ ppQuery -> receives the string pointer
|
||
|
/ pPrefixQuery -> string placed at head of query / = NULL if none
|
||
|
/ hDlg = handle for the dialog to get the data from
|
||
|
/ aCtrls / iCtrls = control information for the window
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
STDAPI GetQueryString(LPWSTR* ppQuery, LPWSTR pPrefixQuery, HWND hDlg, LPPAGECTRL aCtrls, INT iCtrls)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
UINT cLen = 0;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "GetQueryString");
|
||
|
|
||
|
hres = _GetQueryString(NULL, &cLen, pPrefixQuery, hDlg, aCtrls, iCtrls);
|
||
|
FailGracefully(hres, "Failed 1st pass (compute string length)");
|
||
|
|
||
|
if ( cLen )
|
||
|
{
|
||
|
hres = LocalAllocStringLenW(ppQuery, cLen);
|
||
|
FailGracefully(hres, "Failed to alloc buffer for query string");
|
||
|
|
||
|
hres = _GetQueryString(*ppQuery, &cLen, pPrefixQuery, hDlg, aCtrls, iCtrls);
|
||
|
FailGracefully(hres, "Failed 2nd pass (fill buffer)");
|
||
|
}
|
||
|
|
||
|
hres = cLen ? S_OK:S_FALSE;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ _GetQueryString
|
||
|
/ ---------------
|
||
|
/ Build the string from the controls or just return the buffer size required.
|
||
|
/
|
||
|
/ In:
|
||
|
/ pQuery -> filled with query string / = NULL
|
||
|
/ pLen = updated to reflect the required string length
|
||
|
/ pPrefixQuery -> string placed at head of query / = NULL if none
|
||
|
/ hDlg = handle for the dialog to get the data from
|
||
|
/ aCtrls / iCtrls = control information for the window
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT _GetQueryString(LPWSTR pQuery, UINT* pLen, LPWSTR pPrefixQuery, HWND hDlg, LPPAGECTRL aCtrl, INT iCtrls)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
INT i;
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
USES_CONVERSION;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "_GetQueryString");
|
||
|
|
||
|
if ( !hDlg || (!aCtrl && iCtrls) )
|
||
|
ExitGracefully(hres, E_INVALIDARG, "No dialog or controls list");
|
||
|
|
||
|
Trace(TEXT("Checking %d controls"), iCtrls);
|
||
|
|
||
|
PutStringElementW(pQuery, pLen, pPrefixQuery);
|
||
|
|
||
|
for ( i = 0 ; i < iCtrls; i++ )
|
||
|
{
|
||
|
if ( GetDlgItemText(hDlg, aCtrl[i].nIDDlgItem, szBuffer, ARRAYSIZE(szBuffer)) )
|
||
|
{
|
||
|
Trace(TEXT("Property %s, value %s"), W2T(aCtrl[i].pPropertyName), szBuffer);
|
||
|
GetFilterString(pQuery, pLen, aCtrl[i].iFilter, aCtrl[i].pPropertyName, T2W(szBuffer));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Trace(TEXT("Resulting query is -%s- (%d)"), pQuery ? W2T(pQuery):TEXT("<no buffer>"), pLen ? *pLen:0);
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ GetFilterString
|
||
|
/ ---------------
|
||
|
/ Given a property, a property and its filter generate a suitable filter
|
||
|
/ string that map returning it into the given buffer via PutStringElement.
|
||
|
/
|
||
|
/ In:
|
||
|
/ pFilter, pLen = buffer information that we are returning int
|
||
|
/ iFilter = condition to be applied
|
||
|
/ pProperty -> property name
|
||
|
/ pValue -> value
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
struct
|
||
|
{
|
||
|
BOOL fNoValue;
|
||
|
BOOL fFixWildcard;
|
||
|
LPWSTR pPrefix;
|
||
|
LPWSTR pOperator;
|
||
|
LPWSTR pPostfix;
|
||
|
}
|
||
|
filter_info[] =
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// The server today does not support contains searches, therefore
|
||
|
// for consistency map that to a STARTSWITH, NOTSTARTSWITH
|
||
|
//
|
||
|
|
||
|
#if 0
|
||
|
0, 1, L"(", L"=*", L"*)", // CONTAIN
|
||
|
0, 1, L"(!", L"=*", L"*)", // NOTCONTAINS
|
||
|
#else
|
||
|
0, 1, L"(", L"=", L"*)", // CONTAINS
|
||
|
0, 1, L"(!", L"=", L"*)", // NOTCONTAINS
|
||
|
#endif
|
||
|
|
||
|
0, 1, L"(", L"=", L"*)", // STARTSWITH
|
||
|
0, 1, L"(", L"=*", L")", // ENDSWITH
|
||
|
0, 0, L"(", L"=", L")", // IS
|
||
|
0, 0, L"(!", L"=", L")", // ISNOT
|
||
|
0, 0, L"(", L">=", L")", // GREATEREQUAL
|
||
|
0, 0, L"(", L"<=", L")", // LESSEQUAL
|
||
|
1, 0, L"(", L"=*)", NULL, // DEFINED
|
||
|
1, 0, L"(!", L"=*)", NULL, // UNDEFINED
|
||
|
|
||
|
1, 0, L"(", L"=TRUE)", NULL, // TRUE
|
||
|
1, 0, L"(!", L"=TRUE)", NULL, // FALSE
|
||
|
};
|
||
|
|
||
|
STDAPI GetFilterString(LPWSTR pFilter, UINT* pLen, INT iFilter, LPWSTR pProperty, LPWSTR pValue)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
USES_CONVERSION;
|
||
|
|
||
|
TraceEnter(TRACE_VIEW, "GetFilterString");
|
||
|
|
||
|
// Check to see if the value we have contains a wildcard, if it does then just
|
||
|
// make it is exact assuming the user knows what they are doing - ho ho ho!
|
||
|
|
||
|
if ( pValue && filter_info[iFilter-FILTER_FIRST].fFixWildcard )
|
||
|
{
|
||
|
if ( wcschr(pValue, L'*') )
|
||
|
{
|
||
|
TraceMsg("START/ENDS contains wildcards, making is exactly");
|
||
|
iFilter = FILTER_IS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Fix the condition to index into the our array then
|
||
|
// put the string elements down
|
||
|
|
||
|
iFilter -= FILTER_FIRST; // compensate for non-zero index
|
||
|
|
||
|
if ( iFilter >= ARRAYSIZE(filter_info) )
|
||
|
ExitGracefully(hres, E_FAIL, "Bad filter value");
|
||
|
|
||
|
PutStringElementW(pFilter, pLen, filter_info[iFilter].pPrefix);
|
||
|
PutStringElementW(pFilter, pLen, pProperty);
|
||
|
PutStringElementW(pFilter, pLen, filter_info[iFilter].pOperator);
|
||
|
|
||
|
if ( !filter_info[iFilter].fNoValue )
|
||
|
{
|
||
|
LPWSTR pszOutput = pFilter ? (pFilter + lstrlenW(pFilter)) : NULL;
|
||
|
for (; *pValue; pValue++)
|
||
|
{
|
||
|
int cchLen = 1;
|
||
|
switch (*pValue)
|
||
|
{
|
||
|
// case L'*': // do no RFC encode *, if we do then the user cannot do foo* for a wildcarded string
|
||
|
case L'(':
|
||
|
case L')':
|
||
|
case L'\\':
|
||
|
{
|
||
|
if (pszOutput)
|
||
|
{
|
||
|
LPCWSTR pszToHex = L"0123456789abcdef";
|
||
|
*pszOutput++ = L'\\';
|
||
|
*pszOutput++ = pszToHex[(*pValue & 0xf0) >> 4];
|
||
|
*pszOutput++ = pszToHex[(*pValue & 0x0f)];
|
||
|
}
|
||
|
cchLen = 3;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
if (pszOutput)
|
||
|
{
|
||
|
*pszOutput++ = *pValue;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (pLen)
|
||
|
*pLen = (*pLen + cchLen);
|
||
|
}
|
||
|
|
||
|
if (pszOutput)
|
||
|
*pszOutput = L'\0';
|
||
|
}
|
||
|
|
||
|
PutStringElementW(pFilter, pLen, filter_info[iFilter].pPostfix);
|
||
|
|
||
|
Trace(TEXT("Filter is: %s"), pFilter ? W2T(pFilter):TEXT("<none>"));
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ GetPatternString
|
||
|
/ ----------------
|
||
|
/ Given a string wrap in suitable wildcards to do the filtering of
|
||
|
/ results.
|
||
|
/
|
||
|
/ In:
|
||
|
/ pPattern, pLen = buffer information that we are returning int
|
||
|
/ iFilter = condition to be applied
|
||
|
/ pValue -> value
|
||
|
/
|
||
|
/ Out:
|
||
|
/ VOID
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
struct
|
||
|
{
|
||
|
LPTSTR pPrefix;
|
||
|
LPTSTR pPostfix;
|
||
|
}
|
||
|
pattern_info[] =
|
||
|
{
|
||
|
TEXT("*"), TEXT("*"), // CONTAIN
|
||
|
TEXT("*"), TEXT("*"), // NOTCONTAINS
|
||
|
TEXT(""), TEXT("*"), // STARTSWITH
|
||
|
TEXT("*"), TEXT(""), // ENDSWITH
|
||
|
TEXT(""), TEXT(""), // IS
|
||
|
TEXT(""), TEXT(""), // ISNOT
|
||
|
};
|
||
|
|
||
|
STDAPI GetPatternString(LPTSTR pFilter, UINT* pLen, INT iFilter, LPTSTR pValue)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
|
||
|
TraceEnter(TRACE_VIEW, "GetFilterString");
|
||
|
|
||
|
iFilter -= FILTER_FIRST; // compensate for non-zero index
|
||
|
|
||
|
if ( iFilter >= ARRAYSIZE(pattern_info) )
|
||
|
ExitGracefully(hres, E_FAIL, "Bad filter value");
|
||
|
|
||
|
PutStringElement(pFilter, pLen, pattern_info[iFilter].pPrefix);
|
||
|
PutStringElement(pFilter, pLen, pValue);
|
||
|
PutStringElement(pFilter, pLen, pattern_info[iFilter].pPostfix);
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ Dialog helper functions
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ EnablePageControls
|
||
|
/ ------------------
|
||
|
/ Enable/Disable the controls on a query form.
|
||
|
/
|
||
|
/ In:
|
||
|
/ hDlg = handle for the dialog to get the data from
|
||
|
/ aCtrls / iCtrls = control information for the window
|
||
|
/ fEnable = TRUE/FALSE to enable disable window controls
|
||
|
/
|
||
|
/ Out:
|
||
|
/ VOID
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
STDAPI_(VOID) EnablePageControls(HWND hDlg, LPPAGECTRL aCtrl, INT iCtrls, BOOL fEnable)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
INT i;
|
||
|
HWND hwndCtrl;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "EnablePageControls");
|
||
|
|
||
|
if ( !hDlg || (!aCtrl && iCtrls) )
|
||
|
ExitGracefully(hres, E_INVALIDARG, "No dialog or controls list");
|
||
|
|
||
|
Trace(TEXT("%s %d controls"), fEnable ? TEXT("Enabling"):TEXT("Disabling"),iCtrls);
|
||
|
|
||
|
for ( i = 0 ; i < iCtrls; i++ )
|
||
|
{
|
||
|
hwndCtrl = GetDlgItem(hDlg, aCtrl[i].nIDDlgItem);
|
||
|
|
||
|
if ( hwndCtrl )
|
||
|
EnableWindow(hwndCtrl, fEnable);
|
||
|
}
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeave();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ ResetPageControls
|
||
|
/ ------------------
|
||
|
/ Reset all the form controls back to their default state.
|
||
|
/
|
||
|
/ In:
|
||
|
/ hDlg = handle for the dialog to get the data from
|
||
|
/ aCtrls / iCtrls = control information for the window
|
||
|
/
|
||
|
/ Out:
|
||
|
/ VOID
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
STDAPI_(VOID) ResetPageControls(HWND hDlg, LPPAGECTRL aCtrl, INT iCtrls)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
INT i;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "ResetPageControls");
|
||
|
|
||
|
if ( !hDlg || (!aCtrl && iCtrls) )
|
||
|
ExitGracefully(hres, E_INVALIDARG, "No dialog or controls list");
|
||
|
|
||
|
for ( i = 0 ; i < iCtrls; i++ )
|
||
|
SetDlgItemText(hDlg, aCtrl[i].nIDDlgItem, TEXT(""));
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeave();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ SetDlgItemFromProperty
|
||
|
/ ----------------------
|
||
|
/ Given an IPropertyBag interface set the control with the text for
|
||
|
/ that property. We assume the property is a string.
|
||
|
/
|
||
|
/ In:
|
||
|
/ ppb -> IPropertyBag
|
||
|
/ pszProperty -> property to read
|
||
|
/ hwnd, id = control information
|
||
|
/ pszDefault = default text / = NULL if not important
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
STDAPI SetDlgItemFromProperty(IPropertyBag* ppb, LPCWSTR pszProperty, HWND hwnd, INT id, LPCWSTR pszDefault)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
VARIANT variant;
|
||
|
USES_CONVERSION;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "SetDlgItemFromProperty");
|
||
|
|
||
|
VariantInit(&variant);
|
||
|
|
||
|
if ( ppb && SUCCEEDED(ppb->Read(pszProperty, &variant, NULL)) )
|
||
|
{
|
||
|
if ( V_VT(&variant) == VT_BSTR )
|
||
|
{
|
||
|
pszDefault = V_BSTR(&variant);
|
||
|
Trace(TEXT("property contained: %s"), W2CT(pszDefault));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( pszDefault )
|
||
|
SetDlgItemText(hwnd, id, W2CT(pszDefault));
|
||
|
|
||
|
VariantClear(&variant);
|
||
|
|
||
|
TraceLeaveResult(S_OK);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ Query Persistance
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ PersistQuery
|
||
|
/ ------------
|
||
|
/ Persist a query into a IPersistQuery object
|
||
|
/
|
||
|
/ In:
|
||
|
/ pPersistQuery = query to persist into
|
||
|
/ fRead = read?
|
||
|
/ pSectionName = section name to use when persisting
|
||
|
/ hDlg = DLG to persist from
|
||
|
/ aCtrls / iCtrls = ctrls to be persisted
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
STDAPI PersistQuery(IPersistQuery* pPersistQuery, BOOL fRead, LPCTSTR pSection, HWND hDlg, LPPAGECTRL aCtrl, INT iCtrls)
|
||
|
{
|
||
|
HRESULT hres = S_OK;
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
INT i;
|
||
|
USES_CONVERSION;
|
||
|
|
||
|
TraceEnter(TRACE_IO, "PersistQuery");
|
||
|
|
||
|
if ( !pPersistQuery || !hDlg || (!aCtrl && iCtrls) )
|
||
|
ExitGracefully(hres, E_INVALIDARG, "No data to persist");
|
||
|
|
||
|
for ( i = 0 ; i < iCtrls ; i++ )
|
||
|
{
|
||
|
if ( fRead )
|
||
|
{
|
||
|
if ( SUCCEEDED(pPersistQuery->ReadString(pSection, W2T(aCtrl[i].pPropertyName), szBuffer, ARRAYSIZE(szBuffer))) )
|
||
|
{
|
||
|
Trace(TEXT("Reading property: %s,%s as %s"), pSection, W2T(aCtrl[i].pPropertyName), szBuffer);
|
||
|
SetDlgItemText(hDlg, aCtrl[i].nIDDlgItem, szBuffer);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( GetDlgItemText(hDlg, aCtrl[i].nIDDlgItem, szBuffer, ARRAYSIZE(szBuffer)) )
|
||
|
{
|
||
|
Trace(TEXT("Writing property: %s,%s as %s"), pSection, W2T(aCtrl[i].pPropertyName), szBuffer);
|
||
|
hres = pPersistQuery->WriteString(pSection, W2T(aCtrl[i].pPropertyName), szBuffer);
|
||
|
FailGracefully(hres, "Failed to write control data");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|