summaryrefslogtreecommitdiffstats
path: root/private/nw/svcdlls/nwwks/client/nwapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/svcdlls/nwwks/client/nwapi.c')
-rw-r--r--private/nw/svcdlls/nwwks/client/nwapi.c1182
1 files changed, 1182 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/client/nwapi.c b/private/nw/svcdlls/nwwks/client/nwapi.c
new file mode 100644
index 000000000..ae92b4f68
--- /dev/null
+++ b/private/nw/svcdlls/nwwks/client/nwapi.c
@@ -0,0 +1,1182 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ api.c
+
+Abstract:
+
+ This module contains exposed APIs that is used by the
+ NetWare Control Panel Applet.
+
+Author:
+
+ Yi-Hsin Sung 15-Jul-1993
+
+Revision History:
+
+ ChuckC 23-Jul-93 Completed the stubs
+
+--*/
+
+#include <nwclient.h>
+#include <nwcanon.h>
+#include <validc.h>
+#include <nwdlg.h>
+#include <nwreg.h>
+#include <nwapi.h>
+#include <ntddnwfs.h>
+
+//
+// forward declare
+//
+
+DWORD
+NwpGetCurrentUserRegKey(
+ IN DWORD DesiredAccess,
+ OUT HKEY *phKeyCurrentUser
+ );
+
+
+
+DWORD
+NwQueryInfo(
+ OUT PDWORD pnPrintOptions,
+ OUT LPWSTR *ppszPreferredSrv
+ )
+/*++
+
+Routine Description:
+ This routine gets the user's preferred server and print options from
+ the registry.
+
+Arguments:
+
+ pnPrintOptions - Receives the user's print option
+
+ ppszPreferredSrv - Receives the user's preferred server
+
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+
+ HKEY hKeyCurrentUser = NULL;
+ DWORD BufferSize;
+ DWORD BytesNeeded;
+ DWORD PrintOption;
+ DWORD ValueType;
+ LPWSTR PreferredServer ;
+ DWORD err ;
+
+ //
+ // get to right place in registry and allocate dthe buffer
+ //
+ if (err = NwpGetCurrentUserRegKey( KEY_READ, &hKeyCurrentUser))
+ {
+ //
+ // If somebody mess around with the registry and we can't find
+ // the registry, just use the defaults.
+ //
+ *ppszPreferredSrv = NULL;
+ *pnPrintOptions = NW_PRINT_OPTION_DEFAULT;
+ return NO_ERROR;
+ }
+
+ BufferSize = sizeof(WCHAR) * (MAX_PATH + 2) ;
+ PreferredServer = (LPWSTR) LocalAlloc(LPTR, BufferSize) ;
+ if (!PreferredServer)
+ return (GetLastError()) ;
+
+ //
+ // Read PreferredServer value into Buffer.
+ //
+ BytesNeeded = BufferSize ;
+
+ err = RegQueryValueExW( hKeyCurrentUser,
+ NW_SERVER_VALUENAME,
+ NULL,
+ &ValueType,
+ (LPBYTE) PreferredServer,
+ &BytesNeeded );
+
+ if (err != NO_ERROR)
+ {
+ //
+ // set to empty and carry on
+ //
+ PreferredServer[0] = 0;
+ }
+
+ //
+ // Read PrintOption value into PrintOption.
+ //
+ BytesNeeded = sizeof(PrintOption);
+
+ err = RegQueryValueExW( hKeyCurrentUser,
+ NW_PRINTOPTION_VALUENAME,
+ NULL,
+ &ValueType,
+ (LPBYTE) &PrintOption,
+ &BytesNeeded );
+
+ if (err != NO_ERROR)
+ {
+ //
+ // set to default and carry on
+ //
+ PrintOption = NW_PRINT_OPTION_DEFAULT;
+ }
+
+ if (hKeyCurrentUser != NULL)
+ (void) RegCloseKey(hKeyCurrentUser) ;
+ *ppszPreferredSrv = PreferredServer ;
+ *pnPrintOptions = PrintOption ;
+ return NO_ERROR ;
+}
+
+
+
+DWORD
+NwSetInfoInRegistry(
+ IN DWORD nPrintOptions,
+ IN LPWSTR pszPreferredSrv
+ )
+/*++
+
+Routine Description:
+
+ This routine set the user's print option and preferred server into
+ the registry.
+
+Arguments:
+
+ nPrintOptions - Supplies the print option.
+
+ pszPreferredSrv - Supplies the preferred server.
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+
+ HKEY hKeyCurrentUser = NULL;
+
+ DWORD err = NwpGetCurrentUserRegKey( KEY_WRITE,
+ &hKeyCurrentUser );
+ if (err != NO_ERROR)
+ return err;
+
+ err = RegSetValueEx(hKeyCurrentUser,
+ NW_SERVER_VALUENAME,
+ 0,
+ REG_SZ,
+ (CONST BYTE *)pszPreferredSrv,
+ (wcslen(pszPreferredSrv)+1) * sizeof(WCHAR)) ;
+
+ if (err != NO_ERROR)
+ {
+ if (hKeyCurrentUser != NULL)
+ (void) RegCloseKey(hKeyCurrentUser) ;
+ return err;
+ }
+
+ err = RegSetValueEx(hKeyCurrentUser,
+ NW_PRINTOPTION_VALUENAME,
+ 0,
+ REG_DWORD,
+ (CONST BYTE *)&nPrintOptions,
+ sizeof(nPrintOptions)) ;
+
+ if (hKeyCurrentUser != NULL)
+ (void) RegCloseKey(hKeyCurrentUser) ;
+ return err;
+}
+DWORD
+NwQueryLogonOptions(
+ OUT PDWORD pnLogonScriptOptions
+ )
+/*++
+
+Routine Description:
+ This routine gets the user's Logon script options from the registry.
+
+Arguments:
+
+ pnLogonScriptOptions - Receives the user's Logon script options
+
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+
+ HKEY hKeyCurrentUser;
+ DWORD BytesNeeded;
+ DWORD LogonScriptOption;
+ DWORD ValueType;
+ DWORD err ;
+
+ //
+ // get to right place in registry and allocate the buffer
+ //
+ if (err = NwpGetCurrentUserRegKey( KEY_READ, &hKeyCurrentUser))
+ {
+ //
+ // If somebody mess around with the registry and we can't find
+ // the registry, assume no.
+ //
+ *pnLogonScriptOptions = NW_LOGONSCRIPT_DEFAULT ;
+ return NO_ERROR;
+ }
+
+ //
+ // Read LogonScriptOption value into LogonScriptOption.
+ //
+ BytesNeeded = sizeof(LogonScriptOption);
+
+ err = RegQueryValueExW( hKeyCurrentUser,
+ NW_LOGONSCRIPT_VALUENAME,
+ NULL,
+ &ValueType,
+ (LPBYTE) &LogonScriptOption,
+ &BytesNeeded );
+
+ if (err != NO_ERROR)
+ {
+ //
+ // default to nothing and carry on
+ //
+ LogonScriptOption = NW_LOGONSCRIPT_DEFAULT;
+ }
+
+ *pnLogonScriptOptions = LogonScriptOption ;
+ return NO_ERROR ;
+}
+
+DWORD
+NwSetLogonOptionsInRegistry(
+ IN DWORD nLogonScriptOptions
+ )
+/*++
+
+Routine Description:
+
+ This routine set the logon script options in the registry.
+
+Arguments:
+
+ nLogonScriptOptions - Supplies the logon options
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+
+ HKEY hKeyCurrentUser;
+
+ DWORD err = NwpGetCurrentUserRegKey( KEY_WRITE,
+ &hKeyCurrentUser );
+ if (err != NO_ERROR)
+ return err;
+
+ err = RegSetValueEx(hKeyCurrentUser,
+ NW_LOGONSCRIPT_VALUENAME,
+ 0,
+ REG_DWORD,
+ (CONST BYTE *)&nLogonScriptOptions,
+ sizeof(nLogonScriptOptions)) ;
+
+ (void) RegCloseKey( hKeyCurrentUser );
+ return err;
+}
+
+
+DWORD
+NwSetInfoInWksta(
+ IN DWORD nPrintOption,
+ IN LPWSTR pszPreferredSrv
+)
+/*++
+
+Routine Description:
+
+ This routine notifies the workstation service and the redirector
+ about the user's new print option and preferred server.
+
+Arguments:
+
+ nPrintOptions - Supplies the print option.
+
+ pszPreferredSrv - Supplies the preferred server.
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+ DWORD err;
+
+ RpcTryExcept {
+
+ err = NwrSetInfo( NULL, nPrintOption, pszPreferredSrv );
+
+ }
+ RpcExcept(1) {
+
+ err = NwpMapRpcError(RpcExceptionCode());
+ }
+ RpcEndExcept
+
+ return err;
+
+}
+
+DWORD
+NwSetLogonScript(
+ IN DWORD ScriptOptions
+)
+/*++
+
+Routine Description:
+
+ This routine notifies the workstation service of login script
+ options.
+
+Arguments:
+
+ ScriptOptions - Supplies the options.
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+ DWORD err;
+
+ RpcTryExcept {
+
+ err = NwrSetLogonScript( NULL, ScriptOptions );
+
+ }
+ RpcExcept(1) {
+
+ err = NwpMapRpcError(RpcExceptionCode());
+ }
+ RpcEndExcept
+
+ return err;
+
+}
+
+
+DWORD
+NwValidateUser(
+ IN LPWSTR pszPreferredSrv
+)
+/*++
+
+Routine Description:
+
+ This routine checks to see if the user can be authenticated on the
+ chosen preferred server.
+
+Arguments:
+
+ pszPreferredSrv - Supplies the preferred server name.
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+ DWORD err;
+
+ //
+ // Don't need to validate if the preferred server is NULL or empty string
+ //
+ if ( ( pszPreferredSrv == NULL )
+ || ( *pszPreferredSrv == 0 )
+ )
+ {
+ return NO_ERROR;
+ }
+
+ //
+ // See if the name contains any invalid characters
+ //
+ if ( !IS_VALID_SERVER_TOKEN( pszPreferredSrv, wcslen( pszPreferredSrv )))
+ return ERROR_INVALID_NAME;
+
+ RpcTryExcept {
+
+ err = NwrValidateUser( NULL, pszPreferredSrv );
+
+ }
+ RpcExcept(1) {
+
+ err = NwpMapRpcError( RpcExceptionCode() );
+ }
+ RpcEndExcept
+
+ return err;
+}
+
+
+DWORD
+NwpGetCurrentUserRegKey(
+ IN DWORD DesiredAccess,
+ OUT HKEY *phKeyCurrentUser
+ )
+/*++
+
+Routine Description:
+
+ This routine opens the current user's registry key under
+ \HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NWCWorkstation\Parameters
+
+Arguments:
+
+ DesiredAccess - The access mask to open the key with
+
+ phKeyCurrentUser - Receives the opened key handle
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+ DWORD err;
+ HKEY hkeyWksta;
+ LPWSTR CurrentUser;
+
+ //
+ // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
+ // \NWCWorkstation\Parameters
+ //
+ err = RegOpenKeyExW(
+ HKEY_LOCAL_MACHINE,
+ NW_WORKSTATION_REGKEY,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ,
+ &hkeyWksta
+ );
+
+ if ( err ) {
+ KdPrint(("NWPROVAU: NwGetCurrentUserRegKey open Parameters key unexpected error %lu!\n", err));
+ return err;
+ }
+ //
+ // Get the current user's SID string.
+ //
+ err = NwReadRegValue(
+ hkeyWksta,
+ NW_CURRENTUSER_VALUENAME,
+ &CurrentUser
+ );
+
+
+ if ( err ) {
+ KdPrint(("NWPROVAU: NwGetCurrentUserRegKey read CurrentUser value unexpected error %lu!\n", err));
+ (void) RegCloseKey( hkeyWksta );
+ return err;
+ }
+
+ (void) RegCloseKey( hkeyWksta );
+
+ //
+ // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
+ // \NWCWorkstation\Parameters\Option
+ //
+ err = RegOpenKeyExW(
+ HKEY_LOCAL_MACHINE,
+ NW_WORKSTATION_OPTION_REGKEY,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ,
+ &hkeyWksta
+ );
+
+ if ( err ) {
+ KdPrint(("NWPROVAU: NwGetCurrentUserRegKey open Parameters\\Option key unexpected error %lu!\n", err));
+ return err;
+ }
+
+ //
+ // Open current user's key
+ //
+ err = RegOpenKeyExW(
+ hkeyWksta,
+ CurrentUser,
+ REG_OPTION_NON_VOLATILE,
+ DesiredAccess,
+ phKeyCurrentUser
+ );
+
+ if ( err == ERROR_FILE_NOT_FOUND)
+ {
+ DWORD Disposition;
+
+ //
+ // Create <NewUser> key under NWCWorkstation\Parameters\Option
+ //
+ err = RegCreateKeyExW(
+ hkeyWksta,
+ CurrentUser,
+ 0,
+ WIN31_CLASS,
+ REG_OPTION_NON_VOLATILE,
+ DesiredAccess,
+ NULL, // security attr
+ phKeyCurrentUser,
+ &Disposition
+ );
+
+ }
+
+ if ( err ) {
+ KdPrint(("NWPROVAU: NwGetCurrentUserRegKey open or create of Parameters\\Option\\%ws key failed %lu\n", CurrentUser, err));
+ }
+
+ (void) RegCloseKey( hkeyWksta );
+ (void) LocalFree((HLOCAL)CurrentUser) ;
+ return err;
+}
+
+DWORD
+NwEnumGWDevices(
+ LPDWORD Index,
+ LPBYTE Buffer,
+ DWORD BufferSize,
+ LPDWORD BytesNeeded,
+ LPDWORD EntriesRead
+ )
+/*++
+
+Routine Description:
+
+ This routine enumerates the special gateway devices (redirections)
+ that are cureently in use.
+
+Arguments:
+
+ Index - Point to start enumeration. Should be zero for first call.
+
+ Buffer - buffer for return data
+
+ BufferSize - size of buffer in bytes
+
+ BytesNeeded - number of bytes needed to return all the data
+
+ EntriesRead - number of entries read
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+ DWORD i, err ;
+ LPNETRESOURCE lpNetRes = (LPNETRESOURCE) Buffer ;
+
+ //
+ // call the implementing routine on server side
+ //
+ RpcTryExcept {
+
+ err = NwrEnumGWDevices( NULL,
+ Index,
+ Buffer,
+ BufferSize,
+ BytesNeeded,
+ EntriesRead) ;
+
+ if ( err == NO_ERROR)
+ {
+ //
+ // the change the offsets into real pointers
+ //
+ for (i = 0; i < *EntriesRead; i++)
+ {
+ lpNetRes->lpLocalName =
+ (LPWSTR) (Buffer+(DWORD)lpNetRes->lpLocalName) ;
+ lpNetRes->lpRemoteName =
+ (LPWSTR) (Buffer+(DWORD)lpNetRes->lpRemoteName) ;
+ lpNetRes->lpProvider =
+ (LPWSTR) (Buffer+(DWORD)lpNetRes->lpProvider) ;
+ lpNetRes++ ;
+ }
+ }
+ }
+ RpcExcept(1) {
+
+ err = NwpMapRpcError( RpcExceptionCode() );
+ }
+ RpcEndExcept
+
+ return err ;
+}
+
+
+DWORD
+NwAddGWDevice(
+ LPWSTR DeviceName,
+ LPWSTR RemoteName,
+ LPWSTR AccountName,
+ LPWSTR Password,
+ DWORD Flags
+ )
+/*++
+
+Routine Description:
+
+ This routine adds a gateway redirection.
+
+Arguments:
+
+ DeviceName - the drive to redirect
+
+ RemoteName - the remote network resource to redirect to
+
+ Flags - supplies the options (eg. UpdateRegistry & make this sticky)
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+ DWORD err;
+
+ RpcTryExcept {
+
+ err = NwrAddGWDevice( NULL,
+ DeviceName,
+ RemoteName,
+ AccountName,
+ Password,
+ Flags) ;
+
+ }
+ RpcExcept(1) {
+
+ err = NwpMapRpcError( RpcExceptionCode() );
+ }
+ RpcEndExcept
+
+ return err;
+}
+
+
+DWORD
+NwDeleteGWDevice(
+ LPWSTR DeviceName,
+ DWORD Flags
+ )
+/*++
+
+Routine Description:
+
+ This routine deletes a gateway redirection.
+
+Arguments:
+
+ DeviceName - the drive to delete
+
+ Flags - supplies the options (eg. UpdateRegistry & make this sticky)
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+ DWORD err;
+
+ RpcTryExcept {
+
+ err = NwrDeleteGWDevice(NULL, DeviceName, Flags) ;
+
+ }
+ RpcExcept(1) {
+
+ err = NwpMapRpcError( RpcExceptionCode() );
+ }
+ RpcEndExcept
+
+ return err;
+}
+
+
+DWORD
+NwQueryGatewayAccount(
+ LPWSTR AccountName,
+ DWORD AccountNameLen,
+ LPDWORD AccountCharsNeeded,
+ LPWSTR Password,
+ DWORD PasswordLen,
+ LPDWORD PasswordCharsNeeded
+ )
+/*++
+
+Routine Description:
+
+ Query the gateway account info. specifically, the Account name and
+ the passeord stored as an LSA secret.
+
+Arguments:
+
+ AccountName - buffer used to return account name
+
+ AccountNameLen - length of buffer
+
+ Password - buffer used to return account name
+
+ PasswordLen - length of buffer
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+ DWORD err;
+
+ RpcTryExcept {
+
+ if (AccountName && AccountNameLen)
+ *AccountName = 0 ;
+
+ if (Password && PasswordLen)
+ *Password = 0 ;
+
+ err = NwrQueryGatewayAccount(NULL,
+ AccountName,
+ AccountNameLen,
+ AccountCharsNeeded,
+ Password,
+ PasswordLen,
+ PasswordCharsNeeded) ;
+ }
+ RpcExcept(1) {
+
+ err = NwpMapRpcError( RpcExceptionCode() );
+ }
+ RpcEndExcept
+
+ return err;
+}
+
+DWORD
+NwSetGatewayAccount(
+ LPWSTR AccountName,
+ LPWSTR Password
+ )
+/*++
+
+Routine Description:
+
+ Set the account and password to be used for gateway access.
+
+Arguments:
+
+ AccountName - the account (NULL terminated)
+
+ Password - the password string (NULL terminated)
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+ DWORD err;
+
+ RpcTryExcept {
+
+ err = NwrSetGatewayAccount( NULL,
+ AccountName,
+ Password);
+ }
+ RpcExcept(1) {
+
+ err = NwpMapRpcError( RpcExceptionCode() );
+ }
+ RpcEndExcept
+
+ return err;
+}
+
+
+DWORD
+NwLogonGatewayAccount(
+ LPWSTR AccountName,
+ LPWSTR Password,
+ LPWSTR Server
+ )
+/*++
+
+Routine Description:
+
+ Logon the SYSTEM process with the specified account/password.
+
+Arguments:
+
+ AccountName - the account (NULL terminated)
+
+ Password - the password string (NULL terminated)
+
+ Server - the server to authenticate against
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+
+ DWORD err ;
+ LUID SystemId = SYSTEM_LUID ;
+
+ RpcTryExcept {
+
+ (void) NwrLogoffUser(NULL, &SystemId);
+
+ err = NwrLogonUser( NULL,
+ &SystemId,
+ AccountName,
+ Password,
+ Server,
+ NULL,
+ 0 );
+ }
+ RpcExcept(1) {
+
+ err = NwpMapRpcError( RpcExceptionCode() );
+ }
+ RpcEndExcept
+
+ return err ;
+}
+
+NTSTATUS
+NwGetUserNameForServer(
+ PUNICODE_STRING ServerName,
+ PUNICODE_STRING UserName
+ )
+/*++
+
+Routine Description:
+
+ Calls the redir to get the User Name used to connect to the server
+ in question.
+
+Arguments:
+
+ ServerName - the server in question
+
+ UserName - used to return the user name
+
+Return Value:
+
+ Returns the appropriate NTSTATUS
+
+--*/
+{
+ NTSTATUS Status;
+ WCHAR LocalUserName[NW_MAX_USERNAME_LEN];
+ ULONG UserNameLen = sizeof(LocalUserName);
+
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING DriverName;
+ HANDLE RdrHandle = NULL;
+ IO_STATUS_BLOCK IoStatus;
+
+ //
+ // Initialize variables
+ //
+
+ RtlInitUnicodeString( &DriverName, DD_NWFS_DEVICE_NAME_U );
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &DriverName,
+ 0,
+ NULL,
+ NULL
+ );
+
+ //
+ // open handle to the redir
+ //
+
+ Status = NtOpenFile(
+ &RdrHandle,
+ FILE_LIST_DIRECTORY | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatus,
+ FILE_SHARE_READ,
+ 0 // open options
+ );
+
+ if (!NT_SUCCESS(Status) ||
+ !NT_SUCCESS(IoStatus.Status) )
+ {
+ return( Status );
+ }
+
+
+ //
+ // Call the driver to get use the user name
+ //
+
+ Status = NtFsControlFile(
+ RdrHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatus,
+ FSCTL_NWR_GET_USERNAME,
+ ServerName->Buffer,
+ ServerName->Length,
+ LocalUserName,
+ UserNameLen
+ );
+
+ NtClose(RdrHandle);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ //
+ // copy the info if it fits. set size required and fail otherwise.
+ //
+
+ if (UserName->MaximumLength >= IoStatus.Information)
+ {
+ UserName->Length = (USHORT) IoStatus.Information;
+
+ RtlCopyMemory( UserName->Buffer,
+ LocalUserName,
+ UserNameLen );
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ UserName->Length = (USHORT) IoStatus.Information;
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ return(Status);
+}
+
+
+NTSTATUS
+NwEncryptChallenge(
+ IN PUCHAR Challenge,
+ IN ULONG ObjectId,
+ IN OPTIONAL PUNICODE_STRING ServerName,
+ IN OPTIONAL PUNICODE_STRING Password,
+ OUT PUCHAR ChallengeResponse,
+ OUT OPTIONAL PUCHAR SessionKey
+ )
+/*++
+
+Routine Description:
+
+ Calls the redir to encrypt a challenge
+
+Arguments:
+
+ Challenge - Challenge key
+
+ ObjectId - User's object ID
+
+ ServerName - The server to authenticate against
+
+ Password - Password supplied
+
+ ChallengeResponse - Used to return the challenge response
+
+ SessionKey - Used to return the session key
+
+Return Value:
+
+ Returns the appropriate NTSTATUS
+
+--*/
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING DriverName;
+ HANDLE RdrHandle = NULL;
+ IO_STATUS_BLOCK IoStatus;
+ PNWR_GET_CHALLENGE_REQUEST ChallengeRequest = NULL;
+ NWR_GET_CHALLENGE_REPLY ChallengeReply;
+ ULONG ChallengeRequestSize;
+
+ //
+ // Initialize variables
+ //
+
+ RtlInitUnicodeString( &DriverName, DD_NWFS_DEVICE_NAME_U );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &DriverName,
+ 0,
+ NULL,
+ NULL
+ );
+
+ //
+ // open handle to redirector
+ //
+
+ Status = NtOpenFile(
+ &RdrHandle,
+ FILE_LIST_DIRECTORY | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatus,
+ FILE_SHARE_READ,
+ 0 // open options
+ );
+
+ if (!NT_SUCCESS(Status) ||
+ !NT_SUCCESS(IoStatus.Status) )
+ {
+ return( Status );
+ }
+
+
+
+ ChallengeRequestSize = sizeof(NWR_GET_CHALLENGE_REQUEST) +
+ ((Password != NULL) ? Password->Length : 0) +
+ ((ServerName != NULL) ? ServerName->Length : 0);
+
+ ChallengeRequest = (PNWR_GET_CHALLENGE_REQUEST) RtlAllocateHeap(
+ RtlProcessHeap(),
+ 0,
+ ChallengeRequestSize
+ );
+
+ if (ChallengeRequest == NULL )
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Cleanup;
+ }
+
+ //
+ // Marshall the challenge request structure. Only send servername if
+ // password has not been specified.
+ //
+
+ ChallengeRequest->ObjectId = ObjectId;
+ ChallengeRequest->Flags = 0;
+
+ //
+ // If both password and servername are present, use the password.
+ //
+
+ if ((Password != NULL) && (Password->Length != 0))
+ {
+
+ ChallengeRequest->ServerNameorPasswordLength = Password->Length;
+ RtlCopyMemory(
+ ChallengeRequest->ServerNameorPassword,
+ Password->Buffer,
+ Password->Length
+ );
+ ChallengeRequest->Flags = CHALLENGE_FLAGS_PASSWORD;
+
+ }
+ else if ((ServerName != NULL) && (ServerName->Length != 0))
+ {
+
+ ChallengeRequest->ServerNameorPasswordLength = ServerName->Length;
+
+ RtlCopyMemory(
+ ChallengeRequest->ServerNameorPassword,
+ ServerName->Buffer,
+ ServerName->Length
+ );
+
+ ChallengeRequest->Flags = CHALLENGE_FLAGS_SERVERNAME;
+ }
+
+ RtlCopyMemory(
+ ChallengeRequest->Challenge,
+ Challenge,
+ 8
+ );
+
+ //
+ // Issue FS control to redir to get challenge response
+ //
+
+ Status = NtFsControlFile(
+ RdrHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatus,
+ FSCTL_NWR_CHALLENGE,
+ ChallengeRequest,
+ ChallengeRequestSize,
+ &ChallengeReply,
+ sizeof(ChallengeReply)
+ );
+ if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStatus.Status)) {
+ goto Cleanup;
+ }
+
+
+ RtlCopyMemory(
+ ChallengeResponse,
+ ChallengeReply.Challenge,
+ 8
+ );
+
+ if (SessionKey != NULL)
+ {
+ RtlCopyMemory(
+ ChallengeResponse,
+ ChallengeReply.Challenge,
+ 8
+ );
+ }
+
+Cleanup:
+
+ if (RdrHandle != NULL)
+ {
+ NtClose(RdrHandle);
+ }
+
+ if (ChallengeRequest != NULL)
+ {
+ RtlFreeHeap(
+ RtlProcessHeap(),
+ 0,
+ ChallengeRequest
+ );
+ }
+
+ return(Status);
+}
+