//Copyright (c) 1998 - 1999 Microsoft Corporation /************************************************************************* * * NWLAN.C * * Name Enumerator for Novell Netware * * *************************************************************************/ /* * Includes */ #include #include #include #include #include #include #include #include #include #include "qappsrv.h" /*============================================================================= == External Functions Defined =============================================================================*/ int NwEnumerate( void ); /*============================================================================= == LoadLibrary/GetProcAddress stuff for NWAPI32.DLL =============================================================================*/ /* * NWAPI32.DLL stuff */ #define PSZ_NWAPI32 TEXT("NWAPI32.DLL") #define PSZ_NWATTACHTOFILESERVER "NWAttachToFileServer" #define PSZ_NWDETACHFROMFILESERVER "NWDetachFromFileServer" #define PSZ_NWREADPROPERTYVALUE "NWReadPropertyValue" #define PSZ_NWSCANOBJECT "NWScanObject" typedef NWCCODE (NWAPI DLLEXPORT *PNWATTACHTOFILESERVER) (const char NWFAR *, NWLOCAL_SCOPE, NWCONN_HANDLE NWFAR *); typedef NWCCODE (NWAPI DLLEXPORT *PNWDETACHFROMFILESERVER) (NWCONN_HANDLE); typedef NWCCODE (NWAPI DLLEXPORT *PNWREADPROPERTYVALUE) (NWCONN_HANDLE, const char NWFAR *, NWOBJ_TYPE, char NWFAR *, unsigned char, char NWFAR *, NWFLAGS NWFAR *, NWFLAGS NWFAR *); typedef NWCCODE (NWAPI DLLEXPORT *PNWSCANOBJECT) (NWCONN_HANDLE, const char NWFAR *, NWOBJ_TYPE, NWOBJ_ID NWFAR *, char NWFAR *, NWOBJ_TYPE NWFAR *, NWFLAGS NWFAR *, NWFLAGS NWFAR *, NWFLAGS NWFAR *); /*============================================================================= == Private Functions =============================================================================*/ int AppServerFindFirstNW( NWCONN_HANDLE, LPTSTR, ULONG, LPTSTR, ULONG ); int AppServerFindNextNW( NWCONN_HANDLE, LPTSTR, ULONG, LPTSTR, ULONG ); int GetNetwareAddress( NWCONN_HANDLE, LPBYTE, LPBYTE ); int w_appsrv_ff_fn( NWCONN_HANDLE, LPTSTR, ULONG, LPTSTR, ULONG ); void FormatAddress( PBYTE, PBYTE ); /*============================================================================= == Functions used =============================================================================*/ int TreeAdd( LPTSTR, LPTSTR ); /*============================================================================= == Local Data =============================================================================*/ static long objectID = -1; static PNWATTACHTOFILESERVER pNWAttachToFileServer = NULL; static PNWDETACHFROMFILESERVER pNWDetachFromFileServer = NULL; static PNWREADPROPERTYVALUE pNWReadPropertyValue = NULL; static PNWSCANOBJECT pNWScanObject = NULL; /*============================================================================= == Global Data =============================================================================*/ extern USHORT fAddress; /******************************************************************************* * * NwEnumerate * * NwEnumerate adds all the hydra application servers on a netware network * to a binary tree * * ENTRY: * nothing * * EXIT: * ERROR_SUCCESS - no error * ******************************************************************************/ int NwEnumerate() { NWCONN_HANDLE hConn; WCHAR abName[MAXNAME]; WCHAR Address[MAXADDRESS]; int rc; HINSTANCE hinst; /* * Load NWAPI32.DLL */ if ( (hinst = LoadLibrary( PSZ_NWAPI32 )) == NULL ) { return( ERROR_DLL_NOT_FOUND ); } /* * Load pointers to the NWAPI32 APIs that we'll need. */ if ( (((FARPROC)pNWAttachToFileServer = GetProcAddress( hinst, PSZ_NWATTACHTOFILESERVER )) == NULL) || (((FARPROC)pNWDetachFromFileServer = GetProcAddress( hinst, PSZ_NWDETACHFROMFILESERVER )) == NULL) || (((FARPROC)pNWReadPropertyValue = GetProcAddress( hinst, PSZ_NWREADPROPERTYVALUE )) == NULL) || (((FARPROC) pNWScanObject = GetProcAddress( hinst, PSZ_NWSCANOBJECT )) == NULL) ) { FreeLibrary( hinst ); return( ERROR_PROC_NOT_FOUND ); } /* * Attach to novell file server */ if ( rc = (*pNWAttachToFileServer)( "*", 0, &hConn ) ) goto badattach; /* * Get first appserver */ if ( rc = AppServerFindFirstNW( hConn, abName, sizeof(abName), Address, sizeof(Address) ) ) goto badfirst; /* * Get remaining appservers */ while ( rc == ERROR_SUCCESS ) { /* * Add appserver name to binary tree */ if ( rc = TreeAdd( abName, Address ) ) goto badadd; /* * Get next appserver name */ rc = AppServerFindNextNW( hConn, abName, sizeof(abName), Address, sizeof(Address) ); } /* * Detach from file server */ (void) (*pNWDetachFromFileServer)( hConn ); FreeLibrary( hinst ); return( ERROR_SUCCESS ); /*============================================================================= == Error returns =============================================================================*/ /* * binary tree name add failed * error getting first appserver name */ badadd: badfirst: (void) (*pNWDetachFromFileServer)( hConn ); /* * Attach failed */ badattach: return( rc ); } /******************************************************************************* * * GetNetwareAddress * * * ENTRY: * * EXIT: * nothing * * ******************************************************************************/ int GetNetwareAddress( NWCONN_HANDLE hConn, LPBYTE pAppServer, LPBYTE pAddress ) { int rc; unsigned char more; unsigned char PropFlags; /* Get property value */ rc = (*pNWReadPropertyValue)( hConn, pAppServer, // IN: object name CITRIX_APPLICATION_SERVER_SWAP, // IN: objectType "NET_ADDRESS", // IN: 1, // IN: 1st buffer pAddress, // OUT: Buffer to put Address &more, // OUT: 0 == no more 128 segment // ff == more 128 segments &PropFlags ); // OUT: optional return( rc ); } /******************************************************************************* * * AppServerFindFirstNW * * * ENTRY: * * EXIT: * nothing * * ******************************************************************************/ int AppServerFindFirstNW( NWCONN_HANDLE hConn, LPTSTR pAppServer, ULONG NameLength, LPTSTR pAddress, ULONG AddrLength ) { objectID = -1; return( w_appsrv_ff_fn( hConn, pAppServer, NameLength, pAddress, AddrLength ) ); } /******************************************************************************* * * AppServerFindNextNW * * * ENTRY: * * EXIT: * nothing * * ******************************************************************************/ int AppServerFindNextNW( NWCONN_HANDLE hConn, LPTSTR pAppServer, ULONG NameLength, LPTSTR pAddress, ULONG AddrLength ) { return( w_appsrv_ff_fn( hConn, pAppServer, NameLength, pAddress, AddrLength ) ); } /******************************************************************************* * * Worker routines * * * ENTRY: * * EXIT: * nothing * * ******************************************************************************/ int w_appsrv_ff_fn( NWCONN_HANDLE hConn, LPTSTR pAppServer, ULONG NameLength, LPTSTR pAddress, ULONG AddrLength ) { int rc; WORD objectType; unsigned char hasPropertiesFlag = 0; unsigned char objectFlags; unsigned char objectSecurity; BYTE abName[49]; BYTE Address[128]; BYTE FormatedAddress[MAXADDRESS]; ULONG ByteCount; /* while there are still properties */ while ( hasPropertiesFlag == 0 ) { /* scan bindery object */ if ( rc = (*pNWScanObject)( hConn, "*", CITRIX_APPLICATION_SERVER_SWAP, &objectID, abName, &objectType, &hasPropertiesFlag, &objectFlags, &objectSecurity )) { break; } } RtlMultiByteToUnicodeN( pAppServer, NameLength, &ByteCount, abName, (strlen(abName) + 1) ); /* get netware address */ if ( fAddress && GetNetwareAddress( hConn, abName, Address ) == ERROR_SUCCESS ) { FormatAddress( Address, FormatedAddress ); RtlMultiByteToUnicodeN( pAddress, AddrLength, &ByteCount, FormatedAddress, (strlen(FormatedAddress) + 1) ); } else { pAddress[0] = '\0'; } return( rc ); } /******************************************************************************* * * FormatAddress * * * ENTRY: * * EXIT: * nothing * * ******************************************************************************/ void FormatAddress( PBYTE pInternetAddress, PBYTE pszAddress ) { USHORT i; USHORT j; USHORT firstPass; BYTE buf2[5]; /* squish leading 0s on network address 1st */ firstPass = TRUE; pszAddress[0] = '['; pszAddress[1] = '\0'; for ( i=0; i<3; i++ ) { j=i; if ( pInternetAddress[i] ) { sprintf( buf2, "%2X", pInternetAddress[i] ); strcat( pszAddress, buf2 ); firstPass = FALSE; break; } else { strcat( pszAddress, " " ); } } /* remaining bytes */ for ( i=++j; i<4; i++ ) { if ( firstPass ) sprintf( buf2, "%2X", pInternetAddress[i] ); else sprintf( buf2, "%02X", pInternetAddress[i] ); strcat( pszAddress, buf2 ); firstPass = FALSE; } strcat( pszAddress, "][" ); /* squish leading 0s on network address 2nd */ firstPass = TRUE; for ( i=4; i<10; i++ ) { j=i; if ( pInternetAddress[i] ) { sprintf( buf2, "%2X", pInternetAddress[i] ); strcat( pszAddress, buf2 ); firstPass = FALSE; break; } else { strcat( pszAddress, " " ); } } /* remaining bytes */ for ( i=++j; i<10; i++ ) { if ( firstPass ) sprintf( buf2, "%2X", pInternetAddress[i] ); else sprintf( buf2, "%02X", pInternetAddress[i] ); strcat( pszAddress, buf2 ); firstPass = FALSE; } strcat( pszAddress, "]" ); }