diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/nw/nwlib | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/nw/nwlib')
-rw-r--r-- | private/nw/nwlib/canon.c | 480 | ||||
-rw-r--r-- | private/nw/nwlib/exchange.c | 571 | ||||
-rw-r--r-- | private/nw/nwlib/makefile | 6 | ||||
-rw-r--r-- | private/nw/nwlib/ndsapi32.c | 2144 | ||||
-rw-r--r-- | private/nw/nwlib/nwapi32.c | 1661 | ||||
-rw-r--r-- | private/nw/nwlib/nwcapi32.c | 798 | ||||
-rw-r--r-- | private/nw/nwlib/nwpapi32.c | 1011 | ||||
-rw-r--r-- | private/nw/nwlib/packstr.c | 125 | ||||
-rw-r--r-- | private/nw/nwlib/procs.h | 55 | ||||
-rw-r--r-- | private/nw/nwlib/regacl.c | 161 | ||||
-rw-r--r-- | private/nw/nwlib/sources | 66 | ||||
-rw-r--r-- | private/nw/nwlib/tpath.c | 238 |
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); + } +} |