2 * Copyright 2002 Andriy Palamarchuk
4 * netapi32 user functions
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * Implement NetUserChangePassword
24 * Implement NetUserDel
25 * Implement NetUserGetGroups
26 * Implement NetUserSetGroups
27 * Implement NetUserSetInfo
28 * NetUserGetLocalGroups does not support LG_INCLUDE_INDIRECT yet.
29 * Add missing information levels.
35 WINE_DEFAULT_DEBUG_CHANNEL(netapi32
);
38 typedef struct _ENUM_CONTEXT
40 SAM_HANDLE ServerHandle
;
41 SAM_HANDLE BuiltinDomainHandle
;
42 SAM_HANDLE AccountDomainHandle
;
44 SAM_ENUMERATE_HANDLE EnumerationContext
;
45 PSAM_RID_ENUMERATION Buffer
;
50 } ENUM_CONTEXT
, *PENUM_CONTEXT
;
53 /* NOTE: So far, this is implemented to support tests that require user logins,
54 * but not designed to handle real user databases. Those should probably
55 * be synced with either the host's user database or with Samba.
57 * FIXME: The user database should hold all the information the USER_INFO_4 struct
58 * needs, but for the first try, I will just implement the USER_INFO_1 fields.
64 WCHAR user_name
[LM20_UNLEN
+1];
65 WCHAR user_password
[PWLEN
+ 1];
66 DWORD sec_since_passwd_change
;
71 LPWSTR user_logon_script_path
;
74 static struct list user_list
= LIST_INIT( user_list
);
76 BOOL
NETAPI_IsLocalComputer(LPCWSTR ServerName
);
78 /************************************************************
79 * NETAPI_ValidateServername
81 * Validates server name
83 static NET_API_STATUS
NETAPI_ValidateServername(LPCWSTR ServerName
)
87 if (ServerName
[0] == 0)
88 return ERROR_BAD_NETPATH
;
90 ((ServerName
[0] == '\\') &&
91 (ServerName
[1] != '\\'))
93 ((ServerName
[0] == '\\') &&
94 (ServerName
[1] == '\\') &&
97 return ERROR_INVALID_NAME
;
102 /************************************************************
105 * Looks for a user in the user database.
106 * Returns a pointer to the entry in the user list when the user
107 * is found, NULL otherwise.
109 static struct sam_user
* NETAPI_FindUser(LPCWSTR UserName
)
111 struct sam_user
*user
;
113 LIST_FOR_EACH_ENTRY(user
, &user_list
, struct sam_user
, entry
)
115 if(lstrcmpW(user
->user_name
, UserName
) == 0)
123 CreateSidFromSidAndRid(PSID SrcSid
,
132 RidCount
= *RtlSubAuthorityCountSid(SrcSid
);
136 DstSidSize
= RtlLengthRequiredSid(RidCount
+ 1);
138 DstSid
= RtlAllocateHeap(RtlGetProcessHeap(),
144 RtlInitializeSid(DstSid
,
145 RtlIdentifierAuthoritySid(SrcSid
),
148 for (i
= 0; i
< (ULONG
)RidCount
; i
++)
150 p
= RtlSubAuthoritySid(SrcSid
, i
);
151 q
= RtlSubAuthoritySid(DstSid
, i
);
155 q
= RtlSubAuthoritySid(DstSid
, (ULONG
)RidCount
);
164 GetAccountFlags(ULONG AccountControl
)
166 ULONG Flags
= UF_SCRIPT
;
168 if (AccountControl
& USER_ACCOUNT_DISABLED
)
169 Flags
|= UF_ACCOUNTDISABLE
;
171 if (AccountControl
& USER_HOME_DIRECTORY_REQUIRED
)
172 Flags
|= UF_HOMEDIR_REQUIRED
;
174 if (AccountControl
& USER_PASSWORD_NOT_REQUIRED
)
175 Flags
|= UF_PASSWD_NOTREQD
;
177 // UF_PASSWD_CANT_CHANGE
179 if (AccountControl
& USER_ACCOUNT_AUTO_LOCKED
)
182 if (AccountControl
& USER_DONT_EXPIRE_PASSWORD
)
183 Flags
|= UF_DONT_EXPIRE_PASSWD
;
186 if (AccountControl & USER_ENCRYPTED_TEXT_PASSWORD_ALLOWED)
187 Flags |= UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED;
189 if (AccountControl & USER_SMARTCARD_REQUIRED)
190 Flags |= UF_SMARTCARD_REQUIRED;
192 if (AccountControl & USER_TRUSTED_FOR_DELEGATION)
193 Flags |= UF_TRUSTED_FOR_DELEGATION;
195 if (AccountControl & USER_NOT_DELEGATED)
196 Flags |= UF_NOT_DELEGATED;
198 if (AccountControl & USER_USE_DES_KEY_ONLY)
199 Flags |= UF_USE_DES_KEY_ONLY;
201 if (AccountControl & USER_DONT_REQUIRE_PREAUTH)
202 Flags |= UF_DONT_REQUIRE_PREAUTH;
204 if (AccountControl & USER_PASSWORD_EXPIRED)
205 Flags |= UF_PASSWORD_EXPIRED;
208 /* Set account type flags */
209 if (AccountControl
& USER_TEMP_DUPLICATE_ACCOUNT
)
210 Flags
|= UF_TEMP_DUPLICATE_ACCOUNT
;
211 else if (AccountControl
& USER_NORMAL_ACCOUNT
)
212 Flags
|= UF_NORMAL_ACCOUNT
;
213 else if (AccountControl
& USER_INTERDOMAIN_TRUST_ACCOUNT
)
214 Flags
|= UF_INTERDOMAIN_TRUST_ACCOUNT
;
215 else if (AccountControl
& USER_WORKSTATION_TRUST_ACCOUNT
)
216 Flags
|= UF_WORKSTATION_TRUST_ACCOUNT
;
217 else if (AccountControl
& USER_SERVER_TRUST_ACCOUNT
)
218 Flags
|= UF_SERVER_TRUST_ACCOUNT
;
226 BuildUserInfoBuffer(PUSER_ACCOUNT_INFORMATION UserInfo
,
231 LPVOID LocalBuffer
= NULL
;
232 PUSER_INFO_0 UserInfo0
;
233 PUSER_INFO_1 UserInfo1
;
234 PUSER_INFO_2 UserInfo2
;
235 PUSER_INFO_3 UserInfo3
;
236 PUSER_INFO_10 UserInfo10
;
237 PUSER_INFO_20 UserInfo20
;
238 PUSER_INFO_23 UserInfo23
;
241 NET_API_STATUS ApiStatus
= NERR_Success
;
248 Size
= sizeof(USER_INFO_0
) +
249 UserInfo
->UserName
.Length
+ sizeof(WCHAR
);
253 Size
= sizeof(USER_INFO_1
) +
254 UserInfo
->UserName
.Length
+ sizeof(WCHAR
);
256 if (UserInfo
->HomeDirectory
.Length
> 0)
257 Size
+= UserInfo
->HomeDirectory
.Length
+ sizeof(WCHAR
);
259 if (UserInfo
->AdminComment
.Length
> 0)
260 Size
+= UserInfo
->AdminComment
.Length
+ sizeof(WCHAR
);
262 if (UserInfo
->ScriptPath
.Length
> 0)
263 Size
+= UserInfo
->ScriptPath
.Length
+ sizeof(WCHAR
);
267 Size
= sizeof(USER_INFO_2
) +
268 UserInfo
->UserName
.Length
+ sizeof(WCHAR
);
270 if (UserInfo
->HomeDirectory
.Length
> 0)
271 Size
+= UserInfo
->HomeDirectory
.Length
+ sizeof(WCHAR
);
273 if (UserInfo
->AdminComment
.Length
> 0)
274 Size
+= UserInfo
->AdminComment
.Length
+ sizeof(WCHAR
);
276 if (UserInfo
->ScriptPath
.Length
> 0)
277 Size
+= UserInfo
->ScriptPath
.Length
+ sizeof(WCHAR
);
279 if (UserInfo
->FullName
.Length
> 0)
280 Size
+= UserInfo
->FullName
.Length
+ sizeof(WCHAR
);
282 /* FIXME: usri2_usr_comment */
283 /* FIXME: usri2_parms */
285 if (UserInfo
->WorkStations
.Length
> 0)
286 Size
+= UserInfo
->WorkStations
.Length
+ sizeof(WCHAR
);
288 /* FIXME: usri2_logon_hours */
289 /* FIXME: usri2_logon_server */
293 Size
= sizeof(USER_INFO_3
) +
294 UserInfo
->UserName
.Length
+ sizeof(WCHAR
);
296 if (UserInfo
->HomeDirectory
.Length
> 0)
297 Size
+= UserInfo
->HomeDirectory
.Length
+ sizeof(WCHAR
);
299 if (UserInfo
->AdminComment
.Length
> 0)
300 Size
+= UserInfo
->AdminComment
.Length
+ sizeof(WCHAR
);
302 if (UserInfo
->ScriptPath
.Length
> 0)
303 Size
+= UserInfo
->ScriptPath
.Length
+ sizeof(WCHAR
);
305 if (UserInfo
->FullName
.Length
> 0)
306 Size
+= UserInfo
->FullName
.Length
+ sizeof(WCHAR
);
308 /* FIXME: usri3_usr_comment */
309 /* FIXME: usri3_parms */
311 if (UserInfo
->WorkStations
.Length
> 0)
312 Size
+= UserInfo
->WorkStations
.Length
+ sizeof(WCHAR
);
314 /* FIXME: usri3_logon_hours */
315 /* FIXME: usri3_logon_server */
317 if (UserInfo
->ProfilePath
.Length
> 0)
318 Size
+= UserInfo
->ProfilePath
.Length
+ sizeof(WCHAR
);
320 if (UserInfo
->HomeDirectoryDrive
.Length
> 0)
321 Size
+= UserInfo
->HomeDirectoryDrive
.Length
+ sizeof(WCHAR
);
327 Size
= sizeof(USER_INFO_10
) +
328 UserInfo
->UserName
.Length
+ sizeof(WCHAR
);
330 if (UserInfo
->AdminComment
.Length
> 0)
331 Size
+= UserInfo
->AdminComment
.Length
+ sizeof(WCHAR
);
333 /* FIXME: usri10_usr_comment */
335 if (UserInfo
->FullName
.Length
> 0)
336 Size
+= UserInfo
->FullName
.Length
+ sizeof(WCHAR
);
342 Size
= sizeof(USER_INFO_20
) +
343 UserInfo
->UserName
.Length
+ sizeof(WCHAR
);
345 if (UserInfo
->FullName
.Length
> 0)
346 Size
+= UserInfo
->FullName
.Length
+ sizeof(WCHAR
);
348 if (UserInfo
->AdminComment
.Length
> 0)
349 Size
+= UserInfo
->AdminComment
.Length
+ sizeof(WCHAR
);
353 Size
= sizeof(USER_INFO_23
) +
354 UserInfo
->UserName
.Length
+ sizeof(WCHAR
);
356 if (UserInfo
->FullName
.Length
> 0)
357 Size
+= UserInfo
->FullName
.Length
+ sizeof(WCHAR
);
359 if (UserInfo
->AdminComment
.Length
> 0)
360 Size
+= UserInfo
->AdminComment
.Length
+ sizeof(WCHAR
);
362 /* FIXME: usri23_user_sid */
366 ApiStatus
= ERROR_INVALID_LEVEL
;
370 ApiStatus
= NetApiBufferAllocate(Size
, &LocalBuffer
);
371 if (ApiStatus
!= NERR_Success
)
374 ZeroMemory(LocalBuffer
, Size
);
379 UserInfo0
= (PUSER_INFO_0
)LocalBuffer
;
381 Ptr
= (LPWSTR
)((ULONG_PTR
)UserInfo0
+ sizeof(USER_INFO_0
));
382 UserInfo0
->usri0_name
= Ptr
;
384 memcpy(UserInfo0
->usri0_name
,
385 UserInfo
->UserName
.Buffer
,
386 UserInfo
->UserName
.Length
);
387 UserInfo0
->usri0_name
[UserInfo
->UserName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
391 UserInfo1
= (PUSER_INFO_1
)LocalBuffer
;
393 Ptr
= (LPWSTR
)((ULONG_PTR
)UserInfo1
+ sizeof(USER_INFO_1
));
395 UserInfo1
->usri1_name
= Ptr
;
397 memcpy(UserInfo1
->usri1_name
,
398 UserInfo
->UserName
.Buffer
,
399 UserInfo
->UserName
.Length
);
400 UserInfo1
->usri1_name
[UserInfo
->UserName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
402 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->UserName
.Length
+ sizeof(WCHAR
));
404 UserInfo1
->usri1_password
= NULL
;
406 /* FIXME: UserInfo1->usri1_password_age */
407 /* FIXME: UserInfo1->usri1_priv */
409 if (UserInfo
->HomeDirectory
.Length
> 0)
411 UserInfo1
->usri1_home_dir
= Ptr
;
413 memcpy(UserInfo1
->usri1_home_dir
,
414 UserInfo
->HomeDirectory
.Buffer
,
415 UserInfo
->HomeDirectory
.Length
);
416 UserInfo1
->usri1_home_dir
[UserInfo
->HomeDirectory
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
418 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->HomeDirectory
.Length
+ sizeof(WCHAR
));
421 if (UserInfo
->AdminComment
.Length
> 0)
423 UserInfo1
->usri1_comment
= Ptr
;
425 memcpy(UserInfo1
->usri1_comment
,
426 UserInfo
->AdminComment
.Buffer
,
427 UserInfo
->AdminComment
.Length
);
428 UserInfo1
->usri1_comment
[UserInfo
->AdminComment
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
430 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->AdminComment
.Length
+ sizeof(WCHAR
));
433 UserInfo1
->usri1_flags
= GetAccountFlags(UserInfo
->UserAccountControl
);
435 if (UserInfo
->ScriptPath
.Length
> 0)
437 UserInfo1
->usri1_script_path
= Ptr
;
439 memcpy(UserInfo1
->usri1_script_path
,
440 UserInfo
->ScriptPath
.Buffer
,
441 UserInfo
->ScriptPath
.Length
);
442 UserInfo1
->usri1_script_path
[UserInfo
->ScriptPath
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
447 UserInfo2
= (PUSER_INFO_2
)LocalBuffer
;
449 Ptr
= (LPWSTR
)((ULONG_PTR
)UserInfo2
+ sizeof(USER_INFO_2
));
451 UserInfo2
->usri2_name
= Ptr
;
453 memcpy(UserInfo2
->usri2_name
,
454 UserInfo
->UserName
.Buffer
,
455 UserInfo
->UserName
.Length
);
456 UserInfo2
->usri2_name
[UserInfo
->UserName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
458 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->UserName
.Length
+ sizeof(WCHAR
));
460 /* FIXME: usri2_password_age */
461 /* FIXME: usri2_priv */
463 if (UserInfo
->HomeDirectory
.Length
> 0)
465 UserInfo2
->usri2_home_dir
= Ptr
;
467 memcpy(UserInfo2
->usri2_home_dir
,
468 UserInfo
->HomeDirectory
.Buffer
,
469 UserInfo
->HomeDirectory
.Length
);
470 UserInfo2
->usri2_home_dir
[UserInfo
->HomeDirectory
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
472 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->HomeDirectory
.Length
+ sizeof(WCHAR
));
475 if (UserInfo
->AdminComment
.Length
> 0)
477 UserInfo2
->usri2_comment
= Ptr
;
479 memcpy(UserInfo2
->usri2_comment
,
480 UserInfo
->AdminComment
.Buffer
,
481 UserInfo
->AdminComment
.Length
);
482 UserInfo2
->usri2_comment
[UserInfo
->AdminComment
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
484 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->AdminComment
.Length
+ sizeof(WCHAR
));
487 UserInfo2
->usri2_flags
= GetAccountFlags(UserInfo
->UserAccountControl
);
489 if (UserInfo
->ScriptPath
.Length
> 0)
491 UserInfo2
->usri2_script_path
= Ptr
;
493 memcpy(UserInfo2
->usri2_script_path
,
494 UserInfo
->ScriptPath
.Buffer
,
495 UserInfo
->ScriptPath
.Length
);
496 UserInfo2
->usri2_script_path
[UserInfo
->ScriptPath
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
498 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->ScriptPath
.Length
+ sizeof(WCHAR
));
501 /* FIXME: usri2_auth_flags */
503 if (UserInfo
->FullName
.Length
> 0)
505 UserInfo2
->usri2_full_name
= Ptr
;
507 memcpy(UserInfo2
->usri2_full_name
,
508 UserInfo
->FullName
.Buffer
,
509 UserInfo
->FullName
.Length
);
510 UserInfo2
->usri2_full_name
[UserInfo
->FullName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
512 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->FullName
.Length
+ sizeof(WCHAR
));
515 /* FIXME: usri2_usr_comment */
516 /* FIXME: usri2_parms */
518 if (UserInfo
->WorkStations
.Length
> 0)
520 UserInfo2
->usri2_workstations
= Ptr
;
522 memcpy(UserInfo2
->usri2_workstations
,
523 UserInfo
->WorkStations
.Buffer
,
524 UserInfo
->WorkStations
.Length
);
525 UserInfo2
->usri2_workstations
[UserInfo
->WorkStations
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
527 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->WorkStations
.Length
+ sizeof(WCHAR
));
530 RtlTimeToSecondsSince1970(&UserInfo
->LastLogon
,
531 &UserInfo2
->usri2_last_logon
);
533 RtlTimeToSecondsSince1970(&UserInfo
->LastLogoff
,
534 &UserInfo2
->usri2_last_logoff
);
536 RtlTimeToSecondsSince1970(&UserInfo
->AccountExpires
,
537 &UserInfo2
->usri2_acct_expires
);
539 UserInfo2
->usri2_max_storage
= USER_MAXSTORAGE_UNLIMITED
;
541 /* FIXME: usri2_units_per_week */
542 /* FIXME: usri2_logon_hours */
544 UserInfo2
->usri2_bad_pw_count
= UserInfo
->BadPasswordCount
;
545 UserInfo2
->usri2_num_logons
= UserInfo
->LogonCount
;
547 /* FIXME: usri2_logon_server */
548 /* FIXME: usri2_country_code */
549 /* FIXME: usri2_code_page */
554 UserInfo3
= (PUSER_INFO_3
)LocalBuffer
;
556 Ptr
= (LPWSTR
)((ULONG_PTR
)UserInfo3
+ sizeof(USER_INFO_3
));
558 UserInfo3
->usri3_name
= Ptr
;
560 memcpy(UserInfo3
->usri3_name
,
561 UserInfo
->UserName
.Buffer
,
562 UserInfo
->UserName
.Length
);
563 UserInfo3
->usri3_name
[UserInfo
->UserName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
565 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->UserName
.Length
+ sizeof(WCHAR
));
567 /* FIXME: usri3_password_age */
568 /* FIXME: usri3_priv */
570 if (UserInfo
->HomeDirectory
.Length
> 0)
572 UserInfo3
->usri3_home_dir
= Ptr
;
574 memcpy(UserInfo3
->usri3_home_dir
,
575 UserInfo
->HomeDirectory
.Buffer
,
576 UserInfo
->HomeDirectory
.Length
);
577 UserInfo3
->usri3_home_dir
[UserInfo
->HomeDirectory
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
579 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->HomeDirectory
.Length
+ sizeof(WCHAR
));
582 if (UserInfo
->AdminComment
.Length
> 0)
584 UserInfo3
->usri3_comment
= Ptr
;
586 memcpy(UserInfo3
->usri3_comment
,
587 UserInfo
->AdminComment
.Buffer
,
588 UserInfo
->AdminComment
.Length
);
589 UserInfo3
->usri3_comment
[UserInfo
->AdminComment
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
591 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->AdminComment
.Length
+ sizeof(WCHAR
));
594 UserInfo3
->usri3_flags
= GetAccountFlags(UserInfo
->UserAccountControl
);
596 if (UserInfo
->ScriptPath
.Length
> 0)
598 UserInfo3
->usri3_script_path
= Ptr
;
600 memcpy(UserInfo3
->usri3_script_path
,
601 UserInfo
->ScriptPath
.Buffer
,
602 UserInfo
->ScriptPath
.Length
);
603 UserInfo3
->usri3_script_path
[UserInfo
->ScriptPath
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
605 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->ScriptPath
.Length
+ sizeof(WCHAR
));
608 /* FIXME: usri3_auth_flags */
610 if (UserInfo
->FullName
.Length
> 0)
612 UserInfo3
->usri3_full_name
= Ptr
;
614 memcpy(UserInfo3
->usri3_full_name
,
615 UserInfo
->FullName
.Buffer
,
616 UserInfo
->FullName
.Length
);
617 UserInfo3
->usri3_full_name
[UserInfo
->FullName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
619 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->FullName
.Length
+ sizeof(WCHAR
));
622 /* FIXME: usri3_usr_comment */
623 /* FIXME: usri3_parms */
625 if (UserInfo
->WorkStations
.Length
> 0)
627 UserInfo3
->usri3_workstations
= Ptr
;
629 memcpy(UserInfo3
->usri3_workstations
,
630 UserInfo
->WorkStations
.Buffer
,
631 UserInfo
->WorkStations
.Length
);
632 UserInfo3
->usri3_workstations
[UserInfo
->WorkStations
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
634 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->WorkStations
.Length
+ sizeof(WCHAR
));
637 RtlTimeToSecondsSince1970(&UserInfo
->LastLogon
,
638 &UserInfo3
->usri3_last_logon
);
640 RtlTimeToSecondsSince1970(&UserInfo
->LastLogoff
,
641 &UserInfo3
->usri3_last_logoff
);
643 RtlTimeToSecondsSince1970(&UserInfo
->AccountExpires
,
644 &UserInfo3
->usri3_acct_expires
);
646 UserInfo3
->usri3_max_storage
= USER_MAXSTORAGE_UNLIMITED
;
648 /* FIXME: usri3_units_per_week */
649 /* FIXME: usri3_logon_hours */
651 UserInfo3
->usri3_bad_pw_count
= UserInfo
->BadPasswordCount
;
652 UserInfo3
->usri3_num_logons
= UserInfo
->LogonCount
;
654 /* FIXME: usri3_logon_server */
655 /* FIXME: usri3_country_code */
656 /* FIXME: usri3_code_page */
658 UserInfo3
->usri3_user_id
= RelativeId
;
659 UserInfo3
->usri3_primary_group_id
= UserInfo
->PrimaryGroupId
;
661 if (UserInfo
->ProfilePath
.Length
> 0)
663 UserInfo3
->usri3_profile
= Ptr
;
665 memcpy(UserInfo3
->usri3_profile
,
666 UserInfo
->ProfilePath
.Buffer
,
667 UserInfo
->ProfilePath
.Length
);
668 UserInfo3
->usri3_profile
[UserInfo
->ProfilePath
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
670 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->ProfilePath
.Length
+ sizeof(WCHAR
));
673 if (UserInfo
->HomeDirectoryDrive
.Length
> 0)
675 UserInfo3
->usri3_home_dir_drive
= Ptr
;
677 memcpy(UserInfo3
->usri3_home_dir_drive
,
678 UserInfo
->HomeDirectoryDrive
.Buffer
,
679 UserInfo
->HomeDirectoryDrive
.Length
);
680 UserInfo3
->usri3_home_dir_drive
[UserInfo
->HomeDirectoryDrive
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
682 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->HomeDirectoryDrive
.Length
+ sizeof(WCHAR
));
685 UserInfo3
->usri3_password_expired
= (UserInfo
->UserAccountControl
& USER_PASSWORD_EXPIRED
);
691 UserInfo10
= (PUSER_INFO_10
)LocalBuffer
;
693 Ptr
= (LPWSTR
)((ULONG_PTR
)UserInfo10
+ sizeof(USER_INFO_10
));
695 UserInfo10
->usri10_name
= Ptr
;
697 memcpy(UserInfo10
->usri10_name
,
698 UserInfo
->UserName
.Buffer
,
699 UserInfo
->UserName
.Length
);
700 UserInfo10
->usri10_name
[UserInfo
->UserName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
702 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->UserName
.Length
+ sizeof(WCHAR
));
704 if (UserInfo
->AdminComment
.Length
> 0)
706 UserInfo10
->usri10_comment
= Ptr
;
708 memcpy(UserInfo10
->usri10_comment
,
709 UserInfo
->AdminComment
.Buffer
,
710 UserInfo
->AdminComment
.Length
);
711 UserInfo10
->usri10_comment
[UserInfo
->AdminComment
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
713 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->AdminComment
.Length
+ sizeof(WCHAR
));
716 /* FIXME: usri10_usr_comment */
718 if (UserInfo
->FullName
.Length
> 0)
720 UserInfo10
->usri10_full_name
= Ptr
;
722 memcpy(UserInfo10
->usri10_full_name
,
723 UserInfo
->FullName
.Buffer
,
724 UserInfo
->FullName
.Length
);
725 UserInfo10
->usri10_full_name
[UserInfo
->FullName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
727 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->FullName
.Length
+ sizeof(WCHAR
));
734 UserInfo20
= (PUSER_INFO_20
)LocalBuffer
;
736 Ptr
= (LPWSTR
)((ULONG_PTR
)UserInfo20
+ sizeof(USER_INFO_20
));
738 UserInfo20
->usri20_name
= Ptr
;
740 memcpy(UserInfo20
->usri20_name
,
741 UserInfo
->UserName
.Buffer
,
742 UserInfo
->UserName
.Length
);
743 UserInfo20
->usri20_name
[UserInfo
->UserName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
745 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->UserName
.Length
+ sizeof(WCHAR
));
747 if (UserInfo
->FullName
.Length
> 0)
749 UserInfo20
->usri20_full_name
= Ptr
;
751 memcpy(UserInfo20
->usri20_full_name
,
752 UserInfo
->FullName
.Buffer
,
753 UserInfo
->FullName
.Length
);
754 UserInfo20
->usri20_full_name
[UserInfo
->FullName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
756 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->FullName
.Length
+ sizeof(WCHAR
));
759 if (UserInfo
->AdminComment
.Length
> 0)
761 UserInfo20
->usri20_comment
= Ptr
;
763 memcpy(UserInfo20
->usri20_comment
,
764 UserInfo
->AdminComment
.Buffer
,
765 UserInfo
->AdminComment
.Length
);
766 UserInfo20
->usri20_comment
[UserInfo
->AdminComment
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
768 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->AdminComment
.Length
+ sizeof(WCHAR
));
771 UserInfo20
->usri20_flags
= GetAccountFlags(UserInfo
->UserAccountControl
);
773 UserInfo20
->usri20_user_id
= RelativeId
;
777 UserInfo23
= (PUSER_INFO_23
)LocalBuffer
;
779 Ptr
= (LPWSTR
)((ULONG_PTR
)UserInfo23
+ sizeof(USER_INFO_23
));
781 UserInfo23
->usri23_name
= Ptr
;
783 memcpy(UserInfo23
->usri23_name
,
784 UserInfo
->UserName
.Buffer
,
785 UserInfo
->UserName
.Length
);
786 UserInfo23
->usri23_name
[UserInfo
->UserName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
788 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->UserName
.Length
+ sizeof(WCHAR
));
790 if (UserInfo
->FullName
.Length
> 0)
792 UserInfo23
->usri23_full_name
= Ptr
;
794 memcpy(UserInfo23
->usri23_full_name
,
795 UserInfo
->FullName
.Buffer
,
796 UserInfo
->FullName
.Length
);
797 UserInfo23
->usri23_full_name
[UserInfo
->FullName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
799 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->FullName
.Length
+ sizeof(WCHAR
));
802 if (UserInfo
->AdminComment
.Length
> 0)
804 UserInfo23
->usri23_comment
= Ptr
;
806 memcpy(UserInfo23
->usri23_comment
,
807 UserInfo
->AdminComment
.Buffer
,
808 UserInfo
->AdminComment
.Length
);
809 UserInfo23
->usri23_comment
[UserInfo
->AdminComment
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
811 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ UserInfo
->AdminComment
.Length
+ sizeof(WCHAR
));
814 UserInfo23
->usri23_flags
= GetAccountFlags(UserInfo
->UserAccountControl
);
816 /* FIXME: usri23_user_sid */
821 if (ApiStatus
== NERR_Success
)
823 *Buffer
= LocalBuffer
;
827 if (LocalBuffer
!= NULL
)
828 NetApiBufferFree(LocalBuffer
);
837 FreeUserInfo(PUSER_ACCOUNT_INFORMATION UserInfo
)
839 if (UserInfo
->UserName
.Buffer
!= NULL
)
840 SamFreeMemory(UserInfo
->UserName
.Buffer
);
842 if (UserInfo
->FullName
.Buffer
!= NULL
)
843 SamFreeMemory(UserInfo
->FullName
.Buffer
);
845 if (UserInfo
->HomeDirectory
.Buffer
!= NULL
)
846 SamFreeMemory(UserInfo
->HomeDirectory
.Buffer
);
848 if (UserInfo
->HomeDirectoryDrive
.Buffer
!= NULL
)
849 SamFreeMemory(UserInfo
->HomeDirectoryDrive
.Buffer
);
851 if (UserInfo
->ScriptPath
.Buffer
!= NULL
)
852 SamFreeMemory(UserInfo
->ScriptPath
.Buffer
);
854 if (UserInfo
->ProfilePath
.Buffer
!= NULL
)
855 SamFreeMemory(UserInfo
->ProfilePath
.Buffer
);
857 if (UserInfo
->AdminComment
.Buffer
!= NULL
)
858 SamFreeMemory(UserInfo
->AdminComment
.Buffer
);
860 if (UserInfo
->WorkStations
.Buffer
!= NULL
)
861 SamFreeMemory(UserInfo
->WorkStations
.Buffer
);
863 if (UserInfo
->LogonHours
.LogonHours
!= NULL
)
864 SamFreeMemory(UserInfo
->LogonHours
.LogonHours
);
866 SamFreeMemory(UserInfo
);
872 SetUserInfo(SAM_HANDLE UserHandle
,
876 USER_ALL_INFORMATION UserAllInfo
;
877 PUSER_INFO_1 UserInfo1
;
878 PUSER_INFO_3 UserInfo3
;
879 NET_API_STATUS ApiStatus
= NERR_Success
;
880 NTSTATUS Status
= STATUS_SUCCESS
;
882 ZeroMemory(&UserAllInfo
, sizeof(USER_ALL_INFORMATION
));
887 UserInfo1
= (PUSER_INFO_1
)UserInfo
;
888 // RtlInitUnicodeString(&UserAllInfo.UserName,
889 // UserInfo1->usri1_name);
891 RtlInitUnicodeString(&UserAllInfo
.AdminComment
,
892 UserInfo1
->usri1_comment
);
894 RtlInitUnicodeString(&UserAllInfo
.HomeDirectory
,
895 UserInfo1
->usri1_home_dir
);
897 RtlInitUnicodeString(&UserAllInfo
.ScriptPath
,
898 UserInfo1
->usri1_script_path
);
900 RtlInitUnicodeString(&UserAllInfo
.NtPassword
,
901 UserInfo1
->usri1_password
);
902 UserAllInfo
.NtPasswordPresent
= TRUE
;
904 // UserInfo1->usri1_flags
905 // UserInfo1->usri1_priv
907 UserAllInfo
.WhichFields
=
908 USER_ALL_ADMINCOMMENT
|
909 USER_ALL_HOMEDIRECTORY
|
910 USER_ALL_SCRIPTPATH
|
911 USER_ALL_NTPASSWORDPRESENT
912 // USER_ALL_USERACCOUNTCONTROL
918 UserInfo3
= (PUSER_INFO_3
)UserInfo
;
920 // LPWSTR usri3_name;
922 RtlInitUnicodeString(&UserAllInfo
.NtPassword
,
923 UserInfo3
->usri3_password
);
924 UserAllInfo
.NtPasswordPresent
= TRUE
;
926 // DWORD usri3_password_age; // ignored
929 RtlInitUnicodeString(&UserAllInfo
.HomeDirectory
,
930 UserInfo3
->usri3_home_dir
);
932 RtlInitUnicodeString(&UserAllInfo
.AdminComment
,
933 UserInfo3
->usri3_comment
);
935 // DWORD usri3_flags;
937 RtlInitUnicodeString(&UserAllInfo
.ScriptPath
,
938 UserInfo3
->usri3_script_path
);
940 // DWORD usri3_auth_flags;
942 RtlInitUnicodeString(&UserAllInfo
.FullName
,
943 UserInfo3
->usri3_full_name
);
945 // LPWSTR usri3_usr_comment;
946 // LPWSTR usri3_parms;
947 // LPWSTR usri3_workstations;
948 // DWORD usri3_last_logon;
949 // DWORD usri3_last_logoff;
950 // DWORD usri3_acct_expires;
951 // DWORD usri3_max_storage;
952 // DWORD usri3_units_per_week;
953 // PBYTE usri3_logon_hours;
954 // DWORD usri3_bad_pw_count;
955 // DWORD usri3_num_logons;
956 // LPWSTR usri3_logon_server;
957 // DWORD usri3_country_code;
958 // DWORD usri3_code_page;
959 // DWORD usri3_user_id; // ignored
960 // DWORD usri3_primary_group_id;
961 // LPWSTR usri3_profile;
962 // LPWSTR usri3_home_dir_drive;
963 // DWORD usri3_password_expired;
965 UserAllInfo
.WhichFields
=
966 USER_ALL_NTPASSWORDPRESENT
|
967 USER_ALL_HOMEDIRECTORY
|
968 USER_ALL_ADMINCOMMENT
|
969 USER_ALL_SCRIPTPATH
|
971 // USER_ALL_USERACCOUNTCONTROL
976 ERR("Unsupported level %lu!\n", Level
);
977 return ERROR_INVALID_PARAMETER
;
980 Status
= SamSetInformationUser(UserHandle
,
983 if (!NT_SUCCESS(Status
))
985 ERR("SamSetInformationUser failed (Status %08lx)\n", Status
);
986 ApiStatus
= NetpNtStatusToApiStatus(Status
);
995 /************************************************************
996 * NetUserAdd (NETAPI32.@)
1000 NetUserAdd(LPCWSTR servername
,
1005 UNICODE_STRING ServerName
;
1006 UNICODE_STRING UserName
;
1007 SAM_HANDLE ServerHandle
= NULL
;
1008 SAM_HANDLE DomainHandle
= NULL
;
1009 SAM_HANDLE UserHandle
= NULL
;
1010 ULONG GrantedAccess
;
1012 NET_API_STATUS ApiStatus
= NERR_Success
;
1013 NTSTATUS Status
= STATUS_SUCCESS
;
1015 TRACE("(%s, %d, %p, %p)\n", debugstr_w(servername
), level
, bufptr
, parm_err
);
1017 /* Check the info level */
1018 if (level
< 1 || level
> 4)
1019 return ERROR_INVALID_LEVEL
;
1021 if (servername
!= NULL
)
1022 RtlInitUnicodeString(&ServerName
, servername
);
1024 /* Connect to the SAM Server */
1025 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
1027 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1029 if (!NT_SUCCESS(Status
))
1031 ERR("SamConnect failed (Status %08lx)\n", Status
);
1032 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1036 /* Open the Account Domain */
1037 Status
= OpenAccountDomain(ServerHandle
,
1038 (servername
!= NULL
) ? &ServerName
: NULL
,
1039 DOMAIN_CREATE_USER
| DOMAIN_LOOKUP
,
1041 if (!NT_SUCCESS(Status
))
1043 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
1044 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1048 /* Initialize the user name string */
1049 RtlInitUnicodeString(&UserName
,
1050 ((PUSER_INFO_1
)bufptr
)->usri1_name
);
1052 /* Create the user account */
1053 Status
= SamCreateUser2InDomain(DomainHandle
,
1055 USER_NORMAL_ACCOUNT
,
1056 USER_ALL_ACCESS
| DELETE
| WRITE_DAC
,
1060 if (!NT_SUCCESS(Status
))
1062 ERR("SamCreateUser2InDomain failed (Status %08lx)\n", Status
);
1063 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1067 /* Set user information */
1068 ApiStatus
= SetUserInfo(UserHandle
,
1071 if (ApiStatus
!= NERR_Success
)
1073 ERR("SetUserInfo failed (Status %lu)\n", ApiStatus
);
1078 if (UserHandle
!= NULL
)
1079 SamCloseHandle(UserHandle
);
1081 if (DomainHandle
!= NULL
)
1082 SamCloseHandle(DomainHandle
);
1084 if (ServerHandle
!= NULL
)
1085 SamCloseHandle(ServerHandle
);
1091 /******************************************************************************
1092 * NetUserChangePassword (NETAPI32.@)
1094 * domainname [I] Optional. Domain on which the user resides or the logon
1095 * domain of the current user if NULL.
1096 * username [I] Optional. Username to change the password for or the name
1097 * of the current user if NULL.
1098 * oldpassword [I] The user's current password.
1099 * newpassword [I] The password that the user will be changed to using.
1102 * Success: NERR_Success.
1103 * Failure: NERR_* failure code or win error code.
1108 NetUserChangePassword(LPCWSTR domainname
,
1110 LPCWSTR oldpassword
,
1111 LPCWSTR newpassword
)
1113 struct sam_user
*user
;
1115 TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname
), debugstr_w(username
));
1118 FIXME("Ignoring domainname %s.\n", debugstr_w(domainname
));
1120 if((user
= NETAPI_FindUser(username
)) == NULL
)
1121 return NERR_UserNotFound
;
1123 if(lstrcmpW(user
->user_password
, oldpassword
) != 0)
1124 return ERROR_INVALID_PASSWORD
;
1126 if(lstrlenW(newpassword
) > PWLEN
)
1127 return ERROR_PASSWORD_RESTRICTION
;
1129 lstrcpyW(user
->user_password
, newpassword
);
1131 return NERR_Success
;
1135 /************************************************************
1136 * NetUserDel (NETAPI32.@)
1140 NetUserDel(LPCWSTR servername
,
1143 NET_API_STATUS status
;
1144 struct sam_user
*user
;
1146 TRACE("(%s, %s)\n", debugstr_w(servername
), debugstr_w(username
));
1148 if((status
= NETAPI_ValidateServername(servername
))!= NERR_Success
)
1151 if ((user
= NETAPI_FindUser(username
)) == NULL
)
1152 return NERR_UserNotFound
;
1154 list_remove(&user
->entry
);
1156 HeapFree(GetProcessHeap(), 0, user
->home_dir
);
1157 HeapFree(GetProcessHeap(), 0, user
->user_comment
);
1158 HeapFree(GetProcessHeap(), 0, user
->user_logon_script_path
);
1159 HeapFree(GetProcessHeap(), 0, user
);
1161 return NERR_Success
;
1165 /************************************************************
1166 * NetUserEnum (NETAPI32.@)
1170 NetUserEnum(LPCWSTR servername
,
1175 LPDWORD entriesread
,
1176 LPDWORD totalentries
,
1177 LPDWORD resume_handle
)
1179 UNICODE_STRING ServerName
;
1180 PSAM_RID_ENUMERATION CurrentUser
;
1181 PENUM_CONTEXT EnumContext
= NULL
;
1182 LPVOID Buffer
= NULL
;
1184 SAM_HANDLE UserHandle
= NULL
;
1185 PUSER_ACCOUNT_INFORMATION UserInfo
= NULL
;
1187 NET_API_STATUS ApiStatus
= NERR_Success
;
1188 NTSTATUS Status
= STATUS_SUCCESS
;
1190 FIXME("(%s %d 0x%d %p %d %p %p %p) stub!\n", debugstr_w(servername
), level
,
1191 filter
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resume_handle
);
1197 if (servername
!= NULL
)
1198 RtlInitUnicodeString(&ServerName
, servername
);
1200 if (resume_handle
!= NULL
&& *resume_handle
!= 0)
1202 EnumContext
= (PENUM_CONTEXT
)*resume_handle
;
1206 ApiStatus
= NetApiBufferAllocate(sizeof(ENUM_CONTEXT
), (PVOID
*)&EnumContext
);
1207 if (ApiStatus
!= NERR_Success
)
1210 EnumContext
->EnumerationContext
= 0;
1211 EnumContext
->Buffer
= NULL
;
1212 EnumContext
->Count
= 0;
1213 EnumContext
->Index
= 0;
1214 EnumContext
->BuiltinDone
= FALSE
;
1216 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
1217 &EnumContext
->ServerHandle
,
1218 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1220 if (!NT_SUCCESS(Status
))
1222 ERR("SamConnect failed (Status %08lx)\n", Status
);
1223 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1227 Status
= OpenAccountDomain(EnumContext
->ServerHandle
,
1228 (servername
!= NULL
) ? &ServerName
: NULL
,
1229 DOMAIN_LIST_ACCOUNTS
| DOMAIN_LOOKUP
,
1230 &EnumContext
->AccountDomainHandle
);
1231 if (!NT_SUCCESS(Status
))
1233 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
1234 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1238 Status
= OpenBuiltinDomain(EnumContext
->ServerHandle
,
1239 DOMAIN_LIST_ACCOUNTS
| DOMAIN_LOOKUP
,
1240 &EnumContext
->BuiltinDomainHandle
);
1241 if (!NT_SUCCESS(Status
))
1243 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status
);
1244 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1251 TRACE("EnumContext->Index: %lu\n", EnumContext
->Index
);
1252 TRACE("EnumContext->Count: %lu\n", EnumContext
->Count
);
1254 if (EnumContext
->Index
>= EnumContext
->Count
)
1256 // if (EnumContext->BuiltinDone == TRUE)
1258 // ApiStatus = NERR_Success;
1262 TRACE("Calling SamEnumerateUsersInDomain\n");
1263 Status
= SamEnumerateUsersInDomain(EnumContext
->AccountDomainHandle
, //BuiltinDomainHandle,
1264 &EnumContext
->EnumerationContext
,
1266 (PVOID
*)&EnumContext
->Buffer
,
1268 &EnumContext
->Count
);
1270 TRACE("SamEnumerateUsersInDomain returned (Status %08lx)\n", Status
);
1271 if (!NT_SUCCESS(Status
))
1273 ERR("SamEnumerateUsersInDomain failed (Status %08lx)\n", Status
);
1274 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1278 if (Status
== STATUS_MORE_ENTRIES
)
1280 ApiStatus
= NERR_BufTooSmall
;
1285 EnumContext
->BuiltinDone
= TRUE
;
1289 TRACE("EnumContext: %lu\n", EnumContext
);
1290 TRACE("EnumContext->Count: %lu\n", EnumContext
->Count
);
1291 TRACE("EnumContext->Buffer: %p\n", EnumContext
->Buffer
);
1293 /* Get a pointer to the current user */
1294 CurrentUser
= &EnumContext
->Buffer
[EnumContext
->Index
];
1296 TRACE("RID: %lu\n", CurrentUser
->RelativeId
);
1298 Status
= SamOpenUser(EnumContext
->AccountDomainHandle
, //BuiltinDomainHandle,
1299 USER_READ_GENERAL
| USER_READ_PREFERENCES
| USER_READ_LOGON
| USER_READ_ACCOUNT
,
1300 CurrentUser
->RelativeId
,
1302 if (!NT_SUCCESS(Status
))
1304 ERR("SamOpenUser failed (Status %08lx)\n", Status
);
1305 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1309 Status
= SamQueryInformationUser(UserHandle
,
1310 UserAccountInformation
,
1311 (PVOID
*)&UserInfo
);
1312 if (!NT_SUCCESS(Status
))
1314 ERR("SamQueryInformationUser failed (Status %08lx)\n", Status
);
1315 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1319 SamCloseHandle(UserHandle
);
1322 ApiStatus
= BuildUserInfoBuffer(UserInfo
,
1324 CurrentUser
->RelativeId
,
1326 if (ApiStatus
!= NERR_Success
)
1328 ERR("BuildUserInfoBuffer failed (ApiStatus %lu)\n", ApiStatus
);
1332 if (UserInfo
!= NULL
)
1334 FreeUserInfo(UserInfo
);
1338 EnumContext
->Index
++;
1344 if (ApiStatus
== NERR_Success
&& EnumContext
->Index
< EnumContext
->Count
)
1345 ApiStatus
= ERROR_MORE_DATA
;
1347 if (EnumContext
!= NULL
)
1348 *totalentries
= EnumContext
->Count
;
1350 if (resume_handle
== NULL
|| ApiStatus
!= ERROR_MORE_DATA
)
1352 if (EnumContext
!= NULL
)
1354 if (EnumContext
->BuiltinDomainHandle
!= NULL
)
1355 SamCloseHandle(EnumContext
->BuiltinDomainHandle
);
1357 if (EnumContext
->AccountDomainHandle
!= NULL
)
1358 SamCloseHandle(EnumContext
->AccountDomainHandle
);
1360 if (EnumContext
->ServerHandle
!= NULL
)
1361 SamCloseHandle(EnumContext
->ServerHandle
);
1363 if (EnumContext
->Buffer
!= NULL
)
1365 for (i
= 0; i
< EnumContext
->Count
; i
++)
1367 SamFreeMemory(EnumContext
->Buffer
[i
].Name
.Buffer
);
1370 SamFreeMemory(EnumContext
->Buffer
);
1373 NetApiBufferFree(EnumContext
);
1378 if (UserHandle
!= NULL
)
1379 SamCloseHandle(UserHandle
);
1381 if (UserInfo
!= NULL
)
1382 FreeUserInfo(UserInfo
);
1384 if (resume_handle
!= NULL
)
1385 *resume_handle
= (DWORD_PTR
)EnumContext
;
1387 *bufptr
= (LPBYTE
)Buffer
;
1389 TRACE("return %lu\n", ApiStatus
);
1395 /************************************************************
1396 * NetUserGetGroups (NETAPI32.@)
1400 NetUserGetGroups(LPCWSTR servername
,
1405 LPDWORD entriesread
,
1406 LPDWORD totalentries
)
1408 FIXME("%s %s %d %p %d %p %p stub\n", debugstr_w(servername
),
1409 debugstr_w(username
), level
, bufptr
, prefixmaxlen
, entriesread
,
1416 return ERROR_INVALID_LEVEL
;
1420 /************************************************************
1421 * NetUserGetInfo (NETAPI32.@)
1425 NetUserGetInfo(LPCWSTR servername
,
1430 UNICODE_STRING ServerName
;
1431 UNICODE_STRING UserName
;
1432 SAM_HANDLE ServerHandle
= NULL
;
1433 SAM_HANDLE AccountDomainHandle
= NULL
;
1434 SAM_HANDLE UserHandle
= NULL
;
1435 PULONG RelativeIds
= NULL
;
1436 PSID_NAME_USE Use
= NULL
;
1437 PUSER_ACCOUNT_INFORMATION UserInfo
= NULL
;
1438 LPVOID Buffer
= NULL
;
1439 NET_API_STATUS ApiStatus
= NERR_Success
;
1440 NTSTATUS Status
= STATUS_SUCCESS
;
1442 TRACE("(%s, %s, %d, %p)\n", debugstr_w(servername
),
1443 debugstr_w(username
), level
, bufptr
);
1445 if (servername
!= NULL
)
1446 RtlInitUnicodeString(&ServerName
, servername
);
1448 RtlInitUnicodeString(&UserName
, username
);
1450 /* Connect to the SAM Server */
1451 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
1453 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1455 if (!NT_SUCCESS(Status
))
1457 ERR("SamConnect failed (Status %08lx)\n", Status
);
1458 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1462 /* Open the Account Domain */
1463 Status
= OpenAccountDomain(ServerHandle
,
1464 (servername
!= NULL
) ? &ServerName
: NULL
,
1465 DOMAIN_LIST_ACCOUNTS
| DOMAIN_LOOKUP
,
1466 &AccountDomainHandle
);
1467 if (!NT_SUCCESS(Status
))
1469 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
1470 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1474 /* Get the RID for the given user name */
1475 Status
= SamLookupNamesInDomain(AccountDomainHandle
,
1480 if (!NT_SUCCESS(Status
))
1482 ERR("SamOpenDomain failed (Status %08lx)\n", Status
);
1483 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1487 /* Check if the account is a user account */
1488 if (Use
[0] != SidTypeUser
)
1490 ERR("No user found!\n");
1491 ApiStatus
= NERR_UserNotFound
;
1495 TRACE("RID: %lu\n", RelativeIds
[0]);
1497 /* Open the user object */
1498 Status
= SamOpenUser(AccountDomainHandle
,
1499 USER_READ_GENERAL
| USER_READ_PREFERENCES
| USER_READ_LOGON
| USER_READ_ACCOUNT
,
1502 if (!NT_SUCCESS(Status
))
1504 ERR("SamOpenUser failed (Status %08lx)\n", Status
);
1505 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1509 Status
= SamQueryInformationUser(UserHandle
,
1510 UserAccountInformation
,
1511 (PVOID
*)&UserInfo
);
1512 if (!NT_SUCCESS(Status
))
1514 ERR("SamQueryInformationUser failed (Status %08lx)\n", Status
);
1515 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1519 ApiStatus
= BuildUserInfoBuffer(UserInfo
,
1523 if (ApiStatus
!= NERR_Success
)
1525 ERR("BuildUserInfoBuffer failed (ApiStatus %08lu)\n", ApiStatus
);
1530 if (UserInfo
!= NULL
)
1531 FreeUserInfo(UserInfo
);
1533 if (UserHandle
!= NULL
)
1534 SamCloseHandle(UserHandle
);
1536 if (RelativeIds
!= NULL
)
1537 SamFreeMemory(RelativeIds
);
1542 if (AccountDomainHandle
!= NULL
)
1543 SamCloseHandle(AccountDomainHandle
);
1545 if (ServerHandle
!= NULL
)
1546 SamCloseHandle(ServerHandle
);
1548 *bufptr
= (LPBYTE
)Buffer
;
1554 /************************************************************
1555 * NetUserGetLocalGroups (NETAPI32.@)
1559 NetUserGetLocalGroups(LPCWSTR servername
,
1565 LPDWORD entriesread
,
1566 LPDWORD totalentries
)
1568 UNICODE_STRING ServerName
;
1569 UNICODE_STRING UserName
;
1570 SAM_HANDLE ServerHandle
= NULL
;
1571 SAM_HANDLE BuiltinDomainHandle
= NULL
;
1572 SAM_HANDLE AccountDomainHandle
= NULL
;
1573 PSID AccountDomainSid
= NULL
;
1574 PSID UserSid
= NULL
;
1575 PULONG RelativeIds
= NULL
;
1576 PSID_NAME_USE Use
= NULL
;
1577 ULONG BuiltinMemberCount
= 0;
1578 ULONG AccountMemberCount
= 0;
1579 PULONG BuiltinAliases
= NULL
;
1580 PULONG AccountAliases
= NULL
;
1581 PUNICODE_STRING BuiltinNames
= NULL
;
1582 PUNICODE_STRING AccountNames
= NULL
;
1583 PLOCALGROUP_USERS_INFO_0 Buffer
= NULL
;
1589 NET_API_STATUS ApiStatus
= NERR_Success
;
1590 NTSTATUS Status
= STATUS_SUCCESS
;
1592 TRACE("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
1593 debugstr_w(servername
), debugstr_w(username
), level
, flags
, bufptr
,
1594 prefmaxlen
, entriesread
, totalentries
);
1597 return ERROR_INVALID_LEVEL
;
1599 if (flags
& ~LG_INCLUDE_INDIRECT
)
1600 return ERROR_INVALID_PARAMETER
;
1602 if (flags
& LG_INCLUDE_INDIRECT
)
1604 WARN("The flag LG_INCLUDE_INDIRECT is not supported yet!\n");
1607 if (servername
!= NULL
)
1608 RtlInitUnicodeString(&ServerName
, servername
);
1610 RtlInitUnicodeString(&UserName
, username
);
1612 /* Connect to the SAM Server */
1613 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
1615 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1617 if (!NT_SUCCESS(Status
))
1619 ERR("SamConnect failed (Status %08lx)\n", Status
);
1620 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1624 /* Open the Builtin Domain */
1625 Status
= OpenBuiltinDomain(ServerHandle
,
1626 DOMAIN_LOOKUP
| DOMAIN_GET_ALIAS_MEMBERSHIP
,
1627 &BuiltinDomainHandle
);
1628 if (!NT_SUCCESS(Status
))
1630 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status
);
1631 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1635 /* Get the Account Domain SID */
1636 Status
= GetAccountDomainSid((servername
!= NULL
) ? &ServerName
: NULL
,
1638 if (!NT_SUCCESS(Status
))
1640 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status
);
1641 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1645 /* Open the Account Domain */
1646 Status
= SamOpenDomain(ServerHandle
,
1647 DOMAIN_LOOKUP
| DOMAIN_GET_ALIAS_MEMBERSHIP
,
1649 &AccountDomainHandle
);
1650 if (!NT_SUCCESS(Status
))
1652 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
1653 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1657 /* Get the RID for the given user name */
1658 Status
= SamLookupNamesInDomain(AccountDomainHandle
,
1663 if (!NT_SUCCESS(Status
))
1665 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status
);
1666 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1670 /* Fail, if it is not a user account */
1671 if (Use
[0] != SidTypeUser
)
1673 ERR("Account is not a User!\n");
1674 ApiStatus
= NERR_UserNotFound
;
1678 /* Build the User SID from the Account Domain SID and the users RID */
1679 UserSid
= CreateSidFromSidAndRid(AccountDomainSid
,
1681 if (UserSid
== NULL
)
1683 ERR("CreateSidFromSidAndRid failed!\n");
1684 ApiStatus
= ERROR_NOT_ENOUGH_MEMORY
;
1688 /* Get alias memberships in the Builtin Domain */
1689 Status
= SamGetAliasMembership(BuiltinDomainHandle
,
1692 &BuiltinMemberCount
,
1694 if (!NT_SUCCESS(Status
))
1696 ERR("SamGetAliasMembership failed (Status %08lx)\n", Status
);
1697 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1701 if (BuiltinMemberCount
> 0)
1703 /* Get the Names of the builtin alias members */
1704 Status
= SamLookupIdsInDomain(BuiltinDomainHandle
,
1709 if (!NT_SUCCESS(Status
))
1711 ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status
);
1712 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1717 /* Get alias memberships in the Account Domain */
1718 Status
= SamGetAliasMembership(AccountDomainHandle
,
1721 &AccountMemberCount
,
1723 if (!NT_SUCCESS(Status
))
1725 ERR("SamGetAliasMembership failed (Status %08lx)\n", Status
);
1726 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1730 if (AccountMemberCount
> 0)
1732 /* Get the Names of the builtin alias members */
1733 Status
= SamLookupIdsInDomain(AccountDomainHandle
,
1738 if (!NT_SUCCESS(Status
))
1740 ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status
);
1741 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1746 /* Calculate the required buffer size */
1749 for (i
= 0; i
< BuiltinMemberCount
; i
++)
1751 if (BuiltinNames
[i
].Length
> 0)
1753 Size
+= (sizeof(LOCALGROUP_USERS_INFO_0
) + BuiltinNames
[i
].Length
+ sizeof(UNICODE_NULL
));
1758 for (i
= 0; i
< AccountMemberCount
; i
++)
1760 if (BuiltinNames
[i
].Length
> 0)
1762 Size
+= (sizeof(LOCALGROUP_USERS_INFO_0
) + AccountNames
[i
].Length
+ sizeof(UNICODE_NULL
));
1769 ApiStatus
= NERR_Success
;
1773 /* Allocate buffer */
1774 ApiStatus
= NetApiBufferAllocate(Size
, (LPVOID
*)&Buffer
);
1775 if (ApiStatus
!= NERR_Success
)
1778 ZeroMemory(Buffer
, Size
);
1780 StrPtr
= (LPWSTR
)((INT_PTR
)Buffer
+ Count
* sizeof(LOCALGROUP_USERS_INFO_0
));
1782 /* Copy data to the allocated buffer */
1784 for (i
= 0; i
< BuiltinMemberCount
; i
++)
1786 if (BuiltinNames
[i
].Length
> 0)
1789 BuiltinNames
[i
].Buffer
,
1790 BuiltinNames
[i
].Length
);
1791 Buffer
[Index
].lgrui0_name
= StrPtr
;
1793 StrPtr
= (LPWSTR
)((INT_PTR
)StrPtr
+ BuiltinNames
[i
].Length
+ sizeof(UNICODE_NULL
));
1798 for (i
= 0; i
< AccountMemberCount
; i
++)
1800 if (AccountNames
[i
].Length
> 0)
1803 AccountNames
[i
].Buffer
,
1804 AccountNames
[i
].Length
);
1805 Buffer
[Index
].lgrui0_name
= StrPtr
;
1807 StrPtr
= (LPWSTR
)((INT_PTR
)StrPtr
+ AccountNames
[i
].Length
+ sizeof(UNICODE_NULL
));
1813 if (AccountNames
!= NULL
)
1814 SamFreeMemory(AccountNames
);
1816 if (BuiltinNames
!= NULL
)
1817 SamFreeMemory(BuiltinNames
);
1819 if (AccountAliases
!= NULL
)
1820 SamFreeMemory(AccountAliases
);
1822 if (BuiltinAliases
!= NULL
)
1823 SamFreeMemory(BuiltinAliases
);
1825 if (RelativeIds
!= NULL
)
1826 SamFreeMemory(RelativeIds
);
1831 if (UserSid
!= NULL
)
1832 RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid
);
1834 if (AccountDomainSid
!= NULL
)
1835 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid
);
1837 if (AccountDomainHandle
!= NULL
)
1838 SamCloseHandle(AccountDomainHandle
);
1840 if (BuiltinDomainHandle
!= NULL
)
1841 SamCloseHandle(BuiltinDomainHandle
);
1843 if (ServerHandle
!= NULL
)
1844 SamCloseHandle(ServerHandle
);
1846 if (ApiStatus
!= NERR_Success
&& ApiStatus
!= ERROR_MORE_DATA
)
1853 *entriesread
= Count
;
1854 *totalentries
= Count
;
1857 *bufptr
= (LPBYTE
)Buffer
;
1863 /******************************************************************************
1864 * NetUserSetGroups (NETAPI32.@)
1868 NetUserSetGroups(LPCWSTR servername
,
1874 FIXME("(%s %s %lu %p %lu)\n",
1875 debugstr_w(servername
), debugstr_w(username
), level
, buf
, num_entries
);
1876 return ERROR_ACCESS_DENIED
;
1880 /******************************************************************************
1881 * NetUserSetInfo (NETAPI32.@)
1885 NetUserSetInfo(LPCWSTR servername
,
1891 FIXME("(%s %s %lu %p %p)\n",
1892 debugstr_w(servername
), debugstr_w(username
), level
, buf
, parm_err
);
1893 return ERROR_ACCESS_DENIED
;