From f039f501b4043dae2cb26e9755126580a84ffa4b Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Mon, 31 Dec 2012 18:39:19 +0000 Subject: [PATCH] [NETAPI32] Implement parts of NetUserAdd. svn path=/trunk/; revision=58071 --- reactos/dll/win32/netapi32/user.c | 282 ++++++++++++++++++++++-------- 1 file changed, 212 insertions(+), 70 deletions(-) diff --git a/reactos/dll/win32/netapi32/user.c b/reactos/dll/win32/netapi32/user.c index 3022cc349d3..0def051ce74 100644 --- a/reactos/dll/win32/netapi32/user.c +++ b/reactos/dll/win32/netapi32/user.c @@ -31,7 +31,7 @@ typedef struct _ENUM_CONTEXT SAM_ENUMERATE_HANDLE EnumerationContext; PSAM_RID_ENUMERATION Buffer; - ULONG Returned; + ULONG Count; ULONG Index; BOOLEAN BuiltinDone; @@ -246,7 +246,7 @@ BuildUserInfoBuffer(PUSER_ACCOUNT_INFORMATION UserInfo, Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR)); } - UserInfo1->usri1_flags = UserInfo->UserAccountControl; +// UserInfo1->usri1_flags = UserInfo->UserAccountControl; if (UserInfo->ScriptPath.Length > 0) { @@ -342,7 +342,7 @@ BuildUserInfoBuffer(PUSER_ACCOUNT_INFORMATION UserInfo, Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR)); } - UserInfo20->usri20_flags = UserInfo->UserAccountControl; +// UserInfo20->usri20_flags = UserInfo->UserAccountControl; UserInfo20->usri20_user_id = RelativeId; break; @@ -399,6 +399,131 @@ FreeUserInfo(PUSER_ACCOUNT_INFORMATION UserInfo) } +static +NET_API_STATUS +SetUserInfo(SAM_HANDLE UserHandle, + LPBYTE UserInfo, + DWORD Level) +{ + USER_ALL_INFORMATION UserAllInfo; + PUSER_INFO_1 UserInfo1; + PUSER_INFO_3 UserInfo3; + NET_API_STATUS ApiStatus = NERR_Success; + NTSTATUS Status = STATUS_SUCCESS; + + ZeroMemory(&UserAllInfo, sizeof(USER_ALL_INFORMATION)); + + switch (Level) + { + case 1: + UserInfo1 = (PUSER_INFO_1)UserInfo; +// RtlInitUnicodeString(&UserAllInfo.UserName, +// UserInfo1->usri1_name); + + RtlInitUnicodeString(&UserAllInfo.AdminComment, + UserInfo1->usri1_comment); + + RtlInitUnicodeString(&UserAllInfo.HomeDirectory, + UserInfo1->usri1_home_dir); + + RtlInitUnicodeString(&UserAllInfo.ScriptPath, + UserInfo1->usri1_script_path); + + RtlInitUnicodeString(&UserAllInfo.NtPassword, + UserInfo1->usri1_password); + UserAllInfo.NtPasswordPresent = TRUE; + +// UserInfo1->usri1_flags +// UserInfo1->usri1_priv + + UserAllInfo.WhichFields = + USER_ALL_ADMINCOMMENT | + USER_ALL_HOMEDIRECTORY | + USER_ALL_SCRIPTPATH | + USER_ALL_NTPASSWORDPRESENT +// USER_ALL_USERACCOUNTCONTROL + ; + break; + + + case 3: + UserInfo3 = (PUSER_INFO_3)UserInfo; + +// LPWSTR usri3_name; + + RtlInitUnicodeString(&UserAllInfo.NtPassword, + UserInfo3->usri3_password); + UserAllInfo.NtPasswordPresent = TRUE; + +// DWORD usri3_password_age; // ignored +// DWORD usri3_priv; + + RtlInitUnicodeString(&UserAllInfo.HomeDirectory, + UserInfo3->usri3_home_dir); + + RtlInitUnicodeString(&UserAllInfo.AdminComment, + UserInfo3->usri3_comment); + +// DWORD usri3_flags; + + RtlInitUnicodeString(&UserAllInfo.ScriptPath, + UserInfo3->usri3_script_path); + +// DWORD usri3_auth_flags; + + RtlInitUnicodeString(&UserAllInfo.FullName, + UserInfo3->usri3_full_name); + +// LPWSTR usri3_usr_comment; +// LPWSTR usri3_parms; +// LPWSTR usri3_workstations; +// DWORD usri3_last_logon; +// DWORD usri3_last_logoff; +// DWORD usri3_acct_expires; +// DWORD usri3_max_storage; +// DWORD usri3_units_per_week; +// PBYTE usri3_logon_hours; +// DWORD usri3_bad_pw_count; +// DWORD usri3_num_logons; +// LPWSTR usri3_logon_server; +// DWORD usri3_country_code; +// DWORD usri3_code_page; +// DWORD usri3_user_id; // ignored +// DWORD usri3_primary_group_id; +// LPWSTR usri3_profile; +// LPWSTR usri3_home_dir_drive; +// DWORD usri3_password_expired; + + UserAllInfo.WhichFields = + USER_ALL_NTPASSWORDPRESENT | + USER_ALL_HOMEDIRECTORY | + USER_ALL_ADMINCOMMENT | + USER_ALL_SCRIPTPATH | + USER_ALL_FULLNAME +// USER_ALL_USERACCOUNTCONTROL + ; + break; + + default: + ERR("Unsupported level %lu!\n", Level); + return ERROR_INVALID_PARAMETER; + } + + Status = SamSetInformationUser(UserHandle, + UserAllInformation, + &UserAllInfo); + if (!NT_SUCCESS(Status)) + { + ERR("SamSetInformationUser failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + +done: + return ApiStatus; +} + + /************************************************************ * NetUserAdd (NETAPI32.@) */ @@ -409,72 +534,89 @@ NetUserAdd(LPCWSTR servername, LPBYTE bufptr, LPDWORD parm_err) { - NET_API_STATUS status; - struct sam_user * su = NULL; + UNICODE_STRING ServerName; + UNICODE_STRING UserName; + SAM_HANDLE ServerHandle = NULL; + SAM_HANDLE DomainHandle = NULL; + SAM_HANDLE UserHandle = NULL; + ULONG GrantedAccess; + ULONG RelativeId; + NET_API_STATUS ApiStatus = NERR_Success; + NTSTATUS Status = STATUS_SUCCESS; - FIXME("(%s, %d, %p, %p) stub!\n", debugstr_w(servername), level, bufptr, parm_err); + FIXME("(%s, %d, %p, %p)\n", debugstr_w(servername), level, bufptr, parm_err); - if((status = NETAPI_ValidateServername(servername)) != NERR_Success) - return status; + /* Check the info level */ + if (level < 1 || level > 4) + return ERROR_INVALID_LEVEL; - switch(level) + if (servername != NULL) + RtlInitUnicodeString(&ServerName, servername); + + /* Connect to the SAM Server */ + Status = SamConnect((servername != NULL) ? &ServerName : NULL, + &ServerHandle, + SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, + NULL); + if (!NT_SUCCESS(Status)) { - /* Level 3 and 4 are identical for the purposes of NetUserAdd */ - case 4: - case 3: - FIXME("Level 3 and 4 not implemented.\n"); - /* Fall through */ - case 2: - FIXME("Level 2 not implemented.\n"); - /* Fall through */ - case 1: - { - PUSER_INFO_1 ui = (PUSER_INFO_1) bufptr; - su = HeapAlloc(GetProcessHeap(), 0, sizeof(struct sam_user)); - if(!su) - { - status = NERR_InternalError; - break; - } - - if(lstrlenW(ui->usri1_name) > LM20_UNLEN) - { - status = NERR_BadUsername; - break; - } - - /*FIXME: do other checks for a valid username */ - lstrcpyW(su->user_name, ui->usri1_name); - - if(lstrlenW(ui->usri1_password) > PWLEN) - { - /* Always return PasswordTooShort on invalid passwords. */ - status = NERR_PasswordTooShort; - break; - } - lstrcpyW(su->user_password, ui->usri1_password); - - su->sec_since_passwd_change = ui->usri1_password_age; - su->user_priv = ui->usri1_priv; - su->user_flags = ui->usri1_flags; - - /*FIXME: set the other LPWSTRs to NULL for now */ - su->home_dir = NULL; - su->user_comment = NULL; - su->user_logon_script_path = NULL; - - list_add_head(&user_list, &su->entry); - return NERR_Success; - } - default: - TRACE("Invalid level %d specified.\n", level); - status = ERROR_INVALID_LEVEL; - break; + ERR("SamConnect failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; } - HeapFree(GetProcessHeap(), 0, su); + /* Open the Account Domain */ + Status = OpenAccountDomain(ServerHandle, + (servername != NULL) ? &ServerName : NULL, + DOMAIN_CREATE_USER | DOMAIN_LOOKUP, + &DomainHandle); + if (!NT_SUCCESS(Status)) + { + ERR("OpenAccountDomain failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } - return status; + /* Initialize the user name string */ + RtlInitUnicodeString(&UserName, + ((PUSER_INFO_1)bufptr)->usri1_name); + + /* Create the user account */ + Status = SamCreateUser2InDomain(DomainHandle, + &UserName, + USER_NORMAL_ACCOUNT, + USER_ALL_ACCESS | DELETE | WRITE_DAC, + &UserHandle, + &GrantedAccess, + &RelativeId); + if (!NT_SUCCESS(Status)) + { + ERR("SamCreateUser2InDomain failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + /* Set user information */ + ApiStatus = SetUserInfo(UserHandle, + bufptr, + level); + if (ApiStatus != NERR_Success) + { + ERR("SetUserInfo failed (Status %lu)\n", ApiStatus); + goto done; + } + +done: + if (UserHandle != NULL) + SamCloseHandle(UserHandle); + + if (DomainHandle != NULL) + SamCloseHandle(DomainHandle); + + if (ServerHandle != NULL) + SamCloseHandle(ServerHandle); + + return ApiStatus; } @@ -599,7 +741,7 @@ NetUserEnum(LPCWSTR servername, EnumContext->EnumerationContext = 0; EnumContext->Buffer = NULL; - EnumContext->Returned = 0; + EnumContext->Count = 0; EnumContext->Index = 0; EnumContext->BuiltinDone = FALSE; @@ -639,9 +781,9 @@ NetUserEnum(LPCWSTR servername, // while (TRUE) // { TRACE("EnumContext->Index: %lu\n", EnumContext->Index); - TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned); + TRACE("EnumContext->Count: %lu\n", EnumContext->Count); - if (EnumContext->Index >= EnumContext->Returned) + if (EnumContext->Index >= EnumContext->Count) { // if (EnumContext->BuiltinDone == TRUE) // { @@ -655,7 +797,7 @@ NetUserEnum(LPCWSTR servername, 0, (PVOID *)&EnumContext->Buffer, prefmaxlen, - &EnumContext->Returned); + &EnumContext->Count); TRACE("SamEnumerateUsersInDomain returned (Status %08lx)\n", Status); if (!NT_SUCCESS(Status)) @@ -677,7 +819,7 @@ NetUserEnum(LPCWSTR servername, } TRACE("EnumContext: %lu\n", EnumContext); - TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned); + TRACE("EnumContext->Count: %lu\n", EnumContext->Count); TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer); /* Get a pointer to the current user */ @@ -731,11 +873,11 @@ NetUserEnum(LPCWSTR servername, // } done: - if (ApiStatus == NERR_Success && EnumContext->Index < EnumContext->Returned) + if (ApiStatus == NERR_Success && EnumContext->Index < EnumContext->Count) ApiStatus = ERROR_MORE_DATA; if (EnumContext != NULL) - *totalentries = EnumContext->Returned; + *totalentries = EnumContext->Count; if (resume_handle == NULL || ApiStatus != ERROR_MORE_DATA) { @@ -752,7 +894,7 @@ done: if (EnumContext->Buffer != NULL) { - for (i = 0; i < EnumContext->Returned; i++) + for (i = 0; i < EnumContext->Count; i++) { SamFreeMemory(EnumContext->Buffer[i].Name.Buffer); }