DWORD LwLdapGetStrings( IN HANDLE hDirectory, IN LDAPMessage* pMessage, IN PCSTR pszFieldName, OUT PSTR** pppszValues, OUT PDWORD pdwNumValues ) { return LwLdapGetStringsWithExtDnResult( hDirectory, pMessage, pszFieldName, FALSE, pppszValues, pdwNumValues); }
// Give an attribute name "pszAttributeName" // Return all the values of the attribute for a given DN "pszDN" // The number of values can be more than 1500 since "ranging" is handled correctly in the routine // Now accept whether to do an extended DN search and whether to parse result to get Sids DWORD ADLdap_GetAttributeValuesList( IN PLSA_DM_LDAP_CONNECTION pConn, IN PCSTR pszDN, IN PCSTR pszAttributeName, IN BOOLEAN bDoExtDnSearch, IN BOOLEAN bDoSidParsing, OUT PDWORD pdwTotalCount, OUT PSTR** pppszValues ) { DWORD dwError = 0; // Do not free "szAttributeList" PSTR szAttributeList[2] = {NULL,NULL}; PSTR* ppszValuesTotal = NULL; PSTR* ppszValues = NULL; LDAPMessage* pMessage = NULL; DWORD dwCount = 0; DWORD dwTotalCount = 0; PLW_DLINKED_LIST pList = NULL; PLW_DLINKED_LIST pNode = NULL; PLSA_AD_QUERY_LISTS_ENTRY pEntry = NULL; PSTR pszRangeAttr = NULL; LDAP* pLd = NULL; BerElement* pBer = NULL; PSTR pszRetrievedAttr = NULL; //Do Not free "pszRetrievedRangeAttr" PSTR pszRetrievedRangeAttr = NULL; BOOLEAN bIsEnd = FALSE; DWORD iValues = 0; DWORD iValuesTotal = 0; PSTR pszAttributeRangedName = NULL; HANDLE hDirectory = NULL; BAIL_ON_INVALID_STRING(pszAttributeName); szAttributeList[0] = (PSTR)pszAttributeName; for (;;) { if (pMessage) { ldap_msgfree(pMessage); pMessage = NULL; } if (!bDoExtDnSearch && bDoSidParsing) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } if (bDoExtDnSearch) { dwError = LsaDmLdapDirectoryExtendedDNSearch( pConn, pszDN, "(objectClass=*)", szAttributeList, LDAP_SCOPE_BASE, &hDirectory, &pMessage); BAIL_ON_LSA_ERROR(dwError); } else { dwError = LsaDmLdapDirectorySearch( pConn, pszDN, LDAP_SCOPE_BASE, "(objectClass=*)", szAttributeList, &hDirectory, &pMessage); BAIL_ON_LSA_ERROR(dwError); } pLd = LwLdapGetSession(hDirectory); dwError = LwLdapGetStringsWithExtDnResult( hDirectory, pMessage, pszAttributeName, bDoSidParsing, &ppszValues, &dwCount); BAIL_ON_LSA_ERROR(dwError); if (ppszValues && dwCount) { if (pList) { // This is the case where we started out getting // ranged info but the info became non-ranged. // We might actually want to allow this to handle // a case where the membership list is trimmed // while we are enumerating. dwError = LW_ERROR_LDAP_ERROR; BAIL_ON_LSA_ERROR(dwError); } dwTotalCount = dwCount; ppszValuesTotal = ppszValues; dwCount = 0; ppszValues = NULL; break; } if (pszRetrievedAttr) { ldap_memfree(pszRetrievedAttr); pszRetrievedAttr = NULL; } if (pBer) { ber_free(pBer, 0); } LW_SAFE_FREE_STRING(pszAttributeRangedName); dwError = LwAllocateStringPrintf( &pszAttributeRangedName, "%s;Range=", pszAttributeName); BAIL_ON_LSA_ERROR(dwError); pszRetrievedAttr = ldap_first_attribute(pLd, pMessage, &pBer); while (pszRetrievedAttr) { if (!strncasecmp(pszRetrievedAttr, pszAttributeRangedName, strlen(pszAttributeRangedName))) { pszRetrievedRangeAttr = pszRetrievedAttr; break; } ldap_memfree(pszRetrievedAttr); pszRetrievedAttr = NULL; pszRetrievedAttr = ldap_next_attribute(pLd, pMessage, pBer); } if (!pszRetrievedRangeAttr) { // This happens when we have an group with no members, break; } if ('*' == pszRetrievedRangeAttr[strlen(pszRetrievedRangeAttr)-1]) { bIsEnd = TRUE; } dwError = LwLdapGetStringsWithExtDnResult( hDirectory, pMessage, pszRetrievedRangeAttr, bDoSidParsing, &ppszValues, &dwCount); BAIL_ON_LSA_ERROR(dwError); dwTotalCount += dwCount; dwError = CreateQueryListEntry( &pEntry, dwCount, ppszValues); BAIL_ON_LSA_ERROR(dwError); ppszValues = NULL; dwCount = 0; dwError = LwDLinkedListPrepend(&pList, pEntry); BAIL_ON_LSA_ERROR(dwError); pEntry = NULL; if (bIsEnd) { break; } LW_SAFE_FREE_STRING(pszRangeAttr); dwError = LwAllocateStringPrintf( &pszRangeAttr, "%s%u-*", pszAttributeRangedName, dwTotalCount); BAIL_ON_LSA_ERROR(dwError); szAttributeList[0] = pszRangeAttr; } if (pList && !ppszValuesTotal) { dwError = LwAllocateMemory( sizeof(*ppszValuesTotal) * dwTotalCount, (PVOID*)&ppszValuesTotal); BAIL_ON_LSA_ERROR(dwError); for (pNode = pList; pNode; pNode = pNode->pNext) { PLSA_AD_QUERY_LISTS_ENTRY pEntry = (PLSA_AD_QUERY_LISTS_ENTRY)pNode->pItem; for (iValues = 0; iValues < pEntry->dwQueryCount; iValues++) { ppszValuesTotal[iValuesTotal] = pEntry->ppszQueryValues[iValues]; pEntry->ppszQueryValues[iValues] = NULL; iValuesTotal++; } } } *pdwTotalCount = dwTotalCount; *pppszValues = ppszValuesTotal; cleanup: if (pMessage) { ldap_msgfree(pMessage); } if (pszRetrievedAttr) { ldap_memfree(pszRetrievedAttr); } if (pBer) { ber_free(pBer, 0); } LwFreeStringArray(ppszValues, dwCount); DestroyQueryListEntry(&pEntry); LW_SAFE_FREE_STRING(pszAttributeRangedName); LW_SAFE_FREE_STRING(pszRangeAttr); for (pNode = pList; pNode; pNode = pNode->pNext) { PLSA_AD_QUERY_LISTS_ENTRY pEntry = (PLSA_AD_QUERY_LISTS_ENTRY)pNode->pItem; DestroyQueryListEntry(&pEntry); } LwDLinkedListFree(pList); return dwError; error: LwFreeStringArray(ppszValuesTotal, iValuesTotal); *pdwTotalCount = 0; *pppszValues = NULL; goto cleanup; }