[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;
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);
}