[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 <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 static SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
60
61
62 static
63 NTSTATUS
64 GetAccountDomainSid(PSID *AccountDomainSid)
65 {
66 PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo = NULL;
67 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
68 LSA_HANDLE PolicyHandle = NULL;
69 ULONG Length = 0;
70 NTSTATUS Status;
71
72 memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
73
74 Status = LsaOpenPolicy(NULL,
75 &ObjectAttributes,
76 POLICY_VIEW_LOCAL_INFORMATION,
77 &PolicyHandle);
78 if (!NT_SUCCESS(Status))
79 {
80 ERR("LsaOpenPolicy failed (Status %08lx)\n", Status);
81 return Status;
82 }
83
84 Status = LsaQueryInformationPolicy(PolicyHandle,
85 PolicyAccountDomainInformation,
86 (PVOID *)&AccountDomainInfo);
87 if (!NT_SUCCESS(Status))
88 {
89 ERR("LsaQueryInformationPolicy failed (Status %08lx)\n", Status);
90 goto done;
91 }
92
93 Length = RtlLengthSid(AccountDomainInfo->DomainSid);
94
95 *AccountDomainSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
96 if (*AccountDomainSid == NULL)
97 {
98 ERR("Failed to allocate SID\n");
99 Status = STATUS_INSUFFICIENT_RESOURCES;
100 goto done;
101 }
102
103 memcpy(*AccountDomainSid, AccountDomainInfo->DomainSid, Length);
104
105 done:
106 if (AccountDomainInfo != NULL)
107 LsaFreeMemory(AccountDomainInfo);
108
109 LsaClose(PolicyHandle);
110
111 return Status;
112 }
113
114
115 static
116 NTSTATUS
117 GetBuiltinDomainSid(PSID *BuiltinDomainSid)
118 {
119 PSID Sid = NULL;
120 PULONG Ptr;
121 NTSTATUS Status = STATUS_SUCCESS;
122
123 *BuiltinDomainSid = NULL;
124
125 Sid = RtlAllocateHeap(RtlGetProcessHeap(),
126 0,
127 RtlLengthRequiredSid(1));
128 if (Sid == NULL)
129 return STATUS_INSUFFICIENT_RESOURCES;
130
131 Status = RtlInitializeSid(Sid,
132 &NtAuthority,
133 1);
134 if (!NT_SUCCESS(Status))
135 goto done;
136
137 Ptr = RtlSubAuthoritySid(Sid, 0);
138 *Ptr = SECURITY_BUILTIN_DOMAIN_RID;
139
140 *BuiltinDomainSid = Sid;
141
142 done:
143 if (!NT_SUCCESS(Status))
144 {
145 if (Sid != NULL)
146 RtlFreeHeap(RtlGetProcessHeap(), 0, Sid);
147 }
148
149 return Status;
150 }
151
152
153 /************************************************************
154 * NetLocalGroupAdd (NETAPI32.@)
155 */
156 NET_API_STATUS WINAPI NetLocalGroupAdd(
157 LPCWSTR servername,
158 DWORD level,
159 LPBYTE buf,
160 LPDWORD parm_err)
161 {
162 FIXME("(%s %d %p %p) stub!\n", debugstr_w(servername), level, buf,
163 parm_err);
164 return NERR_Success;
165 }
166
167 /************************************************************
168 * NetLocalGroupAddMember (NETAPI32.@)
169 */
170 NET_API_STATUS WINAPI NetLocalGroupAddMember(
171 LPCWSTR servername,
172 LPCWSTR groupname,
173 PSID membersid)
174 {
175 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
176 debugstr_w(groupname), membersid);
177 return NERR_Success;
178 }
179
180 /************************************************************
181 * NetLocalGroupAddMembers (NETAPI32.@)
182 */
183 NET_API_STATUS WINAPI NetLocalGroupAddMembers(
184 LPCWSTR servername,
185 LPCWSTR groupname,
186 DWORD level,
187 LPBYTE buf,
188 DWORD totalentries)
189 {
190 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
191 debugstr_w(groupname), level, buf, totalentries);
192 return NERR_Success;
193 }
194
195 /************************************************************
196 * NetLocalGroupDel (NETAPI32.@)
197 */
198 NET_API_STATUS WINAPI NetLocalGroupDel(
199 LPCWSTR servername,
200 LPCWSTR groupname)
201 {
202 FIXME("(%s %s) stub!\n", debugstr_w(servername), debugstr_w(groupname));
203 return NERR_Success;
204 }
205
206 /************************************************************
207 * NetLocalGroupDelMember (NETAPI32.@)
208 */
209 NET_API_STATUS WINAPI NetLocalGroupDelMember(
210 LPCWSTR servername,
211 LPCWSTR groupname,
212 PSID membersid)
213 {
214 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
215 debugstr_w(groupname), membersid);
216 return NERR_Success;
217 }
218
219 /************************************************************
220 * NetLocalGroupDelMembers (NETAPI32.@)
221 */
222 NET_API_STATUS WINAPI NetLocalGroupDelMembers(
223 LPCWSTR servername,
224 LPCWSTR groupname,
225 DWORD level,
226 LPBYTE buf,
227 DWORD totalentries)
228 {
229 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
230 debugstr_w(groupname), level, buf, totalentries);
231 return NERR_Success;
232 }
233
234 /************************************************************
235 * NetLocalGroupEnum (NETAPI32.@)
236 */
237 NET_API_STATUS WINAPI NetLocalGroupEnum(
238 LPCWSTR servername,
239 DWORD level,
240 LPBYTE* bufptr,
241 DWORD prefmaxlen,
242 LPDWORD entriesread,
243 LPDWORD totalentries,
244 PDWORD_PTR resumehandle)
245 {
246 PSAM_RID_ENUMERATION CurrentAlias;
247 PENUM_CONTEXT EnumContext = NULL;
248 PSID DomainSid = NULL;
249 PLOCALGROUP_INFO_0 LocalInfo0;
250 PLOCALGROUP_INFO_1 LocalInfo1;
251 LPWSTR Ptr;
252 ULONG i;
253 ULONG Size;
254 SAM_HANDLE AliasHandle = NULL;
255 PALIAS_GENERAL_INFORMATION AliasInfo = NULL;
256 LPVOID Buffer = NULL;
257 NET_API_STATUS ApiStatus = NERR_Success;
258 NTSTATUS Status = STATUS_SUCCESS;
259
260 FIXME("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername),
261 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
262
263 *entriesread = 0;
264 *totalentries = 0;
265 *bufptr = NULL;
266
267 if (resumehandle != NULL && *resumehandle != 0)
268 {
269 EnumContext = (PENUM_CONTEXT)*resumehandle;
270 }
271 else
272 {
273 ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
274 if (ApiStatus != NERR_Success)
275 goto done;
276
277 EnumContext->EnumerationContext = 0;
278 EnumContext->Buffer = NULL;
279 EnumContext->Returned = 0;
280 EnumContext->Index = 0;
281 EnumContext->BuiltinDone = FALSE;
282
283 Status = SamConnect(NULL,
284 &EnumContext->ServerHandle,
285 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
286 NULL);
287 if (!NT_SUCCESS(Status))
288 {
289 ERR("SamConnect failed (Status %08lx)\n", Status);
290 ApiStatus = NetpNtStatusToApiStatus(Status);
291 goto done;
292 }
293
294 Status = GetAccountDomainSid(&DomainSid);
295 if (!NT_SUCCESS(Status))
296 {
297 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
298 ApiStatus = NetpNtStatusToApiStatus(Status);
299 goto done;
300 }
301
302 Status = SamOpenDomain(EnumContext->ServerHandle,
303 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
304 DomainSid,
305 &EnumContext->AccountDomainHandle);
306
307 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
308
309 if (!NT_SUCCESS(Status))
310 {
311 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
312 ApiStatus = NetpNtStatusToApiStatus(Status);
313 goto done;
314 }
315
316 Status = GetBuiltinDomainSid(&DomainSid);
317 if (!NT_SUCCESS(Status))
318 {
319 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
320 ApiStatus = NetpNtStatusToApiStatus(Status);
321 goto done;
322 }
323
324 Status = SamOpenDomain(EnumContext->ServerHandle,
325 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
326 DomainSid,
327 &EnumContext->BuiltinDomainHandle);
328
329 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
330
331 if (!NT_SUCCESS(Status))
332 {
333 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
334 ApiStatus = NetpNtStatusToApiStatus(Status);
335 goto done;
336 }
337 }
338
339
340 // while (TRUE)
341 // {
342 TRACE("EnumContext->Index: %lu\n", EnumContext->Index);
343 TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
344
345 if (EnumContext->Index >= EnumContext->Returned)
346 {
347 // if (EnumContext->BuiltinDone == TRUE)
348 // {
349 // ApiStatus = NERR_Success;
350 // goto done;
351 // }
352
353 TRACE("Calling SamEnumerateAliasesInDomain\n");
354
355 Status = SamEnumerateAliasesInDomain(EnumContext->BuiltinDomainHandle,
356 &EnumContext->EnumerationContext,
357 (PVOID *)&EnumContext->Buffer,
358 prefmaxlen,
359 &EnumContext->Returned);
360
361 TRACE("SamEnumerateAliasesInDomain returned (Status %08lx)\n", Status);
362 if (!NT_SUCCESS(Status))
363 {
364 ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status);
365 ApiStatus = NetpNtStatusToApiStatus(Status);
366 goto done;
367 }
368
369 if (Status == STATUS_MORE_ENTRIES)
370 {
371 ApiStatus = NERR_BufTooSmall;
372 goto done;
373 }
374 else
375 {
376 EnumContext->BuiltinDone = TRUE;
377 }
378 }
379
380 TRACE("EnumContext: %lu\n", EnumContext);
381 TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
382 TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
383
384 /* Get a pointer to the current alias */
385 CurrentAlias = &EnumContext->Buffer[EnumContext->Index];
386
387 TRACE("RID: %lu\n", CurrentAlias->RelativeId);
388
389 Status = SamOpenAlias(EnumContext->BuiltinDomainHandle,
390 ALIAS_READ_INFORMATION,
391 CurrentAlias->RelativeId,
392 &AliasHandle);
393 if (!NT_SUCCESS(Status))
394 {
395 ERR("SamOpenAlias failed (Status %08lx)\n", Status);
396 ApiStatus = NetpNtStatusToApiStatus(Status);
397 goto done;
398 }
399
400 Status = SamQueryInformationAlias(AliasHandle,
401 AliasGeneralInformation,
402 (PVOID *)&AliasInfo);
403 if (!NT_SUCCESS(Status))
404 {
405 ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status);
406 ApiStatus = NetpNtStatusToApiStatus(Status);
407 goto done;
408 }
409
410 SamCloseHandle(AliasHandle);
411 AliasHandle = NULL;
412
413 TRACE("Name: %S\n", AliasInfo->Name.Buffer);
414 TRACE("Comment: %S\n", AliasInfo->AdminComment.Buffer);
415
416 switch (level)
417 {
418 case 0:
419 Size = sizeof(LOCALGROUP_INFO_0) +
420 AliasInfo->Name.Length + sizeof(WCHAR);
421 break;
422
423 case 1:
424 Size = sizeof(LOCALGROUP_INFO_1) +
425 AliasInfo->Name.Length + sizeof(WCHAR) +
426 AliasInfo->AdminComment.Length + sizeof(WCHAR);
427 break;
428
429 default:
430 ApiStatus = ERROR_INVALID_LEVEL;
431 goto done;
432 }
433
434 ApiStatus = NetApiBufferAllocate(Size, &Buffer);
435 if (ApiStatus != NERR_Success)
436 goto done;
437
438 switch (level)
439 {
440 case 0:
441 LocalInfo0 = (PLOCALGROUP_INFO_0)Buffer;
442
443 Ptr = (LPWSTR)LocalInfo0++;
444 LocalInfo0->lgrpi0_name = Ptr;
445
446 memcpy(LocalInfo0->lgrpi0_name,
447 AliasInfo->Name.Buffer,
448 AliasInfo->Name.Length);
449 LocalInfo0->lgrpi0_name[AliasInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
450 break;
451
452 case 1:
453 LocalInfo1 = (PLOCALGROUP_INFO_1)Buffer;
454
455 Ptr = (LPWSTR)((ULONG_PTR)LocalInfo1 + sizeof(LOCALGROUP_INFO_1));
456 LocalInfo1->lgrpi1_name = Ptr;
457
458 memcpy(LocalInfo1->lgrpi1_name,
459 AliasInfo->Name.Buffer,
460 AliasInfo->Name.Length);
461 LocalInfo1->lgrpi1_name[AliasInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
462
463 Ptr = (LPWSTR)((ULONG_PTR)Ptr + AliasInfo->Name.Length + sizeof(WCHAR));
464 LocalInfo1->lgrpi1_comment = Ptr;
465
466 memcpy(LocalInfo1->lgrpi1_comment,
467 AliasInfo->AdminComment.Buffer,
468 AliasInfo->AdminComment.Length);
469 LocalInfo1->lgrpi1_comment[AliasInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
470 break;
471 }
472
473 if (AliasInfo != NULL)
474 {
475 if (AliasInfo->Name.Buffer != NULL)
476 SamFreeMemory(AliasInfo->Name.Buffer);
477
478 if (AliasInfo->AdminComment.Buffer != NULL)
479 SamFreeMemory(AliasInfo->AdminComment.Buffer);
480
481 SamFreeMemory(AliasInfo);
482 AliasInfo = NULL;
483 }
484
485 EnumContext->Index++;
486
487 (*entriesread)++;
488
489 // }
490
491 done:
492 if (ApiStatus == NERR_Success && EnumContext->Index < EnumContext->Returned)
493 ApiStatus = ERROR_MORE_DATA;
494
495 if (EnumContext != NULL)
496 *totalentries = EnumContext->Returned;
497
498 if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA)
499 {
500 if (EnumContext != NULL)
501 {
502 if (EnumContext->BuiltinDomainHandle != NULL)
503 SamCloseHandle(EnumContext->BuiltinDomainHandle);
504
505 if (EnumContext->AccountDomainHandle != NULL)
506 SamCloseHandle(EnumContext->AccountDomainHandle);
507
508 if (EnumContext->ServerHandle != NULL)
509 SamCloseHandle(EnumContext->ServerHandle);
510
511 if (EnumContext->Buffer != NULL)
512 {
513 for (i = 0; i < EnumContext->Returned; i++)
514 {
515 SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
516 }
517
518 SamFreeMemory(EnumContext->Buffer);
519 }
520
521 NetApiBufferFree(EnumContext);
522 EnumContext = NULL;
523 }
524 }
525
526 if (AliasHandle != NULL)
527 SamCloseHandle(AliasHandle);
528
529 if (AliasInfo != NULL)
530 {
531 if (AliasInfo->Name.Buffer != NULL)
532 SamFreeMemory(AliasInfo->Name.Buffer);
533
534 if (AliasInfo->AdminComment.Buffer != NULL)
535 SamFreeMemory(AliasInfo->AdminComment.Buffer);
536
537 SamFreeMemory(AliasInfo);
538 }
539
540 if (resumehandle != NULL)
541 *resumehandle = (DWORD_PTR)EnumContext;
542
543 *bufptr = (LPBYTE)Buffer;
544
545 TRACE ("return %lu\n", ApiStatus);
546
547 return ApiStatus;
548 }
549
550 /************************************************************
551 * NetLocalGroupGetInfo (NETAPI32.@)
552 */
553 NET_API_STATUS WINAPI NetLocalGroupGetInfo(
554 LPCWSTR servername,
555 LPCWSTR groupname,
556 DWORD level,
557 LPBYTE* bufptr)
558 {
559 FIXME("(%s %s %d %p) stub!\n", debugstr_w(servername),
560 debugstr_w(groupname), level, bufptr);
561 return NERR_Success;
562 }
563
564 /************************************************************
565 * NetLocalGroupGetMembers (NETAPI32.@)
566 */
567 NET_API_STATUS WINAPI NetLocalGroupGetMembers(
568 LPCWSTR servername,
569 LPCWSTR localgroupname,
570 DWORD level,
571 LPBYTE* bufptr,
572 DWORD prefmaxlen,
573 LPDWORD entriesread,
574 LPDWORD totalentries,
575 PDWORD_PTR resumehandle)
576 {
577 FIXME("(%s %s %d %p %d, %p %p %p) stub!\n", debugstr_w(servername),
578 debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread,
579 totalentries, resumehandle);
580
581 if (level == 3)
582 {
583 WCHAR userName[MAX_COMPUTERNAME_LENGTH + 1];
584 DWORD userNameLen;
585 DWORD len,needlen;
586 PLOCALGROUP_MEMBERS_INFO_3 ptr;
587
588 /* still a stub, current user is belonging to all groups */
589
590 *totalentries = 1;
591 *entriesread = 0;
592
593 userNameLen = MAX_COMPUTERNAME_LENGTH + 1;
594 GetUserNameW(userName,&userNameLen);
595 needlen = sizeof(LOCALGROUP_MEMBERS_INFO_3) +
596 (userNameLen+2) * sizeof(WCHAR);
597 if (prefmaxlen != MAX_PREFERRED_LENGTH)
598 len = min(prefmaxlen,needlen);
599 else
600 len = needlen;
601
602 NetApiBufferAllocate(len, (LPVOID *) bufptr);
603 if (len < needlen)
604 return ERROR_MORE_DATA;
605
606 ptr = (PLOCALGROUP_MEMBERS_INFO_3)*bufptr;
607 ptr->lgrmi3_domainandname = (LPWSTR)(*bufptr+sizeof(LOCALGROUP_MEMBERS_INFO_3));
608 lstrcpyW(ptr->lgrmi3_domainandname,userName);
609
610 *entriesread = 1;
611 }
612
613 return NERR_Success;
614 }
615
616 /************************************************************
617 * NetLocalGroupSetInfo (NETAPI32.@)
618 */
619 NET_API_STATUS WINAPI NetLocalGroupSetInfo(
620 LPCWSTR servername,
621 LPCWSTR groupname,
622 DWORD level,
623 LPBYTE buf,
624 LPDWORD parm_err)
625 {
626 FIXME("(%s %s %d %p %p) stub!\n", debugstr_w(servername),
627 debugstr_w(groupname), level, buf, parm_err);
628 return NERR_Success;
629 }
630
631 /************************************************************
632 * NetLocalGroupSetMember (NETAPI32.@)
633 */
634 NET_API_STATUS WINAPI NetLocalGroupSetMembers(
635 LPCWSTR servername,
636 LPCWSTR groupname,
637 DWORD level,
638 LPBYTE buf,
639 DWORD totalentries)
640 {
641 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
642 debugstr_w(groupname), level, buf, totalentries);
643 return NERR_Success;
644 }