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
|