[Win32k]
[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 ULONG i;
250 SAM_HANDLE AliasHandle = NULL;
251 PALIAS_GENERAL_INFORMATION AliasInfo = NULL;
252
253 NET_API_STATUS ApiStatus = NERR_Success;
254 NTSTATUS Status = STATUS_SUCCESS;
255
256
257 FIXME("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername),
258 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
259
260 *entriesread = 0;
261 *totalentries = 0;
262 *bufptr = NULL;
263
264 if (resumehandle != NULL && *resumehandle != 0)
265 {
266 EnumContext = (PENUM_CONTEXT)resumehandle;
267 }
268 else
269 {
270 ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
271 if (ApiStatus != NERR_Success)
272 goto done;
273
274 EnumContext->EnumerationContext = 0;
275 EnumContext->Buffer = NULL;
276 EnumContext->Returned = 0;
277 EnumContext->Index = 0;
278 EnumContext->BuiltinDone = FALSE;
279
280 Status = SamConnect(NULL,
281 &EnumContext->ServerHandle,
282 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
283 NULL);
284 if (!NT_SUCCESS(Status))
285 {
286 ERR("SamConnect failed (Status %08lx)\n", Status);
287 ApiStatus = NetpNtStatusToApiStatus(Status);
288 goto done;
289 }
290
291 Status = GetAccountDomainSid(&DomainSid);
292 if (!NT_SUCCESS(Status))
293 {
294 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
295 ApiStatus = NetpNtStatusToApiStatus(Status);
296 goto done;
297 }
298
299 Status = SamOpenDomain(EnumContext->ServerHandle,
300 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
301 DomainSid,
302 &EnumContext->AccountDomainHandle);
303
304 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
305
306 if (!NT_SUCCESS(Status))
307 {
308 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
309 ApiStatus = NetpNtStatusToApiStatus(Status);
310 goto done;
311 }
312
313 Status = GetBuiltinDomainSid(&DomainSid);
314 if (!NT_SUCCESS(Status))
315 {
316 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
317 ApiStatus = NetpNtStatusToApiStatus(Status);
318 goto done;
319 }
320
321 Status = SamOpenDomain(EnumContext->ServerHandle,
322 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
323 DomainSid,
324 &EnumContext->BuiltinDomainHandle);
325
326 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
327
328 if (!NT_SUCCESS(Status))
329 {
330 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
331 ApiStatus = NetpNtStatusToApiStatus(Status);
332 goto done;
333 }
334 }
335
336
337 while (TRUE)
338 {
339
340 if (EnumContext->Index >= EnumContext->Returned)
341 {
342 if (EnumContext->BuiltinDone == TRUE)
343 {
344 ApiStatus = NERR_Success;
345 goto done;
346 }
347
348 TRACE("Calling SamEnumerateAliasesInDomain\n");
349
350 Status = SamEnumerateAliasesInDomain(EnumContext->BuiltinDomainHandle,
351 &EnumContext->EnumerationContext,
352 (PVOID *)&EnumContext->Buffer,
353 prefmaxlen,
354 &EnumContext->Returned);
355
356 TRACE("SamEnumerateAliasesInDomain returned (Status %08lx)\n", Status);
357 if (!NT_SUCCESS(Status))
358 {
359 ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status);
360 ApiStatus = NetpNtStatusToApiStatus(Status);
361 goto done;
362 }
363
364 if (Status == STATUS_MORE_ENTRIES)
365 {
366 ApiStatus = NERR_BufTooSmall;
367 goto done;
368 }
369 else
370 {
371 EnumContext->BuiltinDone = TRUE;
372 }
373 }
374
375 TRACE("EnumContext: %lu\n", EnumContext);
376 TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
377 TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
378
379 /* Get a pointer to the current alias */
380 CurrentAlias = &EnumContext->Buffer[EnumContext->Index];
381
382 TRACE("RID: %lu\n", CurrentAlias->RelativeId);
383
384 Status = SamOpenAlias(EnumContext->BuiltinDomainHandle,
385 ALIAS_READ_INFORMATION,
386 CurrentAlias->RelativeId,
387 &AliasHandle);
388 if (!NT_SUCCESS(Status))
389 {
390 ERR("SamOpenAlias failed (Status %08lx)\n", Status);
391 ApiStatus = NetpNtStatusToApiStatus(Status);
392 goto done;
393 }
394
395 Status = SamQueryInformationAlias(AliasHandle,
396 AliasGeneralInformation,
397 (PVOID *)&AliasInfo);
398 if (!NT_SUCCESS(Status))
399 {
400 ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status);
401 ApiStatus = NetpNtStatusToApiStatus(Status);
402 goto done;
403 }
404
405 SamCloseHandle(AliasHandle);
406 AliasHandle = NULL;
407
408 TRACE("Name: %S\n", AliasInfo->Name.Buffer);
409 TRACE("Comment: %S\n", AliasInfo->AdminComment.Buffer);
410
411
412 if (AliasInfo != NULL)
413 {
414 if (AliasInfo->Name.Buffer != NULL)
415 SamFreeMemory(AliasInfo->Name.Buffer);
416
417 if (AliasInfo->AdminComment.Buffer != NULL)
418 SamFreeMemory(AliasInfo->AdminComment.Buffer);
419
420 SamFreeMemory(AliasInfo);
421 AliasInfo = NULL;
422 }
423
424
425 EnumContext->Index++;
426 }
427
428
429 done:
430 if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA)
431 {
432 if (EnumContext != NULL)
433 {
434 if (EnumContext->BuiltinDomainHandle != NULL)
435 SamCloseHandle(EnumContext->BuiltinDomainHandle);
436
437 if (EnumContext->AccountDomainHandle != NULL)
438 SamCloseHandle(EnumContext->AccountDomainHandle);
439
440 if (EnumContext->ServerHandle != NULL)
441 SamCloseHandle(EnumContext->ServerHandle);
442
443 if (EnumContext->Buffer != NULL)
444 {
445 for (i = 0; i < EnumContext->Returned; i++)
446 {
447 SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
448 }
449
450 SamFreeMemory(EnumContext->Buffer);
451 }
452
453 NetApiBufferFree(EnumContext);
454 EnumContext = NULL;
455 }
456 }
457
458 if (AliasHandle != NULL)
459 SamCloseHandle(AliasHandle);
460
461 if (AliasInfo != NULL)
462 {
463 if (AliasInfo->Name.Buffer != NULL)
464 SamFreeMemory(AliasInfo->Name.Buffer);
465
466 if (AliasInfo->AdminComment.Buffer != NULL)
467 SamFreeMemory(AliasInfo->AdminComment.Buffer);
468
469 SamFreeMemory(AliasInfo);
470 }
471
472 if (resumehandle != NULL)
473 *resumehandle = (DWORD_PTR)EnumContext;
474
475 return ApiStatus;
476 }
477
478 /************************************************************
479 * NetLocalGroupGetInfo (NETAPI32.@)
480 */
481 NET_API_STATUS WINAPI NetLocalGroupGetInfo(
482 LPCWSTR servername,
483 LPCWSTR groupname,
484 DWORD level,
485 LPBYTE* bufptr)
486 {
487 FIXME("(%s %s %d %p) stub!\n", debugstr_w(servername),
488 debugstr_w(groupname), level, bufptr);
489 return NERR_Success;
490 }
491
492 /************************************************************
493 * NetLocalGroupGetMembers (NETAPI32.@)
494 */
495 NET_API_STATUS WINAPI NetLocalGroupGetMembers(
496 LPCWSTR servername,
497 LPCWSTR localgroupname,
498 DWORD level,
499 LPBYTE* bufptr,
500 DWORD prefmaxlen,
501 LPDWORD entriesread,
502 LPDWORD totalentries,
503 PDWORD_PTR resumehandle)
504 {
505 FIXME("(%s %s %d %p %d, %p %p %p) stub!\n", debugstr_w(servername),
506 debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread,
507 totalentries, resumehandle);
508
509 if (level == 3)
510 {
511 WCHAR userName[MAX_COMPUTERNAME_LENGTH + 1];
512 DWORD userNameLen;
513 DWORD len,needlen;
514 PLOCALGROUP_MEMBERS_INFO_3 ptr;
515
516 /* still a stub, current user is belonging to all groups */
517
518 *totalentries = 1;
519 *entriesread = 0;
520
521 userNameLen = MAX_COMPUTERNAME_LENGTH + 1;
522 GetUserNameW(userName,&userNameLen);
523 needlen = sizeof(LOCALGROUP_MEMBERS_INFO_3) +
524 (userNameLen+2) * sizeof(WCHAR);
525 if (prefmaxlen != MAX_PREFERRED_LENGTH)
526 len = min(prefmaxlen,needlen);
527 else
528 len = needlen;
529
530 NetApiBufferAllocate(len, (LPVOID *) bufptr);
531 if (len < needlen)
532 return ERROR_MORE_DATA;
533
534 ptr = (PLOCALGROUP_MEMBERS_INFO_3)*bufptr;
535 ptr->lgrmi3_domainandname = (LPWSTR)(*bufptr+sizeof(LOCALGROUP_MEMBERS_INFO_3));
536 lstrcpyW(ptr->lgrmi3_domainandname,userName);
537
538 *entriesread = 1;
539 }
540
541 return NERR_Success;
542 }
543
544 /************************************************************
545 * NetLocalGroupSetInfo (NETAPI32.@)
546 */
547 NET_API_STATUS WINAPI NetLocalGroupSetInfo(
548 LPCWSTR servername,
549 LPCWSTR groupname,
550 DWORD level,
551 LPBYTE buf,
552 LPDWORD parm_err)
553 {
554 FIXME("(%s %s %d %p %p) stub!\n", debugstr_w(servername),
555 debugstr_w(groupname), level, buf, parm_err);
556 return NERR_Success;
557 }
558
559 /************************************************************
560 * NetLocalGroupSetMember (NETAPI32.@)
561 */
562 NET_API_STATUS WINAPI NetLocalGroupSetMembers(
563 LPCWSTR servername,
564 LPCWSTR groupname,
565 DWORD level,
566 LPBYTE buf,
567 DWORD totalentries)
568 {
569 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
570 debugstr_w(groupname), level, buf, totalentries);
571 return NERR_Success;
572 }