SAM_HANDLE AccountDomainHandle;
SAM_ENUMERATE_HANDLE EnumerationContext;
- PSAM_RID_ENUMERATION EnumBuffer;
- ULONG EnumReturned;
+ PSAM_RID_ENUMERATION Buffer;
+ ULONG Returned;
+ ULONG Index;
+ BOOLEAN BuiltinDone;
} ENUM_CONTEXT, *PENUM_CONTEXT;
-static SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
-
static
-NTSTATUS
-GetAccountDomainSid(PSID *AccountDomainSid)
+NET_API_STATUS
+BuildAliasInfoBuffer(PALIAS_GENERAL_INFORMATION AliasInfo,
+ DWORD level,
+ LPVOID *Buffer)
{
- PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo = NULL;
- LSA_OBJECT_ATTRIBUTES ObjectAttributes;
- LSA_HANDLE PolicyHandle = NULL;
- ULONG Length = 0;
- NTSTATUS Status;
-
- memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
-
- Status = LsaOpenPolicy(NULL,
- &ObjectAttributes,
- POLICY_VIEW_LOCAL_INFORMATION,
- &PolicyHandle);
- if (!NT_SUCCESS(Status))
+ LPVOID LocalBuffer = NULL;
+ PLOCALGROUP_INFO_0 LocalInfo0;
+ PLOCALGROUP_INFO_1 LocalInfo1;
+ LPWSTR Ptr;
+ ULONG Size = 0;
+ NET_API_STATUS ApiStatus = NERR_Success;
+
+ *Buffer = NULL;
+
+ switch (level)
{
- ERR("LsaOpenPolicy failed (Status %08lx)\n", Status);
- return Status;
+ case 0:
+ Size = sizeof(LOCALGROUP_INFO_0) +
+ AliasInfo->Name.Length + sizeof(WCHAR);
+ break;
+
+ case 1:
+ Size = sizeof(LOCALGROUP_INFO_1) +
+ AliasInfo->Name.Length + sizeof(WCHAR) +
+ AliasInfo->AdminComment.Length + sizeof(WCHAR);
+ break;
+
+ default:
+ ApiStatus = ERROR_INVALID_LEVEL;
+ goto done;
}
- Status = LsaQueryInformationPolicy(PolicyHandle,
- PolicyAccountDomainInformation,
- (PVOID *)&AccountDomainInfo);
- if (!NT_SUCCESS(Status))
- {
- ERR("LsaQueryInformationPolicy failed (Status %08lx)\n", Status);
+ ApiStatus = NetApiBufferAllocate(Size, &LocalBuffer);
+ if (ApiStatus != NERR_Success)
goto done;
- }
- Length = RtlLengthSid(AccountDomainInfo->DomainSid);
+ ZeroMemory(LocalBuffer, Size);
- *AccountDomainSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
- if (*AccountDomainSid == NULL)
+ switch (level)
{
- ERR("Failed to allocate SID\n");
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto done;
- }
+ case 0:
+ LocalInfo0 = (PLOCALGROUP_INFO_0)LocalBuffer;
- memcpy(*AccountDomainSid, AccountDomainInfo->DomainSid, Length);
+ Ptr = (LPWSTR)LocalInfo0++;
+ LocalInfo0->lgrpi0_name = Ptr;
-done:
- if (AccountDomainInfo != NULL)
- LsaFreeMemory(AccountDomainInfo);
+ memcpy(LocalInfo0->lgrpi0_name,
+ AliasInfo->Name.Buffer,
+ AliasInfo->Name.Length);
+ LocalInfo0->lgrpi0_name[AliasInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
+ break;
+
+ case 1:
+ LocalInfo1 = (PLOCALGROUP_INFO_1)LocalBuffer;
+
+ Ptr = (LPWSTR)((ULONG_PTR)LocalInfo1 + sizeof(LOCALGROUP_INFO_1));
+ LocalInfo1->lgrpi1_name = Ptr;
- LsaClose(PolicyHandle);
+ memcpy(LocalInfo1->lgrpi1_name,
+ AliasInfo->Name.Buffer,
+ AliasInfo->Name.Length);
+ LocalInfo1->lgrpi1_name[AliasInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
+
+ Ptr = (LPWSTR)((ULONG_PTR)Ptr + AliasInfo->Name.Length + sizeof(WCHAR));
+ LocalInfo1->lgrpi1_comment = Ptr;
+
+ memcpy(LocalInfo1->lgrpi1_comment,
+ AliasInfo->AdminComment.Buffer,
+ AliasInfo->AdminComment.Length);
+ LocalInfo1->lgrpi1_comment[AliasInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
+ break;
+ }
+
+done:
+ if (ApiStatus == NERR_Success)
+ {
+ *Buffer = LocalBuffer;
+ }
+ else
+ {
+ if (LocalBuffer != NULL)
+ NetApiBufferFree(LocalBuffer);
+ }
- return Status;
+ return ApiStatus;
}
static
-NTSTATUS
-GetBuiltinDomainSid(PSID *BuiltinDomainSid)
+VOID
+FreeAliasInfo(PALIAS_GENERAL_INFORMATION AliasInfo)
{
- PSID Sid = NULL;
- PULONG Ptr;
- NTSTATUS Status = STATUS_SUCCESS;
+ if (AliasInfo->Name.Buffer != NULL)
+ SamFreeMemory(AliasInfo->Name.Buffer);
- *BuiltinDomainSid = NULL;
+ if (AliasInfo->AdminComment.Buffer != NULL)
+ SamFreeMemory(AliasInfo->AdminComment.Buffer);
- Sid = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- RtlLengthRequiredSid(1));
- if (Sid == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
+ SamFreeMemory(AliasInfo);
+}
- Status = RtlInitializeSid(Sid,
- &NtAuthority,
- 1);
- if (!NT_SUCCESS(Status))
- goto done;
- Ptr = RtlSubAuthoritySid(Sid, 0);
- *Ptr = SECURITY_BUILTIN_DOMAIN_RID;
+static
+NET_API_STATUS
+OpenAliasByName(SAM_HANDLE DomainHandle,
+ PUNICODE_STRING AliasName,
+ ULONG DesiredAccess,
+ PSAM_HANDLE AliasHandle)
+{
+ PULONG RelativeIds = NULL;
+ PSID_NAME_USE Use = NULL;
+ NET_API_STATUS ApiStatus = NERR_Success;
+ NTSTATUS Status = STATUS_SUCCESS;
- *BuiltinDomainSid = Sid;
+ /* Get the RID for the given user name */
+ Status = SamLookupNamesInDomain(DomainHandle,
+ 1,
+ AliasName,
+ &RelativeIds,
+ &Use);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
+ return NetpNtStatusToApiStatus(Status);
+ }
-done:
+ /* Fail, if it is not an alias account */
+ if (Use[0] != SidTypeAlias)
+ {
+ ERR("Object is not an Alias!\n");
+ ApiStatus = NERR_GroupNotFound;
+ goto done;
+ }
+
+ /* Open the alias account */
+ Status = SamOpenAlias(DomainHandle,
+ DesiredAccess,
+ RelativeIds[0],
+ AliasHandle);
if (!NT_SUCCESS(Status))
{
- if (Sid != NULL)
- RtlFreeHeap(RtlGetProcessHeap(), 0, Sid);
+ ERR("SamOpenDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
}
- return Status;
+done:
+ if (RelativeIds != NULL)
+ SamFreeMemory(RelativeIds);
+
+ if (Use != NULL)
+ SamFreeMemory(Use);
+
+ return ApiStatus;
}
/************************************************************
- * NetLocalGroupAdd (NETAPI32.@)
+ * NetLocalGroupAdd (NETAPI32.@)
*/
-NET_API_STATUS WINAPI NetLocalGroupAdd(
+NET_API_STATUS
+WINAPI
+NetLocalGroupAdd(
LPCWSTR servername,
DWORD level,
LPBYTE buf,
LPDWORD parm_err)
{
- FIXME("(%s %d %p %p) stub!\n", debugstr_w(servername), level, buf,
+ ALIAS_ADM_COMMENT_INFORMATION AdminComment;
+ UNICODE_STRING ServerName;
+ UNICODE_STRING AliasName;
+ SAM_HANDLE ServerHandle = NULL;
+ SAM_HANDLE DomainHandle = NULL;
+ SAM_HANDLE AliasHandle = NULL;
+ PSID DomainSid = NULL;
+ LPWSTR aliasname = NULL;
+ LPWSTR aliascomment = NULL;
+ ULONG RelativeId;
+ NET_API_STATUS ApiStatus = NERR_Success;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TRACE("(%s %d %p %p) stub!\n", debugstr_w(servername), level, buf,
parm_err);
- return NERR_Success;
+
+ /* Initialize the Server name*/
+ if (servername != NULL)
+ RtlInitUnicodeString(&ServerName, servername);
+
+ /* Initialize the Alias name*/
+ switch (level)
+ {
+ case 0:
+ aliasname = ((PLOCALGROUP_INFO_0)buf)->lgrpi0_name;
+ aliascomment = NULL;
+ break;
+
+ case 1:
+ aliasname = ((PLOCALGROUP_INFO_1)buf)->lgrpi1_name;
+ aliascomment = ((PLOCALGROUP_INFO_1)buf)->lgrpi1_comment;
+ break;
+
+ default:
+ return ERROR_INVALID_LEVEL;
+ }
+
+ RtlInitUnicodeString(&AliasName, aliasname);
+
+ /* Connect to the SAM Server */
+ Status = SamConnect((servername != NULL) ? &ServerName : NULL,
+ &ServerHandle,
+ SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamConnect failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Get the Builtin Domain SID */
+ Status = GetBuiltinDomainSid(&DomainSid);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("GetBuiltinDomainSid failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the Builtin Domain */
+ Status = SamOpenDomain(ServerHandle,
+ DOMAIN_LOOKUP,
+ DomainSid,
+ &DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamOpenDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Try to open the Alias Account in the Builtin Domain */
+ ApiStatus = OpenAliasByName(DomainHandle,
+ &AliasName,
+ ALIAS_READ_INFORMATION,
+ &AliasHandle);
+ if (ApiStatus == NERR_Success)
+ {
+ ERR("OpenAliasByName: alias %wZ already exists!\n", &AliasName);
+
+ SamCloseHandle(AliasHandle);
+ ApiStatus = ERROR_ALIAS_EXISTS;
+ goto done;
+ }
+
+ ApiStatus = NERR_Success;
+
+ /* Free the Builtin Domain SID */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
+ DomainSid = NULL;
+
+ /* Close the Builtin Domain */
+ SamCloseHandle(DomainHandle);
+ DomainHandle = NULL;
+
+ /* Get the account domain SID */
+ Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
+ &DomainSid);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the account domain */
+ Status = SamOpenDomain(ServerHandle,
+ DOMAIN_CREATE_ALIAS | DOMAIN_LOOKUP,
+ DomainSid,
+ &DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamOpenDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Create the alias */
+ Status = SamCreateAliasInDomain(DomainHandle,
+ &AliasName,
+ DELETE | ALIAS_WRITE_ACCOUNT,
+ &AliasHandle,
+ &RelativeId);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamCreateAliasInDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ TRACE("Created alias \"%wZ\" (RID: %lu)\n", &AliasName, RelativeId);
+
+ /* Set the admin comment */
+ if (level == 1)
+ {
+ RtlInitUnicodeString(&AdminComment.AdminComment, aliascomment);
+
+ Status = SamSetInformationAlias(AliasHandle,
+ AliasAdminCommentInformation,
+ &AdminComment);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamSetInformationAlias failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+
+ /* Delete the Alias if the Comment could not be set */
+ SamDeleteAlias(AliasHandle);
+
+ goto done;
+ }
+ }
+
+done:
+ if (AliasHandle != NULL)
+ SamCloseHandle(AliasHandle);
+
+ if (DomainSid != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
+
+ if (DomainHandle != NULL)
+ SamCloseHandle(DomainHandle);
+
+ if (ServerHandle != NULL)
+ SamCloseHandle(ServerHandle);
+
+ return ApiStatus;
}
+
/************************************************************
* NetLocalGroupAddMember (NETAPI32.@)
*/
LPDWORD totalentries,
PDWORD_PTR resumehandle)
{
+ UNICODE_STRING ServerName;
+ PSAM_RID_ENUMERATION CurrentAlias;
PENUM_CONTEXT EnumContext = NULL;
PSID DomainSid = NULL;
ULONG i;
-
+ SAM_HANDLE AliasHandle = NULL;
+ PALIAS_GENERAL_INFORMATION AliasInfo = NULL;
+ LPVOID Buffer = NULL;
NET_API_STATUS ApiStatus = NERR_Success;
NTSTATUS Status = STATUS_SUCCESS;
-
- FIXME("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername),
+ TRACE("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername),
level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
*entriesread = 0;
*totalentries = 0;
*bufptr = NULL;
+ if (servername != NULL)
+ RtlInitUnicodeString(&ServerName, servername);
+
if (resumehandle != NULL && *resumehandle != 0)
{
- EnumContext = (PENUM_CONTEXT)resumehandle;
+ EnumContext = (PENUM_CONTEXT)*resumehandle;
}
else
{
goto done;
EnumContext->EnumerationContext = 0;
- EnumContext->EnumBuffer = NULL;
- EnumContext->EnumReturned = 0;
+ EnumContext->Buffer = NULL;
+ EnumContext->Returned = 0;
+ EnumContext->Index = 0;
+ EnumContext->BuiltinDone = FALSE;
- Status = SamConnect(NULL,
+ Status = SamConnect((servername != NULL) ? &ServerName : NULL,
&EnumContext->ServerHandle,
SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
NULL);
goto done;
}
- Status = GetAccountDomainSid(&DomainSid);
+ Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
+ &DomainSid);
if (!NT_SUCCESS(Status))
{
ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
}
Status = SamOpenDomain(EnumContext->ServerHandle,
- DOMAIN_LIST_ACCOUNTS,
+ DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
DomainSid,
&EnumContext->AccountDomainHandle);
}
Status = SamOpenDomain(EnumContext->ServerHandle,
- DOMAIN_LIST_ACCOUNTS,
+ DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
DomainSid,
&EnumContext->BuiltinDomainHandle);
}
}
- while (TRUE)
- {
- Status = SamEnumerateAliasesInDomain(EnumContext->BuiltinDomainHandle,
- &EnumContext->EnumerationContext,
- (PVOID *)&EnumContext->EnumBuffer,
- prefmaxlen,
- &EnumContext->EnumReturned);
- TRACE("SamEnumerateAliasesInDomain returned (Status %08lx)\n", Status);
+// while (TRUE)
+// {
+ TRACE("EnumContext->Index: %lu\n", EnumContext->Index);
+ TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
+ if (EnumContext->Index >= EnumContext->Returned)
+ {
+// if (EnumContext->BuiltinDone == TRUE)
+// {
+// ApiStatus = NERR_Success;
+// goto done;
+// }
+
+ TRACE("Calling SamEnumerateAliasesInDomain\n");
+
+ Status = SamEnumerateAliasesInDomain(EnumContext->BuiltinDomainHandle,
+ &EnumContext->EnumerationContext,
+ (PVOID *)&EnumContext->Buffer,
+ prefmaxlen,
+ &EnumContext->Returned);
+
+ TRACE("SamEnumerateAliasesInDomain returned (Status %08lx)\n", Status);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ if (Status == STATUS_MORE_ENTRIES)
+ {
+ ApiStatus = NERR_BufTooSmall;
+ goto done;
+ }
+ else
+ {
+ EnumContext->BuiltinDone = TRUE;
+ }
+ }
+
+ TRACE("EnumContext: %lu\n", EnumContext);
+ TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
+ TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
+
+ /* Get a pointer to the current alias */
+ CurrentAlias = &EnumContext->Buffer[EnumContext->Index];
+
+ TRACE("RID: %lu\n", CurrentAlias->RelativeId);
+
+ Status = SamOpenAlias(EnumContext->BuiltinDomainHandle,
+ ALIAS_READ_INFORMATION,
+ CurrentAlias->RelativeId,
+ &AliasHandle);
if (!NT_SUCCESS(Status))
{
- ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status);
+ ERR("SamOpenAlias failed (Status %08lx)\n", Status);
ApiStatus = NetpNtStatusToApiStatus(Status);
goto done;
}
- TRACE("EnumContext: %lu\n", EnumContext);
- TRACE("EnumReturned: %lu\n", EnumContext->EnumReturned);
- TRACE("EnumBuffer: %p\n", EnumContext->EnumBuffer);
+ Status = SamQueryInformationAlias(AliasHandle,
+ AliasGeneralInformation,
+ (PVOID *)&AliasInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ SamCloseHandle(AliasHandle);
+ AliasHandle = NULL;
+
+ TRACE("Name: %S\n", AliasInfo->Name.Buffer);
+ TRACE("Comment: %S\n", AliasInfo->AdminComment.Buffer);
+
+ ApiStatus = BuildAliasInfoBuffer(AliasInfo,
+ level,
+ &Buffer);
+ if (ApiStatus != NERR_Success)
+ goto done;
- for (i = 0; i < EnumContext->EnumReturned; i++)
+ if (AliasInfo != NULL)
{
- TRACE("RID: %lu\n", EnumContext->EnumBuffer[i].RelativeId);
- TRACE("Name: %p\n", EnumContext->EnumBuffer[i].Name.Buffer);
- TRACE("Name: %S\n", EnumContext->EnumBuffer[i].Name.Buffer);
- if (EnumContext->EnumBuffer[i].Name.Buffer != NULL)
- {
- TRACE("Name: %hx\n", EnumContext->EnumBuffer[i].Name.Buffer[0]);
- }
+ FreeAliasInfo(AliasInfo);
+ AliasInfo = NULL;
}
- if (Status != STATUS_MORE_ENTRIES)
- break;
- }
+ EnumContext->Index++;
+ (*entriesread)++;
+
+// }
done:
+ if (ApiStatus == NERR_Success && EnumContext->Index < EnumContext->Returned)
+ ApiStatus = ERROR_MORE_DATA;
+
+ if (EnumContext != NULL)
+ *totalentries = EnumContext->Returned;
+
if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA)
{
if (EnumContext != NULL)
if (EnumContext->ServerHandle != NULL)
SamCloseHandle(EnumContext->ServerHandle);
- if (EnumContext->EnumBuffer != NULL)
+ if (EnumContext->Buffer != NULL)
{
- for (i = 0; i < EnumContext->EnumReturned; i++)
+ for (i = 0; i < EnumContext->Returned; i++)
{
- SamFreeMemory(EnumContext->EnumBuffer[i].Name.Buffer);
+ SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
}
- SamFreeMemory(EnumContext->EnumBuffer);
+ SamFreeMemory(EnumContext->Buffer);
}
NetApiBufferFree(EnumContext);
}
}
+ if (AliasHandle != NULL)
+ SamCloseHandle(AliasHandle);
+
+ if (AliasInfo != NULL)
+ FreeAliasInfo(AliasInfo);
if (resumehandle != NULL)
*resumehandle = (DWORD_PTR)EnumContext;
+ *bufptr = (LPBYTE)Buffer;
+
+ TRACE ("return %lu\n", ApiStatus);
+
return ApiStatus;
}
+
/************************************************************
- * NetLocalGroupGetInfo (NETAPI32.@)
+ * NetLocalGroupGetInfo (NETAPI32.@)
*/
-NET_API_STATUS WINAPI NetLocalGroupGetInfo(
+NET_API_STATUS
+WINAPI
+NetLocalGroupGetInfo(
LPCWSTR servername,
LPCWSTR groupname,
DWORD level,
LPBYTE* bufptr)
{
- FIXME("(%s %s %d %p) stub!\n", debugstr_w(servername),
+ UNICODE_STRING ServerName;
+ UNICODE_STRING GroupName;
+ SAM_HANDLE ServerHandle = NULL;
+ SAM_HANDLE DomainHandle = NULL;
+ SAM_HANDLE AliasHandle = NULL;
+ PSID DomainSid = NULL;
+ PALIAS_GENERAL_INFORMATION AliasInfo = NULL;
+ LPVOID Buffer = NULL;
+ NET_API_STATUS ApiStatus = NERR_Success;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TRACE("(%s %s %d %p) stub!\n", debugstr_w(servername),
debugstr_w(groupname), level, bufptr);
- return NERR_Success;
+
+ if (servername != NULL)
+ RtlInitUnicodeString(&ServerName, servername);
+
+ RtlInitUnicodeString(&GroupName, groupname);
+
+ /* Connect to the SAM Server */
+ Status = SamConnect((servername != NULL) ? &ServerName : NULL,
+ &ServerHandle,
+ SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamConnect failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Get the Builtin Domain SID */
+ Status = GetBuiltinDomainSid(&DomainSid);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("GetBuiltinDomainSid failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the Builtin Domain */
+ Status = SamOpenDomain(ServerHandle,
+ DOMAIN_LOOKUP,
+ DomainSid,
+ &DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamOpenDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the alias account in the builtin domain */
+ ApiStatus = OpenAliasByName(DomainHandle,
+ &GroupName,
+ ALIAS_READ_INFORMATION,
+ &AliasHandle);
+ if (ApiStatus != NERR_Success)
+ {
+ ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
+ goto done;
+ }
+
+ if (AliasHandle == NULL)
+ {
+ if (DomainSid != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
+
+ if (DomainHandle != NULL)
+ SamCloseHandle(DomainHandle);
+
+ /* Get the Account Domain SID */
+ Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
+ &DomainSid);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the Acount Domain */
+ Status = SamOpenDomain(ServerHandle,
+ DOMAIN_LOOKUP,
+ DomainSid,
+ &DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamOpenDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the alias account in the account domain */
+ ApiStatus = OpenAliasByName(DomainHandle,
+ &GroupName,
+ ALIAS_READ_INFORMATION,
+ &AliasHandle);
+ if (ApiStatus != NERR_Success)
+ {
+ ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
+ goto done;
+ }
+ }
+
+ Status = SamQueryInformationAlias(AliasHandle,
+ AliasGeneralInformation,
+ (PVOID *)&AliasInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ ApiStatus = BuildAliasInfoBuffer(AliasInfo,
+ level,
+ &Buffer);
+ if (ApiStatus != NERR_Success)
+ goto done;
+
+done:
+ if (AliasInfo != NULL)
+ FreeAliasInfo(AliasInfo);
+
+ if (AliasHandle != NULL)
+ SamCloseHandle(AliasHandle);
+
+ if (DomainSid != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
+
+ if (DomainHandle != NULL)
+ SamCloseHandle(DomainHandle);
+
+ if (ServerHandle != NULL)
+ SamCloseHandle(ServerHandle);
+
+ *bufptr = (LPBYTE)Buffer;
+
+ return ApiStatus;
}
+
/************************************************************
* NetLocalGroupGetMembers (NETAPI32.@)
*/