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

303 lines
7.6 KiB
C

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
csc.c
Abstract:
These are the browser service API RPC client stubs for CSC
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <rpcutil.h>
#include <lmcons.h>
#include <lmerr.h>
#include <lmapibuf.h>
#include <lmserver.h>
#include "cscp.h"
static FARPROC pCSCFindFirstFile = NULL;
static FARPROC pCSCFindNextFile = NULL;
static FARPROC pCSCFindClose = NULL;
static FARPROC pCSCIsServerOffline = NULL;
BrowserGetCSCEntryPoints()
{
HANDLE hMod;
if( pCSCFindFirstFile == NULL ) {
//
// Get the entry points in reverse order for multithread protection
//
hMod = LoadLibrary(L"cscdll.dll");
if( hMod == NULL ) {
return 0;
}
pCSCFindClose = GetProcAddress(hMod,"CSCFindClose");
if( pCSCFindClose == NULL ) {
return 0;
}
pCSCFindNextFile = GetProcAddress(hMod,"CSCFindNextFileW" );
if( pCSCFindNextFile == NULL ) {
return 0;
}
pCSCIsServerOffline = GetProcAddress(hMod, "CSCIsServerOfflineW" );
if( pCSCIsServerOffline == NULL ) {
return 0;
}
pCSCFindFirstFile = GetProcAddress(hMod,"CSCFindFirstFileW" );
}
return pCSCFindFirstFile != 0;
}
BOOLEAN NET_API_FUNCTION
CSCIsOffline()
{
BOOL isOffline;
if( BrowserGetCSCEntryPoints() &&
pCSCIsServerOffline( NULL, &isOffline ) &&
isOffline == TRUE ) {
return TRUE;
}
return FALSE;
}
NET_API_STATUS NET_API_FUNCTION
CSCNetServerEnumEx(
IN DWORD level,
OUT LPBYTE *bufptr,
IN DWORD prefmaxlen,
OUT LPDWORD entriesread,
OUT LPDWORD totalentries
)
/*++
Arguments:
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.
Ignored for this case.
entriesread - Returns the number of entries read into the buffer.
totalentries - Returns the total number of entries available.
--*/
{
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW sFind32;
DWORD dwError, dwStatus, dwPinCount, dwHintFlags;
FILETIME ftOrgTime;
NET_API_STATUS apiStatus;
LPWSTR server, share;
PBYTE outbuf = NULL, endp;
DWORD count, numFound, serverlen;
try {
count = 1024;
retry:
numFound = 0;
//
// Allocate space for the results
//
if( outbuf != NULL ) {
NetApiBufferFree( outbuf );
outbuf = NULL;
count *= 2;
}
apiStatus = NetApiBufferAllocate( count, &outbuf );
if( apiStatus != NO_ERROR ) {
goto try_exit;
}
endp = outbuf + count;
RtlZeroMemory( outbuf, count );
//
// See if we can enumerate the cached servers and shares
//
if( hFind != INVALID_HANDLE_VALUE ) {
pCSCFindClose( hFind );
hFind = INVALID_HANDLE_VALUE;
}
hFind = (HANDLE)pCSCFindFirstFile( NULL,
&sFind32,
&dwStatus,
&dwPinCount,
&dwHintFlags,
&ftOrgTime
);
if( hFind == INVALID_HANDLE_VALUE ) {
NetApiBufferFree( outbuf );
apiStatus = ERROR_NOT_SUPPORTED;
goto try_exit;
}
do {
//
// For each entry, take a look to see if it's one that we want. If
// it is one, pack the results into the output buffer. If the output
// buffer is too small, grow the buffer and start over again.
//
//
// The name returned should be \\server\sharename
//
if( sFind32.cFileName[0] != L'\\' || sFind32.cFileName[1] != L'\\' ||
sFind32.cFileName[2] == L'\0' ) {
//
// We got a strange server name entry
//
continue;
}
server = &sFind32.cFileName[2];
for( share = server; *share && *share != '\\'; share++ );
if( share[0] != '\\' ) {
//
// No share component?
//
continue;
}
//
// NULL terminate the servername
//
*share++ = L'\0';
serverlen = (DWORD)(share - server) * sizeof( WCHAR ) ;
//
// We've found a server entry!
//
if( level == 0 ) {
PSERVER_INFO_100 s100 = (PSERVER_INFO_100)outbuf + numFound;
PSERVER_INFO_100 s;
if( (PBYTE)(endp - serverlen) < (PBYTE)(s100 + sizeof( s100 )) ) {
goto retry;
}
//
// If we've already gotten this server, skip it
//
for( s = (PSERVER_INFO_100)outbuf; s < s100; s++ ) {
if( !lstrcmpiW( s->sv100_name, server ) ) {
break;
}
}
if( s != s100 ) {
continue;
}
endp -= serverlen;
RtlCopyMemory( endp, server, serverlen );
s100->sv100_name = (LPWSTR)endp;
s100->sv100_platform_id = SV_PLATFORM_ID_NT;
} else {
PSERVER_INFO_101 s101 = (PSERVER_INFO_101)outbuf + numFound;
PSERVER_INFO_101 s;
if( (PBYTE)(endp - serverlen) < (PBYTE)(s101 + sizeof( s101 )) ) {
goto retry;
}
//
// If we've already gotten this server, skip it
//
for( s = (PSERVER_INFO_101)outbuf; s < s101; s++ ) {
if( !lstrcmpiW( s->sv101_name, server ) ) {
break;
}
}
if( s != s101 ) {
continue;
}
endp -= serverlen;
RtlCopyMemory( endp, server, serverlen );
s101->sv101_name = (LPWSTR)endp;
s101->sv101_platform_id = SV_PLATFORM_ID_NT;
s101->sv101_version_major = 5;
s101->sv101_version_minor = 0;
s101->sv101_type = SV_TYPE_SERVER;
s101->sv101_comment = (LPWSTR)(endp + serverlen - sizeof(WCHAR));
}
numFound++;
} while( pCSCFindNextFile(hFind, &sFind32, &dwStatus, &dwPinCount, &dwHintFlags, &ftOrgTime) );
pCSCFindClose(hFind);
if( numFound != 0 ) {
apiStatus = NERR_Success;
} else {
NetApiBufferFree( outbuf );
outbuf = NULL;
apiStatus = NERR_BrowserTableIncomplete;
}
*bufptr = outbuf;
*entriesread = numFound;
*totalentries = numFound;
try_exit:;
} except( EXCEPTION_EXECUTE_HANDLER ) {
if( outbuf != NULL ) {
NetApiBufferFree( outbuf );
}
if( hFind != INVALID_HANDLE_VALUE ) {
pCSCFindClose( hFind );
}
apiStatus = ERROR_INVALID_PARAMETER;
}
return apiStatus;
}