d3606a2bc45229aa2bd0fbf98987136211ed2887
[reactos.git] / reactos / dll / win32 / netapi32 / local_group.c
1 /*
2 * Copyright 2006 Robert Reif
3 *
4 * netapi32 local group functions
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include <stdarg.h>
22
23 #include "ntstatus.h"
24 #define WIN32_NO_STATUS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winerror.h"
28 #include "lmcons.h"
29 #include "lmaccess.h"
30 #include "lmapibuf.h"
31 #include "lmerr.h"
32 #include "winreg.h"
33 #include "ntsecapi.h"
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36
37 #define NTOS_MODE_USER
38 #include <ndk/rtlfuncs.h>
39 #include "ntsam.h"
40 #include "netapi32.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
43
44
45 typedef struct _ENUM_CONTEXT
46 {
47 SAM_HANDLE ServerHandle;
48 SAM_HANDLE BuiltinDomainHandle;
49 SAM_HANDLE AccountDomainHandle;
50
51 SAM_ENUMERATE_HANDLE EnumerationContext;
52 PSAM_RID_ENUMERATION Buffer;
53 ULONG Returned;
54 ULONG Index;
55 BOOLEAN BuiltinDone;
56
57 } ENUM_CONTEXT, *PENUM_CONTEXT;
58
59
60 static
61 NET_API_STATUS
62 BuildAliasInfoBuffer(PALIAS_GENERAL_INFORMATION AliasInfo,
63 DWORD level,
64 LPVOID *Buffer)
65 {
66 LPVOID LocalBuffer = NULL;
67 PLOCALGROUP_INFO_0 LocalInfo0;
68 PLOCALGROUP_INFO_1 LocalInfo1;
69 LPWSTR Ptr;
70 ULONG Size = 0;
71 NET_API_STATUS ApiStatus = NERR_Success;
72
73 *Buffer = NULL;
74
75 switch (level)
76 {
77 case 0:
78 Size = sizeof(LOCALGROUP_INFO_0) +
79 AliasInfo->Name.Length + sizeof(WCHAR);
80 break;
81
82 case 1:
83 Size = sizeof(LOCALGROUP_INFO_1) +
84 AliasInfo->Name.Length + sizeof(WCHAR) +
85 AliasInfo->AdminComment.Length + sizeof(WCHAR);
86 break;
87
88 default:
89 ApiStatus = ERROR_INVALID_LEVEL;
90 goto done;
91 }
92
93 ApiStatus = NetApiBufferAllocate(Size, &LocalBuffer);
94 if (ApiStatus != NERR_Success)
95 goto done;
96
97 ZeroMemory(LocalBuffer, Size);
98
99 switch (level)
100 {
101 case 0:
102 LocalInfo0 = (PLOCALGROUP_INFO_0)LocalBuffer;
103
104 Ptr = (LPWSTR)LocalInfo0++;
105 LocalInfo0->lgrpi0_name = Ptr;
106
107 memcpy(LocalInfo0->lgrpi0_name,
108 AliasInfo->Name.Buffer,
109 AliasInfo->Name.Length);
110 LocalInfo0->lgrpi0_name[AliasInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
111 break;
112
113 case 1:
114 LocalInfo1 = (PLOCALGROUP_INFO_1)LocalBuffer;
115
116 Ptr = (LPWSTR)((ULONG_PTR)LocalInfo1 + sizeof(LOCALGROUP_INFO_1));
117 LocalInfo1->lgrpi1_name = Ptr;
118
119 memcpy(LocalInfo1->lgrpi1_name,
120 AliasInfo->Name.Buffer,
121 AliasInfo->Name.Length);
122 LocalInfo1->lgrpi1_name[AliasInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
123
124 Ptr = (LPWSTR)((ULONG_PTR)Ptr + AliasInfo->Name.Length + sizeof(WCHAR));
125 LocalInfo1->lgrpi1_comment = Ptr;
126
127 memcpy(LocalInfo1->lgrpi1_comment,
128 AliasInfo->AdminComment.Buffer,
129 AliasInfo->AdminComment.Length);
130 LocalInfo1->lgrpi1_comment[AliasInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
131 break;
132 }
133
134 done:
135 if (ApiStatus == NERR_Success)
136 {
137 *Buffer = LocalBuffer;
138 }
139 else
140 {
141 if (LocalBuffer != NULL)
142 NetApiBufferFree(LocalBuffer);
143 }
144
145 return ApiStatus;
146 }
147
148
149 static
150 VOID
151 FreeAliasInfo(PALIAS_GENERAL_INFORMATION AliasInfo)
152 {
153 if (AliasInfo->Name.Buffer != NULL)
154 SamFreeMemory(AliasInfo->Name.Buffer);
155
156 if (AliasInfo->AdminComment.Buffer != NULL)
157 SamFreeMemory(AliasInfo->AdminComment.Buffer);
158
159 SamFreeMemory(AliasInfo);
160 }
161
162
163 static
164 NET_API_STATUS
165 OpenAliasByName(SAM_HANDLE DomainHandle,
166 PUNICODE_STRING AliasName,
167 ULONG DesiredAccess,
168 PSAM_HANDLE AliasHandle)
169 {
170 PULONG RelativeIds = NULL;
171 PSID_NAME_USE Use = NULL;
172 NET_API_STATUS ApiStatus = NERR_Success;
173 NTSTATUS Status = STATUS_SUCCESS;
174
175 /* Get the RID for the given user name */
176 Status = SamLookupNamesInDomain(DomainHandle,
177 1,
178 AliasName,
179 &RelativeIds,
180 &Use);
181 if (!NT_SUCCESS(Status))
182 {
183 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
184 return NetpNtStatusToApiStatus(Status);
185 }
186
187 /* Fail, if it is not an alias account */
188 if (Use[0] != SidTypeAlias)
189 {
190 ERR("Object is not an Alias!\n");
191 ApiStatus = NERR_GroupNotFound;
192 goto done;
193 }
194
195 /* Open the alias account */
196 Status = SamOpenAlias(DomainHandle,
197 DesiredAccess,
198 RelativeIds[0],
199 AliasHandle);
200 if (!NT_SUCCESS(Status))
201 {
202 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
203 ApiStatus = NetpNtStatusToApiStatus(Status);
204 goto done;
205 }
206
207 done:
208 if (RelativeIds != NULL)
209 SamFreeMemory(RelativeIds);
210
211 if (Use != NULL)
212 SamFreeMemory(Use);
213
214 return ApiStatus;
215 }
216
217
218 /************************************************************
219 * NetLocalGroupAdd (NETAPI32.@)
220 */
221 NET_API_STATUS
222 WINAPI
223 NetLocalGroupAdd(
224 LPCWSTR servername,
225 DWORD level,
226 LPBYTE buf,
227 LPDWORD parm_err)
228 {
229 ALIAS_ADM_COMMENT_INFORMATION AdminComment;
230 UNICODE_STRING ServerName;
231 UNICODE_STRING AliasName;
232 SAM_HANDLE ServerHandle = NULL;
233 SAM_HANDLE DomainHandle = NULL;
234 SAM_HANDLE AliasHandle = NULL;
235 PSID DomainSid = NULL;
236 LPWSTR aliasname = NULL;
237 LPWSTR aliascomment = NULL;
238 ULONG RelativeId;
239 NET_API_STATUS ApiStatus = NERR_Success;
240 NTSTATUS Status = STATUS_SUCCESS;
241
242 TRACE("(%s %d %p %p) stub!\n", debugstr_w(servername), level, buf,
243 parm_err);
244
245 /* Initialize the Server name*/
246 if (servername != NULL)
247 RtlInitUnicodeString(&ServerName, servername);
248
249 /* Initialize the Alias name*/
250 switch (level)
251 {
252 case 0:
253 aliasname = ((PLOCALGROUP_INFO_0)buf)->lgrpi0_name;
254 aliascomment = NULL;
255 break;
256
257 case 1:
258 aliasname = ((PLOCALGROUP_INFO_1)buf)->lgrpi1_name;
259 aliascomment = ((PLOCALGROUP_INFO_1)buf)->lgrpi1_comment;
260 break;
261
262 default:
263 return ERROR_INVALID_LEVEL;
264 }
265
266 RtlInitUnicodeString(&AliasName, aliasname);
267
268 /* Connect to the SAM Server */
269 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
270 &ServerHandle,
271 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
272 NULL);
273 if (!NT_SUCCESS(Status))
274 {
275 ERR("SamConnect failed (Status %08lx)\n", Status);
276 ApiStatus = NetpNtStatusToApiStatus(Status);
277 goto done;
278 }
279
280 /* Get the Builtin Domain SID */
281 Status = GetBuiltinDomainSid(&DomainSid);
282 if (!NT_SUCCESS(Status))
283 {
284 ERR("GetBuiltinDomainSid failed (Status %08lx)\n", Status);
285 ApiStatus = NetpNtStatusToApiStatus(Status);
286 goto done;
287 }
288
289 /* Open the Builtin Domain */
290 Status = SamOpenDomain(ServerHandle,
291 DOMAIN_LOOKUP,
292 DomainSid,
293 &DomainHandle);
294 if (!NT_SUCCESS(Status))
295 {
296 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
297 ApiStatus = NetpNtStatusToApiStatus(Status);
298 goto done;
299 }
300
301 /* Try to open the Alias Account in the Builtin Domain */
302 ApiStatus = OpenAliasByName(DomainHandle,
303 &AliasName,
304 ALIAS_READ_INFORMATION,
305 &AliasHandle);
306 if (ApiStatus == NERR_Success)
307 {
308 ERR("OpenAliasByName: alias %wZ already exists!\n", &AliasName);
309
310 SamCloseHandle(AliasHandle);
311 ApiStatus = ERROR_ALIAS_EXISTS;
312 goto done;
313 }
314
315 ApiStatus = NERR_Success;
316
317 /* Free the Builtin Domain SID */
318 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
319 DomainSid = NULL;
320
321 /* Close the Builtin Domain */
322 SamCloseHandle(DomainHandle);
323 DomainHandle = NULL;
324
325 /* Get the account domain SID */
326 Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
327 &DomainSid);
328 if (!NT_SUCCESS(Status))
329 {
330 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
331 ApiStatus = NetpNtStatusToApiStatus(Status);
332 goto done;
333 }
334
335 /* Open the account domain */
336 Status = SamOpenDomain(ServerHandle,
337 DOMAIN_CREATE_ALIAS | DOMAIN_LOOKUP,
338 DomainSid,
339 &DomainHandle);
340 if (!NT_SUCCESS(Status))
341 {
342 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
343 ApiStatus = NetpNtStatusToApiStatus(Status);
344 goto done;
345 }
346
347 /* Create the alias */
348 Status = SamCreateAliasInDomain(DomainHandle,
349 &AliasName,
350 DELETE | ALIAS_WRITE_ACCOUNT,
351 &AliasHandle,
352 &RelativeId);
353 if (!NT_SUCCESS(Status))
354 {
355 ERR("SamCreateAliasInDomain failed (Status %08lx)\n", Status);
356 ApiStatus = NetpNtStatusToApiStatus(Status);
357 goto done;
358 }
359
360 TRACE("Created alias \"%wZ\" (RID: %lu)\n", &AliasName, RelativeId);
361
362 /* Set the admin comment */
363 if (level == 1)
364 {
365 RtlInitUnicodeString(&AdminComment.AdminComment, aliascomment);
366
367 Status = SamSetInformationAlias(AliasHandle,
368 AliasAdminCommentInformation,
369 &AdminComment);
370 if (!NT_SUCCESS(Status))
371 {
372 ERR("SamSetInformationAlias failed (Status %08lx)\n", Status);
373 ApiStatus = NetpNtStatusToApiStatus(Status);
374
375 /* Delete the Alias if the Comment could not be set */
376 SamDeleteAlias(AliasHandle);
377
378 goto done;
379 }
380 }
381
382 done:
383 if (AliasHandle != NULL)
384 SamCloseHandle(AliasHandle);
385
386 if (DomainSid != NULL)
387 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
388
389 if (DomainHandle != NULL)
390 SamCloseHandle(DomainHandle);
391
392 if (ServerHandle != NULL)
393 SamCloseHandle(ServerHandle);
394
395 return ApiStatus;
396 }
397
398
399 /************************************************************
400 * NetLocalGroupAddMember (NETAPI32.@)
401 */
402 NET_API_STATUS WINAPI NetLocalGroupAddMember(
403 LPCWSTR servername,
404 LPCWSTR groupname,
405 PSID membersid)
406 {
407 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
408 debugstr_w(groupname), membersid);
409 return NERR_Success;
410 }
411
412 /************************************************************
413 * NetLocalGroupAddMembers (NETAPI32.@)
414 */
415 NET_API_STATUS WINAPI NetLocalGroupAddMembers(
416 LPCWSTR servername,
417 LPCWSTR groupname,
418 DWORD level,
419 LPBYTE buf,
420 DWORD totalentries)
421 {
422 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
423 debugstr_w(groupname), level, buf, totalentries);
424 return NERR_Success;
425 }
426
427 /************************************************************
428 * NetLocalGroupDel (NETAPI32.@)
429 */
430 NET_API_STATUS WINAPI NetLocalGroupDel(
431 LPCWSTR servername,
432 LPCWSTR groupname)
433 {
434 FIXME("(%s %s) stub!\n", debugstr_w(servername), debugstr_w(groupname));
435 return NERR_Success;
436 }
437
438 /************************************************************
439 * NetLocalGroupDelMember (NETAPI32.@)
440 */
441 NET_API_STATUS WINAPI NetLocalGroupDelMember(
442 LPCWSTR servername,
443 LPCWSTR groupname,
444 PSID membersid)
445 {
446 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
447 debugstr_w(groupname), membersid);
448 return NERR_Success;
449 }
450
451 /************************************************************
452 * NetLocalGroupDelMembers (NETAPI32.@)
453 */
454 NET_API_STATUS WINAPI NetLocalGroupDelMembers(
455 LPCWSTR servername,
456 LPCWSTR groupname,
457 DWORD level,
458 LPBYTE buf,
459 DWORD totalentries)
460 {
461 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
462 debugstr_w(groupname), level, buf, totalentries);
463 return NERR_Success;
464 }
465
466 /************************************************************
467 * NetLocalGroupEnum (NETAPI32.@)
468 */
469 NET_API_STATUS WINAPI NetLocalGroupEnum(
470 LPCWSTR servername,
471 DWORD level,
472 LPBYTE* bufptr,
473 DWORD prefmaxlen,
474 LPDWORD entriesread,
475 LPDWORD totalentries,
476 PDWORD_PTR resumehandle)
477 {
478 UNICODE_STRING ServerName;
479 PSAM_RID_ENUMERATION CurrentAlias;
480 PENUM_CONTEXT EnumContext = NULL;
481 PSID DomainSid = NULL;
482 ULONG i;
483 SAM_HANDLE AliasHandle = NULL;
484 PALIAS_GENERAL_INFORMATION AliasInfo = NULL;
485 LPVOID Buffer = NULL;
486 NET_API_STATUS ApiStatus = NERR_Success;
487 NTSTATUS Status = STATUS_SUCCESS;
488
489 TRACE("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername),
490 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
491
492 *entriesread = 0;
493 *totalentries = 0;
494 *bufptr = NULL;
495
496 if (servername != NULL)
497 RtlInitUnicodeString(&ServerName, servername);
498
499 if (resumehandle != NULL && *resumehandle != 0)
500 {
501 EnumContext = (PENUM_CONTEXT)*resumehandle;
502 }
503 else
504 {
505 ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
506 if (ApiStatus != NERR_Success)
507 goto done;
508
509 EnumContext->EnumerationContext = 0;
510 EnumContext->Buffer = NULL;
511 EnumContext->Returned = 0;
512 EnumContext->Index = 0;
513 EnumContext->BuiltinDone = FALSE;
514
515 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
516 &EnumContext->ServerHandle,
517 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
518 NULL);
519 if (!NT_SUCCESS(Status))
520 {
521 ERR("SamConnect failed (Status %08lx)\n", Status);
522 ApiStatus = NetpNtStatusToApiStatus(Status);
523 goto done;
524 }
525
526 Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
527 &DomainSid);
528 if (!NT_SUCCESS(Status))
529 {
530 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
531 ApiStatus = NetpNtStatusToApiStatus(Status);
532 goto done;
533 }
534
535 Status = SamOpenDomain(EnumContext->ServerHandle,
536 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
537 DomainSid,
538 &EnumContext->AccountDomainHandle);
539
540 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
541
542 if (!NT_SUCCESS(Status))
543 {
544 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
545 ApiStatus = NetpNtStatusToApiStatus(Status);
546 goto done;
547 }
548
549 Status = GetBuiltinDomainSid(&DomainSid);
550 if (!NT_SUCCESS(Status))
551 {
552 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
553 ApiStatus = NetpNtStatusToApiStatus(Status);
554 goto done;
555 }
556
557 Status = SamOpenDomain(EnumContext->ServerHandle,
558 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
559 DomainSid,
560 &EnumContext->BuiltinDomainHandle);
561
562 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
563
564 if (!NT_SUCCESS(Status))
565 {
566 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
567 ApiStatus = NetpNtStatusToApiStatus(Status);
568 goto done;
569 }
570 }
571
572
573 // while (TRUE)
574 // {
575 TRACE("EnumContext->Index: %lu\n", EnumContext->Index);
576 TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
577
578 if (EnumContext->Index >= EnumContext->Returned)
579 {
580 // if (EnumContext->BuiltinDone == TRUE)
581 // {
582 // ApiStatus = NERR_Success;
583 // goto done;
584 // }
585
586 TRACE("Calling SamEnumerateAliasesInDomain\n");
587
588 Status = SamEnumerateAliasesInDomain(EnumContext->BuiltinDomainHandle,
589 &EnumContext->EnumerationContext,
590 (PVOID *)&EnumContext->Buffer,
591 prefmaxlen,
592 &EnumContext->Returned);
593
594 TRACE("SamEnumerateAliasesInDomain returned (Status %08lx)\n", Status);
595 if (!NT_SUCCESS(Status))
596 {
597 ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status);
598 ApiStatus = NetpNtStatusToApiStatus(Status);
599 goto done;
600 }
601
602 if (Status == STATUS_MORE_ENTRIES)
603 {
604 ApiStatus = NERR_BufTooSmall;
605 goto done;
606 }
607 else
608 {
609 EnumContext->BuiltinDone = TRUE;
610 }
611 }
612
613 TRACE("EnumContext: %lu\n", EnumContext);
614 TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
615 TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
616
617 /* Get a pointer to the current alias */
618 CurrentAlias = &EnumContext->Buffer[EnumContext->Index];
619
620 TRACE("RID: %lu\n", CurrentAlias->RelativeId);
621
622 Status = SamOpenAlias(EnumContext->BuiltinDomainHandle,
623 ALIAS_READ_INFORMATION,
624 CurrentAlias->RelativeId,
625 &AliasHandle);
626 if (!NT_SUCCESS(Status))
627 {
628 ERR("SamOpenAlias failed (Status %08lx)\n", Status);
629 ApiStatus = NetpNtStatusToApiStatus(Status);
630 goto done;
631 }
632
633 Status = SamQueryInformationAlias(AliasHandle,
634 AliasGeneralInformation,
635 (PVOID *)&AliasInfo);
636 if (!NT_SUCCESS(Status))
637 {
638 ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status);
639 ApiStatus = NetpNtStatusToApiStatus(Status);
640 goto done;
641 }
642
643 SamCloseHandle(AliasHandle);
644 AliasHandle = NULL;
645
646 TRACE("Name: %S\n", AliasInfo->Name.Buffer);
647 TRACE("Comment: %S\n", AliasInfo->AdminComment.Buffer);
648
649 ApiStatus = BuildAliasInfoBuffer(AliasInfo,
650 level,
651 &Buffer);
652 if (ApiStatus != NERR_Success)
653 goto done;
654
655 if (AliasInfo != NULL)
656 {
657 FreeAliasInfo(AliasInfo);
658 AliasInfo = NULL;
659 }
660
661 EnumContext->Index++;
662
663 (*entriesread)++;
664
665 // }
666
667 done:
668 if (ApiStatus == NERR_Success && EnumContext->Index < EnumContext->Returned)
669 ApiStatus = ERROR_MORE_DATA;
670
671 if (EnumContext != NULL)
672 *totalentries = EnumContext->Returned;
673
674 if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA)
675 {
676 if (EnumContext != NULL)
677 {
678 if (EnumContext->BuiltinDomainHandle != NULL)
679 SamCloseHandle(EnumContext->BuiltinDomainHandle);
680
681 if (EnumContext->AccountDomainHandle != NULL)
682 SamCloseHandle(EnumContext->AccountDomainHandle);
683
684 if (EnumContext->ServerHandle != NULL)
685 SamCloseHandle(EnumContext->ServerHandle);
686
687 if (EnumContext->Buffer != NULL)
688 {
689 for (i = 0; i < EnumContext->Returned; i++)
690 {
691 SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
692 }
693
694 SamFreeMemory(EnumContext->Buffer);
695 }
696
697 NetApiBufferFree(EnumContext);
698 EnumContext = NULL;
699 }
700 }
701
702 if (AliasHandle != NULL)
703 SamCloseHandle(AliasHandle);
704
705 if (AliasInfo != NULL)
706 FreeAliasInfo(AliasInfo);
707
708 if (resumehandle != NULL)
709 *resumehandle = (DWORD_PTR)EnumContext;
710
711 *bufptr = (LPBYTE)Buffer;
712
713 TRACE ("return %lu\n", ApiStatus);
714
715 return ApiStatus;
716 }
717
718
719 /************************************************************
720 * NetLocalGroupGetInfo (NETAPI32.@)
721 */
722 NET_API_STATUS
723 WINAPI
724 NetLocalGroupGetInfo(
725 LPCWSTR servername,
726 LPCWSTR groupname,
727 DWORD level,
728 LPBYTE* bufptr)
729 {
730 UNICODE_STRING ServerName;
731 UNICODE_STRING GroupName;
732 SAM_HANDLE ServerHandle = NULL;
733 SAM_HANDLE DomainHandle = NULL;
734 SAM_HANDLE AliasHandle = NULL;
735 PSID DomainSid = NULL;
736 PALIAS_GENERAL_INFORMATION AliasInfo = NULL;
737 LPVOID Buffer = NULL;
738 NET_API_STATUS ApiStatus = NERR_Success;
739 NTSTATUS Status = STATUS_SUCCESS;
740
741 TRACE("(%s %s %d %p) stub!\n", debugstr_w(servername),
742 debugstr_w(groupname), level, bufptr);
743
744 if (servername != NULL)
745 RtlInitUnicodeString(&ServerName, servername);
746
747 RtlInitUnicodeString(&GroupName, groupname);
748
749 /* Connect to the SAM Server */
750 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
751 &ServerHandle,
752 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
753 NULL);
754 if (!NT_SUCCESS(Status))
755 {
756 ERR("SamConnect failed (Status %08lx)\n", Status);
757 ApiStatus = NetpNtStatusToApiStatus(Status);
758 goto done;
759 }
760
761 /* Get the Builtin Domain SID */
762 Status = GetBuiltinDomainSid(&DomainSid);
763 if (!NT_SUCCESS(Status))
764 {
765 ERR("GetBuiltinDomainSid failed (Status %08lx)\n", Status);
766 ApiStatus = NetpNtStatusToApiStatus(Status);
767 goto done;
768 }
769
770 /* Open the Builtin Domain */
771 Status = SamOpenDomain(ServerHandle,
772 DOMAIN_LOOKUP,
773 DomainSid,
774 &DomainHandle);
775 if (!NT_SUCCESS(Status))
776 {
777 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
778 ApiStatus = NetpNtStatusToApiStatus(Status);
779 goto done;
780 }
781
782 /* Open the alias account in the builtin domain */
783 ApiStatus = OpenAliasByName(DomainHandle,
784 &GroupName,
785 ALIAS_READ_INFORMATION,
786 &AliasHandle);
787 if (ApiStatus != NERR_Success)
788 {
789 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
790 goto done;
791 }
792
793 if (AliasHandle == NULL)
794 {
795 if (DomainSid != NULL)
796 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
797
798 if (DomainHandle != NULL)
799 SamCloseHandle(DomainHandle);
800
801 /* Get the Account Domain SID */
802 Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
803 &DomainSid);
804 if (!NT_SUCCESS(Status))
805 {
806 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
807 ApiStatus = NetpNtStatusToApiStatus(Status);
808 goto done;
809 }
810
811 /* Open the Acount Domain */
812 Status = SamOpenDomain(ServerHandle,
813 DOMAIN_LOOKUP,
814 DomainSid,
815 &DomainHandle);
816 if (!NT_SUCCESS(Status))
817 {
818 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
819 ApiStatus = NetpNtStatusToApiStatus(Status);
820 goto done;
821 }
822
823 /* Open the alias account in the account domain */
824 ApiStatus = OpenAliasByName(DomainHandle,
825 &GroupName,
826 ALIAS_READ_INFORMATION,
827 &AliasHandle);
828 if (ApiStatus != NERR_Success)
829 {
830 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
831 goto done;
832 }
833 }
834
835 Status = SamQueryInformationAlias(AliasHandle,
836 AliasGeneralInformation,
837 (PVOID *)&AliasInfo);
838 if (!NT_SUCCESS(Status))
839 {
840 ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status);
841 ApiStatus = NetpNtStatusToApiStatus(Status);
842 goto done;
843 }
844
845 ApiStatus = BuildAliasInfoBuffer(AliasInfo,
846 level,
847 &Buffer);
848 if (ApiStatus != NERR_Success)
849 goto done;
850
851 done:
852 if (AliasInfo != NULL)
853 FreeAliasInfo(AliasInfo);
854
855 if (AliasHandle != NULL)
856 SamCloseHandle(AliasHandle);
857
858 if (DomainSid != NULL)
859 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
860
861 if (DomainHandle != NULL)
862 SamCloseHandle(DomainHandle);
863
864 if (ServerHandle != NULL)
865 SamCloseHandle(ServerHandle);
866
867 *bufptr = (LPBYTE)Buffer;
868
869 return ApiStatus;
870 }
871
872
873 /************************************************************
874 * NetLocalGroupGetMembers (NETAPI32.@)
875 */
876 NET_API_STATUS WINAPI NetLocalGroupGetMembers(
877 LPCWSTR servername,
878 LPCWSTR localgroupname,
879 DWORD level,
880 LPBYTE* bufptr,
881 DWORD prefmaxlen,
882 LPDWORD entriesread,
883 LPDWORD totalentries,
884 PDWORD_PTR resumehandle)
885 {
886 FIXME("(%s %s %d %p %d, %p %p %p) stub!\n", debugstr_w(servername),
887 debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread,
888 totalentries, resumehandle);
889
890 if (level == 3)
891 {
892 WCHAR userName[MAX_COMPUTERNAME_LENGTH + 1];
893 DWORD userNameLen;
894 DWORD len,needlen;
895 PLOCALGROUP_MEMBERS_INFO_3 ptr;
896
897 /* still a stub, current user is belonging to all groups */
898
899 *totalentries = 1;
900 *entriesread = 0;
901
902 userNameLen = MAX_COMPUTERNAME_LENGTH + 1;
903 GetUserNameW(userName,&userNameLen);
904 needlen = sizeof(LOCALGROUP_MEMBERS_INFO_3) +
905 (userNameLen+2) * sizeof(WCHAR);
906 if (prefmaxlen != MAX_PREFERRED_LENGTH)
907 len = min(prefmaxlen,needlen);
908 else
909 len = needlen;
910
911 NetApiBufferAllocate(len, (LPVOID *) bufptr);
912 if (len < needlen)
913 return ERROR_MORE_DATA;
914
915 ptr = (PLOCALGROUP_MEMBERS_INFO_3)*bufptr;
916 ptr->lgrmi3_domainandname = (LPWSTR)(*bufptr+sizeof(LOCALGROUP_MEMBERS_INFO_3));
917 lstrcpyW(ptr->lgrmi3_domainandname,userName);
918
919 *entriesread = 1;
920 }
921
922 return NERR_Success;
923 }
924
925 /************************************************************
926 * NetLocalGroupSetInfo (NETAPI32.@)
927 */
928 NET_API_STATUS WINAPI NetLocalGroupSetInfo(
929 LPCWSTR servername,
930 LPCWSTR groupname,
931 DWORD level,
932 LPBYTE buf,
933 LPDWORD parm_err)
934 {
935 FIXME("(%s %s %d %p %p) stub!\n", debugstr_w(servername),
936 debugstr_w(groupname), level, buf, parm_err);
937 return NERR_Success;
938 }
939
940 /************************************************************
941 * NetLocalGroupSetMember (NETAPI32.@)
942 */
943 NET_API_STATUS WINAPI NetLocalGroupSetMembers(
944 LPCWSTR servername,
945 LPCWSTR groupname,
946 DWORD level,
947 LPBYTE buf,
948 DWORD totalentries)
949 {
950 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
951 debugstr_w(groupname), level, buf, totalentries);
952 return NERR_Success;
953 }