[NETAPI32]
authorEric Kohl <eric.kohl@reactos.org>
Mon, 31 Dec 2012 18:39:19 +0000 (18:39 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Mon, 31 Dec 2012 18:39:19 +0000 (18:39 +0000)
Implement parts of NetUserAdd.

svn path=/trunk/; revision=58071

reactos/dll/win32/netapi32/user.c

index 3022cc3..0def051 100644 (file)
@@ -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)
-    {
-    /* 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:
+    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))
     {
-        PUSER_INFO_1 ui = (PUSER_INFO_1) bufptr;
-        su = HeapAlloc(GetProcessHeap(), 0, sizeof(struct sam_user));
-        if(!su)
-        {
-            status = NERR_InternalError;
-            break;
-        }
+        ERR("SamConnect failed (Status %08lx)\n", Status);
+        ApiStatus = NetpNtStatusToApiStatus(Status);
+        goto done;
+    }
 
-        if(lstrlenW(ui->usri1_name) > LM20_UNLEN)
-        {
-            status = NERR_BadUsername;
-            break;
-        }
+    /* 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;
+    }
 
-        /*FIXME: do other checks for a valid username */
-        lstrcpyW(su->user_name, ui->usri1_name);
+    /* Initialize the user name string */
+    RtlInitUnicodeString(&UserName,
+                         ((PUSER_INFO_1)bufptr)->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);
+    /* 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;
+    }
 
-        su->sec_since_passwd_change = ui->usri1_password_age;
-        su->user_priv = ui->usri1_priv;
-        su->user_flags = ui->usri1_flags;
+    /* Set user information */
+    ApiStatus = SetUserInfo(UserHandle,
+                            bufptr,
+                            level);
+    if (ApiStatus != NERR_Success)
+    {
+        ERR("SetUserInfo failed (Status %lu)\n", ApiStatus);
+        goto done;
+    }
 
-        /*FIXME: set the other LPWSTRs to NULL for now */
-        su->home_dir = NULL;
-        su->user_comment = NULL;
-        su->user_logon_script_path = NULL;
+done:
+    if (UserHandle != NULL)
+        SamCloseHandle(UserHandle);
 
-        list_add_head(&user_list, &su->entry);
-        return NERR_Success;
-    }
-    default:
-        TRACE("Invalid level %d specified.\n", level);
-        status = ERROR_INVALID_LEVEL;
-        break;
-    }
+    if (DomainHandle != NULL)
+        SamCloseHandle(DomainHandle);
 
-    HeapFree(GetProcessHeap(), 0, su);
+    if (ServerHandle != NULL)
+        SamCloseHandle(ServerHandle);
 
-    return status;
+    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);
                 }