[NETAPI32]

Implement parts of NetUserAdd.

svn path=/trunk/; revision=58071
This commit is contained in:
Eric Kohl 2012-12-31 18:39:19 +00:00
parent e2273f3e3e
commit f039f501b4

View file

@ -31,7 +31,7 @@ typedef struct _ENUM_CONTEXT
SAM_ENUMERATE_HANDLE EnumerationContext; SAM_ENUMERATE_HANDLE EnumerationContext;
PSAM_RID_ENUMERATION Buffer; PSAM_RID_ENUMERATION Buffer;
ULONG Returned; ULONG Count;
ULONG Index; ULONG Index;
BOOLEAN BuiltinDone; BOOLEAN BuiltinDone;
@ -246,7 +246,7 @@ BuildUserInfoBuffer(PUSER_ACCOUNT_INFORMATION UserInfo,
Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR)); 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) if (UserInfo->ScriptPath.Length > 0)
{ {
@ -342,7 +342,7 @@ BuildUserInfoBuffer(PUSER_ACCOUNT_INFORMATION UserInfo,
Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR)); 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; UserInfo20->usri20_user_id = RelativeId;
break; 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.@) * NetUserAdd (NETAPI32.@)
*/ */
@ -409,72 +534,89 @@ NetUserAdd(LPCWSTR servername,
LPBYTE bufptr, LPBYTE bufptr,
LPDWORD parm_err) LPDWORD parm_err)
{ {
NET_API_STATUS status; UNICODE_STRING ServerName;
struct sam_user * su = NULL; 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) /* Check the info level */
return status; 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 */ ERR("SamConnect failed (Status %08lx)\n", Status);
case 4: ApiStatus = NetpNtStatusToApiStatus(Status);
case 3: goto done;
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); /* 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->EnumerationContext = 0;
EnumContext->Buffer = NULL; EnumContext->Buffer = NULL;
EnumContext->Returned = 0; EnumContext->Count = 0;
EnumContext->Index = 0; EnumContext->Index = 0;
EnumContext->BuiltinDone = FALSE; EnumContext->BuiltinDone = FALSE;
@ -639,9 +781,9 @@ NetUserEnum(LPCWSTR servername,
// while (TRUE) // while (TRUE)
// { // {
TRACE("EnumContext->Index: %lu\n", EnumContext->Index); 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) // if (EnumContext->BuiltinDone == TRUE)
// { // {
@ -655,7 +797,7 @@ NetUserEnum(LPCWSTR servername,
0, 0,
(PVOID *)&EnumContext->Buffer, (PVOID *)&EnumContext->Buffer,
prefmaxlen, prefmaxlen,
&EnumContext->Returned); &EnumContext->Count);
TRACE("SamEnumerateUsersInDomain returned (Status %08lx)\n", Status); TRACE("SamEnumerateUsersInDomain returned (Status %08lx)\n", Status);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -677,7 +819,7 @@ NetUserEnum(LPCWSTR servername,
} }
TRACE("EnumContext: %lu\n", EnumContext); 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); TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
/* Get a pointer to the current user */ /* Get a pointer to the current user */
@ -731,11 +873,11 @@ NetUserEnum(LPCWSTR servername,
// } // }
done: done:
if (ApiStatus == NERR_Success && EnumContext->Index < EnumContext->Returned) if (ApiStatus == NERR_Success && EnumContext->Index < EnumContext->Count)
ApiStatus = ERROR_MORE_DATA; ApiStatus = ERROR_MORE_DATA;
if (EnumContext != NULL) if (EnumContext != NULL)
*totalentries = EnumContext->Returned; *totalentries = EnumContext->Count;
if (resume_handle == NULL || ApiStatus != ERROR_MORE_DATA) if (resume_handle == NULL || ApiStatus != ERROR_MORE_DATA)
{ {
@ -752,7 +894,7 @@ done:
if (EnumContext->Buffer != NULL) if (EnumContext->Buffer != NULL)
{ {
for (i = 0; i < EnumContext->Returned; i++) for (i = 0; i < EnumContext->Count; i++)
{ {
SamFreeMemory(EnumContext->Buffer[i].Name.Buffer); SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
} }