1 /* Copyright 2001 Mike McCormack
2 * Copyright 2002 Andriy Palamarchuk
3 * Copyright 2003 Juan Lang
4 * Copyright 2005,2006 Paul Vriens
5 * Copyright 2006 Robert Reif
6 * Copyright 2013 Hans Leidekker for CodeWeavers
7 * Copyright 2020 Dmitry Timoshkov
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #define WIN32_NO_STATUS
48 #include "wine/debug.h"
49 #include "wine/list.h"
54 WINE_DEFAULT_DEBUG_CHANNEL(netapi32
);
56 DEFINE_GUID(GUID_NULL
,0,0,0,0,0,0,0,0,0,0,0);
58 static HINSTANCE netapi32_instance
;
60 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
62 static const struct samba_funcs
*samba_funcs
;
64 static BOOL WINAPI
load_samba( INIT_ONCE
*once
, void *param
, void **context
)
66 __wine_init_unix_lib( netapi32_instance
, DLL_PROCESS_ATTACH
, NULL
, &samba_funcs
);
70 static BOOL
samba_init(void)
72 return InitOnceExecuteOnce( &init_once
, load_samba
, NULL
, NULL
) && samba_funcs
;
75 /************************************************************
76 * NETAPI_IsLocalComputer
78 * Checks whether the server name indicates local machine.
80 static BOOL
NETAPI_IsLocalComputer( LMCSTR name
)
82 WCHAR buf
[MAX_COMPUTERNAME_LENGTH
+ 1];
83 DWORD size
= ARRAY_SIZE(buf
);
86 if (!name
|| !name
[0]) return TRUE
;
88 ret
= GetComputerNameW( buf
, &size
);
89 if (ret
&& name
[0] == '\\' && name
[1] == '\\') name
+= 2;
90 return ret
&& !wcsicmp( name
, buf
);
93 BOOL WINAPI
DllMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
95 TRACE("%p,%x,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
98 case DLL_PROCESS_ATTACH
:
99 netapi32_instance
= hinstDLL
;
100 DisableThreadLibraryCalls(hinstDLL
);
104 case DLL_PROCESS_DETACH
:
105 if (lpvReserved
) break;
113 /************************************************************
114 * NetServerEnum (NETAPI32.@)
116 NET_API_STATUS WINAPI
NetServerEnum(
122 LPDWORD totalentries
,
125 LPDWORD resume_handle
128 FIXME("Stub (%s %d %p %d %p %p %d %s %p)\n", debugstr_w(servername
),
129 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, servertype
,
130 debugstr_w(domain
), resume_handle
);
132 return ERROR_NO_BROWSER_SERVERS_FOUND
;
135 /************************************************************
136 * NetServerEnumEx (NETAPI32.@)
138 NET_API_STATUS WINAPI
NetServerEnumEx(
144 LPDWORD totalentries
,
147 LMCSTR FirstNameToReturn
)
149 FIXME("Stub (%s %d %p %d %p %p %d %s %s)\n",
150 debugstr_w(ServerName
), Level
, Bufptr
, PrefMaxlen
, EntriesRead
, totalentries
,
151 servertype
, debugstr_w(domain
), debugstr_w(FirstNameToReturn
));
153 return ERROR_NO_BROWSER_SERVERS_FOUND
;
156 /************************************************************
157 * NetServerDiskEnum (NETAPI32.@)
159 NET_API_STATUS WINAPI
NetServerDiskEnum(
165 LPDWORD totalentries
,
166 LPDWORD Resume_Handle
)
168 FIXME("Stub (%s %d %p %d %p %p %p)\n", debugstr_w(ServerName
),
169 Level
, Bufptr
, PrefMaxlen
, EntriesRead
, totalentries
, Resume_Handle
);
171 return ERROR_NO_BROWSER_SERVERS_FOUND
;
174 /************************************************************
175 * NetServerGetInfo (NETAPI32.@)
177 NET_API_STATUS WINAPI
NetServerGetInfo(LMSTR servername
, DWORD level
, LPBYTE
* bufptr
)
180 BOOL local
= NETAPI_IsLocalComputer( servername
);
182 TRACE("%s %d %p\n", debugstr_w( servername
), level
, bufptr
);
192 if (!(*bufptr
= malloc( size
))) return ERROR_OUTOFMEMORY
;
193 ret
= samba_funcs
->server_getinfo( servername
, level
, *bufptr
, &size
);
194 if (ret
) free( *bufptr
);
195 if (ret
!= ERROR_INSUFFICIENT_BUFFER
) return ret
;
198 FIXME( "remote computers not supported\n" );
199 return ERROR_INVALID_LEVEL
;
201 if (!bufptr
) return ERROR_INVALID_PARAMETER
;
208 DWORD computerNameLen
, size
;
209 WCHAR computerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
211 computerNameLen
= MAX_COMPUTERNAME_LENGTH
+ 1;
212 GetComputerNameW(computerName
, &computerNameLen
);
213 computerNameLen
++; /* include NULL terminator */
215 /* Plus 1 for empty comment */
216 size
= sizeof(SERVER_INFO_101
) + (computerNameLen
+ 1) * sizeof(WCHAR
);
217 ret
= NetApiBufferAllocate(size
, (LPVOID
*)bufptr
);
218 if (ret
== NERR_Success
)
220 /* INFO_100 structure is a subset of INFO_101 */
221 PSERVER_INFO_101 info
= (PSERVER_INFO_101
)*bufptr
;
222 OSVERSIONINFOW verInfo
;
224 info
->sv101_platform_id
= PLATFORM_ID_NT
;
225 info
->sv101_name
= (LMSTR
)(*bufptr
+ sizeof(SERVER_INFO_101
));
226 memcpy(info
->sv101_name
, computerName
,
227 computerNameLen
* sizeof(WCHAR
));
228 verInfo
.dwOSVersionInfoSize
= sizeof(verInfo
);
229 GetVersionExW(&verInfo
);
230 info
->sv101_version_major
= verInfo
.dwMajorVersion
;
231 info
->sv101_version_minor
= verInfo
.dwMinorVersion
;
232 /* Use generic type as no wine equivalent of DC / Server */
233 info
->sv101_type
= SV_TYPE_NT
;
234 info
->sv101_comment
= (LMSTR
)(*bufptr
+ sizeof(SERVER_INFO_101
)
235 + computerNameLen
* sizeof(WCHAR
));
236 info
->sv101_comment
[0] = '\0';
242 FIXME("level %d unimplemented\n", level
);
243 ret
= ERROR_INVALID_LEVEL
;
249 /************************************************************
250 * NetStatisticsGet (NETAPI32.@)
252 NET_API_STATUS WINAPI
NetStatisticsGet(LMSTR server
, LMSTR service
,
253 DWORD level
, DWORD options
,
259 STAT_WORKSTATION_0 workst
;
260 STAT_SERVER_0 server
;
264 TRACE("(server %s, service %s, level %d, options %d, buffer %p): stub\n",
265 debugstr_w(server
), debugstr_w(service
), level
, options
, bufptr
);
267 res
= NetApiBufferAllocate(sizeof(*stat
), &dataptr
);
268 if (res
!= NERR_Success
) return res
;
270 res
= NERR_InternalError
;
275 if (!wcscmp( service
, L
"Lanman Workstation" ))
277 /* Fill the struct STAT_WORKSTATION_0 properly */
278 memset(&stat
->workst
, 0, sizeof(stat
->workst
));
281 else if (!wcscmp( service
, L
"Lanman Server" ))
283 /* Fill the struct STAT_SERVER_0 properly */
284 memset(&stat
->server
, 0, sizeof(stat
->server
));
289 if (res
!= NERR_Success
)
290 NetApiBufferFree(dataptr
);
297 NET_API_STATUS WINAPI
NetUseEnum(LMSTR server
, DWORD level
, LPBYTE
* bufptr
, DWORD prefmaxsize
,
298 LPDWORD entriesread
, LPDWORD totalentries
, LPDWORD resumehandle
)
300 FIXME("stub (%p, %d, %p, %d, %p, %p, %p)\n", server
, level
, bufptr
, prefmaxsize
,
301 entriesread
, totalentries
, resumehandle
);
302 return ERROR_NOT_SUPPORTED
;
305 NET_API_STATUS WINAPI
NetScheduleJobAdd(LPCWSTR server
, LPBYTE bufptr
, LPDWORD jobid
)
307 TRACE("(%s, %p, %p)\n", debugstr_w(server
), bufptr
, jobid
);
308 return NetrJobAdd(server
, (AT_INFO
*)bufptr
, jobid
);
311 NET_API_STATUS WINAPI
NetScheduleJobDel(LPCWSTR server
, DWORD minjobid
, DWORD maxjobid
)
313 TRACE("(%s, %u, %u)\n", debugstr_w(server
), minjobid
, maxjobid
);
314 return NetrJobDel(server
, minjobid
, maxjobid
);
317 NET_API_STATUS WINAPI
NetScheduleJobEnum(LPCWSTR server
, LPBYTE
* bufptr
, DWORD prefmaxsize
, LPDWORD entriesread
,
318 LPDWORD totalentries
, LPDWORD resumehandle
)
320 AT_ENUM_CONTAINER container
;
323 TRACE("(%s, %p, %u, %p, %p, %p)\n", debugstr_w(server
), bufptr
, prefmaxsize
, entriesread
, totalentries
, resumehandle
);
325 container
.EntriesRead
= 0;
326 container
.Buffer
= NULL
;
327 ret
= NetrJobEnum(server
, &container
, prefmaxsize
, totalentries
, resumehandle
);
328 if (ret
== ERROR_SUCCESS
)
330 *bufptr
= (LPBYTE
)container
.Buffer
;
331 *entriesread
= container
.EntriesRead
;
336 NET_API_STATUS WINAPI
NetScheduleJobGetInfo(LPCWSTR server
, DWORD jobid
, LPBYTE
*bufptr
)
338 TRACE("(%s, %u, %p)\n", debugstr_w(server
), jobid
, bufptr
);
339 return NetrJobGetInfo(server
, jobid
, (LPAT_INFO
*)bufptr
);
342 NET_API_STATUS WINAPI
NetUseGetInfo(LMSTR server
, LMSTR name
, DWORD level
, LPBYTE
*bufptr
)
344 FIXME("stub (%p, %p, %d, %p)\n", server
, name
, level
, bufptr
);
345 return ERROR_NOT_SUPPORTED
;
349 /************************************************************
350 * NetApiBufferAllocate (NETAPI32.@)
352 NET_API_STATUS WINAPI
NetApiBufferAllocate(DWORD ByteCount
, LPVOID
* Buffer
)
354 TRACE("(%d, %p)\n", ByteCount
, Buffer
);
356 if (Buffer
== NULL
) return ERROR_INVALID_PARAMETER
;
357 *Buffer
= HeapAlloc(GetProcessHeap(), 0, ByteCount
);
361 return GetLastError();
364 /************************************************************
365 * NetApiBufferFree (NETAPI32.@)
367 NET_API_STATUS WINAPI
NetApiBufferFree(LPVOID Buffer
)
369 TRACE("(%p)\n", Buffer
);
370 MIDL_user_free(Buffer
);
374 /************************************************************
375 * NetApiBufferReallocate (NETAPI32.@)
377 NET_API_STATUS WINAPI
NetApiBufferReallocate(LPVOID OldBuffer
, DWORD NewByteCount
,
380 TRACE("(%p, %d, %p)\n", OldBuffer
, NewByteCount
, NewBuffer
);
384 *NewBuffer
= HeapReAlloc(GetProcessHeap(), 0, OldBuffer
, NewByteCount
);
386 *NewBuffer
= HeapAlloc(GetProcessHeap(), 0, NewByteCount
);
387 return *NewBuffer
? NERR_Success
: GetLastError();
391 if (!HeapFree(GetProcessHeap(), 0, OldBuffer
)) return GetLastError();
397 /************************************************************
398 * NetApiBufferSize (NETAPI32.@)
400 NET_API_STATUS WINAPI
NetApiBufferSize(LPVOID Buffer
, LPDWORD ByteCount
)
404 TRACE("(%p, %p)\n", Buffer
, ByteCount
);
406 return ERROR_INVALID_PARAMETER
;
407 dw
= HeapSize(GetProcessHeap(), 0, Buffer
);
408 TRACE("size: %d\n", dw
);
409 if (dw
!= 0xFFFFFFFF)
417 /************************************************************
418 * NetSessionEnum (NETAPI32.@)
421 * servername [I] Pointer to a string with the name of the server
422 * UncClientName [I] Pointer to a string with the name of the session
423 * username [I] Pointer to a string with the name of the user
424 * level [I] Data information level
425 * bufptr [O] Buffer to the data
426 * prefmaxlen [I] Preferred maximum length of the data
427 * entriesread [O] Pointer to the number of entries enumerated
428 * totalentries [O] Pointer to the possible number of entries
429 * resume_handle [I/O] Pointer to a handle for subsequent searches
432 * If successful, the function returns NERR_Success
433 * On failure it returns:
434 * ERROR_ACCESS_DENIED User has no access to the requested information
435 * ERROR_INVALID_LEVEL Value of 'level' is not correct
436 * ERROR_INVALID_PARAMETER Wrong parameter
437 * ERROR_MORE_DATA Need a larger buffer
438 * ERROR_NOT_ENOUGH_MEMORY Not enough memory
439 * NERR_ClientNameNotFound A session does not exist on a given computer
440 * NERR_InvalidComputer Invalid computer name
441 * NERR_UserNotFound User name could not be found.
443 NET_API_STATUS WINAPI
NetSessionEnum(LMSTR servername
, LMSTR UncClientName
,
444 LMSTR username
, DWORD level
, LPBYTE
* bufptr
, DWORD prefmaxlen
, LPDWORD entriesread
,
445 LPDWORD totalentries
, LPDWORD resume_handle
)
447 FIXME("Stub (%s %s %s %d %p %d %p %p %p)\n", debugstr_w(servername
),
448 debugstr_w(UncClientName
), debugstr_w(username
),
449 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resume_handle
);
454 /************************************************************
455 * NetShareEnum (NETAPI32.@)
458 * servername [I] Pointer to a string with the name of the server
459 * level [I] Data information level
460 * bufptr [O] Buffer to the data
461 * prefmaxlen [I] Preferred maximum length of the data
462 * entriesread [O] Pointer to the number of entries enumerated
463 * totalentries [O] Pointer to the possible number of entries
464 * resume_handle [I/O] Pointer to a handle for subsequent searches
467 * If successful, the function returns NERR_Success
468 * On failure it returns a system error code (FIXME: find out which)
471 NET_API_STATUS WINAPI
NetShareEnum( LMSTR servername
, DWORD level
, LPBYTE
* bufptr
,
472 DWORD prefmaxlen
, LPDWORD entriesread
, LPDWORD totalentries
, LPDWORD resume_handle
)
474 FIXME("Stub (%s %d %p %d %p %p %p)\n", debugstr_w(servername
), level
, bufptr
,
475 prefmaxlen
, entriesread
, totalentries
, resume_handle
);
477 return ERROR_NOT_SUPPORTED
;
480 /************************************************************
481 * NetShareDel (NETAPI32.@)
483 NET_API_STATUS WINAPI
NetShareDel(LMSTR servername
, LMSTR netname
, DWORD reserved
)
485 BOOL local
= NETAPI_IsLocalComputer( servername
);
487 TRACE("%s %s %d\n", debugstr_w(servername
), debugstr_w(netname
), reserved
);
491 if (samba_init()) return samba_funcs
->share_del( servername
, netname
, reserved
);
492 FIXME( "remote computers not supported\n" );
495 FIXME("%s %s %d\n", debugstr_w(servername
), debugstr_w(netname
), reserved
);
499 /************************************************************
500 * NetShareGetInfo (NETAPI32.@)
502 NET_API_STATUS WINAPI
NetShareGetInfo(LMSTR servername
, LMSTR netname
,
503 DWORD level
, LPBYTE
*bufptr
)
505 FIXME("Stub (%s %s %d %p)\n", debugstr_w(servername
),
506 debugstr_w(netname
),level
, bufptr
);
507 return NERR_NetNameNotFound
;
510 /************************************************************
511 * NetShareAdd (NETAPI32.@)
513 NET_API_STATUS WINAPI
NetShareAdd(LMSTR servername
,
514 DWORD level
, LPBYTE buf
, LPDWORD parm_err
)
516 BOOL local
= NETAPI_IsLocalComputer( servername
);
518 TRACE("%s %d %p %p\n", debugstr_w(servername
), level
, buf
, parm_err
);
522 if (samba_init()) return samba_funcs
->share_add( servername
, level
, buf
, parm_err
);
523 FIXME( "remote computers not supported\n" );
526 FIXME("%s %d %p %p\n", debugstr_w(servername
), level
, buf
, parm_err
);
527 return ERROR_NOT_SUPPORTED
;
530 /************************************************************
531 * NetFileEnum (NETAPI32.@)
533 NET_API_STATUS WINAPI
NetFileEnum(
534 LPWSTR ServerName
, LPWSTR BasePath
, LPWSTR UserName
,
535 DWORD Level
, LPBYTE
* BufPtr
, DWORD PrefMaxLen
,
536 LPDWORD EntriesRead
, LPDWORD TotalEntries
, PDWORD_PTR ResumeHandle
)
538 FIXME("(%s, %s, %s, %u): stub\n", debugstr_w(ServerName
), debugstr_w(BasePath
),
539 debugstr_w(UserName
), Level
);
540 return ERROR_NOT_SUPPORTED
;
543 static void wprint_mac(WCHAR
* buffer
, int len
, const MIB_IFROW
*ifRow
)
558 for (i
= 0; i
< ifRow
->dwPhysAddrLen
&& 2 * i
< len
; i
++)
560 val
= ifRow
->bPhysAddr
[i
];
562 buffer
[2*i
] = (WCHAR
)((val
>>4) + 'A' - 10);
564 buffer
[2*i
] = (WCHAR
)((val
>>4) + '0');
566 buffer
[2*i
+1] = (WCHAR
)((val
& 0xf) + 'A' - 10);
568 buffer
[2*i
+1] = (WCHAR
)((val
& 0xf) + '0');
573 /* Theoretically this could be too short, except that MS defines
574 * MAX_ADAPTER_NAME as 128, and MAX_INTERFACE_NAME_LEN as 256, and both
575 * represent a count of WCHARs, so even with an extraordinarily long header
576 * this will be plenty
578 #define MAX_TRANSPORT_NAME MAX_INTERFACE_NAME_LEN
579 #define MAX_TRANSPORT_ADDR 13
581 #define NBT_TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
582 #define UNKNOWN_TRANSPORT_NAME_HEADER "\\Device\\UnknownTransport_"
584 static void wprint_name(WCHAR
*buffer
, int len
, ULONG transport
,
598 if (!memcmp(&transport
, TRANSPORT_NBT
, sizeof(ULONG
)))
599 name
= NBT_TRANSPORT_NAME_HEADER
;
601 name
= UNKNOWN_TRANSPORT_NAME_HEADER
;
603 for (ptr1
= buffer
; *name
&& ptr1
< buffer
+ len
; ptr1
++, name
++)
605 for (ptr2
= ifRow
->wszName
; *ptr2
&& ptr1
< buffer
+ len
; ptr1
++, ptr2
++)
610 /***********************************************************************
611 * NetWkstaTransportEnum (NETAPI32.@)
614 struct WkstaTransportEnumData
623 /**********************************************************************/
625 static BOOL
WkstaEnumAdaptersCallback(UCHAR totalLANAs
, UCHAR lanaIndex
,
626 ULONG transport
, const NetBIOSAdapterImpl
*data
, void *closure
)
629 struct WkstaTransportEnumData
*enumData
= closure
;
631 if (enumData
&& enumData
->pbuf
)
637 enumData
->n_adapt
= totalLANAs
;
638 enumData
->n_read
= 0;
640 toAllocate
= totalLANAs
* (sizeof(WKSTA_TRANSPORT_INFO_0
)
641 + MAX_TRANSPORT_NAME
* sizeof(WCHAR
) +
642 MAX_TRANSPORT_ADDR
* sizeof(WCHAR
));
643 if (enumData
->prefmaxlen
!= MAX_PREFERRED_LENGTH
)
644 toAllocate
= enumData
->prefmaxlen
;
645 NetApiBufferAllocate(toAllocate
, (LPVOID
*)enumData
->pbuf
);
647 if (*(enumData
->pbuf
))
651 if (enumData
->prefmaxlen
== MAX_PREFERRED_LENGTH
)
652 spaceFor
= totalLANAs
;
654 spaceFor
= enumData
->prefmaxlen
/
655 (sizeof(WKSTA_TRANSPORT_INFO_0
) + (MAX_TRANSPORT_NAME
+
656 MAX_TRANSPORT_ADDR
) * sizeof(WCHAR
));
657 if (enumData
->n_read
< spaceFor
)
659 PWKSTA_TRANSPORT_INFO_0 ti
;
660 LMSTR transport_name
, transport_addr
;
663 ti
= (PWKSTA_TRANSPORT_INFO_0
)(*(enumData
->pbuf
) +
664 enumData
->n_read
* sizeof(WKSTA_TRANSPORT_INFO_0
));
665 transport_name
= (LMSTR
)(*(enumData
->pbuf
) +
666 totalLANAs
* sizeof(WKSTA_TRANSPORT_INFO_0
) +
667 enumData
->n_read
* MAX_TRANSPORT_NAME
* sizeof(WCHAR
));
668 transport_addr
= (LMSTR
)(*(enumData
->pbuf
) +
669 totalLANAs
* (sizeof(WKSTA_TRANSPORT_INFO_0
) +
670 MAX_TRANSPORT_NAME
* sizeof(WCHAR
)) +
671 enumData
->n_read
* MAX_TRANSPORT_ADDR
* sizeof(WCHAR
));
673 ifRow
.dwIndex
= data
->ifIndex
;
675 ti
->wkti0_quality_of_service
= 0;
676 ti
->wkti0_number_of_vcs
= 0;
677 ti
->wkti0_transport_name
= transport_name
;
678 wprint_name(ti
->wkti0_transport_name
, MAX_TRANSPORT_NAME
,
680 ti
->wkti0_transport_address
= transport_addr
;
681 wprint_mac(ti
->wkti0_transport_address
, MAX_TRANSPORT_ADDR
,
683 if (!memcmp(&transport
, TRANSPORT_NBT
, sizeof(ULONG
)))
684 ti
->wkti0_wan_ish
= TRUE
;
686 ti
->wkti0_wan_ish
= FALSE
;
687 TRACE("%d of %d:ti at %p\n", lanaIndex
, totalLANAs
, ti
);
688 TRACE("transport_name at %p %s\n",
689 ti
->wkti0_transport_name
,
690 debugstr_w(ti
->wkti0_transport_name
));
691 TRACE("transport_address at %p %s\n",
692 ti
->wkti0_transport_address
,
693 debugstr_w(ti
->wkti0_transport_address
));
695 enumData
->ret
= NERR_Success
;
700 enumData
->ret
= ERROR_MORE_DATA
;
706 enumData
->ret
= ERROR_OUTOFMEMORY
;
715 /**********************************************************************/
717 NET_API_STATUS WINAPI
718 NetWkstaTransportEnum(LMSTR ServerName
, DWORD level
, PBYTE
* pbuf
,
719 DWORD prefmaxlen
, LPDWORD read_entries
,
720 PDWORD total_entries
, PDWORD hresume
)
724 TRACE(":%s, 0x%08x, %p, 0x%08x, %p, %p, %p\n", debugstr_w(ServerName
),
725 level
, pbuf
, prefmaxlen
, read_entries
, total_entries
,hresume
);
726 if (!NETAPI_IsLocalComputer(ServerName
))
728 FIXME(":not implemented for non-local computers\n");
729 ret
= ERROR_INVALID_LEVEL
;
733 if (hresume
&& *hresume
)
735 FIXME(":resume handle not implemented\n");
736 return ERROR_INVALID_LEVEL
;
741 case 0: /* transport info */
744 struct WkstaTransportEnumData enumData
;
746 if (NetBIOSNumAdapters() == 0)
747 return ERROR_NETWORK_UNREACHABLE
;
749 return STATUS_ACCESS_VIOLATION
;
750 if (!total_entries
|| !pbuf
)
751 return RPC_X_NULL_REF_POINTER
;
753 enumData
.prefmaxlen
= prefmaxlen
;
754 enumData
.pbuf
= pbuf
;
755 memcpy(&allTransports
, ALL_TRANSPORTS
, sizeof(ULONG
));
756 NetBIOSEnumAdapters(allTransports
, WkstaEnumAdaptersCallback
,
758 *read_entries
= enumData
.n_read
;
759 *total_entries
= enumData
.n_adapt
;
760 if (hresume
) *hresume
= 0;
765 TRACE("Invalid level %d is specified\n", level
);
766 ret
= ERROR_INVALID_LEVEL
;
772 /************************************************************
773 * NetWkstaUserGetInfo (NETAPI32.@)
775 NET_API_STATUS WINAPI
NetWkstaUserGetInfo(LMSTR reserved
, DWORD level
,
778 NET_API_STATUS nastatus
;
780 TRACE("(%s, %d, %p)\n", debugstr_w(reserved
), level
, bufptr
);
785 PWKSTA_USER_INFO_0 ui
;
786 DWORD dwSize
= UNLEN
+ 1;
789 nastatus
= NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0
) + dwSize
* sizeof(WCHAR
),
791 if (nastatus
!= NERR_Success
)
792 return ERROR_NOT_ENOUGH_MEMORY
;
794 ui
= (PWKSTA_USER_INFO_0
) *bufptr
;
795 ui
->wkui0_username
= (LMSTR
) (*bufptr
+ sizeof(WKSTA_USER_INFO_0
));
798 if (!GetUserNameW(ui
->wkui0_username
, &dwSize
))
800 NetApiBufferFree(ui
);
801 return ERROR_NOT_ENOUGH_MEMORY
;
804 nastatus
= NetApiBufferReallocate(
805 *bufptr
, sizeof(WKSTA_USER_INFO_0
) +
806 (lstrlenW(ui
->wkui0_username
) + 1) * sizeof(WCHAR
),
808 if (nastatus
!= NERR_Success
)
810 NetApiBufferFree(ui
);
813 ui
= (PWKSTA_USER_INFO_0
) *bufptr
;
814 ui
->wkui0_username
= (LMSTR
) (*bufptr
+ sizeof(WKSTA_USER_INFO_0
));
821 PWKSTA_USER_INFO_1 ui
;
822 PWKSTA_USER_INFO_0 ui0
;
823 LSA_OBJECT_ATTRIBUTES ObjectAttributes
;
824 LSA_HANDLE PolicyHandle
;
825 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo
;
828 /* sizes of the field buffers in WCHARS */
829 int username_sz
, logon_domain_sz
, oth_domains_sz
, logon_server_sz
;
831 FIXME("Level 1 processing is partially implemented\n");
835 /* get some information first to estimate size of the buffer */
837 nastatus
= NetWkstaUserGetInfo(NULL
, 0, (PBYTE
*) &ui0
);
838 if (nastatus
!= NERR_Success
)
840 username_sz
= lstrlenW(ui0
->wkui0_username
) + 1;
842 ZeroMemory(&ObjectAttributes
, sizeof(ObjectAttributes
));
843 NtStatus
= LsaOpenPolicy(NULL
, &ObjectAttributes
,
844 POLICY_VIEW_LOCAL_INFORMATION
,
846 if (NtStatus
!= STATUS_SUCCESS
)
848 TRACE("LsaOpenPolicyFailed with NT status %x\n",
849 LsaNtStatusToWinError(NtStatus
));
850 NetApiBufferFree(ui0
);
851 return ERROR_NOT_ENOUGH_MEMORY
;
853 LsaQueryInformationPolicy(PolicyHandle
, PolicyAccountDomainInformation
,
854 (PVOID
*) &DomainInfo
);
855 logon_domain_sz
= lstrlenW(DomainInfo
->DomainName
.Buffer
) + 1;
856 LsaClose(PolicyHandle
);
859 nastatus
= NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1
) +
860 (username_sz
+ logon_domain_sz
+
861 oth_domains_sz
+ logon_server_sz
) * sizeof(WCHAR
),
863 if (nastatus
!= NERR_Success
) {
864 NetApiBufferFree(ui0
);
867 ui
= (WKSTA_USER_INFO_1
*) *bufptr
;
868 ui
->wkui1_username
= (LMSTR
) (*bufptr
+ sizeof(WKSTA_USER_INFO_1
));
869 ui
->wkui1_logon_domain
= (LMSTR
) (
870 ((PBYTE
) ui
->wkui1_username
) + username_sz
* sizeof(WCHAR
));
871 ui
->wkui1_oth_domains
= (LMSTR
) (
872 ((PBYTE
) ui
->wkui1_logon_domain
) +
873 logon_domain_sz
* sizeof(WCHAR
));
874 ui
->wkui1_logon_server
= (LMSTR
) (
875 ((PBYTE
) ui
->wkui1_oth_domains
) +
876 oth_domains_sz
* sizeof(WCHAR
));
879 lstrcpyW(ui
->wkui1_username
, ui0
->wkui0_username
);
880 NetApiBufferFree(ui0
);
882 lstrcpynW(ui
->wkui1_logon_domain
, DomainInfo
->DomainName
.Buffer
,
884 LsaFreeMemory(DomainInfo
);
886 /* FIXME. Not implemented. Populated with empty strings */
887 ui
->wkui1_oth_domains
[0] = 0;
888 ui
->wkui1_logon_server
[0] = 0;
893 PWKSTA_USER_INFO_1101 ui
;
896 FIXME("Stub. Level 1101 processing is not implemented\n");
897 /* FIXME see also wkui1_oth_domains for level 1 */
900 nastatus
= NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101
) + dwSize
* sizeof(WCHAR
),
902 if (nastatus
!= NERR_Success
)
904 ui
= (PWKSTA_USER_INFO_1101
) *bufptr
;
905 ui
->wkui1101_oth_domains
= (LMSTR
)(ui
+ 1);
908 ui
->wkui1101_oth_domains
[0] = 0;
912 TRACE("Invalid level %d is specified\n", level
);
913 return ERROR_INVALID_LEVEL
;
918 /************************************************************
919 * NetWkstaUserEnum (NETAPI32.@)
921 NET_API_STATUS WINAPI
922 NetWkstaUserEnum(LMSTR servername
, DWORD level
, LPBYTE
* bufptr
,
923 DWORD prefmaxlen
, LPDWORD entriesread
,
924 LPDWORD totalentries
, LPDWORD resumehandle
)
926 FIXME("(%s, %d, %p, %d, %p, %p, %p): stub!\n", debugstr_w(servername
),
927 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resumehandle
);
928 return ERROR_INVALID_PARAMETER
;
931 /************************************************************
932 * NetpGetComputerName (NETAPI32.@)
934 NET_API_STATUS WINAPI
NetpGetComputerName(LPWSTR
*Buffer
)
936 DWORD dwSize
= MAX_COMPUTERNAME_LENGTH
+ 1;
938 TRACE("(%p)\n", Buffer
);
939 NetApiBufferAllocate(dwSize
* sizeof(WCHAR
), (LPVOID
*) Buffer
);
940 if (GetComputerNameW(*Buffer
, &dwSize
))
942 return NetApiBufferReallocate(
943 *Buffer
, (dwSize
+ 1) * sizeof(WCHAR
),
948 NetApiBufferFree(*Buffer
);
949 return ERROR_NOT_ENOUGH_MEMORY
;
953 NET_API_STATUS WINAPI
I_NetNameCompare(LPVOID p1
, LPWSTR wkgrp
, LPWSTR comp
,
954 LPVOID p4
, LPVOID p5
)
956 FIXME("(%p %s %s %p %p): stub\n", p1
, debugstr_w(wkgrp
), debugstr_w(comp
),
958 return ERROR_INVALID_PARAMETER
;
961 NET_API_STATUS WINAPI
I_NetNameValidate(LPVOID p1
, LPWSTR wkgrp
, LPVOID p3
,
964 FIXME("(%p %s %p %p): stub\n", p1
, debugstr_w(wkgrp
), p3
, p4
);
965 return ERROR_INVALID_PARAMETER
;
968 NET_API_STATUS WINAPI
NetWkstaGetInfo( LMSTR servername
, DWORD level
,
972 BOOL local
= NETAPI_IsLocalComputer( servername
);
974 TRACE("%s %d %p\n", debugstr_w( servername
), level
, bufptr
);
984 if (!(*bufptr
= malloc( size
))) return ERROR_OUTOFMEMORY
;
985 ret
= samba_funcs
->wksta_getinfo( servername
, level
, *bufptr
, &size
);
986 if (ret
) free( *bufptr
);
987 if (ret
!= ERROR_INSUFFICIENT_BUFFER
) return ret
;
990 FIXME( "remote computers not supported\n" );
991 return ERROR_INVALID_LEVEL
;
993 if (!bufptr
) return ERROR_INVALID_PARAMETER
;
1001 static const WCHAR lanroot
[] = L
"c:\\lanman"; /* FIXME */
1002 DWORD computerNameLen
, domainNameLen
, size
;
1003 WCHAR computerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1004 LSA_OBJECT_ATTRIBUTES ObjectAttributes
;
1005 LSA_HANDLE PolicyHandle
;
1008 computerNameLen
= MAX_COMPUTERNAME_LENGTH
+ 1;
1009 GetComputerNameW(computerName
, &computerNameLen
);
1010 computerNameLen
++; /* include NULL terminator */
1012 ZeroMemory(&ObjectAttributes
, sizeof(ObjectAttributes
));
1013 NtStatus
= LsaOpenPolicy(NULL
, &ObjectAttributes
,
1014 POLICY_VIEW_LOCAL_INFORMATION
, &PolicyHandle
);
1015 if (NtStatus
!= STATUS_SUCCESS
)
1016 ret
= LsaNtStatusToWinError(NtStatus
);
1019 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo
;
1021 LsaQueryInformationPolicy(PolicyHandle
,
1022 PolicyAccountDomainInformation
, (PVOID
*)&DomainInfo
);
1023 domainNameLen
= lstrlenW(DomainInfo
->DomainName
.Buffer
) + 1;
1024 size
= sizeof(WKSTA_INFO_102
) + computerNameLen
* sizeof(WCHAR
)
1025 + domainNameLen
* sizeof(WCHAR
) + sizeof(lanroot
);
1026 ret
= NetApiBufferAllocate(size
, (LPVOID
*)bufptr
);
1027 if (ret
== NERR_Success
)
1029 /* INFO_100 and INFO_101 structures are subsets of INFO_102 */
1030 PWKSTA_INFO_102 info
= (PWKSTA_INFO_102
)*bufptr
;
1031 OSVERSIONINFOW verInfo
;
1033 info
->wki102_platform_id
= PLATFORM_ID_NT
;
1034 info
->wki102_computername
= (LMSTR
)(*bufptr
+
1035 sizeof(WKSTA_INFO_102
));
1036 memcpy(info
->wki102_computername
, computerName
,
1037 computerNameLen
* sizeof(WCHAR
));
1038 info
->wki102_langroup
= info
->wki102_computername
+ computerNameLen
;
1039 memcpy(info
->wki102_langroup
, DomainInfo
->DomainName
.Buffer
,
1040 domainNameLen
* sizeof(WCHAR
));
1041 info
->wki102_lanroot
= info
->wki102_langroup
+ domainNameLen
;
1042 memcpy(info
->wki102_lanroot
, lanroot
, sizeof(lanroot
));
1043 memset(&verInfo
, 0, sizeof(verInfo
));
1044 verInfo
.dwOSVersionInfoSize
= sizeof(verInfo
);
1045 GetVersionExW(&verInfo
);
1046 info
->wki102_ver_major
= verInfo
.dwMajorVersion
;
1047 info
->wki102_ver_minor
= verInfo
.dwMinorVersion
;
1048 info
->wki102_logged_on_users
= 1;
1050 LsaFreeMemory(DomainInfo
);
1051 LsaClose(PolicyHandle
);
1057 FIXME("level %d unimplemented\n", level
);
1058 ret
= ERROR_INVALID_LEVEL
;
1063 /************************************************************
1064 * NetGetJoinInformation (NETAPI32.@)
1066 NET_API_STATUS NET_API_FUNCTION
NetGetJoinInformation(
1069 PNETSETUP_JOIN_STATUS type
)
1071 static const WCHAR workgroupW
[] = L
"Workgroup";
1073 FIXME("Semi-stub %s %p %p\n", wine_dbgstr_w(Server
), Name
, type
);
1076 return ERROR_INVALID_PARAMETER
;
1078 NetApiBufferAllocate(sizeof(workgroupW
), (LPVOID
*)Name
);
1079 lstrcpyW(*Name
, workgroupW
);
1080 *type
= NetSetupWorkgroupName
;
1082 return NERR_Success
;
1085 /************************************************************
1086 * NetUserGetGroups (NETAPI32.@)
1088 NET_API_STATUS NET_API_FUNCTION
NetUserGetGroups(
1094 LPDWORD entriesread
,
1095 LPDWORD totalentries
)
1097 FIXME("%s %s %d %p %d %p %p stub\n", debugstr_w(servername
),
1098 debugstr_w(username
), level
, bufptr
, prefixmaxlen
, entriesread
,
1105 return ERROR_INVALID_LEVEL
;
1111 WCHAR user_name
[LM20_UNLEN
+1];
1112 WCHAR user_password
[PWLEN
+ 1];
1113 DWORD sec_since_passwd_change
;
1116 LPWSTR user_comment
;
1118 LPWSTR user_logon_script_path
;
1121 static struct list user_list
= LIST_INIT( user_list
);
1123 /************************************************************
1124 * NETAPI_ValidateServername
1126 * Validates server name
1128 static NET_API_STATUS
NETAPI_ValidateServername(LPCWSTR ServerName
)
1132 if (ServerName
[0] == 0)
1133 return ERROR_BAD_NETPATH
;
1135 ((ServerName
[0] == '\\') &&
1136 (ServerName
[1] != '\\'))
1138 ((ServerName
[0] == '\\') &&
1139 (ServerName
[1] == '\\') &&
1140 (ServerName
[2] == 0))
1142 return ERROR_INVALID_NAME
;
1144 return NERR_Success
;
1147 /************************************************************
1150 * Looks for a user in the user database.
1151 * Returns a pointer to the entry in the user list when the user
1152 * is found, NULL otherwise.
1154 static struct sam_user
* NETAPI_FindUser(LPCWSTR UserName
)
1156 struct sam_user
*user
;
1158 LIST_FOR_EACH_ENTRY(user
, &user_list
, struct sam_user
, entry
)
1160 if(wcscmp(user
->user_name
, UserName
) == 0)
1166 static BOOL
NETAPI_IsCurrentUser(LPCWSTR username
)
1168 LPWSTR curr_user
= NULL
;
1172 dwSize
= LM20_UNLEN
+1;
1173 curr_user
= HeapAlloc(GetProcessHeap(), 0, dwSize
* sizeof(WCHAR
));
1176 ERR("Failed to allocate memory for user name.\n");
1179 if(!GetUserNameW(curr_user
, &dwSize
))
1181 ERR("Failed to get current user's user name.\n");
1184 if (!wcscmp(curr_user
, username
))
1190 HeapFree(GetProcessHeap(), 0, curr_user
);
1194 /************************************************************
1195 * NetUserAdd (NETAPI32.@)
1197 NET_API_STATUS WINAPI
NetUserAdd(LPCWSTR servername
,
1198 DWORD level
, LPBYTE bufptr
, LPDWORD parm_err
)
1200 NET_API_STATUS status
;
1201 struct sam_user
* su
= NULL
;
1203 FIXME("(%s, %d, %p, %p) stub!\n", debugstr_w(servername
), level
, bufptr
, parm_err
);
1205 if((status
= NETAPI_ValidateServername(servername
)) != NERR_Success
)
1210 /* Level 3 and 4 are identical for the purposes of NetUserAdd */
1213 FIXME("Level 3 and 4 not implemented.\n");
1216 FIXME("Level 2 not implemented.\n");
1220 PUSER_INFO_1 ui
= (PUSER_INFO_1
) bufptr
;
1221 su
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct sam_user
));
1224 status
= NERR_InternalError
;
1228 if(lstrlenW(ui
->usri1_name
) > LM20_UNLEN
)
1230 status
= NERR_BadUsername
;
1234 /*FIXME: do other checks for a valid username */
1235 lstrcpyW(su
->user_name
, ui
->usri1_name
);
1237 if(lstrlenW(ui
->usri1_password
) > PWLEN
)
1239 /* Always return PasswordTooShort on invalid passwords. */
1240 status
= NERR_PasswordTooShort
;
1243 lstrcpyW(su
->user_password
, ui
->usri1_password
);
1245 su
->sec_since_passwd_change
= ui
->usri1_password_age
;
1246 su
->user_priv
= ui
->usri1_priv
;
1247 su
->user_flags
= ui
->usri1_flags
;
1249 /*FIXME: set the other LPWSTRs to NULL for now */
1250 su
->home_dir
= NULL
;
1251 su
->user_comment
= NULL
;
1252 su
->user_logon_script_path
= NULL
;
1254 list_add_head(&user_list
, &su
->entry
);
1255 return NERR_Success
;
1258 TRACE("Invalid level %d specified.\n", level
);
1259 status
= ERROR_INVALID_LEVEL
;
1263 HeapFree(GetProcessHeap(), 0, su
);
1268 /************************************************************
1269 * NetUserDel (NETAPI32.@)
1271 NET_API_STATUS WINAPI
NetUserDel(LPCWSTR servername
, LPCWSTR username
)
1273 NET_API_STATUS status
;
1274 struct sam_user
*user
;
1276 TRACE("(%s, %s)\n", debugstr_w(servername
), debugstr_w(username
));
1278 if((status
= NETAPI_ValidateServername(servername
))!= NERR_Success
)
1281 if ((user
= NETAPI_FindUser(username
)) == NULL
)
1282 return NERR_UserNotFound
;
1284 list_remove(&user
->entry
);
1286 HeapFree(GetProcessHeap(), 0, user
->home_dir
);
1287 HeapFree(GetProcessHeap(), 0, user
->user_comment
);
1288 HeapFree(GetProcessHeap(), 0, user
->user_logon_script_path
);
1289 HeapFree(GetProcessHeap(), 0, user
);
1291 return NERR_Success
;
1294 /************************************************************
1295 * NetUserGetInfo (NETAPI32.@)
1297 NET_API_STATUS WINAPI
1298 NetUserGetInfo(LPCWSTR servername
, LPCWSTR username
, DWORD level
,
1301 NET_API_STATUS status
;
1302 TRACE("(%s, %s, %d, %p)\n", debugstr_w(servername
), debugstr_w(username
),
1304 status
= NETAPI_ValidateServername(servername
);
1305 if (status
!= NERR_Success
)
1308 if(!NETAPI_IsLocalComputer(servername
))
1310 FIXME("Only implemented for local computer, but remote server"
1311 "%s was requested.\n", debugstr_w(servername
));
1312 return NERR_InvalidComputer
;
1315 if(!NETAPI_FindUser(username
) && !NETAPI_IsCurrentUser(username
))
1317 TRACE("User %s is unknown.\n", debugstr_w(username
));
1318 return NERR_UserNotFound
;
1328 name_sz
= lstrlenW(username
) + 1;
1331 NetApiBufferAllocate(sizeof(USER_INFO_0
) + name_sz
* sizeof(WCHAR
),
1334 ui
= (PUSER_INFO_0
) *bufptr
;
1335 ui
->usri0_name
= (LPWSTR
) (*bufptr
+ sizeof(USER_INFO_0
));
1338 lstrcpyW(ui
->usri0_name
, username
);
1346 /* sizes of the field buffers in WCHARS */
1347 int name_sz
, comment_sz
, usr_comment_sz
, full_name_sz
;
1354 status
= NetUserGetInfo(servername
, username
, 0, (LPBYTE
*) &ui0
);
1355 if (status
!= NERR_Success
)
1357 NetApiBufferFree(ui0
);
1360 name_sz
= lstrlenW(ui0
->usri0_name
) + 1;
1363 NetApiBufferAllocate(sizeof(USER_INFO_10
) +
1364 (name_sz
+ comment_sz
+ usr_comment_sz
+
1365 full_name_sz
) * sizeof(WCHAR
),
1367 ui
= (PUSER_INFO_10
) *bufptr
;
1368 ui
->usri10_name
= (LPWSTR
) (*bufptr
+ sizeof(USER_INFO_10
));
1369 ui
->usri10_comment
= (LPWSTR
) (
1370 ((PBYTE
) ui
->usri10_name
) + name_sz
* sizeof(WCHAR
));
1371 ui
->usri10_usr_comment
= (LPWSTR
) (
1372 ((PBYTE
) ui
->usri10_comment
) + comment_sz
* sizeof(WCHAR
));
1373 ui
->usri10_full_name
= (LPWSTR
) (
1374 ((PBYTE
) ui
->usri10_usr_comment
) + usr_comment_sz
* sizeof(WCHAR
));
1377 lstrcpyW(ui
->usri10_name
, ui0
->usri0_name
);
1378 NetApiBufferFree(ui0
);
1379 ui
->usri10_comment
[0] = 0;
1380 ui
->usri10_usr_comment
[0] = 0;
1381 ui
->usri10_full_name
[0] = 0;
1389 /* sizes of the field buffers in WCHARS */
1390 int name_sz
, password_sz
, home_dir_sz
, comment_sz
, script_path_sz
;
1392 password_sz
= 1; /* not filled out for security reasons for NetUserGetInfo*/
1397 status
= NetUserGetInfo(servername
, username
, 0, (LPBYTE
*) &ui0
);
1398 if (status
!= NERR_Success
)
1400 NetApiBufferFree(ui0
);
1403 name_sz
= lstrlenW(ui0
->usri0_name
) + 1;
1404 home_dir_sz
= GetEnvironmentVariableW(L
"HOME", NULL
,0);
1406 NetApiBufferAllocate(sizeof(USER_INFO_1
) +
1407 (name_sz
+ password_sz
+ home_dir_sz
+
1408 comment_sz
+ script_path_sz
) * sizeof(WCHAR
),
1411 ui
= (PUSER_INFO_1
) *bufptr
;
1412 ui
->usri1_name
= (LPWSTR
) (ui
+ 1);
1413 ui
->usri1_password
= ui
->usri1_name
+ name_sz
;
1414 ui
->usri1_home_dir
= ui
->usri1_password
+ password_sz
;
1415 ui
->usri1_comment
= ui
->usri1_home_dir
+ home_dir_sz
;
1416 ui
->usri1_script_path
= ui
->usri1_comment
+ comment_sz
;
1418 lstrcpyW(ui
->usri1_name
, ui0
->usri0_name
);
1419 NetApiBufferFree(ui0
);
1420 ui
->usri1_password
[0] = 0;
1421 ui
->usri1_password_age
= 0;
1423 GetEnvironmentVariableW(L
"HOME", ui
->usri1_home_dir
,home_dir_sz
);
1424 ui
->usri1_comment
[0] = 0;
1425 ui
->usri1_flags
= 0;
1426 ui
->usri1_script_path
[0] = 0;
1456 FIXME("Level %d is not implemented\n", level
);
1457 return NERR_InternalError
;
1460 TRACE("Invalid level %d is specified\n", level
);
1461 return ERROR_INVALID_LEVEL
;
1463 return NERR_Success
;
1466 /************************************************************
1467 * NetUserGetLocalGroups (NETAPI32.@)
1469 NET_API_STATUS WINAPI
1470 NetUserGetLocalGroups(LPCWSTR servername
, LPCWSTR username
, DWORD level
,
1471 DWORD flags
, LPBYTE
* bufptr
, DWORD prefmaxlen
,
1472 LPDWORD entriesread
, LPDWORD totalentries
)
1474 static const WCHAR admins
[] = L
"Administrators";
1475 NET_API_STATUS status
;
1477 LOCALGROUP_USERS_INFO_0
* info
;
1480 FIXME("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
1481 debugstr_w(servername
), debugstr_w(username
), level
, flags
, bufptr
,
1482 prefmaxlen
, entriesread
, totalentries
);
1484 status
= NETAPI_ValidateServername(servername
);
1485 if (status
!= NERR_Success
)
1489 NetApiBufferAllocate(size
* sizeof(WCHAR
), (LPVOID
*)¤tuser
);
1490 if (!GetUserNameW(currentuser
, &size
)) {
1491 NetApiBufferFree(currentuser
);
1492 return ERROR_NOT_ENOUGH_MEMORY
;
1495 if (lstrcmpiW(username
, currentuser
) && NETAPI_FindUser(username
))
1497 NetApiBufferFree(currentuser
);
1498 return NERR_UserNotFound
;
1501 NetApiBufferFree(currentuser
);
1503 size
= sizeof(*info
) + sizeof(admins
);
1505 if(prefmaxlen
< size
)
1506 status
= ERROR_MORE_DATA
;
1508 status
= NetApiBufferAllocate(size
, (LPVOID
*)&info
);
1510 if(status
!= NERR_Success
)
1517 info
->lgrui0_name
= (LPWSTR
)((LPBYTE
)info
+ sizeof(*info
));
1518 lstrcpyW(info
->lgrui0_name
, admins
);
1520 *bufptr
= (LPBYTE
)info
;
1523 return NERR_Success
;
1526 /************************************************************
1527 * NetUserEnum (NETAPI32.@)
1529 NET_API_STATUS WINAPI
1530 NetUserEnum(LPCWSTR servername
, DWORD level
, DWORD filter
, LPBYTE
* bufptr
,
1531 DWORD prefmaxlen
, LPDWORD entriesread
, LPDWORD totalentries
,
1532 LPDWORD resume_handle
)
1534 NET_API_STATUS status
;
1535 WCHAR user
[UNLEN
+ 1];
1536 DWORD size
, len
= ARRAY_SIZE(user
);
1538 TRACE("(%s, %u, 0x%x, %p, %u, %p, %p, %p)\n", debugstr_w(servername
), level
,
1539 filter
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resume_handle
);
1541 status
= NETAPI_ValidateServername(servername
);
1542 if (status
!= NERR_Success
)
1545 if (!NETAPI_IsLocalComputer(servername
))
1547 FIXME("Only implemented for local computer, but remote server"
1548 "%s was requested.\n", debugstr_w(servername
));
1549 return NERR_InvalidComputer
;
1552 if (!GetUserNameW(user
, &len
)) return GetLastError();
1560 size
= sizeof(*info
) + (wcslen(user
) + 1) * sizeof(WCHAR
);
1562 if (prefmaxlen
< size
)
1563 status
= ERROR_MORE_DATA
;
1565 status
= NetApiBufferAllocate(size
, (void **)&info
);
1567 if (status
!= NERR_Success
)
1570 info
->usri0_name
= (WCHAR
*)((char *)info
+ sizeof(*info
));
1571 wcscpy(info
->usri0_name
, user
);
1573 *bufptr
= (BYTE
*)info
;
1574 *entriesread
= *totalentries
= 1;
1585 size
= sizeof(*info
) + (wcslen(user
) + 1) * sizeof(WCHAR
);
1587 if (prefmaxlen
< size
)
1588 status
= ERROR_MORE_DATA
;
1590 status
= NetApiBufferAllocate(size
, (void **)&info
);
1592 if (status
!= NERR_Success
)
1596 LookupAccountNameW(NULL
, user
, NULL
, &size
, NULL
, &len
, &use
);
1597 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1598 return GetLastError();
1600 status
= NetApiBufferAllocate(size
, (void **)&sid
);
1601 if (status
!= NERR_Success
)
1604 if (!LookupAccountNameW(NULL
, user
, sid
, &size
, NULL
, &len
, &use
))
1605 return GetLastError();
1607 count
= GetSidSubAuthorityCount(sid
);
1608 rid
= GetSidSubAuthority(sid
, *count
- 1);
1610 info
->usri20_name
= (WCHAR
*)((char *)info
+ sizeof(*info
));
1611 wcscpy(info
->usri20_name
, user
);
1612 info
->usri20_full_name
= NULL
;
1613 info
->usri20_comment
= NULL
;
1614 info
->usri20_flags
= UF_NORMAL_ACCOUNT
;
1615 info
->usri20_user_id
= *rid
;
1617 *bufptr
= (BYTE
*)info
;
1618 *entriesread
= *totalentries
= 1;
1620 NetApiBufferFree(sid
);
1624 FIXME("level %u not supported\n", level
);
1625 return ERROR_INVALID_LEVEL
;
1627 return NERR_Success
;
1630 /************************************************************
1631 * ACCESS_QueryAdminDisplayInformation
1633 * Creates a buffer with information for the Admin User
1635 static void ACCESS_QueryAdminDisplayInformation(PNET_DISPLAY_USER
*buf
, PDWORD pdwSize
)
1637 static const WCHAR sAdminUserName
[] = L
"Administrator";
1639 /* sizes of the field buffers in WCHARS */
1640 int name_sz
, comment_sz
, full_name_sz
;
1641 PNET_DISPLAY_USER usr
;
1644 name_sz
= lstrlenW(sAdminUserName
) + 1;
1648 *pdwSize
= sizeof(NET_DISPLAY_USER
);
1649 *pdwSize
+= (name_sz
+ comment_sz
+ full_name_sz
) * sizeof(WCHAR
);
1650 NetApiBufferAllocate(*pdwSize
, (LPVOID
*) buf
);
1653 usr
->usri1_name
= (LPWSTR
) ((PBYTE
) usr
+ sizeof(NET_DISPLAY_USER
));
1654 usr
->usri1_comment
= (LPWSTR
) (
1655 ((PBYTE
) usr
->usri1_name
) + name_sz
* sizeof(WCHAR
));
1656 usr
->usri1_full_name
= (LPWSTR
) (
1657 ((PBYTE
) usr
->usri1_comment
) + comment_sz
* sizeof(WCHAR
));
1660 lstrcpyW(usr
->usri1_name
, sAdminUserName
);
1661 usr
->usri1_comment
[0] = 0;
1662 usr
->usri1_flags
= UF_SCRIPT
| UF_NORMAL_ACCOUNT
| UF_DONT_EXPIRE_PASSWD
;
1663 usr
->usri1_full_name
[0] = 0;
1664 usr
->usri1_user_id
= DOMAIN_USER_RID_ADMIN
;
1665 usr
->usri1_next_index
= 0;
1668 /************************************************************
1669 * ACCESS_QueryGuestDisplayInformation
1671 * Creates a buffer with information for the Guest User
1673 static void ACCESS_QueryGuestDisplayInformation(PNET_DISPLAY_USER
*buf
, PDWORD pdwSize
)
1675 static const WCHAR sGuestUserName
[] = L
"Guest";
1677 /* sizes of the field buffers in WCHARS */
1678 int name_sz
, comment_sz
, full_name_sz
;
1679 PNET_DISPLAY_USER usr
;
1682 name_sz
= lstrlenW(sGuestUserName
) + 1;
1686 *pdwSize
= sizeof(NET_DISPLAY_USER
);
1687 *pdwSize
+= (name_sz
+ comment_sz
+ full_name_sz
) * sizeof(WCHAR
);
1688 NetApiBufferAllocate(*pdwSize
, (LPVOID
*) buf
);
1691 usr
->usri1_name
= (LPWSTR
) ((PBYTE
) usr
+ sizeof(NET_DISPLAY_USER
));
1692 usr
->usri1_comment
= (LPWSTR
) (
1693 ((PBYTE
) usr
->usri1_name
) + name_sz
* sizeof(WCHAR
));
1694 usr
->usri1_full_name
= (LPWSTR
) (
1695 ((PBYTE
) usr
->usri1_comment
) + comment_sz
* sizeof(WCHAR
));
1698 lstrcpyW(usr
->usri1_name
, sGuestUserName
);
1699 usr
->usri1_comment
[0] = 0;
1700 usr
->usri1_flags
= UF_ACCOUNTDISABLE
| UF_SCRIPT
| UF_NORMAL_ACCOUNT
|
1701 UF_DONT_EXPIRE_PASSWD
;
1702 usr
->usri1_full_name
[0] = 0;
1703 usr
->usri1_user_id
= DOMAIN_USER_RID_GUEST
;
1704 usr
->usri1_next_index
= 0;
1707 /************************************************************
1708 * Copies NET_DISPLAY_USER record.
1710 static void ACCESS_CopyDisplayUser(const NET_DISPLAY_USER
*dest
, LPWSTR
*dest_buf
,
1711 PNET_DISPLAY_USER src
)
1713 LPWSTR str
= *dest_buf
;
1715 src
->usri1_name
= str
;
1716 lstrcpyW(src
->usri1_name
, dest
->usri1_name
);
1718 ((PBYTE
) str
) + (lstrlenW(str
) + 1) * sizeof(WCHAR
));
1720 src
->usri1_comment
= str
;
1721 lstrcpyW(src
->usri1_comment
, dest
->usri1_comment
);
1723 ((PBYTE
) str
) + (lstrlenW(str
) + 1) * sizeof(WCHAR
));
1725 src
->usri1_flags
= dest
->usri1_flags
;
1727 src
->usri1_full_name
= str
;
1728 lstrcpyW(src
->usri1_full_name
, dest
->usri1_full_name
);
1730 ((PBYTE
) str
) + (lstrlenW(str
) + 1) * sizeof(WCHAR
));
1732 src
->usri1_user_id
= dest
->usri1_user_id
;
1733 src
->usri1_next_index
= dest
->usri1_next_index
;
1737 /************************************************************
1738 * NetQueryDisplayInformation (NETAPI32.@)
1740 * The buffer structure:
1741 * - array of fixed size record of the level type
1742 * - strings, referenced by the record of the level type
1744 NET_API_STATUS WINAPI
1745 NetQueryDisplayInformation(
1746 LPCWSTR ServerName
, DWORD Level
, DWORD Index
, DWORD EntriesRequested
,
1747 DWORD PreferredMaximumLength
, LPDWORD ReturnedEntryCount
,
1748 PVOID
*SortedBuffer
)
1750 TRACE("(%s, %d, %d, %d, %d, %p, %p)\n", debugstr_w(ServerName
),
1751 Level
, Index
, EntriesRequested
, PreferredMaximumLength
,
1752 ReturnedEntryCount
, SortedBuffer
);
1754 if(!NETAPI_IsLocalComputer(ServerName
))
1756 FIXME("Only implemented on local computer, but requested for "
1757 "remote server %s\n", debugstr_w(ServerName
));
1758 return ERROR_ACCESS_DENIED
;
1765 /* current record */
1766 PNET_DISPLAY_USER inf
;
1767 /* current available strings buffer */
1769 PNET_DISPLAY_USER admin
, guest
;
1770 DWORD admin_size
, guest_size
;
1774 /* sizes of the field buffers in WCHARS */
1775 int name_sz
, comment_sz
, full_name_sz
;
1777 /* number of the records, returned in SortedBuffer
1778 3 - for current user, Administrator and Guest users
1782 FIXME("Level %d partially implemented\n", Level
);
1783 *ReturnedEntryCount
= records
;
1789 NetApiBufferAllocate(dwSize
* sizeof(WCHAR
), (LPVOID
*) &name
);
1790 if (!GetUserNameW(name
, &dwSize
))
1792 NetApiBufferFree(name
);
1793 return ERROR_ACCESS_DENIED
;
1796 ACCESS_QueryAdminDisplayInformation(&admin
, &admin_size
);
1797 ACCESS_QueryGuestDisplayInformation(&guest
, &guest_size
);
1800 dwSize
= sizeof(NET_DISPLAY_USER
) * records
;
1801 dwSize
+= (name_sz
+ comment_sz
+ full_name_sz
) * sizeof(WCHAR
);
1803 NetApiBufferAllocate(dwSize
+
1804 admin_size
- sizeof(NET_DISPLAY_USER
) +
1805 guest_size
- sizeof(NET_DISPLAY_USER
),
1807 inf
= *SortedBuffer
;
1808 str
= (LPWSTR
) ((PBYTE
) inf
+ sizeof(NET_DISPLAY_USER
) * records
);
1809 inf
->usri1_name
= str
;
1811 ((PBYTE
) str
) + name_sz
* sizeof(WCHAR
));
1812 inf
->usri1_comment
= str
;
1814 ((PBYTE
) str
) + comment_sz
* sizeof(WCHAR
));
1815 inf
->usri1_full_name
= str
;
1817 ((PBYTE
) str
) + full_name_sz
* sizeof(WCHAR
));
1820 lstrcpyW(inf
->usri1_name
, name
);
1821 NetApiBufferFree(name
);
1822 inf
->usri1_comment
[0] = 0;
1824 UF_SCRIPT
| UF_NORMAL_ACCOUNT
| UF_DONT_EXPIRE_PASSWD
;
1825 inf
->usri1_full_name
[0] = 0;
1826 inf
->usri1_user_id
= 0;
1827 inf
->usri1_next_index
= 0;
1830 ACCESS_CopyDisplayUser(admin
, &str
, inf
);
1831 NetApiBufferFree(admin
);
1834 ACCESS_CopyDisplayUser(guest
, &str
, inf
);
1835 NetApiBufferFree(guest
);
1842 FIXME("Level %d is not implemented\n", Level
);
1847 TRACE("Invalid level %d is specified\n", Level
);
1848 return ERROR_INVALID_LEVEL
;
1850 return NERR_Success
;
1853 /************************************************************
1854 * NetGetDCName (NETAPI32.@)
1856 * Return the name of the primary domain controller (PDC)
1859 NET_API_STATUS WINAPI
1860 NetGetDCName(LPCWSTR servername
, LPCWSTR domainname
, LPBYTE
*bufptr
)
1862 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername
),
1863 debugstr_w(domainname
), bufptr
);
1864 return NERR_DCNotFound
; /* say we can't find a domain controller */
1867 /************************************************************
1868 * NetGetAnyDCName (NETAPI32.@)
1870 * Return the name of any domain controller (DC) for a
1871 * domain that is directly trusted by the specified server
1874 NET_API_STATUS WINAPI
NetGetAnyDCName(LPCWSTR servername
, LPCWSTR domainname
, LPBYTE
*bufptr
)
1876 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername
),
1877 debugstr_w(domainname
), bufptr
);
1878 return ERROR_NO_SUCH_DOMAIN
;
1881 /************************************************************
1882 * NetGroupAddUser (NETAPI32.@)
1884 NET_API_STATUS WINAPI
1885 NetGroupAddUser(LPCWSTR servername
, LPCWSTR groupname
, LPCWSTR username
)
1887 FIXME("(%s, %s, %s) stub!\n", debugstr_w(servername
),
1888 debugstr_w(groupname
), debugstr_w(username
));
1889 return NERR_Success
;
1892 /************************************************************
1893 * NetGroupEnum (NETAPI32.@)
1896 NET_API_STATUS WINAPI
1897 NetGroupEnum(LPCWSTR servername
, DWORD level
, LPBYTE
*bufptr
, DWORD prefmaxlen
,
1898 LPDWORD entriesread
, LPDWORD totalentries
, LPDWORD resume_handle
)
1900 FIXME("(%s, %d, %p, %d, %p, %p, %p) stub!\n", debugstr_w(servername
),
1901 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resume_handle
);
1902 return ERROR_ACCESS_DENIED
;
1905 /************************************************************
1906 * NetGroupGetInfo (NETAPI32.@)
1909 NET_API_STATUS WINAPI
NetGroupGetInfo(LPCWSTR servername
, LPCWSTR groupname
, DWORD level
, LPBYTE
*bufptr
)
1911 FIXME("(%s, %s, %d, %p) stub!\n", debugstr_w(servername
), debugstr_w(groupname
), level
, bufptr
);
1912 return ERROR_ACCESS_DENIED
;
1915 /******************************************************************************
1916 * NetUserModalsGet (NETAPI32.@)
1918 * Retrieves global information for all users and global groups in the security
1922 * szServer [I] Specifies the DNS or the NetBIOS name of the remote server
1923 * on which the function is to execute.
1924 * level [I] Information level of the data.
1925 * 0 Return global passwords parameters. bufptr points to a
1926 * USER_MODALS_INFO_0 struct.
1927 * 1 Return logon server and domain controller information. bufptr
1928 * points to a USER_MODALS_INFO_1 struct.
1929 * 2 Return domain name and identifier. bufptr points to a
1930 * USER_MODALS_INFO_2 struct.
1931 * 3 Return lockout information. bufptr points to a USER_MODALS_INFO_3
1933 * pbuffer [I] Buffer that receives the data.
1936 * Success: NERR_Success.
1938 * ERROR_ACCESS_DENIED - the user does not have access to the info.
1939 * NERR_InvalidComputer - computer name is invalid.
1941 NET_API_STATUS WINAPI
NetUserModalsGet(
1942 LPCWSTR szServer
, DWORD level
, LPBYTE
*pbuffer
)
1944 TRACE("(%s %d %p)\n", debugstr_w(szServer
), level
, pbuffer
);
1949 /* return global passwords parameters */
1950 FIXME("level 0 not implemented!\n");
1952 return NERR_InternalError
;
1954 /* return logon server and domain controller info */
1955 FIXME("level 1 not implemented!\n");
1957 return NERR_InternalError
;
1960 /* return domain name and identifier */
1961 PUSER_MODALS_INFO_2 umi
;
1962 LSA_HANDLE policyHandle
;
1963 LSA_OBJECT_ATTRIBUTES objectAttributes
;
1964 PPOLICY_ACCOUNT_DOMAIN_INFO domainInfo
;
1966 PSID domainIdentifier
= NULL
;
1969 ZeroMemory(&objectAttributes
, sizeof(objectAttributes
));
1970 objectAttributes
.Length
= sizeof(objectAttributes
);
1972 ntStatus
= LsaOpenPolicy(NULL
, &objectAttributes
,
1973 POLICY_VIEW_LOCAL_INFORMATION
,
1975 if (ntStatus
!= STATUS_SUCCESS
)
1977 WARN("LsaOpenPolicy failed with NT status %x\n",
1978 LsaNtStatusToWinError(ntStatus
));
1982 ntStatus
= LsaQueryInformationPolicy(policyHandle
,
1983 PolicyAccountDomainInformation
,
1984 (PVOID
*)&domainInfo
);
1985 if (ntStatus
!= STATUS_SUCCESS
)
1987 WARN("LsaQueryInformationPolicy failed with NT status %x\n",
1988 LsaNtStatusToWinError(ntStatus
));
1989 LsaClose(policyHandle
);
1993 domainIdentifier
= domainInfo
->DomainSid
;
1994 domainNameLen
= lstrlenW(domainInfo
->DomainName
.Buffer
) + 1;
1995 LsaClose(policyHandle
);
1997 ntStatus
= NetApiBufferAllocate(sizeof(USER_MODALS_INFO_2
) +
1998 GetLengthSid(domainIdentifier
) +
1999 domainNameLen
* sizeof(WCHAR
),
2002 if (ntStatus
!= NERR_Success
)
2004 WARN("NetApiBufferAllocate() failed\n");
2005 LsaFreeMemory(domainInfo
);
2009 umi
= (USER_MODALS_INFO_2
*) *pbuffer
;
2010 umi
->usrmod2_domain_id
= *pbuffer
+ sizeof(USER_MODALS_INFO_2
);
2011 umi
->usrmod2_domain_name
= (LPWSTR
)(*pbuffer
+
2012 sizeof(USER_MODALS_INFO_2
) + GetLengthSid(domainIdentifier
));
2014 lstrcpynW(umi
->usrmod2_domain_name
,
2015 domainInfo
->DomainName
.Buffer
,
2017 CopySid(GetLengthSid(domainIdentifier
), umi
->usrmod2_domain_id
,
2020 LsaFreeMemory(domainInfo
);
2025 /* return lockout information */
2026 FIXME("level 3 not implemented!\n");
2028 return NERR_InternalError
;
2030 TRACE("Invalid level %d is specified\n", level
);
2032 return ERROR_INVALID_LEVEL
;
2035 return NERR_Success
;
2038 /******************************************************************************
2039 * NetUserChangePassword (NETAPI32.@)
2041 * domainname [I] Optional. Domain on which the user resides or the logon
2042 * domain of the current user if NULL.
2043 * username [I] Optional. Username to change the password for or the name
2044 * of the current user if NULL.
2045 * oldpassword [I] The user's current password.
2046 * newpassword [I] The password that the user will be changed to using.
2049 * Success: NERR_Success.
2050 * Failure: NERR_* failure code or win error code.
2053 NET_API_STATUS WINAPI
NetUserChangePassword(LPCWSTR domainname
, LPCWSTR username
,
2054 LPCWSTR oldpassword
, LPCWSTR newpassword
)
2056 struct sam_user
*user
;
2058 TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname
), debugstr_w(username
));
2060 if (!samba_init()) return ERROR_DLL_INIT_FAILED
;
2062 if (!samba_funcs
->change_password( domainname
, username
, oldpassword
, newpassword
))
2063 return NERR_Success
;
2066 FIXME("Ignoring domainname %s.\n", debugstr_w(domainname
));
2068 if((user
= NETAPI_FindUser(username
)) == NULL
)
2069 return NERR_UserNotFound
;
2071 if(wcscmp(user
->user_password
, oldpassword
) != 0)
2072 return ERROR_INVALID_PASSWORD
;
2074 if(lstrlenW(newpassword
) > PWLEN
)
2075 return ERROR_PASSWORD_RESTRICTION
;
2077 lstrcpyW(user
->user_password
, newpassword
);
2079 return NERR_Success
;
2082 NET_API_STATUS WINAPI
NetUseAdd(LMSTR servername
, DWORD level
, LPBYTE bufptr
, LPDWORD parm_err
)
2084 FIXME("%s %d %p %p stub\n", debugstr_w(servername
), level
, bufptr
, parm_err
);
2085 return NERR_Success
;
2088 NET_API_STATUS WINAPI
NetUseDel(LMSTR servername
, LMSTR usename
, DWORD forcecond
)
2090 FIXME("%s %s %d stub\n", debugstr_w(servername
), debugstr_w(usename
), forcecond
);
2091 return NERR_Success
;
2094 /************************************************************
2095 * I_BrowserSetNetlogonState (NETAPI32.@)
2097 NET_API_STATUS WINAPI
I_BrowserSetNetlogonState(
2098 LPWSTR ServerName
, LPWSTR DomainName
, LPWSTR EmulatedServerName
,
2101 return ERROR_NOT_SUPPORTED
;
2104 /************************************************************
2105 * I_BrowserQueryEmulatedDomains (NETAPI32.@)
2107 NET_API_STATUS WINAPI
I_BrowserQueryEmulatedDomains(
2108 LPWSTR ServerName
, PBROWSER_EMULATED_DOMAIN
*EmulatedDomains
,
2109 LPDWORD EntriesRead
)
2111 return ERROR_NOT_SUPPORTED
;
2114 #define NS_MAXDNAME 1025
2116 static DWORD
get_dc_info(const WCHAR
*domain
, WCHAR
*dc
, WCHAR
*ip
)
2118 WCHAR name
[NS_MAXDNAME
];
2122 wcscpy( name
, L
"_ldap._tcp.dc._msdcs." );
2123 wcscat( name
, domain
);
2125 ret
= DnsQuery_W(name
, DNS_TYPE_SRV
, DNS_QUERY_STANDARD
, NULL
, &rec
, NULL
);
2126 TRACE("DnsQuery_W(%s) => %d\n", wine_dbgstr_w(domain
), ret
);
2127 if (ret
== ERROR_SUCCESS
)
2129 TRACE("target %s, port %d\n", wine_dbgstr_w(rec
->Data
.Srv
.pNameTarget
), rec
->Data
.Srv
.wPort
);
2131 lstrcpynW(dc
, rec
->Data
.Srv
.pNameTarget
, NS_MAXDNAME
);
2132 DnsRecordListFree(rec
, DnsFreeRecordList
);
2135 ret
= DnsQuery_W(dc
, DNS_TYPE_A
, DNS_QUERY_STANDARD
, NULL
, &rec
, NULL
);
2136 TRACE("DnsQuery_W(%s) => %d\n", wine_dbgstr_w(dc
), ret
);
2137 if (ret
== ERROR_SUCCESS
)
2141 addr
.sin_family
= AF_INET
;
2143 addr
.sin_addr
.s_addr
= rec
->Data
.A
.IpAddress
;
2144 size
= IP6_ADDRESS_STRING_LENGTH
;
2145 ret
= WSAAddressToStringW((SOCKADDR
*)&addr
, sizeof(addr
), NULL
, ip
, &size
);
2147 TRACE("WSAAddressToStringW => %d, %s\n", ret
, wine_dbgstr_w(ip
));
2149 DnsRecordListFree(rec
, DnsFreeRecordList
);
2155 ret
= DnsQuery_W(dc
, DNS_TYPE_AAAA
, DNS_QUERY_STANDARD
, NULL
, &rec
, NULL
);
2156 TRACE("DnsQuery_W(%s) => %d\n", wine_dbgstr_w(dc
), ret
);
2157 if (ret
== ERROR_SUCCESS
)
2161 addr
.sin6_family
= AF_INET6
;
2163 addr
.sin6_scope_id
= 0;
2164 memcpy(addr
.sin6_addr
.s6_addr
, &rec
->Data
.AAAA
.Ip6Address
, sizeof(rec
->Data
.AAAA
.Ip6Address
));
2165 size
= IP6_ADDRESS_STRING_LENGTH
;
2166 ret
= WSAAddressToStringW((SOCKADDR
*)&addr
, sizeof(addr
), NULL
, ip
, &size
);
2168 TRACE("WSAAddressToStringW => %d, %s\n", ret
, wine_dbgstr_w(ip
));
2170 DnsRecordListFree(rec
, DnsFreeRecordList
);
2177 DWORD WINAPI
DsGetDcNameW(LPCWSTR computer
, LPCWSTR domain
, GUID
*domain_guid
,
2178 LPCWSTR site
, ULONG flags
, PDOMAIN_CONTROLLER_INFOW
*dc_info
)
2180 static const WCHAR pfxW
[] = {'\\','\\'};
2181 static const WCHAR default_site_nameW
[] = L
"Default-First-Site-Name";
2183 POLICY_DNS_DOMAIN_INFO
*dns_domain_info
= NULL
;
2184 DOMAIN_CONTROLLER_INFOW
*info
;
2185 WCHAR dc
[NS_MAXDNAME
], ip
[IP6_ADDRESS_STRING_LENGTH
];
2188 FIXME("(%s, %s, %s, %s, %08x, %p): semi-stub\n", debugstr_w(computer
),
2189 debugstr_w(domain
), debugstr_guid(domain_guid
), debugstr_w(site
), flags
, dc_info
);
2191 if (!dc_info
) return ERROR_INVALID_PARAMETER
;
2195 LSA_OBJECT_ATTRIBUTES attrs
;
2198 memset(&attrs
, 0, sizeof(attrs
));
2199 attrs
.Length
= sizeof(attrs
);
2200 status
= LsaOpenPolicy(NULL
, &attrs
, POLICY_VIEW_LOCAL_INFORMATION
, &lsa
);
2202 return LsaNtStatusToWinError(status
);
2204 status
= LsaQueryInformationPolicy(lsa
, PolicyDnsDomainInformation
, (void **)&dns_domain_info
);
2207 return LsaNtStatusToWinError(status
);
2209 domain
= dns_domain_info
->DnsDomainName
.Buffer
;
2212 status
= get_dc_info(domain
, dc
, ip
);
2213 if (status
) return status
;
2215 size
= sizeof(DOMAIN_CONTROLLER_INFOW
) + lstrlenW(domain
) * sizeof(WCHAR
) +
2216 sizeof(pfxW
) * 2 + (lstrlenW(dc
) + 1 + lstrlenW(ip
) + 1) * sizeof(WCHAR
) +
2217 lstrlenW(domain
) * sizeof(WCHAR
) /* assume forest == domain */ +
2218 sizeof(default_site_nameW
) * 2;
2219 status
= NetApiBufferAllocate(size
, (void **)&info
);
2220 if (status
!= NERR_Success
)
2222 LsaFreeMemory(dns_domain_info
);
2223 return ERROR_NOT_ENOUGH_MEMORY
;
2226 info
->DomainControllerName
= (WCHAR
*)(info
+ 1);
2227 memcpy(info
->DomainControllerName
, pfxW
, sizeof(pfxW
));
2228 lstrcpyW(info
->DomainControllerName
+ 2, dc
);
2229 info
->DomainControllerAddress
= (WCHAR
*)((char *)info
->DomainControllerName
+ (wcslen(info
->DomainControllerName
) + 1) * sizeof(WCHAR
));
2230 memcpy(info
->DomainControllerAddress
, pfxW
, sizeof(pfxW
));
2231 lstrcpyW(info
->DomainControllerAddress
+ 2, ip
);
2232 info
->DomainControllerAddressType
= DS_INET_ADDRESS
;
2233 info
->DomainGuid
= dns_domain_info
? dns_domain_info
->DomainGuid
: GUID_NULL
/* FIXME */;
2234 info
->DomainName
= (WCHAR
*)((char *)info
->DomainControllerAddress
+ (wcslen(info
->DomainControllerAddress
) + 1) * sizeof(WCHAR
));
2235 lstrcpyW(info
->DomainName
, domain
);
2236 info
->DnsForestName
= (WCHAR
*)((char *)info
->DomainName
+ (lstrlenW(info
->DomainName
) + 1) * sizeof(WCHAR
));
2237 lstrcpyW(info
->DnsForestName
, domain
);
2238 info
->DcSiteName
= (WCHAR
*)((char *)info
->DnsForestName
+ (lstrlenW(info
->DnsForestName
) + 1) * sizeof(WCHAR
));
2239 lstrcpyW(info
->DcSiteName
, default_site_nameW
);
2240 info
->ClientSiteName
= (WCHAR
*)((char *)info
->DcSiteName
+ sizeof(default_site_nameW
));
2241 lstrcpyW(info
->ClientSiteName
, default_site_nameW
);
2242 info
->Flags
= DS_DNS_DOMAIN_FLAG
| DS_DNS_FOREST_FLAG
;
2244 LsaFreeMemory(dns_domain_info
);
2248 return ERROR_SUCCESS
;
2251 DWORD WINAPI
DsGetDcNameA(LPCSTR ComputerName
, LPCSTR AvoidDCName
,
2252 GUID
* DomainGuid
, LPCSTR SiteName
, ULONG Flags
,
2253 PDOMAIN_CONTROLLER_INFOA
*DomainControllerInfo
)
2255 FIXME("(%s, %s, %s, %s, %08x, %p): stub\n", debugstr_a(ComputerName
),
2256 debugstr_a(AvoidDCName
), debugstr_guid(DomainGuid
),
2257 debugstr_a(SiteName
), Flags
, DomainControllerInfo
);
2258 return ERROR_CALL_NOT_IMPLEMENTED
;
2261 DWORD WINAPI
DsGetSiteNameW(LPCWSTR ComputerName
, LPWSTR
*SiteName
)
2263 FIXME("(%s, %p): stub\n", debugstr_w(ComputerName
), SiteName
);
2264 return ERROR_CALL_NOT_IMPLEMENTED
;
2267 DWORD WINAPI
DsGetSiteNameA(LPCSTR ComputerName
, LPSTR
*SiteName
)
2269 FIXME("(%s, %p): stub\n", debugstr_a(ComputerName
), SiteName
);
2270 return ERROR_CALL_NOT_IMPLEMENTED
;
2273 /************************************************************
2274 * DsRoleFreeMemory (NETAPI32.@)
2277 * Buffer [I] Pointer to the to-be-freed buffer.
2282 VOID WINAPI
DsRoleFreeMemory(PVOID Buffer
)
2284 TRACE("(%p)\n", Buffer
);
2285 HeapFree(GetProcessHeap(), 0, Buffer
);
2288 /************************************************************
2289 * DsRoleGetPrimaryDomainInformation (NETAPI32.@)
2292 * lpServer [I] Pointer to UNICODE string with ComputerName
2293 * InfoLevel [I] Type of data to retrieve
2294 * Buffer [O] Pointer to to the requested data
2299 * When lpServer is NULL, use the local computer
2301 DWORD WINAPI
DsRoleGetPrimaryDomainInformation(
2302 LPCWSTR lpServer
, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel
,
2307 FIXME("(%p, %d, %p) stub\n", lpServer
, InfoLevel
, Buffer
);
2309 /* Check some input parameters */
2311 if (!Buffer
) return ERROR_INVALID_PARAMETER
;
2312 if ((InfoLevel
< DsRolePrimaryDomainInfoBasic
) || (InfoLevel
> DsRoleOperationState
)) return ERROR_INVALID_PARAMETER
;
2317 case DsRolePrimaryDomainInfoBasic
:
2319 LSA_OBJECT_ATTRIBUTES ObjectAttributes
;
2320 LSA_HANDLE PolicyHandle
;
2321 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo
;
2323 int logon_domain_sz
;
2325 PDSROLE_PRIMARY_DOMAIN_INFO_BASIC basic
;
2327 ZeroMemory(&ObjectAttributes
, sizeof(ObjectAttributes
));
2328 NtStatus
= LsaOpenPolicy(NULL
, &ObjectAttributes
,
2329 POLICY_VIEW_LOCAL_INFORMATION
, &PolicyHandle
);
2330 if (NtStatus
!= STATUS_SUCCESS
)
2332 TRACE("LsaOpenPolicyFailed with NT status %x\n",
2333 LsaNtStatusToWinError(NtStatus
));
2334 return ERROR_OUTOFMEMORY
;
2336 LsaQueryInformationPolicy(PolicyHandle
,
2337 PolicyAccountDomainInformation
, (PVOID
*)&DomainInfo
);
2338 logon_domain_sz
= lstrlenW(DomainInfo
->DomainName
.Buffer
) + 1;
2339 LsaClose(PolicyHandle
);
2341 size
= sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC
) +
2342 logon_domain_sz
* sizeof(WCHAR
);
2343 basic
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
2346 basic
->MachineRole
= DsRole_RoleStandaloneWorkstation
;
2347 basic
->DomainNameFlat
= (LPWSTR
)((LPBYTE
)basic
+
2348 sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC
));
2349 lstrcpyW(basic
->DomainNameFlat
, DomainInfo
->DomainName
.Buffer
);
2350 ret
= ERROR_SUCCESS
;
2353 ret
= ERROR_OUTOFMEMORY
;
2354 *Buffer
= (PBYTE
)basic
;
2355 LsaFreeMemory(DomainInfo
);
2359 ret
= ERROR_CALL_NOT_IMPLEMENTED
;
2364 /************************************************************
2365 * NetLocalGroupAdd (NETAPI32.@)
2367 NET_API_STATUS WINAPI
NetLocalGroupAdd(
2373 FIXME("(%s %d %p %p) stub!\n", debugstr_w(servername
), level
, buf
,
2375 return NERR_Success
;
2378 /************************************************************
2379 * NetLocalGroupAddMember (NETAPI32.@)
2381 NET_API_STATUS WINAPI
NetLocalGroupAddMember(
2386 FIXME("(%s %s %p) stub!\n", debugstr_w(servername
),
2387 debugstr_w(groupname
), membersid
);
2388 return NERR_Success
;
2391 /************************************************************
2392 * NetLocalGroupAddMembers (NETAPI32.@)
2394 NET_API_STATUS WINAPI
NetLocalGroupAddMembers(
2401 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
2402 debugstr_w(groupname
), level
, buf
, totalentries
);
2403 return NERR_Success
;
2406 /************************************************************
2407 * NetLocalGroupDel (NETAPI32.@)
2409 NET_API_STATUS WINAPI
NetLocalGroupDel(
2413 FIXME("(%s %s) stub!\n", debugstr_w(servername
), debugstr_w(groupname
));
2414 return NERR_Success
;
2417 /************************************************************
2418 * NetLocalGroupDelMember (NETAPI32.@)
2420 NET_API_STATUS WINAPI
NetLocalGroupDelMember(
2425 FIXME("(%s %s %p) stub!\n", debugstr_w(servername
),
2426 debugstr_w(groupname
), membersid
);
2427 return NERR_Success
;
2430 /************************************************************
2431 * NetLocalGroupDelMembers (NETAPI32.@)
2433 NET_API_STATUS WINAPI
NetLocalGroupDelMembers(
2440 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
2441 debugstr_w(groupname
), level
, buf
, totalentries
);
2442 return NERR_Success
;
2445 /************************************************************
2446 * NetLocalGroupEnum (NETAPI32.@)
2448 NET_API_STATUS WINAPI
NetLocalGroupEnum(
2453 LPDWORD entriesread
,
2454 LPDWORD totalentries
,
2455 PDWORD_PTR resumehandle
)
2457 FIXME("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername
),
2458 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resumehandle
);
2461 return NERR_Success
;
2464 /************************************************************
2465 * NetLocalGroupGetInfo (NETAPI32.@)
2467 NET_API_STATUS WINAPI
NetLocalGroupGetInfo(
2473 static const WCHAR commentW
[] = L
"No comment";
2474 LOCALGROUP_INFO_1
* info
;
2477 FIXME("(%s %s %d %p) semi-stub!\n", debugstr_w(servername
),
2478 debugstr_w(groupname
), level
, bufptr
);
2480 size
= sizeof(*info
) + sizeof(WCHAR
) * (lstrlenW(groupname
)+1) + sizeof(commentW
);
2481 NetApiBufferAllocate(size
, (LPVOID
*)&info
);
2483 info
->lgrpi1_name
= (LPWSTR
)(info
+ 1);
2484 lstrcpyW(info
->lgrpi1_name
, groupname
);
2486 info
->lgrpi1_comment
= info
->lgrpi1_name
+ lstrlenW(groupname
) + 1;
2487 lstrcpyW(info
->lgrpi1_comment
, commentW
);
2489 *bufptr
= (LPBYTE
)info
;
2491 return NERR_Success
;
2494 /************************************************************
2495 * NetLocalGroupGetMembers (NETAPI32.@)
2497 NET_API_STATUS WINAPI
NetLocalGroupGetMembers(
2499 LPCWSTR localgroupname
,
2503 LPDWORD entriesread
,
2504 LPDWORD totalentries
,
2505 PDWORD_PTR resumehandle
)
2507 FIXME("(%s %s %d %p %d, %p %p %p) stub!\n", debugstr_w(servername
),
2508 debugstr_w(localgroupname
), level
, bufptr
, prefmaxlen
, entriesread
,
2509 totalentries
, resumehandle
);
2513 WCHAR userName
[MAX_COMPUTERNAME_LENGTH
+ 1];
2516 PLOCALGROUP_MEMBERS_INFO_3 ptr
;
2518 /* still a stub, current user is belonging to all groups */
2523 userNameLen
= MAX_COMPUTERNAME_LENGTH
+ 1;
2524 if (!GetUserNameW(userName
,&userNameLen
))
2525 return ERROR_NOT_ENOUGH_MEMORY
;
2527 needlen
= sizeof(LOCALGROUP_MEMBERS_INFO_3
) +
2528 (userNameLen
+2) * sizeof(WCHAR
);
2529 if (prefmaxlen
!= MAX_PREFERRED_LENGTH
)
2530 len
= min(prefmaxlen
,needlen
);
2534 NetApiBufferAllocate(len
, (LPVOID
*) bufptr
);
2536 return ERROR_MORE_DATA
;
2538 ptr
= (PLOCALGROUP_MEMBERS_INFO_3
)*bufptr
;
2539 ptr
->lgrmi3_domainandname
= (LPWSTR
)(*bufptr
+sizeof(LOCALGROUP_MEMBERS_INFO_3
));
2540 lstrcpyW(ptr
->lgrmi3_domainandname
,userName
);
2545 return NERR_Success
;
2548 /************************************************************
2549 * NetLocalGroupSetInfo (NETAPI32.@)
2551 NET_API_STATUS WINAPI
NetLocalGroupSetInfo(
2558 FIXME("(%s %s %d %p %p) stub!\n", debugstr_w(servername
),
2559 debugstr_w(groupname
), level
, buf
, parm_err
);
2560 return NERR_Success
;
2563 /************************************************************
2564 * NetLocalGroupSetMember (NETAPI32.@)
2566 NET_API_STATUS WINAPI
NetLocalGroupSetMembers(
2573 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
2574 debugstr_w(groupname
), level
, buf
, totalentries
);
2575 return NERR_Success
;
2578 /************************************************************
2579 * DavGetHTTPFromUNCPath (NETAPI32.@)
2581 DWORD WINAPI
DavGetHTTPFromUNCPath(const WCHAR
*unc_path
, WCHAR
*buf
, DWORD
*buflen
)
2583 static const WCHAR httpW
[] = L
"http://";
2584 static const WCHAR httpsW
[] = L
"https://";
2585 const WCHAR
*p
= unc_path
, *q
, *server
, *path
, *scheme
= httpW
;
2586 UINT i
, len_server
, len_path
= 0, len_port
= 0, len
, port
= 0;
2587 WCHAR
*end
, portbuf
[12];
2589 TRACE("(%s %p %p)\n", debugstr_w(unc_path
), buf
, buflen
);
2591 if (p
[0] != '\\' || p
[1] != '\\' || !p
[2]) return ERROR_INVALID_PARAMETER
;
2593 while (*q
&& *q
!= '\\' && *q
!= '/' && *q
!= '@') q
++;
2599 while (*p
&& (*p
!= '\\' && *p
!= '/' && *p
!= '@')) p
++;
2600 if (p
- q
== 3 && !wcsnicmp( q
, L
"SSL", 3 ))
2605 else if ((port
= wcstol( q
, &end
, 10 ))) q
= end
;
2606 else return ERROR_INVALID_PARAMETER
;
2610 if (!(port
= wcstol( ++q
, &end
, 10 ))) return ERROR_INVALID_PARAMETER
;
2613 if (*q
== '\\' || *q
== '/') q
++;
2615 while (*q
++) len_path
++;
2616 if (len_path
&& (path
[len_path
- 1] == '\\' || path
[len_path
- 1] == '/'))
2617 len_path
--; /* remove trailing slash */
2619 swprintf( portbuf
, ARRAY_SIZE(portbuf
), L
":%u", port
);
2620 if (scheme
== httpsW
)
2622 len
= wcslen( httpsW
);
2623 if (port
&& port
!= 443) len_port
= wcslen( portbuf
);
2627 len
= wcslen( httpW
);
2628 if (port
&& port
!= 80) len_port
= wcslen( portbuf
);
2632 if (len_path
) len
+= len_path
+ 1; /* leading '/' */
2638 return ERROR_INSUFFICIENT_BUFFER
;
2641 memcpy( buf
, scheme
, wcslen(scheme
) * sizeof(WCHAR
) );
2642 buf
+= wcslen( scheme
);
2643 memcpy( buf
, server
, len_server
* sizeof(WCHAR
) );
2647 memcpy( buf
, portbuf
, len_port
* sizeof(WCHAR
) );
2653 for (i
= 0; i
< len_path
; i
++)
2655 if (path
[i
] == '\\') *buf
++ = '/';
2656 else *buf
++ = path
[i
];
2662 return ERROR_SUCCESS
;
2665 /************************************************************
2666 * DavGetUNCFromHTTPPath (NETAPI32.@)
2668 DWORD WINAPI
DavGetUNCFromHTTPPath(const WCHAR
*http_path
, WCHAR
*buf
, DWORD
*buflen
)
2670 static const WCHAR httpW
[] = {'h','t','t','p'};
2671 static const WCHAR httpsW
[] = {'h','t','t','p','s'};
2672 static const WCHAR davrootW
[] = {'\\','D','a','v','W','W','W','R','o','o','t'};
2673 static const WCHAR sslW
[] = {'@','S','S','L'};
2674 static const WCHAR port80W
[] = {'8','0'};
2675 static const WCHAR port443W
[] = {'4','4','3'};
2676 const WCHAR
*p
= http_path
, *server
, *port
= NULL
, *path
= NULL
;
2677 DWORD i
, len
= 0, len_server
= 0, len_port
= 0, len_path
= 0;
2680 TRACE("(%s %p %p)\n", debugstr_w(http_path
), buf
, buflen
);
2682 while (*p
&& *p
!= ':') { p
++; len
++; };
2683 if (len
== ARRAY_SIZE(httpW
) && !wcsnicmp( http_path
, httpW
, len
)) ssl
= FALSE
;
2684 else if (len
== ARRAY_SIZE(httpsW
) && !wcsnicmp( http_path
, httpsW
, len
)) ssl
= TRUE
;
2685 else return ERROR_INVALID_PARAMETER
;
2687 if (p
[0] != ':' || p
[1] != '/' || p
[2] != '/') return ERROR_INVALID_PARAMETER
;
2690 while (*p
&& *p
!= ':' && *p
!= '/') { p
++; len_server
++; };
2691 if (!len_server
) return ERROR_BAD_NET_NAME
;
2695 while (*p
>= '0' && *p
<= '9') { p
++; len_port
++; };
2696 if (len_port
== 2 && !ssl
&& !memcmp( port
, port80W
, sizeof(port80W
) )) port
= NULL
;
2697 else if (len_port
== 3 && ssl
&& !memcmp( port
, port443W
, sizeof(port443W
) )) port
= NULL
;
2700 else if (*p
== '/') path
= p
;
2704 if (p
[0] == '/' && p
[1] == '/') return ERROR_BAD_NET_NAME
;
2707 if (len_path
&& path
[len_path
- 1] == '/') len_path
--;
2709 len
= len_server
+ 2; /* \\ */
2710 if (ssl
) len
+= 4; /* @SSL */
2711 if (port
) len
+= len_port
+ 1 /* @ */;
2712 len
+= ARRAY_SIZE(davrootW
);
2713 len
+= len_path
+ 1; /* nul */
2718 return ERROR_INSUFFICIENT_BUFFER
;
2721 buf
[0] = buf
[1] = '\\';
2723 memcpy( buf
, server
, len_server
* sizeof(WCHAR
) );
2727 memcpy( buf
, sslW
, sizeof(sslW
) );
2733 memcpy( buf
, port
, len_port
* sizeof(WCHAR
) );
2736 memcpy( buf
, davrootW
, sizeof(davrootW
) );
2737 buf
+= ARRAY_SIZE(davrootW
);
2738 for (i
= 0; i
< len_path
; i
++)
2740 if (path
[i
] == '/') *buf
++ = '\\';
2741 else *buf
++ = path
[i
];
2747 return ERROR_SUCCESS
;
2750 /************************************************************
2751 * DsEnumerateDomainTrustsA (NETAPI32.@)
2753 DWORD WINAPI
DsEnumerateDomainTrustsA(LPSTR server
, ULONG flags
, PDS_DOMAIN_TRUSTSA
* domains
, PULONG count
)
2755 FIXME("(%s, 0x%04x, %p, %p): stub\n", debugstr_a(server
), flags
, domains
, count
);
2756 return ERROR_NO_LOGON_SERVERS
;
2759 /************************************************************
2760 * DsEnumerateDomainTrustsW (NETAPI32.@)
2762 DWORD WINAPI
DsEnumerateDomainTrustsW(LPWSTR server
, ULONG flags
, PDS_DOMAIN_TRUSTSW
* domains
, PULONG count
)
2764 FIXME("(%s, 0x%04x, %p, %p): stub\n", debugstr_w(server
), flags
, domains
, count
);
2765 return ERROR_NO_LOGON_SERVERS
;
2768 DECLSPEC_HIDDEN
void __RPC_FAR
*__RPC_USER
MIDL_user_allocate(SIZE_T n
)
2770 return HeapAlloc(GetProcessHeap(), 0, n
);
2773 DECLSPEC_HIDDEN
void __RPC_USER
MIDL_user_free(void __RPC_FAR
*p
)
2775 HeapFree(GetProcessHeap(), 0, p
);
2778 DECLSPEC_HIDDEN handle_t __RPC_USER
ATSVC_HANDLE_bind(ATSVC_HANDLE str
)
2780 static unsigned char ncalrpc
[] = "ncalrpc";
2781 unsigned char *binding_str
;
2782 handle_t rpc_handle
= 0;
2784 if (RpcStringBindingComposeA(NULL
, ncalrpc
, NULL
, NULL
, NULL
, &binding_str
) == RPC_S_OK
)
2786 RpcBindingFromStringBindingA(binding_str
, &rpc_handle
);
2787 RpcStringFreeA(&binding_str
);
2792 DECLSPEC_HIDDEN
void __RPC_USER
ATSVC_HANDLE_unbind(ATSVC_HANDLE ServerName
, handle_t rpc_handle
)
2794 RpcBindingFree(&rpc_handle
);