2 * Copyright 2006 Robert Reif
4 * netapi32 local group functions
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.
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.
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
24 #define WIN32_NO_STATUS
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
37 #define NTOS_MODE_USER
38 #include <ndk/rtlfuncs.h>
42 WINE_DEFAULT_DEBUG_CHANNEL(netapi32
);
45 typedef struct _ENUM_CONTEXT
47 SAM_HANDLE ServerHandle
;
48 SAM_HANDLE BuiltinDomainHandle
;
49 SAM_HANDLE AccountDomainHandle
;
51 SAM_ENUMERATE_HANDLE EnumerationContext
;
52 PSAM_RID_ENUMERATION Buffer
;
57 } ENUM_CONTEXT
, *PENUM_CONTEXT
;
59 static SID_IDENTIFIER_AUTHORITY NtAuthority
= {SECURITY_NT_AUTHORITY
};
64 GetAccountDomainSid(PSID
*AccountDomainSid
)
66 PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo
= NULL
;
67 LSA_OBJECT_ATTRIBUTES ObjectAttributes
;
68 LSA_HANDLE PolicyHandle
= NULL
;
72 memset(&ObjectAttributes
, 0, sizeof(LSA_OBJECT_ATTRIBUTES
));
74 Status
= LsaOpenPolicy(NULL
,
76 POLICY_VIEW_LOCAL_INFORMATION
,
78 if (!NT_SUCCESS(Status
))
80 ERR("LsaOpenPolicy failed (Status %08lx)\n", Status
);
84 Status
= LsaQueryInformationPolicy(PolicyHandle
,
85 PolicyAccountDomainInformation
,
86 (PVOID
*)&AccountDomainInfo
);
87 if (!NT_SUCCESS(Status
))
89 ERR("LsaQueryInformationPolicy failed (Status %08lx)\n", Status
);
93 Length
= RtlLengthSid(AccountDomainInfo
->DomainSid
);
95 *AccountDomainSid
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Length
);
96 if (*AccountDomainSid
== NULL
)
98 ERR("Failed to allocate SID\n");
99 Status
= STATUS_INSUFFICIENT_RESOURCES
;
103 memcpy(*AccountDomainSid
, AccountDomainInfo
->DomainSid
, Length
);
106 if (AccountDomainInfo
!= NULL
)
107 LsaFreeMemory(AccountDomainInfo
);
109 LsaClose(PolicyHandle
);
117 GetBuiltinDomainSid(PSID
*BuiltinDomainSid
)
121 NTSTATUS Status
= STATUS_SUCCESS
;
123 *BuiltinDomainSid
= NULL
;
125 Sid
= RtlAllocateHeap(RtlGetProcessHeap(),
127 RtlLengthRequiredSid(1));
129 return STATUS_INSUFFICIENT_RESOURCES
;
131 Status
= RtlInitializeSid(Sid
,
134 if (!NT_SUCCESS(Status
))
137 Ptr
= RtlSubAuthoritySid(Sid
, 0);
138 *Ptr
= SECURITY_BUILTIN_DOMAIN_RID
;
140 *BuiltinDomainSid
= Sid
;
143 if (!NT_SUCCESS(Status
))
146 RtlFreeHeap(RtlGetProcessHeap(), 0, Sid
);
153 /************************************************************
154 * NetLocalGroupAdd (NETAPI32.@)
156 NET_API_STATUS WINAPI
NetLocalGroupAdd(
162 FIXME("(%s %d %p %p) stub!\n", debugstr_w(servername
), level
, buf
,
167 /************************************************************
168 * NetLocalGroupAddMember (NETAPI32.@)
170 NET_API_STATUS WINAPI
NetLocalGroupAddMember(
175 FIXME("(%s %s %p) stub!\n", debugstr_w(servername
),
176 debugstr_w(groupname
), membersid
);
180 /************************************************************
181 * NetLocalGroupAddMembers (NETAPI32.@)
183 NET_API_STATUS WINAPI
NetLocalGroupAddMembers(
190 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
191 debugstr_w(groupname
), level
, buf
, totalentries
);
195 /************************************************************
196 * NetLocalGroupDel (NETAPI32.@)
198 NET_API_STATUS WINAPI
NetLocalGroupDel(
202 FIXME("(%s %s) stub!\n", debugstr_w(servername
), debugstr_w(groupname
));
206 /************************************************************
207 * NetLocalGroupDelMember (NETAPI32.@)
209 NET_API_STATUS WINAPI
NetLocalGroupDelMember(
214 FIXME("(%s %s %p) stub!\n", debugstr_w(servername
),
215 debugstr_w(groupname
), membersid
);
219 /************************************************************
220 * NetLocalGroupDelMembers (NETAPI32.@)
222 NET_API_STATUS WINAPI
NetLocalGroupDelMembers(
229 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
230 debugstr_w(groupname
), level
, buf
, totalentries
);
234 /************************************************************
235 * NetLocalGroupEnum (NETAPI32.@)
237 NET_API_STATUS WINAPI
NetLocalGroupEnum(
243 LPDWORD totalentries
,
244 PDWORD_PTR resumehandle
)
246 PSAM_RID_ENUMERATION CurrentAlias
;
247 PENUM_CONTEXT EnumContext
= NULL
;
248 PSID DomainSid
= NULL
;
250 SAM_HANDLE AliasHandle
= NULL
;
251 PALIAS_GENERAL_INFORMATION AliasInfo
= NULL
;
253 NET_API_STATUS ApiStatus
= NERR_Success
;
254 NTSTATUS Status
= STATUS_SUCCESS
;
257 FIXME("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername
),
258 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resumehandle
);
264 if (resumehandle
!= NULL
&& *resumehandle
!= 0)
266 EnumContext
= (PENUM_CONTEXT
)resumehandle
;
270 ApiStatus
= NetApiBufferAllocate(sizeof(ENUM_CONTEXT
), (PVOID
*)&EnumContext
);
271 if (ApiStatus
!= NERR_Success
)
274 EnumContext
->EnumerationContext
= 0;
275 EnumContext
->Buffer
= NULL
;
276 EnumContext
->Returned
= 0;
277 EnumContext
->Index
= 0;
278 EnumContext
->BuiltinDone
= FALSE
;
280 Status
= SamConnect(NULL
,
281 &EnumContext
->ServerHandle
,
282 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
284 if (!NT_SUCCESS(Status
))
286 ERR("SamConnect failed (Status %08lx)\n", Status
);
287 ApiStatus
= NetpNtStatusToApiStatus(Status
);
291 Status
= GetAccountDomainSid(&DomainSid
);
292 if (!NT_SUCCESS(Status
))
294 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status
);
295 ApiStatus
= NetpNtStatusToApiStatus(Status
);
299 Status
= SamOpenDomain(EnumContext
->ServerHandle
,
300 DOMAIN_LIST_ACCOUNTS
| DOMAIN_LOOKUP
,
302 &EnumContext
->AccountDomainHandle
);
304 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid
);
306 if (!NT_SUCCESS(Status
))
308 ERR("SamOpenDomain failed (Status %08lx)\n", Status
);
309 ApiStatus
= NetpNtStatusToApiStatus(Status
);
313 Status
= GetBuiltinDomainSid(&DomainSid
);
314 if (!NT_SUCCESS(Status
))
316 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status
);
317 ApiStatus
= NetpNtStatusToApiStatus(Status
);
321 Status
= SamOpenDomain(EnumContext
->ServerHandle
,
322 DOMAIN_LIST_ACCOUNTS
| DOMAIN_LOOKUP
,
324 &EnumContext
->BuiltinDomainHandle
);
326 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid
);
328 if (!NT_SUCCESS(Status
))
330 ERR("SamOpenDomain failed (Status %08lx)\n", Status
);
331 ApiStatus
= NetpNtStatusToApiStatus(Status
);
340 if (EnumContext
->Index
>= EnumContext
->Returned
)
342 if (EnumContext
->BuiltinDone
== TRUE
)
344 ApiStatus
= NERR_Success
;
348 TRACE("Calling SamEnumerateAliasesInDomain\n");
350 Status
= SamEnumerateAliasesInDomain(EnumContext
->BuiltinDomainHandle
,
351 &EnumContext
->EnumerationContext
,
352 (PVOID
*)&EnumContext
->Buffer
,
354 &EnumContext
->Returned
);
356 TRACE("SamEnumerateAliasesInDomain returned (Status %08lx)\n", Status
);
357 if (!NT_SUCCESS(Status
))
359 ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status
);
360 ApiStatus
= NetpNtStatusToApiStatus(Status
);
364 if (Status
== STATUS_MORE_ENTRIES
)
366 ApiStatus
= NERR_BufTooSmall
;
371 EnumContext
->BuiltinDone
= TRUE
;
375 TRACE("EnumContext: %lu\n", EnumContext
);
376 TRACE("EnumContext->Returned: %lu\n", EnumContext
->Returned
);
377 TRACE("EnumContext->Buffer: %p\n", EnumContext
->Buffer
);
379 /* Get a pointer to the current alias */
380 CurrentAlias
= &EnumContext
->Buffer
[EnumContext
->Index
];
382 TRACE("RID: %lu\n", CurrentAlias
->RelativeId
);
384 Status
= SamOpenAlias(EnumContext
->BuiltinDomainHandle
,
385 ALIAS_READ_INFORMATION
,
386 CurrentAlias
->RelativeId
,
388 if (!NT_SUCCESS(Status
))
390 ERR("SamOpenAlias failed (Status %08lx)\n", Status
);
391 ApiStatus
= NetpNtStatusToApiStatus(Status
);
395 Status
= SamQueryInformationAlias(AliasHandle
,
396 AliasGeneralInformation
,
397 (PVOID
*)&AliasInfo
);
398 if (!NT_SUCCESS(Status
))
400 ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status
);
401 ApiStatus
= NetpNtStatusToApiStatus(Status
);
405 SamCloseHandle(AliasHandle
);
408 TRACE("Name: %S\n", AliasInfo
->Name
.Buffer
);
409 TRACE("Comment: %S\n", AliasInfo
->AdminComment
.Buffer
);
412 if (AliasInfo
!= NULL
)
414 if (AliasInfo
->Name
.Buffer
!= NULL
)
415 SamFreeMemory(AliasInfo
->Name
.Buffer
);
417 if (AliasInfo
->AdminComment
.Buffer
!= NULL
)
418 SamFreeMemory(AliasInfo
->AdminComment
.Buffer
);
420 SamFreeMemory(AliasInfo
);
425 EnumContext
->Index
++;
430 if (resumehandle
== NULL
|| ApiStatus
!= ERROR_MORE_DATA
)
432 if (EnumContext
!= NULL
)
434 if (EnumContext
->BuiltinDomainHandle
!= NULL
)
435 SamCloseHandle(EnumContext
->BuiltinDomainHandle
);
437 if (EnumContext
->AccountDomainHandle
!= NULL
)
438 SamCloseHandle(EnumContext
->AccountDomainHandle
);
440 if (EnumContext
->ServerHandle
!= NULL
)
441 SamCloseHandle(EnumContext
->ServerHandle
);
443 if (EnumContext
->Buffer
!= NULL
)
445 for (i
= 0; i
< EnumContext
->Returned
; i
++)
447 SamFreeMemory(EnumContext
->Buffer
[i
].Name
.Buffer
);
450 SamFreeMemory(EnumContext
->Buffer
);
453 NetApiBufferFree(EnumContext
);
458 if (AliasHandle
!= NULL
)
459 SamCloseHandle(AliasHandle
);
461 if (AliasInfo
!= NULL
)
463 if (AliasInfo
->Name
.Buffer
!= NULL
)
464 SamFreeMemory(AliasInfo
->Name
.Buffer
);
466 if (AliasInfo
->AdminComment
.Buffer
!= NULL
)
467 SamFreeMemory(AliasInfo
->AdminComment
.Buffer
);
469 SamFreeMemory(AliasInfo
);
472 if (resumehandle
!= NULL
)
473 *resumehandle
= (DWORD_PTR
)EnumContext
;
478 /************************************************************
479 * NetLocalGroupGetInfo (NETAPI32.@)
481 NET_API_STATUS WINAPI
NetLocalGroupGetInfo(
487 FIXME("(%s %s %d %p) stub!\n", debugstr_w(servername
),
488 debugstr_w(groupname
), level
, bufptr
);
492 /************************************************************
493 * NetLocalGroupGetMembers (NETAPI32.@)
495 NET_API_STATUS WINAPI
NetLocalGroupGetMembers(
497 LPCWSTR localgroupname
,
502 LPDWORD totalentries
,
503 PDWORD_PTR resumehandle
)
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
);
511 WCHAR userName
[MAX_COMPUTERNAME_LENGTH
+ 1];
514 PLOCALGROUP_MEMBERS_INFO_3 ptr
;
516 /* still a stub, current user is belonging to all groups */
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
);
530 NetApiBufferAllocate(len
, (LPVOID
*) bufptr
);
532 return ERROR_MORE_DATA
;
534 ptr
= (PLOCALGROUP_MEMBERS_INFO_3
)*bufptr
;
535 ptr
->lgrmi3_domainandname
= (LPWSTR
)(*bufptr
+sizeof(LOCALGROUP_MEMBERS_INFO_3
));
536 lstrcpyW(ptr
->lgrmi3_domainandname
,userName
);
544 /************************************************************
545 * NetLocalGroupSetInfo (NETAPI32.@)
547 NET_API_STATUS WINAPI
NetLocalGroupSetInfo(
554 FIXME("(%s %s %d %p %p) stub!\n", debugstr_w(servername
),
555 debugstr_w(groupname
), level
, buf
, parm_err
);
559 /************************************************************
560 * NetLocalGroupSetMember (NETAPI32.@)
562 NET_API_STATUS WINAPI
NetLocalGroupSetMembers(
569 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
570 debugstr_w(groupname
), level
, buf
, totalentries
);