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/svcdlls/nwwks/server/gateway.c | |
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/svcdlls/nwwks/server/gateway.c')
-rw-r--r-- | private/nw/svcdlls/nwwks/server/gateway.c | 1258 |
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 ; +} + + + |