NTSTATUS SamrSrvQueryAliasInfo( /* [in] */ handle_t hBinding, /* [in] */ ACCOUNT_HANDLE hAlias, /* [in] */ UINT16 level, /* [out] */ AliasInfo **info ) { PCSTR filterFormat = "%s=%Q"; NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = 0; PACCOUNT_CONTEXT pAcctCtx = NULL; PDOMAIN_CONTEXT pDomCtx = NULL; PCONNECT_CONTEXT pConnCtx = NULL; PWSTR pwszBase = NULL; WCHAR wszAttrDn[] = DS_ATTR_DISTINGUISHED_NAME; WCHAR wszAttrSamAccountName[] = DS_ATTR_SAM_ACCOUNT_NAME; WCHAR wszAttrDescription[] = DS_ATTR_DESCRIPTION; CHAR szAttrDn[] = DS_ATTR_DISTINGUISHED_NAME; DWORD dwScope = 0; PSTR pszDn = NULL; PWSTR pwszFilter = NULL; PDIRECTORY_ENTRY pEntry = NULL; DWORD dwEntriesNum = 0; PDIRECTORY_ENTRY pMemberEntry = NULL; DWORD dwNumMembers = 0; AliasInfo *pAliasInfo = NULL; PWSTR wszAttributesLevel1[] = { wszAttrSamAccountName, wszAttrDescription, NULL }; PWSTR wszAttributesLevel2[] = { wszAttrSamAccountName, NULL }; PWSTR wszAttributesLevel3[] = { wszAttrDescription, NULL }; PWSTR *pwszAttributes[] = { wszAttributesLevel1, wszAttributesLevel2, wszAttributesLevel3 }; PWSTR wszMemberAttributes[] = { wszAttrDn, NULL }; pAcctCtx = (PACCOUNT_CONTEXT)hAlias; if (pAcctCtx == NULL || pAcctCtx->Type != SamrContextAccount) { ntStatus = STATUS_INVALID_HANDLE; BAIL_ON_NTSTATUS_ERROR(ntStatus); } if (!(pAcctCtx->dwAccessGranted & ALIAS_ACCESS_LOOKUP_INFO)) { ntStatus = STATUS_ACCESS_DENIED; BAIL_ON_NTSTATUS_ERROR(ntStatus); } pDomCtx = pAcctCtx->pDomCtx; pConnCtx = pDomCtx->pConnCtx; pwszBase = pDomCtx->pwszDn; dwError = LwWc16sToMbs(pAcctCtx->pwszDn, &pszDn); BAIL_ON_LSA_ERROR(dwError); dwError = DirectoryAllocateWC16StringFilterPrintf( &pwszFilter, filterFormat, szAttrDn, pszDn); BAIL_ON_LSA_ERROR(dwError); dwError = DirectorySearch(pConnCtx->hDirectory, pwszBase, dwScope, pwszFilter, pwszAttributes[level - 1], FALSE, &pEntry, &dwEntriesNum); BAIL_ON_LSA_ERROR(dwError); if (dwEntriesNum == 0) { ntStatus = STATUS_INVALID_HANDLE; } else if (dwEntriesNum > 1) { ntStatus = STATUS_INTERNAL_ERROR; } BAIL_ON_NTSTATUS_ERROR(ntStatus); if (level == ALIAS_INFO_ALL) { dwError = DirectoryGetGroupMembers(pConnCtx->hDirectory, pAcctCtx->pwszDn, wszMemberAttributes, &pMemberEntry, &dwNumMembers); BAIL_ON_LSA_ERROR(dwError); } ntStatus = SamrSrvAllocateMemory((void**)&pAliasInfo, sizeof(*pAliasInfo)); BAIL_ON_NTSTATUS_ERROR(ntStatus); switch (level) { case ALIAS_INFO_ALL: ntStatus = SamrFillAliasInfo1(pEntry, dwNumMembers, pAliasInfo); break; case ALIAS_INFO_NAME: ntStatus = SamrFillAliasInfo2(pEntry, pAliasInfo); break; case ALIAS_INFO_DESCRIPTION: ntStatus = SamrFillAliasInfo3(pEntry, pAliasInfo); break; default: ntStatus = STATUS_INVALID_INFO_CLASS; } BAIL_ON_NTSTATUS_ERROR(ntStatus); *info = pAliasInfo; cleanup: LW_SAFE_FREE_MEMORY(pszDn); LW_SAFE_FREE_MEMORY(pwszFilter); if (pEntry) { DirectoryFreeEntries(pEntry, dwEntriesNum); } if (ntStatus == STATUS_SUCCESS && dwError != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(dwError); } return ntStatus; error: if (pAliasInfo) { SamrSrvFreeMemory(pAliasInfo); } *info = NULL; goto cleanup; }
NTSTATUS SamrSrvLookupDomain( /* [in] */ handle_t hBinding, /* [in] */ CONNECT_HANDLE hConn, /* [in] */ UNICODE_STRING *domain_name, /* [out] */ SID **ppSid ) { CHAR szDnToken[] = "DC"; wchar_t wszFilter[] = L"%ws=%u AND %ws=\'%ws\'"; NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = 0; PCONNECT_CONTEXT pConnCtx = NULL; PWSTR pwszBase = NULL; WCHAR wszAttrObjectClass[] = DS_ATTR_OBJECT_CLASS; WCHAR wszAttrDomain[] = DS_ATTR_DOMAIN; WCHAR wszAttrObjectSID[] = DS_ATTR_OBJECT_SID; DWORD dwObjectClass = DS_OBJECT_CLASS_DOMAIN; WCHAR wszBuiltinDomainName[] = SAMR_BUILTIN_DOMAIN_NAME; PWSTR pwszDomainName = NULL; DWORD dwBaseLen = 0; DWORD dwScope = 0; PWSTR pwszFilter = NULL; DWORD dwFilterLen = 0; PWSTR wszAttributes[2]; PDIRECTORY_ENTRY pEntries = NULL; DWORD dwCount = 0; PDIRECTORY_ATTRIBUTE pAttr = NULL; PATTRIBUTE_VALUE pAttrVal = NULL; PSID pDomainSid = NULL; BAIL_ON_INVALID_PARAMETER(ppSid); BAIL_ON_INVALID_PARAMETER(domain_name); memset(wszAttributes, 0, sizeof(wszAttributes)); pConnCtx = (PCONNECT_CONTEXT)hConn; if (pConnCtx == NULL || pConnCtx->Type != SamrContextConnect) { ntStatus = STATUS_INVALID_HANDLE; BAIL_ON_NTSTATUS_ERROR(ntStatus); } ntStatus = SamrSrvGetFromUnicodeString(&pwszDomainName, domain_name); BAIL_ON_NO_MEMORY(pwszDomainName); if (!wc16scasecmp(pwszDomainName, wszBuiltinDomainName)) { dwObjectClass = DS_OBJECT_CLASS_BUILTIN_DOMAIN; } dwBaseLen = domain_name->MaximumLength + ((sizeof(szDnToken) + 2) * sizeof(WCHAR)); dwFilterLen = (sizeof(wszAttrObjectClass) - 1) + 10 + (sizeof(wszAttrDomain) - 1) + domain_name->Length + sizeof(wszFilter); ntStatus = SamrSrvAllocateMemory(OUT_PPVOID(&pwszFilter), dwFilterLen); BAIL_ON_NTSTATUS_ERROR(ntStatus); if (sw16printfw(pwszFilter, dwFilterLen/sizeof(WCHAR), wszFilter, wszAttrObjectClass, dwObjectClass, wszAttrDomain, pwszDomainName) < 0) { ntStatus = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(ntStatus); } wszAttributes[0] = wszAttrObjectSID; wszAttributes[1] = NULL; dwError = DirectorySearch(pConnCtx->hDirectory, pwszBase, dwScope, pwszFilter, wszAttributes, FALSE, &pEntries, &dwCount); BAIL_ON_LSA_ERROR(dwError); if (dwCount == 1) { dwError = DirectoryGetEntryAttributeSingle(pEntries, &pAttr); BAIL_ON_LSA_ERROR(dwError); dwError = DirectoryGetAttributeValue(pAttr, &pAttrVal); BAIL_ON_LSA_ERROR(dwError); if (pAttrVal->Type == DIRECTORY_ATTR_TYPE_UNICODE_STRING) { ntStatus = SamrSrvAllocateSidFromWC16String( &pDomainSid, pAttrVal->data.pwszStringValue); BAIL_ON_NTSTATUS_ERROR(ntStatus); } else { ntStatus = STATUS_INTERNAL_ERROR; BAIL_ON_NTSTATUS_ERROR(ntStatus); } } else if (dwCount == 0) { ntStatus = STATUS_NO_SUCH_DOMAIN; BAIL_ON_NTSTATUS_ERROR(ntStatus); } else { ntStatus = STATUS_INTERNAL_ERROR; BAIL_ON_NTSTATUS_ERROR(ntStatus); } *ppSid = pDomainSid; cleanup: if (pwszBase) { SamrSrvFreeMemory(pwszBase); } if (pwszDomainName) { SamrSrvFreeMemory(pwszDomainName); } if (pwszFilter) { SamrSrvFreeMemory(pwszFilter); } if (pEntries) { DirectoryFreeEntries(pEntries, dwCount); } if (ntStatus == STATUS_SUCCESS && dwError != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(dwError); } return ntStatus; error: if (pDomainSid) { SamrSrvFreeMemory(&pDomainSid); } *ppSid = NULL; goto cleanup; }
NTSTATUS SamrSrvEnumDomainAccounts( IN handle_t hBinding, IN DOMAIN_HANDLE hDomain, IN OUT PDWORD pdwResume, IN DWORD dwObjectClass, IN DWORD dwFlagsFilter, IN DWORD dwMaxSize, OUT RID_NAME_ARRAY **ppNames, OUT UINT32 *pdwNumEntries ) { wchar_t wszFilterFmt[] = L"%ws=%u AND %ws='%ws'"; NTSTATUS ntStatus = STATUS_SUCCESS; NTSTATUS ntEnumStatus = STATUS_SUCCESS; DWORD dwError = 0; PDOMAIN_CONTEXT pDomCtx = NULL; PCONNECT_CONTEXT pConnCtx = NULL; PWSTR pwszBase = NULL; WCHAR wszAttrObjectClass[] = DS_ATTR_OBJECT_CLASS; WCHAR wszAttrDomainName[] = DS_ATTR_DOMAIN; WCHAR wszAttrAccountFlags[] = DS_ATTR_ACCOUNT_FLAGS; WCHAR wszAttrSamAccountName[] = DS_ATTR_SAM_ACCOUNT_NAME; WCHAR wszAttrObjectSid[] = DS_ATTR_OBJECT_SID; DWORD dwScope = 0; PWSTR pwszFilter = NULL; size_t sDomainNameLen = 0; PWSTR pwszDomainName = NULL; DWORD dwFilterLen = 0; PDIRECTORY_ENTRY pEntries = NULL; PDIRECTORY_ENTRY pEntry = NULL; DWORD dwNumEntries = 0; DWORD dwTotalSize = 0; DWORD dwSize = 0; DWORD i = 0; DWORD dwCount = 0; DWORD dwNumEntriesReturned = 0; DWORD dwResume = 0; DWORD dwAccountFlags = 0; size_t sNameLen = 0; PWSTR pwszName = NULL; PWSTR pwszSid = NULL; PSID pSid = NULL; DWORD dwRid = 0; RID_NAME_ARRAY *pNames = NULL; RID_NAME *pName = NULL; DWORD dwNewResumeIdx = 0; PWSTR wszAttributes[] = { wszAttrSamAccountName, wszAttrObjectSid, wszAttrAccountFlags, NULL }; BAIL_ON_INVALID_PTR(hDomain); BAIL_ON_INVALID_PTR(pdwResume); BAIL_ON_INVALID_PTR(ppNames); BAIL_ON_INVALID_PTR(pdwNumEntries); pDomCtx = (PDOMAIN_CONTEXT)hDomain; dwResume = *pdwResume; if (pDomCtx == NULL || pDomCtx->Type != SamrContextDomain) { ntStatus = STATUS_INVALID_HANDLE; BAIL_ON_NTSTATUS_ERROR(ntStatus); } if (!(pDomCtx->dwAccessGranted & DOMAIN_ACCESS_ENUM_ACCOUNTS)) { ntStatus = STATUS_ACCESS_DENIED; BAIL_ON_NTSTATUS_ERROR(ntStatus); } pConnCtx = pDomCtx->pConnCtx; pwszBase = pDomCtx->pwszDn; pwszDomainName = pDomCtx->pwszDomainName; dwError = LwWc16sLen(pwszDomainName, &sDomainNameLen); BAIL_ON_LSA_ERROR(dwError); dwFilterLen = ((sizeof(wszAttrObjectClass)/sizeof(WCHAR)) - 1) + 10 + ((sizeof(wszAttrDomainName)/sizeof(WCHAR)) - 1) + (sDomainNameLen + 1) + (sizeof(wszFilterFmt)/sizeof(wszFilterFmt[0])); dwError = LwAllocateMemory(dwFilterLen * sizeof(pwszFilter[0]), OUT_PPVOID(&pwszFilter)); BAIL_ON_LSA_ERROR(dwError); if (sw16printfw(pwszFilter, dwFilterLen, wszFilterFmt, wszAttrObjectClass, dwObjectClass, wszAttrDomainName, pwszDomainName) < 0) { ntStatus = LwErrnoToNtStatus(errno); BAIL_ON_NTSTATUS_ERROR(ntStatus); } dwError = DirectorySearch(pConnCtx->hDirectory, pwszBase, dwScope, pwszFilter, wszAttributes, FALSE, &pEntries, &dwNumEntries); BAIL_ON_LSA_ERROR(dwError); ntStatus = SamrSrvAllocateMemory(OUT_PPVOID(&pNames), sizeof(*pNames)); BAIL_ON_NTSTATUS_ERROR(ntStatus); if (dwResume >= dwNumEntries) { ntEnumStatus = STATUS_NO_MORE_ENTRIES; BAIL_ON_NTSTATUS_ERROR(ntStatus); } dwTotalSize += sizeof(pNames->dwCount); for (i = 0; i + dwResume < dwNumEntries; i++) { pEntry = &(pEntries[i + dwResume]); dwError = DirectoryGetEntryAttrValueByName( pEntry, wszAttrSamAccountName, DIRECTORY_ATTR_TYPE_UNICODE_STRING, &pwszName); BAIL_ON_LSA_ERROR(dwError); dwError = DirectoryGetEntryAttrValueByName( pEntry, wszAttrAccountFlags, DIRECTORY_ATTR_TYPE_INTEGER, &dwAccountFlags); BAIL_ON_LSA_ERROR(dwError); dwSize = 0; if (dwFlagsFilter && !(dwAccountFlags & dwFlagsFilter)) { continue; } dwError = LwWc16sLen(pwszName, &sNameLen); BAIL_ON_LSA_ERROR(dwError); dwSize += sizeof(UINT32); dwSize += sNameLen * sizeof(pwszName[0]); dwSize += 2 * sizeof(UINT16); dwTotalSize += dwSize; dwCount++; if (dwTotalSize > dwMaxSize) { dwTotalSize -= dwSize; dwCount--; ntEnumStatus = STATUS_MORE_ENTRIES; break; } } /* * At least one entry is returned regardless of declared * max response size */ dwNumEntriesReturned = (dwSize > 0 && dwCount == 0) ? 1 : dwCount; pNames->dwCount = dwNumEntriesReturned; ntStatus = SamrSrvAllocateMemory( OUT_PPVOID(&pNames->pEntries), sizeof(pNames->pEntries[0]) * pNames->dwCount); BAIL_ON_NTSTATUS_ERROR(ntStatus); for (i = 0, dwCount = 0; dwCount < dwNumEntriesReturned && i + dwResume < dwNumEntries; i++) { pEntry = &(pEntries[i + dwResume]); dwError = DirectoryGetEntryAttrValueByName(pEntry, wszAttrObjectSid, DIRECTORY_ATTR_TYPE_UNICODE_STRING, &pwszSid); BAIL_ON_LSA_ERROR(dwError); dwError = DirectoryGetEntryAttrValueByName(pEntry, wszAttrSamAccountName, DIRECTORY_ATTR_TYPE_UNICODE_STRING, &pwszName); BAIL_ON_LSA_ERROR(dwError); dwError = DirectoryGetEntryAttrValueByName(pEntry, wszAttrAccountFlags, DIRECTORY_ATTR_TYPE_INTEGER, &dwAccountFlags); BAIL_ON_LSA_ERROR(dwError); dwNewResumeIdx = i + dwResume + 1; if (dwFlagsFilter && !(dwAccountFlags & dwFlagsFilter)) { continue; } pName = &(pNames->pEntries[dwCount++]); ntStatus = RtlAllocateSidFromWC16String(&pSid, pwszSid); BAIL_ON_NTSTATUS_ERROR(ntStatus); dwRid = pSid->SubAuthority[pSid->SubAuthorityCount - 1]; pName->dwRid = (UINT32)dwRid; ntStatus = SamrSrvInitUnicodeString(&pName->Name, pwszName); BAIL_ON_NTSTATUS_ERROR(ntStatus); RTL_FREE(&pSid); } *pdwResume = dwNewResumeIdx; *pdwNumEntries = dwNumEntriesReturned; *ppNames = pNames; cleanup: LW_SAFE_FREE_MEMORY(pwszFilter); RTL_FREE(&pSid); if (pEntries) { DirectoryFreeEntries(pEntries, dwNumEntries); } if (ntStatus == STATUS_SUCCESS && dwError != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(dwError); } if (ntStatus == STATUS_SUCCESS && ntEnumStatus != STATUS_SUCCESS) { ntStatus = ntEnumStatus; } return ntStatus; error: if (pNames) { for (i = 0; i < pNames->dwCount; i++) { SamrSrvFreeUnicodeString(&(pNames->pEntries[i].Name)); } SamrSrvFreeMemory(pNames->pEntries); SamrSrvFreeMemory(pNames); } *pdwResume = 0; *pdwNumEntries = 0; *ppNames = NULL; goto cleanup; }
NTSTATUS SamrSrvGetMembersInAlias( IN handle_t hBinding, IN ACCOUNT_HANDLE hAlias, OUT SID_ARRAY *pSids ) { NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = 0; PACCOUNT_CONTEXT pAcctCtx = NULL; PCONNECT_CONTEXT pConnCtx = NULL; HANDLE hDirectory = NULL; PWSTR pwszAliasDn = NULL; WCHAR wszAttrObjectSid[] = DS_ATTR_OBJECT_SID; PDIRECTORY_ENTRY pMemberEntries; DWORD dwMembersNum = 0; DWORD i = 0; PWSTR pwszMemberSid = NULL; PSID pMemberSid = NULL; SID_ARRAY Sids = {0}; PWSTR wszAttributes[] = { wszAttrObjectSid, NULL }; pAcctCtx = (PACCOUNT_CONTEXT)hAlias; if (pAcctCtx == NULL || pAcctCtx->Type != SamrContextAccount) { ntStatus = STATUS_INVALID_HANDLE; BAIL_ON_NTSTATUS_ERROR(ntStatus); } if (!(pAcctCtx->dwAccessGranted & ALIAS_ACCESS_GET_MEMBERS)) { ntStatus = STATUS_ACCESS_DENIED; BAIL_ON_NTSTATUS_ERROR(ntStatus); } pConnCtx = (PCONNECT_CONTEXT)pAcctCtx->pDomCtx->pConnCtx; hDirectory = pConnCtx->hDirectory; pwszAliasDn = pAcctCtx->pwszDn; dwError = DirectoryGetGroupMembers(hDirectory, pwszAliasDn, wszAttributes, &pMemberEntries, &dwMembersNum); BAIL_ON_LSA_ERROR(dwError); Sids.dwNumSids = dwMembersNum; ntStatus = SamrSrvAllocateMemory((PVOID*)&Sids.pSids, sizeof(*Sids.pSids) * Sids.dwNumSids); BAIL_ON_NTSTATUS_ERROR(ntStatus); for (i = 0; i < dwMembersNum; i++) { PDIRECTORY_ENTRY pEntry = &(pMemberEntries[i]); dwError = DirectoryGetEntryAttrValueByName( pEntry, wszAttrObjectSid, DIRECTORY_ATTR_TYPE_UNICODE_STRING, &pwszMemberSid); BAIL_ON_LSA_ERROR(dwError); ntStatus = SamrSrvAllocateSidFromWC16String( &pMemberSid, pwszMemberSid); BAIL_ON_NTSTATUS_ERROR(ntStatus); Sids.pSids[i].pSid = pMemberSid; } pSids->dwNumSids = Sids.dwNumSids; pSids->pSids = Sids.pSids; cleanup: if (pMemberEntries) { DirectoryFreeEntries(pMemberEntries, dwMembersNum); } if (ntStatus == STATUS_SUCCESS && dwError != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(dwError); } return ntStatus; error: for (i = 0; i < dwMembersNum; i++) { SamrSrvFreeMemory(Sids.pSids[i].pSid); } SamrSrvFreeMemory(Sids.pSids); memset(pSids, 0, sizeof(*pSids)); goto cleanup; }
NTSTATUS SamrSrvQueryUserInfo( /* [in] */ handle_t hBinding, /* [in] */ ACCOUNT_HANDLE hUser, /* [in] */ UINT16 level, /* [out] */ UserInfo **info ) { PCSTR filterFormat = "%s=%Q"; NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = 0; PACCOUNT_CONTEXT pAcctCtx = NULL; PDOMAIN_CONTEXT pDomCtx = NULL; PCONNECT_CONTEXT pConnCtx = NULL; PWSTR pwszBase = NULL; WCHAR wszAttrObjectSid[] = DS_ATTR_OBJECT_SID; WCHAR wszAttrSamAccountName[] = DS_ATTR_SAM_ACCOUNT_NAME; WCHAR wszAttrFullName[] = DS_ATTR_FULL_NAME; WCHAR wszAttrPrimaryGroup[] = DS_ATTR_PRIMARY_GROUP; WCHAR wszAttrDescription[] = DS_ATTR_DESCRIPTION; WCHAR wszAttrComment[] = DS_ATTR_COMMENT; WCHAR wszAttrCountryCode[] = DS_ATTR_COUNTRY_CODE; WCHAR wszAttrCodePage[] = DS_ATTR_CODE_PAGE; WCHAR wszAttrHomeDirectory[] = DS_ATTR_HOME_DIR; WCHAR wszAttrHomeDrive[] = DS_ATTR_HOME_DRIVE; WCHAR wszAttrLogonScript[] = DS_ATTR_LOGON_SCRIPT; WCHAR wszAttrProfilePath[] = DS_ATTR_PROFILE_PATH; WCHAR wszAttrWorkstations[]= DS_ATTR_WORKSTATIONS; WCHAR wszAttrParameters[] = DS_ATTR_PARAMETERS; WCHAR wszAttrLastLogon[] = DS_ATTR_LAST_LOGON; WCHAR wszAttrLastLogoff[] = DS_ATTR_LAST_LOGOFF; WCHAR wszAttrPasswordLastSet[] = DS_ATTR_PASSWORD_LAST_SET; WCHAR wszAttrAllowPasswordChange[] = DS_ATTR_ALLOW_PASSWORD_CHANGE; WCHAR wszAttrForcePasswordChange[] = DS_ATTR_FORCE_PASSWORD_CHANGE; WCHAR wszAttrLogonHours[] = DS_ATTR_LOGON_HOURS; WCHAR wszAttrBadPasswordCount[] = DS_ATTR_BAD_PASSWORD_COUNT; WCHAR wszAttrLogonCount[] = DS_ATTR_LOGON_COUNT; WCHAR wszAttrAccountFlags[] = DS_ATTR_ACCOUNT_FLAGS; WCHAR wszAttrAccountExpiry[] = DS_ATTR_ACCOUNT_EXPIRY; WCHAR wszAttrLmHash[] = DS_ATTR_LM_HASH; WCHAR wszAttrNtHash[] = DS_ATTR_NT_HASH; CHAR szAttrDn[] = DS_ATTR_DISTINGUISHED_NAME; DWORD dwScope = 0; PSTR pszDn = NULL; PWSTR pwszFilter = NULL; PDIRECTORY_ENTRY pEntry = NULL; DWORD dwEntriesNum = 0; UserInfo *pUserInfo = NULL; PWSTR wszAttributesLevel1[] = { wszAttrSamAccountName, wszAttrFullName, wszAttrPrimaryGroup, wszAttrDescription, wszAttrComment, NULL }; PWSTR wszAttributesLevel2[] = { wszAttrComment, wszAttrCountryCode, wszAttrCodePage, NULL }; PWSTR wszAttributesLevel3[] = { wszAttrSamAccountName, wszAttrFullName, wszAttrObjectSid, wszAttrPrimaryGroup, wszAttrHomeDirectory, wszAttrHomeDrive, wszAttrLogonScript, wszAttrProfilePath, wszAttrWorkstations, wszAttrLastLogon, wszAttrLastLogoff, wszAttrPasswordLastSet, wszAttrAllowPasswordChange, wszAttrForcePasswordChange, wszAttrLogonHours, wszAttrBadPasswordCount, wszAttrLogonCount, wszAttrAccountFlags, NULL }; PWSTR wszAttributesLevel4[] = { wszAttrLogonHours, NULL }; PWSTR wszAttributesLevel5[] = { wszAttrSamAccountName, wszAttrFullName, wszAttrObjectSid, wszAttrPrimaryGroup, wszAttrHomeDirectory, wszAttrHomeDrive, wszAttrLogonScript, wszAttrProfilePath, wszAttrDescription, wszAttrWorkstations, wszAttrLastLogon, wszAttrLastLogoff, wszAttrLogonHours, wszAttrBadPasswordCount, wszAttrLogonCount, wszAttrPasswordLastSet, wszAttrAccountExpiry, wszAttrAccountFlags, NULL }; PWSTR wszAttributesLevel6[] = { wszAttrSamAccountName, wszAttrFullName, NULL }; PWSTR wszAttributesLevel7[] = { wszAttrSamAccountName, NULL }; PWSTR wszAttributesLevel8[] = { wszAttrFullName, NULL }; PWSTR wszAttributesLevel9[] = { wszAttrPrimaryGroup, NULL }; PWSTR wszAttributesLevel10[] = { wszAttrHomeDirectory, wszAttrHomeDrive, NULL }; PWSTR wszAttributesLevel11[] = { wszAttrLogonScript, NULL }; PWSTR wszAttributesLevel12[] = { wszAttrProfilePath, NULL }; PWSTR wszAttributesLevel13[] = { wszAttrDescription, NULL }; PWSTR wszAttributesLevel14[] = { wszAttrWorkstations, NULL }; PWSTR wszAttributesLevel16[] = { wszAttrAccountFlags, NULL }; PWSTR wszAttributesLevel17[] = { wszAttrAccountExpiry, NULL }; PWSTR wszAttributesLevel20[] = { wszAttrParameters, NULL }; PWSTR wszAttributesLevel21[] = { wszAttrLastLogon, wszAttrLastLogoff, wszAttrPasswordLastSet, wszAttrAccountExpiry, wszAttrAllowPasswordChange, wszAttrForcePasswordChange, wszAttrSamAccountName, wszAttrFullName, wszAttrHomeDirectory, wszAttrHomeDrive, wszAttrLogonScript, wszAttrProfilePath, wszAttrDescription, wszAttrWorkstations, wszAttrComment, wszAttrParameters, wszAttrObjectSid, wszAttrPrimaryGroup, wszAttrAccountFlags, wszAttrLogonHours, wszAttrBadPasswordCount, wszAttrLogonCount, wszAttrCountryCode, wszAttrCodePage, wszAttrLmHash, wszAttrNtHash, NULL }; PWSTR *pwszAttributes[] = { wszAttributesLevel1, wszAttributesLevel2, wszAttributesLevel3, wszAttributesLevel4, wszAttributesLevel5, wszAttributesLevel6, wszAttributesLevel7, wszAttributesLevel8, wszAttributesLevel9, wszAttributesLevel10, wszAttributesLevel11, wszAttributesLevel12, wszAttributesLevel13, wszAttributesLevel14, NULL, wszAttributesLevel16, wszAttributesLevel17, NULL, NULL, wszAttributesLevel20, wszAttributesLevel21 }; pAcctCtx = (PACCOUNT_CONTEXT)hUser; if (pAcctCtx == NULL || pAcctCtx->Type != SamrContextAccount) { ntStatus = STATUS_INVALID_HANDLE; BAIL_ON_NTSTATUS_ERROR(ntStatus); } switch (level) { case 15: case 18: case 19: ntStatus = STATUS_INVALID_INFO_CLASS; break; default: ntStatus = STATUS_SUCCESS; } BAIL_ON_NTSTATUS_ERROR(ntStatus); pDomCtx = pAcctCtx->pDomCtx; pConnCtx = pDomCtx->pConnCtx; pwszBase = pDomCtx->pwszDn; dwError = LwWc16sToMbs(pAcctCtx->pwszDn, &pszDn); BAIL_ON_LSA_ERROR(dwError); dwError = DirectoryAllocateWC16StringFilterPrintf( &pwszFilter, filterFormat, szAttrDn, pszDn); BAIL_ON_LSA_ERROR(dwError); dwError = DirectorySearch(pConnCtx->hDirectory, pwszBase, dwScope, pwszFilter, pwszAttributes[level - 1], FALSE, &pEntry, &dwEntriesNum); BAIL_ON_LSA_ERROR(dwError); if (dwEntriesNum == 0) { ntStatus = STATUS_INVALID_HANDLE; } else if (dwEntriesNum > 1) { ntStatus = STATUS_INTERNAL_ERROR; } BAIL_ON_NTSTATUS_ERROR(ntStatus); ntStatus = SamrSrvAllocateMemory((void**)&pUserInfo, sizeof(*pUserInfo)); BAIL_ON_NTSTATUS_ERROR(ntStatus); switch (level) { case 1: case 6: case 7: case 8: case 13: if (!(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_NAME_ETC) || !(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_ATTRIBUTES)) { ntStatus = STATUS_ACCESS_DENIED; BAIL_ON_NTSTATUS_ERROR(ntStatus); } break; case 2: if (!(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_LOCALE) || !(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_ATTRIBUTES)) { ntStatus = STATUS_ACCESS_DENIED; BAIL_ON_NTSTATUS_ERROR(ntStatus); } break; case 4: case 5: case 10: case 11: case 12: case 14: case 17: if (!(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_LOGONINFO) || !(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_ATTRIBUTES)) { ntStatus = STATUS_ACCESS_DENIED; BAIL_ON_NTSTATUS_ERROR(ntStatus); } break; case 3: case 9: case 16: case 20: case 21: if (!(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_ATTRIBUTES)) { ntStatus = STATUS_ACCESS_DENIED; BAIL_ON_NTSTATUS_ERROR(ntStatus); } break; } switch (level) { case 1: ntStatus = SamrFillUserInfo1(pEntry, pUserInfo); break; case 2: ntStatus = SamrFillUserInfo2(pEntry, pUserInfo); break; case 3: ntStatus = SamrFillUserInfo3(pAcctCtx, pEntry, pUserInfo); break; case 4: ntStatus = SamrFillUserInfo4(pEntry, pUserInfo); break; case 5: ntStatus = SamrFillUserInfo5(pEntry, pUserInfo); break; case 6: ntStatus = SamrFillUserInfo6(pEntry, pUserInfo); break; case 7: ntStatus = SamrFillUserInfo7(pEntry, pUserInfo); break; case 8: ntStatus = SamrFillUserInfo8(pEntry, pUserInfo); break; case 9: ntStatus = SamrFillUserInfo9(pEntry, pUserInfo); break; case 10: ntStatus = SamrFillUserInfo10(pEntry, pUserInfo); break; case 11: ntStatus = SamrFillUserInfo11(pEntry, pUserInfo); break; case 12: ntStatus = SamrFillUserInfo12(pEntry, pUserInfo); break; case 13: ntStatus = SamrFillUserInfo13(pEntry, pUserInfo); break; case 14: ntStatus = SamrFillUserInfo14(pEntry, pUserInfo); break; case 16: ntStatus = SamrFillUserInfo16(pEntry, pUserInfo); break; case 17: ntStatus = SamrFillUserInfo17(pEntry, pUserInfo); break; case 20: ntStatus = SamrFillUserInfo20(pEntry, pUserInfo); break; case 21: ntStatus = SamrFillUserInfo21(pAcctCtx, pEntry, pUserInfo); break; default: ntStatus = STATUS_INVALID_INFO_CLASS; } BAIL_ON_NTSTATUS_ERROR(ntStatus); *info = pUserInfo; cleanup: LW_SAFE_FREE_MEMORY(pszDn); LW_SAFE_FREE_MEMORY(pwszFilter); if (pEntry) { DirectoryFreeEntries(pEntry, dwEntriesNum); } return ntStatus; error: if (pUserInfo) { SamrSrvFreeMemory(pUserInfo); } *info = NULL; goto cleanup; }