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