|
|
/********************************************************************/ /** Microsoft LAN Manager **/ /** Copyright(c) Microsoft Corp., 1987-1992 **/ /********************************************************************/
/*
* view.c * Commands for viewing what resources are available for use. * * History: * 07/02/87, ericpe, initial coding. * 10/31/88, erichn, uses OS2.H instead of DOSCALLS * 01/04/89, erichn, filenames now MAXPATHLEN LONG * 05/02/89, erichn, NLS conversion * 05/19/89, erichn, NETCMD output sorting * 06/08/89, erichn, canonicalization sweep * 02/15/91, danhi, convert to 16/32 mapping layer * 04/09/91, robdu, LM21 bug fix 1502 * 07/20/92, JohnRo, Use DEFAULT_SERVER equate. */
/* Include files */
#define INCL_NOCOMMON
#define INCL_DOSMEMMGR
#define INCL_DOSFILEMGR
#define INCL_ERRORS
#include <os2.h>
#include <search.h>
#include <lmcons.h>
#include <lmerr.h>
#include <lmapibuf.h>
#include <apperr.h>
#include <apperr2.h>
#include <lmshare.h>
#include <lmuse.h>
#include <dlserver.h>
#include "mserver.h"
#include "netcmds.h"
#include "nettext.h"
#include "msystem.h"
/* Forward declarations */
int __cdecl CmpSvrInfo1 ( const VOID FAR *, const VOID FAR * ); int __cdecl CmpShrInfo1 ( const VOID FAR *, const VOID FAR *); int __cdecl CmpShrInfoGen ( const VOID FAR *, const VOID FAR *);
DWORD get_used_as ( LPWSTR, LPWSTR, DWORD ); void display_other_net(TCHAR *net, TCHAR *node) ; TCHAR * get_provider_name(TCHAR *net) ; DWORD enum_net_resource(LPNETRESOURCE, LPBYTE *, LPDWORD, LPDWORD) ; DWORD list_nets(VOID);
#define VIEW_UNC 0
#define VIEW_MORE (VIEW_UNC + 1)
#define USE_TYPE_DISK (VIEW_MORE + 1)
#define USE_TYPE_COMM (USE_TYPE_DISK + 1)
#define USE_TYPE_PRINT (USE_TYPE_COMM + 1)
#define USE_TYPE_IPC (USE_TYPE_PRINT + 1)
#define USE_TYPE_UNKNOWN (USE_TYPE_IPC + 1)
#define VIEW_CACHED_MANUAL (USE_TYPE_UNKNOWN + 1)
#define VIEW_CACHED_AUTO (VIEW_CACHED_MANUAL+1)
#define VIEW_CACHED_VDO (VIEW_CACHED_AUTO+1)
#define VIEW_CACHED_DISABLED (VIEW_CACHED_VDO+1)
static MESSAGE ViewMsgList[] = { { APE2_VIEW_UNC, NULL }, { APE2_VIEW_MORE, NULL }, { APE2_USE_TYPE_DISK, NULL }, { APE2_USE_TYPE_COMM, NULL }, { APE2_USE_TYPE_PRINT, NULL }, { APE2_USE_TYPE_IPC, NULL }, { APE2_GEN_UNKNOWN, NULL }, { APE2_GEN_CACHED_MANUAL, NULL }, { APE2_GEN_CACHED_AUTO, NULL }, { APE2_GEN_CACHED_VDO, NULL }, { APE2_GEN_CACHED_DISABLED, NULL }, };
#define NUM_VIEW_MSGS (sizeof(ViewMsgList)/sizeof(ViewMsgList[0]))
#define MAX_SHARE_LEN (MAX_PATH + NNLEN + 4)
/***
* view_display() * * Displays info as reqested through use of the Net View command. * * Args: * name - the name of the server for which info is desired. * If NULL, the servers on the Net are enumerated. * * Returns: * nothing - success * exit(1) - command completed with errors */ VOID view_display ( TCHAR * name ) { DWORD dwErr; LPTSTR pEnumBuffer; LPTSTR pGetInfoBuffer; DWORD _read; /* to receive # of entries read */ DWORD msgLen; /* to hold max length of messages */ LPTSTR msgPtr; /* message to print */ LPSERVER_INFO_1 server_entry; LPSERVER_INFO_0 server_entry_0; LPSHARE_INFO_1 share_entry;
SHORT errorflag = 0; DWORD i; LPTSTR comment; LPWSTR tname = NULL; USHORT more_data = FALSE; LPTSTR DollarPtr;
TCHAR *Domain = NULL; TCHAR *Network = NULL; ULONG Type = SV_TYPE_ALL; BOOLEAN b501 = TRUE; BOOLEAN bShowCache = FALSE;
INT iLongestShareName = 0; INT iLongestType = 0; INT iLongestUsedAs = 0; INT iLongestCacheOrRemark = 0;
#define NEXT_SHARE_ENTRY(p) \
p= (b501 ? (LPSHARE_INFO_1) (((LPSHARE_INFO_501) p) + 1) : ((LPSHARE_INFO_1) p) + 1)
GetMessageList(NUM_VIEW_MSGS, ViewMsgList, &msgLen);
for (i = 0; SwitchList[i]; i++) { TCHAR *ptr;
//
// only have 2 switches, and they are not compatible
//
if (i > 0) { ErrorExit(APE_ConflictingSwitches); }
ptr = FindColon(SwitchList[i]);
if (!_tcscmp(SwitchList[i], swtxt_SW_DOMAIN)) {
//
// If no domain specified, then we want to enumerate domains,
// otherwise we want to enumerate the servers on the domain
// specified.
//
if (ptr == NULL) Type = SV_TYPE_DOMAIN_ENUM; else Domain = ptr; } else if (!_tcscmp(SwitchList[i], swtxt_SW_NETWORK)) { //
// enumerate top level of specific network. if none,
// default to LM.
//
if (ptr && *ptr) Network = ptr ; } else if( !_tcscmp(SwitchList[i], swtxt_SW_CACHE)) { //
// Show the cache setting for each share
//
bShowCache = TRUE; } else { ErrorExit(APE_InvalidSwitch); } }
//
// a specific net was requested. display_other_net does
// not return.
//
if (Network != NULL) { (void) display_other_net(Network,name) ; }
if (name == NULL) {
ULONG i;
if ((dwErr = MNetServerEnum(DEFAULT_SERVER, (Type == SV_TYPE_DOMAIN_ENUM ? 100 : 101), (LPBYTE*)&pEnumBuffer, &_read, Type, Domain)) == ERROR_MORE_DATA) { more_data = TRUE; } else if (dwErr) { ErrorExit(dwErr); }
if (_read == 0) EmptyExit();
qsort(pEnumBuffer, _read, (Type == SV_TYPE_DOMAIN_ENUM ? sizeof(SERVER_INFO_0) : sizeof(SERVER_INFO_1)), CmpSvrInfo1);
if (Type == SV_TYPE_DOMAIN_ENUM) InfoPrint(APE2_VIEW_DOMAIN_HDR); else InfoPrint(APE2_VIEW_ALL_HDR); PrintLine();
/* Print the listing */
if (Type == SV_TYPE_DOMAIN_ENUM) { for (i=0, server_entry_0 = (LPSERVER_INFO_0) pEnumBuffer; i < _read; i++, server_entry_0++) { WriteToCon(TEXT("%Fws "), PaddedString(20,server_entry_0->sv0_name,NULL)); PrintNL(); } } else {
for (i=0, server_entry = (LPSERVER_INFO_1) pEnumBuffer; i < _read; i++, server_entry++) { WriteToCon(TEXT("\\\\%Fws "), PaddedString(20,server_entry->sv1_name,NULL)); PrintDependingOnLength(-56, server_entry->sv1_comment); PrintNL(); } } NetApiBufferFree(pEnumBuffer); } else { DWORD avail ; DWORD totAvail;
if( bShowCache == TRUE ) { dwErr = NetShareEnum(name, 501, (LPBYTE*)&pEnumBuffer, MAX_PREFERRED_LENGTH, &_read, &totAvail, NULL); }
if( bShowCache == FALSE || (dwErr != NO_ERROR && dwErr != ERROR_BAD_NETPATH) ) { dwErr = NetShareEnum(name, 1, (LPBYTE*)&pEnumBuffer, MAX_PREFERRED_LENGTH, &_read, &totAvail, NULL); b501 = FALSE; }
if( dwErr == ERROR_MORE_DATA ) { more_data = TRUE; } else if (dwErr) { ErrorExit(dwErr); }
if (_read == 0) { EmptyExit(); }
/* Are there any shares that we will display? */
for (i=0, share_entry = (LPSHARE_INFO_1) pEnumBuffer; i < _read; i++, NEXT_SHARE_ENTRY( share_entry ) ) { DollarPtr = _tcsrchr(share_entry->shi1_netname, DOLLAR);
//
// If no DOLLAR in sharename, or last DOLLAR is nonterminal, it is a
// valid share and we want to display it. Find out the lengths of the
// longest strings to display so that we can format the output in a
// decent way
//
if (!DollarPtr || *(DollarPtr + 1)) { int iTempLength = 0;
//
// Get the share name string that needs the most screen characters
// to be displayed.
//
iTempLength = SizeOfHalfWidthString(share_entry->shi1_netname);
if (iTempLength > iLongestShareName) { iLongestShareName = iTempLength; }
//
// Get the share type string that needs the most screen characters
// to be displayed.
//
switch ( share_entry->shi1_type & ~STYPE_SPECIAL ) { case STYPE_DISKTREE : iTempLength = SizeOfHalfWidthString(ViewMsgList[USE_TYPE_DISK].msg_text); break; case STYPE_PRINTQ : iTempLength = SizeOfHalfWidthString(ViewMsgList[USE_TYPE_PRINT].msg_text); break; case STYPE_DEVICE : iTempLength = SizeOfHalfWidthString(ViewMsgList[USE_TYPE_COMM].msg_text); break; case STYPE_IPC : iTempLength = SizeOfHalfWidthString(ViewMsgList[USE_TYPE_IPC].msg_text); break; default: iTempLength = SizeOfHalfWidthString(ViewMsgList[USE_TYPE_UNKNOWN].msg_text); break; }
if (iTempLength > iLongestType) { iLongestType = iTempLength; }
//
// Get the Used As string that needs the most screen characters
// to be displayed. Add 2 for a backslash and NUL character.
//
if (dwErr = AllocMem((wcslen(name) + wcslen(share_entry->shi1_netname) + 2) * sizeof(WCHAR), &tname)) { ErrorExit(dwErr); }
_tcscpy(tname, name); _tcscat(tname, TEXT("\\")); _tcscat(tname, share_entry->shi1_netname);
if (!get_used_as ( tname, Buffer, LITTLE_BUF_SIZE - 1 )) { iTempLength = SizeOfHalfWidthString(Buffer);
if (iTempLength > iLongestUsedAs) { iLongestUsedAs = iTempLength; } }
FreeMem(tname); tname = NULL;
//
// Get the cache or remark string (depending on which one we
// will end up displaying) that needs the most screen characters
// to be displayed.
//
if( b501 == TRUE) { TCHAR *CacheString = NULL;
switch(((LPSHARE_INFO_501) share_entry)->shi501_flags & CSC_MASK) { case CSC_CACHE_MANUAL_REINT: iTempLength = SizeOfHalfWidthString(ViewMsgList[ VIEW_CACHED_MANUAL ].msg_text); break; case CSC_CACHE_AUTO_REINT: iTempLength = SizeOfHalfWidthString(ViewMsgList[ VIEW_CACHED_AUTO ].msg_text); break; case CSC_CACHE_VDO: iTempLength = SizeOfHalfWidthString(ViewMsgList[ VIEW_CACHED_VDO ].msg_text); break; case CSC_CACHE_NONE: iTempLength = SizeOfHalfWidthString(ViewMsgList[ VIEW_CACHED_DISABLED ].msg_text); break; } } else { iTempLength = SizeOfHalfWidthString(share_entry->shi1_remark); }
if (iTempLength > iLongestCacheOrRemark) { iLongestCacheOrRemark = iTempLength; } } }
if (!iLongestShareName) { //
// No shares to display
//
EmptyExit(); }
qsort(pEnumBuffer, _read, b501 ? sizeof(SHARE_INFO_501) : sizeof(SHARE_INFO_1), CmpShrInfo1);
InfoPrintInsTxt(APE_ViewResourcesAt, name);
if (dwErr = MNetServerGetInfo(name, 1, (LPBYTE*)&pGetInfoBuffer)) { PrintNL(); } else { server_entry = (LPSERVER_INFO_1) pGetInfoBuffer; comment = server_entry->sv1_comment; WriteToCon(TEXT("%Fws\r\n\r\n"), comment); NetApiBufferFree(pGetInfoBuffer); }
//
// Print the header
//
iLongestShareName = FindColumnWidthAndPrintHeader(iLongestShareName, APE2_VIEW_SVR_HDR_NAME, 2); iLongestType = FindColumnWidthAndPrintHeader(iLongestType, APE2_VIEW_SVR_HDR_TYPE, 2);
iLongestUsedAs = FindColumnWidthAndPrintHeader(iLongestUsedAs, APE2_VIEW_SVR_HDR_USEDAS, 2);
iLongestCacheOrRemark = FindColumnWidthAndPrintHeader(iLongestCacheOrRemark, APE2_VIEW_SVR_HDR_CACHEORREMARK, 2); PrintNL();
//
// Bail out on failure
//
if (iLongestShareName == -1 || iLongestType == -1 || iLongestUsedAs == -1 || iLongestCacheOrRemark == -1) { ErrorExit(ERROR_INVALID_PARAMETER); }
PrintNL(); PrintLine();
/* Print the listing */
for (i=0, share_entry = (LPSHARE_INFO_1) pEnumBuffer; i < _read; i++, NEXT_SHARE_ENTRY(share_entry)) { /* if the name end in $, do not print it */
DollarPtr = _tcsrchr(share_entry->shi1_netname, DOLLAR);
if (DollarPtr && *(DollarPtr + 1) == NULLC) { continue; } PrintDependingOnLength(iLongestShareName, share_entry->shi1_netname);
// mask out the non type related bits
switch ( share_entry->shi1_type & ~STYPE_SPECIAL ) { case STYPE_DISKTREE : msgPtr = ViewMsgList[USE_TYPE_DISK].msg_text; break; case STYPE_PRINTQ : msgPtr = ViewMsgList[USE_TYPE_PRINT].msg_text; break; case STYPE_DEVICE : msgPtr = ViewMsgList[USE_TYPE_COMM].msg_text; break; case STYPE_IPC : msgPtr = ViewMsgList[USE_TYPE_IPC].msg_text; break; default: msgPtr = ViewMsgList[USE_TYPE_UNKNOWN].msg_text; break; }
PrintDependingOnLength(iLongestType, msgPtr);
if (dwErr = AllocMem((wcslen(name) + wcslen(share_entry->shi1_netname) + 2) * sizeof(WCHAR), &tname)) { ErrorExit(dwErr); } _tcscpy(tname, name); _tcscat(tname, TEXT("\\")); _tcscat(tname, share_entry->shi1_netname);
if (dwErr = get_used_as ( tname, Buffer, LITTLE_BUF_SIZE - 1 )) { errorflag = TRUE; } else { PrintDependingOnLength(iLongestUsedAs, Buffer); }
FreeMem(tname); tname = NULL;
//
// Print out the cache settings for the share, if we're supposed to
//
if( b501 == TRUE ) { TCHAR *CacheString = NULL;
switch (((LPSHARE_INFO_501) share_entry)->shi501_flags & CSC_MASK) { case CSC_CACHE_MANUAL_REINT: CacheString = ViewMsgList[ VIEW_CACHED_MANUAL ].msg_text; break; case CSC_CACHE_AUTO_REINT: CacheString = ViewMsgList[ VIEW_CACHED_AUTO ].msg_text; break; case CSC_CACHE_VDO: CacheString = ViewMsgList[ VIEW_CACHED_VDO ].msg_text; break; case CSC_CACHE_NONE: CacheString = ViewMsgList[ VIEW_CACHED_DISABLED ].msg_text; break; }
PrintDependingOnLength(iLongestCacheOrRemark, CacheString ? CacheString : TEXT("")); } else { PrintDependingOnLength(iLongestCacheOrRemark, share_entry->shi1_remark); } PrintNL(); } NetApiBufferFree(pEnumBuffer); }
if ( errorflag ) { InfoPrint(APE_CmdComplWErrors); NetcmdExit(1); }
if ( more_data ) InfoPrint( APE_MoreData); else InfoSuccess(); }
/***
* cmpsvinfo1(sva,svb) * * Compares two SERVER_INFO_1 structures and returns a relative * lexical value, suitable for using in qsort. * */
int __cdecl CmpSvrInfo1(const VOID FAR * sva, const VOID FAR * svb) { return _tcsicmp(((LPSERVER_INFO_1) sva)->sv1_name, ((LPSERVER_INFO_1) svb)->sv1_name); }
/***
* CmpShrInfo1(share1,share2) * * Compares two SHARE_INFO_1 structures and returns a relative * lexical value, suitable for using in qsort. * */
int __cdecl CmpShrInfo1(const VOID FAR * share1, const VOID FAR * share2) { return _tcsicmp(((LPSHARE_INFO_1) share1)->shi1_netname, ((LPSHARE_INFO_1) share2)->shi1_netname); }
/***
* CmpShrInfoGen(share1,share2) * * Compares two NETRESOURCE structures and returns a relative * lexical value, suitable for using in qsort. * */
int __cdecl CmpShrInfoGen(const VOID FAR * share1, const VOID FAR * share2) { return _wcsicmp ( (*((LPNETRESOURCE *) share1))->lpRemoteName, (*((LPNETRESOURCE *) share2))->lpRemoteName ); }
/*
* Note- get_used_as assumes the message list has been loaded. */ DWORD get_used_as( LPTSTR unc, LPTSTR outbuf, DWORD cchBuf ) { DWORD dwErr; DWORD cTotalAvail; LPTSTR pBuffer; LPUSE_INFO_0 pUseInfo; DWORD i; DWORD eread; BOOL fMatch = FALSE; LPTSTR tname = NULL;
outbuf[0] = 0;
if (dwErr = NetUseEnum(DEFAULT_SERVER, 0, (LPBYTE*)&pBuffer, MAX_PREFERRED_LENGTH, &eread, &cTotalAvail, NULL)) { return dwErr; }
pUseInfo = (LPUSE_INFO_0) pBuffer;
for (i = 0; i < eread; i++) { if ( (!_tcsicmp(unc, pUseInfo[i].ui0_remote))) { fMatch = TRUE; } else { //
// <unc> didn't match -- try \\<unc> since we allow
// "net view <server>" as well as "net view \\<server>"
//
if (tname == NULL) { if (dwErr = AllocMem((wcslen(unc) + 3) * sizeof(WCHAR), &tname)) { return dwErr; }
tname[0] = tname[1] = L'\\'; }
wcscpy(tname + 2, unc);
if ( (!_tcsicmp(tname, pUseInfo[i].ui0_remote))) { fMatch = TRUE; } }
if (fMatch) { if (_tcslen(pUseInfo[i].ui0_local) > 0) { wcsncpy(outbuf, pUseInfo[i].ui0_local, cchBuf); } else { wcsncpy(outbuf, ViewMsgList[VIEW_UNC].msg_text, cchBuf); }
break; } }
NetApiBufferFree(pBuffer);
if (tname != NULL) { FreeMem(tname); }
return 0; }
/*
* Displays resources for another network (other than Lanman). This * function does not return. * * Args: * net - the shortname of the network we are interested in * node - the starting point of the enumeration. */ void display_other_net(TCHAR *net, TCHAR *node) { LPNETRESOURCE *lplpNetResource ; NETRESOURCE NetResource ; HANDLE Handle ;
BYTE TopLevelBuffer[4096] ; DWORD TopLevelBufferSize = sizeof(TopLevelBuffer) ; LPBYTE ResultBuffer ; DWORD ResultBufferSize ; DWORD i, dwErr, TopLevelCount, ResultCount = 0 ; TCHAR * ProviderName = get_provider_name(net) ;
//
// Check that we can get provider name and alloc the results
// buffer. Netcmd normally does not free memory it allocates,
// as it exits immediately.
//
if (!ProviderName) { DWORD dwErr = list_nets();
if (dwErr != NERR_Success) { ErrorPrint(dwErr, 0); }
NetcmdExit(1) ; }
if (dwErr = AllocMem(ResultBufferSize = 8192, &ResultBuffer)) { ErrorExit(dwErr); }
if (!node) { BOOL found = FALSE ;
//
// no node, so must be top level. enum the top and find
// matching provider.
//
dwErr = WNetOpenEnum(RESOURCE_GLOBALNET, 0, 0, NULL, &Handle) ;
if (dwErr != WN_SUCCESS) { ErrorExit (dwErr) ; } do { TopLevelCount = 0xFFFFFFFF ;
dwErr = WNetEnumResource(Handle, &TopLevelCount, TopLevelBuffer, &TopLevelBufferSize) ; if (dwErr == WN_SUCCESS || dwErr == WN_NO_MORE_ENTRIES) { LPNETRESOURCE lpNet ; DWORD i ; //
// go thru looking for the right provider
//
lpNet = (LPNETRESOURCE) TopLevelBuffer ; for ( i = 0; i < TopLevelCount; i++, lpNet++ ) { DWORD dwEnumErr ; if (!_tcsicmp(lpNet->lpProvider, ProviderName)) { //
// found it!
//
found = TRUE ;
//
// now go enumerate that network.
//
dwEnumErr = enum_net_resource(lpNet, &ResultBuffer, &ResultBufferSize, &ResultCount) ; if (dwEnumErr) { // dont report any errors here
WNetCloseEnum(Handle); ErrorExit(dwEnumErr); }
break ; } } } else { //
// error occured.
//
WNetCloseEnum(Handle); // dont report any errors here
ErrorExit(dwErr); } } while ((dwErr == WN_SUCCESS) && !found) ; WNetCloseEnum(Handle) ; // dont report any errors here
if (!found) { ErrorExit(ERROR_BAD_PROVIDER); } } else { //
// node is provided, lets start there.
//
NETRESOURCE NetRes ; DWORD dwEnumErr ;
memset(&NetRes, 0, sizeof(NetRes)) ;
NetRes.lpProvider = ProviderName ; NetRes.lpRemoteName = node ;
dwEnumErr = enum_net_resource(&NetRes, &ResultBuffer, &ResultBufferSize, &ResultCount) ; if (dwEnumErr) { ErrorExit(dwEnumErr); } } if (ResultCount == 0) { EmptyExit(); }
//
// By the time we get here, we have a buffer of pointers that
// point to NETRESOURCE structures. We sort the pointers, and then
// print them out.
//
qsort(ResultBuffer, ResultCount, sizeof(LPNETRESOURCE), CmpShrInfoGen); lplpNetResource = (LPNETRESOURCE *)ResultBuffer ;
if (node) { TCHAR *TypeString ;
InfoPrintInsTxt(APE_ViewResourcesAt, node); PrintLine();
for (i = 0; i < ResultCount; i++, lplpNetResource++) { switch ((*lplpNetResource)->dwType) { case RESOURCETYPE_DISK: TypeString = ViewMsgList[USE_TYPE_DISK].msg_text; break ; case RESOURCETYPE_PRINT: TypeString = ViewMsgList[USE_TYPE_PRINT].msg_text; break ; default: TypeString = L"" ; break ; } WriteToCon(TEXT("%Fs %s\r\n"), PaddedString(12,TypeString,NULL), (*lplpNetResource)->lpRemoteName) ; } } else { InfoPrintInsTxt(APE2_VIEW_OTHER_HDR, ProviderName); PrintLine();
for (i = 0; i < ResultCount; i++, lplpNetResource++) { WriteToCon(TEXT("%s\r\n"), (*lplpNetResource)->lpRemoteName) ; } }
InfoSuccess(); NetcmdExit(0); }
/*
* Enumerates resources for a network starting at a specific point. * * Args: * lpNetResourceStart - Where to start the enumeration * ResultBuffer - Used to return array of pointers to NETRESOURCEs. * May be reallocated as need. * ResultBufferSize - Buffer size, also used to return final size. * ResultCount - Used to return number of entries in buffer. */ DWORD enum_net_resource( LPNETRESOURCE lpNetResourceStart, LPBYTE *ResultBuffer, LPDWORD ResultBufferSize, LPDWORD ResultCount ) { DWORD dwErr ; HANDLE EnumHandle ; DWORD Count ; DWORD err ; LPBYTE Buffer ; DWORD BufferSize ; BOOL fDisconnect = FALSE ; LPNETRESOURCE *lpNext = (LPNETRESOURCE *)*ResultBuffer ; //
// allocate memory and open the enumeration
//
if (err = AllocMem(BufferSize = 8192, &Buffer)) { return err; }
dwErr = WNetOpenEnum(RESOURCE_GLOBALNET, 0, 0, lpNetResourceStart, &EnumHandle) ;
if (dwErr == ERROR_NOT_AUTHENTICATED) { //
// try connecting with default credentials. we need this because
// Win95 changed the behaviour of the API to fail if we are not
// already logged on. below will attempt a logon with default
// credentials, but will fail if that doesnt work.
//
dwErr = WNetAddConnection2(lpNetResourceStart, NULL, NULL, 0) ;
if (dwErr == NERR_Success) { dwErr = WNetOpenEnum(RESOURCE_GLOBALNET, // redo the enum
0, 0, lpNetResourceStart, &EnumHandle) ;
if (dwErr == NERR_Success) { fDisconnect = TRUE ; // remember to disconnect
} else { //
// disconnect now
//
WNetCancelConnection2(lpNetResourceStart->lpRemoteName, 0, FALSE) ; } } else { dwErr = ERROR_NOT_AUTHENTICATED ; // use original error
} }
if (dwErr != WN_SUCCESS) { return dwErr; }
do { Count = 0xFFFFFFFF ; dwErr = WNetEnumResource(EnumHandle, &Count, Buffer, &BufferSize) ;
if (((dwErr == WN_SUCCESS) || (dwErr == WN_NO_MORE_ENTRIES)) && (Count != 0xFFFFFFFF))
// NOTE - the check for FFFFFFFF is workaround for another bug in API.
{ LPNETRESOURCE lpNetResource ; DWORD i ; lpNetResource = (LPNETRESOURCE) Buffer ;
//
// stick the entries into the MyUseInfoBuffer
//
for ( i = 0; i < Count; i++,lpNetResource++ ) { *lpNext++ = lpNetResource ; ++(*ResultCount) ; if ((LPBYTE)lpNext >= (*ResultBuffer + *ResultBufferSize)) { DWORD err;
*ResultBufferSize *= 2 ; if (err = ReallocMem(*ResultBufferSize,ResultBuffer)) { ErrorExit(err); }
lpNext = (LPNETRESOURCE *) *ResultBuffer ; lpNext += *ResultCount ; } }
//
// allocate a new buffer for next set, since we still need
// data in the old one, we dont free it. Netcmd always lets the
// system clean up when it exits.
//
if (dwErr == WN_SUCCESS) { if (err = AllocMem(BufferSize, &Buffer)) { if (fDisconnect) { WNetCancelConnection2(lpNetResourceStart->lpRemoteName, 0, FALSE); }
ErrorExit(err); } } } else { if (dwErr == WN_NO_MORE_ENTRIES) dwErr = WN_SUCCESS ;
WNetCloseEnum(EnumHandle) ; // dont report any errors here
if (fDisconnect) { WNetCancelConnection2(lpNetResourceStart->lpRemoteName, 0, FALSE);
} return dwErr; } } while (dwErr == WN_SUCCESS);
WNetCloseEnum(EnumHandle) ; // we dont report any errors here
if (fDisconnect) { WNetCancelConnection2(lpNetResourceStart->lpRemoteName, 0, FALSE) ; }
return NERR_Success ; }
#define SHORT_NAME_KEY L"System\\CurrentControlSet\\Control\\NetworkProvider\\ShortName"
/*
* Given a short name for a network, find the real name (stored in registry). * * Args: * net - the short name * * Returns: * Pointer to static data containing the looked up name if successful, * NULL otherwise. */ TCHAR * get_provider_name(TCHAR *net) { DWORD err ; static TCHAR buffer[256] ; HKEY hKey ; DWORD buffersize, datatype ;
buffersize = sizeof(buffer) ; datatype = REG_SZ ;
err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SHORT_NAME_KEY, 0L, KEY_QUERY_VALUE, &hKey) ;
if (err != ERROR_SUCCESS) return NULL ; err = RegQueryValueEx(hKey, net, 0L, &datatype, (LPBYTE) buffer, &buffersize) ;
(void) RegCloseKey(hKey) ; // ignore any error here. its harmless
// and NET.EXE doesnt hang around anyway.
if (err != ERROR_SUCCESS) return(NULL) ; // treat as cannot read
return ( buffer ) ; }
/*
* Print out the installed nets * * Args: * none * * Returns: * NERR_Success if success * error code otherwise. */ DWORD list_nets( VOID ) { DWORD err ; TCHAR value_name[256] ; TCHAR value_data[512] ; HKEY hKey ; BOOL fProviderFound = FALSE ; DWORD iValue, value_name_size, value_data_size ;
err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SHORT_NAME_KEY, 0L, KEY_QUERY_VALUE, &hKey) ;
if (err != ERROR_SUCCESS) { if (err == ERROR_FILE_NOT_FOUND) { err = ERROR_BAD_PROVIDER; }
return err; }
iValue = 0 ;
do { value_name_size = sizeof(value_name)/sizeof(value_name[0]) ; value_data_size = sizeof(value_data) ; err = RegEnumValue(hKey, iValue, value_name, &value_name_size, NULL, NULL, (LPBYTE) value_data, &value_data_size) ;
if (err == NO_ERROR) { if (!fProviderFound) { PrintNL(); InfoPrint(APE2_VIEW_OTHER_LIST) ; fProviderFound = TRUE; }
WriteToCon(TEXT("\t%s - %s\r\n"),value_name, value_data) ; }
iValue++ ;
} while (err == NO_ERROR) ;
RegCloseKey(hKey) ; // ignore any error here. its harmless
// and NET.EXE doesnt hang around anyway.
if (err == ERROR_NO_MORE_ITEMS) { if (!fProviderFound) { return ERROR_BAD_PROVIDER; }
return NO_ERROR; } return err; }
|