diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/nw/nwlib/nwapi32.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/nw/nwlib/nwapi32.c')
-rw-r--r-- | private/nw/nwlib/nwapi32.c | 1661 |
1 files changed, 1661 insertions, 0 deletions
diff --git a/private/nw/nwlib/nwapi32.c b/private/nw/nwlib/nwapi32.c new file mode 100644 index 000000000..cab4c7d45 --- /dev/null +++ b/private/nw/nwlib/nwapi32.c @@ -0,0 +1,1661 @@ +/*++ + +Copyright (C) 1993 Microsoft Corporation + +Module Name: + + NWAPI32.C + +Abstract: + + This module contains the NetWare(R) SDK support to routines + into the NetWare redirector + +Author: + + Chris Sandys (a-chrisa) 09-Sep-1993 + +Revision History: + + Chuck Y. Chan (chuckc) 02/06/94 Moved to NWCS. Make it more NT like. + Chuck Y. Chan (chuckc) 02/27/94 Clear out old code. + Make logout work. + Check for error in many places. + Dont hard code strings. + Remove non compatible parameters. + Lotsa other cleanup. + +--*/ + + +#include "procs.h" +#include "nwapi32.h" +#include <stdio.h> + +// +// Define structure for internal use. Our handle passed back from attach to +// file server will be pointer to this. We keep server string around for +// discnnecting from the server on logout. The structure is freed on detach. +// Callers should not use this structure but treat pointer as opaque handle. +// +typedef struct _NWC_SERVER_INFO { + HANDLE hConn ; + UNICODE_STRING ServerString ; +} NWC_SERVER_INFO, *PNWC_SERVER_INFO ; + +// +// define define categories of errors +// +typedef enum _NCP_CLASS { + NcpClassConnect, + NcpClassBindery, + NcpClassDir +} NCP_CLASS ; + +// +// define error mapping structure +// +typedef struct _NTSTATUS_TO_NCP { + NTSTATUS NtStatus ; + NWCCODE NcpCode ; +} NTSTATUS_TO_NCP, *LPNTSTATUS_TO_NCP ; + +// +// Error mappings for directory errors +// +NTSTATUS_TO_NCP MapNcpDirErrors[] = +{ + {STATUS_NO_SUCH_DEVICE, VOLUME_DOES_NOT_EXIST}, + {STATUS_INVALID_HANDLE, BAD_DIRECTORY_HANDLE}, + {STATUS_OBJECT_PATH_NOT_FOUND, INVALID_PATH}, + {STATUS_UNSUCCESSFUL, INVALID_PATH}, + {STATUS_NO_MORE_ENTRIES, NO_SUCH_OBJECT}, + {STATUS_ACCESS_DENIED, NO_OBJECT_READ_PRIVILEGE}, + {STATUS_INSUFF_SERVER_RESOURCES, SERVER_OUT_OF_MEMORY}, + { 0, 0 } +} ; + +// +// Error mappings for connect errors +// +NTSTATUS_TO_NCP MapNcpConnectErrors[] = +{ + {STATUS_UNSUCCESSFUL, INVALID_CONNECTION}, + {STATUS_ACCESS_DENIED, NO_OBJECT_READ_PRIVILEGE}, + {STATUS_NO_MORE_ENTRIES, UNKNOWN_FILE_SERVER}, + {STATUS_INSUFF_SERVER_RESOURCES, SERVER_OUT_OF_MEMORY}, + { 0, 0 } +} ; + +// +// Error mappings for bindery errors +// +NTSTATUS_TO_NCP MapNcpBinderyErrors[] = +{ + {STATUS_ACCESS_DENIED, NO_OBJECT_READ_PRIVILEGE}, + {STATUS_NO_MORE_ENTRIES, NO_SUCH_OBJECT}, + {STATUS_INVALID_PARAMETER, NO_SUCH_PROPERTY}, + {STATUS_UNSUCCESSFUL, INVALID_CONNECTION}, + {STATUS_INSUFF_SERVER_RESOURCES, SERVER_OUT_OF_MEMORY}, + { 0, 0 } +} ; + + +// +// Forwards +// +NTSTATUS +NwAttachToServer( + LPWSTR ServerName, + LPHANDLE phandleServer + ); + +NTSTATUS +NwDetachFromServer( + HANDLE handleServer +); + +DWORD +CancelAllConnections( + LPWSTR pszServer +); + + +NWCCODE +MapNtStatus( + const NTSTATUS ntstatus, + const NCP_CLASS ncpclass +); + +DWORD +SetWin32ErrorFromNtStatus( + NTSTATUS NtStatus +) ; + +DWORD +szToWide( + LPWSTR lpszW, + LPCSTR lpszC, + INT nSize +); + +// +// Static functions used internally +// + +LPSTR +NwDupStringA( + const LPSTR lpszA, + WORD length +) +{ + LPSTR lpRet; + + // + // Allocate memory + // + lpRet = LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT , length ); + + if(lpRet == NULL) return(NULL); + + // + // Dupulicate string + // + memcpy( (LPVOID)lpRet, (LPVOID)lpszA, length ); + + return(lpRet); +} + + +VOID +MapSpecialJapaneseChars( + LPSTR lpszA, + WORD length +) +{ + LCID lcid; +// +// Netware Japanese version The following character is replaced with another one +// if the string is for File Name only when sendding from Client to Server. +// +// any char, even DBCS trailByte. +// +// SJIS+0xBF -> 0x10 +// SJIS+0xAE -> 0x11 +// SJIS+0xAA -> 0x12 +// +// DBCS TrailByte only. +// +// SJIS+0x5C -> 0x13 +// + +// Get system locale and language ID in Kernel mode in order to +// distinguish the currently running system. + + NtQueryDefaultLocale( TRUE, &lcid ); + + if (! (PRIMARYLANGID(lcid) == LANG_JAPANESE || + PRIMARYLANGID(lcid) == LANG_KOREAN || + PRIMARYLANGID(lcid) == LANG_CHINESE) ) { + + return; + } + + if(lpszA == NULL) + return; + + if( PRIMARYLANGID(lcid) == LANG_JAPANESE ) { + + while( length ) { + + if( IsDBCSLeadByte(*lpszA) ) { + + // + // This is a DBCS character, check trailbyte is 0x5C or not. + // + + lpszA++; + length--; + if( *lpszA == 0x5C ) { + *lpszA = (UCHAR)0x13; + } + + } + + switch( (UCHAR) *lpszA ) { + case 0xBF : + *lpszA = (UCHAR)0x10; + break; + case 0xAE : + *lpszA = (UCHAR)0x11; + break; + case 0xAA : + *lpszA = (UCHAR)0x12; + break; + } + + // + // next char + // + lpszA++; + length--; + } + } + else if (PRIMARYLANGID(lcid) == LANG_CHINESE || + PRIMARYLANGID(lcid) == LANG_KOREAN) { + + while( length ) { + if( IsDBCSLeadByte(*lpszA) && *(lpszA+1) == 0x5C ) { + *(lpszA+1) = (UCHAR)0x13; + } + + switch( (UCHAR) *lpszA ) { + + case 0xBF : + *lpszA = (UCHAR)0x10; + break; + + case 0xAE : + *lpszA = (UCHAR)0x11; + break; + + case 0xAA : + *lpszA = (UCHAR)0x12; + break; + } + + // + // next char + // + lpszA++; + length--; + } + } +} + +VOID +UnmapSpecialJapaneseChars( + LPSTR lpszA, + WORD length +) +{ + LCID lcid; + + // + // Get system locale and language ID in Kernel mode in order to + // distinguish the currently running system. + // + + NtQueryDefaultLocale( TRUE, &lcid ); + + if (! (PRIMARYLANGID(lcid) == LANG_JAPANESE || + PRIMARYLANGID(lcid) == LANG_KOREAN || + PRIMARYLANGID(lcid) == LANG_CHINESE) ) { + + return; + } + + if (lpszA == NULL) + return; + + if( PRIMARYLANGID(lcid) == LANG_JAPANESE ) { + while( length ) { + if( IsDBCSLeadByte(*lpszA) ) { + // + // This is a DBCS character, check trailbyte is 0x5C or not. + // + lpszA++; + length--; + if( *lpszA == 0x13 ) { + *lpszA = (UCHAR)0x5C; + } + } + + switch( (UCHAR) *lpszA ) { + case 0x10 : + *lpszA = (UCHAR)0xBF; + break; + case 0x11 : + *lpszA = (UCHAR)0xAE; + break; + case 0x12 : + *lpszA = (UCHAR)0xAA; + break; + } + // + // next char + // + lpszA++; + length--; + } + } + else if (PRIMARYLANGID(lcid) == LANG_CHINESE || + PRIMARYLANGID(lcid) == LANG_KOREAN) { + + while( length ) { + switch( (UCHAR) *lpszA ) { + case 0x10 : + *lpszA = (UCHAR)0xBF; + break; + case 0x11 : + *lpszA = (UCHAR)0xAE; + break; + case 0x12 : + *lpszA = (UCHAR)0xAA; + break; + } + // have to check after restoring leadbyte values + if( IsDBCSLeadByte(*lpszA) && *(lpszA+1) == 0x13 ) { + *(lpszA+1) = (UCHAR)0x5C; + } + // + // next char + // + lpszA++; + length--; + } + } +} + +DWORD +szToWide( + LPWSTR lpszW, + LPCSTR lpszC, + INT nSize + ) +{ + if (!MultiByteToWideChar(CP_ACP, + MB_PRECOMPOSED, + lpszC, + -1, + lpszW, + nSize)) + { + return (GetLastError()) ; + } + + return NO_ERROR ; +} + + +NWCCODE +MapNtStatus( + const NTSTATUS ntstatus, + const NCP_CLASS ncpclass + ) +{ + LPNTSTATUS_TO_NCP pErrorMap ; + + if (ntstatus == STATUS_SUCCESS) + return SUCCESSFUL ; + + switch ( ncpclass ) { + case NcpClassBindery: + pErrorMap = MapNcpBinderyErrors ; + break ; + case NcpClassDir: + pErrorMap = MapNcpDirErrors ; + break ; + case NcpClassConnect: + pErrorMap = MapNcpConnectErrors ; + break ; + default: + return 0xFFFF ; + } + + while (pErrorMap->NtStatus) + { + if (pErrorMap->NtStatus == ntstatus) + return (pErrorMap->NcpCode) ; + + pErrorMap++ ; + } + + return 0xFFFF ; +} + +DWORD +SetWin32ErrorFromNtStatus( + NTSTATUS NtStatus +) +{ + DWORD Status ; + + if (NtStatus & 0xC0010000) { // netware specific + + Status = ERROR_EXTENDED_ERROR ; + + } else if (NtStatus == NWRDR_PASSWORD_HAS_EXPIRED) { + + Status = 0 ; // note this is not an error (the operation suceeded!) + + } else { + + Status = RtlNtStatusToDosError(NtStatus) ; + + } + + SetLastError(Status) ; + + return Status ; +} + +// +// FormatString - Supplies an ANSI string which describes how to +// convert from the input arguments into NCP request fields, and +// from the NCP response fields into the output arguments. +// +// Field types, request/response: +// +// 'b' byte ( byte / byte* ) +// 'w' hi-lo word ( word / word* ) +// 'd' hi-lo dword ( dword / dword* ) +// '-' zero/skip byte ( void ) +// '=' zero/skip word ( void ) +// ._. zero/skip string ( word ) +// 'p' pstring ( char* ) +// 'P' DBCS pstring ( char* ) +// 'c' cstring ( char* ) +// 'C' cstring followed skip word ( char*, word ) +// 'r' raw bytes ( byte*, word ) +// 'R' DBCS raw bytes ( byte*, word ) +// 'u' p unicode string ( UNICODE_STRING * ) +// 'U' p uppercase string( UNICODE_STRING * ) +// 'W' word n followed by an array of word[n] ( word, word* ) +// +// +// +// +// Standard NCP Function Block +// +// +// NWCCODE NWAPI DLLEXPORT +// NW***( +// NWCONN_HANDLE hConn, +// ) +// { +// NWCCODE NcpCode; +// NTSTATUS NtStatus; +// +// NtStatus = NwlibMakeNcp( +// hConn, // Connection Handle +// FSCTL_NWR_NCP_E3H, // Bindery function +// , // Max request packet size +// , // Max response packet size +// "b|", // Format string +// // === REQUEST ================================ +// 0x, // b Function +// // === REPLY ================================== +// ); +// +// return MapNtStatus( NtStatus, NcpClassXXX ); +// } +// +// + +NWCCODE NWAPI DLLEXPORT +NWAddTrusteeToDirectory( + NWCONN_HANDLE hConn, + NWDIR_HANDLE dirHandle, + const char NWFAR *pszPath, + NWOBJ_ID dwTrusteeID, + NWACCESS_RIGHTS rightsMask + ) +{ + unsigned short reply; + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E2H, // Directory function + 265, // Max request packet size + 2, // Max response packet size + "bbrbP|", // Format string + // === REQUEST ================================ + 0x0d, // b Add trustee to directory + dirHandle, // b 0xffffffff to start or last returned ID when enumerating HI-LO + &dwTrusteeID,DW_SIZE, // r Object ID to assigned to directory + rightsMask, // b User rights for directory + pszPath, // P Directory (if dirHandle = 0 then vol:directory) + // === REPLY ================================== + &reply // Not used + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassDir ); + +} +NWCCODE NWAPI DLLEXPORT +NWAllocPermanentDirectoryHandle( + NWCONN_HANDLE hConn, + NWDIR_HANDLE dirHandle, + char NWFAR *pszDirPath, + NWDIR_HANDLE NWFAR *pbNewDirHandle, + NWACCESS_RIGHTS NWFAR *pbRightsMask + ) +{ + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E2H, // E2 Function function + 261, // Max request packet size + 4, // Max response packet size + "bbbP|bb", // Format string + // === REQUEST ================================ + 0x12, // b Function Alloc Perm Dir + dirHandle, // b 0 for new + 0, // b Drive Letter + pszDirPath, // P Volume Name (SYS: or SYS:\PUBLIC) + // === REPLY ================================== + pbNewDirHandle, // b Dir Handle + pbRightsMask // b Rights + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassDir ); +} + +NWCCODE NWAPI DLLEXPORT +NWAllocTemporaryDirectoryHandle( + NWCONN_HANDLE hConn, + NWDIR_HANDLE dirHandle, + char NWFAR *pszDirPath, + NWDIR_HANDLE NWFAR *pbNewDirHandle, + NWACCESS_RIGHTS NWFAR *pbRightsMask + ) +{ + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E2H, // E2 Function function + 261, // Max request packet size + 4, // Max response packet size + "bbbP|bb", // Format string + // === REQUEST ================================ + 0x13, // b Function Alloc Temp Dir + dirHandle, // b 0 for new + 0, // b Drive Letter + pszDirPath, // P Volume Name (SYS: or SYS:\PUBLIC) + // === REPLY ================================== + pbNewDirHandle, // b Dir Handle + pbRightsMask // b Rights + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassDir ); +} + +NWCCODE NWAPI DLLEXPORT +NWAttachToFileServer( + const char NWFAR *pszServerName, + NWLOCAL_SCOPE ScopeFlag, + NWCONN_HANDLE NWFAR *phNewConn + ) +{ + DWORD dwRes; + NWCCODE nwRes; + LPWSTR lpwszServerName; // Pointer to buffer for WIDE servername + int nSize; + PNWC_SERVER_INFO pServerInfo ; + + + // + // check parameters and init return result to be null. + // + if (!pszServerName || !phNewConn) + return INVALID_CONNECTION ; + + *phNewConn = NULL ; + + // + // Allocate a buffer for wide server name + // + nSize = strlen(pszServerName)+1 ; + if(!(lpwszServerName = (LPWSTR) LocalAlloc( + LPTR, + nSize * sizeof(WCHAR) ))) + { + nwRes = REQUESTER_ERROR ; + goto ExitPoint ; + } + if (szToWide( lpwszServerName, pszServerName, nSize ) != NO_ERROR) + { + nwRes = REQUESTER_ERROR ; + goto ExitPoint ; + } + + // + // Call createfile to get a handle for the redirector calls + // + nwRes = NWAttachToFileServerW( lpwszServerName, + ScopeFlag, + phNewConn ); + + +ExitPoint: + + // + // Free the memory allocated above before exiting + // + if (lpwszServerName) + (void) LocalFree( (HLOCAL) lpwszServerName ); + + // + // Return with NWCCODE + // + return( nwRes ); +} + + +NWCCODE NWAPI DLLEXPORT +NWAttachToFileServerW( + const WCHAR NWFAR *pszServerName, + NWLOCAL_SCOPE ScopeFlag, + NWCONN_HANDLE NWFAR *phNewConn + ) +{ + DWORD NtStatus; + NWCCODE nwRes; + LPWSTR lpwszServerName; // Pointer to buffer for WIDE servername + int nSize; + PNWC_SERVER_INFO pServerInfo ; + + UNREFERENCED_PARAMETER(ScopeFlag) ; + + // + // check parameters and init return result to be null. + // + if (!pszServerName || !phNewConn) + return INVALID_CONNECTION ; + + *phNewConn = NULL ; + + // + // Allocate a buffer to store the file server name + // + nSize = wcslen(pszServerName)+3 ; + if(!(lpwszServerName = (LPWSTR) LocalAlloc( + LPTR, + nSize * sizeof(WCHAR) ))) + { + nwRes = REQUESTER_ERROR ; + goto ExitPoint ; + } + wcscpy( lpwszServerName, L"\\\\" ); + wcscat( lpwszServerName, pszServerName ); + + // + // Allocate a buffer for the server info (handle + name pointer). Also + // init the unicode string. + // + if( !(pServerInfo = (PNWC_SERVER_INFO) LocalAlloc( + LPTR, + sizeof(NWC_SERVER_INFO))) ) + { + nwRes = REQUESTER_ERROR ; + goto ExitPoint ; + } + RtlInitUnicodeString(&pServerInfo->ServerString, lpwszServerName) ; + + // + // Call createfile to get a handle for the redirector calls + // + NtStatus = NwAttachToServer( lpwszServerName, &pServerInfo->hConn ); + + if(NT_SUCCESS(NtStatus)) + { + nwRes = SUCCESSFUL; + } + else + { + (void) SetWin32ErrorFromNtStatus( NtStatus ); + nwRes = MapNtStatus( NtStatus, NcpClassConnect ); + } + +ExitPoint: + + // + // Free the memory allocated above before exiting + // + if (nwRes != SUCCESSFUL) + { + if (lpwszServerName) + (void) LocalFree( (HLOCAL) lpwszServerName ); + if (pServerInfo) + (void) LocalFree( (HLOCAL) pServerInfo ); + } + else + *phNewConn = (HANDLE) pServerInfo ; + + // + // Return with NWCCODE + // + return( nwRes ); +} + +NWCCODE NWAPI DLLEXPORT +NWCheckConsolePrivileges( + NWCONN_HANDLE hConn + ) +{ + WORD wDummy; + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E3H, // Bindery function + 3, // Max request packet size + 2, // Max response packet size + "b|r", // Format string + // === REQUEST ================================ + 0xC8, // b Get Console Privilges + // === REPLY ================================== + &wDummy,W_SIZE // r Dummy Response + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassBindery ); +} + +NWCCODE NWAPI DLLEXPORT +NWDeallocateDirectoryHandle( + NWCONN_HANDLE hConn, + NWDIR_HANDLE dirHandle + ) +{ + WORD wDummy; + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E2H, // E2 Function function + 4, // Max request packet size + 2, // Max response packet size + "bb|w", // Format string + // === REQUEST ================================ + 0x14, // b Function Dealloc Dir Hand + dirHandle, // b 0 for new + // === REPLY ================================== + &wDummy + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassDir ); +} + +NWCCODE NWAPI DLLEXPORT +NWDetachFromFileServer( + NWCONN_HANDLE hConn + ) +{ + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + (void) NwDetachFromServer( pServerInfo->hConn ); + + (void) LocalFree (pServerInfo->ServerString.Buffer) ; + + // + // catch any body that still trirs to use this puppy... + // + pServerInfo->ServerString.Buffer = NULL ; + pServerInfo->hConn = NULL ; + + (void) LocalFree (pServerInfo) ; + + return SUCCESSFUL; +} + +NWCCODE NWAPI DLLEXPORT +NWGetFileServerVersionInfo( + NWCONN_HANDLE hConn, + VERSION_INFO NWFAR *lpVerInfo + ) +{ + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E3H, // Bindery function + 3, // Max request packet size + 130, // Max response packet size + "b|r", // Format string + // === REQUEST ================================ + 0x11, // b Get File Server Information + // === REPLY ================================== + lpVerInfo, // r File Version Structure + sizeof(VERSION_INFO) + ); + + // Convert HI-LO words to LO-HI + // =========================================================== + lpVerInfo->ConnsSupported = wSWAP( lpVerInfo->ConnsSupported ); + lpVerInfo->connsInUse = wSWAP( lpVerInfo->connsInUse ); + lpVerInfo->maxVolumes = wSWAP( lpVerInfo->maxVolumes ); + lpVerInfo->PeakConns = wSWAP( lpVerInfo->PeakConns ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassBindery ); +} + +NWCCODE NWAPI DLLEXPORT +NWGetInternetAddress( + NWCONN_HANDLE hConn, + NWCONN_NUM nConnNum, + NWNET_ADDR NWFAR *pIntAddr + ) +{ + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E3H, // Bindery function + 4, // Max request packet size + 14, // Max response packet size + "bb|r", // Format string + // === REQUEST ================================ + 0x13, // b Get Internet Address + nConnNum, // b Connection Number + // === REPLY ================================== + pIntAddr,12 // r File Version Structure + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassBindery ); +} + + +NWCCODE NWAPI DLLEXPORT +NWGetObjectName( + NWCONN_HANDLE hConn, + NWOBJ_ID dwObjectID, + char NWFAR *pszObjName, + NWOBJ_TYPE NWFAR *pwObjType ) +{ + NWOBJ_ID dwRetID; + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E3H, // Bindery function + 7, // Max request packet size + 56, // Max response packet size + "br|rrR", // Format string + // === REQUEST ================================ + 0x36, // b Get Bindery Object Name + &dwObjectID,DW_SIZE, // r Object ID HI-LO + // === REPLY ================================== + &dwRetID,DW_SIZE, // r Object ID HI-LO + pwObjType,W_SIZE, // r Object Type + pszObjName,48 // R Object Name + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassBindery ); +} + +// This function not supported (E3 E9) +NWCCODE NWAPI DLLEXPORT +NWGetVolumeInfoWithNumber( + NWCONN_HANDLE hConn, + NWVOL_NUM nVolNum, + char NWFAR *pszVolName, + NWNUMBER NWFAR *pwTotalBlocks, + NWNUMBER NWFAR *pwSectors, + NWNUMBER NWFAR *pwAvailBlocks, + NWNUMBER NWFAR *pwTotalDir, + NWNUMBER NWFAR *pwAvailDir, + NWVOL_FLAGS NWFAR *pfVolRemovable + ) +{ + WORD wTime; // w Elapsed Time + BYTE bVoln; // b Vol Num + BYTE bDriven; // b Drive Num + WORD wStartBlock; // w Starting Block + WORD wMaxUsedDir; // w Actual Max Used Directory Entries + BYTE bVolHashed; // b Volume is hashed + BYTE bVolCached; // b Volume is Cached + BYTE bVolMounted; // b Volume is mounted + + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E3H, // Bindery function + 4, // Max request packet size + 42, // Max response packet size + "bb|wbbwwwwwwwbbbbr", // Format string + // === REQUEST ================================ + 0xe9, // b Get Volume Information + nVolNum, // b Volume Number (0 to Max Vol) + // === REPLY ================================== + &wTime, // w Elapsed Time + &bVoln, // b Vol Num + &bDriven, // b Drive Num + pwSectors, // w Sectors per block + &wStartBlock, // w Starting Block + pwTotalBlocks, // w Total Blocks + pwAvailBlocks, // w Available Blocks (free) + pwTotalDir, // w Total Dir Slots + pwAvailDir, // w Available Directory Slots + &wMaxUsedDir, // w Actual Max Used Directory Entries + &bVolHashed, // b Volume is hashed + &bVolCached, // b Volume is Cached + pfVolRemovable, // b Volume is removable + &bVolMounted, // b Volume is mounted + pszVolName,16 // r Volume Name + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassBindery ); +} + +NWCCODE NWAPI DLLEXPORT +NWGetVolumeInfoWithHandle( + NWCONN_HANDLE hConn, + NWDIR_HANDLE nDirHand, + char NWFAR *pszVolName, + NWNUMBER NWFAR *pwTotalBlocks, + NWNUMBER NWFAR *pwSectors, + NWNUMBER NWFAR *pwAvailBlocks, + NWNUMBER NWFAR *pwTotalDir, + NWNUMBER NWFAR *pwAvailDir, + NWVOL_FLAGS NWFAR *pfVolRemovable + ) +{ + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E2H, // Bindery function + 4, // Max request packet size + 30, // Max response packet size + "bb|wwwwwrb", // Format string + // === REQUEST ================================ + 0x15, // b Get Volume Information + nDirHand, // b Dir Handle + // === REPLY ================================== + pwSectors, // w Sectors per block + pwTotalBlocks, // w Total Blocks + pwAvailBlocks, // w Available Blocks (free) + pwTotalDir, // w Total Dir Slots + pwAvailDir, // w Available Directory Slots + pszVolName,16, // r Volume Name + pfVolRemovable // b Volume is removable + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassDir ); +} + +NWCCODE NWAPI DLLEXPORT +NWGetVolumeName( + NWCONN_HANDLE hConn, + NWVOL_NUM bVolNum, + char NWFAR *pszVolName + ) +{ + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E2H, // Directory Services + 4, // Max request packet size + 19, // Max response packet size + "bb|p", // Format string + // === REQUEST ================================ + 0x06, // Get Volume Name + bVolNum, // Volume Number + // === REPLY ================================== + pszVolName // Return Volume name + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassDir ); +} + +NWCCODE NWAPI DLLEXPORT +NWIsObjectInSet( + NWCONN_HANDLE hConn, + const char NWFAR *lpszObjectName, + NWOBJ_TYPE wObjType, + const char NWFAR *lpszPropertyName, + const char NWFAR *lpszMemberName, + NWOBJ_TYPE wMemberType + ) +{ + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + WORD Dummy; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E3H, // Bindery function + 122, // Max request packet size + 2, // Max response packet size + "brPPrP|", // Format string + // === REQUEST ================================ + 0x43, // b Read Property Value + &wObjType,W_SIZE, // r OT_??? HI-LO + lpszObjectName, // P Object Name + lpszPropertyName, // P Prop Name + &wMemberType,W_SIZE, // r Member Type + lpszMemberName, // P Member Name + // === REPLY ================================== + &Dummy,W_SIZE + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassBindery ); + +} // NWIsObjectInSet + +NWCCODE NWAPI DLLEXPORT +NWLoginToFileServer( + NWCONN_HANDLE hConn, + const char NWFAR *pszUserName, + NWOBJ_TYPE wObType, + const char NWFAR *pszPassword + ) +{ + NETRESOURCEW NetResource; + DWORD dwRes, dwSize; + NWCCODE nwRes; + LPWSTR pszUserNameW = NULL, + pszPasswordW = NULL; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + // + // validate parameters + // + if (!hConn || !pszUserName || !pszPassword) + return INVALID_CONNECTION ; + + // + // allocate memory for unicode strings and convert ANSI input + // to Unicode. + // + dwSize = strlen(pszUserName)+1 ; + if (!(pszUserNameW = (LPWSTR)LocalAlloc( + LPTR, + dwSize * sizeof(WCHAR)))) + { + nwRes = REQUESTER_ERROR ; + goto ExitPoint ; + } + if (szToWide( pszUserNameW, pszUserName, dwSize ) != NO_ERROR) + { + nwRes = REQUESTER_ERROR ; + goto ExitPoint ; + } + + dwSize = strlen(pszPassword)+1 ; + if (!(pszPasswordW = (LPWSTR)LocalAlloc( + LPTR, + dwSize * sizeof(WCHAR)))) + { + nwRes = REQUESTER_ERROR ; + goto ExitPoint ; + } + + if (szToWide( pszPasswordW, pszPassword, dwSize ) != NO_ERROR) + { + nwRes = REQUESTER_ERROR ; + goto ExitPoint ; + } + + NetResource.dwScope = 0 ; + NetResource.dwUsage = 0 ; + NetResource.dwType = RESOURCETYPE_ANY; + NetResource.lpLocalName = NULL; + NetResource.lpRemoteName = (LPWSTR) pServerInfo->ServerString.Buffer; + NetResource.lpComment = NULL; + NetResource.lpProvider = NULL ; + + // + // make the connection + // + dwRes=NPAddConnection ( &NetResource, + pszPasswordW, + pszUserNameW ); + + if( NO_ERROR != dwRes ) { + dwRes = GetLastError(); + switch( dwRes ) { + case ERROR_SESSION_CREDENTIAL_CONFLICT: + nwRes = SUCCESSFUL; + break; + case ERROR_ALREADY_ASSIGNED: + nwRes = ALREADY_ATTACHED; + break; + case ERROR_ACCESS_DENIED: + case ERROR_BAD_DEV_TYPE: + case ERROR_BAD_DEVICE: + case ERROR_BAD_NET_NAME: + case ERROR_BAD_PROFILE: + case ERROR_CANNOT_OPEN_PROFILE: + case ERROR_DEVICE_ALREADY_REMEMBERED: + case ERROR_EXTENDED_ERROR: + case ERROR_INVALID_PASSWORD: + case ERROR_NO_NET_OR_BAD_PATH: + case ERROR_NO_NETWORK: + nwRes = INVALID_CONNECTION; + break; + default: + nwRes = INVALID_CONNECTION; + break; + } + } else { + nwRes = SUCCESSFUL; + } + +ExitPoint: + + if (pszUserNameW) + (void) LocalFree((HLOCAL) pszUserNameW) ; + if (pszPasswordW) + (void) LocalFree((HLOCAL) pszPasswordW) ; + + return( nwRes ); +} + +NWCCODE NWAPI DLLEXPORT +NWLogoutFromFileServer( + NWCONN_HANDLE hConn + ) +{ + DWORD dwRes; + NWCCODE nwRes; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + // + // cancel all explicit connections to that server + // + (void) CancelAllConnections ( pServerInfo->ServerString.Buffer ); + + // + // now cancel the any connection to \\servername. + // + dwRes=NPCancelConnection( pServerInfo->ServerString.Buffer, TRUE ); + + if( NO_ERROR != dwRes ) { + dwRes = GetLastError(); + switch( dwRes ) + { + case ERROR_NOT_CONNECTED: + case ERROR_INVALID_HANDLE: + nwRes = SUCCESSFUL; + break; + + case ERROR_BAD_PROFILE: + case ERROR_CANNOT_OPEN_PROFILE: + case ERROR_DEVICE_IN_USE: + case ERROR_EXTENDED_ERROR: + nwRes = INVALID_CONNECTION; + break; + default: + nwRes = INVALID_CONNECTION; + break; + } + } else { + nwRes = SUCCESSFUL; + } + + return( nwRes ); +} + +NWCCODE NWAPI DLLEXPORT +NWReadPropertyValue( + NWCONN_HANDLE hConn, + const char NWFAR *pszObjName, + NWOBJ_TYPE wObjType, + char NWFAR *pszPropName, + unsigned char ucSegment, + char NWFAR *pValue, + NWFLAGS NWFAR *pucMoreFlag, + NWFLAGS NWFAR *pucPropFlag + ) +{ + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E3H, // Bindery function + 70, // Max request packet size + 132, // Max response packet size + "brPbP|rbb", // Format string + // === REQUEST ================================ + 0x3D, // b Read Property Value + &wObjType,W_SIZE, // r Object Type HI-LO + pszObjName, // P Object Name + ucSegment, // b Segment Number + pszPropName, // P Property Name + // === REPLY ================================== + pValue,128, // r Property value + pucMoreFlag, // b More Flag + pucPropFlag // b Prop Flag + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassBindery ); +} + +NWCCODE NWAPI DLLEXPORT +NWScanObject( + NWCONN_HANDLE hConn, + const char NWFAR *pszSearchName, + NWOBJ_TYPE wObjSearchType, + NWOBJ_ID NWFAR *pdwObjectID, + char NWFAR *pszObjectName, + NWOBJ_TYPE NWFAR *pwObjType, + NWFLAGS NWFAR *pucHasProperties, + NWFLAGS NWFAR *pucObjectFlags, + NWFLAGS NWFAR *pucObjSecurity + ) +{ + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E3H, // Bindery function + 57, // Max request packet size + 59, // Max response packet size + "brrP|rrRbbb", // Format string + // === REQUEST ================================ + 0x37, // b Scan bindery object + pdwObjectID,DW_SIZE, // r 0xffffffff to start or last returned ID when enumerating HI-LO + &wObjSearchType,W_SIZE, // r Use OT_??? Defines HI-LO + pszSearchName, // P Search Name. (use "*") for all + // === REPLY ================================== + pdwObjectID,DW_SIZE, // r Returned ID HI-LO + pwObjType,W_SIZE, // r rObject Type HI-LO + pszObjectName,48, // R Found Name + pucObjectFlags, // b Object Flag + pucObjSecurity, // b Object Security + pucHasProperties // b Has Properties + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassBindery ); +} + +NWCCODE NWAPI DLLEXPORT +NWScanProperty( + NWCONN_HANDLE hConn, + const char NWFAR *pszObjectName, + NWOBJ_TYPE wObjType, + char NWFAR *pszSearchName, + NWOBJ_ID NWFAR *pdwSequence, + char NWFAR *pszPropName, + NWFLAGS NWFAR *pucPropFlags, + NWFLAGS NWFAR *pucPropSecurity, + NWFLAGS NWFAR *pucHasValue, + NWFLAGS NWFAR *pucMore + ) +{ + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E3H, // Bindery function + 73, // Max request packet size + 26, // Max response packet size + "brPrP|Rbbrbb", // Format string + // === REQUEST ================================ + 0x3C, // b Scan Prop function + &wObjType,W_SIZE, // r Type of Object + pszObjectName, // P Object Name + pdwSequence,DW_SIZE, // r Sequence HI-LO + pszSearchName, // P Property Name to Search for + // === REPLY ================================== + pszPropName,16, // R Returned Property Name + pucPropFlags, // b Property Flags + pucPropSecurity, // b Property Security + pdwSequence,DW_SIZE, // r Sequence HI-LO + pucHasValue, // b Property Has value + pucMore // b More Properties + ); + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassBindery ); +} + + + + +NWCCODE NWAPI DLLEXPORT +NWGetFileServerDateAndTime( + NWCONN_HANDLE hConn, + BYTE NWFAR *year, + BYTE NWFAR *month, + BYTE NWFAR *day, + BYTE NWFAR *hour, + BYTE NWFAR *minute, + BYTE NWFAR *second, + BYTE NWFAR *dayofweek + ) +{ + NTSTATUS NtStatus ; + PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ; + + NtStatus = NwlibMakeNcp( + pServerInfo->hConn, // Connection Handle + FSCTL_NWR_NCP_E0H, // Server function + 0, // Max request packet size + 9, // Max response packet size + "|bbbbbbb", // Format string + // === REQUEST ================================ + // === REPLY ================================== + year, + month, + day, + hour, + minute, + second, + dayofweek + ); + + + (void) SetWin32ErrorFromNtStatus( NtStatus ); + return MapNtStatus( NtStatus, NcpClassConnect ); + +} // NWGetFileServerDateAndTime + + +// +// worker routines +// + +#define NW_RDR_SERVER_PREFIX L"\\Device\\Nwrdr\\" + +NTSTATUS +NwAttachToServer( + IN LPWSTR ServerName, + OUT LPHANDLE phandleServer + ) +/*++ + +Routine Description: + + This routine opens a handle to the given server. + +Arguments: + + ServerName - The server name to attach to. + phandleServer - Receives an opened handle to the preferred or + nearest server. + +Return Value: + + 0 or reason for failure. + +--*/ +{ + NTSTATUS ntstatus = STATUS_SUCCESS; + IO_STATUS_BLOCK IoStatusBlock; + OBJECT_ATTRIBUTES ObjectAttributes; + + LPWSTR FullName; + UNICODE_STRING UServerName; + + FullName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, + (UINT) ( wcslen( NW_RDR_SERVER_PREFIX) + + wcslen( ServerName ) - 1) * + sizeof(WCHAR) + ); + + if ( FullName == NULL ) { + return STATUS_INSUFFICIENT_RESOURCES ; + } + + wcscpy( FullName, NW_RDR_SERVER_PREFIX ); + wcscat( FullName, ServerName + 2 ); // Skip past the prefix "\\" + + RtlInitUnicodeString( &UServerName, FullName ); + + InitializeObjectAttributes( + &ObjectAttributes, + &UServerName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL + ); + + // + // Open a handle to the preferred server. + // + ntstatus = NtOpenFile( + phandleServer, + SYNCHRONIZE | FILE_LIST_DIRECTORY, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_VALID_FLAGS, + FILE_SYNCHRONOUS_IO_NONALERT + ); + + if ( NT_SUCCESS(ntstatus)) { + ntstatus = IoStatusBlock.Status; + } + + if (! NT_SUCCESS(ntstatus)) { + *phandleServer = NULL; + } + + LocalFree( FullName ); + return (ntstatus); +} + + +NTSTATUS +NwDetachFromServer( + IN HANDLE handleServer + ) +/*++ + +Routine Description: + + This routine closes a handle to the given server. + +Arguments: + + handleServer - Supplies a open handle to be closed. + +Return Value: + + NO_ERROR or reason for failure. + +--*/ +{ + NTSTATUS ntstatus = NtClose( handleServer ); + return (ntstatus); +} + + +DWORD +CancelAllConnections( + LPWSTR pszServer +) +/*++ + +Routine Description: + + This routine cancels all connections to a server + +Arguments: + + pszServer - the server we are disconnecting from + +Return Value: + + NO_ERROR or win32 error for failure. + +--*/ +{ + DWORD status = ERROR_NO_NETWORK; + HANDLE EnumHandle = (HANDLE) NULL; + + LPNETRESOURCE NetR = NULL; + + DWORD BytesNeeded = 4096; + DWORD EntriesRead; + DWORD i; + + // + // Retrieve the list of connections + // + status = NPOpenEnum( + RESOURCE_CONNECTED, + 0, + 0, + NULL, + &EnumHandle + ); + + if (status != NO_ERROR) { + EnumHandle = (HANDLE) NULL; + goto CleanExit; + } + + // + // Allocate buffer to get connection list. + // + if ((NetR = (LPNETRESOURCE) LocalAlloc( + LPTR, + (UINT) BytesNeeded + )) == NULL) { + + status = ERROR_NOT_ENOUGH_MEMORY; + goto CleanExit; + } + + do { + + EntriesRead = 0xFFFFFFFF; // Read as many as possible + + status = NPEnumResource( + EnumHandle, + &EntriesRead, + (LPVOID) NetR, + &BytesNeeded + ); + + if (status == WN_SUCCESS) + { + LPNETRESOURCE TmpPtr = NetR; + + for (i = 0; i < EntriesRead; i++, TmpPtr++) + { + LPWSTR pszTmp ; + + // + // If it contains the server we are logging off from, we want + // to cancel it. First, lets extract the server name part. + // + + pszTmp = TmpPtr->lpRemoteName ; + + if (!pszTmp || !*pszTmp) + continue ; + + if ((*pszTmp == L'\\') && (*(pszTmp+1) == L'\\')) + pszTmp += 2 ; + + if (pszTmp = wcschr(pszTmp, L'\\')) + *pszTmp = 0 ; + + if (_wcsicmp(TmpPtr->lpRemoteName, pszServer) == 0) + { + // + // Aha, it matches. Restore the '\' and nuke it with force. + // Ignore errors here. + // + if (pszTmp) + *pszTmp = L'\\' ; + + if (TmpPtr->lpLocalName && *(TmpPtr->lpLocalName)) + { + // + // if local name present, its a redirection. + // + (void) NPCancelConnection( TmpPtr->lpLocalName,TRUE ); + } + else + { + // + // else cancel the deviceless use + // + (void) NPCancelConnection( TmpPtr->lpRemoteName,TRUE ); + } + } + } + + } + else if (status != WN_NO_MORE_ENTRIES) { + + status = GetLastError(); + + if (status == WN_MORE_DATA) { + + // + // Original buffer was too small. Free it and allocate + // the recommended size and then some to get as many + // entries as possible. + // + + (void) LocalFree((HLOCAL) NetR); + + if ((NetR = (LPNETRESOURCE) LocalAlloc( + LPTR, + (UINT) BytesNeeded + )) == NULL) { + + status = ERROR_NOT_ENOUGH_MEMORY; + goto CleanExit; + } + } + else + { + // + // cant handle other errors. bag out. + // + goto CleanExit; + } + } + + } while (status != WN_NO_MORE_ENTRIES); + + if (status == WN_NO_MORE_ENTRIES) + { + status = NO_ERROR; + } + +CleanExit: + + if (EnumHandle != (HANDLE) NULL) + { + (void) NPCloseEnum(EnumHandle); + } + + if (NetR != NULL) + { + (void) LocalFree((HLOCAL) NetR); + } + + return status; +} |