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