Leaked source code of windows server 2003
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.
 
 
 
 
 
 

927 lines
31 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000
//
// File: querybld.cpp
//
// Contents: Contains implementatin of functions to build query.
//
// History: 24-Sep-2000 Hiteshr Created
//
//
//--------------------------------------------------------------------------
#include "pch.h"
#include "cstrings.h"
#include "querytable.h"
#include "usage.h"
#include "querybld.h"
#include "resource.h" // For IDS_MSG_INVALID_ACCT_ERROR
#include <lmaccess.h> // UF_ACCOUNTDISABLE and UF_DONT_EXPIRE_PASSWD
#include <ntldap.h> // LDAP_MATCHING_RULE_BIT_AND_W
#include <Sddl.h> // For ConvertSidToStringSid
static const LPWSTR g_szUserAccountCtrlQuery = L"(userAccountControl:" LDAP_MATCHING_RULE_BIT_AND_W L":=%u)";
static const LPWSTR g_szServerIsGCQuery = L"(&(objectCategory=NTDS-DSA)(options:" LDAP_MATCHING_RULE_BIT_AND_W L":=1))";
static const LPWSTR g_szCommonQueryFormat= L"(%s=%s)";
//+--------------------------------------------------------------------------
//
// Function: LdapEscape
//
// Synopsis: Escape the characters in *[pszInput] as required by
// RFC 2254.
//
// Arguments: [pszInput] - string to escape
//
// History: 06-23-2000 DavidMun Created
//
// Notes: RFC 2254
//
// If a value should contain any of the following characters
//
// Character ASCII value
// ---------------------------
// * 0x2a
// ( 0x28
// ) 0x29
// \ 0x5c
// NUL 0x00
//
// the character must be encoded as the backslash '\'
// character (ASCII 0x5c) followed by the two hexadecimal
// digits representing the ASCII value of the encoded
// character. The case of the two hexadecimal digits is not
// significant.
//
//---------------------------------------------------------------------------
bool
LdapEscape(IN LPCWSTR pszInput, OUT CComBSTR& strFilter)
{
if(!pszInput)
return FALSE;
//Security Review:pszInput is null terminated.
int iLen = (int)wcslen(pszInput);
for( int i = 0; i < iLen; ++i)
{
switch (*(pszInput+i))
{
case L'(':
strFilter += L"\\28";
break;
case L')':
strFilter += L"\\29";
break;
case L'\\':
if( i + 1 < iLen )
{
// \\ is treated as '\'
switch (*(pszInput+i + 1))
{
case L'\\':
strFilter += L"\\5c";
i++;
break;
// \* is treated as '*'
case L'*':
strFilter += L"\\2a";
i++;
break;
default:
// \X is treated \X only
strFilter += L"\\5c";
break;
}
}
else
strFilter += L"\\5c";
break;
default:
strFilter.Append(pszInput+i,1);
break;
}
}
return TRUE;
}
HRESULT MakeQuery(IN LPCWSTR pszAttrName,
IN LPCWSTR pszCommandLineFilter,
OUT CComBSTR& strFilter)
{
ENTER_FUNCTION_HR(LEVEL3_LOGGING, MakeQuery, hr);
if(!pszAttrName || !pszCommandLineFilter)
{
ASSERT(FALSE);
hr = E_INVALIDARG;
return hr;
}
CComBSTR strEscapedCLFilter;
LdapEscape(pszCommandLineFilter,strEscapedCLFilter);
strFilter = L"(";
strFilter += pszAttrName;
strFilter += L"=";
strFilter += strEscapedCLFilter;
strFilter += L")";
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: CommonFilterFunc
//
// Synopsis: This function takes the input filter from the commandline
// and converts it into ldapfilter.
// For ex -user (ab* | bc*) is converted to |(cn=ab*)(cn=bc*)
// The pEntry->pszName given the attribute name to use in
// filter( cn in above example).
//
// Arguments: [pRecord - IN] : the command line argument structure used
// to retrieve the filter entered by user
// [pObjectEntry - IN] : pointer to the DSQUERY_ATTR_TABLE_ENTRY
// which has info on attribute corresponding
// switch in pRecord
// [pVoid - IN] :Not used.
// [strFilter - OUT] :Contains the output filter.
// Returns: HRESULT : S_OK if everything succeeded
// E_INVALIDARG if the object entry wasn't found
// Anything else is a failure code from an ADSI call
//
// History: 25-Sep-2000 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT CommonFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
IN ARG_RECORD* pRecord,
IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
IN CDSCmdCredentialObject& /*refCredentialObject*/,
IN PVOID ,
OUT CComBSTR& strFilter)
{
ENTER_FUNCTION_HR(LEVEL3_LOGGING, CommonFilterFunc, hr);
//validate input
if( !pEntry || !pRecord
//validate DSQUERY_ATTR_TABLE_ENTRY entry
|| !pEntry->pszName || !pEntry->nAttributeID
//validate pRecord
|| !pRecord->bDefined || !pRecord->strValue)
{
ASSERT(FALSE);
hr = E_INVALIDARG;
return hr;
}
//Make Query
hr = MakeQuery(pEntry->pszName,
pRecord->strValue,
strFilter);
DEBUG_OUTPUT(LEVEL3_LOGGING, L"filter = %s", strFilter);
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: StarFilterFunc
//
// Synopsis: Filter Function for dsquery *. It returns the value of
// -filter flag.
//
// Arguments: [pRecord - IN] : the command line argument structure used
// to retrieve the filter entered by user
// [pObjectEntry - IN] : pointer to the DSQUERY_ATTR_TABLE_ENTRY
// which has info on attribute corresponding
// switch in pRecord
// [pVoid - IN] :Not used.
// [strFilter - OUT] :Contains the output filter.
// Returns: HRESULT : S_OK if everything succeeded
// E_INVALIDARG if the object entry wasn't found
// Anything else is a failure code from an ADSI call
//
// History: 25-Sep-2000 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT StarFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
IN ARG_RECORD* pRecord,
IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
IN CDSCmdCredentialObject& /*refCredentialObject*/,
IN PVOID ,
OUT CComBSTR& strFilter)
{
ENTER_FUNCTION_HR(LEVEL3_LOGGING, StarFilterFunc, hr);
//validate input
if(!pEntry || !pRecord
//validate DSQUERY_ATTR_TABLE_ENTRY entry
|| !pEntry->nAttributeID
//validate pRecord
|| !pRecord->bDefined || !pRecord->strValue)
{
ASSERT(FALSE);
hr = E_INVALIDARG;
return hr;
}
strFilter = pRecord->strValue;
DEBUG_OUTPUT(LEVEL3_LOGGING, L"filter = %s", strFilter);
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: InactiveComputerFilterFunc
//
// Synopsis: Filter Function for computer inactive query.
//
// Arguments: [pRecord - IN] : Not Used
// [pObjectEntry - IN] : Not Used
// [pVoid - IN] :Not used.
// [strFilter - OUT] :Contains the output filter.
// Returns: HRESULT : S_OK if everything succeeded
// E_INVALIDARG if the object entry wasn't found
// Anything else is a failure code from an ADSI call
//
// History: 06-05-2002 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT InactiveComputerFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
IN ARG_RECORD* pRecord,
IN CDSCmdBasePathsInfo& refBasePathsInfo,
IN CDSCmdCredentialObject& refCredentialObject,
IN PVOID pData,
OUT CComBSTR& strFilter)
{
return InactiveFilterFunc(pEntry,
pRecord,
refBasePathsInfo,
refCredentialObject,
pData,
strFilter,
true);
}
//+--------------------------------------------------------------------------
//
// Function: InactiveUserFilterFunc
//
// Synopsis: Filter Function for user inactive query.
//
// Arguments: [pRecord - IN] : Not Used
// [pObjectEntry - IN] : Not Used
// [pVoid - IN] :Not used.
// [strFilter - OUT] :Contains the output filter.
// Returns: HRESULT : S_OK if everything succeeded
// E_INVALIDARG if the object entry wasn't found
// Anything else is a failure code from an ADSI call
//
// History: 25-Sep-2000 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT InactiveUserFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
IN ARG_RECORD* pRecord,
IN CDSCmdBasePathsInfo& refBasePathsInfo,
IN CDSCmdCredentialObject& refCredentialObject,
IN PVOID pData,
OUT CComBSTR& strFilter)
{
return InactiveFilterFunc(pEntry,
pRecord,
refBasePathsInfo,
refCredentialObject,
pData,
strFilter,
false);
}
//+--------------------------------------------------------------------------
//
// Function: InactiveFilterFunc
//
// Synopsis: Filter Function for account inactive query.
//
// Arguments: [pRecord - IN] : Not Used
// [pObjectEntry - IN] : Not Used
// [pVoid - IN] :Not used.
// [strFilter - OUT] :Contains the output filter.
// [bComputer]: if true query is for inactive computer accounts
// Returns: HRESULT : S_OK if everything succeeded
// E_INVALIDARG if the object entry wasn't found
// Anything else is a failure code from an ADSI call
//
// History: 25-Sep-2000 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT InactiveFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
IN ARG_RECORD* pRecord,
IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
IN CDSCmdCredentialObject& /*refCredentialObject*/,
IN PVOID ,
OUT CComBSTR& strFilter,
IN bool bComputer)
{
ENTER_FUNCTION_HR(LEVEL3_LOGGING, InactiveFilterFunc, hr);
if( !pEntry || !pRecord || !pRecord->bDefined )
{
hr = E_INVALIDARG;
return hr;
}
if(pRecord->nValue < 0 )
{
hr = E_INVALIDARG;
return hr;
}
//
//Unit at commandline is Week
//
int nDays = pRecord->nValue * 7;
FILETIME ftCurrent;
::GetSystemTimeAsFileTime(&ftCurrent);
LARGE_INTEGER li;
li.LowPart = ftCurrent.dwLowDateTime;
li.HighPart = ftCurrent.dwHighDateTime;
//
//Get the number of days since the reference time
//
int nDaysSince1600 = (int)(li.QuadPart/(((LONGLONG) (24 * 60) * 60) * 10000000));
if(nDaysSince1600 < nDays)
{
hr = E_INVALIDARG;
return hr;
}
li.QuadPart -= ((((LONGLONG)nDays * 24) * 60) * 60) * 10000000;
CComBSTR strTime;
litow(li, strTime);
WCHAR buffer[256];
//Security Review:Replace with strsafe api
//NTRAID#NTBUG9-573989-2002/03/12-hiteshr
if(bComputer)
{
//NTRAID#NTBUG9-616892-2002/06/05-hiteshr
//Cluster creates some virtual computers which never update password or login and
//these accounts should not be displayed by dsquery computer -[inactive|stalepwd]
hr = StringCchPrintf(buffer,256,L"(!(serviceprincipalname=msclustervirtualserver/*))(lastLogonTimestamp<=%s)",(LPCWSTR)strTime);
}
else
{
hr = StringCchPrintf(buffer,256,L"(lastLogonTimestamp<=%s)",(LPCWSTR)strTime);
}
if(SUCCEEDED(hr))
{
strFilter = buffer;
DEBUG_OUTPUT(LEVEL3_LOGGING, L"filter = %s", strFilter);
}
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: StalepwdComputerFilterFunc
//
// Synopsis: Filter Function for Stale Computer Password query.
//
// Arguments: [pRecord - IN] : Not Used
// [pObjectEntry - IN] : Not Used
// [pVoid - IN] :Not used.
// [strFilter - OUT] :Contains the output filter.
// Returns: HRESULT : S_OK if everything succeeded
// E_INVALIDARG if the object entry wasn't found
// Anything else is a failure code from an ADSI call
//
// History: 25-Sep-2000 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT StalepwdComputerFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
IN ARG_RECORD* pRecord,
IN CDSCmdBasePathsInfo& refBasePathsInfo,
IN CDSCmdCredentialObject& refCredentialObject,
IN PVOID pData,
OUT CComBSTR& strFilter)
{
return StalepwdFilterFunc(pEntry,
pRecord,
refBasePathsInfo,
refCredentialObject,
pData,
strFilter,
true);
}
//+--------------------------------------------------------------------------
//
// Function: StalepwdUserFilterFunc
//
// Synopsis: Filter Function for Stale User Password query.
//
// Arguments: [pRecord - IN] : Not Used
// [pObjectEntry - IN] : Not Used
// [pVoid - IN] :Not used.
// [strFilter - OUT] :Contains the output filter.
// Returns: HRESULT : S_OK if everything succeeded
// E_INVALIDARG if the object entry wasn't found
// Anything else is a failure code from an ADSI call
//
// History: 25-Sep-2000 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT StalepwdUserFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
IN ARG_RECORD* pRecord,
IN CDSCmdBasePathsInfo& refBasePathsInfo,
IN CDSCmdCredentialObject& refCredentialObject,
IN PVOID pData,
OUT CComBSTR& strFilter)
{
return StalepwdFilterFunc(pEntry,
pRecord,
refBasePathsInfo,
refCredentialObject,
pData,
strFilter,
false);
}
//+--------------------------------------------------------------------------
//
// Function: StalepwdFilterFunc
//
// Synopsis: Filter Function for Stale Password query.
//
// Arguments: [pRecord - IN] : Not Used
// [pObjectEntry - IN] : Not Used
// [pVoid - IN] :Not used.
// [strFilter - OUT] :Contains the output filter.
// [bComputer]: if true query is for inactive computer accounts
// Returns: HRESULT : S_OK if everything succeeded
// E_INVALIDARG if the object entry wasn't found
// Anything else is a failure code from an ADSI call
//
// History: 25-Sep-2000 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT StalepwdFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
IN ARG_RECORD* pRecord,
IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
IN CDSCmdCredentialObject& /*refCredentialObject*/,
IN PVOID ,
OUT CComBSTR& strFilter,
bool bComputer)
{
ENTER_FUNCTION_HR(LEVEL3_LOGGING, StalepwdFilterFunc, hr);
if( !pEntry || !pRecord || !pRecord->bDefined )
{
hr = E_INVALIDARG;
return hr;
}
int nDays = pRecord->nValue;
if(nDays < 0)
{
hr = E_INVALIDARG;
return hr;
}
FILETIME ftCurrent;
::GetSystemTimeAsFileTime(&ftCurrent);
LARGE_INTEGER li;
li.LowPart = ftCurrent.dwLowDateTime;
li.HighPart = ftCurrent.dwHighDateTime;
//
//Get the number of days since the reference time
//
int nDaysSince1600 = (int)(li.QuadPart/(((LONGLONG) (24 * 60) * 60) * 10000000));
if(nDaysSince1600 < nDays)
{
hr = E_INVALIDARG;
return hr;
}
li.QuadPart -= ((((ULONGLONG)nDays * 24) * 60) * 60) * 10000000;
CComBSTR strTime;
litow(li, strTime);
WCHAR buffer[256];
//Security Review:Replace with strsafe api
//NTRAID#NTBUG9-573989-2002/03/12-hiteshr
if(bComputer)
{
//NTRAID#NTBUG9-616892-2002/06/05-hiteshr
//Cluster creates some virtual computers which never update password or login and
//these accounts should not be displayed by dsquery computer -[inactive|stalepwd]
hr = StringCchPrintf(buffer,256,L"(!(serviceprincipalname=msclustervirtualserver/*))(pwdLastSet<=%s)",(LPCWSTR)strTime);
}
else
{
hr = StringCchPrintf(buffer,256,L"(pwdLastSet<=%s)",(LPCWSTR)strTime);
}
if(SUCCEEDED(hr))
{
strFilter = buffer;
DEBUG_OUTPUT(LEVEL3_LOGGING, L"filter = %s", strFilter);
}
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: DisabledFilterFunc
//
// Synopsis: Filter Function for account disabled query.
//
// Arguments: [pRecord - IN] : Not Used
// [pObjectEntry - IN] : Not Used
// [pVoid - IN] :Not used.
// [strFilter - OUT] :Contains the output filter.
// Returns: HRESULT : S_OK if everything succeeded
// E_INVALIDARG if the object entry wasn't found
// Anything else is a failure code from an ADSI call
//
// History: 25-Sep-2000 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT DisabledFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *,
IN ARG_RECORD* ,
IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
IN CDSCmdCredentialObject& /*refCredentialObject*/,
IN PVOID ,
OUT CComBSTR& strFilter)
{
ENTER_FUNCTION_HR(LEVEL3_LOGGING, DisabledFilterFunc, hr);
WCHAR buffer[256]; //This is long enough
//Security Review:Replace with strsafe api
//NTRAID#NTBUG9-573989-2002/03/12-hiteshr
hr = StringCchPrintf(buffer,256,g_szUserAccountCtrlQuery,UF_ACCOUNTDISABLE);
if(SUCCEEDED(hr))
{
strFilter = buffer;
DEBUG_OUTPUT(LEVEL3_LOGGING, L"filter = %s", strFilter);
}
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: SubnetSiteFilterFunc
//
// Synopsis: Filter Function for -site switch in dsquery subnet.
//
// Arguments: [pEntry - IN] : Not Used
// [pRecord - IN] : Command Line value supplied by user
// [pVoid - IN] : suffix for the siteobject attribute.
// [strFilter - OUT] :Contains the output filter.
// Returns: HRESULT : S_OK if everything succeeded
//
// History: 24-April-2001 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT SubnetSiteFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *,
IN ARG_RECORD* pRecord,
IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
IN CDSCmdCredentialObject& /*refCredentialObject*/,
IN PVOID pParam,
OUT CComBSTR& strFilter)
{
ENTER_FUNCTION_HR(LEVEL3_LOGGING, InactiveFilterFunc, hr);
if( !pRecord || !pRecord->bDefined || !pParam)
{
hr = E_INVALIDARG;
return hr;
}
CComBSTR strEscapedCLFilter;
LdapEscape(pRecord->strValue,strEscapedCLFilter);
strFilter = L"(siteobject=cn=";
strFilter += strEscapedCLFilter;
strFilter += L",";
strFilter += *(static_cast<BSTR*>(pParam));
strFilter += L")";
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: BuildQueryFilter
//
// Synopsis: This function builds the LDAP query filter for given object type.
//
// Arguments: [pCommandArgs - IN] :the command line argument structure used
// to retrieve the values of switches
// [pObjectEntry - IN] :Contains info about the object type
// [pParam -IN] :This value is passed to filter function.
// [strLDAPFilter - OUT] :Contains the output filter.
// Returns: HRESULT : S_OK if everything succeeded
// E_INVALIDARG if the object entry wasn't found
// Anything else is a failure code from an ADSI call
//
// History: 25-Sep-2000 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT BuildQueryFilter(PARG_RECORD pCommandArgs,
PDSQueryObjectTableEntry pObjectEntry,
CDSCmdBasePathsInfo& refBasePathsInfo,
CDSCmdCredentialObject& refCredentialObject,
PVOID pParam,
CComBSTR& strLDAPFilter)
{
ENTER_FUNCTION_HR(LEVEL3_LOGGING, BuildQueryFilter, hr);
if( !pCommandArgs || !pObjectEntry )
{
ASSERT(FALSE);
hr = E_INVALIDARG;
return hr;
}
DSQUERY_ATTR_TABLE_ENTRY** pAttributeTable;
DWORD dwAttributeCount;
pAttributeTable = pObjectEntry->pAttributeTable;
dwAttributeCount = pObjectEntry->dwAttributeCount;
if( !pAttributeTable || !dwAttributeCount )
{
hr = E_INVALIDARG;
return hr;
}
BOOL bUseDefaultFilter = TRUE;
CComBSTR strFilter;
for( UINT i = 0; i < dwAttributeCount; ++i )
{
if(pCommandArgs[pAttributeTable[i]->nAttributeID].bDefined)
{
bUseDefaultFilter = FALSE;
CComBSTR strLocalFilter;
hr = pAttributeTable[i]->pMakeFilterFunc(pAttributeTable[i],
pCommandArgs + pAttributeTable[i]->nAttributeID,
refBasePathsInfo,
refCredentialObject,
pParam,
strLocalFilter);
if(FAILED(hr))
return hr;
strFilter += strLocalFilter;
DEBUG_OUTPUT(FULL_LOGGING, L"Current filter = %s", strFilter);
}
}
//
//If none of the commandline filter switches are specified, use
//default filter
//
strLDAPFilter = L"(";
if(bUseDefaultFilter)
{
strLDAPFilter += pObjectEntry->pszDefaultFilter;
}
else
{
if(pObjectEntry->pszPrefixFilter)
{
strLDAPFilter += pObjectEntry->pszPrefixFilter;
strLDAPFilter += strFilter;
}
else
strLDAPFilter += strFilter;
}
strLDAPFilter += L")";
DEBUG_OUTPUT(LEVEL3_LOGGING, L"ldapfilter = %s", strLDAPFilter);
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: QLimitFilterFunc
//
// Synopsis: Filter Function for -qlimit switch in dsquery quota.
//
// Arguments: [pEntry - IN] : Not Used
// [pRecord - IN] : Command Line value supplied by user
// [pVoid - IN] : unused.
// [strFilter - OUT] :Contains the output filter.
// Returns: HRESULT : S_OK if everything succeeded
//
// History: 13-Aug-2002 ronmart Created
//
//---------------------------------------------------------------------------
HRESULT QLimitFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *,
IN ARG_RECORD* pRecord,
IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
IN CDSCmdCredentialObject& /*refCredentialObject*/,
IN PVOID,
OUT CComBSTR& strFilter)
{
ENTER_FUNCTION_HR(LEVEL3_LOGGING, QLimitFilterFunc, hr);
if( !pRecord || !pRecord->bDefined)
{
hr = E_INVALIDARG;
return hr;
}
// Build the quotaAmount string
strFilter = L"(msDS-QuotaAmount";
strFilter += pRecord->strValue;
strFilter += L")";
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: AccountFilterFunc
//
// Synopsis: Filter Function for -acct switch in dsquery quota.
//
// Arguments: [pEntry - IN] : Not Used
// [pRecord - IN] : Command Line value supplied by user
// [pVoid - IN] : Not Used
// [strFilter - OUT] :Contains the output filter.
// Returns: HRESULT : S_OK if everything succeeded
//
// History: 14-Aug-2002 ronmart Created
//
//---------------------------------------------------------------------------
HRESULT AccountFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *,
IN ARG_RECORD* pRecord,
IN CDSCmdBasePathsInfo& refBasePathsInfo,
IN CDSCmdCredentialObject& refCredentialObject,
IN PVOID ,
OUT CComBSTR& strFilter)
{
ENTER_FUNCTION_HR(LEVEL3_LOGGING, AccountFilterFunc, hr);
if( !pRecord || !pRecord->bDefined || !refBasePathsInfo.IsInitialized())
{
hr = E_INVALIDARG;
return hr;
}
PWSTR* ppszArray = NULL; // Array of accts from param or STDIN
do // false loop
{
// Get the accts (trustees)
UINT nStrings = 0;
ParseNullSeparatedString(pRecord->strValue,
&ppszArray,
&nStrings);
if (nStrings < 1 ||
!ppszArray)
{
ASSERT(false); // This should never happen
hr = E_OUTOFMEMORY;
break;
}
// Or the return values together
strFilter = L"(|";
// Get a trustee query for each acct
for(UINT i = 0; i < nStrings; i++)
{
// Append (msDS-QuotaTrustee=<sid>) for this acct
// to the filter
hr = AddSingleAccountFilter(ppszArray[i], refBasePathsInfo,
refCredentialObject, strFilter);
if(FAILED(hr))
{
hr = E_UNEXPECTED;
break;
}
}
// Close the query string
strFilter += L")";
} while (false);
// Free the Acct array
if(ppszArray)
LocalFree(ppszArray);
// If we failed in the loop then clear out the filter string
if(FAILED(hr))
strFilter = L"";
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: AddSingleAccountFilter
//
// Synopsis: Appends an account string to strFilter for the specified user
//
// Arguments: [lpszUser - IN] : User whose sid string is requested
// [strFilter - OUT] : Contains the output filter to append to
// Returns: HRESULT : S_OK if everything succeeded
//
// History: 14-Aug-2002 ronmart Created
//
//---------------------------------------------------------------------------
HRESULT AddSingleAccountFilter(IN LPCWSTR lpszUser,
IN CDSCmdBasePathsInfo& refBasePathsInfo,
IN CDSCmdCredentialObject& refCredentialObject,
OUT CComBSTR& strFilter)
{
ENTER_FUNCTION_HR(LEVEL3_LOGGING, AddSingleAccountFilter, hr);
if(!lpszUser)
{
hr = E_INVALIDARG;
return hr;
}
PSID pSid = NULL;
LPWSTR pszSid = NULL;
LPWSTR lpszDN = NULL;
do // false loop
{
// TODO: Need to provide the first param
hr = ConvertTrusteeToDN(NULL, lpszUser, &lpszDN);
if(FAILED(hr))
{
// 700068 - If the user doesn't exist or has been deleted then
// give the user a clue as to what went wrong. 686693 addresses
// the known issue of multiple error messages being displayed
// and may not be addressed until a future release - ronmart
hr = E_INVALIDARG;
DisplayErrorMessage(g_pszDSCommandName, 0, hr, IDS_MSG_INVALID_ACCT_ERROR);
break;
}
// Get the SID
hr = GetDNSid(lpszDN,
refBasePathsInfo,
refCredentialObject,
&pSid);
if(FAILED(hr))
{
break;
}
// Convert the sid to a string
if(ConvertSidToStringSid(pSid, &pszSid))
{
DEBUG_OUTPUT(LEVEL3_LOGGING, L"ConvertSidToStringSid = %s", pszSid);
// APPEND the trustee query with the sid
strFilter += L"(msDS-QuotaTrustee=";
strFilter += pszSid;
strFilter += L")";
}
else
{
DEBUG_OUTPUT(LEVEL3_LOGGING, L"ConvertSidToStringSid failed!");
hr = E_FAIL;
break;
}
} while (false);
if(pSid)
LocalFree(pSid);
if(pszSid)
LocalFree(pszSid);
if(lpszDN)
LocalFree(lpszDN);
return hr;
}