windows-nt/Source/XPSP1/NT/ds/nw/nwlib/nwapi32.c
2020-09-26 16:20:57 +08:00

1547 lines
50 KiB
C

/*++
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.
Tommy R. Evans (tommye) 04/21/00 Added two routines:
NwNdsObjectHandleToConnHandle()
NwNdsConnHandleFree()
--*/
#include "procs.h"
#include "nwapi32.h"
#include <nds32.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, UNKNOWN_FILE_SERVER},
{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},
{STATUS_NO_SUCH_DEVICE, VOLUME_DOES_NOT_EXIST},
{STATUS_INVALID_HANDLE, BAD_DIRECTORY_HANDLE},
{STATUS_OBJECT_PATH_NOT_FOUND, INVALID_PATH},
// {0xC0010001, INVALID_CONNECTION},
// {0xC0010096, SERVER_OUT_OF_MEMORY},
// {0xC0010098, VOLUME_DOES_NOT_EXIST},
// {0xC001009B, BAD_DIRECTORY_HANDLE},
// {0xC001009C, INVALID_PATH},
// {0xC00100FB, NO_SUCH_PROPERTY},
// {0xC00100FC, NO_SUCH_OBJECT},
{ 0, 0 }
} ;
//
// Forwards
//
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) && (length >= 2) ) {
// Adding length>=2 ensure the Lead Byte is followed by
// a trail byte , Fix bug #102729
//
// 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) && (length >= 2) ) {
// Adding length>=2 ensure the Lead Byte is followed by
// a trail byte , Fix bug #102729
//
// 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
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
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\\"
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;
}
NWCCODE NWAPI DLLEXPORT
NWCreateQueue(
NWCONN_HANDLE hConn,
NWDIR_HANDLE dirHandle,
const char NWFAR *pszQueueName,
NWOBJ_TYPE wQueueType,
const char NWFAR *pszPathName,
NWOBJ_ID NWFAR *pdwQueueId
)
{
NTSTATUS NtStatus;
PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
NtStatus = NwlibMakeNcp(
pServerInfo->hConn, // Connection Handle
FSCTL_NWR_NCP_E3H, // Bindery function
174, // Max request packet size
6, // Max response packet size
"brPbP|r", // Format string
// === REQUEST ================================
0x64, // b Create Queue
&wQueueType,W_SIZE, // r Queue Type HI-LO
pszQueueName, // P Queue Name
dirHandle, // b Directory Handle
pszPathName, // P Path name
// === REPLY ==================================
pdwQueueId,DW_SIZE // r Queue ID HI-LO
);
(void) SetWin32ErrorFromNtStatus(NtStatus);
return MapNtStatus( NtStatus, NcpClassBindery );
}
NWCCODE NWAPI DLLEXPORT
NWChangePropertySecurity(
NWCONN_HANDLE hConn,
const char NWFAR *pszObjName,
NWOBJ_TYPE wObjType,
const char NWFAR *pszPropertyName,
NWFLAGS ucObjSecurity
)
{
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
2, // Max response packet size
"brPbP|", // Format string
// === REQUEST ================================
0x3B, // b Change Property Security
&wObjType,W_SIZE, // r OT_??? HI-LO
pszObjName, // P Prop Name
ucObjSecurity, // b New Property security
pszPropertyName // P Property Name
// === REPLY ==================================
);
(void) SetWin32ErrorFromNtStatus( NtStatus );
return MapNtStatus( NtStatus, NcpClassBindery );
}
NWCCODE NWAPI DLLEXPORT
NWDestroyQueue(
NWCONN_HANDLE hConn,
NWOBJ_ID dwQueueId
)
{
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
2, // Max response packet size
"bd|", // Format string
// === REQUEST ================================
0x65, // b Destroy Queue
dwQueueId // d Queue ID
// === REPLY ==================================
);
(void) SetWin32ErrorFromNtStatus( NtStatus );
return MapNtStatus( NtStatus, NcpClassBindery );
}
//
// tommye MS 88021 / MCS
//
// Added the following two routines to allow the library user
// to obtain a NWCONN_HANDLE given a ObjectHandle, then free that
// handle.
//
NWCONN_HANDLE NWAPI DLLEXPORT
NwNdsObjectHandleToConnHandle(
IN HANDLE ObjectHandle)
{
PNWC_SERVER_INFO pServerInfo;
LPNDS_OBJECT_PRIV pObject = (LPNDS_OBJECT_PRIV)ObjectHandle;
/** Allocate the NWCONN_HANDLE to return **/
pServerInfo = (PNWC_SERVER_INFO)LocalAlloc(LPTR, sizeof(NWC_SERVER_INFO));
if (pServerInfo == NULL) {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return NULL;
}
/** Fill it in **/
pServerInfo->hConn = pObject->NdsTree;
/**
Fill in the server name, even though NWLoginToFileServer and
NWLogoutFromFileServer are the only calls that use it now.
**/
RtlInitUnicodeString(
&pServerInfo->ServerString,
pObject->szContainerName);
/**
Return the pointer to the block, which is our form of NWCONN_HANDLE.
The caller is responsible for calling NwNdsConnHandlFree when done.
**/
return (NWCONN_HANDLE)pServerInfo;
}
VOID NWAPI DLLEXPORT
NwNdsConnHandleFree(
IN NWCONN_HANDLE hConn)
{
if (hConn) {
PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn;
/** Free the connection handle **/
LocalFree(pServerInfo);
}
/** All done **/
return;
}