//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 2000 // // File: dsget.cpp // // Contents: Defines the main function DSGET // command line utility // // History: 13-Oct-2000 JeffJon Created // // //-------------------------------------------------------------------------- #include "pch.h" #include "cstrings.h" #include "usage.h" #include "gettable.h" #include "query.h" #include "resource.h" #include "output.h" // // Forward Function Declarations // HRESULT DoGetValidation(PARG_RECORD pCommandArgs, PDSGetObjectTableEntry pObjectEntry, BOOL& bErrorShown); HRESULT DoGet(PARG_RECORD pCommandArgs, PDSGetObjectTableEntry pObjectEntry); HRESULT GetAttributesToFetch(IN PARG_RECORD pCommandArgs, IN PDSGetObjectTableEntry pObjectEntry, OUT LPWSTR **ppszAttributes, OUT DWORD * pCount); VOID FreeAttributesToFetch( IN LPWSTR *ppszAttributes, IN DWORD dwCount); HRESULT SetRange(IN LPCWSTR pszAttrName, IN DWORD dwRangeUBound, OUT LPWSTR* pszAttrs); // NTRAID#NTBUG9-717576-2002/10/10-JeffJon // set this global so that we don't show the success message // when displaying members of a group or memberof or manager bool bDontDisplaySuccess = false; // //Main Function // int __cdecl _tmain( VOID ) { int argc = 0; LPTOKEN pToken = NULL; HRESULT hr = S_OK; PARG_RECORD pNewCommandArgs = 0; // // False loop // do { // // Initialize COM // hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if (FAILED(hr)) break; //Get CommandLine Input DWORD _dwErr = GetCommandInput(&argc,&pToken); hr = HRESULT_FROM_WIN32(_dwErr); if(FAILED(hr)) break; if(argc == 1) { // // Display the error message and then break out of the false loop // DisplayMessage(USAGE_DSGET,TRUE); hr = E_INVALIDARG; break; } if(argc == 2) { if(IsTokenHelpSwitch(pToken + 1)) { hr = S_OK; DisplayMessage(USAGE_DSGET,TRUE); break; } } // // Find which object table entry to use from // the second command line argument // PDSGetObjectTableEntry pObjectEntry = NULL; UINT idx = 0; PWSTR pszObjectType = (pToken+1)->GetToken(); while (true) { pObjectEntry = g_DSObjectTable[idx++]; if (!pObjectEntry) { break; } //Security Review:Both are null terminated. if (0 == _wcsicmp(pObjectEntry->pszCommandLineObjectType, pszObjectType)) { break; } } if (!pObjectEntry) { // // Display the error message and then break out of the false loop // DisplayMessage(USAGE_DSGET); hr = E_INVALIDARG; break; } // // Now that we have the correct table entry, merge the command line table // for this object with the common commands // hr = MergeArgCommand(DSGET_COMMON_COMMANDS, pObjectEntry->pParserTable, &pNewCommandArgs); if (FAILED(hr)) break; // //Parse the Input // PARSE_ERROR Error; if(!ParseCmd(g_pszDSCommandName, pNewCommandArgs, argc-1, pToken+1, pObjectEntry->nUsageID, &Error, TRUE)) { //ParseCmd did not display any error. Error should //be handled here. Check DisplayParseError for the //cases where Error is not shown by ParseCmd if(!Error.MessageShown) { hr = E_INVALIDARG; DisplayErrorMessage(g_pszDSCommandName, NULL, hr); break; } if(Error.ErrorSource == ERROR_FROM_PARSER && Error.Error == PARSE_ERROR_HELP_SWITCH) { hr = S_OK; break; } hr = E_INVALIDARG; break; } // // Check to see if we are doing debug spew // #ifdef DBG bool bDebugging = pNewCommandArgs[eCommDebug].bDefined && pNewCommandArgs[eCommDebug].nValue; if (bDebugging) { ENABLE_DEBUG_OUTPUT(pNewCommandArgs[eCommDebug].nValue); } #else DISABLE_DEBUG_OUTPUT(); #endif // // Do extra validation like switch dependency check etc. // BOOL bErrorShown = FALSE; hr = DoGetValidation(pNewCommandArgs, pObjectEntry, bErrorShown); if (FAILED(hr)) { if (!bErrorShown) { DisplayErrorMessage(g_pszDSCommandName, 0, hr); } break; } // // Command line parsing succeeded // hr = DoGet(pNewCommandArgs, pObjectEntry); if(FAILED(hr)) break; } while (false); //False Loop // //Do the CleanUp // // // Free the memory associated with the command values // if (pNewCommandArgs) { FreeCmd(pNewCommandArgs); } // // Free the tokens // if (pToken) { delete[] pToken; pToken = 0; } // //Display Failure or Success Message // // NTRAID#NTBUG9-717576-2002/10/10-JeffJon // don't show the success message when displaying members // of a group or memberof if(SUCCEEDED(hr) && !bDontDisplaySuccess) { DisplaySuccessMessage(g_pszDSCommandName, NULL); } // // Uninitialize COM // CoUninitialize(); return hr; } //+-------------------------------------------------------------------------- // // Function: DoGetValidation // // Synopsis: Checks to be sure that command line switches that are mutually // exclusive are not both present and those that are dependent are // both present, and other validations which cannot be done by parser. // // Arguments: [pCommandArgs - IN] : the command line argument structure used // to retrieve the values for each switch // [pObjectEntry - IN] : pointer to the object table entry for the // object type that will be queryied // [bErrorShown - OUT] : this is set to true if the error is // displayed within this function // // Returns: HRESULT : S_OK if everything succeeded // E_INVALIDARG if the object entry wasn't found // // History: 13-Oct-2000 JeffJon Created // 15-Jan-2002 JeffJon Added the bErrorShown out parameter // and a special error message for server/domain // //--------------------------------------------------------------------------- HRESULT DoGetValidation(IN PARG_RECORD pCommandArgs, IN PDSGetObjectTableEntry pObjectEntry, OUT BOOL& bErrorShown) { ENTER_FUNCTION_HR(MINIMAL_LOGGING, DoGetValidation, hr); do // false loop { if (!pCommandArgs || !pObjectEntry) { ASSERT(pCommandArgs); ASSERT(pObjectEntry); hr = E_INVALIDARG; break; } // Check to be sure the server and domain switches // are mutually exclusive if (pCommandArgs[eCommServer].bDefined && pCommandArgs[eCommDomain].bDefined) { hr = E_INVALIDARG; DisplayErrorMessage(g_pszDSCommandName, 0, hr, IDS_NO_SERVER_AND_DOMAIN); bErrorShown = TRUE; break; } // // Check the object type specific switches // PWSTR pszObjectType = NULL; if (!pCommandArgs[eCommObjectType].bDefined && !pCommandArgs[eCommObjectType].strValue) { hr = E_INVALIDARG; break; } pszObjectType = pCommandArgs[eCommObjectType].strValue; UINT nMemberOfIdx = 0; UINT nExpandIdx = 0; UINT nIdxLast = 0; UINT nMembersIdx = 0; bool bMembersDefined = false; bool bMemberOfDefined = false; UINT nPartIdx = 0; bool bServerPartDefined = false; bool bPartitionTopObjDefined = false; bool bServerTopObjDefined = false; //Security Review:Both are null terminated. if (0 == _wcsicmp(g_pszUser, pszObjectType) ) { nMemberOfIdx = eUserMemberOf; nExpandIdx = eUserExpand; nIdxLast = eUserLast; if (pCommandArgs[eUserMemberOf].bDefined) { bMemberOfDefined = true; } // // If nothing is defined, then define DN, SAMAccountName, and Description // bool bSomethingDefined = false; for (UINT nIdx = eCommDN; nIdx <= eUserLast; nIdx++) { if (pCommandArgs[nIdx].bDefined) { bSomethingDefined = true; break; } } if (!bSomethingDefined) { pCommandArgs[eCommDN].bDefined = TRUE; pCommandArgs[eCommDN].bValue = TRUE; pCommandArgs[eUserSamID].bDefined = TRUE; pCommandArgs[eUserSamID].bValue = TRUE; pCommandArgs[eCommDescription].bDefined = TRUE; pCommandArgs[eCommDescription].bValue = TRUE; } if (pCommandArgs[eUserManager].bDefined) { bDontDisplaySuccess = true; } } //Security Review:Both are null terminated. else if (0 == _wcsicmp(g_pszComputer, pszObjectType) ) { nMemberOfIdx = eComputerMemberOf; nExpandIdx = eComputerExpand; nIdxLast = eComputerLast; if (pCommandArgs[eComputerMemberOf].bDefined) { bMemberOfDefined = true; } // // If nothing is defined, then define DN, and Description // bool bSomethingDefined = false; for (UINT nIdx = eCommDN; nIdx <= eComputerLast; nIdx++) { if (pCommandArgs[nIdx].bDefined) { bSomethingDefined = true; break; } } if (!bSomethingDefined) { pCommandArgs[eCommDN].bDefined = TRUE; pCommandArgs[eCommDN].bValue = TRUE; pCommandArgs[eCommDescription].bDefined = TRUE; pCommandArgs[eCommDescription].bValue = TRUE; } } // Both are null terminated. else if (0 == _wcsicmp(g_pszPartition, pszObjectType) ) { if (pCommandArgs[ePartitionTopObjOwner].bDefined) { nPartIdx = ePartitionTopObjOwner; nIdxLast = ePartitionLast; bPartitionTopObjDefined = true; } } // Both are null terminated. else if (0 == _wcsicmp(g_pszServer, pszObjectType) ) { if (pCommandArgs[eServerPart].bDefined) { nPartIdx = eServerPart; nIdxLast = eServerLast; bServerPartDefined = true; } else if(pCommandArgs[eServerTopObjOwner].bDefined) { nPartIdx = eServerTopObjOwner; nIdxLast = eServerLast; bServerTopObjDefined = true; } } //Security Review:Both are null terminated. else if (0 == _wcsicmp(g_pszGroup, pszObjectType) ) { nMemberOfIdx = eGroupMemberOf; nExpandIdx = eGroupExpand; nIdxLast = eGroupLast; nMembersIdx = eGroupMembers; if (pCommandArgs[eGroupMemberOf].bDefined) { bMemberOfDefined = true; } if (pCommandArgs[eGroupMembers].bDefined) { bMembersDefined = true; } // // If nothing is defined, then define DN, and Description // bool bSomethingDefined = false; for (UINT nIdx = eCommDN; nIdx <= eGroupLast; nIdx++) { if (pCommandArgs[nIdx].bDefined) { bSomethingDefined = true; break; } } if (!bSomethingDefined) { pCommandArgs[eCommDN].bDefined = TRUE; pCommandArgs[eCommDN].bValue = TRUE; pCommandArgs[eCommDescription].bDefined = TRUE; pCommandArgs[eCommDescription].bValue = TRUE; } } //Security Review:Both are null terminated. else if (0 == _wcsicmp(g_pszOU, pszObjectType)) { // // If nothing is defined, then define DN, and Description // bool bSomethingDefined = false; for (UINT nIdx = eCommDN; nIdx <= eCommDescription; nIdx++) { if (pCommandArgs[nIdx].bDefined) { bSomethingDefined = true; break; } } if (!bSomethingDefined) { pCommandArgs[eCommDN].bDefined = TRUE; pCommandArgs[eCommDN].bValue = TRUE; pCommandArgs[eCommDescription].bDefined = TRUE; pCommandArgs[eCommDescription].bValue = TRUE; } } //Security Review:Both are null terminated. else if(0 == _wcsicmp(g_pszContact, pszObjectType)) { // // If nothing is defined, then define DN, and Description // bool bSomethingDefined = false; for (UINT nIdx = eCommDN; nIdx <= eContactLast; nIdx++) { if (pCommandArgs[nIdx].bDefined) { bSomethingDefined = true; break; } } if (!bSomethingDefined) { pCommandArgs[eCommDN].bDefined = TRUE; pCommandArgs[eCommDN].bValue = TRUE; pCommandArgs[eCommDescription].bDefined = TRUE; pCommandArgs[eCommDescription].bValue = TRUE; } } //Security Review:Both are null terminated. else if(0 == _wcsicmp(g_pszServer, pszObjectType)) { // // If nothing is defined, then define DN, and Description // bool bSomethingDefined = false; for (UINT nIdx = eCommDN; nIdx <= eServerLast; nIdx++) { if (pCommandArgs[nIdx].bDefined) { bSomethingDefined = true; break; } } if (!bSomethingDefined) { pCommandArgs[eCommDN].bDefined = TRUE; pCommandArgs[eCommDN].bValue = TRUE; pCommandArgs[eServerDnsName].bDefined = TRUE; pCommandArgs[eServerDnsName].bValue = TRUE; } } //Security Review:Both are null terminated. else if(0 == _wcsicmp(g_pszSite, pszObjectType)) { // // If nothing is defined, then define DN, and Description // bool bSomethingDefined = false; for (UINT nIdx = eCommDN; nIdx <= eSiteLast; nIdx++) { if (pCommandArgs[nIdx].bDefined) { bSomethingDefined = true; break; } } if (!bSomethingDefined) { pCommandArgs[eCommDN].bDefined = TRUE; pCommandArgs[eCommDN].bValue = TRUE; pCommandArgs[eCommDescription].bDefined = TRUE; pCommandArgs[eCommDescription].bValue = TRUE; } } //Security Review:Both are null terminated. else if(0 == _wcsicmp(g_pszSubnet, pszObjectType)) { // // If nothing is defined, then define DN, and Description // bool bSomethingDefined = false; for (UINT nIdx = eCommDN; nIdx <= eSubnetLast; nIdx++) { if (pCommandArgs[nIdx].bDefined) { bSomethingDefined = true; break; } } if (!bSomethingDefined) { pCommandArgs[eCommDN].bDefined = TRUE; pCommandArgs[eCommDN].bValue = TRUE; pCommandArgs[eCommDescription].bDefined = TRUE; pCommandArgs[eCommDescription].bValue = TRUE; pCommandArgs[eSubnetSite].bDefined = TRUE; pCommandArgs[eSubnetSite].bValue = TRUE; } } // // if the -members or the -memberof switch is defined // if (bMemberOfDefined || bMembersDefined) { // NTRAID#NTBUG9-717576-2002/10/10-JeffJon // set this global so that we don't show the success message // when displaying members of a group or memberof bDontDisplaySuccess = true; // 476206-2002/04/23-JonN if (bMemberOfDefined && bMembersDefined) { hr = E_INVALIDARG; break; } // // If either the -members or -memberof switch is defined, // no other switches may be defined // for (UINT nIdx = eCommDN; nIdx < nIdxLast; nIdx++) { // 476206-2002/04/23-JonN if (pCommandArgs[nIdx].bDefined && nIdx != nMemberOfIdx && nIdx != nMembersIdx && nIdx != nExpandIdx) { hr = E_INVALIDARG; break; } } // // MemberOf should always be seen in list view // pCommandArgs[eCommList].bDefined = TRUE; pCommandArgs[eCommList].bValue = TRUE; } // // if the [server -part], [partition -topobjowner] // or [server -topobjowner] switch is defined // if (bServerPartDefined || bPartitionTopObjDefined || bServerTopObjDefined) { // Server and Partition are mutually exclusive objects types so // the parser will ensure that these two flags can never be true // at the same time. The following check ensures that both values // weren't passed at the same time if (bServerPartDefined && bServerTopObjDefined) { DEBUG_OUTPUT(MINIMAL_LOGGING, L"Server -part and server -topobjowner can not be defined at the same time"); hr = E_INVALIDARG; break; } // If one of these switches is defined, // then no other switches may be defined for (UINT nIdx = eCommDN; nIdx < nIdxLast; nIdx++) { if (pCommandArgs[nIdx].bDefined && nIdx != nPartIdx) { hr = E_INVALIDARG; break; } } // // should always be seen in a list view // pCommandArgs[eCommList].bDefined = TRUE; pCommandArgs[eCommList].bValue = TRUE; } } while (false); return hr; } //+-------------------------------------------------------------------------- // // Function: DoGet // // Synopsis: Does the get // Arguments: [pCommandArgs - IN] : the command line argument structure used // to retrieve the values for each switch // [pObjectEntry - IN] : pointer to the object table entry for the // object type that will be modified // // 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: 13-Oct-2000 JeffJon Created // //--------------------------------------------------------------------------- HRESULT DoGet(PARG_RECORD pCommandArgs, PDSGetObjectTableEntry pObjectEntry) { ENTER_FUNCTION_HR(MINIMAL_LOGGING, DoGet, hr); PWSTR pszPartitionDN = NULL; do // false loop { if (!pCommandArgs || !pObjectEntry) { ASSERT(pCommandArgs); ASSERT(pObjectEntry); hr = E_INVALIDARG; break; } // // The DNs or Names should be given as a \0 separated list // So parse it and loop through each object // UINT nStrings = 0; PWSTR* ppszArray = NULL; ParseNullSeparatedString(pCommandArgs[eCommObjectDNorName].strValue, &ppszArray, &nStrings); if (nStrings < 1 || !ppszArray) { // // Display an error message and then fail // hr = E_INVALIDARG; DisplayErrorMessage(g_pszDSCommandName, 0, hr); break; } // Make sure all the DNs actually have DN syntax bool bContinue = pCommandArgs[eCommContinue].bDefined && pCommandArgs[eCommContinue].bValue; UINT nValidDNs = ValidateDNSyntax(ppszArray, nStrings); if (nValidDNs < nStrings && !bContinue) { hr = E_ADS_BAD_PATHNAME; DisplayErrorMessage(g_pszDSCommandName, 0, hr); break; } CDSCmdCredentialObject credentialObject; if (pCommandArgs[eCommUserName].bDefined) { credentialObject.SetUsername(pCommandArgs[eCommUserName].strValue); credentialObject.SetUsingCredentials(true); } if (pCommandArgs[eCommPassword].bDefined) { //Security Review:pCommandArgs[eCommPassword].strValue is encrypted. //Decrypt pCommandArgs[eCommPassword].strValue and then pass it to the //credentialObject.SetPassword. //See NTRAID#NTBUG9-571544-2000/11/13-hiteshr credentialObject.SetEncryptedPassword(&pCommandArgs[eCommPassword].encryptedDataBlob); credentialObject.SetUsingCredentials(true); } // // Initialize the base paths info from the command line args // CDSCmdBasePathsInfo basePathsInfo; if (pCommandArgs[eCommServer].bDefined) { hr = basePathsInfo.InitializeFromName(credentialObject, pCommandArgs[eCommServer].strValue, true); } else if (pCommandArgs[eCommDomain].bDefined) { hr = basePathsInfo.InitializeFromName(credentialObject, pCommandArgs[eCommDomain].strValue, false); } else { hr = basePathsInfo.InitializeFromName(credentialObject, NULL, false); } if (FAILED(hr)) { break; } // // Create the formatting object and initialize it // CFormatInfo formatInfo; hr = formatInfo.Initialize(nStrings, pCommandArgs[eCommList].bDefined != 0, pCommandArgs[eCommQuiet].bDefined != 0); if (FAILED(hr)) { break; } // // Loop through each of the objects // for (UINT nNameIdx = 0; nNameIdx < nStrings; nNameIdx++) { // // Use a false do loop here so that we can break on an // error but still have the chance to determine if we // should continue the for loop if the -c option was provided // bool fDisplayedMessage = false; // 662519-2002/07/11-JonN double-display do // false loop { PWSTR pszObjectDN = ppszArray[nNameIdx]; if (!pszObjectDN) { // // Display an error message and then fail // hr = E_INVALIDARG; break; } // If partition object then look at first DN and then munge it if(0 == lstrcmpi(pObjectEntry->pszCommandLineObjectType, g_pszPartition)) { // Validate the partition and get the DN to the NTDS Quotas Container hr = GetQuotaContainerDN(basePathsInfo, credentialObject, pszObjectDN, &pszPartitionDN); if(FAILED(hr)) { hr = E_INVALIDARG; DisplayErrorMessage(g_pszDSCommandName, NULL, hr, IDS_ERRMSG_NO_QUOTAS_CONTAINER); fDisplayedMessage = true; break; } // Replace the object pointer with the new partition container DN pszObjectDN = pszPartitionDN; } DEBUG_OUTPUT(MINIMAL_LOGGING, L"Object DN = %s", pszObjectDN); CComBSTR sbstrObjectPath; basePathsInfo.ComposePathFromDN(pszObjectDN, sbstrObjectPath); CComPtr spObject; hr = DSCmdOpenObject(credentialObject, sbstrObjectPath, IID_IDirectoryObject, (void**)&spObject, true); if(FAILED(hr)) { break; } // 602981-2002/04/25-JonN check object class CComQIPtr spADs(spObject); if (!spADs) { ASSERT(spADs); hr = E_INVALIDARG; DisplayErrorMessage(g_pszDSCommandName, pszObjectDN, hr); fDisplayedMessage = true; // 662519-2002/07/11-JonN double-display break; } CComBSTR sbstrClass; hr = spADs->get_Class( &sbstrClass ); if (FAILED(hr)) { DEBUG_OUTPUT(MINIMAL_LOGGING, L"get_Class failed: hr = 0x%x", hr); DisplayErrorMessage(g_pszDSCommandName, pszObjectDN, hr); fDisplayedMessage = true; // 662519-2002/07/11-JonN double-display break; } if (_wcsicmp(sbstrClass, pObjectEntry->pszObjectClass) && ( _wcsicmp(pObjectEntry->pszObjectClass,L"user") || _wcsicmp(sbstrClass,L"inetorgperson")) // 662519-2002/07/11-JonN fix OU bug && ( _wcsicmp(pObjectEntry->pszObjectClass,L"ou") || _wcsicmp(sbstrClass,L"organizationalUnit")) ) { // // Display error message and return // DEBUG_OUTPUT(MINIMAL_LOGGING, L"Command line type does not match object class"); DEBUG_OUTPUT(MINIMAL_LOGGING, L"command line type = %s", pCommandArgs[eCommObjectType].strValue); DEBUG_OUTPUT(MINIMAL_LOGGING, L"object class = %s", sbstrClass); DisplayErrorMessage(g_pszDSCommandName, pszObjectDN, hr, IDS_ERRMSG_CLASS_NOT_EQUAL); hr = E_INVALIDARG; fDisplayedMessage = true; // 662519-2002/07/11-JonN double-display break; } // //Get the attributes to fetch // LPWSTR *ppszAttributes = NULL; DWORD dwCountAttr = 0; hr = GetAttributesToFetch(pCommandArgs, pObjectEntry, &ppszAttributes, &dwCountAttr); if (FAILED(hr)) { break; } DEBUG_OUTPUT(MINIMAL_LOGGING, L"Calling GetObjectAttributes for %d attributes.", dwCountAttr); DWORD dwAttrsReturned = 0; PADS_ATTR_INFO pAttrInfo = NULL; if(dwCountAttr > 0) { hr = spObject->GetObjectAttributes(ppszAttributes, dwCountAttr, &pAttrInfo, &dwAttrsReturned); if(FAILED(hr)) { DEBUG_OUTPUT(MINIMAL_LOGGING, L"GetObjectAttributes failed: hr = 0x%x", hr); FreeAttributesToFetch(ppszAttributes,dwCountAttr); break; } DEBUG_OUTPUT(LEVEL5_LOGGING, L"GetObjectAttributes succeeded: dwAttrsReturned = %d", dwAttrsReturned); } // // NOTE: there may be other items to display that are not // part of the attributes fetched // /* if (dwAttrsReturned == 0 || !pAttrInfo) { break; } */ // // Output the result of search // hr = DsGetOutputValuesList(pszObjectDN, basePathsInfo, credentialObject, pCommandArgs, pObjectEntry, dwAttrsReturned, pAttrInfo, spObject, formatInfo); } while (false); // // If there was a failure and the -c (continue) flag wasn't given // then stop processing names // if (FAILED(hr)) { if (!fDisplayedMessage) // 662519-2002/07/11-JonN double-display { DisplayErrorMessage(g_pszDSCommandName, 0, hr); } if (!pCommandArgs[eCommContinue].bDefined) { break; } } // If we alloc'd a partition DN, then free it if(pszPartitionDN) { LocalFree(pszPartitionDN); pszPartitionDN = NULL; } } // Names for loop // // Now display the results // formatInfo.Display(); } while (false); // If we alloc'd a partition DN, then free it if(pszPartitionDN) { LocalFree(pszPartitionDN); pszPartitionDN = NULL; } return hr; } //+-------------------------------------------------------------------------- // // Function: GetAttributesToFetch // // Synopsis: Make an array of attributes to fetch. // Arguments: [ppszAttributes - OUT] : array of attributes to fetch // [pCount - OUT] : count of attributes in array // // 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 GetAttributesToFetch(IN PARG_RECORD pCommandArgs, IN PDSGetObjectTableEntry pObjectEntry, OUT LPWSTR **ppszAttributes, OUT DWORD * pCount) { ENTER_FUNCTION_HR(LEVEL8_LOGGING, GetAttributesToFetch, hr); do // false loop { if(!pCommandArgs || !pObjectEntry) { ASSERT(pCommandArgs); ASSERT(pObjectEntry); hr = E_INVALIDARG; break; } LPWSTR *ppszAttr = (LPWSTR *)LocalAlloc(LPTR,pObjectEntry->dwAttributeCount *sizeof(LPCTSTR)); if(!ppszAttr) { hr = E_OUTOFMEMORY; break; } // // Loop through the attributes that are needed and copy // them into the array. // // REVIEW_JEFFON : what if there are duplicates? // DEBUG_OUTPUT(FULL_LOGGING, L"Adding attributes to list:"); DWORD dwAttrCount = 0; for(DWORD i = 0; i < pObjectEntry->dwAttributeCount; i++) { if (pObjectEntry->pAttributeTable[i]) { UINT nCommandEntry = pObjectEntry->pAttributeTable[i]->nAttributeID; if (pCommandArgs[nCommandEntry].bDefined) { LPWSTR pszAttr = pObjectEntry->pAttributeTable[i]->pszName; if (pszAttr) { // 702724 ronmart 2002/09/18 If looking for top // object owner then specify a range if(0 == lstrcmpi(pObjectEntry->pszCommandLineObjectType, g_pszPartition) && pCommandArgs[ePartitionTopObjOwner].bDefined) { hr = SetRange(pszAttr, pCommandArgs[ePartitionTopObjOwner].nValue, ppszAttr+dwAttrCount); } else if(0 == lstrcmpi(pObjectEntry->pszCommandLineObjectType, g_pszServer) && pCommandArgs[eServerTopObjOwner].bDefined) { hr = SetRange(pszAttr, pCommandArgs[eServerTopObjOwner].nValue, ppszAttr+dwAttrCount); } // NTRAID#NTBUG9-765440-2003/01/17-ronmart-dsget user/group -qlimit -qused // not returning values // These do not appear on the user object so GetObjectAttributes // will fail if these are included in the fetch array else if(0 == lstrcmpi(pszAttr,g_pszAttrmsDSQuotaEffective) || 0 == lstrcmpi(pszAttr,g_pszAttrmsDSQuotaUsed)) { continue; // ignore } else { hr = LocalCopyString(ppszAttr+dwAttrCount, pszAttr); } if (FAILED(hr)) { LocalFree(ppszAttr); hr = E_OUTOFMEMORY; break; } // 702724 ronmart 2002/09/18 Use the array value that has // be created (and possibly modified to include the range) // rather than the attribute name when spewing attrs DEBUG_OUTPUT(FULL_LOGGING, L"\t%s", *(ppszAttr+dwAttrCount)); dwAttrCount++; } } } } if (SUCCEEDED(hr)) { DEBUG_OUTPUT(FULL_LOGGING, L"Done adding %d attributes to list.", dwAttrCount); } *ppszAttributes = ppszAttr; *pCount = dwAttrCount; } while (false); return hr; } //+-------------------------------------------------------------------------- // // Function: FreeAttributesToFetch // // Synopsis: Function to free memory allocated by GetAttributesToFetch // Arguments: [dwszAttributes - in] : array of attributes to fetch // [dwCount - in] : count of attributes in array // // 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 // //--------------------------------------------------------------------------- VOID FreeAttributesToFetch( IN LPWSTR *ppszAttributes, IN DWORD dwCount) { while(dwCount) { LocalFree(ppszAttributes[--dwCount]); } LocalFree(ppszAttributes); } //+-------------------------------------------------------------------------- // // Function: SetRange // // Synopsis: Set's the range qualifier for an attribute // Arguments: [pszAttrName - IN] : attribute name to append the range to // [dwRangeUBound - IN]: one based upper bound of the range // [pszAttrs - OUT] : attr array entry that should be allocated // // 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: 18-Sep-2002 ronmart Created for 702724 fix // //--------------------------------------------------------------------------- HRESULT SetRange(IN LPCWSTR pszAttrName, IN DWORD dwRangeUBound, OUT LPWSTR* pszAttrs) { ENTER_FUNCTION_HR(MINIMAL_LOGGING, SetRange, hr); do // false loop { // Validate params if(!pszAttrName || !pszAttrs ) { hr = E_INVALIDARG; break; } // Get the size of the base attribute name size_t cbSize = lstrlen(pszAttrName); if(cbSize == 0) break; cbSize += 64; // leave room for null term, range string and int value cbSize *= sizeof(WCHAR); // Allocate the buffer to hold the range *pszAttrs = (LPWSTR) LocalAlloc(LPTR, cbSize); if(NULL == *pszAttrs) { hr = E_OUTOFMEMORY; break; } // If zero then show all if(dwRangeUBound == 0) { hr = StringCbPrintf(*pszAttrs, cbSize, L"%s%s=0-*", pszAttrName, g_pszRange); } // Otherwise show the value specified else { hr = StringCbPrintf(*pszAttrs, cbSize, L"%s%s=0-%d", pszAttrName, // Name of the attribute to append the range to g_pszRange, // The range qualifer ;range dwRangeUBound - 1); // Range is 0 based, and input is 1 based so adjust } if(FAILED(hr)) break; } while(false); return hr; }