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