summaryrefslogtreecommitdiffstats
path: root/private/nw/nwlib/nwapi32.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/nwlib/nwapi32.c')
-rw-r--r--private/nw/nwlib/nwapi32.c1661
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;
+}