windows-nt/Source/XPSP1/NT/ds/adsi/drt/adsqry/main.cxx
2020-09-26 16:20:57 +08:00

847 lines
24 KiB
C++

//----------------------------------------------------------------------------
//
// Microsoft Active Directory 1.1 Sample Code
//
// Copyright (C) Microsoft Corporation, 1996
//
// File: main.cxx
//
// Contents: Main for adsqry
//
//
//----------------------------------------------------------------------------
#include "main.hxx"
#define MAX_SIZE 10
#define USE_OPENROWSET 0
//
// Globals representing the properties
//
DBPROPSET rgDBPropSet[MAX_SIZE], rgCmdPropSet[MAX_SIZE];
DBPROP rgDBProp[MAX_SIZE], rgCmdProp[MAX_SIZE];
ULONG cDBPropSet, cCmdPropSet, cDBProp, cCmdProp;
LPWSTR pszCommandText;
LPWSTR pszSortAttrList = NULL;
#if USE_OPENROWSET
LPWSTR pszTableName;
#endif
GUID rguidDialect = DBGUID_DEFAULT;
DWORD cErr;
int __cdecl
main( int argc, char ** argv)
{
HRESULT hr;
ULONG i;
DBCOUNTITEM j;
HROW * phRows;
WCHAR pszErrorBuf[MAX_PATH], pszNameBuf[MAX_PATH];
DWORD dwError;
OLECHAR * szColNames = NULL;
DBCOLUMNINFO * prgColInfo = NULL;
DBCOLUMNINFO * rgInfo = NULL;
WCHAR * pStringBuffer = NULL;
WCHAR * pColInfoBuffer = NULL;
IMalloc * pIMalloc = NULL;
IDBInitialize * pIDBInit = NULL;
IDBCreateSession * pIDBCS = NULL;
IDBCreateCommand * pIDBCreateCommand = NULL;
ICommandText * pICommandText = NULL;
ICommand * pICommand = NULL;
IRowset * pIRowset = NULL;
IAccessor * pAccessor = NULL;
IColumnsInfo * pIColsInfo = NULL;
DBORDINAL cCol, nAttrs;
DBCOUNTITEM cRowsObtained;
Data * pMyData = NULL;
DBBINDSTATUS * pMyStatus = NULL;
HACCESSOR myAccessor = NULL;
ICommandProperties * pICommandProperties;
IDBProperties * pIDBProperties;
#if USE_OPENROWSET
DBID tableId;
IOpenRowset * pIOpenRowset;
#endif
hr = ProcessArgs(argc, argv);
BAIL_ON_FAILURE(hr);
hr = CoInitialize(NULL);
if (FAILED(hr)) {
printf("CoInitialize failed\n");
exit(1);
}
//
// Instantiate a data source object for LDAP provider
//
hr = CoCreateInstance(
CLSID_ADsDSOObject,
0,
CLSCTX_INPROC_SERVER,
IID_IDBInitialize,
(void **)&pIDBInit
);
if(FAILED(hr)) {
printf("CoCreateInstance failed \n");
goto error;
}
//
// Initialize the Data Source
//
hr = pIDBInit->Initialize();
if(FAILED(hr)) {
printf("IDBIntialize::Initialize failed \n");
goto error;
}
if (cDBPropSet) {
pIDBInit->QueryInterface(
IID_IDBProperties,
(void**) &pIDBProperties);
if(FAILED(hr)) {
printf("QueryInterface for IDBProperties failed \n");
goto error;
}
hr = pIDBProperties->SetProperties(
cDBPropSet,
rgDBPropSet);
if(FAILED(hr)) {
printf("IDBProperties->SetProperties failed \n");
goto error;
}
FREE_INTERFACE(pIDBProperties);
}
pIDBInit->QueryInterface(
IID_IDBCreateSession,
(void**) &pIDBCS);
if(FAILED(hr)) {
printf("QueryInterface for IDBCreateSession failed \n");
goto error;
}
FREE_INTERFACE(pIDBInit);
#if USE_OPENROWSET
//
// Create a session returning a pointer to its IOpenRowset interface
//
hr = pIDBCS->CreateSession(
NULL,
IID_IOpenRowset,
(LPUNKNOWN*) &pIOpenRowset
);
if(FAILED(hr)) {
printf("IDBCreateSession::CreateSession failed \n");
goto error;
}
tableId.eKind = DBKIND_NAME;
tableId.uName.pwszName = pszTableName;
hr = pIOpenRowset->OpenRowset(
NULL,
&tableId,
NULL,
IID_IRowset,
0,
NULL,
(LPUNKNOWN *)&pIRowset
);
BAIL_ON_FAILURE (hr);
FREE_INTERFACE(pIOpenRowset);
FREE_STRING(pszTableName);
#else
//
// Create a session returning a pointer to its CreateCommand interface
//
hr = pIDBCS->CreateSession(
NULL,
IID_IDBCreateCommand,
(LPUNKNOWN*) &pIDBCreateCommand
);
if(FAILED(hr)) {
printf("IDBCreateSession::CreateSession failed \n");
goto error;
}
FREE_INTERFACE(pIDBCS);
//
//
// Create a command from the session object
//
hr = pIDBCreateCommand->CreateCommand(
NULL,
IID_ICommandText,
(LPUNKNOWN*) &pICommandText
);
if(FAILED(hr)) {
printf(" IDBCreateCommand::CreateCommand failed\n");
goto error;
}
FREE_INTERFACE(pIDBCreateCommand);
//
// Set the CommandText for the Query
//
hr = pICommandText->SetCommandText(
rguidDialect,
pszCommandText
);
if(FAILED(hr)) {
printf("ICommandText::SetCommandText failed \n");
goto error;
}
if (cCmdPropSet) {
hr = pICommandText->QueryInterface(
IID_ICommandProperties,
(void**) &pICommandProperties);
if(FAILED(hr)) {
printf("QueryInterface for ICommandProperties failed \n");
goto error;
}
hr = pICommandProperties->SetProperties(
cCmdPropSet,
rgCmdPropSet);
if(FAILED(hr)) {
printf("ICommandProperties:;SetProperties failed \n");
goto error;
}
FREE_INTERFACE(pICommandProperties);
}
hr = pICommandText->QueryInterface(
IID_ICommand,
(void**) &pICommand);
if(FAILED(hr)) {
printf("QueryInterface for ICommand failed \n");
goto error;
}
FREE_INTERFACE(pICommandText);
//
// Do the Query and get back a rowset
//
hr = pICommand->Execute(
NULL,
IID_IRowset,
NULL,
NULL,
(LPUNKNOWN *)&pIRowset
);
if(FAILED(hr)) {
printf("ICommand::Execute failed \n");
goto error;
}
FREE_INTERFACE(pICommand);
#endif
hr = pIRowset->QueryInterface(
IID_IColumnsInfo,
(void**) &pIColsInfo
);
if(FAILED(hr)) {
printf("QueryInterface for IColumnsInfo failed \n");
goto error;
}
hr = pIColsInfo->GetColumnInfo(
&cCol,
&prgColInfo,
&szColNames
);
if(FAILED(hr)) {
printf("IColumnsInfo::GetColumnInfo failed \n");
goto error;
}
//
// The no. of attributes is one less than the no. of columns because of
// the Bookmark column
//
nAttrs = cCol - 1;
pMyStatus = (DBBINDSTATUS *) LocalAlloc(
LPTR,
sizeof(DBBINDSTATUS) * nAttrs
);
BAIL_ON_NULL(pMyStatus);
hr = CreateAccessorHelper(
pIRowset,
nAttrs,
prgColInfo,
&myAccessor,
pMyStatus
);
if(FAILED(hr)) {
printf("CreateAccessorHelper failed \n");
goto error;
}
pMyData = (Data *) LocalAlloc(
LPTR,
sizeof(Data) * nAttrs
);
if(!pMyData) {
hr = E_OUTOFMEMORY;
goto error;
}
//
// Get the rows; 256 at a time
//
phRows = NULL;
hr = pIRowset->GetNextRows(
NULL,
0,
256,
&cRowsObtained,
&phRows
);
if(FAILED(hr)) {
printf("IRowset::GetNextRows failed \n");
goto error;
}
j = cRowsObtained;
while (cRowsObtained) {
for (i = 0; i < cRowsObtained; i++) {
//
// Get the data from each row
//
hr = pIRowset->GetData(
phRows[i],
myAccessor,
(void*)pMyData
);
if(FAILED(hr)) {
printf("IRowset::GetData failed \n");
goto error;
}
PrintData(pMyData, nAttrs, prgColInfo);
}
pIRowset->ReleaseRows(
cRowsObtained,
phRows,
NULL,
NULL,
NULL
);
//
// Get the next 256 rows
//
hr = pIRowset->GetNextRows(
NULL,
0,
256,
&cRowsObtained,
&phRows
);
if(FAILED(hr)) {
printf("IRowset::GetNextRows failed \n");
goto error;
}
j+=cRowsObtained;
}
printf("Rows printed = %d\n", j);
FREE_STRING(pszCommandText);
hr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
//
// Nothing much we can do at this point if this failed.
//
if (FAILED(hr)) {
CoUninitialize();
exit(0);
}
IMALLOC_FREE(pIMalloc, prgColInfo);
IMALLOC_FREE(pIMalloc, szColNames);
FREE_INTERFACE(pIMalloc);
FREE_INTERFACE(pAccessor);
FREE_INTERFACE(pIColsInfo);
FREE_INTERFACE(pIRowset);
LOCAL_FREE(pMyStatus);
LOCAL_FREE(pMyData);
//
// Uninitialize OLE.
//
CoUninitialize();
exit(0);
error:
CoGetMalloc(MEMCTX_TASK, &pIMalloc);
IMALLOC_FREE(pIMalloc, prgColInfo);
IMALLOC_FREE(pIMalloc, szColNames);
FREE_STRING(pszCommandText);
FREE_INTERFACE(pIMalloc);
FREE_INTERFACE(pIDBInit);
FREE_INTERFACE(pIDBCS);
FREE_INTERFACE(pIDBCreateCommand);
FREE_INTERFACE(pICommandText);
FREE_INTERFACE(pICommand);
FREE_INTERFACE(pIRowset);
FREE_INTERFACE(pIColsInfo);
FREE_INTERFACE(pAccessor);
LOCAL_FREE(pMyStatus);
LOCAL_FREE(pMyData);
printf("Errors stopped the Query; hr = %x", hr);
if(hr == ERROR_EXTENDED_ERROR) {
hr = ADsGetLastError(
&dwError,
pszErrorBuf,
MAX_PATH,
pszNameBuf,
MAX_PATH
);
}
if(SUCCEEDED(hr)) {
wprintf(L"Error in %s; %s\n", pszNameBuf, pszErrorBuf);
}
exit(1);
return(0);
}
//+---------------------------------------------------------------------------
//
// Function: ProcessArgs
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
ProcessArgs(
int argc,
char * argv[]
)
{
argc--;
int currArg = 1;
LPWSTR pTemp = NULL;
char *pszCurrPref = NULL, *pszCurrPrefValue = NULL;
LPWSTR pszSearchBase = NULL, pszSearchFilter = NULL, pszAttrList = NULL;
LPWSTR pszUserName = NULL, pszPassword = NULL;
DWORD dwAuthFlags;
cCmdProp = cDBProp = 0;
while (argc) {
if (argv[currArg][0] != '/' && argv[currArg][0] != '-')
BAIL_ON_FAILURE (E_FAIL);
switch (argv[currArg][1]) {
case 'b':
argc--;
currArg++;
if (argc <= 0)
BAIL_ON_FAILURE (E_FAIL);
pszSearchBase = AllocateUnicodeString(argv[currArg]);
BAIL_ON_NULL(pszSearchBase);
break;
case 'f':
argc--;
currArg++;
if (argc <= 0)
BAIL_ON_FAILURE (E_FAIL);
pszSearchFilter = AllocateUnicodeString(argv[currArg]);
BAIL_ON_NULL(pszSearchFilter);
break;
case 'd':
argc--;
currArg++;
if (argc <= 0)
BAIL_ON_FAILURE (E_FAIL);
if (!_stricmp(argv[currArg], "sql"))
rguidDialect = DBGUID_SQL;
else if (!_stricmp(argv[currArg], "ldap"))
rguidDialect = DBGUID_LDAPDialect;
else if (!_stricmp(argv[currArg], "default"))
rguidDialect = DBGUID_DEFAULT;
else
BAIL_ON_FAILURE (E_FAIL);
break;
case 'a':
argc--;
currArg++;
if (argc <= 0)
BAIL_ON_FAILURE (E_FAIL);
pszAttrList = AllocateUnicodeString(argv[currArg]);
BAIL_ON_NULL(pszAttrList);
break;
case 'u':
argc--;
currArg++;
if (argc <= 0)
BAIL_ON_FAILURE (E_FAIL);
pszUserName = AllocateUnicodeString(argv[currArg]);
BAIL_ON_NULL(pszUserName);
argc--;
currArg++;
if (argc <= 0)
BAIL_ON_FAILURE (E_FAIL);
pszPassword = AllocateUnicodeString(argv[currArg]);
BAIL_ON_NULL(pszPassword);
rgDBProp[cDBProp].dwPropertyID = DBPROP_AUTH_USERID;
rgDBProp[cDBProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBProp[cDBProp].vValue.vt = VT_BSTR;
V_BSTR (&rgDBProp[cDBProp].vValue) = SysAllocString(pszUserName);
cDBProp++;
rgDBProp[cDBProp].dwPropertyID = DBPROP_AUTH_PASSWORD;
rgDBProp[cDBProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBProp[cDBProp].vValue.vt = VT_BSTR;
V_BSTR (&rgDBProp[cDBProp].vValue) = SysAllocString(pszPassword);
cDBProp++;
break;
case 'p':
argc--;
currArg++;
if (argc <= 0)
BAIL_ON_FAILURE (E_FAIL);
pszCurrPref = strtok(argv[currArg], "=");
pszCurrPrefValue = strtok(NULL, "=");
if (!pszCurrPref || !pszCurrPrefValue)
BAIL_ON_FAILURE(E_FAIL);
if (!_stricmp(pszCurrPref, "asynchronous")) {
rgCmdProp[cCmdProp].dwPropertyID = ADSIPROP_ASYNCHRONOUS;
rgCmdProp[cCmdProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[cCmdProp].vValue.vt = VT_BOOL;
if (!_stricmp(pszCurrPrefValue, "yes" ))
V_BOOL (&rgCmdProp[cCmdProp].vValue) = VARIANT_TRUE;
else if (!_stricmp(pszCurrPrefValue, "no" ))
V_BOOL (&rgCmdProp[cCmdProp].vValue) = VARIANT_FALSE;
else
BAIL_ON_FAILURE(E_FAIL);
cCmdProp++;
}
else if (!_stricmp(pszCurrPref, "attrTypesOnly")) {
rgCmdProp[cCmdProp].dwPropertyID = ADSIPROP_ATTRIBTYPES_ONLY;
rgCmdProp[cCmdProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[cCmdProp].vValue.vt = VT_BOOL;
if (!_stricmp(pszCurrPrefValue, "yes" ))
V_BOOL (&rgCmdProp[cCmdProp].vValue) = VARIANT_TRUE;
else if (!_stricmp(pszCurrPrefValue, "no" ))
V_BOOL (&rgCmdProp[cCmdProp].vValue) = VARIANT_FALSE;
else
BAIL_ON_FAILURE(E_FAIL);
cCmdProp++;
}
else if (!_stricmp(pszCurrPref, "SecureAuth")) {
if (!_stricmp(pszCurrPrefValue, "yes" ))
dwAuthFlags |= ADS_SECURE_AUTHENTICATION;
else if (!_stricmp(pszCurrPrefValue, "no" ))
dwAuthFlags &= ~ADS_SECURE_AUTHENTICATION;
else
BAIL_ON_FAILURE(E_FAIL);
rgDBProp[cDBProp].dwPropertyID = DBPROP_AUTH_ENCRYPT_PASSWORD;
rgDBProp[cDBProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBProp[cDBProp].vValue.vt = VT_BSTR;
V_BSTR (&rgDBProp[cDBProp].vValue) = SysAllocString(pszPassword);
cDBProp++;
}
else if (!_stricmp(pszCurrPref, "derefAliases")) {
rgCmdProp[cCmdProp].dwPropertyID = ADSIPROP_DEREF_ALIASES;
rgCmdProp[cCmdProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[cCmdProp].vValue.vt = VT_BOOL;
if (!_stricmp(pszCurrPrefValue, "yes" ))
V_BOOL (&rgCmdProp[cCmdProp].vValue) = VARIANT_TRUE;
else if (!_stricmp(pszCurrPrefValue, "no" ))
V_BOOL (&rgCmdProp[cCmdProp].vValue) = VARIANT_FALSE;
else
BAIL_ON_FAILURE(E_FAIL);
cCmdProp++;
}
else if (!_stricmp(pszCurrPref, "timeOut")) {
rgCmdProp[cCmdProp].dwPropertyID = ADSIPROP_TIMEOUT;
rgCmdProp[cCmdProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[cCmdProp].vValue.vt = VT_I4;
V_I4 (&rgCmdProp[cCmdProp].vValue) = atoi(pszCurrPrefValue);
cCmdProp++;
}
else if (!_stricmp(pszCurrPref, "timeLimit")) {
rgCmdProp[cCmdProp].dwPropertyID = ADSIPROP_TIME_LIMIT;
rgCmdProp[cCmdProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[cCmdProp].vValue.vt = VT_I4;
V_I4 (&rgCmdProp[cCmdProp].vValue) = atoi(pszCurrPrefValue);
cCmdProp++;
}
else if (!_stricmp(pszCurrPref, "sizeLimit")) {
rgCmdProp[cCmdProp].dwPropertyID = ADSIPROP_SIZE_LIMIT;
rgCmdProp[cCmdProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[cCmdProp].vValue.vt = VT_I4;
V_I4 (&rgCmdProp[cCmdProp].vValue) = atoi(pszCurrPrefValue);
cCmdProp++;
}
else if (!_stricmp(pszCurrPref, "PageSize")) {
rgCmdProp[cCmdProp].dwPropertyID = ADSIPROP_PAGESIZE;
rgCmdProp[cCmdProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[cCmdProp].vValue.vt = VT_I4;
V_I4 (&rgCmdProp[cCmdProp].vValue) = atoi(pszCurrPrefValue);
cCmdProp++;
}
else if (!_stricmp(pszCurrPref, "PagedTimeLimit")) {
rgCmdProp[cCmdProp].dwPropertyID = ADSIPROP_PAGED_TIME_LIMIT;
rgCmdProp[cCmdProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[cCmdProp].vValue.vt = VT_I4;
V_I4 (&rgCmdProp[cCmdProp].vValue) = atoi(pszCurrPrefValue);
cCmdProp++;
}
else if (!_stricmp(pszCurrPref, "SearchScope")) {
rgCmdProp[cCmdProp].dwPropertyID = ADSIPROP_SEARCH_SCOPE;
rgCmdProp[cCmdProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[cCmdProp].vValue.vt = VT_I4;
if (!_stricmp(pszCurrPrefValue, "Base" ))
V_I4 (&rgCmdProp[cCmdProp].vValue) = ADS_SCOPE_BASE;
else if (!_stricmp(pszCurrPrefValue, "OneLevel" ))
V_I4 (&rgCmdProp[cCmdProp].vValue) = ADS_SCOPE_ONELEVEL;
else if (!_stricmp(pszCurrPrefValue, "Subtree" ))
V_I4 (&rgCmdProp[cCmdProp].vValue) = ADS_SCOPE_SUBTREE;
else
BAIL_ON_FAILURE(E_FAIL);
cCmdProp++;
}
else if (!_stricmp(pszCurrPref, "ChaseReferrals")) {
rgCmdProp[cCmdProp].dwPropertyID = ADSIPROP_CHASE_REFERRALS;
rgCmdProp[cCmdProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[cCmdProp].vValue.vt = VT_I4;
if (!_stricmp(pszCurrPrefValue, "always" ))
V_I4 (&rgCmdProp[cCmdProp].vValue) = ADS_CHASE_REFERRALS_ALWAYS;
else if (!_stricmp(pszCurrPrefValue, "never" ))
V_I4 (&rgCmdProp[cCmdProp].vValue) = ADS_CHASE_REFERRALS_NEVER;
else if (!_stricmp(pszCurrPrefValue, "external" ))
V_I4 (&rgCmdProp[cCmdProp].vValue) = ADS_CHASE_REFERRALS_EXTERNAL;
else if (!_stricmp(pszCurrPrefValue, "subordinate" ))
V_I4 (&rgCmdProp[cCmdProp].vValue) = ADS_CHASE_REFERRALS_SUBORDINATE;
else
BAIL_ON_FAILURE(E_FAIL);
cCmdProp++;
}
else if (!_stricmp(pszCurrPref, "cacheResults")) {
rgCmdProp[cCmdProp].dwPropertyID = ADSIPROP_CACHE_RESULTS;
rgCmdProp[cCmdProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[cCmdProp].vValue.vt = VT_BOOL;
if (!_stricmp(pszCurrPrefValue, "yes" ))
V_BOOL (&rgCmdProp[cCmdProp].vValue) = VARIANT_TRUE;
else if (!_stricmp(pszCurrPrefValue, "no" ))
V_BOOL (&rgCmdProp[cCmdProp].vValue) = VARIANT_FALSE;
else
BAIL_ON_FAILURE(E_FAIL);
cCmdProp++;
}
else if (!_stricmp(pszCurrPref, "sortOn")) {
pszSortAttrList = AllocateUnicodeString(pszCurrPrefValue);
}
else
BAIL_ON_FAILURE(E_FAIL);
break;
default:
BAIL_ON_FAILURE(E_FAIL);
}
argc--;
currArg++;
}
//
// Check for Mandatory arguments;
//
if (!pszSearchBase || !pszSearchFilter || !pszAttrList)
BAIL_ON_FAILURE(E_FAIL);
#if USE_OPENROWSET
pszTableName = AllocADsStr(
pszSearchBase
);
BAIL_ON_NULL(E_FAIL);
#endif
if (IsEqualGUID(rguidDialect, DBGUID_SQL) ) {
// if sorting is specified, add to the command text itself
//
DWORD sortAttrLen = pszSortAttrList ?
wcslen(L" ORDER BY ") + wcslen(pszSortAttrList) : 0;
pszCommandText = (LPWSTR) AllocADsMem(
(wcslen(pszSearchBase) +
wcslen(pszSearchFilter) +
wcslen(pszAttrList) +
wcslen(L"''") +
wcslen(L"SELECT ") +
wcslen(L" FROM ") +
wcslen(L" WHERE ") +
sortAttrLen +
1) * sizeof(WCHAR)
);
BAIL_ON_NULL(E_FAIL);
wcscpy(pszCommandText, L"SELECT ");
wcscat(pszCommandText, pszAttrList);
wcscat(pszCommandText, L" FROM '");
wcscat(pszCommandText, pszSearchBase);
wcscat(pszCommandText, L"' WHERE ");
wcscat(pszCommandText, pszSearchFilter);
if (pszSortAttrList) {
wcscat(pszCommandText, L" ORDER BY ");
wcscat(pszCommandText, pszSortAttrList);
}
} else {
pszCommandText = (LPWSTR) AllocADsMem(
(wcslen(pszSearchBase) +
wcslen(pszSearchFilter) +
wcslen(pszAttrList) +
5) * sizeof(WCHAR)
);
BAIL_ON_NULL(E_FAIL);
wcscpy(pszCommandText, L"<");
wcscat(pszCommandText, pszSearchBase);
wcscat(pszCommandText, L">;");
wcscat(pszCommandText, pszSearchFilter);
wcscat(pszCommandText, L";");
wcscat(pszCommandText, pszAttrList);
if (pszSortAttrList) {
// if sorting is specified, add as a command property
rgCmdProp[cCmdProp].dwPropertyID = ADSIPROP_SORT_ON;
rgCmdProp[cCmdProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[cCmdProp].vValue.vt = VT_BSTR;
V_BSTR (&rgCmdProp[cCmdProp].vValue) = AllocateUnicodeString(pszCurrPrefValue);
cCmdProp++;
}
}
if (cDBProp > 0) {
cDBPropSet = 1;
rgDBPropSet[0].rgProperties = rgDBProp;
rgDBPropSet[0].cProperties = cDBProp;
rgDBPropSet[0].guidPropertySet = DBPROPSET_DBINIT;
}
if (cCmdProp > 0) {
cCmdPropSet = 1;
rgCmdPropSet[0].rgProperties = rgCmdProp;
rgCmdPropSet[0].cProperties = cCmdProp;
rgCmdPropSet[0].guidPropertySet = DBPROPSET_ADSISEARCH;
}
FreeUnicodeString(pszSearchBase) ;
FreeUnicodeString(pszSearchFilter) ;
FreeUnicodeString(pszAttrList) ;
return (S_OK);
error:
FreeUnicodeString(pszSearchBase) ;
FreeUnicodeString(pszSearchFilter) ;
FreeUnicodeString(pszAttrList) ;
PrintUsage();
return E_FAIL;
}