windows-nt/Source/XPSP1/NT/ds/netapi/svcdlls/browser/client/browstub.c
2020-09-26 16:20:57 +08:00

1606 lines
42 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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