summaryrefslogtreecommitdiffstats
path: root/private/nw/svcdlls/nwwks/server/gateway.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/svcdlls/nwwks/server/gateway.c')
-rw-r--r--private/nw/svcdlls/nwwks/server/gateway.c1258
1 files changed, 1258 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/server/gateway.c b/private/nw/svcdlls/nwwks/server/gateway.c
new file mode 100644
index 000000000..48b8ecf3b
--- /dev/null
+++ b/private/nw/svcdlls/nwwks/server/gateway.c
@@ -0,0 +1,1258 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ gateway.c
+
+Abstract:
+
+ This module contains gateway devices routines supported by
+ NetWare Workstation service.
+
+Author:
+
+ Chuck Y Chan (ChuckC) 31-Oct-1993
+
+Revision History:
+
+--*/
+
+#include <nw.h>
+#include <handle.h>
+#include <nwreg.h>
+#include <nwlsa.h>
+#include <nwapi.h>
+
+#include <lmcons.h>
+#include <lmshare.h>
+
+
+//-------------------------------------------------------------------//
+// //
+// Local Function Prototypes //
+// //
+//-------------------------------------------------------------------//
+
+//
+// wrapper round the RPC routines.
+//
+
+DWORD
+NwrEnumGWDevices(
+ LPWSTR Reserved,
+ 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.
+ This is set by the function and can be used to resume the
+ enumeration.
+
+ 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. If NO_ERROR or ERROR_MORE_DATA
+ then EntriesRead will indicated the number of valid entries in buffer.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(Reserved);
+
+ return ( NwEnumerateGWDevices(
+ Index,
+ Buffer,
+ BufferSize,
+ BytesNeeded,
+ EntriesRead
+ ) ) ;
+}
+
+
+DWORD
+NwrAddGWDevice(
+ LPWSTR Reserved,
+ 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 status ;
+ UNREFERENCED_PARAMETER(Reserved);
+
+ //
+ // make connection to the server to ensure we have a connection.
+ // if GatewayConnectionAlways is false, the function will immediately
+ // delete the connection, so this will just be an access check.
+ //
+ status = NwCreateGWConnection( RemoteName,
+ AccountName,
+ Password,
+ GatewayConnectionAlways) ;
+
+ if (status != NO_ERROR)
+ {
+ return status ;
+ }
+
+ //
+ // make the symbolic link
+ //
+ return ( NwCreateGWDevice(
+ DeviceName,
+ RemoteName,
+ Flags
+ ) ) ;
+}
+
+
+DWORD
+NwrDeleteGWDevice(
+ LPWSTR Reserved,
+ LPWSTR DeviceName,
+ DWORD Flags
+ )
+/*++
+
+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.
+ This is set by the function and can be used to resume the
+ enumeration.
+
+ 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.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(Reserved);
+
+ return ( NwRemoveGWDevice(
+ DeviceName,
+ Flags
+ ) ) ;
+}
+
+
+DWORD
+NwrQueryGatewayAccount(
+ LPWSTR Reserved,
+ 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
+
+ AccountCharsNeeded - number of chars needed. only set properly if
+ AccountNameLen is too small.
+
+ Password - buffer used to return account name
+
+ PasswordLen - length of buffer
+
+ PasswordCharsNeeded - number of chars needed, only set properly if
+ PasswordLen is too small.
+
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(Reserved);
+
+ return ( NwQueryGWAccount(
+ AccountName,
+ AccountNameLen,
+ AccountCharsNeeded,
+ Password,
+ PasswordLen,
+ PasswordCharsNeeded
+ ) ) ;
+}
+
+
+DWORD
+NwrSetGatewayAccount(
+ LPWSTR Reserved,
+ 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.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(Reserved);
+
+ return ( NwSetGWAccount(
+ AccountName,
+ Password
+ ) ) ;
+}
+
+
+//
+// actual functions
+//
+
+
+
+DWORD
+NwEnumerateGWDevices(
+ 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.
+ This is set by the function and can be used to resume the
+ enumeration.
+
+ 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 NwRdrNameLength, NwProviderNameSize ;
+ DWORD i, status ;
+ DWORD Length, Count, BytesRequired, SkipCount ;
+ WCHAR Drive[3] ;
+ WCHAR Path[MAX_PATH+1] ;
+ NETRESOURCEW *lpNetRes = (NETRESOURCEW *) Buffer ;
+ LPBYTE BufferEnd = Buffer + ROUND_DOWN_COUNT(BufferSize,ALIGN_WCHAR) ;
+
+ //
+ // init the parts of the drives string we never change
+ //
+ Drive[1] = L':' ;
+ Drive[2] = 0 ;
+
+ Count = 0 ;
+ BytesRequired = 0 ;
+ SkipCount = *Index ;
+ NwProviderNameSize = wcslen(NwProviderName) + 1 ;
+ NwRdrNameLength = sizeof(DD_NWFS_DEVICE_NAME_U)/sizeof(WCHAR) - 1 ;
+
+
+ //
+ // for all logical drives
+ //
+ for (i = 0; i <26 ; i++)
+ {
+ BOOL GatewayDrive = FALSE ;
+
+ Drive[0] = L'A' + (USHORT)i ;
+
+ //
+ // get the symbolic link
+ //
+ Length = QueryDosDeviceW(Drive,
+ Path,
+ sizeof(Path)/sizeof(Path[0])) ;
+
+ //
+ // the value must be at least as long as our device name
+ //
+ if (Length >= NwRdrNameLength + 4)
+ {
+ //
+ // and it must match the following criteria:
+ // 1) start with \device\nwrdr
+ // 2) must have '\' after \device\nwrdr
+ // 3) must not have colon (ie. must be`
+ // \\device\nwrdr\server\share, and not
+ // \\device\nwrdr\x:\server\share
+ //
+
+ if ((_wcsnicmp(Path,DD_NWFS_DEVICE_NAME_U,NwRdrNameLength)
+ == 0)
+ && (Path[NwRdrNameLength] == '\\')
+ && (Path[NwRdrNameLength+2] != ':'))
+ {
+ //
+ // if this is an indexed read, skip the first N.
+ // this is inefficient, but we do not expect to
+ // have to go thru this very often. there are few
+ // such devices, and any reasonable buffer (even 1K)
+ // should get them all first time.
+ //
+
+ if (SkipCount)
+ SkipCount-- ;
+ else
+ GatewayDrive = TRUE ; // found a drive we want
+ }
+ }
+
+ if (GatewayDrive)
+ {
+ //
+ // we meet all criteria above
+ //
+
+ DWORD UncSize ;
+
+ UncSize = Length - NwRdrNameLength + 2 ;
+ BytesRequired += ( sizeof(NETRESOURCE) +
+ (UncSize * sizeof(WCHAR)) +
+ (NwProviderNameSize * sizeof(WCHAR)) +
+ (3 * sizeof(WCHAR))) ; // 3 for drive, X:\0
+
+ if (BytesRequired <= BufferSize)
+ {
+ LPWSTR lpStr = (LPWSTR) BufferEnd ;
+
+ Count++ ;
+
+ //
+ // copy the drive name
+ //
+ lpStr -= 3 ;
+ wcscpy(lpStr, Drive) ;
+ lpNetRes->lpLocalName = (LPWSTR) ((LPBYTE)lpStr - Buffer) ;
+
+ //
+ // copy the UNC name
+ //
+ lpStr -= UncSize ; // for the UNC name
+ lpStr[0] = L'\\' ;
+ wcscpy(lpStr+1, Path+NwRdrNameLength) ;
+ lpNetRes->lpRemoteName = (LPWSTR) ((LPBYTE)lpStr - Buffer) ;
+
+ //
+ // copy the provider name
+ //
+ lpStr -= NwProviderNameSize ; // for the provider name
+ wcscpy(lpStr, NwProviderName) ;
+ lpNetRes->lpProvider = (LPWSTR) ((LPBYTE)lpStr - Buffer) ;
+
+ //
+ // set up the rest of the structure
+ //
+ lpNetRes->dwScope = RESOURCE_CONNECTED ;
+ lpNetRes->dwType = RESOURCETYPE_DISK ;
+ lpNetRes->dwDisplayType = 0 ;
+ lpNetRes->dwUsage = 0 ;
+ lpNetRes->lpComment = 0 ;
+
+ lpNetRes++ ;
+ BufferEnd = (LPBYTE) lpStr ;
+ }
+ }
+
+ }
+
+
+ *EntriesRead = Count ; // set number of entries
+ *Index += Count ; // move index
+ *BytesNeeded = BytesRequired ; // set bytes needed
+
+ if (BytesRequired == 0) // no info left
+ return (ERROR_NO_MORE_ITEMS) ;
+
+ if (BytesRequired > BufferSize)
+ {
+ return (ERROR_MORE_DATA) ;
+ }
+
+ return NO_ERROR ;
+}
+
+
+DWORD
+NwCreateGWDevice(
+ LPWSTR DeviceName,
+ LPWSTR RemoteName,
+ 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.
+
+--*/
+{
+ LPWSTR ConnectName = NULL;
+ DWORD status ;
+ WCHAR Path [MAX_PATH + 1] ;
+
+ //
+ // validate/canon the name. Use a drive to specific we allow UNC only.
+ //
+ if ((status = NwLibCanonRemoteName( L"A:",
+ RemoteName,
+ &ConnectName,
+ NULL
+ )) != NO_ERROR)
+ {
+ return status;
+ }
+
+ //
+ // build up the full name of \device\nwrdr\server\volume
+ //
+ wcscpy(Path, DD_NWFS_DEVICE_NAME_U) ;
+ wcscat(Path, ConnectName+1 ) ;
+
+ //
+ // create the symbolic link
+ //
+ status = NwCreateSymbolicLink(DeviceName, Path) ;
+
+ (void) LocalFree((HLOCAL) ConnectName);
+
+ //
+ // if update registry is set, write it out
+ //
+ if ((status == NO_ERROR) && (Flags & NW_GW_UPDATE_REGISTRY))
+ {
+ HKEY hKey ;
+ DWORD dwDisposition ;
+
+ //
+ //
+ // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
+ // \NWCWorkstation\Drives (create it if not there)
+ //
+ status = RegCreateKeyExW(
+ HKEY_LOCAL_MACHINE,
+ NW_WORKSTATION_GATEWAY_DRIVES,
+ 0,
+ L"",
+ REG_OPTION_NON_VOLATILE,
+ KEY_WRITE, // desired access
+ NULL, // default security
+ &hKey,
+ &dwDisposition // ignored
+ );
+
+ if ( status )
+ return status ;
+
+ status = RegSetValueExW(
+ hKey,
+ DeviceName,
+ 0,
+ REG_SZ,
+ (LPBYTE) RemoteName,
+ (wcslen(RemoteName)+1) * sizeof(WCHAR)) ;
+
+ RegCloseKey( hKey );
+ }
+
+ return status ;
+
+}
+
+DWORD
+NwRemoveGWDevice(
+ 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 status ;
+ LPWSTR Local = NULL ;
+
+ if (status = NwLibCanonLocalName(DeviceName,
+ &Local,
+ NULL))
+ return status ;
+
+ //
+ // delete the symbolic link
+ //
+ if (! DefineDosDeviceW(DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH,
+ Local,
+ DD_NWFS_DEVICE_NAME_U))
+ {
+ status = ERROR_INVALID_DRIVE ;
+ }
+
+ //
+ // If cleanup deleted (dangling) share is set go do it now.
+ // We loop thru all the shares looking for one that matches that drive.
+ // Then we ask the server to nuke that dangling share.
+ //
+ if ((status == NO_ERROR) && (Flags & NW_GW_CLEANUP_DELETED))
+ {
+ HKEY hKey ;
+ DWORD err ;
+
+ //
+ //
+ // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
+ // \NWCWorkstation\Shares
+ //
+ err = RegOpenKeyExW(
+ HKEY_LOCAL_MACHINE,
+ NW_WORKSTATION_GATEWAY_SHARES,
+ REG_OPTION_NON_VOLATILE, // options
+ KEY_READ | KEY_WRITE, // desired access
+ &hKey
+ );
+
+ if (err == NO_ERROR)
+ {
+ WCHAR Path[MAX_PATH + 1], ShareName[MAX_PATH+1] ;
+ DWORD dwType, i = 0, dwPathSize, dwShareNameSize ;
+
+ do {
+
+ dwPathSize = sizeof(Path),
+ dwShareNameSize = sizeof(ShareName)/sizeof(ShareName[0]) ;
+ dwType = REG_SZ ;
+
+ err = RegEnumValueW(hKey,
+ i,
+ ShareName,
+ &dwShareNameSize,
+ NULL,
+ &dwType,
+ (LPBYTE)Path,
+ &dwPathSize) ;
+
+ //
+ // Look for matching drive, eg. "X:"
+ // If have match, cleanup as best we can and break out now.
+ //
+ if ((err == NO_ERROR) &&
+ (_wcsnicmp(Path,DeviceName,2) == 0))
+ {
+ (void) NetShareDelSticky( NULL,
+ ShareName,
+ 0 ) ;
+ (void) RegDeleteValueW(hKey,
+ ShareName) ;
+ break ;
+ }
+
+ i++ ;
+
+ } while (err == NO_ERROR) ;
+
+ RegCloseKey( hKey );
+ }
+
+ }
+
+ //
+ // if update registry is set, write it out
+ //
+ if ((status == NO_ERROR) && (Flags & NW_GW_UPDATE_REGISTRY))
+ {
+ HKEY hKey ;
+ WCHAR Path[MAX_PATH + 1] ;
+ DWORD dwType, dwSize = sizeof(Path) ;
+
+ //
+ //
+ // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
+ // \NWCWorkstation\Drives
+ //
+ status = RegOpenKeyExW(
+ HKEY_LOCAL_MACHINE,
+ NW_WORKSTATION_GATEWAY_DRIVES,
+ REG_OPTION_NON_VOLATILE, // options
+ KEY_READ | KEY_WRITE, // desired access
+ &hKey
+ );
+
+ if ( status )
+ goto ExitPoint ;
+
+ if (GatewayConnectionAlways)
+ {
+ //
+ // Read the remote path and delete the connection
+ // if we made one in the first place.
+ //
+ status = RegQueryValueExW(
+ hKey,
+ Local,
+ NULL,
+ &dwType,
+ (LPBYTE) Path,
+ &dwSize
+ );
+
+ if (status == NO_ERROR)
+ {
+ (void) NwDeleteGWConnection(Path) ;
+ }
+ }
+
+ status = RegDeleteValueW(
+ hKey,
+ DeviceName
+ ) ;
+
+ RegCloseKey( hKey );
+ }
+
+ExitPoint:
+
+ if (Local)
+ (void) LocalFree((HLOCAL)Local) ;
+
+ return status ;
+}
+
+DWORD
+NwGetGatewayResource(
+ IN LPWSTR LocalName,
+ OUT LPWSTR RemoteName,
+ IN DWORD RemoteNameLen,
+ OUT LPDWORD CharsRequired
+ )
+/*++
+
+Routine Description:
+
+ For a gateway devicename, get the network resource associated with it.
+
+Arguments:
+
+ LocalName - name of devive to query
+
+ RemoteName - buffer to return the network resource
+
+ RemoteNameLen - size of buffer (chars)
+
+ CharsRequired - the number of chars needed
+
+Return Value:
+
+ WN_SUCCESS - success (the device is a gateway redirection)
+
+ WN_MORE_DATA - buffer too small, but device is a gateway redirection
+
+ WN_NOT_CONNECTED - not a gateway redirection
+
+--*/
+{
+ WCHAR Path[MAX_PATH+1] ;
+ DWORD Length ;
+ DWORD NwRdrNameLength ;
+
+ NwRdrNameLength = sizeof(DD_NWFS_DEVICE_NAME_U)/sizeof(WCHAR) - 1 ;
+
+ //
+ // retrieve symbolic link for the device
+ //
+ Length = QueryDosDeviceW(LocalName,
+ Path,
+ sizeof(Path)/sizeof(Path[0])) ;
+
+ //
+ // the result is only interesting if it can at least fit:
+ // \device\nwrdr\x\y
+ //
+ if (Length >= NwRdrNameLength + 4)
+ {
+ //
+ // check to make sure that the prefix is coreect, and that
+ // it is not of form: \device\nwrdr\x:\...
+ //
+ if ((_wcsnicmp(Path,DD_NWFS_DEVICE_NAME_U,NwRdrNameLength) == 0)
+ && (Path[NwRdrNameLength] == '\\')
+ && (Path[NwRdrNameLength+2] != ':'))
+ {
+ //
+ // check buffer size
+ //
+ if (RemoteNameLen < ((Length - NwRdrNameLength) + 1))
+ {
+ if (CharsRequired)
+ *CharsRequired = ((Length - NwRdrNameLength) + 1) ;
+ return WN_MORE_DATA ;
+ }
+
+ *RemoteName = L'\\' ;
+ wcscpy(RemoteName+1,Path+NwRdrNameLength) ;
+ return WN_SUCCESS ;
+ }
+ }
+
+ return WN_NOT_CONNECTED ;
+}
+
+
+DWORD
+NwQueryGWAccount(
+ 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
+
+ AccountCharsNeeded - number of chars needed. only set properly if
+ AccountNameLen is too small.
+
+ Password - buffer used to return account name
+
+ PasswordLen - length of buffer
+
+ PasswordCharsNeeded - number of chars needed, only set properly if
+ PasswordLen is too small.
+
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+ DWORD status = NO_ERROR ;
+ LONG RegError;
+
+ HKEY WkstaKey = NULL;
+ LPWSTR GatewayAccount = NULL;
+
+ PUNICODE_STRING StoredPassword = NULL;
+ PUNICODE_STRING StoredOldPassword = NULL;
+
+ *AccountCharsNeeded = 0 ;
+ *PasswordCharsNeeded = 0 ;
+
+ //
+ // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
+ // \NWCWorkstation\Parameters
+ //
+ RegError = RegOpenKeyExW(
+ HKEY_LOCAL_MACHINE,
+ NW_WORKSTATION_REGKEY,
+ REG_OPTION_NON_VOLATILE, // options
+ KEY_READ, // desired access
+ &WkstaKey
+ );
+
+ if (RegError != ERROR_SUCCESS)
+ {
+ return (RegError);
+ }
+
+ //
+ // Read the gateway account from the registry.
+ //
+ status = NwReadRegValue(
+ WkstaKey,
+ NW_GATEWAYACCOUNT_VALUENAME,
+ &GatewayAccount
+ );
+
+ if (status != NO_ERROR)
+ {
+ if (status != ERROR_FILE_NOT_FOUND)
+ goto CleanExit;
+
+ if (AccountNameLen > 0)
+ *AccountName = 0 ;
+ status = NO_ERROR ;
+ }
+ else
+ {
+ *AccountCharsNeeded = wcslen(GatewayAccount) + 1 ;
+ if (*AccountCharsNeeded > AccountNameLen)
+ {
+ status = ERROR_INSUFFICIENT_BUFFER ;
+ goto CleanExit;
+ }
+ wcscpy(AccountName,GatewayAccount);
+ }
+
+ //
+ // Read the password from its secret object in LSA.
+ //
+ status = NwGetPassword(
+ GATEWAY_USER,
+ &StoredPassword, // Must be freed with LsaFreeMemory
+ &StoredOldPassword // Must be freed with LsaFreeMemory
+ );
+
+ if (status != NO_ERROR)
+ {
+ if (status != ERROR_FILE_NOT_FOUND)
+ goto CleanExit;
+
+ if (PasswordLen > 0)
+ *Password = 0 ;
+
+ status = NO_ERROR ;
+ }
+ else
+ {
+ *PasswordCharsNeeded = StoredPassword->Length/sizeof(WCHAR) + 1 ;
+ if ((StoredPassword->Length/sizeof(WCHAR)) >= PasswordLen)
+ {
+ status = ERROR_INSUFFICIENT_BUFFER ;
+ goto CleanExit;
+ }
+ wcsncpy(Password,
+ StoredPassword->Buffer,
+ StoredPassword->Length/sizeof(WCHAR));
+ Password[StoredPassword->Length/sizeof(WCHAR)] = 0 ;
+ }
+
+
+CleanExit:
+
+ if (StoredPassword != NULL) {
+ (void) LsaFreeMemory((PVOID) StoredPassword);
+ }
+
+ if (StoredOldPassword != NULL) {
+ (void) LsaFreeMemory((PVOID) StoredOldPassword);
+ }
+
+ if (GatewayAccount != NULL) {
+ (void) LocalFree((HLOCAL) GatewayAccount);
+ }
+
+ (void) RegCloseKey(WkstaKey);
+
+ return status ;
+}
+
+DWORD
+NwSetGWAccount(
+ 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 status ;
+ HKEY WkstaKey = NULL;
+
+ //
+ // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
+ // \NWCWorkstation\Parameters
+ //
+ status = RegOpenKeyExW(
+ HKEY_LOCAL_MACHINE,
+ NW_WORKSTATION_REGKEY,
+ REG_OPTION_NON_VOLATILE, // options
+ KEY_WRITE, // desired access
+ &WkstaKey
+ );
+
+ if (status != ERROR_SUCCESS)
+ {
+ return (status);
+ }
+
+ //
+ // Write the account name out
+ //
+ status = RegSetValueExW(
+ WkstaKey,
+ NW_GATEWAYACCOUNT_VALUENAME,
+ 0,
+ REG_SZ,
+ (LPVOID) AccountName,
+ (wcslen(AccountName) + 1) * sizeof(WCHAR)
+ );
+
+ if (status == NO_ERROR)
+ {
+ status = NwSetPassword(
+ GATEWAY_USER,
+ Password) ;
+ }
+
+ return status ;
+}
+
+
+DWORD
+NwCreateRedirections(
+ LPWSTR Account,
+ LPWSTR Password
+ )
+/*++
+
+Routine Description:
+
+ Create the gateway redirections from what is stored in registry.
+ As we go along, we validate that we have access to it using the
+ gateway account.
+
+Arguments:
+
+ AccountName - the account (NULL terminated)
+
+ Password - the password string (NULL terminated)
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+ DWORD err, i, type ;
+ HKEY hKey ;
+ FILETIME FileTime ;
+ WCHAR Class[256], Device[64], Path[MAX_PATH+1] ;
+ DWORD dwClass, dwSubKeys, dwMaxSubKey, dwMaxClass,
+ dwValues, dwMaxValueName, dwMaxValueData, dwSDLength,
+ dwDeviceLength, dwPathLength ;
+
+ //
+ //
+ // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
+ // \NWCGateway\Parameters
+ //
+ err = RegOpenKeyExW(
+ HKEY_LOCAL_MACHINE,
+ NW_WORKSTATION_GATEWAY_DRIVES,
+ REG_OPTION_NON_VOLATILE, // options
+ KEY_READ, // desired access
+ &hKey
+ );
+
+ if ( err )
+ return err ;
+
+ dwClass = sizeof(Class)/sizeof(Class[0]) ;
+ err = RegQueryInfoKeyW(hKey,
+ Class,
+ &dwClass,
+ NULL,
+ &dwSubKeys,
+ &dwMaxSubKey,
+ &dwMaxClass,
+ &dwValues,
+ &dwMaxValueName,
+ &dwMaxValueData,
+ &dwSDLength,
+ &FileTime) ;
+ if ( err )
+ {
+ RegCloseKey( hKey );
+ return err ;
+ }
+
+ //
+ // for each value we have a redirection to recreate
+ //
+ for (i = 0; i < dwValues; i++)
+ {
+ dwDeviceLength = sizeof(Device)/sizeof(Device[0]) ;
+ dwPathLength = sizeof(Path) ;
+ type = REG_SZ ;
+ err = RegEnumValueW(hKey,
+ i,
+ Device,
+ &dwDeviceLength,
+ NULL,
+ &type,
+ (LPBYTE)Path,
+ &dwPathLength) ;
+
+ //
+ // connect to the server. this will take up a connection but
+ // it will also make sure we have one. on a low limit server, if
+ // we rely on UNC then it is quite likely that other people will
+ // come along & use up all the connections, preventing the Gateway
+ // from getting to it.
+ //
+ // user may turn this off by setting Registry value that results
+ // GatewayConnectionAlways being false.
+ //
+ // regardless of result, we carry on. so if server is down & comes
+ // up later, the symbolic link to UNC will still work.
+ //
+ if (!err)
+ {
+ (void) NwCreateGWConnection( Path,
+ Account,
+ Password,
+ GatewayConnectionAlways) ;
+ }
+
+ //
+ // create the symbolic link
+ //
+ if (!err)
+ {
+ err = NwCreateGWDevice(Device, Path, 0L) ;
+ }
+
+ if (err)
+ {
+ //
+ // log the error in the event log
+ //
+
+ WCHAR Number[16] ;
+ LPWSTR InsertStrings[3] ;
+
+ wsprintfW(Number, L"%d", err) ;
+ InsertStrings[0] = Device ;
+ InsertStrings[1] = Path ;
+ InsertStrings[2] = Number ;
+
+ NwLogEvent(EVENT_NWWKSTA_CANNOT_REDIRECT_DEVICES,
+ 3,
+ InsertStrings,
+ 0) ;
+ }
+ }
+
+ RegCloseKey( hKey );
+
+
+ return NO_ERROR ;
+}
+
+DWORD
+NwDeleteRedirections(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Delete all gateway devices
+
+Arguments:
+
+Return Value:
+
+ Returns the appropriate Win32 error.
+
+--*/
+{
+ LPBYTE Buffer ;
+ DWORD i, status, Index, BufferSize, EntriesRead, BytesNeeded ;
+ LPNETRESOURCE lpNetRes ;
+
+ Index = 0 ;
+
+ //
+ // below is good initial guess
+ //
+ BufferSize = 26 * (sizeof(NETRESOURCE) +
+ (3 + MAX_PATH + 1 + MAX_PATH + 1) * sizeof(WCHAR)) ;
+ Buffer = (LPBYTE) LocalAlloc(LPTR, BufferSize) ;
+
+ if (!Buffer)
+ return (GetLastError()) ;
+
+ lpNetRes = (LPNETRESOURCE) Buffer ;
+
+ status = NwrEnumGWDevices(NULL,
+ &Index,
+ Buffer,
+ BufferSize,
+ &BytesNeeded,
+ &EntriesRead) ;
+
+ //
+ // reallocate as need
+ //
+ if (status == ERROR_MORE_DATA || status == ERROR_INSUFFICIENT_BUFFER)
+ {
+ Buffer = (LPBYTE) LocalReAlloc((HLOCAL)Buffer,
+ BytesNeeded,
+ LMEM_ZEROINIT) ;
+ if (!Buffer)
+ return (GetLastError()) ;
+ Index = 0 ;
+ BufferSize = BytesNeeded ;
+ status = NwrEnumGWDevices(NULL,
+ &Index,
+ Buffer,
+ BufferSize,
+ &BytesNeeded,
+ &EntriesRead) ;
+
+ }
+
+ if (status != NO_ERROR)
+ return status ;
+
+ //
+ // loop thru and delete all the devices
+ //
+ for (i = 0; i < EntriesRead; i++)
+ {
+ status = NwrDeleteGWDevice(NULL,
+ (LPWSTR)((LPBYTE)Buffer +
+ (DWORD)lpNetRes->lpLocalName),
+ 0L) ;
+
+ //
+ // no need report the error, since we are shutting down.
+ // there is no real deletion here - just removing the symbolic link.
+ //
+
+ lpNetRes++ ;
+ }
+
+ return NO_ERROR ;
+}
+
+
+