Exemple #1
0
NTSTATUS
SetAdministratorPassword(LPCWSTR Password)
{
    PPOLICY_ACCOUNT_DOMAIN_INFO OrigInfo = NULL;
    PUSER_ACCOUNT_NAME_INFORMATION AccountNameInfo = NULL;
    USER_SET_PASSWORD_INFORMATION PasswordInfo;
    LSA_OBJECT_ATTRIBUTES ObjectAttributes;
    LSA_HANDLE PolicyHandle = NULL;
    SAM_HANDLE ServerHandle = NULL;
    SAM_HANDLE DomainHandle = NULL;
    SAM_HANDLE UserHandle = NULL;
    NTSTATUS Status;

    DPRINT1("SYSSETUP: SetAdministratorPassword(%S)\n", Password);

    memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
    ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES);

    Status = LsaOpenPolicy(NULL,
                           &ObjectAttributes,
                           POLICY_VIEW_LOCAL_INFORMATION | POLICY_TRUST_ADMIN,
                           &PolicyHandle);
    if (Status != STATUS_SUCCESS)
    {
        DPRINT1("LsaOpenPolicy() failed (Status: 0x%08lx)\n", Status);
        return Status;
    }

    Status = LsaQueryInformationPolicy(PolicyHandle,
                                       PolicyAccountDomainInformation,
                                       (PVOID *)&OrigInfo);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("LsaQueryInformationPolicy() failed (Status: 0x%08lx)\n", Status);
        goto done;
    }

    Status = SamConnect(NULL,
                        &ServerHandle,
                        SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
                        NULL);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("SamConnect() failed (Status: 0x%08lx)\n", Status);
        goto done;
    }

    Status = SamOpenDomain(ServerHandle,
                           DOMAIN_LOOKUP,
                           OrigInfo->DomainSid,
                           &DomainHandle);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("SamOpenDomain() failed (Status: 0x%08lx)\n", Status);
        goto done;
    }

    Status = SamOpenUser(DomainHandle,
                         USER_FORCE_PASSWORD_CHANGE | USER_READ_GENERAL,
                         DOMAIN_USER_RID_ADMIN,
                         &UserHandle);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("SamOpenUser() failed (Status %08lx)\n", Status);
        goto done;
    }

    RtlInitUnicodeString(&PasswordInfo.Password, Password);
    PasswordInfo.PasswordExpired = FALSE;

    Status = SamSetInformationUser(UserHandle,
                                   UserSetPasswordInformation,
                                   (PVOID)&PasswordInfo);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("SamSetInformationUser() failed (Status %08lx)\n", Status);
        goto done;
    }

    Status = SamQueryInformationUser(UserHandle,
                                     UserAccountNameInformation,
                                     (PVOID*)&AccountNameInfo);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("SamSetInformationUser() failed (Status %08lx)\n", Status);
        goto done;
    }

    AdminInfo.Name = RtlAllocateHeap(RtlGetProcessHeap(),
                                     HEAP_ZERO_MEMORY,
                                     AccountNameInfo->UserName.Length + sizeof(WCHAR));
    if (AdminInfo.Name != NULL)
        RtlCopyMemory(AdminInfo.Name,
                      AccountNameInfo->UserName.Buffer,
                      AccountNameInfo->UserName.Length);

    AdminInfo.Domain = RtlAllocateHeap(RtlGetProcessHeap(),
                                       HEAP_ZERO_MEMORY,
                                       OrigInfo->DomainName.Length + sizeof(WCHAR));
    if (AdminInfo.Domain != NULL)
        RtlCopyMemory(AdminInfo.Domain,
                      OrigInfo->DomainName.Buffer,
                      OrigInfo->DomainName.Length);

    AdminInfo.Password = RtlAllocateHeap(RtlGetProcessHeap(),
                                         0,
                                         (wcslen(Password) + 1) * sizeof(WCHAR));
    if (AdminInfo.Password != NULL)
        wcscpy(AdminInfo.Password, Password);

    DPRINT("Administrator Name: %S\n", AdminInfo.Name);
    DPRINT("Administrator Domain: %S\n", AdminInfo.Domain);
    DPRINT("Administrator Password: %S\n", AdminInfo.Password);

done:
    if (AccountNameInfo != NULL)
        SamFreeMemory(AccountNameInfo);

    if (OrigInfo != NULL)
        LsaFreeMemory(OrigInfo);

    if (PolicyHandle != NULL)
        LsaClose(PolicyHandle);

    if (UserHandle != NULL)
        SamCloseHandle(UserHandle);

    if (DomainHandle != NULL)
        SamCloseHandle(DomainHandle);

    if (ServerHandle != NULL)
        SamCloseHandle(ServerHandle);

    DPRINT1("SYSSETUP: SetAdministratorPassword() done (Status %08lx)\n", Status);

    return Status;
}
Exemple #2
0
NTSTATUS
SetAccountDomain(LPCWSTR DomainName,
                 PSID DomainSid)
{
    PPOLICY_ACCOUNT_DOMAIN_INFO OrigInfo = NULL;
    POLICY_ACCOUNT_DOMAIN_INFO Info;
    LSA_OBJECT_ATTRIBUTES ObjectAttributes;
    LSA_HANDLE PolicyHandle;

    SAM_HANDLE ServerHandle = NULL;
    SAM_HANDLE DomainHandle = NULL;
    DOMAIN_NAME_INFORMATION DomainNameInfo;

    NTSTATUS Status;

    DPRINT1("SYSSETUP: SetAccountDomain\n");

    memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
    ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES);

    Status = LsaOpenPolicy(NULL,
                           &ObjectAttributes,
                           POLICY_VIEW_LOCAL_INFORMATION | POLICY_TRUST_ADMIN,
                           &PolicyHandle);
    if (Status != STATUS_SUCCESS)
    {
        DPRINT("LsaOpenPolicy failed (Status: 0x%08lx)\n", Status);
        return Status;
    }

    Status = LsaQueryInformationPolicy(PolicyHandle,
                                       PolicyAccountDomainInformation,
                                       (PVOID *)&OrigInfo);
    if (Status == STATUS_SUCCESS && OrigInfo != NULL)
    {
        if (DomainName == NULL)
        {
            Info.DomainName.Buffer = OrigInfo->DomainName.Buffer;
            Info.DomainName.Length = OrigInfo->DomainName.Length;
            Info.DomainName.MaximumLength = OrigInfo->DomainName.MaximumLength;
        }
        else
        {
            Info.DomainName.Buffer = (LPWSTR)DomainName;
            Info.DomainName.Length = wcslen(DomainName) * sizeof(WCHAR);
            Info.DomainName.MaximumLength = Info.DomainName.Length + sizeof(WCHAR);
        }

        if (DomainSid == NULL)
            Info.DomainSid = OrigInfo->DomainSid;
        else
            Info.DomainSid = DomainSid;
    }
    else
    {
        Info.DomainName.Buffer = (LPWSTR)DomainName;
        Info.DomainName.Length = wcslen(DomainName) * sizeof(WCHAR);
        Info.DomainName.MaximumLength = Info.DomainName.Length + sizeof(WCHAR);
        Info.DomainSid = DomainSid;
    }

    Status = LsaSetInformationPolicy(PolicyHandle,
                                     PolicyAccountDomainInformation,
                                     (PVOID)&Info);
    if (Status != STATUS_SUCCESS)
    {
        DPRINT("LsaSetInformationPolicy failed (Status: 0x%08lx)\n", Status);
    }

    if (OrigInfo != NULL)
        LsaFreeMemory(OrigInfo);

    LsaClose(PolicyHandle);

    DomainNameInfo.DomainName.Length = wcslen(DomainName) * sizeof(WCHAR);
    DomainNameInfo.DomainName.MaximumLength = (wcslen(DomainName) + 1) * sizeof(WCHAR);
    DomainNameInfo.DomainName.Buffer = (LPWSTR)DomainName;

    Status = SamConnect(NULL,
                        &ServerHandle,
                        SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
                        NULL);
    if (NT_SUCCESS(Status))
    {
        Status = SamOpenDomain(ServerHandle,
                               DOMAIN_WRITE_OTHER_PARAMETERS,
                               Info.DomainSid,
                               &DomainHandle);
        if (NT_SUCCESS(Status))
        {
            Status = SamSetInformationDomain(DomainHandle,
                                             DomainNameInformation,
                                             (PVOID)&DomainNameInfo);
            if (!NT_SUCCESS(Status))
            {
                DPRINT1("SamSetInformationDomain failed (Status: 0x%08lx)\n", Status);
            }

            SamCloseHandle(DomainHandle);
        }
        else
        {
            DPRINT1("SamOpenDomain failed (Status: 0x%08lx)\n", Status);
        }

        SamCloseHandle(ServerHandle);
    }

    return Status;
}
Exemple #3
0
void impersonateToGetData(PCSTR user, PCSTR domain, PCSTR password, PCSTR kdc, PSID *sid, DWORD *rid, PCSTR usingWhat)
{
	NTSTATUS status;
	DWORD ret, *aRid, *usage;
	ANSI_STRING aUser, aKdc, aDomain, aPass, aProg;
	UNICODE_STRING uUser, uKdc, uDomain, uPass, uProg;
	SAMPR_HANDLE hServerHandle, hDomainHandle;
	PSID domainSid;
	HANDLE hToken, hNewToken;
	PROCESS_INFORMATION processInfos;
	STARTUPINFOW startupInfo;
	RtlZeroMemory(&startupInfo, sizeof(STARTUPINFOW));
	startupInfo.cb = sizeof(STARTUPINFOW);

	RtlInitString(&aUser, user);
	RtlInitString(&aKdc, kdc);
	RtlInitString(&aDomain, domain);
	RtlInitString(&aPass, password);
	RtlInitString(&aProg, usingWhat ? usingWhat : "winver.exe");
	if(NT_SUCCESS(RtlAnsiStringToUnicodeString(&uUser, &aUser, TRUE)))
	{
		if(NT_SUCCESS(RtlAnsiStringToUnicodeString(&uKdc, &aKdc, TRUE)))
		{
			if(NT_SUCCESS(RtlAnsiStringToUnicodeString(&uDomain, &aDomain, TRUE)))
			{
				if(NT_SUCCESS(RtlAnsiStringToUnicodeString(&uPass, &aPass, TRUE)))
				{

					if(NT_SUCCESS(RtlAnsiStringToUnicodeString(&uProg, &aProg, TRUE)))
					{
						if(CreateProcessWithLogonW(uUser.Buffer, uDomain.Buffer, uPass.Buffer, LOGON_NETCREDENTIALS_ONLY, uProg.Buffer, NULL, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInfos))
						{
							if(OpenProcessToken(processInfos.hProcess, TOKEN_DUPLICATE, &hToken))
							{
								if(DuplicateTokenEx(hToken, TOKEN_QUERY | TOKEN_IMPERSONATE, NULL, SecurityDelegation, TokenImpersonation, &hNewToken))
								{
									if(SetThreadToken(NULL, hNewToken))
									{
										kprintf("[AUTH] Impersonation\n");
										if(!(*sid && *rid))
										{
											kprintf("[SID/RID] \'%s @ %s\' must be translated to SID/RID\n", user, domain);
											status = SamConnect(&uKdc, &hServerHandle, SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, FALSE);
											if(NT_SUCCESS(status))
											{
												status = SamLookupDomainInSamServer(hServerHandle, &uDomain, &domainSid);
												if(NT_SUCCESS(status))
												{
													status = SamOpenDomain(hServerHandle, DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP, domainSid, &hDomainHandle);
													if(NT_SUCCESS(status))
													{
														status = SamLookupNamesInDomain(hDomainHandle, 1, &uUser, &aRid, &usage);
														if(NT_SUCCESS(status))
															*rid = *aRid;
														else PRINT_ERROR("SamLookupNamesInDomain %08x\n", status);
													}
													else PRINT_ERROR("SamOpenDomain %08x\n", status);

													ret = GetLengthSid(domainSid);
													if(*sid = (PSID) LocalAlloc(LPTR, ret))
													{
														if(!CopySid(ret, *sid, domainSid))
														{
															*sid = (PSID) LocalFree(*sid);
															PRINT_ERROR_AUTO("CopySid");
														}
													}
													SamFreeMemory(domainSid);
												}
												else PRINT_ERROR("SamLookupDomainInSamServer %08x\n", status);
												SamCloseHandle(hServerHandle);
											}
											else PRINT_ERROR("SamConnect %08x\n", status);
										}
										RevertToSelf();
									}
									else PRINT_ERROR_AUTO("SetThreadToken");
									CloseHandle(hNewToken);
								}
								else PRINT_ERROR_AUTO("DuplicateTokenEx");
								CloseHandle(hToken);
							}
							else PRINT_ERROR_AUTO("OpenProcessToken");
							TerminateProcess(processInfos.hProcess, 0);
							CloseHandle(processInfos.hProcess);
							CloseHandle(processInfos.hThread);
						}
						else PRINT_ERROR_AUTO("CreateProcessWithLogonW");

						RtlFreeUnicodeString(&uProg);
					}
					RtlFreeUnicodeString(&uPass);
				}
				RtlFreeUnicodeString(&uDomain);
			}
			RtlFreeUnicodeString(&uKdc);
		}
		RtlFreeUnicodeString(&uUser);
	}
}
Exemple #4
0
NTSTATUS kuhl_m_net_user(int argc, wchar_t * argv[])
{
	NTSTATUS status, enumDomainStatus, enumUserStatus;
	UNICODE_STRING serverName, *groupName;
	SAMPR_HANDLE hServerHandle, hBuiltinHandle = NULL, hDomainHandle, hUserHandle;
	DWORD domainEnumerationContext, domainCountRetourned, userEnumerationContext, userCountRetourned, groupsCountRetourned, i, j, k, *usage, aliasCountRetourned, *alias;
	PSAMPR_RID_ENUMERATION pEnumDomainBuffer, pEnumUsersBuffer;
	PSID domainSid, userSid;
	PGROUP_MEMBERSHIP pGroupMemberShip;
	SID builtin = {1, 1, {0, 0, 0, 0, 0, 5}, {32}};

	RtlInitUnicodeString(&serverName, argc ? argv[0] : L"");
	status = SamConnect(&serverName, &hServerHandle, SAM_SERVER_CONNECT | SAM_SERVER_ENUMERATE_DOMAINS | SAM_SERVER_LOOKUP_DOMAIN, FALSE);
	if(NT_SUCCESS(status))
	{
		status = SamOpenDomain(hServerHandle, DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP, &builtin, &hBuiltinHandle);
		if(!NT_SUCCESS(status))
			PRINT_ERROR(L"SamOpenDomain Builtin (?) %08x\n", status);
		
		domainEnumerationContext = 0;
		do
		{
			enumDomainStatus = SamEnumerateDomainsInSamServer(hServerHandle, &domainEnumerationContext, &pEnumDomainBuffer, 1, &domainCountRetourned);
			if(NT_SUCCESS(enumDomainStatus) || enumDomainStatus == STATUS_MORE_ENTRIES)
			{
				for(i = 0; i < domainCountRetourned; i++)
				{
					kprintf(L"\nDomain name : %wZ", &pEnumDomainBuffer[i].Name);
					status = SamLookupDomainInSamServer(hServerHandle, &pEnumDomainBuffer[i].Name, &domainSid);
					if(NT_SUCCESS(status))
					{
						kprintf(L"\nDomain SID  : ");
						kull_m_string_displaySID(domainSid);
						
						status = SamOpenDomain(hServerHandle, DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP, domainSid, &hDomainHandle);
						if(NT_SUCCESS(status))
						{
							userEnumerationContext = 0;
							do
							{
								enumUserStatus = SamEnumerateUsersInDomain(hDomainHandle, &userEnumerationContext, 0/*UF_NORMAL_ACCOUNT*/, &pEnumUsersBuffer, 1, &userCountRetourned);
								if(NT_SUCCESS(enumUserStatus) || enumUserStatus == STATUS_MORE_ENTRIES)
								{
									for(j = 0; j < userCountRetourned; j++)
									{
										kprintf(L"\n %-5u %wZ", pEnumUsersBuffer[j].RelativeId, &pEnumUsersBuffer[j].Name);
										status = SamOpenUser(hDomainHandle, USER_READ_GROUP_INFORMATION | USER_LIST_GROUPS | USER_READ_ACCOUNT | USER_READ_LOGON |  USER_READ_PREFERENCES | USER_READ_GENERAL, pEnumUsersBuffer[j].RelativeId, &hUserHandle);
										if(NT_SUCCESS(status))
										{
											status = SamGetGroupsForUser(hUserHandle, &pGroupMemberShip, &groupsCountRetourned);
											if(NT_SUCCESS(status))
											{
												for(k = 0; k < groupsCountRetourned; k++)
												{
													kprintf(L"\n | %-5u ", pGroupMemberShip[k].RelativeId);
													status = SamLookupIdsInDomain(hDomainHandle, 1, &pGroupMemberShip[k].RelativeId, &groupName, &usage);
													if(NT_SUCCESS(status))
													{
														kprintf(L"%wZ", groupName);
														SamFreeMemory(groupName);
														SamFreeMemory(usage);
													} else PRINT_ERROR(L"SamLookupIdsInDomain %08x", status);
												}
												SamFreeMemory(pGroupMemberShip);
											} else PRINT_ERROR(L"SamGetGroupsForUser %08x", status);

											status = SamRidToSid(hUserHandle, pEnumUsersBuffer[j].RelativeId, &userSid);
											if(NT_SUCCESS(status))
											{
												status = SamGetAliasMembership(hDomainHandle, 1, &userSid, &aliasCountRetourned, &alias);
												if(NT_SUCCESS(status))
												{
													for(k = 0; k < aliasCountRetourned; k++)
													{
														kprintf(L"\n |`%-5u ", alias[k]);
														status = SamLookupIdsInDomain(hDomainHandle, 1, &alias[k], &groupName, &usage);
														if(NT_SUCCESS(status))
														{
															kprintf(L"%wZ", groupName);
															SamFreeMemory(groupName);
															SamFreeMemory(usage);
														} else PRINT_ERROR(L"SamLookupIdsInDomain %08x", status);
													}
													SamFreeMemory(alias);
												} else PRINT_ERROR(L"SamGetAliasMembership %08x", status);

												if(hBuiltinHandle)
												{
													status = SamGetAliasMembership(hBuiltinHandle, 1, &userSid, &aliasCountRetourned, &alias);
													if(NT_SUCCESS(status))
													{
														for(k = 0; k < aliasCountRetourned; k++)
														{
															kprintf(L"\n |´%-5u ", alias[k]);
															status = SamLookupIdsInDomain(hBuiltinHandle, 1, &alias[k], &groupName, &usage);
															if(NT_SUCCESS(status))
															{
																kprintf(L"%wZ", groupName);
																SamFreeMemory(groupName);
																SamFreeMemory(usage);
															} else PRINT_ERROR(L"SamLookupIdsInDomain %08x", status);
														}
														SamFreeMemory(alias);
													} else PRINT_ERROR(L"SamGetAliasMembership %08x", status);
												}


												SamFreeMemory(userSid);
											} else PRINT_ERROR(L"SamRidToSid %08x", status);
										} else PRINT_ERROR(L"SamOpenUser %08x", status);
									}
									SamFreeMemory(pEnumUsersBuffer);
								} else PRINT_ERROR(L"SamEnumerateUsersInDomain %08x", enumUserStatus);
							} while(enumUserStatus == STATUS_MORE_ENTRIES);
							SamCloseHandle(hDomainHandle);
						} else PRINT_ERROR(L"SamOpenDomain %08x", status);
						SamFreeMemory(domainSid);
					} else PRINT_ERROR(L"SamLookupDomainInSamServer %08x", status);
				}
				SamFreeMemory(pEnumDomainBuffer);
			} else PRINT_ERROR(L"SamEnumerateDomainsInSamServer %08x\n", enumDomainStatus);
			kprintf(L"\n");
		} while(enumDomainStatus == STATUS_MORE_ENTRIES);

		if(hBuiltinHandle)
			SamCloseHandle(hBuiltinHandle);

		SamCloseHandle(hServerHandle);
	} else PRINT_ERROR(L"SamConnect %08x\n", status);
	
	return ERROR_SUCCESS;
}
Exemple #5
0
NET_API_STATUS
WINAPI
NetQueryDisplayInformation(
    _In_ LPCWSTR ServerName,
    _In_ DWORD Level,
    _In_ DWORD Index,
    _In_ DWORD EntriesRequested,
    _In_ DWORD PreferredMaximumLength,
    _Out_ LPDWORD ReturnedEntryCount,
    _Out_ PVOID *SortedBuffer)
{
    UNICODE_STRING ServerNameString;
    SAM_HANDLE ServerHandle = NULL;
    SAM_HANDLE DomainHandle = NULL;
    DOMAIN_DISPLAY_INFORMATION DisplayInformation;
    DWORD LocalTotalBytesAvailable;
    DWORD LocalTotalBytesReturned;
    DWORD LocalReturnedEntryCount;
    PVOID LocalSortedBuffer;
    NET_API_STATUS ApiStatus = NERR_Success;
    NTSTATUS Status;

    TRACE("NetQueryDisplayInformation(%s, %ld, %ld, %ld, %ld, %p, %p)\n",
          debugstr_w(ServerName), Level, Index, EntriesRequested,
          PreferredMaximumLength, ReturnedEntryCount, SortedBuffer);

    *ReturnedEntryCount = 0;
    *SortedBuffer = NULL;

    switch (Level)
    {
        case 1:
            DisplayInformation = DomainDisplayUser;
            break;

        case 2:
            DisplayInformation = DomainDisplayMachine;
            break;

        case 3:
            DisplayInformation = DomainDisplayGroup;
            break;

        default:
            return ERROR_INVALID_LEVEL;
    }

    if (ServerName != NULL)
        RtlInitUnicodeString(&ServerNameString, ServerName);

    /* Connect to the SAM Server */
    Status = SamConnect((ServerName != NULL) ? &ServerNameString : 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;
    }

    /* Open the Account Domain */
    Status = OpenAccountDomain(ServerHandle,
                               (ServerName != NULL) ? &ServerNameString : NULL,
                               DOMAIN_LIST_ACCOUNTS,
                               &DomainHandle);
    if (!NT_SUCCESS(Status))
    {
        ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
        ApiStatus = NetpNtStatusToApiStatus(Status);
        goto done;
    }

    /* Query the information */
    Status = SamQueryDisplayInformation(DomainHandle,
                                        DisplayInformation,
                                        Index,
                                        EntriesRequested,
                                        PreferredMaximumLength,
                                        &LocalTotalBytesAvailable,
                                        &LocalTotalBytesReturned,
                                        &LocalReturnedEntryCount,
                                        &LocalSortedBuffer);
    if (!NT_SUCCESS(Status))
    {
        ERR("SamQueryDisplayInformation failed (Status %08lx)\n", Status);
        ApiStatus = NetpNtStatusToApiStatus(Status);
        goto done;
    }

    /* FIXME */

done:
    if (DomainHandle != NULL)
        SamCloseHandle(DomainHandle);

    if (ServerHandle != NULL)
        SamCloseHandle(ServerHandle);

    return ApiStatus;
}
Exemple #6
0
NET_API_STATUS
WINAPI
NetGetDisplayInformationIndex(
    _In_ LPCWSTR ServerName,
    _In_ DWORD Level,
    _In_ LPCWSTR Prefix,
    _Out_ LPDWORD Index)
{
    UNICODE_STRING ServerNameString, PrefixString;
    SAM_HANDLE ServerHandle = NULL;
    SAM_HANDLE DomainHandle = NULL;
    DOMAIN_DISPLAY_INFORMATION DisplayInformation;
    NET_API_STATUS ApiStatus = NERR_Success;
    NTSTATUS Status;

    TRACE("NetGetDisplayInformationIndex(%s %ld %s %p)\n",
          debugstr_w(ServerName), Level, debugstr_w(Prefix), Index);

    switch (Level)
    {
        case 1:
            DisplayInformation = DomainDisplayUser;
            break;

        case 2:
            DisplayInformation = DomainDisplayMachine;
            break;

        case 3:
            DisplayInformation = DomainDisplayGroup;
            break;

        default:
            return ERROR_INVALID_LEVEL;
    }

    if (ServerName != NULL)
        RtlInitUnicodeString(&ServerNameString, ServerName);

    /* Connect to the SAM Server */
    Status = SamConnect((ServerName != NULL) ? &ServerNameString : 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;
    }

    /* Open the Account Domain */
    Status = OpenAccountDomain(ServerHandle,
                               (ServerName != NULL) ? &ServerNameString : NULL,
                               DOMAIN_LIST_ACCOUNTS,
                               &DomainHandle);
    if (!NT_SUCCESS(Status))
    {
        ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
        ApiStatus = NetpNtStatusToApiStatus(Status);
        goto done;
    }

    RtlInitUnicodeString(&PrefixString, Prefix);

    /* Get the index */
    Status = SamGetDisplayEnumerationIndex(DomainHandle,
                                           DisplayInformation,
                                           &PrefixString,
                                           Index);
    if (!NT_SUCCESS(Status))
    {
        ERR("SamGetDisplayEnumerationIndex failed (Status %08lx)\n", Status);
        ApiStatus = NetpNtStatusToApiStatus(Status);
    }

done:
    if (DomainHandle != NULL)
        SamCloseHandle(DomainHandle);

    if (ServerHandle != NULL)
        SamCloseHandle(ServerHandle);

    return ApiStatus;
}