summaryrefslogtreecommitdiffstats
path: root/private/nw/nwlib
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/nw/nwlib
downloadNT4.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')
-rw-r--r--private/nw/nwlib/canon.c480
-rw-r--r--private/nw/nwlib/exchange.c571
-rw-r--r--private/nw/nwlib/makefile6
-rw-r--r--private/nw/nwlib/ndsapi32.c2144
-rw-r--r--private/nw/nwlib/nwapi32.c1661
-rw-r--r--private/nw/nwlib/nwcapi32.c798
-rw-r--r--private/nw/nwlib/nwpapi32.c1011
-rw-r--r--private/nw/nwlib/packstr.c125
-rw-r--r--private/nw/nwlib/procs.h55
-rw-r--r--private/nw/nwlib/regacl.c161
-rw-r--r--private/nw/nwlib/sources66
-rw-r--r--private/nw/nwlib/tpath.c238
12 files changed, 7316 insertions, 0 deletions
diff --git a/private/nw/nwlib/canon.c b/private/nw/nwlib/canon.c
new file mode 100644
index 000000000..c33846a66
--- /dev/null
+++ b/private/nw/nwlib/canon.c
@@ -0,0 +1,480 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ canon.c
+
+Abstract:
+
+ Contains canonicalization routines for NetWare names.
+
+Author:
+
+ Rita Wong (ritaw) 19-Feb-1993
+
+Environment:
+
+
+Revision History:
+
+
+--*/
+
+
+#include <procs.h>
+
+
+DWORD
+NwLibValidateLocalName(
+ IN LPWSTR LocalName
+ )
+/*++
+
+Routine Description:
+
+ This routine checks to see if the supplied name is a valid
+ DOS device name.
+
+Arguments:
+
+ LocalName - Supplies a local device name. It can be any of
+ the following:
+
+ X:
+ LPTn or LPTn:
+ COMn or COMn:
+ PRN or PRN:
+ AUX or AUX:
+
+
+Return Value:
+
+ NO_ERROR - LocalName is valid.
+
+ WN_BAD_NETNAME - LocalName is invalid.
+
+--*/
+{
+ DWORD LocalNameLength;
+
+
+ //
+ // Cannot be a NULL or empty string
+ //
+ if (LocalName == NULL || *LocalName == 0) {
+ return WN_BAD_NETNAME;
+ }
+
+ LocalNameLength = wcslen(LocalName);
+
+ if (LocalNameLength == 1) {
+ return WN_BAD_NETNAME;
+ }
+
+ if (LocalName[LocalNameLength - 1] == L':') {
+ if (! IS_VALID_TOKEN(LocalName, LocalNameLength - 1)) {
+ return WN_BAD_NETNAME;
+ }
+ }
+ else {
+ if (! IS_VALID_TOKEN(LocalName, LocalNameLength)) {
+ return WN_BAD_NETNAME;
+ }
+ }
+
+ if (LocalNameLength == 2) {
+ //
+ // Must be in the form of X:
+ //
+ if (! iswalpha(*LocalName)) {
+ return WN_BAD_NETNAME;
+ }
+
+ if (LocalName[1] != L':') {
+ return WN_BAD_NETNAME;
+ }
+
+ return NO_ERROR;
+ }
+
+ if (RtlIsDosDeviceName_U(LocalName) == 0) {
+ return WN_BAD_NETNAME;
+ }
+
+ //
+ // Valid DOS device name but invalid redirection name
+ //
+ if (_wcsnicmp(LocalName, L"NUL", 3) == 0) {
+ return WN_BAD_NETNAME;
+
+ }
+ return NO_ERROR;
+}
+
+
+DWORD
+NwLibCanonLocalName(
+ IN LPWSTR LocalName,
+ OUT LPWSTR *OutputBuffer,
+ OUT LPDWORD OutputBufferLength OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ This routine canonicalizes the local name by uppercasing the string
+ and converting the following:
+
+ x: -> X:
+ LPTn: -> LPTn
+ COMn: -> COMn
+ PRN or PRN: -> LPT1
+ AUX or AUX: -> COM1
+
+Arguments:
+
+ LocalName - Supplies a local device name.
+
+ OutputBuffer - Receives a pointer to the canonicalized LocalName.
+
+ OutputBufferLength - Receives the length of the canonicalized name
+ in number of characters, if specified.
+
+Return Value:
+
+ NO_ERROR - Successfully canonicalized the local name.
+
+ WN_BAD_NETNAME - LocalName is invalid.
+
+ ERROR_NOT_ENOUGH_MEMORY - Could not allocate output buffer.
+
+--*/
+{
+ DWORD status;
+ DWORD LocalNameLength;
+
+
+ status = NwLibValidateLocalName(LocalName);
+
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ LocalNameLength = wcslen(LocalName);
+
+ //
+ // Allocate output buffer. Should be the size of the LocalName
+ // plus 1 for the special case of PRN -> LPT1 or AUX -> COM1.
+ //
+ *OutputBuffer = (PVOID) LocalAlloc(
+ LMEM_ZEROINIT,
+ (LocalNameLength + 2) * sizeof(WCHAR)
+ );
+
+ if (*OutputBuffer == NULL) {
+ KdPrint(("NWLIB: NwLibCanonLocalName LocalAlloc failed %lu\n",
+ GetLastError()));
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ wcscpy(*OutputBuffer, LocalName);
+
+ if (LocalNameLength > 2) {
+
+ if (_wcsnicmp(*OutputBuffer, L"PRN", 3) == 0) {
+
+ //
+ // Convert PRN or PRN: to LPT1
+ //
+ wcscpy(*OutputBuffer, L"LPT1");
+ LocalNameLength = 4;
+
+ }
+ else if (_wcsnicmp(*OutputBuffer, L"AUX", 3) == 0) {
+
+ //
+ // Convert AUX or AUX: to COM1
+ //
+ wcscpy(*OutputBuffer, L"COM1");
+ LocalNameLength = 4;
+ }
+
+ //
+ // Remove trailing colon, if there is one, and decrement the length
+ // of DOS device name.
+ //
+ if ((*OutputBuffer)[LocalNameLength - 1] == L':') {
+ (*OutputBuffer)[--LocalNameLength] = 0;
+ }
+ }
+
+ //
+ // LocalName is always in uppercase.
+ //
+ _wcsupr(*OutputBuffer);
+
+ if (ARGUMENT_PRESENT(OutputBufferLength)) {
+ *OutputBufferLength = LocalNameLength;
+ }
+
+ return NO_ERROR;
+}
+
+
+DWORD
+NwLibCanonRemoteName(
+ IN LPWSTR LocalName OPTIONAL,
+ IN LPWSTR RemoteName,
+ OUT LPWSTR *OutputBuffer,
+ OUT LPDWORD OutputBufferLength OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ This routine validates and canonicalizes the supplied
+ NetWare UNC name. It can be of any length in the form of:
+
+ \\Server\Volume\Directory\Subdirectory
+
+Arguments:
+
+ LocalName - Supplies the local device name. If it is NULL, then
+ \\Server is an acceptable format for the UNC name.
+
+ RemoteName - Supplies the UNC name.
+
+ OutputBuffer - Receives a pointer to the canonicalized RemoteName.
+
+ OutputBufferLength - Receives the length of the canonicalized name
+ in number of characters, if specified.
+
+Return Value:
+
+ NO_ERROR - RemoteName is valid.
+
+ WN_BAD_NETNAME - RemoteName is invalid.
+
+--*/
+{
+ DWORD RemoteNameLength;
+ DWORD i;
+ DWORD TokenLength;
+ LPWSTR TokenPtr;
+ BOOL fFirstToken = TRUE;
+
+
+ //
+ // Cannot be a NULL or empty string
+ //
+ if (RemoteName == NULL || *RemoteName == 0) {
+ return WN_BAD_NETNAME;
+ }
+
+ RemoteNameLength = wcslen(RemoteName);
+
+ //
+ // Must be at least \\x\y if local device name is specified.
+ // Otherwise it must be at least \\x.
+ //
+ if ((RemoteNameLength < 5 && ARGUMENT_PRESENT(LocalName)) ||
+ (RemoteNameLength < 3)) {
+ return WN_BAD_NETNAME;
+ }
+
+ //
+ // First two characters must be "\\"
+ //
+ if (*RemoteName != L'\\' || RemoteName[1] != L'\\') {
+ return WN_BAD_NETNAME;
+ }
+
+ if (! ARGUMENT_PRESENT(LocalName) &&
+ (IS_VALID_TOKEN(&RemoteName[2], RemoteNameLength - 2))) {
+
+ //
+ // Return success for \\Server case.
+ //
+
+ *OutputBuffer = (PVOID) LocalAlloc(
+ LMEM_ZEROINIT,
+ (RemoteNameLength + 1) * sizeof(WCHAR)
+ );
+
+ if (*OutputBuffer == NULL) {
+ KdPrint(("NWLIB: NwLibCanonRemoteName LocalAlloc failed %lu\n",
+ GetLastError()));
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ wcscpy(*OutputBuffer, RemoteName);
+
+ return NO_ERROR;
+ }
+
+ //
+ // Must have at least one more backslash after the third character
+ //
+ if (wcschr(&RemoteName[3], L'\\') == NULL) {
+ return WN_BAD_NETNAME;
+ }
+
+ //
+ // Last character cannot a backward slash
+ //
+ if (RemoteName[RemoteNameLength - 1] == L'\\') {
+ return WN_BAD_NETNAME;
+ }
+
+ //
+ // Allocate output buffer. Should be the size of the RemoteName
+ // and space for an extra character to simplify parsing code below.
+ //
+ *OutputBuffer = (PVOID) LocalAlloc(
+ LMEM_ZEROINIT,
+ (RemoteNameLength + 2) * sizeof(WCHAR)
+ );
+
+
+ if (*OutputBuffer == NULL) {
+ KdPrint(("NWLIB: NwLibCanonRemoteName LocalAlloc failed %lu\n",
+ GetLastError()));
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ wcscpy(*OutputBuffer, RemoteName);
+
+ //
+ // Convert all backslashes to NULL terminator, skipping first 2 chars.
+ //
+ for (i = 2; i < RemoteNameLength; i++) {
+ if ((*OutputBuffer)[i] == L'\\') {
+
+ (*OutputBuffer)[i] = 0;
+
+ //
+ // Two consecutive forward or backslashes is bad.
+ //
+ if ((i + 1 < RemoteNameLength) &&
+ ((*OutputBuffer)[i + 1] == L'\\')) {
+
+ (void) LocalFree((HLOCAL) *OutputBuffer);
+ *OutputBuffer = NULL;
+ return WN_BAD_NETNAME;
+ }
+ }
+ }
+
+ //
+ // Validate each token of the RemoteName, separated by NULL terminator.
+ //
+ TokenPtr = *OutputBuffer + 2; // Skip first 2 chars
+
+ while (*TokenPtr != 0) {
+
+ TokenLength = wcslen(TokenPtr);
+
+ if ( ( fFirstToken && !IS_VALID_SERVER_TOKEN(TokenPtr, TokenLength))
+ || ( !fFirstToken && !IS_VALID_TOKEN(TokenPtr, TokenLength))
+ )
+ {
+ (void) LocalFree((HLOCAL) *OutputBuffer);
+ *OutputBuffer = NULL;
+ return WN_BAD_NETNAME;
+ }
+
+ fFirstToken = FALSE;
+ TokenPtr += TokenLength + 1;
+ }
+
+ //
+ // Convert NULL separators to backslashes
+ //
+ for (i = 0; i < RemoteNameLength; i++) {
+ if ((*OutputBuffer)[i] == 0) {
+ (*OutputBuffer)[i] = L'\\';
+ }
+ }
+
+ if (ARGUMENT_PRESENT(OutputBufferLength)) {
+ *OutputBufferLength = RemoteNameLength;
+ }
+
+ return NO_ERROR;
+}
+
+
+DWORD
+NwLibCanonUserName(
+ IN LPWSTR UserName,
+ OUT LPWSTR *OutputBuffer,
+ OUT LPDWORD OutputBufferLength OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ This routine canonicalizes the user name by checking to see
+ if the name contains any illegal characters.
+
+
+Arguments:
+
+ UserName - Supplies a username.
+
+ OutputBuffer - Receives a pointer to the canonicalized UserName.
+
+ OutputBufferLength - Receives the length of the canonicalized name
+ in number of characters, if specified.
+
+Return Value:
+
+ NO_ERROR - Successfully canonicalized the username.
+
+ WN_BAD_NETNAME - UserName is invalid.
+
+ ERROR_NOT_ENOUGH_MEMORY - Could not allocate output buffer.
+
+--*/
+{
+ DWORD UserNameLength;
+
+
+ //
+ // Cannot be a NULL or empty string
+ //
+ if (UserName == NULL) {
+ return WN_BAD_NETNAME;
+ }
+
+ UserNameLength = wcslen(UserName);
+
+ if (! IS_VALID_TOKEN(UserName, UserNameLength)) {
+ return WN_BAD_NETNAME;
+ }
+
+ //
+ // Allocate output buffer. Should be the size of the UserName
+ // plus 1 for the special case of PRN -> LPT1 or AUX -> COM1.
+ //
+ *OutputBuffer = (PVOID) LocalAlloc(
+ LMEM_ZEROINIT,
+ (UserNameLength + 1) * sizeof(WCHAR)
+ );
+
+ if (*OutputBuffer == NULL) {
+ KdPrint(("NWLIB: NwLibCanonUserName LocalAlloc failed %lu\n",
+ GetLastError()));
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ wcscpy(*OutputBuffer, UserName);
+
+ if (ARGUMENT_PRESENT(OutputBufferLength)) {
+ *OutputBufferLength = UserNameLength;
+ }
+
+ return NO_ERROR;
+}
diff --git a/private/nw/nwlib/exchange.c b/private/nw/nwlib/exchange.c
new file mode 100644
index 000000000..52f34ad38
--- /dev/null
+++ b/private/nw/nwlib/exchange.c
@@ -0,0 +1,571 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ exchange.c
+
+Abstract:
+
+ Contains routine which packages the request buffer, makes
+ the NCP request, and unpackages the response buffer.
+
+Author:
+
+ Hans Hurvig (hanshu) Aug-1992 Created
+ Colin Watson (colinw) 19-Dec-1992
+ Rita Wong (ritaw) 11-Mar-1993 FSCtl version
+
+Environment:
+
+
+Revision History:
+
+
+--*/
+
+
+#include <procs.h>
+
+NTSTATUS
+NwlibMakeNcp(
+ IN HANDLE DeviceHandle,
+ IN ULONG FsControlCode,
+ IN ULONG RequestBufferSize,
+ IN ULONG ResponseBufferSize,
+ IN PCHAR FormatString,
+ ... // Arguments to FormatString
+ )
+/*++
+
+Routine Description:
+
+ This function converts the input arguments into an NCP request buffer
+ based on the format specified in FormatString (e.g. takes a word
+ and writes it in hi-lo format in the request buffer as required by
+ an NCP).
+
+ It then makes the NCP call via the NtFsControlFile API.
+
+ The FormatString also specifies how to convert the fields in the
+ response buffer from the completed NCP call into the output
+ arguments.
+
+ The FormatString takes the form of "xxxx|yyyy" where each 'x'
+ indicates an input argument to convert from, and each 'y' indicates
+ an output argument to convert into. The '|' character separates
+ the input format from the output format specifications.
+
+Arguments:
+
+ DeviceHandle - Supplies a handle to the network file system driver
+ which will be making the network request. This function
+ assumes that the handle was opened for synchronouse I/O access.
+
+ FsControlCode - Supplies the control code which determines the
+ NCP.
+
+ RequestBufferSize - Supplies the size of the request buffer in
+ bytes to be allocated by this routine.
+
+ ResponseBufferSize - Supplies the size of the response buffer in
+ bytes to be allocated by this routine.
+
+ 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* )
+
+Return Value:
+
+ Return code from the NCP call.
+
+--*/
+{
+ NTSTATUS status;
+
+ va_list Arguments;
+ PCHAR z;
+ WORD t = 1;
+ ULONG data_size;
+
+ LPBYTE RequestBuffer = NULL;
+ LPBYTE ResponseBuffer;
+
+ IO_STATUS_BLOCK IoStatusBlock;
+ DWORD ReturnedDataSize;
+
+
+ //
+ // Allocate memory for request and response buffers.
+ //
+ RequestBuffer = LocalAlloc(
+ LMEM_ZEROINIT,
+ RequestBufferSize + ResponseBufferSize
+ );
+
+ if (RequestBuffer == NULL) {
+ KdPrint(("NWLIB: NwlibMakeNcp LocalAlloc failed %lu\n", GetLastError()));
+ return STATUS_NO_MEMORY;
+ }
+
+ ResponseBuffer = (LPBYTE) ((ULONG) RequestBuffer + RequestBufferSize);
+
+
+ va_start( Arguments, FormatString );
+
+ //
+ // Convert the input arguments into request packet.
+ //
+ z = FormatString;
+
+ data_size = 0;
+
+ while ( *z && *z != '|')
+ {
+ switch ( *z )
+ {
+ case '=':
+ RequestBuffer[data_size++] = 0;
+ case '-':
+ RequestBuffer[data_size++] = 0;
+ break;
+
+ case '_':
+ {
+ WORD l = va_arg ( Arguments, WORD );
+ if (data_size + l > RequestBufferSize)
+ {
+ KdPrint(("NWLIB: NwlibMakeNcp case '_' request buffer too small\n"));
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto CleanExit;
+ }
+ while ( l-- )
+ RequestBuffer[data_size++] = 0;
+ break;
+ }
+
+ case 'b':
+ RequestBuffer[data_size++] = va_arg ( Arguments, BYTE );
+ break;
+
+ case 'w':
+ {
+ WORD w = va_arg ( Arguments, WORD );
+ RequestBuffer[data_size++] = (BYTE) (w >> 8);
+ RequestBuffer[data_size++] = (BYTE) (w >> 0);
+ break;
+ }
+
+ case 'd':
+ {
+ DWORD d = va_arg ( Arguments, DWORD );
+ RequestBuffer[data_size++] = (BYTE) (d >> 24);
+ RequestBuffer[data_size++] = (BYTE) (d >> 16);
+ RequestBuffer[data_size++] = (BYTE) (d >> 8);
+ RequestBuffer[data_size++] = (BYTE) (d >> 0);
+ break;
+ }
+
+ case 'c':
+ {
+ char* c = va_arg ( Arguments, char* );
+ WORD l = strlen( c );
+ if (data_size + l > RequestBufferSize)
+ {
+ KdPrint(("NWLIB: NwlibMakeNcp case 'c' request buffer too small\n"));
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto CleanExit;
+ }
+ RtlCopyMemory( &RequestBuffer[data_size], c, l+1 );
+ data_size += l + 1;
+ break;
+ }
+
+ case 'C':
+ {
+ char* c = va_arg ( Arguments, char* );
+ WORD l = va_arg ( Arguments, WORD );
+ WORD len = strlen( c ) + 1;
+ if (data_size + l > RequestBufferSize)
+ {
+ KdPrint(("NWLIB: NwlibMakeNcp case 'C' request buffer too small\n"));
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto CleanExit;
+ }
+
+ RtlCopyMemory( &RequestBuffer[data_size], c, len > l? l : len);
+ data_size += l;
+ RequestBuffer[data_size-1] = 0;
+ break;
+ }
+
+ case 'P':
+ case 'p':
+ {
+ char* c = va_arg ( Arguments, char* );
+ BYTE l = strlen( c );
+ char* p;
+
+ if (data_size + l > RequestBufferSize)
+ {
+ KdPrint(("NWLIB: NwlibMakeNcp case 'p' request buffer too small\n"));
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto CleanExit;
+ }
+ RequestBuffer[data_size++] = l;
+ RtlCopyMemory( (p=(char*)&RequestBuffer[data_size]), c, l );
+ data_size += l;
+
+ //
+ // Map Japanese special chars
+ //
+ if (*z == 'P') {
+ MapSpecialJapaneseChars(p, (WORD)l);
+ }
+
+ break;
+ }
+
+ case 'u':
+ {
+ PUNICODE_STRING pUString = va_arg ( Arguments, PUNICODE_STRING );
+ OEM_STRING OemString;
+ ULONG Length;
+
+ //
+ // Calculate required string length, excluding trailing NUL.
+ //
+
+ Length = RtlUnicodeStringToOemSize( pUString ) - 1;
+ ASSERT( Length < 0x100 );
+
+ if ( data_size + Length > RequestBufferSize ) {
+ KdPrint(("NWLIB: NwlibMakeNcp case 'u' request buffer too small\n"));
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto CleanExit;
+ }
+
+ RequestBuffer[data_size++] = (UCHAR)Length;
+ OemString.Buffer = &RequestBuffer[data_size];
+ OemString.MaximumLength = (USHORT)Length + 1;
+
+ //
+ // BUGBUG: The following should call RtlUnicodeStringToCountedOemString
+ // but this routine is not exported by ntdll.dll so we can't get to it.
+ //
+ status = RtlUnicodeStringToOemString( &OemString, pUString, FALSE );
+ ASSERT( NT_SUCCESS( status ));
+ data_size += (USHORT)Length;
+ break;
+ }
+
+ case 'U':
+ {
+ //
+ // UPPERCASE the string, copy it from unicode to the packet
+ //
+
+ PUNICODE_STRING pUString = va_arg ( Arguments, PUNICODE_STRING );
+ UNICODE_STRING UUppercaseString;
+ OEM_STRING OemString;
+ ULONG Length;
+
+ status = RtlUpcaseUnicodeString(&UUppercaseString, pUString, TRUE);
+ if ( status )
+ {
+ goto CleanExit;
+ }
+
+ pUString = &UUppercaseString;
+
+ //
+ // Calculate required string length, excluding trailing NUL.
+ //
+
+ Length = RtlUnicodeStringToOemSize( pUString ) - 1;
+ ASSERT( Length < 0x100 );
+
+ if ( data_size + Length > RequestBufferSize ) {
+ KdPrint(("NWLIB: NwlibMakeNcp case 'U' request buffer too small\n"));
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto CleanExit;
+ }
+
+ RequestBuffer[data_size++] = (UCHAR)Length;
+ OemString.Buffer = &RequestBuffer[data_size];
+ OemString.MaximumLength = (USHORT)Length + 1;
+
+ //
+ // BUGBUG: The following should call RtlUnicodeStringToCountedOemString
+ // but this routine is not exported by ntdll.dll so we can't get to it.
+ //
+ status = RtlUnicodeStringToOemString( &OemString, pUString, FALSE );
+ ASSERT( NT_SUCCESS( status ));
+
+ RtlFreeUnicodeString( &UUppercaseString );
+
+ data_size += (USHORT)Length;
+ break;
+ }
+
+ case 'R':
+ case 'r':
+ {
+ BYTE* b = va_arg ( Arguments, BYTE* );
+ WORD l = va_arg ( Arguments, WORD );
+ char* c;
+
+ if ( data_size + l > RequestBufferSize )
+ {
+ KdPrint(("NWLIB: NwlibMakeNcp case 'r' request buffer too small\n"));
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto CleanExit;
+ }
+
+ RtlCopyMemory( (c=(char*)&RequestBuffer[data_size]), b, l );
+ data_size += l;
+
+ //
+ // Map Japanese special chars
+ //
+ if (*z == 'R') {
+ MapSpecialJapaneseChars(c, (WORD)l);
+ }
+
+ break;
+ }
+
+ default:
+ KdPrint(("NWLIB: NwlibMakeNcp invalid request field, %x\n", *z));
+ ASSERT(FALSE);
+ }
+
+ if ( data_size > RequestBufferSize )
+ {
+ KdPrint(("NWLIB: NwlibMakeNcp too much request data\n"));
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto CleanExit;
+ }
+
+
+ z++;
+ }
+
+
+ //
+ // Make the NCP request
+ //
+ status = NtFsControlFile(
+ DeviceHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FsControlCode,
+ (PVOID) RequestBuffer,
+ RequestBufferSize,
+ (PVOID) ResponseBuffer,
+ ResponseBufferSize
+ );
+
+ if (status == STATUS_SUCCESS) {
+ status = IoStatusBlock.Status;
+ }
+
+ if (status != STATUS_SUCCESS) {
+
+#if 0
+ if (! NT_SUCCESS(status)) {
+ KdPrint(("NWLIB: NwlibMakeNcp: NtFsControlFile returns x%08lx\n", status));
+ }
+#endif
+
+ goto CleanExit;
+ }
+
+
+ ReturnedDataSize = IoStatusBlock.Information; // Number of bytes returned
+ // in ResponseBuffer
+
+
+ //
+ // Convert the response packet into output arguments.
+ //
+
+ data_size = 0;
+
+ if (*z && *z == '|') {
+ z++;
+ }
+
+ while ( *z )
+ {
+ switch ( *z )
+ {
+ case '-':
+ data_size += 1;
+ break;
+
+ case '=':
+ data_size += 2;
+ break;
+
+ case '_':
+ {
+ WORD l = va_arg ( Arguments, WORD );
+ data_size += l;
+ break;
+ }
+
+ case 'b':
+ {
+ BYTE* b = va_arg ( Arguments, BYTE* );
+ *b = ResponseBuffer[data_size++];
+ break;
+ }
+
+ case 'w':
+ {
+ BYTE* b = va_arg ( Arguments, BYTE* );
+ b[1] = ResponseBuffer[data_size++];
+ b[0] = ResponseBuffer[data_size++];
+ break;
+ }
+
+ case 'd':
+ {
+ BYTE* b = va_arg ( Arguments, BYTE* );
+ b[3] = ResponseBuffer[data_size++];
+ b[2] = ResponseBuffer[data_size++];
+ b[1] = ResponseBuffer[data_size++];
+ b[0] = ResponseBuffer[data_size++];
+ break;
+ }
+
+ case 'c':
+ {
+ char* c = va_arg ( Arguments, char* );
+ WORD l = strlen( &ResponseBuffer[data_size] );
+ if ( data_size+l+1 < ReturnedDataSize ) {
+ RtlCopyMemory( c, &ResponseBuffer[data_size], l+1 );
+ }
+ data_size += l+1;
+ break;
+ }
+
+ case 'C':
+ {
+ char* c = va_arg ( Arguments, char* );
+ WORD l = va_arg ( Arguments, WORD );
+ WORD len = strlen( &ResponseBuffer[data_size] ) + 1;
+
+ if ( data_size + l < ReturnedDataSize ) {
+ RtlCopyMemory( c, &ResponseBuffer[data_size], len > l ? l :len);
+ }
+ c[l-1] = 0;
+ data_size += l;
+ break;
+
+ }
+
+ case 'P':
+ case 'p':
+ {
+ char* c = va_arg ( Arguments, char* );
+ BYTE l = ResponseBuffer[data_size++];
+ if ( data_size+l <= ReturnedDataSize ) {
+ RtlCopyMemory( c, &ResponseBuffer[data_size], l );
+ c[l] = 0;
+ }
+ data_size += l;
+
+ //
+ // Unmap Japanese special chars
+ //
+ if (*z == 'P') {
+ UnmapSpecialJapaneseChars(c, l);
+ }
+
+ break;
+ }
+
+ case 'R':
+ case 'r':
+ {
+ BYTE* b = va_arg ( Arguments, BYTE* );
+ WORD l = va_arg ( Arguments, WORD );
+ RtlCopyMemory( b, &ResponseBuffer[data_size], l );
+ data_size += l;
+
+ //
+ // Unmap Japanese special chars
+ //
+ if (*z == 'R') {
+ UnmapSpecialJapaneseChars(b, l);
+ }
+ break;
+ }
+
+ case 'W':
+ {
+ BYTE* b = va_arg ( Arguments, BYTE* );
+ BYTE* w = va_arg ( Arguments, BYTE* );
+ WORD i;
+
+ b[1] = ResponseBuffer[data_size++];
+ b[0] = ResponseBuffer[data_size++];
+
+ for ( i = 0; i < ((WORD) *b); i++, w += sizeof(WORD) )
+ {
+ w[1] = ResponseBuffer[data_size++];
+ w[0] = ResponseBuffer[data_size++];
+ }
+ break;
+ }
+
+ default:
+ KdPrint(("NWLIB: NwlibMakeNcp invalid response field, %x\n", *z));
+ ASSERT(FALSE);
+ }
+
+ if ( data_size > ReturnedDataSize )
+ {
+ KdPrint(("NWLIB: NwlibMakeNcp not enough response data\n"));
+ status = STATUS_UNSUCCESSFUL;
+ goto CleanExit;
+ }
+
+ z++;
+ }
+
+ status = STATUS_SUCCESS;
+
+CleanExit:
+ if (RequestBuffer != NULL) {
+ (void) LocalFree((HLOCAL) RequestBuffer);
+ }
+
+ va_end( Arguments );
+
+ return status;
+}
+
diff --git a/private/nw/nwlib/makefile b/private/nw/nwlib/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/nw/nwlib/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/nw/nwlib/ndsapi32.c b/private/nw/nwlib/ndsapi32.c
new file mode 100644
index 000000000..9efe22830
--- /dev/null
+++ b/private/nw/nwlib/ndsapi32.c
@@ -0,0 +1,2144 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ NdsLib32.c
+
+Abstract:
+
+ This module implements the exposed user-mode link to
+ Netware NDS support in the Netware redirector. For
+ more comments, see ndslib32.h.
+
+Author:
+
+ Cory West [CoryWest] 23-Feb-1995
+
+--*/
+
+#include <procs.h>
+
+NTSTATUS
+NwNdsOpenTreeHandle(
+ IN PUNICODE_STRING puNdsTree,
+ OUT PHANDLE phNwRdrHandle
+) {
+
+ NTSTATUS ntstatus, OpenStatus;
+ IO_STATUS_BLOCK IoStatusBlock;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ACCESS_MASK DesiredAccess = SYNCHRONIZE | FILE_LIST_DIRECTORY;
+
+ WCHAR DevicePreamble[] = L"\\Device\\Nwrdr\\";
+ UINT PreambleLength = 14;
+
+ WCHAR NameStr[128];
+ UNICODE_STRING uOpenName;
+ UINT i;
+
+ PNWR_NDS_REQUEST_PACKET Rrp;
+ BYTE RrpData[1024];
+
+ //
+ // Prepare the open name.
+ //
+
+ uOpenName.MaximumLength = sizeof( NameStr );
+
+ for ( i = 0; i < PreambleLength ; i++ )
+ NameStr[i] = DevicePreamble[i];
+
+ try {
+
+ for ( i = 0 ; i < ( puNdsTree->Length / sizeof( WCHAR ) ) ; i++ ) {
+ NameStr[i + PreambleLength] = puNdsTree->Buffer[i];
+ }
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return STATUS_INVALID_PARAMETER;
+
+ }
+
+ uOpenName.Length = ( i * sizeof( WCHAR ) ) +
+ ( PreambleLength * sizeof( WCHAR ) );
+ uOpenName.Buffer = NameStr;
+
+ //
+ // Set up the object attributes.
+ //
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &uOpenName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ ntstatus = NtOpenFile(
+ phNwRdrHandle,
+ DesiredAccess,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_VALID_FLAGS,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ );
+
+ if ( !NT_SUCCESS(ntstatus) )
+ return ntstatus;
+
+ OpenStatus = IoStatusBlock.Status;
+
+ //
+ // Verify that this is a tree handle, not a server handle.
+ //
+
+ Rrp = (PNWR_NDS_REQUEST_PACKET)RrpData;
+
+ Rrp->Version = 0;
+
+ RtlCopyMemory( &(Rrp->Parameters).VerifyTree,
+ puNdsTree,
+ sizeof( UNICODE_STRING ) );
+
+ RtlCopyMemory( (BYTE *)(&(Rrp->Parameters).VerifyTree) + sizeof( UNICODE_STRING ),
+ puNdsTree->Buffer,
+ puNdsTree->Length );
+
+ try {
+
+ ntstatus = NtFsControlFile( *phNwRdrHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_VERIFY_TREE,
+ (PVOID) Rrp,
+ sizeof( NWR_NDS_REQUEST_PACKET ),
+ NULL,
+ 0 );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+ ntstatus = GetExceptionCode();
+ goto CloseAndExit;
+ }
+
+ if ( !NT_SUCCESS( ntstatus )) {
+ goto CloseAndExit;
+ }
+
+ //
+ // Otherwise, all is well!
+ //
+
+ return OpenStatus;
+
+CloseAndExit:
+
+ NtClose( *phNwRdrHandle );
+ *phNwRdrHandle = NULL;
+
+ return ntstatus;
+}
+
+NTSTATUS
+NwNdsOpenGenericHandle(
+ IN PUNICODE_STRING puNdsTree,
+ OUT LPDWORD lpdwHandleType,
+ OUT PHANDLE phNwRdrHandle
+) {
+
+ NTSTATUS ntstatus, OpenStatus;
+ IO_STATUS_BLOCK IoStatusBlock;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ACCESS_MASK DesiredAccess = SYNCHRONIZE | FILE_LIST_DIRECTORY;
+
+ WCHAR DevicePreamble[] = L"\\Device\\Nwrdr\\";
+ UINT PreambleLength = 14;
+
+ WCHAR NameStr[128];
+ UNICODE_STRING uOpenName;
+ UINT i;
+
+ PNWR_NDS_REQUEST_PACKET Rrp;
+ BYTE RrpData[1024];
+
+ //
+ // Prepare the open name.
+ //
+
+ uOpenName.MaximumLength = sizeof( NameStr );
+
+ for ( i = 0; i < PreambleLength ; i++ )
+ NameStr[i] = DevicePreamble[i];
+
+ try {
+
+ for ( i = 0 ; i < ( puNdsTree->Length / sizeof( WCHAR ) ) ; i++ ) {
+ NameStr[i + PreambleLength] = puNdsTree->Buffer[i];
+ }
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return STATUS_INVALID_PARAMETER;
+
+ }
+
+ uOpenName.Length = ( i * sizeof( WCHAR ) ) +
+ ( PreambleLength * sizeof( WCHAR ) );
+ uOpenName.Buffer = NameStr;
+
+ //
+ // Set up the object attributes.
+ //
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &uOpenName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ ntstatus = NtOpenFile(
+ phNwRdrHandle,
+ DesiredAccess,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_VALID_FLAGS,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ );
+
+ if ( !NT_SUCCESS(ntstatus) )
+ return ntstatus;
+
+ OpenStatus = IoStatusBlock.Status;
+
+ //
+ // Verify that this is a tree handle, not a server handle.
+ //
+
+ Rrp = (PNWR_NDS_REQUEST_PACKET)RrpData;
+
+ Rrp->Version = 0;
+
+ RtlCopyMemory( &(Rrp->Parameters).VerifyTree,
+ puNdsTree,
+ sizeof( UNICODE_STRING ) );
+
+ RtlCopyMemory( (BYTE *)(&(Rrp->Parameters).VerifyTree) + sizeof( UNICODE_STRING ),
+ puNdsTree->Buffer,
+ puNdsTree->Length );
+
+ try {
+
+ ntstatus = NtFsControlFile( *phNwRdrHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_VERIFY_TREE,
+ (PVOID) Rrp,
+ sizeof( NWR_NDS_REQUEST_PACKET ),
+ NULL,
+ 0 );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+ ntstatus = GetExceptionCode();
+ goto CloseAndExit2;
+ }
+
+ if ( !NT_SUCCESS( ntstatus ))
+ {
+ *lpdwHandleType = HANDLE_TYPE_NCP_SERVER;
+ }
+ else
+ {
+ *lpdwHandleType = HANDLE_TYPE_NDS_TREE;
+ }
+
+ return OpenStatus;
+
+CloseAndExit2:
+
+ NtClose( *phNwRdrHandle );
+ *phNwRdrHandle = NULL;
+
+ return ntstatus;
+}
+
+NTSTATUS
+NwOpenHandleWithSupplementalCredentials(
+ IN PUNICODE_STRING puResourceName,
+ IN PUNICODE_STRING puUserName,
+ IN PUNICODE_STRING puPassword,
+ OUT LPDWORD lpdwHandleType,
+ OUT PHANDLE phNwHandle
+) {
+
+ NTSTATUS ntstatus, OpenStatus;
+ IO_STATUS_BLOCK IoStatusBlock;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ACCESS_MASK DesiredAccess = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
+
+ WCHAR DevicePreamble[] = L"\\Device\\Nwrdr\\";
+ UINT PreambleLength = 14;
+
+ WCHAR NameStr[128];
+ UNICODE_STRING uOpenName;
+ UINT i;
+
+ PFILE_FULL_EA_INFORMATION pEaEntry;
+ PBYTE EaBuffer;
+ ULONG EaLength, EaNameLength, EaTotalLength;
+ ULONG UserNameLen, PasswordLen, TypeLen, CredLen;
+
+ PNWR_NDS_REQUEST_PACKET Rrp;
+ BYTE RrpData[1024];
+
+ //
+ // Prepare the open name.
+ //
+
+ uOpenName.MaximumLength = sizeof( NameStr );
+
+ for ( i = 0; i < PreambleLength ; i++ )
+ NameStr[i] = DevicePreamble[i];
+
+ try {
+
+ for ( i = 0 ; i < ( puResourceName->Length / sizeof( WCHAR ) ) ; i++ ) {
+ NameStr[i + PreambleLength] = puResourceName->Buffer[i];
+ }
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return STATUS_INVALID_PARAMETER;
+
+ }
+
+ uOpenName.Length = ( i * sizeof( WCHAR ) ) +
+ ( PreambleLength * sizeof( WCHAR ) );
+ uOpenName.Buffer = NameStr;
+
+ //
+ // Set up the object attributes.
+ //
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &uOpenName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ //
+ // Allocate the EA buffer - be a little generous.
+ //
+
+ UserNameLen = strlen( EA_NAME_USERNAME );
+ PasswordLen = strlen( EA_NAME_PASSWORD );
+ TypeLen = strlen( EA_NAME_TYPE );
+ CredLen = strlen( EA_NAME_CREDENTIAL_EX );
+
+ EaLength = 4 * sizeof( FILE_FULL_EA_INFORMATION );
+ EaLength += 4 * sizeof( ULONG );
+ EaLength += ROUNDUP4( UserNameLen );
+ EaLength += ROUNDUP4( PasswordLen );
+ EaLength += ROUNDUP4( TypeLen );
+ EaLength += ROUNDUP4( CredLen );
+ EaLength += ROUNDUP4( puUserName->Length );
+ EaLength += ROUNDUP4( puPassword->Length );
+
+ EaBuffer = LocalAlloc( LMEM_ZEROINIT, EaLength );
+
+ if ( !EaBuffer ) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Pack in the first EA: UserName.
+ //
+
+ pEaEntry = (PFILE_FULL_EA_INFORMATION) EaBuffer;
+
+ EaNameLength = UserNameLen + sizeof( CHAR );
+
+ pEaEntry->EaNameLength = (UCHAR) EaNameLength;
+ pEaEntry->EaValueLength = puUserName->Length;
+
+ RtlCopyMemory( &(pEaEntry->EaName[0]),
+ EA_NAME_USERNAME,
+ EaNameLength );
+
+ EaNameLength = ROUNDUP2( EaNameLength + sizeof( CHAR ) );
+
+ RtlCopyMemory( &(pEaEntry->EaName[EaNameLength]),
+ puUserName->Buffer,
+ puUserName->Length );
+
+ EaLength = ( 2 * sizeof( DWORD ) ) +
+ EaNameLength +
+ puUserName->Length;
+
+ EaLength = ROUNDUP4( EaLength );
+
+ EaTotalLength = EaLength;
+
+ pEaEntry->NextEntryOffset = EaLength;
+
+ //
+ // Pack in the second EA: Password.
+ //
+
+ pEaEntry = (PFILE_FULL_EA_INFORMATION)
+ ( ( (PBYTE)pEaEntry ) + pEaEntry->NextEntryOffset );
+
+ EaNameLength = PasswordLen + sizeof( CHAR );
+
+ pEaEntry->EaNameLength = (UCHAR) EaNameLength;
+ pEaEntry->EaValueLength = puPassword->Length;
+
+ RtlCopyMemory( &(pEaEntry->EaName[0]),
+ EA_NAME_PASSWORD,
+ EaNameLength );
+
+ EaNameLength = ROUNDUP2( EaNameLength + sizeof( CHAR ) );
+
+ RtlCopyMemory( &(pEaEntry->EaName[EaNameLength]),
+ puPassword->Buffer,
+ puPassword->Length );
+
+ EaLength = ( 2 * sizeof( DWORD ) ) +
+ EaNameLength +
+ puPassword->Length;
+
+ EaLength = ROUNDUP4( EaLength );
+
+ EaTotalLength += EaLength;
+
+ pEaEntry->NextEntryOffset = EaLength;
+
+ //
+ // Pack in the third EA: Type.
+ //
+
+ pEaEntry = (PFILE_FULL_EA_INFORMATION)
+ ( ( (PBYTE)pEaEntry ) + pEaEntry->NextEntryOffset );
+
+ EaNameLength = TypeLen + sizeof( CHAR );
+
+ pEaEntry->EaNameLength = (UCHAR) EaNameLength;
+ pEaEntry->EaValueLength = sizeof( ULONG );
+
+ RtlCopyMemory( &(pEaEntry->EaName[0]),
+ EA_NAME_TYPE,
+ EaNameLength );
+
+ EaNameLength = ROUNDUP2( EaNameLength + sizeof( CHAR ) );
+
+ EaLength = ( 2 * sizeof( DWORD ) ) +
+ EaNameLength +
+ sizeof( ULONG );
+
+ EaLength = ROUNDUP4( EaLength );
+
+ EaTotalLength += EaLength;
+
+ pEaEntry->NextEntryOffset = EaLength;
+
+ //
+ // Pack in the fourth EA: the CredentialEx flag.
+ //
+
+ pEaEntry = (PFILE_FULL_EA_INFORMATION)
+ ( ( (PBYTE)pEaEntry ) + pEaEntry->NextEntryOffset );
+
+ EaNameLength = CredLen + sizeof( CHAR );
+
+ pEaEntry->EaNameLength = (UCHAR) EaNameLength;
+ pEaEntry->EaValueLength = sizeof( ULONG );
+
+ RtlCopyMemory( &(pEaEntry->EaName[0]),
+ EA_NAME_CREDENTIAL_EX,
+ EaNameLength );
+
+ EaNameLength = ROUNDUP2( EaNameLength + sizeof( CHAR ) );
+
+ EaLength = ( 2 * sizeof( DWORD ) ) +
+ EaNameLength +
+ sizeof( ULONG );
+
+ EaLength = ROUNDUP4( EaLength );
+ EaTotalLength += EaLength;
+
+ pEaEntry->NextEntryOffset = 0;
+
+ //
+ // Do the open.
+ //
+
+ ntstatus = NtCreateFile( phNwHandle, // File handle (OUT)
+ DesiredAccess, // Access mask
+ &ObjectAttributes, // Object attributes
+ &IoStatusBlock, // Io status
+ NULL, // Optional Allocation size
+ FILE_ATTRIBUTE_NORMAL, // File attributes
+ FILE_SHARE_VALID_FLAGS, // File share access
+ FILE_OPEN, // Create disposition
+ 0, // Create options
+ (PVOID) EaBuffer, // Our EA buffer
+ EaTotalLength ); // Ea buffer length
+
+ LocalFree( EaBuffer );
+
+ if ( !NT_SUCCESS(ntstatus) )
+ return ntstatus;
+
+ OpenStatus = IoStatusBlock.Status;
+
+ //
+ // Check the handle type.
+ //
+
+ Rrp = (PNWR_NDS_REQUEST_PACKET)RrpData;
+
+ Rrp->Version = 0;
+
+ RtlCopyMemory( &(Rrp->Parameters).VerifyTree,
+ puResourceName,
+ sizeof( UNICODE_STRING ) );
+
+ RtlCopyMemory( (BYTE *)(&(Rrp->Parameters).VerifyTree) + sizeof( UNICODE_STRING ),
+ puResourceName->Buffer,
+ puResourceName->Length );
+
+ try {
+
+ ntstatus = NtFsControlFile( *phNwHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_VERIFY_TREE,
+ (PVOID) Rrp,
+ sizeof( NWR_NDS_REQUEST_PACKET ),
+ NULL,
+ 0 );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+ ntstatus = GetExceptionCode();
+ goto CloseAndExit2;
+ }
+
+ if ( !NT_SUCCESS( ntstatus ))
+ {
+ *lpdwHandleType = HANDLE_TYPE_NCP_SERVER;
+ }
+ else
+ {
+ *lpdwHandleType = HANDLE_TYPE_NDS_TREE;
+ }
+
+ return OpenStatus;
+
+CloseAndExit2:
+
+ NtClose( *phNwHandle );
+ *phNwHandle = NULL;
+
+ return ntstatus;
+}
+
+NTSTATUS
+NwNdsSetTreeContext (
+ IN HANDLE hNdsRdr,
+ IN PUNICODE_STRING puTree,
+ IN PUNICODE_STRING puContext
+)
+/*+++
+
+ This sets the current context in the requested tree.
+
+---*/
+{
+
+ NTSTATUS ntstatus;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ PNWR_NDS_REQUEST_PACKET Rrp;
+ DWORD RrpSize;
+ BYTE *CurrentString;
+
+ //
+ // Set up the request.
+ //
+
+ RrpSize = sizeof( NWR_NDS_REQUEST_PACKET ) +
+ puTree->Length +
+ puContext->Length;
+
+ Rrp = LocalAlloc( LMEM_ZEROINIT, RrpSize );
+
+ if ( !Rrp ) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ try {
+
+ (Rrp->Parameters).SetContext.TreeNameLen = puTree->Length;
+ (Rrp->Parameters).SetContext.ContextLen = puContext->Length;
+
+ CurrentString = (BYTE *)(Rrp->Parameters).SetContext.TreeAndContextString;
+
+ RtlCopyMemory( CurrentString, puTree->Buffer, puTree->Length );
+ CurrentString += puTree->Length;
+ RtlCopyMemory( CurrentString, puContext->Buffer, puContext->Length );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ ntstatus = STATUS_INVALID_PARAMETER;
+ goto ExitWithCleanup;
+ }
+
+ try {
+
+ ntstatus = NtFsControlFile( hNdsRdr,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_SETCONTEXT,
+ (PVOID) Rrp,
+ RrpSize,
+ NULL,
+ 0 );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ ntstatus = GetExceptionCode();
+ goto ExitWithCleanup;
+ }
+
+ExitWithCleanup:
+
+ LocalFree( Rrp );
+ return ntstatus;
+}
+
+NTSTATUS
+NwNdsGetTreeContext (
+ IN HANDLE hNdsRdr,
+ IN PUNICODE_STRING puTree,
+ OUT PUNICODE_STRING puContext
+)
+/*+++
+
+ This gets the current context of the requested tree.
+
+---*/
+{
+
+ NTSTATUS ntstatus;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ PNWR_NDS_REQUEST_PACKET Rrp;
+ DWORD RrpSize;
+
+ //
+ // Set up the request.
+ //
+
+ RrpSize = sizeof( NWR_NDS_REQUEST_PACKET ) + puTree->Length;
+
+ Rrp = LocalAlloc( LMEM_ZEROINIT, RrpSize );
+
+ if ( !Rrp ) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ try {
+
+ (Rrp->Parameters).GetContext.TreeNameLen = puTree->Length;
+
+ RtlCopyMemory( (BYTE *)(Rrp->Parameters).GetContext.TreeNameString,
+ puTree->Buffer,
+ puTree->Length );
+
+ (Rrp->Parameters).GetContext.Context.MaximumLength = puContext->MaximumLength;
+ (Rrp->Parameters).GetContext.Context.Length = 0;
+ (Rrp->Parameters).GetContext.Context.Buffer = puContext->Buffer;
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ ntstatus = STATUS_INVALID_PARAMETER;
+ goto ExitWithCleanup;
+ }
+
+ try {
+
+ ntstatus = NtFsControlFile( hNdsRdr,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_GETCONTEXT,
+ (PVOID) Rrp,
+ RrpSize,
+ NULL,
+ 0 );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ ntstatus = GetExceptionCode();
+ goto ExitWithCleanup;
+ }
+
+ //
+ // Copy out the length; the buffer has already been written.
+ //
+
+ puContext->Length = (Rrp->Parameters).GetContext.Context.Length;
+
+ExitWithCleanup:
+
+ LocalFree( Rrp );
+ return ntstatus;
+}
+
+NTSTATUS
+NwNdsResolveName (
+ IN HANDLE hNdsTree,
+ IN PUNICODE_STRING puObjectName,
+ OUT DWORD *dwObjectId,
+ OUT PUNICODE_STRING puReferredServer,
+ OUT PBYTE pbRawResponse,
+ IN DWORD dwResponseBufferLen
+) {
+
+ //
+ // BUGBUG: Do I want or need to expose the flags parameter?
+ //
+
+ NTSTATUS ntstatus;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ PNWR_NDS_REQUEST_PACKET Rrp;
+ PNDS_RESPONSE_RESOLVE_NAME Rsp;
+ DWORD dwRspBufferLen, dwNameLen, dwPadding;
+
+ BYTE RrpData[1024];
+ BYTE RspData[256];
+
+ Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
+
+ RtlZeroMemory( Rrp, 1024 );
+
+ //
+ // NW NDS strings are null terminated, so we make sure we
+ // report the correct length...
+ //
+
+ dwNameLen = puObjectName->Length + sizeof( WCHAR );
+
+ Rrp->Version = 0;
+ Rrp->Parameters.ResolveName.ObjectNameLength = ROUNDUP4( dwNameLen );
+ Rrp->Parameters.ResolveName.ResolverFlags = RSLV_DEREF_ALIASES |
+ RSLV_WALK_TREE |
+ RSLV_WRITABLE;
+
+ try {
+
+ //
+ // But don't try to copy more than the user gave us.
+ //
+
+ memcpy( Rrp->Parameters.ResolveName.ObjectName,
+ puObjectName->Buffer,
+ puObjectName->Length );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Send the request to the Redirector FSD.
+ //
+
+ if ( dwResponseBufferLen != 0 &&
+ pbRawResponse != NULL ) {
+
+ Rsp = ( PNDS_RESPONSE_RESOLVE_NAME ) pbRawResponse;
+ dwRspBufferLen = dwResponseBufferLen;
+
+ } else {
+
+ Rsp = ( PNDS_RESPONSE_RESOLVE_NAME ) RspData;
+ dwRspBufferLen = 256;
+
+ }
+
+ try {
+
+ ntstatus = NtFsControlFile( hNdsTree,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_RESOLVE_NAME,
+ (PVOID) Rrp,
+ sizeof( NWR_NDS_REQUEST_PACKET ),
+ (PVOID) Rsp,
+ dwRspBufferLen );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return GetExceptionCode();
+ }
+
+ //
+ // Dig out the object id and referred server.
+ //
+
+ if ( NT_SUCCESS( ntstatus ) ) {
+
+ try {
+
+ *dwObjectId = Rsp->EntryId;
+
+ if ( Rsp->ServerNameLength > puReferredServer->MaximumLength ) {
+
+ ntstatus = STATUS_BUFFER_TOO_SMALL;
+
+ } else {
+
+ RtlCopyMemory( puReferredServer->Buffer,
+ Rsp->ReferredServer,
+ Rsp->ServerNameLength );
+
+ puReferredServer->Length = (USHORT)Rsp->ServerNameLength;
+
+ }
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return ntstatus;
+
+ }
+
+ }
+
+ return ntstatus;
+
+}
+
+NTSTATUS
+NwNdsList (
+ IN HANDLE hNdsTree,
+ IN DWORD dwObjectId,
+ OUT DWORD *dwIterHandle,
+ OUT BYTE *pbReplyBuf,
+ IN DWORD dwReplyBufLen
+) {
+
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ PNWR_NDS_REQUEST_PACKET Rrp;
+
+ PNDS_RESPONSE_SUBORDINATE_LIST Rsp;
+ DWORD dwRspBufferLen;
+
+ BYTE RrpData[256];
+ BYTE RspData[1024];
+
+ //
+ // BUGBUG: I should make the reply buffer small and start testing
+ // fragment assembly stuff.
+ //
+
+ Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
+
+ Rrp->Parameters.ListSubordinates.ObjectId = dwObjectId;
+ Rrp->Parameters.ListSubordinates.IterHandle = *dwIterHandle;
+
+ if ( dwReplyBufLen != 0 &&
+ pbReplyBuf != NULL ) {
+
+ Rsp = ( PNDS_RESPONSE_SUBORDINATE_LIST ) pbReplyBuf;
+ dwRspBufferLen = dwReplyBufLen;
+
+ } else {
+
+ Rsp = ( PNDS_RESPONSE_SUBORDINATE_LIST ) RspData;
+ dwRspBufferLen = 1024;
+
+ }
+
+ try {
+
+ Status = NtFsControlFile( hNdsTree,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_LIST_SUBS,
+ (PVOID) Rrp,
+ sizeof( NWR_NDS_REQUEST_PACKET ),
+ (PVOID) Rsp,
+ dwRspBufferLen );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return GetExceptionCode();
+ }
+
+ return Status;
+
+}
+
+NTSTATUS
+NwNdsReadObjectInfo(
+ IN HANDLE hNdsTree,
+ IN DWORD dwObjectId,
+ OUT BYTE *pbRawReply,
+ IN DWORD dwReplyBufLen
+)
+{
+
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ PNWR_NDS_REQUEST_PACKET Rrp;
+
+ PNDS_RESPONSE_GET_OBJECT_INFO Rsp;
+ DWORD dwRspBufferLen;
+
+ BYTE RrpData[256];
+ BYTE RspData[1024];
+
+ Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
+
+ Rrp->Parameters.GetObjectInfo.ObjectId = dwObjectId;
+
+ if ( dwReplyBufLen != 0 &&
+ pbRawReply != NULL ) {
+
+ Rsp = ( PNDS_RESPONSE_GET_OBJECT_INFO ) pbRawReply;
+ dwRspBufferLen = dwReplyBufLen;
+
+ } else {
+
+ Rsp = ( PNDS_RESPONSE_GET_OBJECT_INFO ) RspData;
+ dwRspBufferLen = 1024;
+
+ }
+
+ try {
+
+ Status = NtFsControlFile( hNdsTree,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_READ_INFO,
+ (PVOID) Rrp,
+ sizeof( NWR_NDS_REQUEST_PACKET ),
+ (PVOID) Rsp,
+ dwRspBufferLen );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return GetExceptionCode();
+ }
+
+ return Status;
+
+}
+
+NTSTATUS
+NwNdsReadAttribute (
+ IN HANDLE hNdsTree,
+ IN DWORD dwObjectId,
+ IN DWORD *dwIterHandle,
+ IN PUNICODE_STRING puAttrName,
+ OUT BYTE *pbReplyBuf,
+ IN DWORD dwReplyBufLen
+) {
+
+ NTSTATUS ntstatus;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ PNWR_NDS_REQUEST_PACKET Rrp;
+ PNDS_RESPONSE_READ_ATTRIBUTE Rsp;
+
+ DWORD dwAttributeNameLen;
+
+ BYTE RrpData[1024];
+
+ //
+ // Check the incoming buffer.
+ //
+ if ( !dwReplyBufLen ||
+ !pbReplyBuf ) {
+
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Set up the request.
+ //
+
+ Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
+ RtlZeroMemory( Rrp, 1024 );
+
+ (Rrp->Parameters).ReadAttribute.ObjectId = dwObjectId;
+ (Rrp->Parameters).ReadAttribute.IterHandle = *dwIterHandle;
+
+ //
+ // Nds strings are NULL terminated; watch the size.
+ //
+
+ dwAttributeNameLen = puAttrName->Length + sizeof( WCHAR );
+
+ (Rrp->Parameters).ReadAttribute.AttributeNameLength = dwAttributeNameLen;
+
+ try {
+
+ //
+ // But don't try to copy more than the user gave us.
+ //
+
+ memcpy( (Rrp->Parameters).ReadAttribute.AttributeName,
+ puAttrName->Buffer,
+ puAttrName->Length );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Send the request to the Redirector FSD.
+ //
+
+ try {
+
+ ntstatus = NtFsControlFile( hNdsTree,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_READ_ATTR,
+ (PVOID) Rrp,
+ sizeof( NWR_NDS_REQUEST_PACKET ),
+ (PVOID) pbReplyBuf,
+ dwReplyBufLen );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return GetExceptionCode();
+ }
+
+ //
+ // There's no buffer post processing on this one.
+ //
+
+ return ntstatus;
+
+}
+
+NTSTATUS
+NwNdsOpenStream (
+ IN HANDLE hNdsTree,
+ IN DWORD dwObjectId,
+ IN PUNICODE_STRING puStreamName,
+ IN DWORD dwOpenFlags,
+ OUT DWORD *pdwFileLength
+) {
+
+ NTSTATUS ntstatus;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ PNWR_NDS_REQUEST_PACKET Rrp;
+ BYTE RrpData[1024];
+
+ //
+ // Set up the request.
+ //
+
+ Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
+ RtlZeroMemory( Rrp, 1024 );
+
+ (Rrp->Parameters).OpenStream.StreamAccess = dwOpenFlags;
+ (Rrp->Parameters).OpenStream.ObjectOid = dwObjectId;
+
+ (Rrp->Parameters).OpenStream.StreamName.Length = puStreamName->Length;
+ (Rrp->Parameters).OpenStream.StreamName.MaximumLength =
+ sizeof( RrpData ) - sizeof( (Rrp->Parameters).OpenStream );
+ (Rrp->Parameters).OpenStream.StreamName.Buffer =
+ (Rrp->Parameters).OpenStream.StreamNameString;
+
+ //
+ // Make sure we're not trashing memory.
+ //
+
+ if ( (Rrp->Parameters).OpenStream.StreamName.Length >
+ (Rrp->Parameters).OpenStream.StreamName.MaximumLength ) {
+
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ try {
+
+ //
+ // But don't try to copy more than the user gave us.
+ //
+
+ memcpy( (Rrp->Parameters).OpenStream.StreamNameString,
+ puStreamName->Buffer,
+ puStreamName->Length );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Send the request to the Redirector FSD.
+ //
+
+ try {
+
+ ntstatus = NtFsControlFile( hNdsTree,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_OPEN_STREAM,
+ (PVOID) Rrp,
+ sizeof( NWR_NDS_REQUEST_PACKET ),
+ NULL,
+ 0 );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return GetExceptionCode();
+ }
+
+ if ( pdwFileLength ) {
+ *pdwFileLength = (Rrp->Parameters).OpenStream.FileLength;
+ }
+
+ return ntstatus;
+}
+
+NTSTATUS
+NwNdsGetQueueInformation(
+ IN HANDLE hNdsTree,
+ IN PUNICODE_STRING puQueueName,
+ OUT PUNICODE_STRING puHostServer,
+ OUT PDWORD pdwQueueId
+) {
+
+ NTSTATUS ntstatus;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ PNWR_NDS_REQUEST_PACKET Rrp;
+ BYTE RrpData[1024];
+
+ //
+ // Set up the request.
+ //
+
+ Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
+ RtlZeroMemory( Rrp, sizeof( RrpData ) );
+
+ if ( puQueueName ) {
+ (Rrp->Parameters).GetQueueInfo.QueueName.Length = puQueueName->Length;
+ (Rrp->Parameters).GetQueueInfo.QueueName.MaximumLength = puQueueName->MaximumLength;
+ (Rrp->Parameters).GetQueueInfo.QueueName.Buffer = puQueueName->Buffer;
+ }
+
+ if ( puHostServer ) {
+ (Rrp->Parameters).GetQueueInfo.HostServer.Length = 0;
+ (Rrp->Parameters).GetQueueInfo.HostServer.MaximumLength = puHostServer->MaximumLength;
+ (Rrp->Parameters).GetQueueInfo.HostServer.Buffer = puHostServer->Buffer;
+ }
+
+ //
+ // Send the request to the Redirector FSD.
+ //
+
+ try {
+
+ ntstatus = NtFsControlFile( hNdsTree,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_GET_QUEUE_INFO,
+ (PVOID) Rrp,
+ sizeof( NWR_NDS_REQUEST_PACKET ),
+ NULL,
+ 0 );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return GetExceptionCode();
+ }
+
+ if ( NT_SUCCESS( ntstatus ) ) {
+
+ if ( pdwQueueId ) {
+ *pdwQueueId = (Rrp->Parameters).GetQueueInfo.QueueId;
+ }
+
+ puHostServer->Length = (Rrp->Parameters).GetQueueInfo.HostServer.Length;
+
+ }
+
+ return ntstatus;
+}
+
+NTSTATUS
+NwNdsGetVolumeInformation(
+ IN HANDLE hNdsTree,
+ IN PUNICODE_STRING puVolumeName,
+ OUT PUNICODE_STRING puHostServer,
+ OUT PUNICODE_STRING puHostVolume
+) {
+
+ NTSTATUS ntstatus;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ PNWR_NDS_REQUEST_PACKET Rrp;
+ DWORD RequestSize;
+ BYTE RrpData[1024];
+ BYTE ReplyData[1024];
+ PBYTE NameStr;
+
+ //
+ // Set up the request.
+ //
+
+ Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
+ RtlZeroMemory( Rrp, sizeof( RrpData ) );
+
+ if ( !puVolumeName ||
+ puVolumeName->Length > MAX_NDS_NAME_SIZE ||
+ !puHostServer ||
+ !puHostVolume ) {
+
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ try {
+
+ (Rrp->Parameters).GetVolumeInfo.VolumeNameLen = puVolumeName->Length;
+ RtlCopyMemory( &((Rrp->Parameters).GetVolumeInfo.VolumeName[0]),
+ puVolumeName->Buffer,
+ puVolumeName->Length );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Send the request to the Redirector FSD.
+ //
+
+ RequestSize = sizeof( NWR_NDS_REQUEST_PACKET ) +
+ (Rrp->Parameters).GetVolumeInfo.VolumeNameLen;
+
+ try {
+
+ ntstatus = NtFsControlFile( hNdsTree,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_GET_VOLUME_INFO,
+ (PVOID) Rrp,
+ RequestSize,
+ ReplyData,
+ sizeof( ReplyData ) );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return GetExceptionCode();
+ }
+
+ if ( NT_SUCCESS( ntstatus ) ) {
+
+ try {
+
+ if ( ( puHostServer->MaximumLength < (Rrp->Parameters).GetVolumeInfo.ServerNameLen ) ||
+ ( puHostVolume->MaximumLength < (Rrp->Parameters).GetVolumeInfo.TargetVolNameLen ) ) {
+
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ puHostServer->Length = (USHORT)(Rrp->Parameters).GetVolumeInfo.ServerNameLen;
+ puHostVolume->Length = (USHORT)(Rrp->Parameters).GetVolumeInfo.TargetVolNameLen;
+
+ NameStr = &ReplyData[0];
+
+ RtlCopyMemory( puHostServer->Buffer, NameStr, puHostServer->Length );
+ NameStr += puHostServer->Length;
+ RtlCopyMemory( puHostVolume->Buffer, NameStr, puHostVolume->Length );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ }
+
+ return ntstatus;
+
+}
+
+//
+// User mode fragment exchange.
+//
+
+int
+_cdecl
+FormatBuf(
+ char *buf,
+ int bufLen,
+ const char *format,
+ va_list args
+);
+
+NTSTATUS
+_cdecl
+FragExWithWait(
+ IN HANDLE hNdsServer,
+ IN DWORD NdsVerb,
+ IN BYTE *pReplyBuffer,
+ IN DWORD pReplyBufferLen,
+ IN OUT DWORD *pdwReplyLen,
+ IN BYTE *NdsRequestStr,
+ ...
+)
+/*
+
+Routine Description:
+
+ Exchanges an NDS request in fragments and collects the fragments
+ of the response and writes them to the reply buffer.
+
+Routine Arguments:
+
+ hNdsServer - A handle to the server you want to talk to.
+ NdsVerb - The verb for that indicates the request.
+
+ pReplyBuffer - The reply buffer.
+ pReplyBufferLen - The length of the reply buffer.
+
+ NdsReqestStr - The format string for the arguments to this NDS request.
+ Arguments - The arguments that satisfy the NDS format string.
+
+Return Value:
+
+ NTSTATUS - Status of the exchange, but not the result code in the packet.
+
+*/
+{
+
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ PNWR_NDS_REQUEST_PACKET RawRequest;
+
+ BYTE *NdsRequestBuf;
+ DWORD NdsRequestLen;
+
+ va_list Arguments;
+
+ //
+ // Allocate a request buffer.
+ //
+
+ RawRequest = LocalAlloc( LMEM_ZEROINIT, NDS_BUFFER_SIZE );
+
+ if ( !RawRequest ) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Build the request in our local buffer. The first DWORD
+ // is the verb and the rest is the formatted request.
+ //
+
+ RawRequest->Parameters.RawRequest.NdsVerb = NdsVerb;
+ NdsRequestBuf = &RawRequest->Parameters.RawRequest.Request[0];
+
+ if ( NdsRequestStr != NULL ) {
+
+ va_start( Arguments, NdsRequestStr );
+
+ NdsRequestLen = FormatBuf( NdsRequestBuf,
+ NDS_BUFFER_SIZE - sizeof( NWR_NDS_REQUEST_PACKET ),
+ NdsRequestStr,
+ Arguments );
+
+ if ( !NdsRequestLen ) {
+
+ Status = STATUS_INVALID_PARAMETER;
+ goto ExitWithCleanup;
+
+ }
+
+ va_end( Arguments );
+
+ } else {
+
+ NdsRequestLen = 0;
+ }
+
+ RawRequest->Parameters.RawRequest.RequestLength = NdsRequestLen;
+
+ //
+ // Pass this buffer to kernel mode via FSCTL.
+ //
+
+ try {
+
+ Status = NtFsControlFile( hNdsServer,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_RAW_FRAGEX,
+ (PVOID) RawRequest,
+ NdsRequestLen + sizeof( NWR_NDS_REQUEST_PACKET ),
+ (PVOID) pReplyBuffer,
+ pReplyBufferLen );
+
+ if ( NT_SUCCESS( Status ) ) {
+ *pdwReplyLen = RawRequest->Parameters.RawRequest.ReplyLength;
+ }
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ Status = GetExceptionCode();
+ }
+
+ExitWithCleanup:
+
+ if ( RawRequest ) {
+ LocalFree( RawRequest );
+ }
+
+ return Status;
+
+}
+
+int
+_cdecl
+FormatBuf(
+ char *buf,
+ int bufLen,
+ const char *format,
+ va_list args
+)
+/*
+
+Routine Description:
+
+ Formats a buffer according to supplied the format string.
+
+ 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* )
+ 'W' lo-hi word ( word / word*)
+ 'D' lo-hi dword ( dword / dword*)
+ '-' zero/skip byte ( void )
+ '=' zero/skip word ( void )
+ ._. zero/skip string ( word )
+ 'p' pstring ( char* )
+ 'c' cstring ( char* )
+ 'C' cstring followed skip word ( char*, word )
+ 'V' sized NDS value ( byte *, dword / byte **, dword *)
+ 'S' p unicode string copy as NDS_STRING (UNICODE_STRING *)
+ 's' cstring copy as NDS_STRING (char* / char *, word)
+ 'r' raw bytes ( byte*, word )
+ 'u' p unicode string ( UNICODE_STRING * )
+ 'U' p uppercase string( UNICODE_STRING * )
+
+Routine Arguments:
+
+ char *buf - destination buffer.
+ int buflen - length of the destination buffer.
+ char *format - format string.
+ args - args to the format string.
+
+Implementation Notes:
+
+ This comes verbatim from kernel mode.
+
+*/
+{
+ ULONG ix;
+
+ NTSTATUS status;
+ const char *z = format;
+
+ //
+ // Convert the input arguments into request packet.
+ //
+
+ ix = 0;
+
+ while ( *z )
+ {
+ switch ( *z )
+ {
+ case '=':
+ buf[ix++] = 0;
+ case '-':
+ buf[ix++] = 0;
+ break;
+
+ case '_':
+ {
+ WORD l = va_arg ( args, WORD );
+ if (ix + (ULONG)l > (ULONG)bufLen)
+ {
+ goto ErrorExit;
+ }
+ while ( l-- )
+ buf[ix++] = 0;
+ break;
+ }
+
+ case 'b':
+ buf[ix++] = va_arg ( args, BYTE );
+ break;
+
+ case 'w':
+ {
+ WORD w = va_arg ( args, WORD );
+ buf[ix++] = (BYTE) (w >> 8);
+ buf[ix++] = (BYTE) (w >> 0);
+ break;
+ }
+
+ case 'd':
+ {
+ DWORD d = va_arg ( args, DWORD );
+ buf[ix++] = (BYTE) (d >> 24);
+ buf[ix++] = (BYTE) (d >> 16);
+ buf[ix++] = (BYTE) (d >> 8);
+ buf[ix++] = (BYTE) (d >> 0);
+ break;
+ }
+
+ case 'W':
+ {
+ WORD w = va_arg(args, WORD);
+ (* (WORD *)&buf[ix]) = w;
+ ix += 2;
+ break;
+ }
+
+ case 'D':
+ {
+ DWORD d = va_arg (args, DWORD);
+ (* (DWORD *)&buf[ix]) = d;
+ ix += 4;
+ break;
+ }
+
+ case 'c':
+ {
+ char* c = va_arg ( args, char* );
+ WORD l = strlen( c );
+ if (ix + (ULONG)l > (ULONG)bufLen)
+ {
+ goto ErrorExit;
+ }
+ RtlCopyMemory( &buf[ix], c, l+1 );
+ ix += l + 1;
+ break;
+ }
+
+ case 'C':
+ {
+ char* c = va_arg ( args, char* );
+ WORD l = va_arg ( args, WORD );
+ WORD len = strlen( c ) + 1;
+ if (ix + (ULONG)l > (ULONG)bufLen)
+ {
+ goto ErrorExit;
+ }
+
+ RtlCopyMemory( &buf[ix], c, len > l? l : len);
+ ix += l;
+ buf[ix-1] = 0;
+ break;
+ }
+
+ case 'p':
+ {
+ char* c = va_arg ( args, char* );
+ BYTE l = strlen( c );
+ if (ix + (ULONG)l +1 > (ULONG)bufLen)
+ {
+ goto ErrorExit;
+ }
+ buf[ix++] = l;
+ RtlCopyMemory( &buf[ix], c, l );
+ ix += l;
+ break;
+ }
+
+ case 'u':
+ {
+ PUNICODE_STRING pUString = va_arg ( args, PUNICODE_STRING );
+ OEM_STRING OemString;
+ ULONG Length;
+
+ //
+ // Calculate required string length, excluding trailing NUL.
+ //
+
+ Length = RtlUnicodeStringToOemSize( pUString ) - 1;
+ ASSERT( Length < 0x100 );
+
+ if ( ix + Length > (ULONG)bufLen ) {
+ goto ErrorExit;
+ }
+
+ buf[ix++] = (UCHAR)Length;
+ OemString.Buffer = &buf[ix];
+ OemString.MaximumLength = (USHORT)Length + 1;
+
+ status = RtlUnicodeStringToOemString( &OemString, pUString, FALSE );
+ ASSERT( NT_SUCCESS( status ));
+ ix += (USHORT)Length;
+ break;
+ }
+
+ case 'S':
+ {
+ PUNICODE_STRING pUString = va_arg (args, PUNICODE_STRING);
+ ULONG Length, rLength;
+
+ Length = pUString->Length;
+ if (ix + Length + sizeof(Length) + sizeof( WCHAR ) > (ULONG)bufLen) {
+ goto ErrorExit;
+ }
+
+ //
+ // The VLM client uses the rounded up length and it seems to
+ // make a difference! Also, don't forget that NDS strings have
+ // to be NULL terminated.
+ //
+
+ rLength = ROUNDUP4(Length + sizeof( WCHAR ));
+ *((DWORD *)&buf[ix]) = rLength;
+ ix += 4;
+ RtlCopyMemory(&buf[ix], pUString->Buffer, Length);
+ ix += Length;
+ rLength -= Length;
+ RtlFillMemory( &buf[ix], rLength, '\0' );
+ ix += rLength;
+ break;
+
+ }
+
+ case 's':
+ {
+ PUNICODE_STRING pUString = va_arg (args, PUNICODE_STRING);
+ ULONG Length, rLength;
+
+ Length = pUString->Length;
+ if (ix + Length + sizeof(Length) + sizeof( WCHAR ) > (ULONG)bufLen) {
+ // DebugTrace( 0, Dbg, "FormatBuf: case 's' request buffer too small.\n", 0 );
+ goto ErrorExit;
+ }
+
+ //
+ // Don't use the padded size here, only the NDS null terminator.
+ //
+
+ rLength = Length + sizeof( WCHAR );
+ *((DWORD *)&buf[ix]) = rLength;
+ ix += 4;
+ RtlCopyMemory(&buf[ix], pUString->Buffer, Length);
+ ix += Length;
+ rLength -= Length;
+ RtlFillMemory( &buf[ix], rLength, '\0' );
+ ix += rLength;
+ break;
+
+
+ }
+
+ case 'V':
+ {
+ // too similar to 'S' - should be combined
+ BYTE* b = va_arg ( args, BYTE* );
+ DWORD l = va_arg ( args, DWORD );
+ if ( ix + l + sizeof(DWORD) > (ULONG)
+ bufLen )
+ {
+ goto ErrorExit;
+ }
+ *((DWORD *)&buf[ix]) = l;
+ ix += sizeof(DWORD);
+ RtlCopyMemory( &buf[ix], b, l );
+ l = ROUNDUP4(l);
+ ix += l;
+ break;
+ }
+
+ case 'r':
+ {
+ BYTE* b = va_arg ( args, BYTE* );
+ WORD l = va_arg ( args, WORD );
+ if ( b == NULL || l == 0 )
+ {
+ break;
+ }
+ if ( ix + l > (ULONG)bufLen )
+ {
+ goto ErrorExit;
+ }
+ RtlCopyMemory( &buf[ix], b, l );
+ ix += l;
+ break;
+ }
+
+ default:
+
+ ;
+
+ }
+
+ if ( ix > (ULONG)bufLen )
+ {
+ goto ErrorExit;
+ }
+
+
+ z++;
+ }
+
+ return(ix);
+
+ErrorExit:
+ return 0;
+}
+
+NTSTATUS
+_cdecl
+ParseResponse(
+ PUCHAR Response,
+ ULONG ResponseLength,
+ char* FormatString,
+ ... // format specific parameters
+ )
+/*++
+
+Routine Description:
+
+ This routine parse an NCP response.
+
+ Packet types:
+
+ 'G' Generic packet ( )
+
+ Field types, request/response:
+
+ 'b' byte ( byte* )
+ 'w' hi-lo word ( word* )
+ 'x' ordered word ( word* )
+ 'd' hi-lo dword ( dword* )
+ 'e' ordered dword ( dword* )
+ '-' zero/skip byte ( void )
+ '=' zero/skip word ( void )
+ ._. zero/skip string ( word )
+ 'p' pstring ( char* )
+ 'c' cstring ( char* )
+ 'r' raw bytes ( byte*, word )
+
+ Added 3/29/95 by CoryWest:
+
+ 'W' lo-hi word ( word / word*)
+ 'D' lo-hi dword ( dword / dword*)
+ 'S' unicode string copy as NDS_STRING (UNICODE_STRING *)
+ 'T' terminal unicode string copy as NDS_STRING (UNICODE_STRING *)
+
+ 't' terminal unicode string with the nds null copied
+ as NDS_STRING (UNICODE_STRING *) (for GetUseName)
+
+Return Value:
+
+ STATUS - Success or failure, depending on the response.
+
+--*/
+
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PCHAR FormatByte;
+ va_list Arguments;
+ ULONG Length = 0;
+
+ va_start( Arguments, FormatString );
+
+ //
+ // User mode parse response handles only generic packets.
+ //
+
+ if ( *FormatString != 'G' ) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ FormatByte = FormatString + 1;
+ while ( *FormatByte ) {
+
+ switch ( *FormatByte ) {
+
+ case '-':
+ Length += 1;
+ break;
+
+ case '=':
+ Length += 2;
+ break;
+
+ case '_':
+ {
+ WORD l = va_arg ( Arguments, WORD );
+ Length += l;
+ break;
+ }
+
+ case 'b':
+ {
+ BYTE* b = va_arg ( Arguments, BYTE* );
+ *b = Response[Length++];
+ break;
+ }
+
+ case 'w':
+ {
+ BYTE* b = va_arg ( Arguments, BYTE* );
+ b[1] = Response[Length++];
+ b[0] = Response[Length++];
+ break;
+ }
+
+ case 'x':
+ {
+ WORD* w = va_arg ( Arguments, WORD* );
+ *w = *(WORD UNALIGNED *)&Response[Length];
+ Length += 2;
+ break;
+ }
+
+ case 'd':
+ {
+ BYTE* b = va_arg ( Arguments, BYTE* );
+ b[3] = Response[Length++];
+ b[2] = Response[Length++];
+ b[1] = Response[Length++];
+ b[0] = Response[Length++];
+ break;
+ }
+
+ case 'e':
+ {
+ DWORD UNALIGNED * d = va_arg ( Arguments, DWORD* );
+ *d = *(DWORD UNALIGNED *)&Response[Length];
+ Length += 4;
+ break;
+ }
+
+ case 'c':
+ {
+ char* c = va_arg ( Arguments, char* );
+ WORD l = strlen( &Response[Length] );
+ memcpy ( c, &Response[Length], l+1 );
+ Length += l+1;
+ break;
+ }
+
+ case 'p':
+ {
+ char* c = va_arg ( Arguments, char* );
+ BYTE l = Response[Length++];
+ memcpy ( c, &Response[Length], l );
+ c[l+1] = 0;
+ break;
+ }
+
+ case 'r':
+ {
+ BYTE* b = va_arg ( Arguments, BYTE* );
+ WORD l = va_arg ( Arguments, WORD );
+ RtlCopyMemory( b, &Response[Length], l );
+ Length += l;
+ break;
+ }
+
+ case 'W':
+ {
+
+ WORD *w = va_arg ( Arguments, WORD* );
+ *w = (* (WORD *)&Response[Length]);
+ Length += 2;
+ break;
+
+ }
+
+ case 'D':
+ {
+
+ DWORD *d = va_arg ( Arguments, DWORD* );
+ *d = (* (DWORD *)&Response[Length]);
+ Length += 4;
+ break;
+
+ }
+
+ case 'S':
+ {
+
+ PUNICODE_STRING pU = va_arg( Arguments, PUNICODE_STRING );
+ USHORT strl;
+
+ if (pU) {
+
+ strl = (USHORT)(* (DWORD *)&Response[Length]);
+
+ //
+ // Don't count the null terminator that is part of
+ // Novell's counted unicode string.
+ //
+
+ pU->Length = strl - sizeof( WCHAR );
+ Length += 4;
+ RtlCopyMemory( pU->Buffer, &Response[Length], pU->Length );
+ Length += ROUNDUP4(strl);
+
+ } else {
+
+ //
+ // Skip over the string since we don't want it.
+ //
+
+ Length += ROUNDUP4((* (DWORD *)&Response[Length] ));
+ Length += 4;
+ }
+
+
+ break;
+
+ }
+
+ case 's':
+ {
+
+ PUNICODE_STRING pU = va_arg( Arguments, PUNICODE_STRING );
+ USHORT strl;
+
+ if (pU) {
+
+ strl = (USHORT)(* (DWORD *)&Response[Length]);
+ pU->Length = strl;
+ Length += 4;
+ RtlCopyMemory( pU->Buffer, &Response[Length], pU->Length );
+ Length += ROUNDUP4(strl);
+
+ } else {
+
+ //
+ // Skip over the string since we don't want it.
+ //
+
+ Length += ROUNDUP4((* (DWORD *)&Response[Length] ));
+ Length += 4;
+ }
+
+
+ break;
+
+ }
+
+ case 'T':
+ {
+
+ PUNICODE_STRING pU = va_arg( Arguments, PUNICODE_STRING );
+ USHORT strl;
+
+ if (pU) {
+
+ strl = (USHORT)(* (DWORD *)&Response[Length] );
+ strl -= sizeof( WCHAR ); // Don't count the NULL from NDS.
+
+ if ( strl <= pU->MaximumLength ) {
+
+ pU->Length = strl;
+ Length += 4;
+ RtlCopyMemory( pU->Buffer, &Response[Length], pU->Length );
+
+ //
+ // No need to advance the pointers since this is
+ // specifically a termination case!
+ //
+
+ } else {
+
+ pU->Length = 0;
+ }
+
+ }
+
+ break;
+
+ }
+
+ case 't':
+ {
+
+ PUNICODE_STRING pU = va_arg( Arguments, PUNICODE_STRING );
+ USHORT strl;
+
+ if (pU) {
+
+ strl = (USHORT)(* (DWORD *)&Response[Length] );
+
+ if ( strl <= pU->MaximumLength ) {
+
+ pU->Length = strl;
+ Length += 4;
+ RtlCopyMemory( pU->Buffer, &Response[Length], pU->Length );
+
+ //
+ // No need to advance the pointers since this is
+ // specifically a termination case!
+ //
+
+ } else {
+
+ pU->Length = 0;
+
+ }
+
+ }
+
+ break;
+
+ }
+
+ }
+
+ if ( Length > ResponseLength ) {
+ return( STATUS_INVALID_PARAMETER );
+ }
+
+ FormatByte++;
+
+ }
+
+ va_end( Arguments );
+ return( Status );
+
+}
+
+NTSTATUS
+NwNdsChangePassword(
+ IN HANDLE hNwRdr,
+ IN PUNICODE_STRING puTreeName,
+ IN PUNICODE_STRING puUserName,
+ IN PUNICODE_STRING puCurrentPassword,
+ IN PUNICODE_STRING puNewPassword
+) {
+
+ NTSTATUS Status;
+ PNWR_NDS_REQUEST_PACKET pNdsRequest;
+ DWORD dwRequestLength;
+ PBYTE CurrentString;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ //
+ // Allocate the request.
+ //
+
+ dwRequestLength = sizeof( NWR_NDS_REQUEST_PACKET ) +
+ puTreeName->Length +
+ puUserName->Length +
+ puCurrentPassword->Length +
+ puNewPassword->Length;
+
+ pNdsRequest = LocalAlloc( LMEM_ZEROINIT, dwRequestLength );
+
+ if ( !pNdsRequest) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Copy the parameters into the request buffer.
+ //
+
+ try {
+
+ (pNdsRequest->Parameters).ChangePass.NdsTreeNameLength =
+ puTreeName->Length;
+ (pNdsRequest->Parameters).ChangePass.UserNameLength =
+ puUserName->Length;
+ (pNdsRequest->Parameters).ChangePass.CurrentPasswordLength =
+ puCurrentPassword->Length;
+ (pNdsRequest->Parameters).ChangePass.NewPasswordLength =
+ puNewPassword->Length;
+
+ CurrentString = ( PBYTE ) &((pNdsRequest->Parameters).ChangePass.StringBuffer[0]);
+ RtlCopyMemory( CurrentString, puTreeName->Buffer, puTreeName->Length );
+
+ CurrentString += puTreeName->Length;
+ RtlCopyMemory( CurrentString, puUserName->Buffer, puUserName->Length );
+
+ CurrentString += puUserName->Length;
+ RtlCopyMemory( CurrentString, puCurrentPassword->Buffer, puCurrentPassword->Length );
+
+ CurrentString += puCurrentPassword->Length;
+ RtlCopyMemory( CurrentString, puNewPassword->Buffer, puNewPassword->Length );
+
+ Status = NtFsControlFile( hNwRdr,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_NDS_CHANGE_PASS,
+ (PVOID) pNdsRequest,
+ dwRequestLength,
+ NULL,
+ 0 );
+
+ } except ( EXCEPTION_EXECUTE_HANDLER ) {
+
+ Status = STATUS_INVALID_PARAMETER;
+ }
+
+ LocalFree( pNdsRequest );
+ return Status;
+
+}
+
+
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;
+}
diff --git a/private/nw/nwlib/nwcapi32.c b/private/nw/nwlib/nwcapi32.c
new file mode 100644
index 000000000..0fd0b4bb1
--- /dev/null
+++ b/private/nw/nwlib/nwcapi32.c
@@ -0,0 +1,798 @@
+/*++
+
+Copyright (C) 1993 Microsoft Corporation
+
+Module Name:
+
+ NWAPI32.C
+
+Abstract:
+
+ This module contains NetWare compatible APIs. The NWC* functions
+ are implemented as wrappers around NWP* or NW* functions.
+
+Author:
+
+ Chuck Y. Chan (ChuckC) 06-Mar-1995
+
+Revision History:
+
+ ChuckC Moved over from DSM to consolidate.
+
+--*/
+
+#include "procs.h"
+
+//
+// define define categories of errors
+//
+typedef enum _NCP_CLASS {
+ NcpClassConnect,
+ NcpClassBindery,
+ NcpClassDir
+} NCP_CLASS ;
+
+extern NWCCODE
+MapNtStatus(
+ const NTSTATUS ntstatus,
+ const NCP_CLASS ncpclass
+);
+
+extern DWORD
+SetWin32ErrorFromNtStatus(
+ NTSTATUS NtStatus
+) ;
+
+
+//
+// Function bodies
+//
+
+
+NWCCODE
+NWCAddTrusteeToDirectory(
+ NWCONN_HANDLE hConn,
+ NWDIR_HANDLE dirHandle,
+ const char *pszPath,
+ NWOBJ_ID dwTrusteeID,
+ NWACCESS_RIGHTS rightsMask
+ )
+{
+ return (NWAddTrusteeToDirectory(
+ hConn,
+ dirHandle,
+ pszPath,
+ dwTrusteeID,
+ rightsMask)) ;
+}
+
+NWCCODE
+NWCAllocPermanentDirectoryHandle(
+ NWCONN_HANDLE hConn,
+ NWDIR_HANDLE dirHandle,
+ char *pszDirPath,
+ NWDIR_HANDLE *pbNewDirHandle,
+ NWACCESS_RIGHTS *pbRightsMask
+ )
+{
+ return (NWAllocPermanentDirectoryHandle(
+ hConn,
+ dirHandle,
+ pszDirPath,
+ pbNewDirHandle,
+ pbRightsMask)) ;
+}
+
+NWCCODE
+NWCAllocTemporaryDirectoryHandle(
+ NWCONN_HANDLE hConn,
+ NWDIR_HANDLE dirHandle,
+ char *pszDirPath,
+ NWDIR_HANDLE *pbNewDirHandle,
+ NWACCESS_RIGHTS *pbRightsMask
+ )
+{
+ return (NWAllocTemporaryDirectoryHandle(
+ hConn,
+ dirHandle,
+ pszDirPath,
+ pbNewDirHandle,
+ pbRightsMask)) ;
+}
+
+NWCCODE
+NWCAttachToFileServer(
+ const char *pszServerName,
+ NWLOCAL_SCOPE ScopeFlag,
+ NWCONN_HANDLE *phNewConn
+ )
+{
+ return (NWAttachToFileServer(
+ pszServerName,
+ ScopeFlag,
+ phNewConn)) ;
+}
+
+NWCCODE
+NWCAttachToFileServerW(
+ const WCHAR *pszServerName,
+ NWLOCAL_SCOPE ScopeFlag,
+ NWCONN_HANDLE *phNewConn
+ )
+{
+ return (NWAttachToFileServerW(
+ pszServerName,
+ ScopeFlag,
+ phNewConn)) ;
+}
+
+NWCCODE
+NWCCheckConsolePrivileges(
+ NWCONN_HANDLE hConn
+ )
+{
+ return(NWCheckConsolePrivileges(hConn));
+}
+
+NWCCODE
+NWCDeallocateDirectoryHandle(
+ NWCONN_HANDLE hConn,
+ NWDIR_HANDLE dirHandle
+ )
+{
+ return(NWDeallocateDirectoryHandle(
+ hConn,
+ dirHandle)) ;
+}
+
+NWCCODE
+NWCDetachFromFileServer(
+ NWCONN_HANDLE hConn
+ )
+{
+ return(NWDetachFromFileServer(hConn)) ;
+}
+
+NWCCODE
+NWCGetFileServerVersionInfo(
+ NWCONN_HANDLE hConn,
+ VERSION_INFO *lpVerInfo
+ )
+{
+ return(NWGetFileServerVersionInfo(
+ hConn,
+ lpVerInfo)) ;
+}
+
+NWCCODE
+NWCGetInternetAddress(
+ NWCONN_HANDLE hConn,
+ NWCONN_NUM nConnNum,
+ NWNET_ADDR *pIntAddr
+ )
+{
+ return (NWGetInternetAddress(
+ hConn,
+ nConnNum,
+ pIntAddr)) ;
+}
+
+NWCCODE
+NWCGetObjectName(
+ NWCONN_HANDLE hConn,
+ NWOBJ_ID dwObjectID,
+ char *pszObjName,
+ NWOBJ_TYPE *pwObjType )
+{
+ return(NWGetObjectName(
+ hConn,
+ dwObjectID,
+ pszObjName,
+ pwObjType )) ;
+}
+
+
+NWCCODE
+NWCGetVolumeInfoWithNumber(
+ NWCONN_HANDLE hConn,
+ NWVOL_NUM nVolNum,
+ char *pszVolName,
+ NWNUMBER *pwTotalBlocks,
+ NWNUMBER *pwSectors,
+ NWNUMBER *pwAvailBlocks,
+ NWNUMBER *pwTotalDir,
+ NWNUMBER *pwAvailDir,
+ NWVOL_FLAGS *pfVolRemovable
+ )
+{
+ return(NWGetVolumeInfoWithNumber(
+ hConn,
+ nVolNum,
+ pszVolName,
+ pwTotalBlocks,
+ pwSectors,
+ pwAvailBlocks,
+ pwTotalDir,
+ pwAvailDir,
+ pfVolRemovable)) ;
+}
+
+NWCCODE
+NWCGetVolumeInfoWithHandle(
+ NWCONN_HANDLE hConn,
+ NWDIR_HANDLE nDirHand,
+ char *pszVolName,
+ NWNUMBER *pwTotalBlocks,
+ NWNUMBER *pwSectors,
+ NWNUMBER *pwAvailBlocks,
+ NWNUMBER *pwTotalDir,
+ NWNUMBER *pwAvailDir,
+ NWVOL_FLAGS *pfVolRemovable
+ )
+{
+ return(NWGetVolumeInfoWithHandle(
+ hConn,
+ nDirHand,
+ pszVolName,
+ pwTotalBlocks,
+ pwSectors,
+ pwAvailBlocks,
+ pwTotalDir,
+ pwAvailDir,
+ pfVolRemovable)) ;
+}
+
+NWCCODE
+NWCGetVolumeName(
+ NWCONN_HANDLE hConn,
+ NWVOL_NUM bVolNum,
+ char *pszVolName
+ )
+{
+ return(NWGetVolumeName(
+ hConn,
+ bVolNum,
+ pszVolName)) ;
+}
+
+NWCCODE
+NWCIsObjectInSet(
+ NWCONN_HANDLE hConn,
+ const char *lpszObjectName,
+ NWOBJ_TYPE wObjType,
+ const char *lpszPropertyName,
+ const char *lpszMemberName,
+ NWOBJ_TYPE wMemberType
+ )
+{
+ return(NWIsObjectInSet(
+ hConn,
+ lpszObjectName,
+ wObjType,
+ lpszPropertyName,
+ lpszMemberName,
+ wMemberType)) ;
+}
+
+
+NWCCODE
+NWCLoginToFileServer(
+ NWCONN_HANDLE hConn,
+ const char *pszUserName,
+ NWOBJ_TYPE wObjType,
+ const char *pszPassword
+ )
+{
+ return(NWLoginToFileServer(
+ hConn,
+ pszUserName,
+ wObjType,
+ pszPassword)) ;
+}
+
+NWCCODE
+NWCLogoutFromFileServer(
+ NWCONN_HANDLE hConn
+ )
+{
+ return(NWLogoutFromFileServer( hConn )) ;
+}
+
+NWCCODE
+NWCReadPropertyValue(
+ NWCONN_HANDLE hConn,
+ const char *pszObjName,
+ NWOBJ_TYPE wObjType,
+ char *pszPropName,
+ unsigned char ucSegment,
+ char *pValue,
+ NWFLAGS *pucMoreFlag,
+ NWFLAGS *pucPropFlag
+ )
+{
+ return(NWReadPropertyValue(
+ hConn,
+ pszObjName,
+ wObjType,
+ pszPropName,
+ ucSegment,
+ pValue,
+ pucMoreFlag,
+ pucPropFlag)) ;
+}
+
+NWCCODE
+NWCScanObject(
+ NWCONN_HANDLE hConn,
+ const char *pszSearchName,
+ NWOBJ_TYPE wObjSearchType,
+ NWOBJ_ID *pdwObjectID,
+ char *pszObjectName,
+ NWOBJ_TYPE *pwObjType,
+ NWFLAGS *pucHasProperties,
+ NWFLAGS *pucObjectFlags,
+ NWFLAGS *pucObjSecurity
+ )
+{
+ return(NWScanObject(
+ hConn,
+ pszSearchName,
+ wObjSearchType,
+ pdwObjectID,
+ pszObjectName,
+ pwObjType,
+ pucHasProperties,
+ pucObjectFlags,
+ pucObjSecurity)) ;
+}
+
+NWCCODE
+NWCScanProperty(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ char *pszSearchName,
+ NWOBJ_ID *pdwSequence,
+ char *pszPropName,
+ NWFLAGS *pucPropFlags,
+ NWFLAGS *pucPropSecurity,
+ NWFLAGS *pucHasValue,
+ NWFLAGS *pucMore
+ )
+{
+ return( NWScanProperty(
+ hConn,
+ pszObjectName,
+ wObjType,
+ pszSearchName,
+ pdwSequence,
+ pszPropName,
+ pucPropFlags,
+ pucPropSecurity,
+ pucHasValue,
+ pucMore)) ;
+}
+
+NWCCODE
+NWCGetFileServerDateAndTime(
+ NWCONN_HANDLE hConn,
+ BYTE *year,
+ BYTE *month,
+ BYTE *day,
+ BYTE *hour,
+ BYTE *minute,
+ BYTE *second,
+ BYTE *dayofweek
+ )
+{
+ return( NWGetFileServerDateAndTime(
+ hConn,
+ year,
+ month,
+ day,
+ hour,
+ minute,
+ second,
+ dayofweek ));
+}
+
+
+NWCCODE
+NWCAddTrustee(
+ NWCONN_HANDLE hConn,
+ NWDIR_HANDLE dirHandle,
+ const char *pszPath,
+ NWOBJ_ID dwTrusteeID,
+ NWRIGHTS_MASK rightsMask
+ )
+{
+ NTSTATUS NtStatus;
+
+ NtStatus = NWPAddTrustee(
+ hConn,
+ dirHandle,
+ pszPath,
+ dwTrusteeID,
+ rightsMask
+ );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassDir );
+}
+
+NWCCODE
+NWCDeleteObject(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType
+ )
+{
+ NTSTATUS NtStatus;
+
+ NtStatus = NWPDeleteObject( hConn,
+ pszObjectName,
+ wObjType );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+NWCCODE
+NWCCreateObject(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ NWFLAGS ucObjectFlags,
+ NWFLAGS ucObjSecurity
+ )
+{
+ NTSTATUS NtStatus ;
+
+ NtStatus = NWPCreateObject( hConn,
+ pszObjectName,
+ wObjType,
+ ucObjectFlags,
+ ucObjSecurity );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+NWCCODE
+NWCCreateProperty(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ const char *pszPropertyName,
+ NWFLAGS ucObjectFlags,
+ NWFLAGS ucObjSecurity
+ )
+{
+ NTSTATUS NtStatus ;
+
+ NtStatus = NWPCreateProperty( hConn,
+ pszObjectName,
+ wObjType,
+ pszPropertyName,
+ ucObjectFlags,
+ ucObjSecurity );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+NWCCODE
+NWCDeleteProperty(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ const char *pszPropertyName
+ )
+{
+ NTSTATUS NtStatus ;
+
+ NtStatus = NWPDeleteProperty( hConn,
+ pszObjectName,
+ wObjType,
+ pszPropertyName );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+NWCCODE
+NWCWritePropertyValue(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ const char *pszPropertyName,
+ NWSEGMENT_NUM segmentNumber,
+ NWSEGMENT_DATA *segmentData,
+ NWFLAGS moreSegments
+ )
+{
+ NTSTATUS NtStatus ;
+
+ NtStatus = NWPWritePropertyValue( hConn,
+ pszObjectName,
+ wObjType,
+ pszPropertyName,
+ segmentNumber,
+ segmentData,
+ moreSegments );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+NWCCODE
+NWCGetObjectID(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ NWOBJ_ID *objectID
+ )
+{
+ NTSTATUS NtStatus ;
+
+ NtStatus = NWPGetObjectID( hConn,
+ pszObjectName,
+ wObjType,
+ objectID );
+
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+NWCCODE
+NWCRenameBinderyObject(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ const char *pszNewObjectName,
+ NWOBJ_TYPE wObjType
+ )
+{
+ NTSTATUS NtStatus;
+
+ NtStatus = NWPRenameBinderyObject(
+ hConn,
+ pszObjectName,
+ pszNewObjectName,
+ wObjType
+ );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+NWCCODE
+NWCAddObjectToSet(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ const char *pszPropertyName,
+ const char *pszMemberName,
+ NWOBJ_TYPE memberType
+ )
+{
+ NTSTATUS NtStatus ;
+
+ NtStatus = NWPAddObjectToSet( hConn,
+ pszObjectName,
+ wObjType,
+ pszPropertyName,
+ pszMemberName,
+ memberType );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+NWCCODE
+NWCDeleteObjectFromSet(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ const char *pszPropertyName,
+ const char *pszMemberName,
+ NWOBJ_TYPE memberType
+ )
+{
+ NTSTATUS NtStatus ;
+
+ NtStatus = NWPDeleteObjectFromSet( hConn,
+ pszObjectName,
+ wObjType,
+ pszPropertyName,
+ pszMemberName,
+ memberType );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+NWCCODE
+NWCCreateDirectory(
+ NWCONN_HANDLE hConn,
+ NWDIR_HANDLE dirHandle,
+ const char *pszPath,
+ NWACCESS_RIGHTS accessMask
+ )
+{
+ NTSTATUS NtStatus;
+
+ NtStatus = NWPCreateDirectory(
+ hConn,
+ dirHandle,
+ pszPath,
+ accessMask
+ );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+
+NWCCODE
+NWCScanForTrustees(
+ NWCONN_HANDLE hConn,
+ NWDIR_HANDLE dirHandle,
+ char *pszsearchDirPath,
+ NWSEQUENCE *pucsequenceNumber,
+ BYTE *numberOfEntries,
+ TRUSTEE_INFO *ti
+ )
+{
+ NTSTATUS NtStatus;
+
+ NtStatus = NWPScanForTrustees(
+ hConn,
+ dirHandle,
+ pszsearchDirPath,
+ pucsequenceNumber,
+ numberOfEntries,
+ ti
+ ) ;
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+
+NWCCODE
+NWCScanDirectoryForTrustees2(
+ NWCONN_HANDLE hConn,
+ NWDIR_HANDLE dirHandle,
+ char *pszsearchDirPath,
+ NWSEQUENCE *pucsequenceNumber,
+ char *pszdirName,
+ NWDATE_TIME *dirDateTime,
+ NWOBJ_ID *ownerID,
+ TRUSTEE_INFO *ti
+ )
+{
+ NTSTATUS NtStatus;
+
+ NtStatus = NWPScanDirectoryForTrustees2(
+ hConn,
+ dirHandle,
+ pszsearchDirPath,
+ pucsequenceNumber,
+ pszdirName,
+ dirDateTime,
+ ownerID,
+ ti
+ );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+
+NWCCODE
+NWCGetBinderyAccessLevel(
+ NWCONN_HANDLE hConn,
+ NWFLAGS *accessLevel,
+ NWOBJ_ID *objectID
+ )
+{
+ NTSTATUS NtStatus;
+
+ NtStatus = NWPGetBinderyAccessLevel(
+ hConn,
+ accessLevel,
+ objectID
+ );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+NWCCODE
+NWCGetFileServerDescription(
+ NWCONN_HANDLE hConn,
+ char *pszCompany,
+ char *pszVersion,
+ char *pszRevision
+ )
+{
+ NTSTATUS NtStatus ;
+
+ NtStatus = NWPGetFileServerDescription(
+ hConn,
+ pszCompany,
+ pszVersion,
+ pszRevision
+ );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+NWCCODE
+NWCGetVolumeNumber(
+ NWCONN_HANDLE hConn,
+ char *pszVolume,
+ NWVOL_NUM *VolumeNumber
+ )
+{
+ NTSTATUS NtStatus ;
+
+ NtStatus = NWPGetVolumeNumber(
+ hConn,
+ pszVolume,
+ VolumeNumber
+ );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
+
+NWCCODE
+NWCGetVolumeUsage(
+ NWCONN_HANDLE hConn,
+ NWVOL_NUM VolumeNumber,
+ DWORD *TotalBlocks,
+ DWORD *FreeBlocks,
+ DWORD *PurgeableBlocks,
+ DWORD *NotYetPurgeableBlocks,
+ DWORD *TotalDirectoryEntries,
+ DWORD *AvailableDirectoryEntries,
+ BYTE *SectorsPerBlock
+ )
+{
+ NTSTATUS NtStatus ;
+
+ NtStatus = NWPGetVolumeUsage(
+ hConn,
+ VolumeNumber,
+ TotalBlocks,
+ FreeBlocks,
+ PurgeableBlocks,
+ NotYetPurgeableBlocks,
+ TotalDirectoryEntries,
+ AvailableDirectoryEntries,
+ SectorsPerBlock
+ );
+
+ (void) SetWin32ErrorFromNtStatus(NtStatus) ;
+
+ return MapNtStatus( NtStatus, NcpClassBindery );
+}
diff --git a/private/nw/nwlib/nwpapi32.c b/private/nw/nwlib/nwpapi32.c
new file mode 100644
index 000000000..030593a71
--- /dev/null
+++ b/private/nw/nwlib/nwpapi32.c
@@ -0,0 +1,1011 @@
+/*++
+
+Copyright (C) 1993 Microsoft Corporation
+
+Module Name:
+
+ NWAPI32.C
+
+Abstract:
+
+ This module contains several useful functions. Mostly wrappers.
+
+Author:
+
+ Chuck Y. Chan (ChuckC) 06-Mar-1995
+
+Revision History:
+
+--*/
+
+
+#include "procs.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 ;
+
+
+//
+// forward declare
+//
+
+extern NTSTATUS
+NwAttachToServer(
+ IN LPWSTR ServerName,
+ OUT LPHANDLE phandleServer
+ ) ;
+
+extern NTSTATUS
+NwDetachFromServer(
+ IN HANDLE handleServer
+ ) ;
+
+extern DWORD
+CancelAllConnections(
+ LPWSTR pszServer
+ ) ;
+
+extern DWORD
+szToWide(
+ LPWSTR lpszW,
+ LPCSTR lpszC,
+ INT nSize
+);
+
+
+
+NTSTATUS
+NWPAttachToFileServerW(
+ const WCHAR *pszServerName,
+ NWLOCAL_SCOPE ScopeFlag,
+ NWCONN_HANDLE *phNewConn
+ )
+{
+ NTSTATUS NtStatus;
+ 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 STATUS_INVALID_PARAMETER;
+
+ *phNewConn = NULL ;
+
+ //
+ // Allocate a buffer to store the file server name
+ //
+ nSize = wcslen(pszServerName)+3 ;
+ if(!(lpwszServerName = (LPWSTR) LocalAlloc(
+ LPTR,
+ nSize * sizeof(WCHAR) )))
+ {
+ NtStatus = STATUS_NO_MEMORY;
+ 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))) )
+ {
+ NtStatus = STATUS_NO_MEMORY;
+ goto ExitPoint ;
+ }
+ RtlInitUnicodeString(&pServerInfo->ServerString, lpwszServerName) ;
+
+ //
+ // Call createfile to get a handle for the redirector calls
+ //
+ NtStatus = NwAttachToServer( lpwszServerName, &pServerInfo->hConn );
+
+ExitPoint:
+
+ //
+ // Free the memory allocated above before exiting
+ //
+ if ( !NT_SUCCESS( NtStatus))
+ {
+ if (lpwszServerName)
+ (void) LocalFree( (HLOCAL) lpwszServerName );
+ if (pServerInfo)
+ (void) LocalFree( (HLOCAL) pServerInfo );
+ }
+ else
+ *phNewConn = (HANDLE) pServerInfo ;
+
+ return( NtStatus );
+}
+
+
+NTSTATUS
+NWPDetachFromFileServer(
+ 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 STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+NWPGetFileServerVersionInfo(
+ NWCONN_HANDLE hConn,
+ VERSION_INFO *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 );
+ return NtStatus;
+}
+
+NTSTATUS
+NWPGetObjectName(
+ NWCONN_HANDLE hConn,
+ NWOBJ_ID dwObjectID,
+ char *pszObjName,
+ NWOBJ_TYPE *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
+ );
+
+ return NtStatus;
+}
+
+DWORD
+NWPLoginToFileServerW(
+ NWCONN_HANDLE hConn,
+ LPWSTR pszUserNameW,
+ NWOBJ_TYPE wObjType,
+ LPWSTR pszPasswordW
+ )
+{
+ NETRESOURCEW NetResource;
+ DWORD dwRes;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ //
+ // validate parameters
+ //
+ if (!hConn || !pszUserNameW || !pszPasswordW)
+ return ERROR_INVALID_PARAMETER;
+
+ 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();
+
+ return( dwRes );
+}
+
+
+DWORD
+NWPLogoutFromFileServer(
+ NWCONN_HANDLE hConn
+ )
+{
+ DWORD dwRes;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ //
+ // now cancel the any connection to \\servername.
+ //
+ dwRes = NPCancelConnection( pServerInfo->ServerString.Buffer, TRUE );
+
+ if ( NO_ERROR != dwRes )
+ dwRes = GetLastError();
+
+ return dwRes;
+}
+
+
+NTSTATUS
+NWPReadPropertyValue(
+ NWCONN_HANDLE hConn,
+ const char *pszObjName,
+ NWOBJ_TYPE wObjType,
+ char *pszPropName,
+ unsigned char ucSegment,
+ char *pValue,
+ NWFLAGS *pucMoreFlag,
+ NWFLAGS *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
+ );
+
+ return NtStatus;
+}
+
+NTSTATUS
+NWPScanObject(
+ NWCONN_HANDLE hConn,
+ const char *pszSearchName,
+ NWOBJ_TYPE wObjSearchType,
+ NWOBJ_ID *pdwObjectID,
+ char *pszObjectName,
+ NWOBJ_TYPE *pwObjType,
+ NWFLAGS *pucHasProperties,
+ NWFLAGS *pucObjectFlags,
+ NWFLAGS *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
+ );
+
+ return NtStatus;
+}
+
+NTSTATUS
+NWPScanProperty(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ char *pszSearchName,
+ NWOBJ_ID *pdwSequence,
+ char *pszPropName,
+ NWFLAGS *pucPropFlags,
+ NWFLAGS *pucPropSecurity,
+ NWFLAGS *pucHasValue,
+ NWFLAGS *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
+ );
+
+ return NtStatus;
+}
+
+NTSTATUS
+NWPDeleteObject(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType
+ )
+{
+ NTSTATUS NtStatus ;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E3H, // Bindery function
+ 54, // Max request packet size
+ 2, // Max response packet size
+ "brp|", // Format string
+ // === REQUEST ================================
+ 0x33, // b Scan Prop function
+ &wObjType,W_SIZE, // r Type of Object
+ pszObjectName // p Object Name
+ // === REPLY ==================================
+ );
+
+ return NtStatus;
+}
+
+NTSTATUS
+NWPCreateObject(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ NWFLAGS ucObjectFlags,
+ NWFLAGS ucObjSecurity
+ )
+{
+ NTSTATUS NtStatus ;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E3H, // Bindery function
+ 56, // Max request packet size
+ 2, // Max response packet size
+ "bbbrp|", // Format string
+ // === REQUEST ================================
+ 0x32, // b Scan Prop function
+ ucObjectFlags, // b Object flags
+ ucObjSecurity, // b Object security
+ &wObjType,W_SIZE, // r Type of Object
+ pszObjectName // p Object Name
+ // === REPLY ==================================
+ );
+
+ return NtStatus;
+}
+
+NTSTATUS
+NWPCreateProperty(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ const char *pszPropertyName,
+ NWFLAGS ucObjectFlags,
+ NWFLAGS ucObjSecurity
+ )
+{
+ 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
+ 2, // Max response packet size
+ "brpbbp|", // Format string
+ // === REQUEST ================================
+ 0x39, // b Create Prop function
+ &wObjType,W_SIZE, // r Type of Object
+ pszObjectName, // p Object Name
+ ucObjectFlags, // b Object flags
+ ucObjSecurity, // b Object security
+ pszPropertyName // p Property Name
+ // === REPLY ==================================
+ );
+
+ return NtStatus;
+}
+
+
+NTSTATUS
+NWPDeleteProperty(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ const char *pszPropertyName
+ )
+{
+ 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
+ 2, // Max response packet size
+ "brpp|", // Format string
+ // === REQUEST ================================
+ 0x3A, // b Delete Prop function
+ &wObjType,W_SIZE, // r Type of Object
+ pszObjectName, // p Object Name
+ pszPropertyName // p Property Name
+ // === REPLY ==================================
+ );
+
+ return NtStatus;
+}
+
+
+NTSTATUS
+NWPWritePropertyValue(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ const char *pszPropertyName,
+ NWSEGMENT_NUM segmentNumber,
+ NWSEGMENT_DATA *segmentData,
+ NWFLAGS moreSegments
+ )
+{
+ NTSTATUS NtStatus ;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E3H, // Bindery function
+ 201, // Max request packet size
+ 2, // Max response packet size
+ "brpbbpr|", // Format string
+ // === REQUEST ================================
+ 0x3E, // b Write Prop function
+ &wObjType,W_SIZE, // r Type of Object
+ pszObjectName, // p Object Name
+ segmentNumber, // b Segment Number
+ moreSegments, // b Segment remaining
+ pszPropertyName, // p Property Name
+ segmentData, 128 // r Property Value Data
+ // === REPLY ==================================
+ );
+
+ return NtStatus;
+}
+
+NTSTATUS
+NWPChangeObjectPasswordEncrypted(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ BYTE *validationKey,
+ BYTE *newKeyedPassword
+ )
+{
+ NTSTATUS NtStatus ;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E3H, // Bindery function
+ strlen( pszObjectName) + 32, // Max request packet size
+ 2, // Max response packet size
+ "brrpr|", // Format string
+ // === REQUEST ================================
+ 0x4B, // b Write Prop function
+ validationKey, 8, // r Key
+ &wObjType,W_SIZE, // r Type of Object
+ pszObjectName, // p Object Name
+ newKeyedPassword, 17 // r New Keyed Password
+ // === REPLY ==================================
+ );
+
+ return NtStatus;
+}
+
+NTSTATUS
+NWPGetObjectID(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ NWOBJ_ID *objectID
+ )
+{
+ NTSTATUS NtStatus ;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E3H, // Bindery function
+ 54, // Max request packet size
+ 56, // Max response packet size
+ "brp|d", // Format string
+ // === REQUEST ================================
+ 0x35, // b Get Obj ID
+ &wObjType,W_SIZE, // r Type of Object
+ pszObjectName, // p Object Name
+ // === REPLY ==================================
+ objectID // d Object ID
+ );
+
+ *objectID = dwSWAP( *objectID );
+
+ return NtStatus;
+}
+
+
+NTSTATUS
+NWPRenameBinderyObject(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ const char *pszNewObjectName,
+ NWOBJ_TYPE wObjType
+ )
+{
+ NTSTATUS NtStatus;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E3H, // Bindery function
+ 105, // Max request packet size
+ 2, // Max response packet size
+ "brpp", // Format string
+ // === REQUEST ================================
+ 0x34, // b Rename bindery object
+ &wObjType,W_SIZE, // r Type of Object
+ pszObjectName, // p Object Name
+ pszNewObjectName // p New Object Name
+ // === REPLY ==================================
+ );
+
+ return NtStatus;
+}
+
+NTSTATUS
+NWPAddObjectToSet(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ const char *pszPropertyName,
+ const char *pszMemberName,
+ NWOBJ_TYPE memberType
+ )
+{
+ NTSTATUS NtStatus ;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ 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 ================================
+ 0x41, // b Add obj to set
+ &wObjType,W_SIZE, // r Type of Object
+ pszObjectName, // p Object Name
+ pszPropertyName, // p Property Name
+ &memberType, W_SIZE, // r Member type
+ pszMemberName // p Member Name
+ // === REPLY ==================================
+ );
+
+ return NtStatus;
+}
+
+
+NTSTATUS
+NWPDeleteObjectFromSet(
+ NWCONN_HANDLE hConn,
+ const char *pszObjectName,
+ NWOBJ_TYPE wObjType,
+ const char *pszPropertyName,
+ const char *pszMemberName,
+ NWOBJ_TYPE memberType
+ )
+{
+ NTSTATUS NtStatus ;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ 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 ================================
+ 0x42, // b Del object from set
+ &wObjType,W_SIZE, // r Type of Object
+ pszObjectName, // p Object Name
+ pszPropertyName, // p Property Name
+ &memberType, W_SIZE, // r Member type
+ pszMemberName // p Member Name
+ // === REPLY ==================================
+ );
+
+ return NtStatus;
+}
+
+NTSTATUS
+NWPGetChallengeKey(
+ NWCONN_HANDLE hConn,
+ UCHAR *challengeKey
+ )
+{
+ 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
+ 10, // Max response packet size
+ "b|r", // Format string
+ // === REQUEST ================================
+ 0x17, // b Get Challenge
+ // === REPLY ==================================
+ challengeKey, 8
+ );
+
+ return NtStatus;
+}
+
+NTSTATUS
+NWPCreateDirectory(
+ NWCONN_HANDLE hConn,
+ NWDIR_HANDLE dirHandle,
+ const char *pszPath,
+ NWACCESS_RIGHTS accessMask
+ )
+{
+ NTSTATUS NtStatus ;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E2H, // Bindery function
+ 261, // Max request packet size
+ 2, // Max response packet size
+ "bbbp|", // Format string
+ // === REQUEST ================================
+ 0xA, // b Create Directory
+ dirHandle, // b Directory Handle
+ accessMask, // b Access Mask
+ pszPath // p Property Name
+ // === REPLY ==================================
+ );
+
+ return NtStatus;
+}
+
+NTSTATUS
+NWPAddTrustee(
+ NWCONN_HANDLE hConn,
+ NWDIR_HANDLE dirHandle,
+ const char *pszPath,
+ NWOBJ_ID dwTrusteeID,
+ NWRIGHTS_MASK rightsMask
+ )
+{
+ NTSTATUS NtStatus ;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E2H, // Directory function
+ 266, // Max request packet size
+ 2, // Max response packet size
+ "bbrrp|", // Format string
+ // === REQUEST ================================
+ 0x27, // b Add trustee to directory
+ dirHandle, // b Directory handle
+ &dwTrusteeID,DW_SIZE, // r Object ID to assigned to directory
+ &rightsMask,W_SIZE, // r User rights for directory
+ pszPath // p Directory (if dirHandle = 0 then vol:directory)
+ );
+
+ return NtStatus;
+
+}
+
+
+NTSTATUS
+NWPScanForTrustees(
+ NWCONN_HANDLE hConn,
+ NWDIR_HANDLE dirHandle,
+ char *pszsearchDirPath,
+ NWSEQUENCE *pucsequenceNumber,
+ BYTE *numberOfEntries,
+ TRUSTEE_INFO *ti
+ )
+{
+ ULONG i;
+ DWORD oid[20];
+ WORD or[20];
+ NTSTATUS NtStatus ;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E2H, // Bindery function
+ 261, // Max request packet size
+ 121, // Max response packet size
+ "bbbp|brr", // Format string
+ // === REQUEST ================================
+ 0x26, // b Scan For Trustees
+ dirHandle, // b Directory Handle
+ *pucsequenceNumber, // b Sequence Number
+ pszsearchDirPath, // p Search Dir Path
+ // === REPLY ==================================
+ numberOfEntries,
+ &oid[0],DW_SIZE*20, // r trustee object ID
+ &or[0], W_SIZE*20 // b Trustee rights mask
+ );
+
+
+ for(i = 0; i < 20; i++) {
+ ti[i].objectID = oid[i];
+ ti[i].objectRights = or[i];
+ }
+
+ (*pucsequenceNumber)++;
+
+ return NtStatus ;
+
+} // NWScanForTrustees
+
+
+NTSTATUS
+NWPScanDirectoryForTrustees2(
+ NWCONN_HANDLE hConn,
+ NWDIR_HANDLE dirHandle,
+ char *pszsearchDirPath,
+ NWSEQUENCE *pucsequenceNumber,
+ char *pszdirName,
+ NWDATE_TIME *dirDateTime,
+ NWOBJ_ID *ownerID,
+ TRUSTEE_INFO *ti
+ )
+{
+ ULONG i;
+ DWORD oid[5];
+ BYTE or[5];
+ NTSTATUS NtStatus ;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ memset(oid, 0, sizeof(oid));
+ memset(or, 0, sizeof(or));
+
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E2H, // Bindery function
+ 261, // Max request packet size
+ 49, // Max response packet size
+ "bbbp|rrrrr", // Format string
+ // === REQUEST ================================
+ 0x0C, // b Scan Directory function
+ dirHandle, // b Directory Handle
+ *pucsequenceNumber, // b Sequence Number
+ pszsearchDirPath, // p Search Dir Path
+ // === REPLY ==================================
+ pszdirName,16, // r Returned Directory Name
+ dirDateTime,DW_SIZE, // r Date and Time
+ ownerID,DW_SIZE, // r Owner ID
+ &oid[0],DW_SIZE*5, // r trustee object ID
+ &or[0], 5 // b Trustee rights mask
+ );
+
+
+ for(i = 0; i < 5; i++) {
+ ti[i].objectID = oid[i];
+ ti[i].objectRights = (WORD) or[i];
+ }
+
+ (*pucsequenceNumber)++;
+
+ return NtStatus ;
+
+} // NWScanDirectoryForTrustees2
+
+
+NTSTATUS
+NWPGetBinderyAccessLevel(
+ NWCONN_HANDLE hConn,
+ NWFLAGS *accessLevel,
+ NWOBJ_ID *objectID
+ )
+{
+ 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
+ 7, // Max response packet size
+ "b|br", // Format string
+ // === REQUEST ================================
+ 0x46, // b Get Bindery Access Level
+ // === REPLY ==================================
+ accessLevel,
+ objectID,DW_SIZE
+ );
+
+
+
+ return NtStatus ;
+
+} // NWGetBinderyAccessLevel
+
+NTSTATUS
+NWPGetFileServerDescription(
+ NWCONN_HANDLE hConn,
+ char *pszCompany,
+ char *pszVersion,
+ char *pszRevision
+ )
+{
+ 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
+ 514, // Max response packet size
+ "b|ccc", // Format string
+ // === REQUEST ================================
+ 0xC9, // b Get File Server Information
+ // === REPLY ==================================
+ pszCompany, // c Company
+ pszVersion, // c Version
+ pszRevision // c Description
+ );
+
+ return NtStatus;
+}
+
+NTSTATUS
+NWPGetVolumeNumber(
+ NWCONN_HANDLE hConn,
+ char *pszVolume,
+ NWVOL_NUM *VolumeNumber
+ )
+{
+ NTSTATUS NtStatus ;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)hConn ;
+
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E2H, // Bindery function
+ 20, // Max request packet size
+ 3, // Max response packet size
+ "bp|b", // Format string
+ // === REQUEST ================================
+ 0x05, // b Get Volume Number
+ pszVolume, // p volume name
+ // === REPLY ==================================
+ VolumeNumber // b Description
+ );
+
+ return NtStatus;
+}
+
+NTSTATUS
+NWPGetVolumeUsage(
+ NWCONN_HANDLE hConn,
+ NWVOL_NUM VolumeNumber,
+ DWORD *TotalBlocks,
+ DWORD *FreeBlocks,
+ DWORD *PurgeableBlocks,
+ DWORD *NotYetPurgeableBlocks,
+ DWORD *TotalDirectoryEntries,
+ DWORD *AvailableDirectoryEntries,
+ BYTE *SectorsPerBlock
+ )
+{
+ 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
+ 46, // Max response packet size
+ "bb|dddddd==b", // Format string
+ // === REQUEST ================================
+ 0x2C, // b Get Volume Number
+ VolumeNumber, // p volume number
+ // === REPLY ==================================
+ TotalBlocks,
+ FreeBlocks,
+ PurgeableBlocks,
+ NotYetPurgeableBlocks,
+ TotalDirectoryEntries,
+ AvailableDirectoryEntries,
+ SectorsPerBlock
+ );
+
+ *TotalBlocks = dwSWAP( *TotalBlocks );
+ *FreeBlocks = dwSWAP( *FreeBlocks );
+ *PurgeableBlocks = dwSWAP( *PurgeableBlocks );
+ *NotYetPurgeableBlocks = dwSWAP( *NotYetPurgeableBlocks );
+ *TotalDirectoryEntries = dwSWAP( *TotalDirectoryEntries );
+ *AvailableDirectoryEntries = dwSWAP( *AvailableDirectoryEntries );
+
+ return NtStatus;
+}
diff --git a/private/nw/nwlib/packstr.c b/private/nw/nwlib/packstr.c
new file mode 100644
index 000000000..d66cef0e3
--- /dev/null
+++ b/private/nw/nwlib/packstr.c
@@ -0,0 +1,125 @@
+/*++
+
+Copyright (c) 1992, 1993 Microsoft Corporation
+
+Module Name:
+
+ packstr.c
+
+Abstract:
+
+ Contains functions for packing strings into buffers that also contain
+ structures.
+
+Author:
+
+ From LAN Manager netlib.
+ Rita Wong (ritaw) 2-Mar-1993
+
+Environment:
+
+ User Mode - Win32
+
+Revision History:
+
+--*/
+
+#include <procs.h>
+
+
+BOOL
+NwlibCopyStringToBuffer(
+ IN LPCWSTR SourceString OPTIONAL,
+ IN DWORD CharacterCount,
+ IN LPCWSTR FixedDataEnd,
+ IN OUT LPWSTR *EndOfVariableData,
+ OUT LPWSTR *VariableDataPointer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a single variable-length string into an output buffer.
+ The string is not written if it would overwrite the last fixed structure
+ in the buffer.
+
+Arguments:
+
+ SourceString - Supplies a pointer to the source string to copy into the
+ output buffer. If SourceString is null then a pointer to a zero terminator
+ is inserted into output buffer.
+
+ CharacterCount - Supplies the length of SourceString, not including zero
+ terminator. (This in units of characters - not bytes).
+
+ FixedDataEnd - Supplies a pointer to just after the end of the last
+ fixed structure in the buffer.
+
+ EndOfVariableData - Supplies an address to a pointer to just after the
+ last position in the output buffer that variable data can occupy.
+ Returns a pointer to the string written in the output buffer.
+
+ VariableDataPointer - Supplies a pointer to the place in the fixed
+ portion of the output buffer where a pointer to the variable data
+ should be written.
+
+Return Value:
+
+ Returns TRUE if string fits into output buffer, FALSE otherwise.
+
+--*/
+{
+ DWORD CharsNeeded = (CharacterCount + 1);
+
+
+ //
+ // Determine if source string will fit, allowing for a zero terminator.
+ // If not, just set the pointer to NULL.
+ //
+
+ if ((*EndOfVariableData - CharsNeeded) >= FixedDataEnd) {
+
+ //
+ // It fits. Move EndOfVariableData pointer up to the location where
+ // we will write the string.
+ //
+
+ *EndOfVariableData -= CharsNeeded;
+
+ //
+ // Copy the string to the buffer if it is not null.
+ //
+
+ if (CharacterCount > 0 && SourceString != NULL) {
+
+ (VOID) wcsncpy(*EndOfVariableData, SourceString, CharacterCount);
+ }
+
+ //
+ // Set the zero terminator.
+ //
+
+ *(*EndOfVariableData + CharacterCount) = L'\0';
+
+ //
+ // Set up the pointer in the fixed data portion to point to where the
+ // string is written.
+ //
+
+ *VariableDataPointer = *EndOfVariableData;
+
+ return TRUE;
+
+ }
+ else {
+
+ //
+ // It doesn't fit. Set the offset to NULL.
+ //
+
+ *VariableDataPointer = NULL;
+
+ return FALSE;
+ }
+}
diff --git a/private/nw/nwlib/procs.h b/private/nw/nwlib/procs.h
new file mode 100644
index 000000000..2cf897262
--- /dev/null
+++ b/private/nw/nwlib/procs.h
@@ -0,0 +1,55 @@
+
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ procs.c
+
+Abstract:
+
+ Common header file for routines which support 16 bit
+ applications.
+
+Author:
+
+ Colin Watson (colinw) 21-Nov-1993
+
+Environment:
+
+
+Revision History:
+
+
+--*/
+
+#define UNICODE
+
+
+#include <stdlib.h>
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <ctype.h>
+
+#include <validc.h>
+#include <nwstatus.h>
+#include <nwcanon.h>
+#include <ntddnwfs.h>
+#include <npapi.h>
+
+#include <nwxchg.h>
+#include <nwapi.h>
+#include <nwapi32.h>
+#include <nwpapi32.h>
+#include <ndsapi32.h>
+#include <nds.h>
+
+#include <debugfmt.h> // FORMAT_LPSTR
+#include <mpr.h>
+
+#include <lmcons.h>
+#include <ntsam.h>
+#include <nwpkstr.h>
diff --git a/private/nw/nwlib/regacl.c b/private/nw/nwlib/regacl.c
new file mode 100644
index 000000000..8258beae9
--- /dev/null
+++ b/private/nw/nwlib/regacl.c
@@ -0,0 +1,161 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ regacl.c
+
+Abstract:
+
+ This module contains the code for adding access permission ACL in a registry
+ key.
+
+Author:
+
+ Terrence Kwan (terryk) 25-Sept-1993
+
+Revision History:
+
+--*/
+
+#include <procs.h>
+
+DWORD
+NwLibSetEverybodyPermission(
+ IN HKEY hKey,
+ IN DWORD dwPermission
+ )
+/*++
+
+Routine Description:
+
+ Set the registry key to everybody "Set Value" (or whatever
+ the caller want.)
+
+Arguments:
+
+ hKey - The handle of the registry key to set security on
+
+ dwPermission - The permission to add to "everybody"
+
+Return Value:
+
+ The win32 error.
+
+--*/
+{
+ LONG err; // error code
+ PSECURITY_DESCRIPTOR psd = NULL; // related SD
+ PACL pDacl = NULL; // Absolute DACL
+ PACL pSacl = NULL; // Absolute SACL
+ PSID pOSid = NULL; // Absolute Owner SID
+ PSID pPSid = NULL; // Absolute Primary SID
+
+ do { // Not a loop, just for breaking out of error
+ //
+ // Initialize all the variables...
+ //
+ // world sid authority
+ SID_IDENTIFIER_AUTHORITY SidAuth= SECURITY_WORLD_SID_AUTHORITY;
+ DWORD cbSize=0; // Security key size
+ PACL pAcl; // original ACL
+ BOOL fDaclPresent;
+ BOOL fDaclDefault;
+ PSID pSid; // original SID
+ SECURITY_DESCRIPTOR absSD; // Absolute SD
+ DWORD AbsSize = sizeof(SECURITY_DESCRIPTOR); // Absolute SD size
+ DWORD DaclSize; // Absolute DACL size
+ DWORD SaclSize; // Absolute SACL size
+ DWORD OSidSize; // Absolute OSID size
+ DWORD PSidSize; // Absolute PSID size
+
+
+ // Get the original DACL list
+
+ RegGetKeySecurity( hKey, DACL_SECURITY_INFORMATION, NULL, &cbSize);
+
+ psd = (PSECURITY_DESCRIPTOR *)LocalAlloc(LMEM_ZEROINIT, cbSize+sizeof(ACCESS_ALLOWED_ACE)+sizeof(ACCESS_MASK)+sizeof(SID));
+ pDacl = (PACL)LocalAlloc(LMEM_ZEROINIT, cbSize+sizeof(ACCESS_ALLOWED_ACE)+sizeof(ACCESS_MASK)+sizeof(SID));
+ pSacl = (PACL)LocalAlloc(LMEM_ZEROINIT, cbSize);
+ pOSid = (PSID)LocalAlloc(LMEM_ZEROINIT, cbSize);
+ pPSid = (PSID)LocalAlloc(LMEM_ZEROINIT, cbSize);
+ DaclSize = cbSize+sizeof(ACCESS_ALLOWED_ACE)+sizeof(ACCESS_MASK)+sizeof(SID);
+ SaclSize = cbSize;
+ OSidSize = cbSize;
+ PSidSize = cbSize;
+
+ if (( NULL == psd) ||
+ ( NULL == pDacl) ||
+ ( NULL == pSacl) ||
+ ( NULL == pOSid) ||
+ ( NULL == pPSid))
+ {
+ err = ERROR_INSUFFICIENT_BUFFER;
+ break;
+ }
+
+ if ( (err = RegGetKeySecurity( hKey, DACL_SECURITY_INFORMATION, psd, &cbSize )) != ERROR_SUCCESS )
+ {
+ break;
+ }
+ if ( !GetSecurityDescriptorDacl( psd, &fDaclPresent, &pAcl, &fDaclDefault ))
+ {
+ err = GetLastError();
+ break;
+ }
+
+ // Increase the size for an extra ACE
+
+ pAcl->AclSize += sizeof(ACCESS_ALLOWED_ACE)+sizeof(ACCESS_MASK)+sizeof(SID);
+
+ // Get World SID
+
+ if ( (err = RtlAllocateAndInitializeSid( &SidAuth, 1,
+ SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSid)) != ERROR_SUCCESS)
+ {
+ break;
+ }
+
+ // Add Permission ACE
+
+ if ( !AddAccessAllowedAce(pAcl, ACL_REVISION, dwPermission ,pSid))
+ {
+ err = GetLastError();
+ break;
+ }
+
+ // Convert from relate format to absolute format
+
+ if ( !MakeAbsoluteSD( psd, &absSD, &AbsSize, pDacl, &DaclSize, pSacl, &SaclSize,
+ pOSid, &OSidSize, pPSid, &PSidSize ))
+ {
+ err = GetLastError();
+ break;
+ }
+
+ // Set SD
+
+ if ( !SetSecurityDescriptorDacl( &absSD, TRUE, pAcl, FALSE ))
+ {
+ err = GetLastError();
+ break;
+ }
+ if ( (err = RegSetKeySecurity( hKey, DACL_SECURITY_INFORMATION, psd ))
+ != ERROR_SUCCESS )
+ {
+ break;
+ }
+
+ } while (FALSE);
+
+ // Clean up the memory
+
+ LocalFree( psd );
+ LocalFree( pDacl );
+ LocalFree( pSacl );
+ LocalFree( pOSid );
+ LocalFree( pPSid );
+
+ return err;
+}
diff --git a/private/nw/nwlib/sources b/private/nw/nwlib/sources
new file mode 100644
index 000000000..5690351a2
--- /dev/null
+++ b/private/nw/nwlib/sources
@@ -0,0 +1,66 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=nw
+MINORCOMP=nwlib
+
+TARGETNAME=nwlib
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+INCLUDES=..\inc;$(_NTROOT)\private\inc;
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES= \
+ canon.c \
+ packstr.c \
+ exchange.c \
+ regacl.c \
+ nwapi32.c \
+ nwcapi32.c \
+ nwpapi32.c \
+ ndsapi32.c
+
+TARGETLIBS= \
+ $(BASEDIR)\Public\Sdk\Lib\*\kernel32.lib \
+ $(BASEDIR)\Public\Sdk\Lib\*\user32.lib \
+ $(BASEDIR)\Public\Sdk\Lib\*\advapi32.lib \
+ $(BASEDIR)\Public\Sdk\Lib\*\nwprovau.lib \
+ $(BASEDIR)\Public\Sdk\Lib\*\ntvdm.lib
+
+UNICODE=1
+
+NET_C_DEFINES=-DRPC_NO_WINDOWS_H -DNWDBG
+
+UMTYPE=console
+
+UMTEST=
+
+UMLIBS=
+
+OPTIONAL_UMTEST=
+
+!IFDEF MARS_PCH
+PRECOMPILED_INCLUDE=procs.h
+PRECOMPILED_PCH=procs.pch
+PRECOMPILED_OBJ=procs.obj
+!ENDIF
diff --git a/private/nw/nwlib/tpath.c b/private/nw/nwlib/tpath.c
new file mode 100644
index 000000000..831b4d5f1
--- /dev/null
+++ b/private/nw/nwlib/tpath.c
@@ -0,0 +1,238 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ tpath.c
+
+Abstract:
+
+ Test for canonicalization helpers.
+
+Author:
+
+ Rita Wong (ritaw) 22-Feb-1993
+
+Environment:
+
+ User Mode - Win32
+
+Revision History:
+
+--*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windef.h>
+#include <winbase.h>
+
+#include <nwcanon.h>
+
+#ifndef UNICODE
+#define UNICODE
+#endif
+
+DWORD
+TestCanonLocalName(
+ IN LPWSTR LocalName,
+ IN DWORD ExpectedError
+ );
+
+DWORD
+TestCanonRemoteName(
+ IN LPWSTR RemoteName,
+ IN DWORD ExpectedError
+ );
+
+// BYTE WorkBuffer[1024];
+
+void _CRTAPI1
+main(
+ void
+ )
+{
+
+
+ TestCanonLocalName(
+ L"x:",
+ NO_ERROR
+ );
+
+ TestCanonLocalName(
+ L"B:",
+ NO_ERROR
+ );
+
+ TestCanonLocalName(
+ L"prn",
+ NO_ERROR
+ );
+
+ TestCanonLocalName(
+ L"lpt1:",
+ NO_ERROR
+ );
+
+ TestCanonLocalName(
+ L"*:",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonLocalName(
+ L"B",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonLocalName(
+ L"abc",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonLocalName(
+ L"\\:",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonRemoteName(
+ L"\\:",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonRemoteName(
+ L"\\\\Ser:ver",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonRemoteName(
+ L"\\\\*",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonRemoteName(
+ L"\\\\:",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonRemoteName(
+ L"\\\\Server\\Volume",
+ NO_ERROR
+ );
+
+ TestCanonRemoteName(
+ L"\\\\Server\\Volume\\Dir1\\Directory2\\ALongDirectory3",
+ NO_ERROR
+ );
+
+ TestCanonRemoteName(
+ L"\\\\Server\\Volume\\",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonRemoteName(
+ L"Server\\Volume\\",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonRemoteName(
+ L"\\\\Server\\Volu:me",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonRemoteName(
+ L"\\\\Server\\Volume\\\\Dir",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonRemoteName(
+ L"\\\\Server/Volume\\Dir",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonRemoteName(
+ L"\\\\Server\\Volume:",
+ ERROR_INVALID_NAME
+ );
+
+ TestCanonRemoteName(
+ L"\\\\Server",
+ ERROR_INVALID_NAME
+ );
+
+}
+
+
+DWORD
+TestCanonLocalName(
+ IN LPWSTR LocalName,
+ IN DWORD ExpectedError
+ )
+{
+ DWORD status;
+ DWORD OutputBufferLength;
+ LPWSTR OutputBuffer;
+
+
+ printf("\nCanon local name %ws\n", LocalName);
+
+ status = NwLibCanonLocalName(
+ LocalName,
+ &OutputBuffer,
+ &OutputBufferLength
+ );
+
+ if (status == NO_ERROR) {
+
+ printf(" got %ws, length %lu\n", OutputBuffer, OutputBufferLength);
+
+ (void) LocalFree((HLOCAL) OutputBuffer);
+ }
+
+ if (status == ExpectedError) {
+ printf(" SUCCESS: Got %lu as expected\n", ExpectedError);
+
+ }
+ else {
+ printf(" FAILED: Got %lu, expected %lu\n", status, ExpectedError);
+ }
+}
+
+
+DWORD
+TestCanonRemoteName(
+ IN LPWSTR RemoteName,
+ IN DWORD ExpectedError
+ )
+{
+ DWORD status;
+ DWORD OutputBufferLength;
+ LPWSTR OutputBuffer;
+
+
+ printf("\nCanon remote name %ws\n", RemoteName);
+
+ status = NwLibCanonRemoteName(
+ RemoteName,
+ &OutputBuffer,
+ &OutputBufferLength
+ );
+
+ if (status == NO_ERROR) {
+
+ printf(" got %ws, length %lu\n", OutputBuffer, OutputBufferLength);
+
+ (void) LocalFree((HLOCAL) OutputBuffer);
+ }
+
+ if (status == ExpectedError) {
+ printf(" SUCCESS: Got %lu as expected\n", ExpectedError);
+
+ }
+ else {
+ printf(" FAILED: Got %lu, expected %lu\n", status, ExpectedError);
+ }
+}