Author: ekohl Date: Mon Dec 31 18:39:19 2012 New Revision: 58071
URL: http://svn.reactos.org/svn/reactos?rev=58071&view=rev Log: [NETAPI32] Implement parts of NetUserAdd.
Modified: trunk/reactos/dll/win32/netapi32/user.c
Modified: trunk/reactos/dll/win32/netapi32/user.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/netapi32/user.c?r... ============================================================================== --- trunk/reactos/dll/win32/netapi32/user.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/netapi32/user.c [iso-8859-1] Mon Dec 31 18:39:19 2012 @@ -31,7 +31,7 @@
SAM_ENUMERATE_HANDLE EnumerationContext; PSAM_RID_ENUMERATION Buffer; - ULONG Returned; + ULONG Count; ULONG Index; BOOLEAN BuiltinDone;
@@ -246,7 +246,7 @@ 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 @@ 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;
@@ -396,6 +396,131 @@ SamFreeMemory(UserInfo->LogonHours.LogonHours);
SamFreeMemory(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; }
@@ -409,72 +534,89 @@ LPBYTE bufptr, LPDWORD parm_err) { - NET_API_STATUS status; - struct sam_user * su = NULL; - - FIXME("(%s, %d, %p, %p) stub!\n", debugstr_w(servername), level, bufptr, parm_err); - - if((status = NETAPI_ValidateServername(servername)) != NERR_Success) - return status; - - switch(level) - { - /* 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; - } - - HeapFree(GetProcessHeap(), 0, su); - - return status; + 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)\n", debugstr_w(servername), level, bufptr, parm_err); + + /* Check the info level */ + if (level < 1 || level > 4) + return ERROR_INVALID_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)) + { + ERR("SamConnect failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + /* 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; + } + + /* 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 @@
EnumContext->EnumerationContext = 0; EnumContext->Buffer = NULL; - EnumContext->Returned = 0; + EnumContext->Count = 0; EnumContext->Index = 0; EnumContext->BuiltinDone = FALSE;
@@ -639,9 +781,9 @@ // while (TRUE) // { TRACE("EnumContext->Index: %lu\n", EnumContext->Index); - TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned); - - if (EnumContext->Index >= EnumContext->Returned) + TRACE("EnumContext->Count: %lu\n", EnumContext->Count); + + if (EnumContext->Index >= EnumContext->Count) { // if (EnumContext->BuiltinDone == TRUE) // { @@ -655,7 +797,7 @@ 0, (PVOID *)&EnumContext->Buffer, prefmaxlen, - &EnumContext->Returned); + &EnumContext->Count);
TRACE("SamEnumerateUsersInDomain returned (Status %08lx)\n", Status); if (!NT_SUCCESS(Status)) @@ -677,7 +819,7 @@ }
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 @@ // }
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 @@
if (EnumContext->Buffer != NULL) { - for (i = 0; i < EnumContext->Returned; i++) + for (i = 0; i < EnumContext->Count; i++) { SamFreeMemory(EnumContext->Buffer[i].Name.Buffer); }