1606 lines
42 KiB
C
1606 lines
42 KiB
C
/*++
|
||
|
||
Copyright (c) 1991-1992 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
wksstub.c
|
||
|
||
Abstract:
|
||
|
||
Client stubs of the Browser service APIs.
|
||
|
||
Author:
|
||
|
||
Rita Wong (ritaw) 10-May-1991
|
||
Larry Osterman (LarryO) 23-Mar-1992
|
||
|
||
Environment:
|
||
|
||
User Mode - Win32
|
||
|
||
Revision History:
|
||
|
||
18-Jun-1991 JohnRo
|
||
Remote NetUse APIs to downlevel servers.
|
||
24-Jul-1991 JohnRo
|
||
Use NET_REMOTE_TRY_RPC etc macros for NetUse APIs.
|
||
Moved NetpIsServiceStarted() into NetLib.
|
||
25-Jul-1991 JohnRo
|
||
Quiet DLL stub debug output.
|
||
19-Aug-1991 JohnRo
|
||
Implement downlevel NetWksta APIs. Use NetRpc.h for NetWksta APIs.
|
||
07-Nov-1991 JohnRo
|
||
RAID 4186: assert in RxNetShareAdd and other DLL stub problems.
|
||
19-Nov-1991 JohnRo
|
||
Make sure status is correct for APIs not supported on downlevel.
|
||
Implement remote NetWkstaUserEnum().
|
||
09-Nov-1992 JohnRo
|
||
Fix NET_API_FUNCTION references.
|
||
Avoid compiler warnings.
|
||
--*/
|
||
|
||
#include "brclient.h"
|
||
#undef IF_DEBUG // avoid wsclient.h vs. debuglib.h conflicts.
|
||
#include <debuglib.h> // IF_DEBUG() (needed by netrpc.h).
|
||
#include <lmserver.h>
|
||
#include <lmsvc.h>
|
||
#include <rxuse.h> // RxNetUse APIs.
|
||
#include <rxwksta.h> // RxNetWksta and RxNetWkstaUser APIs.
|
||
#include <rap.h> // Needed by rxserver.h
|
||
#include <rxserver.h> // RxNetServerEnum API.
|
||
#include <netlib.h> // NetpServiceIsStarted() (needed by netrpc.h).
|
||
#include <ntddbrow.h> // Browser definitions
|
||
#include <netrpc.h> // NET_REMOTE macros.
|
||
#include <align.h>
|
||
#include <tstr.h>
|
||
#include <tstring.h> // NetpInitOemString().
|
||
#include <brcommon.h> // Routines common between client & server
|
||
#include <lmapibuf.h> // NetApiBufferFree().
|
||
#include <lmbrowsr.h> // Definition of I_BrowserServerEnum
|
||
#include <icanon.h>
|
||
#include <lmapibuf.h>
|
||
#include "cscp.h"
|
||
|
||
//-------------------------------------------------------------------//
|
||
// //
|
||
// Global variables //
|
||
// //
|
||
//-------------------------------------------------------------------//
|
||
|
||
#define API_SUCCESS(x) ((x) == NERR_Success || (x) == ERROR_MORE_DATA)
|
||
|
||
|
||
//-------------------------------------------------------------------//
|
||
// //
|
||
// Global types //
|
||
// //
|
||
//-------------------------------------------------------------------//
|
||
|
||
|
||
|
||
//-------------------------------------------------------------------//
|
||
// //
|
||
// Private routines //
|
||
// //
|
||
//-------------------------------------------------------------------//
|
||
|
||
|
||
NET_API_STATUS
|
||
GetBrowserTransportList(
|
||
OUT PLMDR_TRANSPORT_LIST *TransportList
|
||
);
|
||
|
||
NET_API_STATUS
|
||
EnumServersForTransport(
|
||
IN PUNICODE_STRING TransportName,
|
||
IN LPCWSTR DomainName OPTIONAL,
|
||
IN ULONG level,
|
||
IN ULONG prefmaxlen,
|
||
IN ULONG servertype,
|
||
IN LPTSTR CurrentComputerName,
|
||
OUT PINTERIM_SERVER_LIST InterimServerList,
|
||
OUT PULONG TotalEntriesOnThisTransport,
|
||
IN LPCWSTR FirstNameToReturn,
|
||
IN BOOLEAN WannishTransport,
|
||
IN BOOLEAN RasTransport,
|
||
IN BOOLEAN IPXTransport
|
||
);
|
||
|
||
#if DBG
|
||
void
|
||
ValidateServerList(
|
||
IN PVOID ServerList,
|
||
IN ULONG ulLevel,
|
||
IN ULONG ulEntries
|
||
);
|
||
#else
|
||
#define ValidateServerList(x,y,z)
|
||
#endif
|
||
|
||
NET_API_STATUS NET_API_FUNCTION
|
||
NetServerEnum(
|
||
IN LPCWSTR servername OPTIONAL,
|
||
IN DWORD level,
|
||
OUT LPBYTE *bufptr,
|
||
IN DWORD prefmaxlen,
|
||
OUT LPDWORD entriesread,
|
||
OUT LPDWORD totalentries,
|
||
IN DWORD servertype,
|
||
IN LPCWSTR domain OPTIONAL,
|
||
IN OUT LPDWORD resume_handle OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the DLL entrypoint for NetServerEnum.
|
||
|
||
Arguments:
|
||
|
||
servername - Supplies the name of server to execute this function
|
||
|
||
level - Supplies the requested level of information.
|
||
|
||
bufptr - Returns a pointer to a buffer which contains the
|
||
requested transport information.
|
||
|
||
prefmaxlen - Supplies the number of bytes of information
|
||
to return in the buffer. If this value is MAXULONG, we will try
|
||
to return all available information if there is enough memory
|
||
resource.
|
||
|
||
entriesread - Returns the number of entries read into the buffer. This
|
||
value is returned only if the return code is NERR_Success or
|
||
ERROR_MORE_DATA.
|
||
|
||
totalentries - Returns the total number of entries available. This value
|
||
is returned only if the return code is NERR_Success or ERROR_MORE_DATA.
|
||
|
||
servertype - Supplies the type of server to enumerate.
|
||
|
||
domain - Supplies the name of one of the active domains to enumerate the
|
||
servers from. If NULL, servers from the primary domain, logon domain
|
||
and other domains are enumerated.
|
||
|
||
resume_handle - Supplies and returns the point to continue with enumeration.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NET_API_STATUS NetStatus;
|
||
|
||
|
||
//
|
||
// NetServerEnum is simply a wrapper to NetServerEnumEx
|
||
//
|
||
|
||
NetStatus = NetServerEnumEx(
|
||
servername,
|
||
level,
|
||
bufptr,
|
||
prefmaxlen,
|
||
entriesread,
|
||
totalentries,
|
||
servertype,
|
||
domain,
|
||
NULL ); // NULL FirstNameToReturn
|
||
|
||
if (ARGUMENT_PRESENT(resume_handle)) {
|
||
*resume_handle = 0;
|
||
}
|
||
|
||
return NetStatus;
|
||
|
||
}
|
||
|
||
|
||
NET_API_STATUS NET_API_FUNCTION
|
||
NetServerEnumEx(
|
||
IN LPCWSTR servername OPTIONAL,
|
||
IN DWORD level,
|
||
OUT LPBYTE *bufptr,
|
||
IN DWORD prefmaxlen,
|
||
OUT LPDWORD entriesread,
|
||
OUT LPDWORD totalentries,
|
||
IN DWORD servertype,
|
||
IN LPCWSTR domain OPTIONAL,
|
||
IN LPCWSTR FirstNameToReturnArg OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the DLL entrypoint for NetServerEnum.
|
||
|
||
Arguments:
|
||
|
||
servername - Supplies the name of server to execute this function
|
||
|
||
level - Supplies the requested level of information.
|
||
|
||
bufptr - Returns a pointer to a buffer which contains the
|
||
requested transport information.
|
||
|
||
prefmaxlen - Supplies the number of bytes of information
|
||
to return in the buffer. If this value is MAXULONG, we will try
|
||
to return all available information if there is enough memory
|
||
resource.
|
||
|
||
entriesread - Returns the number of entries read into the buffer. This
|
||
value is returned only if the return code is NERR_Success or
|
||
ERROR_MORE_DATA.
|
||
|
||
totalentries - Returns the total number of entries available. This value
|
||
is returned only if the return code is NERR_Success or ERROR_MORE_DATA.
|
||
|
||
servertype - Supplies the type of server to enumerate.
|
||
|
||
domain - Supplies the name of one of the active domains to enumerate the
|
||
servers from. If NULL, servers from the primary domain, logon domain
|
||
and other domains are enumerated.
|
||
|
||
FirstNameToReturnArg - Supplies the name of the first domain or server entry to return.
|
||
The caller can use this parameter to implement a resume handle of sorts by passing
|
||
the name of the last entry returned on a previous call. (Notice that the specified
|
||
entry will, also, be returned on this call unless it has since been deleted.)
|
||
Pass NULL (or a zero length string) to start with the first entry available.
|
||
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
ERROR_MORE_DATA - More servers are available to be enumerated.
|
||
|
||
It is possible to return ERROR_MORE_DATA and zero entries in the case
|
||
where the browser server used doesn't support enumerating all the entries
|
||
it has. (e.g., an NT 3.5x Domain Master Browser that downloaded a domain
|
||
list from WINS and the WINS list is more than 64Kb long.) The caller
|
||
should simply ignore the additional data.
|
||
|
||
It is possible to fail to return ERROR_MORE_DATA and return a truncated
|
||
list. (e.g., an NT 3.5x Backup browser or WIN 95 backup browser in the
|
||
above mentioned domain. Such a backup browser replicates only 64kb
|
||
of data from the DMB (PDC) then represents that list as the entire list.)
|
||
The caller should ignore this problem. The site should upgrade its
|
||
browser servers.
|
||
|
||
--*/
|
||
{
|
||
PLMDR_TRANSPORT_LIST TransportList = NULL;
|
||
PLMDR_TRANSPORT_LIST TransportEntry = NULL;
|
||
INTERIM_SERVER_LIST InterimServerList;
|
||
NET_API_STATUS Status;
|
||
DWORD DomainNameSize = 0;
|
||
TCHAR DomainName[DNLEN + 1];
|
||
WCHAR FirstNameToReturn[DNLEN+1];
|
||
DWORD LocalTotalEntries;
|
||
BOOLEAN AnyTransportHasMoreData = FALSE;
|
||
|
||
//
|
||
//
|
||
// The workstation has to be started for the NetServerEnum API to work.
|
||
//
|
||
//
|
||
|
||
if ((Status = CheckForService(SERVICE_WORKSTATION, NULL)) != NERR_Success) {
|
||
return Status;
|
||
}
|
||
|
||
#ifdef ENABLE_PSEUDO_BROWSER
|
||
//
|
||
// Disabled NetServerEnum check
|
||
//
|
||
if ( !IsEnumServerEnabled() ||
|
||
GetBrowserPseudoServerLevel() == BROWSER_PSEUDO ) {
|
||
// NetServerEnum is disabled or pseudo server is
|
||
// enabled on box ==> return no entries.
|
||
*entriesread = 0;
|
||
*totalentries = 0;
|
||
*bufptr = NULL;
|
||
return NERR_Success;
|
||
}
|
||
#endif
|
||
|
||
|
||
//
|
||
// Canonicalize the input parameters to make later comparisons easier.
|
||
//
|
||
|
||
if (ARGUMENT_PRESENT(domain)) {
|
||
|
||
if ( I_NetNameCanonicalize(
|
||
NULL,
|
||
(LPWSTR) domain,
|
||
DomainName,
|
||
(DNLEN + 1) * sizeof(TCHAR),
|
||
NAMETYPE_WORKGROUP,
|
||
LM2X_COMPATIBLE
|
||
) != NERR_Success) {
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
DomainNameSize = STRLEN(DomainName) * sizeof(WCHAR);
|
||
|
||
domain = DomainName;
|
||
}
|
||
|
||
if (ARGUMENT_PRESENT(FirstNameToReturnArg) && *FirstNameToReturnArg != L'\0') {
|
||
|
||
if ( I_NetNameCanonicalize(
|
||
NULL,
|
||
(LPWSTR) FirstNameToReturnArg,
|
||
FirstNameToReturn,
|
||
sizeof(FirstNameToReturn),
|
||
NAMETYPE_WORKGROUP,
|
||
LM2X_COMPATIBLE
|
||
) != NERR_Success) {
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
} else {
|
||
FirstNameToReturn[0] = L'\0';
|
||
}
|
||
|
||
if ((servername != NULL) &&
|
||
( *servername != TCHAR_EOS)) {
|
||
|
||
//
|
||
// Call downlevel version of the API
|
||
//
|
||
|
||
Status = RxNetServerEnum(
|
||
servername,
|
||
NULL,
|
||
level,
|
||
bufptr,
|
||
prefmaxlen,
|
||
entriesread,
|
||
totalentries,
|
||
servertype,
|
||
domain,
|
||
FirstNameToReturn );
|
||
|
||
return Status;
|
||
}
|
||
|
||
//
|
||
// Only levels 100 and 101 are valid
|
||
//
|
||
|
||
if ((level != 100) && (level != 101)) {
|
||
return ERROR_INVALID_LEVEL;
|
||
}
|
||
|
||
if (servertype != SV_TYPE_ALL) {
|
||
if (servertype & SV_TYPE_DOMAIN_ENUM) {
|
||
if (servertype != SV_TYPE_DOMAIN_ENUM) {
|
||
return ERROR_INVALID_FUNCTION;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Initialize the buffer to a known value.
|
||
//
|
||
|
||
*bufptr = NULL;
|
||
|
||
*entriesread = 0;
|
||
|
||
*totalentries = 0;
|
||
|
||
//
|
||
// If we are off-line, give CSC a chance to do the enumeration
|
||
//
|
||
if( !ARGUMENT_PRESENT( servername ) &&
|
||
(servertype & SV_TYPE_SERVER) &&
|
||
CSCIsOffline() ) {
|
||
|
||
Status = CSCNetServerEnumEx( level,
|
||
bufptr,
|
||
prefmaxlen,
|
||
entriesread,
|
||
totalentries
|
||
);
|
||
if( Status == NERR_Success ) {
|
||
return Status;
|
||
}
|
||
}
|
||
|
||
Status = InitializeInterimServerList(&InterimServerList, NULL, NULL, NULL, NULL);
|
||
|
||
try {
|
||
BOOL AnyEnumServersSucceeded = FALSE;
|
||
LPTSTR MyComputerName = NULL;
|
||
|
||
Status = NetpGetComputerName( &MyComputerName);
|
||
|
||
if ( Status != NERR_Success ) {
|
||
goto try_exit;
|
||
}
|
||
|
||
//
|
||
// Retrieve the list of transports from the browser.
|
||
//
|
||
|
||
Status = GetBrowserTransportList(&TransportList);
|
||
|
||
if (Status != NERR_Success) {
|
||
goto try_exit;
|
||
}
|
||
|
||
TransportEntry = TransportList;
|
||
|
||
while (TransportEntry != NULL) {
|
||
UNICODE_STRING TransportName;
|
||
|
||
TransportName.Buffer = TransportEntry->TransportName;
|
||
TransportName.Length = (USHORT)TransportEntry->TransportNameLength;
|
||
TransportName.MaximumLength = (USHORT)TransportEntry->TransportNameLength;
|
||
|
||
Status = EnumServersForTransport(&TransportName,
|
||
domain,
|
||
level,
|
||
prefmaxlen,
|
||
servertype,
|
||
MyComputerName,
|
||
&InterimServerList,
|
||
&LocalTotalEntries,
|
||
FirstNameToReturn,
|
||
(BOOLEAN)((TransportEntry->Flags & LMDR_TRANSPORT_WANNISH) != 0),
|
||
(BOOLEAN)((TransportEntry->Flags & LMDR_TRANSPORT_RAS) != 0),
|
||
(BOOLEAN)((TransportEntry->Flags & LMDR_TRANSPORT_IPX) != 0));
|
||
|
||
if (API_SUCCESS(Status)) {
|
||
if ( Status == ERROR_MORE_DATA ) {
|
||
AnyTransportHasMoreData = TRUE;
|
||
}
|
||
AnyEnumServersSucceeded = TRUE;
|
||
if ( LocalTotalEntries > *totalentries ) {
|
||
*totalentries = LocalTotalEntries;
|
||
}
|
||
}
|
||
|
||
if (TransportEntry->NextEntryOffset == 0) {
|
||
TransportEntry = NULL;
|
||
} else {
|
||
TransportEntry = (PLMDR_TRANSPORT_LIST)((PCHAR)TransportEntry+TransportEntry->NextEntryOffset);
|
||
}
|
||
|
||
}
|
||
|
||
if ( MyComputerName != NULL ) {
|
||
(void) NetApiBufferFree( MyComputerName );
|
||
}
|
||
|
||
if (AnyEnumServersSucceeded) {
|
||
|
||
//
|
||
// Pack the interim server list into its final form.
|
||
//
|
||
|
||
Status = PackServerList(&InterimServerList,
|
||
level,
|
||
servertype,
|
||
prefmaxlen,
|
||
(PVOID *)bufptr,
|
||
entriesread,
|
||
&LocalTotalEntries, // Pack thinks it has ALL the entries
|
||
NULL ); // The server has already returned us the right entries
|
||
|
||
if ( API_SUCCESS( Status ) ) {
|
||
if ( LocalTotalEntries > *totalentries ) {
|
||
*totalentries = LocalTotalEntries;
|
||
}
|
||
}
|
||
}
|
||
|
||
try_exit:NOTHING;
|
||
} finally {
|
||
if (TransportList != NULL) {
|
||
MIDL_user_free(TransportList);
|
||
}
|
||
|
||
UninitializeInterimServerList(&InterimServerList);
|
||
}
|
||
|
||
if ( API_SUCCESS( Status )) {
|
||
|
||
//
|
||
// At this point,
|
||
// *totalentries is the largest of:
|
||
// The TotalEntries returned from any transport.
|
||
// The actual number of entries read.
|
||
//
|
||
// Adjust TotalEntries returned for reality.
|
||
//
|
||
|
||
if ( Status == NERR_Success ) {
|
||
*totalentries = *entriesread;
|
||
} else {
|
||
if ( *totalentries <= *entriesread ) {
|
||
*totalentries = *entriesread + 1;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Ensure we return ERROR_MORE_DATA if any transport has more data.
|
||
//
|
||
|
||
if ( AnyTransportHasMoreData ) {
|
||
Status = ERROR_MORE_DATA;
|
||
}
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
NET_API_STATUS
|
||
EnumServersForTransport(
|
||
IN PUNICODE_STRING TransportName,
|
||
IN LPCWSTR DomainName OPTIONAL,
|
||
IN ULONG level,
|
||
IN ULONG prefmaxlen,
|
||
IN ULONG servertype,
|
||
IN LPTSTR CurrentComputerName,
|
||
OUT PINTERIM_SERVER_LIST InterimServerList,
|
||
OUT PULONG TotalEntriesOnThisTransport,
|
||
IN LPCWSTR FirstNameToReturn,
|
||
IN BOOLEAN WannishTransport,
|
||
IN BOOLEAN RasTransport,
|
||
IN BOOLEAN IpxTransport
|
||
)
|
||
{
|
||
PWSTR *BrowserList = NULL;
|
||
ULONG BrowserListLength = 0;
|
||
NET_API_STATUS Status;
|
||
PVOID ServerList = NULL;
|
||
ULONG EntriesInList = 0;
|
||
ULONG ServerIndex = 0;
|
||
|
||
//
|
||
// Skip over IPX transports - we can't contact machines over them anyway.
|
||
//
|
||
|
||
*TotalEntriesOnThisTransport = 0;
|
||
|
||
if (IpxTransport) {
|
||
return NERR_Success;
|
||
}
|
||
|
||
//
|
||
// Retrieve a new browser list. Do not force a revalidation.
|
||
//
|
||
|
||
Status = GetBrowserServerList(TransportName,
|
||
DomainName,
|
||
&BrowserList,
|
||
&BrowserListLength,
|
||
FALSE);
|
||
|
||
//
|
||
// If a domain name was specified and we were unable to find the browse
|
||
// master for the domain and we are running on a wannish transport,
|
||
// invoke the "double hop" code and allow a local browser server
|
||
// remote the API to the browse master for that domain (we assume that
|
||
// this means that the workgroup is on a different subnet of a WAN).
|
||
//
|
||
|
||
if (!API_SUCCESS(Status) &&
|
||
DomainName != NULL) {
|
||
|
||
Status = GetBrowserServerList(TransportName,
|
||
NULL,
|
||
&BrowserList,
|
||
&BrowserListLength,
|
||
FALSE);
|
||
|
||
|
||
}
|
||
|
||
|
||
//
|
||
// If we were able to retrieve the list, remote the API. Otherwise
|
||
// return.
|
||
//
|
||
|
||
if (API_SUCCESS(Status) && BrowserList) {
|
||
|
||
do {
|
||
LPTSTR Transport;
|
||
LPTSTR ServerName;
|
||
BOOL AlreadyInTree;
|
||
|
||
//
|
||
// Remote the API to that server.
|
||
//
|
||
|
||
Transport = TransportName->Buffer;
|
||
ServerName = BrowserList[0];
|
||
*TotalEntriesOnThisTransport = 0;
|
||
|
||
// add 2 to skip double backslash at start of ServerName
|
||
|
||
if ( STRICMP(ServerName + 2, CurrentComputerName ) == 0 ) {
|
||
|
||
//
|
||
// If we are going to remote the API to ourselves,
|
||
// and we are running the browser service, simply
|
||
// use RPC to get the information we need, don't
|
||
// bother using the redirector. This allows us to
|
||
// avoid tying up RPCXLATE thread.
|
||
//
|
||
|
||
Status = I_BrowserServerEnumEx (
|
||
NULL,
|
||
Transport,
|
||
CurrentComputerName,
|
||
level,
|
||
(LPBYTE *)&ServerList,
|
||
prefmaxlen,
|
||
&EntriesInList,
|
||
TotalEntriesOnThisTransport,
|
||
servertype,
|
||
DomainName,
|
||
FirstNameToReturn );
|
||
|
||
|
||
} else {
|
||
|
||
Status = RxNetServerEnum(
|
||
ServerName,
|
||
Transport,
|
||
level,
|
||
(LPBYTE *)&ServerList,
|
||
prefmaxlen,
|
||
&EntriesInList,
|
||
TotalEntriesOnThisTransport,
|
||
servertype,
|
||
DomainName,
|
||
FirstNameToReturn );
|
||
|
||
|
||
}
|
||
|
||
if ( !API_SUCCESS(Status)) {
|
||
NET_API_STATUS GetBListStatus;
|
||
|
||
//
|
||
// If we failed to remote the API for some reason,
|
||
// we want to regenerate the bowsers list of browser
|
||
// servers.
|
||
//
|
||
|
||
if (BrowserList != NULL) {
|
||
|
||
MIDL_user_free(BrowserList);
|
||
|
||
BrowserList = NULL;
|
||
}
|
||
|
||
|
||
GetBListStatus = GetBrowserServerList(TransportName,
|
||
DomainName,
|
||
&BrowserList,
|
||
&BrowserListLength,
|
||
TRUE);
|
||
if (GetBListStatus != NERR_Success) {
|
||
|
||
//
|
||
// If we were unable to reload the list,
|
||
// try the next transport.
|
||
//
|
||
|
||
break;
|
||
}
|
||
|
||
ServerIndex += 1;
|
||
|
||
//
|
||
// If we've looped more times than we got servers
|
||
// in the list, we're done.
|
||
//
|
||
|
||
if ( ServerIndex > BrowserListLength ) {
|
||
break;
|
||
}
|
||
|
||
} else {
|
||
|
||
NET_API_STATUS TempStatus;
|
||
|
||
TempStatus = MergeServerList(
|
||
InterimServerList,
|
||
level,
|
||
ServerList,
|
||
EntriesInList,
|
||
*TotalEntriesOnThisTransport );
|
||
|
||
if ( TempStatus != NERR_Success ) {
|
||
Status = TempStatus;
|
||
}
|
||
|
||
//
|
||
// The remote API succeeded.
|
||
//
|
||
// Now free up the remaining parts of the list.
|
||
//
|
||
|
||
if (ServerList != NULL) {
|
||
NetApiBufferFree(ServerList);
|
||
ServerList = NULL;
|
||
}
|
||
|
||
// We're done regardless of the success or failure of MergeServerList.
|
||
break;
|
||
|
||
}
|
||
|
||
} while ( !API_SUCCESS(Status) );
|
||
|
||
}
|
||
|
||
//
|
||
// Free up the browser list.
|
||
//
|
||
|
||
if (BrowserList != NULL) {
|
||
MIDL_user_free(BrowserList);
|
||
BrowserList = NULL;
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
NET_API_STATUS
|
||
GetBrowserTransportList(
|
||
OUT PLMDR_TRANSPORT_LIST *TransportList
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine returns the list of transports bound into the browser.
|
||
|
||
Arguments:
|
||
|
||
OUT PLMDR_TRANSPORT_LIST *TransportList - Transport list to return.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NET_API_STATUS Status;
|
||
HANDLE BrowserHandle;
|
||
LMDR_REQUEST_PACKET RequestPacket;
|
||
|
||
Status = OpenBrowser(&BrowserHandle);
|
||
|
||
if (Status != NERR_Success) {
|
||
return Status;
|
||
}
|
||
|
||
ZeroMemory(&RequestPacket, sizeof(RequestPacket));
|
||
RequestPacket.Version = LMDR_REQUEST_PACKET_VERSION_DOM;
|
||
|
||
RequestPacket.Type = EnumerateXports;
|
||
|
||
RtlInitUnicodeString(&RequestPacket.TransportName, NULL);
|
||
RtlInitUnicodeString(&RequestPacket.EmulatedDomainName, NULL);
|
||
|
||
Status = DeviceControlGetInfo(
|
||
BrowserHandle,
|
||
IOCTL_LMDR_ENUMERATE_TRANSPORTS,
|
||
&RequestPacket,
|
||
sizeof(RequestPacket),
|
||
(PVOID *)TransportList,
|
||
0xffffffff,
|
||
4096,
|
||
NULL);
|
||
|
||
NtClose(BrowserHandle);
|
||
|
||
return Status;
|
||
}
|
||
|
||
NET_API_STATUS
|
||
I_BrowserServerEnum (
|
||
IN LPCWSTR servername OPTIONAL,
|
||
IN LPCWSTR transport OPTIONAL,
|
||
IN LPCWSTR clientname OPTIONAL,
|
||
IN DWORD level,
|
||
OUT LPBYTE *bufptr,
|
||
IN DWORD prefmaxlen,
|
||
OUT LPDWORD entriesread,
|
||
OUT LPDWORD totalentries,
|
||
IN DWORD servertype,
|
||
IN LPCWSTR domain OPTIONAL,
|
||
IN OUT LPDWORD resume_handle OPTIONAL
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the DLL entrypoint for NetWkstaSetInfo.
|
||
|
||
Arguments:
|
||
|
||
servername - Supplies the name of server to execute this function
|
||
|
||
level - Supplies the level of information.
|
||
|
||
buf - Supplies a buffer which contains the information structure of fields
|
||
to set. The level denotes the structure in this buffer.
|
||
|
||
parm_err - Returns the identifier to the invalid parameter in buf if this
|
||
function returns ERROR_INVALID_PARAMETER.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NET_API_STATUS status;
|
||
GENERIC_INFO_CONTAINER GenericInfoContainer;
|
||
GENERIC_ENUM_STRUCT InfoStruct;
|
||
|
||
GenericInfoContainer.Buffer = NULL;
|
||
GenericInfoContainer.EntriesRead = 0;
|
||
|
||
InfoStruct.Container = &GenericInfoContainer;
|
||
InfoStruct.Level = level;
|
||
|
||
NET_REMOTE_TRY_RPC
|
||
|
||
//
|
||
// Try RPC (local or remote) version of API.
|
||
//
|
||
|
||
status = I_BrowserrServerEnum(
|
||
(LPWSTR) servername,
|
||
(LPWSTR) transport,
|
||
(LPWSTR) clientname,
|
||
(LPSERVER_ENUM_STRUCT)&InfoStruct,
|
||
prefmaxlen,
|
||
totalentries,
|
||
servertype,
|
||
(LPWSTR) domain,
|
||
resume_handle
|
||
);
|
||
|
||
if (status == NERR_Success || status == ERROR_MORE_DATA) {
|
||
*bufptr = (LPBYTE) GenericInfoContainer.Buffer;
|
||
*entriesread = GenericInfoContainer.EntriesRead;
|
||
|
||
#if 0
|
||
if (((servertype == SV_TYPE_ALL || servertype == SV_TYPE_DOMAIN_ENUM)) &&
|
||
(STRICMP(transport, L"\\Device\\Streams\\NBT"))) {
|
||
if (*entriesread <= 20) {
|
||
KdPrint(("RPC API Returned EntriesRead == %ld on transport %ws\n", *entriesread, transport));
|
||
}
|
||
if (*totalentries <= 20) {
|
||
KdPrint(("RPC API Returned TotalEntries == %ld on transport %ws\n", *totalentries, transport));
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|
||
NET_REMOTE_RPC_FAILED("I_BrServerEnum",
|
||
servername,
|
||
status,
|
||
NET_REMOTE_FLAG_NORMAL,
|
||
SERVICE_BROWSER )
|
||
|
||
//
|
||
// There is no downlevel version of api.
|
||
//
|
||
status = ERROR_NOT_SUPPORTED;
|
||
|
||
NET_REMOTE_END
|
||
|
||
#if 0
|
||
if ((servertype == SV_TYPE_ALL || servertype == SV_TYPE_DOMAIN_ENUM) &&
|
||
(STRICMP(transport, L"\\Device\\Streams\\NBT"))) {
|
||
if (*entriesread <= 20) {
|
||
KdPrint(("Client API Returned EntriesRead == %ld on transport %ws\n", *entriesread, transport));
|
||
}
|
||
if (*totalentries <= 20) {
|
||
KdPrint(("Client API Returned TotalEntries == %ld on transport %ws\n", *totalentries, transport));
|
||
}
|
||
}
|
||
#endif
|
||
|
||
return status;
|
||
}
|
||
|
||
NET_API_STATUS
|
||
I_BrowserServerEnumEx (
|
||
IN LPCWSTR servername OPTIONAL,
|
||
IN LPCWSTR transport OPTIONAL,
|
||
IN LPCWSTR clientname OPTIONAL,
|
||
IN DWORD level,
|
||
OUT LPBYTE *bufptr,
|
||
IN DWORD prefmaxlen,
|
||
OUT LPDWORD entriesread,
|
||
OUT LPDWORD totalentries,
|
||
IN DWORD servertype,
|
||
IN LPCWSTR domain OPTIONAL,
|
||
IN LPCWSTR FirstNameToReturn OPTIONAL
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the DLL entrypoint for NetWkstaSetInfo.
|
||
|
||
Arguments:
|
||
|
||
servername - Supplies the name of server to execute this function
|
||
|
||
level - Supplies the level of information.
|
||
|
||
buf - Supplies a buffer which contains the information structure of fields
|
||
to set. The level denotes the structure in this buffer.
|
||
|
||
parm_err - Returns the identifier to the invalid parameter in buf if this
|
||
function returns ERROR_INVALID_PARAMETER.
|
||
|
||
FirstNameToReturn - Supplies the name of the first domain or server entry to return.
|
||
The caller can use this parameter to implement a resume handle of sorts by passing
|
||
the name of the last entry returned on a previous call. (Notice that the specified
|
||
entry will, also, be returned on this call unless it has since been deleted.)
|
||
Pass NULL to start with the first entry available.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NET_API_STATUS status;
|
||
GENERIC_INFO_CONTAINER GenericInfoContainer;
|
||
GENERIC_ENUM_STRUCT InfoStruct;
|
||
|
||
GenericInfoContainer.Buffer = NULL;
|
||
GenericInfoContainer.EntriesRead = 0;
|
||
|
||
InfoStruct.Container = &GenericInfoContainer;
|
||
InfoStruct.Level = level;
|
||
|
||
NET_REMOTE_TRY_RPC
|
||
|
||
//
|
||
// Try RPC (local or remote) version of API.
|
||
//
|
||
|
||
status = I_BrowserrServerEnumEx(
|
||
(LPWSTR) servername,
|
||
(LPWSTR) transport,
|
||
(LPWSTR) clientname,
|
||
(LPSERVER_ENUM_STRUCT)&InfoStruct,
|
||
prefmaxlen,
|
||
totalentries,
|
||
servertype,
|
||
(LPWSTR) domain,
|
||
(LPWSTR) FirstNameToReturn );
|
||
|
||
if (status == NERR_Success || status == ERROR_MORE_DATA) {
|
||
*bufptr = (LPBYTE) GenericInfoContainer.Buffer;
|
||
*entriesread = GenericInfoContainer.EntriesRead;
|
||
|
||
#if 0
|
||
if (((servertype == SV_TYPE_ALL || servertype == SV_TYPE_DOMAIN_ENUM)) &&
|
||
(STRICMP(transport, L"\\Device\\Streams\\NBT"))) {
|
||
if (*entriesread <= 20) {
|
||
KdPrint(("RPC API Returned EntriesRead == %ld on transport %ws\n", *entriesread, transport));
|
||
}
|
||
if (*totalentries <= 20) {
|
||
KdPrint(("RPC API Returned TotalEntries == %ld on transport %ws\n", *totalentries, transport));
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|
||
NET_REMOTE_RPC_FAILED("I_BrServerEnum",
|
||
servername,
|
||
status,
|
||
NET_REMOTE_FLAG_NORMAL,
|
||
SERVICE_BROWSER )
|
||
|
||
//
|
||
// There is no downlevel version of api.
|
||
//
|
||
status = ERROR_NOT_SUPPORTED;
|
||
|
||
NET_REMOTE_END
|
||
|
||
#if 0
|
||
if ((servertype == SV_TYPE_ALL || servertype == SV_TYPE_DOMAIN_ENUM) &&
|
||
(STRICMP(transport, L"\\Device\\Streams\\NBT"))) {
|
||
if (*entriesread <= 20) {
|
||
KdPrint(("Client API Returned EntriesRead == %ld on transport %ws\n", *entriesread, transport));
|
||
}
|
||
if (*totalentries <= 20) {
|
||
KdPrint(("Client API Returned TotalEntries == %ld on transport %ws\n", *totalentries, transport));
|
||
}
|
||
}
|
||
#endif
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
NET_API_STATUS NET_API_FUNCTION
|
||
I_BrowserQueryOtherDomains (
|
||
IN LPCWSTR servername OPTIONAL,
|
||
OUT LPBYTE *bufptr,
|
||
OUT LPDWORD entriesread,
|
||
OUT LPDWORD totalentries
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the DLL entrypoint for NetWkstaSetInfo.
|
||
|
||
Arguments:
|
||
|
||
servername - Supplies the name of server to execute this function
|
||
|
||
buf - Supplies a buffer which contains the information structure of fields
|
||
to set. The level denotes the structure in this buffer.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NET_API_STATUS status;
|
||
GENERIC_INFO_CONTAINER GenericInfoContainer;
|
||
GENERIC_ENUM_STRUCT InfoStruct;
|
||
|
||
GenericInfoContainer.Buffer = NULL;
|
||
GenericInfoContainer.EntriesRead = 0;
|
||
|
||
InfoStruct.Container = &GenericInfoContainer;
|
||
InfoStruct.Level = 100;
|
||
|
||
NET_REMOTE_TRY_RPC
|
||
|
||
//
|
||
// Try RPC (local or remote) version of API.
|
||
//
|
||
|
||
status = I_BrowserrQueryOtherDomains (
|
||
(LPWSTR) servername,
|
||
(LPSERVER_ENUM_STRUCT)&InfoStruct,
|
||
totalentries
|
||
);
|
||
|
||
if (status == NERR_Success || status == ERROR_MORE_DATA) {
|
||
*bufptr = (LPBYTE) GenericInfoContainer.Buffer;
|
||
*entriesread = GenericInfoContainer.EntriesRead;
|
||
}
|
||
|
||
NET_REMOTE_RPC_FAILED("I_BrowserQueryOtherDomains",
|
||
servername,
|
||
status,
|
||
NET_REMOTE_FLAG_NORMAL,
|
||
SERVICE_BROWSER )
|
||
|
||
//
|
||
// There is no downlevel version of api.
|
||
//
|
||
status = ERROR_NOT_SUPPORTED;
|
||
|
||
NET_REMOTE_END
|
||
|
||
return status;
|
||
}
|
||
NET_API_STATUS
|
||
I_BrowserResetNetlogonState (
|
||
IN LPCWSTR servername OPTIONAL
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the DLL entrypoint for NetWkstaSetInfo.
|
||
|
||
Arguments:
|
||
|
||
servername - Supplies the name of server to execute this function
|
||
|
||
buf - Supplies a buffer which contains the information structure of fields
|
||
to set. The level denotes the structure in this buffer.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NET_API_STATUS status;
|
||
|
||
NET_REMOTE_TRY_RPC
|
||
|
||
//
|
||
// Try RPC (local or remote) version of API.
|
||
//
|
||
|
||
status = I_BrowserrResetNetlogonState (
|
||
(LPWSTR) servername );
|
||
|
||
NET_REMOTE_RPC_FAILED("I_BrowserResetNetlogonState",
|
||
servername,
|
||
status,
|
||
NET_REMOTE_FLAG_NORMAL,
|
||
SERVICE_BROWSER )
|
||
|
||
//
|
||
// There is no downlevel version of api.
|
||
//
|
||
status = ERROR_NOT_SUPPORTED;
|
||
|
||
NET_REMOTE_END
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
NET_API_STATUS
|
||
I_BrowserDebugCall (
|
||
IN LPTSTR servername OPTIONAL,
|
||
IN DWORD DebugCode,
|
||
IN DWORD Options
|
||
)
|
||
{
|
||
NET_API_STATUS status;
|
||
|
||
NET_REMOTE_TRY_RPC
|
||
|
||
//
|
||
// Try RPC (local or remote) version of API.
|
||
//
|
||
|
||
status = I_BrowserrDebugCall(
|
||
servername,
|
||
DebugCode,
|
||
Options
|
||
);
|
||
|
||
|
||
NET_REMOTE_RPC_FAILED("I_BrowserDebugCall",
|
||
servername,
|
||
status,
|
||
NET_REMOTE_FLAG_NORMAL,
|
||
SERVICE_BROWSER )
|
||
|
||
//
|
||
// There is no downlevel version of api.
|
||
//
|
||
status = ERROR_NOT_SUPPORTED;
|
||
|
||
NET_REMOTE_END
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
NET_API_STATUS
|
||
I_BrowserDebugTrace (
|
||
IN LPTSTR servername OPTIONAL,
|
||
IN PCHAR DebugString
|
||
)
|
||
{
|
||
NET_API_STATUS status;
|
||
|
||
NET_REMOTE_TRY_RPC
|
||
|
||
//
|
||
// Try RPC (local or remote) version of API.
|
||
//
|
||
|
||
status = I_BrowserrDebugTrace(
|
||
servername,
|
||
DebugString
|
||
);
|
||
|
||
|
||
NET_REMOTE_RPC_FAILED("I_BrowserDebugTrace",
|
||
servername,
|
||
status,
|
||
NET_REMOTE_FLAG_NORMAL,
|
||
SERVICE_BROWSER )
|
||
|
||
//
|
||
// There is no downlevel version of api.
|
||
//
|
||
status = ERROR_NOT_SUPPORTED;
|
||
|
||
NET_REMOTE_END
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
|
||
NET_API_STATUS
|
||
I_BrowserQueryStatistics (
|
||
IN LPCWSTR servername OPTIONAL,
|
||
IN OUT LPBROWSER_STATISTICS *Statistics
|
||
)
|
||
{
|
||
NET_API_STATUS status;
|
||
|
||
NET_REMOTE_TRY_RPC
|
||
|
||
//
|
||
// Try RPC (local or remote) version of API.
|
||
//
|
||
|
||
status = I_BrowserrQueryStatistics(
|
||
(LPWSTR) servername,
|
||
Statistics
|
||
);
|
||
|
||
|
||
NET_REMOTE_RPC_FAILED("I_BrowserQueryStatistics",
|
||
servername,
|
||
status,
|
||
NET_REMOTE_FLAG_NORMAL,
|
||
SERVICE_BROWSER )
|
||
|
||
//
|
||
// There is no downlevel version of api.
|
||
//
|
||
status = ERROR_NOT_SUPPORTED;
|
||
|
||
NET_REMOTE_END
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
NET_API_STATUS
|
||
I_BrowserResetStatistics (
|
||
IN LPCWSTR servername OPTIONAL
|
||
)
|
||
{
|
||
NET_API_STATUS status;
|
||
|
||
NET_REMOTE_TRY_RPC
|
||
|
||
//
|
||
// Try RPC (local or remote) version of API.
|
||
//
|
||
|
||
status = I_BrowserrResetStatistics(
|
||
(LPWSTR) servername );
|
||
|
||
|
||
NET_REMOTE_RPC_FAILED("I_BrowserResetStatistics",
|
||
servername,
|
||
status,
|
||
NET_REMOTE_FLAG_NORMAL,
|
||
SERVICE_BROWSER )
|
||
|
||
//
|
||
// There is no downlevel version of api.
|
||
//
|
||
status = ERROR_NOT_SUPPORTED;
|
||
|
||
NET_REMOTE_END
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
|
||
NET_API_STATUS
|
||
NetBrowserStatisticsGet(
|
||
IN LPTSTR ServerName,
|
||
IN DWORD Level,
|
||
OUT LPBYTE* Buffer
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Wrapper for workstation statistics retrieval routine - either calls the
|
||
client-side RPC function or calls RxNetStatisticsGet to retrieve the
|
||
statistics from a down-level workstation service
|
||
|
||
Arguments:
|
||
|
||
ServerName - where to remote this function
|
||
Level - of information required (100, or 101)
|
||
Buffer - pointer to pointer to returned buffer
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS
|
||
Success - NERR_Success
|
||
Failure - ERROR_INVALID_LEVEL
|
||
Level not 0
|
||
ERROR_INVALID_PARAMETER
|
||
Unsupported options requested
|
||
ERROR_NOT_SUPPORTED
|
||
Service is not SERVER or WORKSTATION
|
||
ERROR_ACCESS_DENIED
|
||
Caller doesn't have necessary access rights for request
|
||
|
||
--*/
|
||
|
||
{
|
||
NET_API_STATUS status;
|
||
GENERIC_INFO_CONTAINER GenericInfoContainer;
|
||
GENERIC_ENUM_STRUCT InfoStruct;
|
||
|
||
//
|
||
// set the caller's buffer pointer to known value. This will kill the
|
||
// calling app if it gave us a bad pointer and didn't use try...except
|
||
//
|
||
|
||
*Buffer = NULL;
|
||
|
||
//
|
||
// validate parms
|
||
//
|
||
|
||
if (Level != 100 && Level != 101) {
|
||
return ERROR_INVALID_LEVEL;
|
||
}
|
||
|
||
GenericInfoContainer.Buffer = NULL;
|
||
GenericInfoContainer.EntriesRead = 0;
|
||
|
||
InfoStruct.Container = &GenericInfoContainer;
|
||
InfoStruct.Level = Level;
|
||
|
||
|
||
NET_REMOTE_TRY_RPC
|
||
status = NetrBrowserStatisticsGet(ServerName,
|
||
Level,
|
||
(PBROWSER_STATISTICS_STRUCT)&InfoStruct
|
||
);
|
||
|
||
if (status == NERR_Success || status == ERROR_MORE_DATA) {
|
||
*Buffer = (LPBYTE) GenericInfoContainer.Buffer;
|
||
}
|
||
|
||
NET_REMOTE_RPC_FAILED("NetBrowserStatisticsGet",
|
||
ServerName,
|
||
status,
|
||
NET_REMOTE_FLAG_NORMAL,
|
||
SERVICE_BROWSER
|
||
)
|
||
|
||
status = ERROR_NOT_SUPPORTED;
|
||
|
||
NET_REMOTE_END
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
NET_API_STATUS
|
||
I_BrowserSetNetlogonState(
|
||
IN LPWSTR ServerName,
|
||
IN LPWSTR DomainName,
|
||
IN LPWSTR EmulatedComputerName,
|
||
IN DWORD Role
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the DLL entrypoint for I_BrowserSetNetlogonState.
|
||
|
||
Arguments:
|
||
|
||
servername - Supplies the name of server to execute this function
|
||
|
||
DomainName - name of the domain who's role is to be updated.
|
||
|
||
EmulatedComputerName - Name of the computer within DomainName
|
||
|
||
Role - Role of the specified domain.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NET_API_STATUS status;
|
||
|
||
NET_REMOTE_TRY_RPC
|
||
|
||
//
|
||
// Try RPC (local or remote) version of API.
|
||
//
|
||
|
||
status = I_BrowserrSetNetlogonState (
|
||
ServerName,
|
||
DomainName,
|
||
EmulatedComputerName,
|
||
Role );
|
||
|
||
NET_REMOTE_RPC_FAILED("I_BrowserSetNetlogonState",
|
||
ServerName,
|
||
status,
|
||
NET_REMOTE_FLAG_NORMAL,
|
||
SERVICE_BROWSER )
|
||
|
||
//
|
||
// There is no downlevel version of api.
|
||
//
|
||
status = ERROR_NOT_SUPPORTED;
|
||
|
||
NET_REMOTE_END
|
||
|
||
return status;
|
||
}
|
||
|
||
NET_API_STATUS NET_API_FUNCTION
|
||
I_BrowserQueryEmulatedDomains (
|
||
IN LPTSTR ServerName OPTIONAL,
|
||
OUT PBROWSER_EMULATED_DOMAIN *EmulatedDomains,
|
||
OUT LPDWORD EntriesRead
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the DLL entrypoint for I_BrowserQueryEmulatedDomains.
|
||
|
||
Arguments:
|
||
|
||
ServerName - Supplies the name of server to execute this function
|
||
|
||
EmulatedDomains - Returns a pointer to a an allocated array of emulated domain
|
||
information.
|
||
|
||
EntriesRead - Returns the number of entries in 'EmulatedDomains'
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NET_API_STATUS NetStatus;
|
||
BROWSER_EMULATED_DOMAIN_CONTAINER Container;
|
||
|
||
// Force RPC to allocate the buffer
|
||
Container.Buffer = NULL;
|
||
Container.EntriesRead = 0;
|
||
*EmulatedDomains = NULL;
|
||
*EntriesRead = 0;
|
||
|
||
NET_REMOTE_TRY_RPC
|
||
|
||
//
|
||
// Try RPC (local or remote) version of API.
|
||
//
|
||
|
||
NetStatus = I_BrowserrQueryEmulatedDomains (
|
||
ServerName,
|
||
&Container );
|
||
|
||
if ( NetStatus == NERR_Success ) {
|
||
*EmulatedDomains = (PBROWSER_EMULATED_DOMAIN) Container.Buffer;
|
||
*EntriesRead = Container.EntriesRead;
|
||
}
|
||
|
||
|
||
NET_REMOTE_RPC_FAILED("I_BrowserQueryEmulatedDomains",
|
||
ServerName,
|
||
NetStatus,
|
||
NET_REMOTE_FLAG_NORMAL,
|
||
SERVICE_BROWSER )
|
||
|
||
//
|
||
// There is no downlevel version of api.
|
||
//
|
||
NetStatus = ERROR_NOT_SUPPORTED;
|
||
|
||
NET_REMOTE_END
|
||
|
||
return NetStatus;
|
||
}
|
||
|
||
|
||
|
||
|
||
#if DBG
|
||
void
|
||
ValidateServerList(
|
||
IN PVOID ServerList,
|
||
IN ULONG ulLevel,
|
||
IN ULONG ulEntries
|
||
)
|
||
/*++
|
||
|
||
Routine Description (ValidateServerList):
|
||
|
||
Cycle through servers. Validate the content in the list of server
|
||
|
||
|
||
Arguments:
|
||
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
|
||
|
||
Remarks:
|
||
None.
|
||
|
||
|
||
--*/
|
||
{
|
||
|
||
LONG i;
|
||
ULONG ServerElementSize;
|
||
PSERVER_INFO_101 ServerInfo = (PSERVER_INFO_101)ServerList;
|
||
static BOOL bDisplayEntries = FALSE;
|
||
|
||
ASSERT (ulLevel == 100 || ulLevel == 101);
|
||
|
||
//
|
||
// Figure out the size of each element.
|
||
//
|
||
|
||
if (ulLevel == 100) {
|
||
ServerElementSize = sizeof(SERVER_INFO_100);
|
||
} else {
|
||
ASSERT( ulLevel == 101 );
|
||
ServerElementSize = sizeof(SERVER_INFO_101);
|
||
}
|
||
|
||
//
|
||
// Next check to see if the input list is sorted.
|
||
//
|
||
|
||
if ( bDisplayEntries ) {
|
||
DbgPrint("Server List:\n");
|
||
}
|
||
for (i = 0 ; i < (LONG)ulEntries ; i++ ) {
|
||
|
||
if ( bDisplayEntries ) {
|
||
DbgPrint("<%d>: [0x%x] %S\n",
|
||
i,
|
||
ServerInfo->sv101_platform_id,
|
||
ServerInfo->sv101_name);
|
||
}
|
||
|
||
ASSERT (ServerInfo->sv101_name &&
|
||
wcslen(ServerInfo->sv101_name) > 0);
|
||
ServerInfo = (PSERVER_INFO_101)((PCHAR)ServerInfo + ServerElementSize);
|
||
}
|
||
}
|
||
#endif
|