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
;
60 /************************************************************
61 * NetLocalGroupAdd (NETAPI32.@)
63 NET_API_STATUS WINAPI
NetLocalGroupAdd(
69 FIXME("(%s %d %p %p) stub!\n", debugstr_w(servername
), level
, buf
,
74 /************************************************************
75 * NetLocalGroupAddMember (NETAPI32.@)
77 NET_API_STATUS WINAPI
NetLocalGroupAddMember(
82 FIXME("(%s %s %p) stub!\n", debugstr_w(servername
),
83 debugstr_w(groupname
), membersid
);
87 /************************************************************
88 * NetLocalGroupAddMembers (NETAPI32.@)
90 NET_API_STATUS WINAPI
NetLocalGroupAddMembers(
97 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
98 debugstr_w(groupname
), level
, buf
, totalentries
);
102 /************************************************************
103 * NetLocalGroupDel (NETAPI32.@)
105 NET_API_STATUS WINAPI
NetLocalGroupDel(
109 FIXME("(%s %s) stub!\n", debugstr_w(servername
), debugstr_w(groupname
));
113 /************************************************************
114 * NetLocalGroupDelMember (NETAPI32.@)
116 NET_API_STATUS WINAPI
NetLocalGroupDelMember(
121 FIXME("(%s %s %p) stub!\n", debugstr_w(servername
),
122 debugstr_w(groupname
), membersid
);
126 /************************************************************
127 * NetLocalGroupDelMembers (NETAPI32.@)
129 NET_API_STATUS WINAPI
NetLocalGroupDelMembers(
136 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
137 debugstr_w(groupname
), level
, buf
, totalentries
);
141 /************************************************************
142 * NetLocalGroupEnum (NETAPI32.@)
144 NET_API_STATUS WINAPI
NetLocalGroupEnum(
150 LPDWORD totalentries
,
151 PDWORD_PTR resumehandle
)
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
;
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
;
168 FIXME("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername
),
169 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resumehandle
);
175 if (servername
!= NULL
)
176 RtlInitUnicodeString(&ServerName
, servername
);
178 if (resumehandle
!= NULL
&& *resumehandle
!= 0)
180 EnumContext
= (PENUM_CONTEXT
)*resumehandle
;
184 ApiStatus
= NetApiBufferAllocate(sizeof(ENUM_CONTEXT
), (PVOID
*)&EnumContext
);
185 if (ApiStatus
!= NERR_Success
)
188 EnumContext
->EnumerationContext
= 0;
189 EnumContext
->Buffer
= NULL
;
190 EnumContext
->Returned
= 0;
191 EnumContext
->Index
= 0;
192 EnumContext
->BuiltinDone
= FALSE
;
194 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
195 &EnumContext
->ServerHandle
,
196 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
198 if (!NT_SUCCESS(Status
))
200 ERR("SamConnect failed (Status %08lx)\n", Status
);
201 ApiStatus
= NetpNtStatusToApiStatus(Status
);
205 Status
= GetAccountDomainSid((servername
!= NULL
) ? &ServerName
: NULL
,
207 if (!NT_SUCCESS(Status
))
209 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status
);
210 ApiStatus
= NetpNtStatusToApiStatus(Status
);
214 Status
= SamOpenDomain(EnumContext
->ServerHandle
,
215 DOMAIN_LIST_ACCOUNTS
| DOMAIN_LOOKUP
,
217 &EnumContext
->AccountDomainHandle
);
219 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid
);
221 if (!NT_SUCCESS(Status
))
223 ERR("SamOpenDomain failed (Status %08lx)\n", Status
);
224 ApiStatus
= NetpNtStatusToApiStatus(Status
);
228 Status
= GetBuiltinDomainSid(&DomainSid
);
229 if (!NT_SUCCESS(Status
))
231 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status
);
232 ApiStatus
= NetpNtStatusToApiStatus(Status
);
236 Status
= SamOpenDomain(EnumContext
->ServerHandle
,
237 DOMAIN_LIST_ACCOUNTS
| DOMAIN_LOOKUP
,
239 &EnumContext
->BuiltinDomainHandle
);
241 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid
);
243 if (!NT_SUCCESS(Status
))
245 ERR("SamOpenDomain failed (Status %08lx)\n", Status
);
246 ApiStatus
= NetpNtStatusToApiStatus(Status
);
254 TRACE("EnumContext->Index: %lu\n", EnumContext
->Index
);
255 TRACE("EnumContext->Returned: %lu\n", EnumContext
->Returned
);
257 if (EnumContext
->Index
>= EnumContext
->Returned
)
259 // if (EnumContext->BuiltinDone == TRUE)
261 // ApiStatus = NERR_Success;
265 TRACE("Calling SamEnumerateAliasesInDomain\n");
267 Status
= SamEnumerateAliasesInDomain(EnumContext
->BuiltinDomainHandle
,
268 &EnumContext
->EnumerationContext
,
269 (PVOID
*)&EnumContext
->Buffer
,
271 &EnumContext
->Returned
);
273 TRACE("SamEnumerateAliasesInDomain returned (Status %08lx)\n", Status
);
274 if (!NT_SUCCESS(Status
))
276 ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status
);
277 ApiStatus
= NetpNtStatusToApiStatus(Status
);
281 if (Status
== STATUS_MORE_ENTRIES
)
283 ApiStatus
= NERR_BufTooSmall
;
288 EnumContext
->BuiltinDone
= TRUE
;
292 TRACE("EnumContext: %lu\n", EnumContext
);
293 TRACE("EnumContext->Returned: %lu\n", EnumContext
->Returned
);
294 TRACE("EnumContext->Buffer: %p\n", EnumContext
->Buffer
);
296 /* Get a pointer to the current alias */
297 CurrentAlias
= &EnumContext
->Buffer
[EnumContext
->Index
];
299 TRACE("RID: %lu\n", CurrentAlias
->RelativeId
);
301 Status
= SamOpenAlias(EnumContext
->BuiltinDomainHandle
,
302 ALIAS_READ_INFORMATION
,
303 CurrentAlias
->RelativeId
,
305 if (!NT_SUCCESS(Status
))
307 ERR("SamOpenAlias failed (Status %08lx)\n", Status
);
308 ApiStatus
= NetpNtStatusToApiStatus(Status
);
312 Status
= SamQueryInformationAlias(AliasHandle
,
313 AliasGeneralInformation
,
314 (PVOID
*)&AliasInfo
);
315 if (!NT_SUCCESS(Status
))
317 ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status
);
318 ApiStatus
= NetpNtStatusToApiStatus(Status
);
322 SamCloseHandle(AliasHandle
);
325 TRACE("Name: %S\n", AliasInfo
->Name
.Buffer
);
326 TRACE("Comment: %S\n", AliasInfo
->AdminComment
.Buffer
);
331 Size
= sizeof(LOCALGROUP_INFO_0
) +
332 AliasInfo
->Name
.Length
+ sizeof(WCHAR
);
336 Size
= sizeof(LOCALGROUP_INFO_1
) +
337 AliasInfo
->Name
.Length
+ sizeof(WCHAR
) +
338 AliasInfo
->AdminComment
.Length
+ sizeof(WCHAR
);
342 ApiStatus
= ERROR_INVALID_LEVEL
;
346 ApiStatus
= NetApiBufferAllocate(Size
, &Buffer
);
347 if (ApiStatus
!= NERR_Success
)
353 LocalInfo0
= (PLOCALGROUP_INFO_0
)Buffer
;
355 Ptr
= (LPWSTR
)LocalInfo0
++;
356 LocalInfo0
->lgrpi0_name
= Ptr
;
358 memcpy(LocalInfo0
->lgrpi0_name
,
359 AliasInfo
->Name
.Buffer
,
360 AliasInfo
->Name
.Length
);
361 LocalInfo0
->lgrpi0_name
[AliasInfo
->Name
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
365 LocalInfo1
= (PLOCALGROUP_INFO_1
)Buffer
;
367 Ptr
= (LPWSTR
)((ULONG_PTR
)LocalInfo1
+ sizeof(LOCALGROUP_INFO_1
));
368 LocalInfo1
->lgrpi1_name
= Ptr
;
370 memcpy(LocalInfo1
->lgrpi1_name
,
371 AliasInfo
->Name
.Buffer
,
372 AliasInfo
->Name
.Length
);
373 LocalInfo1
->lgrpi1_name
[AliasInfo
->Name
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
375 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ AliasInfo
->Name
.Length
+ sizeof(WCHAR
));
376 LocalInfo1
->lgrpi1_comment
= Ptr
;
378 memcpy(LocalInfo1
->lgrpi1_comment
,
379 AliasInfo
->AdminComment
.Buffer
,
380 AliasInfo
->AdminComment
.Length
);
381 LocalInfo1
->lgrpi1_comment
[AliasInfo
->AdminComment
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
385 if (AliasInfo
!= NULL
)
387 if (AliasInfo
->Name
.Buffer
!= NULL
)
388 SamFreeMemory(AliasInfo
->Name
.Buffer
);
390 if (AliasInfo
->AdminComment
.Buffer
!= NULL
)
391 SamFreeMemory(AliasInfo
->AdminComment
.Buffer
);
393 SamFreeMemory(AliasInfo
);
397 EnumContext
->Index
++;
404 if (ApiStatus
== NERR_Success
&& EnumContext
->Index
< EnumContext
->Returned
)
405 ApiStatus
= ERROR_MORE_DATA
;
407 if (EnumContext
!= NULL
)
408 *totalentries
= EnumContext
->Returned
;
410 if (resumehandle
== NULL
|| ApiStatus
!= ERROR_MORE_DATA
)
412 if (EnumContext
!= NULL
)
414 if (EnumContext
->BuiltinDomainHandle
!= NULL
)
415 SamCloseHandle(EnumContext
->BuiltinDomainHandle
);
417 if (EnumContext
->AccountDomainHandle
!= NULL
)
418 SamCloseHandle(EnumContext
->AccountDomainHandle
);
420 if (EnumContext
->ServerHandle
!= NULL
)
421 SamCloseHandle(EnumContext
->ServerHandle
);
423 if (EnumContext
->Buffer
!= NULL
)
425 for (i
= 0; i
< EnumContext
->Returned
; i
++)
427 SamFreeMemory(EnumContext
->Buffer
[i
].Name
.Buffer
);
430 SamFreeMemory(EnumContext
->Buffer
);
433 NetApiBufferFree(EnumContext
);
438 if (AliasHandle
!= NULL
)
439 SamCloseHandle(AliasHandle
);
441 if (AliasInfo
!= NULL
)
443 if (AliasInfo
->Name
.Buffer
!= NULL
)
444 SamFreeMemory(AliasInfo
->Name
.Buffer
);
446 if (AliasInfo
->AdminComment
.Buffer
!= NULL
)
447 SamFreeMemory(AliasInfo
->AdminComment
.Buffer
);
449 SamFreeMemory(AliasInfo
);
452 if (resumehandle
!= NULL
)
453 *resumehandle
= (DWORD_PTR
)EnumContext
;
455 *bufptr
= (LPBYTE
)Buffer
;
457 TRACE ("return %lu\n", ApiStatus
);
462 /************************************************************
463 * NetLocalGroupGetInfo (NETAPI32.@)
465 NET_API_STATUS WINAPI
NetLocalGroupGetInfo(
471 FIXME("(%s %s %d %p) stub!\n", debugstr_w(servername
),
472 debugstr_w(groupname
), level
, bufptr
);
476 /************************************************************
477 * NetLocalGroupGetMembers (NETAPI32.@)
479 NET_API_STATUS WINAPI
NetLocalGroupGetMembers(
481 LPCWSTR localgroupname
,
486 LPDWORD totalentries
,
487 PDWORD_PTR resumehandle
)
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
);
495 WCHAR userName
[MAX_COMPUTERNAME_LENGTH
+ 1];
498 PLOCALGROUP_MEMBERS_INFO_3 ptr
;
500 /* still a stub, current user is belonging to all groups */
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
);
514 NetApiBufferAllocate(len
, (LPVOID
*) bufptr
);
516 return ERROR_MORE_DATA
;
518 ptr
= (PLOCALGROUP_MEMBERS_INFO_3
)*bufptr
;
519 ptr
->lgrmi3_domainandname
= (LPWSTR
)(*bufptr
+sizeof(LOCALGROUP_MEMBERS_INFO_3
));
520 lstrcpyW(ptr
->lgrmi3_domainandname
,userName
);
528 /************************************************************
529 * NetLocalGroupSetInfo (NETAPI32.@)
531 NET_API_STATUS WINAPI
NetLocalGroupSetInfo(
538 FIXME("(%s %s %d %p %p) stub!\n", debugstr_w(servername
),
539 debugstr_w(groupname
), level
, buf
, parm_err
);
543 /************************************************************
544 * NetLocalGroupSetMember (NETAPI32.@)
546 NET_API_STATUS WINAPI
NetLocalGroupSetMembers(
553 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
554 debugstr_w(groupname
), level
, buf
, totalentries
);