Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1355 lines
40 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: N W C L I I N F . C P P
//
// Contents: NetWare client configuration notify object.
// Functionality from old INF
//
// Notes:
//
// Author: jeffspr 24 Jun 1997
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "lmerr.h"
#include "lmcons.h"
#include "lmserver.h"
#include "ncreg.h"
#include "nwclidef.h"
#include "nwcliobj.h"
extern const WCHAR c_szRegKeyCtlLsa[];
//---[ Constants ]------------------------------------------------------------
const WCHAR c_szConfigDLLName[] = NW_CONFIG_DLL_NAME;
const WCHAR c_szAuthPackageName[] = NW_AUTH_PACKAGE_NAME;
const WCHAR c_szParamOptionKeyPath[] = NW_NWC_PARAM_OPTION_KEY;
const WCHAR c_szParamLogonKeyPath[] = NW_NWC_PARAM_LOGON_KEY;
const WCHAR c_szNwDocGWHelpName[] = L"nwdocgw.hlp";
const WCHAR c_szNwDocGWCNTName[] = L"nwdocgw.cnt";
const WCHAR c_szNwDocHelpName[] = L"nwdoc.hlp";
const WCHAR c_szNwDocCNTName[] = L"nwdoc.cnt";
const DWORD c_dwOptionKeyPermissions = KEY_SET_VALUE | KEY_CREATE_SUB_KEY;
//---[ Prototypes ]-----------------------------------------------------------
// See the function headers for descriptions
//
HRESULT HrAppendNetwareToAuthPackages();
HRESULT HrCreateParametersSubkeys();
HRESULT HrMungeAutoexecNT();
BOOL FMoveSzToEndOfFile( PSTR pszAutoexecName, PSTR pszMatch);
HRESULT HrAddNetWareToWOWKnownList();
HRESULT HrUpdateLanmanSharedDrivesValue();
HRESULT HrRemoveNetwareFromAuthPackages();
HRESULT HrRemoveNetWareFromWOWKnownList();
HRESULT HrDeleteParametersSubkeys();
HRESULT HrRenameNWDocFiles();
//+---------------------------------------------------------------------------
//
// Member: CNWClient::HrLoadConfigDLL
//
// Purpose: Load nwcfg.dll, so we can call some of the functions within.
// Also, do the GetProcAddress calls for all of the functions
// that we might need.
//
// Arguments:
// (none)
//
// Returns: S_OK or valid Win32 error code.
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
HRESULT CNWClient::HrLoadConfigDLL()
{
HRESULT hr = S_OK;
AssertSz(!m_hlibConfig, "This should not be getting initialized twice");
TraceTag(ttidNWClientCfgFn, ">> CNWClient::HrLoadConfigDLL");
m_hlibConfig = LoadLibrary(c_szConfigDLLName);
if (!m_hlibConfig)
{
DWORD dwLastError = GetLastError();
TraceLastWin32Error("HrLoadConfigDLL() failed");
// More specific info
//
TraceTag(ttidNWClientCfg,
"HrLoadConfigDLL() - LoadLibrary failed on %S, Err: %d",
c_szConfigDLLName, dwLastError);
hr = E_FAIL;
goto Exit;
}
// $$REVIEW: We probably won't need all of these, so make sure that we've
// cut out the ones that we're no longer using (or have never used).
//
m_pfnAppendSzToFile = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "AppendSzToFile");
m_pfnRemoveSzFromFile = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "RemoveSzFromFile");
m_pfnGetKernelVersion = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "GetKernelVersion");
m_pfnSetEverybodyPermission = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "SetEverybodyPermission");
m_pfnlodctr = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "lodctr");
m_pfnunlodctr = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "unlodctr");
m_pfnDeleteGatewayPassword = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "DeleteGatewayPassword");
m_pfnSetFileSysChangeValue = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "SetFileSysChangeValue");
m_pfnCleanupRegistryForNWCS = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "CleanupRegistryForNWCS");
m_pfnSetupRegistryForNWCS = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "SetupRegistryForNWCS");
if (!m_pfnAppendSzToFile || !m_pfnRemoveSzFromFile ||
!m_pfnGetKernelVersion || !m_pfnSetEverybodyPermission ||
!m_pfnlodctr || !m_pfnunlodctr ||
!m_pfnDeleteGatewayPassword || !m_pfnSetFileSysChangeValue ||
!m_pfnCleanupRegistryForNWCS || !m_pfnSetupRegistryForNWCS)
{
TraceLastWin32Error("HrLoadConfigDLL() - GetProcAddress failed");
hr = E_FAIL;
goto Exit;
}
Exit:
TraceTag(ttidNWClientCfgFn, "<< CNWClient::HrLoadConfigDLL");
TraceError("HrLoadConfigDLL", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: CNWClient::FreeConfigDLL
//
// Purpose: Free nwcfg.dll, and NULL out the function pointers.
//
// Arguments:
// (none)
//
// Returns: No return (VOID)
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
VOID CNWClient::FreeConfigDLL()
{
TraceTag(ttidNWClientCfgFn, ">> CNWClient::FreeConfigDLL()");
// If we successfully loaded the library, free it.
if (m_hlibConfig)
{
// Free up the library resources.
FreeLibrary(m_hlibConfig);
m_hlibConfig = NULL;
m_pfnAppendSzToFile = NULL;
m_pfnRemoveSzFromFile = NULL;
m_pfnGetKernelVersion = NULL;
m_pfnSetEverybodyPermission = NULL;
m_pfnlodctr = NULL;
m_pfnunlodctr = NULL;
m_pfnDeleteGatewayPassword = NULL;
m_pfnSetFileSysChangeValue = NULL;
m_pfnCleanupRegistryForNWCS = NULL;
m_pfnSetupRegistryForNWCS = NULL;
}
TraceTag(ttidNWClientCfgFn, "<< CNWClient::FreeConfigDLL()");
}
//+---------------------------------------------------------------------------
//
// Member: CNWClient::HrInstallCodeFromOldINF
//
// Purpose: This contains all of the logic from the old oemnsvnw.inf, or
// at least calls to helper functions that perform all of the
// logic. This runs pretty much straight through the old
// installadapter code.
//
// Arguments:
// (none)
//
// Returns: S_OK or valid Win32 error code.
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
HRESULT CNWClient::HrInstallCodeFromOldINF()
{
HRESULT hr = S_OK;
BOOL fResult = FALSE;
// Get result from NWCFG functions. We won't use it though.
PWSTR pszDummy = NULL;
TraceTag(ttidNWClientCfgFn, ">> CNWClient::HrInstallCodeFromOldINF()");
hr = HrLoadConfigDLL();
if (FAILED(hr))
{
// Error traced in the call itself.
goto Exit;
}
// Call the NWCFG function that does (their comment):
// "set the FileSysChangeValue to please NETWARE.DRV.
// also set win.ini parameter so wfwnet.drv knows we are there."
fResult = m_pfnSetupRegistryForNWCS(0, NULL, &pszDummy);
if (!fResult)
{
TraceTag(ttidNWClientCfg, "HrInstallCodeFromOldINF() - m_pfnSetupRegistryForNWCS failed");
goto Exit;
}
// Append our name to the Lsa Authentication packages reg value.
hr = HrAppendNetwareToAuthPackages();
if (FAILED(hr))
{
// Error traced within the function itself.
//
goto Exit;
}
// Create the required subkeys under the services\NWCWorkstation\parameters
// key
//
hr = HrCreateParametersSubkeys();
if (FAILED(hr))
{
// Error traced within the function itself.
//
goto Exit;
}
// Munge the autoexec.nt (or autoexec.tmp) file. Pass the function pointers
// to the munge that will allow it to manipulate the autoexec.nt
hr = HrMungeAutoexecNT();
if (FAILED(hr))
{
// Error traced within the function itself.
//
goto Exit;
}
hr = HrAddNetWareToWOWKnownList();
if (FAILED(hr))
{
// Error traced within the function itself.
//
goto Exit;
}
// If this is the gateway that we're installing, do the work that will
// allow us to share a redirected resource.
//
if (PF_SERVER == m_pf)
{
hr = HrUpdateLanmanSharedDrivesValue();
if (FAILED(hr))
{
// Error traced within the function itself.
//
goto Exit;
}
// On the server build, rename nwdocgw.* to nwdoc.*
hr = HrRenameNWDocFiles();
if (FAILED(hr))
{
goto Exit;
}
}
Exit:
// This will work even if the handle is NULL.
FreeConfigDLL();
TraceTag(ttidNWClientCfgFn, "<< CNWClient::HrInstallCodeFromOldINF()");
TraceError("CNWClient::HrInstallCodeFromOldINF()", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: CNWClient::HrRemoveCodeFromOldINF
//
// Purpose: This contains all of the remove logic from the old
// oemnsvnw.inf, or at least calls to helper functions that
// perform all of the logic. This runs pretty much straight
// through the old removeadapter code.
//
// Arguments:
// (none)
//
// Returns: S_OK or valid Win32 error code.
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
HRESULT CNWClient::HrRemoveCodeFromOldINF()
{
HRESULT hr = S_OK;
BOOL fResult = FALSE;
// Get result from NWCFG functions. We won't use it though.
PWSTR pszDummy = NULL;
TraceTag(ttidNWClientCfgFn, ">> CNWClient::HrRemoveCodeFromOldINF()");
hr = HrLoadConfigDLL();
if (FAILED(hr))
{
// Error traced in the call itself.
goto Exit;
}
// Call the NWCFG function that does (their comment):
// "set the FileSysChangeValue to please NETWARE.DRV.
// also set win.ini parameter so wfwnet.drv knows we are there."
fResult = m_pfnCleanupRegistryForNWCS(0, NULL, &pszDummy);
if (!fResult)
{
TraceTag(ttidNWClientCfg, "HrRemoveCodeFromOldINF() - m_pfnCleanupRegistryForNWCS failed");
goto Exit;
}
// Remove our name from the Lsa Authentication packages reg value.
hr = HrRemoveNetwareFromAuthPackages();
if (FAILED(hr))
{
// Error traced within the function itself.
//
goto Exit;
}
// Delete the NWC subkeys under the services\NWCWorkstation\parameters
// key
//
hr = HrDeleteParametersSubkeys();
if (FAILED(hr))
{
// Error traced within the function itself.
//
goto Exit;
}
hr = HrRemoveNetWareFromWOWKnownList();
if (FAILED(hr))
{
// Error traced within the function itself.
//
goto Exit;
}
Exit:
// This will work even if the handle is NULL.
FreeConfigDLL();
TraceTag(ttidNWClientCfgFn, "<< CNWClient::HrRemoveCodeFromOldINF()");
TraceError("CNWClient::HrRemoveCodeFromOldINF()", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrAppendNetwareToAuthPackages
//
// Purpose: Helper function for HrCodeFromOldINF() - Appends the netware
// authentication provider name to the end of the LSA
// authentication packages value.
//
// Arguments:
// (none)
//
// Returns: S_OK or valid Win32 Error code.
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
HRESULT HrAppendNetwareToAuthPackages()
{
HRESULT hr = S_OK;
TraceTag(ttidNWClientCfgFn, ">> HrAppendNetwareToAuthPackages");
// Call the cool new AddString... function
//
hr = HrRegAddStringToMultiSz(
(PWSTR) c_szAuthPackageName,
HKEY_LOCAL_MACHINE,
c_szRegKeyCtlLsa,
L"Authentication Packages",
STRING_FLAG_ENSURE_AT_END,
0);
if (FAILED(hr))
{
TraceTag(ttidNWClientCfg, "HrAppendNetwareToAuthPackages() - Failed to "
"Add string to multi-sz 'Authentication Packages' in key: %S",
c_szRegKeyCtlLsa);
goto Exit;
}
Exit:
TraceTag(ttidNWClientCfgFn, "<< HrAppendNetwareToAuthPackages");
TraceError("HrAppendNetwareToAuthPackages", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRemoveNetwareFromAuthPackages
//
// Purpose: Helper function for HrCodeFromOldINF() - Appends the netware
// authentication provider name to the end of the LSA
// authentication packages value.
//
// Arguments:
// (none)
//
// Returns: S_OK or valid Win32 Error code.
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
HRESULT HrRemoveNetwareFromAuthPackages()
{
HRESULT hr = S_OK;
TraceTag(ttidNWClientCfgFn, ">> HrRemoveNetwareFromAuthPackages");
// Call the cool new AddString... function
//
hr = HrRegRemoveStringFromMultiSz(
(PWSTR) c_szAuthPackageName,
HKEY_LOCAL_MACHINE,
c_szRegKeyCtlLsa,
L"Authentication Packages",
STRING_FLAG_REMOVE_ALL);
if (FAILED(hr))
{
TraceTag(ttidNWClientCfg, "HrRemoveNetwareFromAuthPackages() - Failed to "
"Remove string to multi-sz 'Authentication Packages' in key: %S",
c_szRegKeyCtlLsa);
goto Exit;
}
Exit:
TraceTag(ttidNWClientCfgFn, "<< HrRemoveNetwareFromAuthPackages");
TraceError("HrRemoveNetwareFromAuthPackages", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrNwLibSetEverybodyPermission
//
// Purpose: 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"
//
// Returns:
//
// Author: jeffspr 18 Jun 1997
//
// Notes:
//
HRESULT HrNwLibSetEverybodyPermission( IN HKEY hKey,
IN DWORD dwPermission)
{
LONG err; // error code
PSECURITY_DESCRIPTOR psd = NULL; // related SD
PSID pSid = NULL; // original SID
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;
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
RtlFreeSid( pSid );
LocalFree( psd );
LocalFree( pDacl );
LocalFree( pSacl );
LocalFree( pOSid );
LocalFree( pPSid );
return (HRESULT_FROM_WIN32(err));
}
//+---------------------------------------------------------------------------
//
// Function: HrSetEverybodyPermissionsOnOptionsKeys
//
// Purpose: Recurse through the options keys (if any), and set the
// "Everybody" permissions on them.
//
// Arguments:
// hkeyOptions []
// dwPermissions []
//
// Returns:
//
// Author: jeffspr 10 Sep 1997
//
// Notes:
//
HRESULT HrSetEverybodyPermissionsOnOptionsKeys(HKEY hkeyOptions, DWORD dwPermissions)
{
HRESULT hr = S_OK;
DWORD dwIndex = 0;
WCHAR szSubkeyName[MAX_PATH+1];
FILETIME ft;
Assert(hkeyOptions);
// First, do it on the root key.
//
hr = HrNwLibSetEverybodyPermission(hkeyOptions, dwPermissions);
// Enumerate the keys, and set it on them as well
//
while (SUCCEEDED(hr))
{
DWORD dwSubkeyNameSize = MAX_PATH+1;
// Get the next key (starting with 0)
//
hr = HrRegEnumKeyEx( hkeyOptions,
dwIndex++,
szSubkeyName,
&dwSubkeyNameSize,
NULL,
NULL,
&ft);
if (SUCCEEDED(hr))
{
HKEY hkeyUser = NULL;
// Open that key for write
hr = HrRegOpenKeyEx(hkeyOptions,
szSubkeyName,
KEY_ALL_ACCESS,
&hkeyUser);
if (SUCCEEDED(hr))
{
hr = HrNwLibSetEverybodyPermission(hkeyUser, dwPermissions);
}
RegSafeCloseKey(hkeyUser);
}
}
if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
{
hr = S_OK;
}
TraceError("HrSetEverybodyPermissionsOnOptionsKeys", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrCreateParametersSubkeys
//
// Purpose: Creates the subkeys under the NWCWorkstation parameters key.
// This could have been done in the INF, but there were some
// permissions that needed to be set on the keys as well, so
// all of the work now takes place in this function.
//
// Arguments:
// (none)
//
// Returns: S_OK or valid Win32 error code.
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
HRESULT HrCreateParametersSubkeys()
{
HRESULT hr = S_OK;
HKEY hkeyOption = NULL;
HKEY hkeyLogon = NULL;
DWORD dwDisposition = 0;
TraceTag(ttidNWClientCfgFn, ">> HrCreateParametersSubkeys");
hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE,
c_szParamOptionKeyPath,
0,
KEY_ALL_ACCESS,
NULL,
&hkeyOption,
&dwDisposition);
if (FAILED(hr))
{
TraceTag(ttidNWClientCfg, "HrCreateParametersSubkeys() - failed to "
"create/open key %S", c_szParamOptionKeyPath);
goto Exit;
}
hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE,
c_szParamLogonKeyPath,
0,
KEY_SET_VALUE,
NULL,
&hkeyLogon,
&dwDisposition);
if (FAILED(hr))
{
TraceTag(ttidNWClientCfg, "HrCreateParametersSubkeys() - failed to "
"create/open key %S", c_szParamLogonKeyPath);
goto Exit;
}
hr = HrSetEverybodyPermissionsOnOptionsKeys(hkeyOption, c_dwOptionKeyPermissions);
if (FAILED(hr))
{
TraceTag(ttidNWClientCfg, "HrSetEverybodyPermissionsOnOptionsKeys failed, hr: 0x%08x", hr);
goto Exit;
}
Exit:
// Close the hkeys, if they're open
RegSafeCloseKey(hkeyLogon);
RegSafeCloseKey(hkeyOption);
TraceTag(ttidNWClientCfgFn, ">> HrCreateParametersSubkeys");
TraceError("HrCreateParametersSubkeys", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrDeleteParametersSubkeys
//
// Purpose: Deletes the subkeys under the NWCWorkstation parameters key.
//
// Arguments:
// (none)
//
// Returns: S_OK or valid Win32 error code.
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
HRESULT HrDeleteParametersSubkeys()
{
HRESULT hr = S_OK;
TraceTag(ttidNWClientCfgFn, ">> HrDeleteParametersSubkeys");
// Note: We need to be taking ownership of these keys so we can delete
// them. Regardless, ignore if the key deletions fail.
hr = HrRegDeleteKeyTree(HKEY_LOCAL_MACHINE,
c_szParamOptionKeyPath);
if (FAILED(hr))
{
TraceTag(ttidNWClientCfg, "HrDeleteParametersSubkeys() - failed to "
"delete key %S, hr = 0x%08x", c_szParamOptionKeyPath, hr);
hr = S_OK;
}
hr = HrRegDeleteKey(HKEY_LOCAL_MACHINE,
c_szParamLogonKeyPath);
if (FAILED(hr))
{
TraceTag(ttidNWClientCfg, "HrDeleteParametersSubkeys() - failed to "
"delete key %S, hr = 0x%08x", c_szParamLogonKeyPath, hr);
hr = S_OK;
}
TraceTag(ttidNWClientCfgFn, ">> HrDeleteParametersSubkeys");
TraceError("HrDeleteParametersSubkeys", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: FCheckForExistingFile
//
// Purpose: Checks for the existance of the passed in file. Should be
// common-ized.
//
// Arguments:
// pszFileToCheck [] The file name to verify
//
// Returns: TRUE if the file was found, FALSE otherwise.
//
// Author: jeffspr 24 Jun 1997
//
// Notes: $$TODO: Should be improved if we move this to common code.
// The thing that it doesn't do is distinguish between a file
// being "not found" and a file error (such as access rights
// or sharing violations) on the CreateFile call.
//
BOOL FCheckForExistingFile( PSTR pszFileToCheck )
{
BOOL fReturn = TRUE;
HANDLE hFile = NULL;
TraceTag(ttidNWClientCfgFn, ">> FCheckForExistingFile");
hFile = CreateFileA(pszFileToCheck,
GENERIC_READ,
0, // No sharing allowed
NULL, // No security attributes
OPEN_EXISTING, // Fail if file doesn't exist
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
hFile = NULL;
}
else
{
// This was previously a bug. We weren't setting FALSE here, which made
// the function somewhat useless.
fReturn = FALSE;
}
TraceTag(ttidNWClientCfgFn, "<< FCheckForExistingFile");
return fReturn;
}
//+---------------------------------------------------------------------------
//
// Function: KillTrailingWhitespace
//
// Purpose: Remove whitespace from a non-UNICODE string. This is a utility
// function for the autoexec.nt parser
//
// Arguments:
// pszKillMyWhitespace [] String from which to remove whitespace
//
// Returns:
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
VOID KillTrailingWhitespace( PSTR pszKillMyWhitespace )
{
long lLength = 0;
if (!pszKillMyWhitespace)
{
Assert(pszKillMyWhitespace);
goto Exit;
}
lLength = lstrlenA(pszKillMyWhitespace);
if (lLength == 0)
{
goto Exit;
}
while (isspace(pszKillMyWhitespace[lLength-1]))
{
pszKillMyWhitespace[--lLength] = '\0';
}
Exit:
return;
}
//+---------------------------------------------------------------------------
//
// Function: FMoveSzToEndOfFile
//
// Purpose: Find a string in the file of this name, and if it's present,
// move the string to the end of the file. This is used by the
// autoexec.nt parser to move the IPX stuff to the end of the
// file. This is a rewrite of similar code in the nwcfg.dll
// stuff. That code apparently wasn't UNICODE, and didn't work
// for what we were doing.
//
// Arguments:
// pszAutoexecName [] Name of the file to modify
// pszMatch [] String to move
//
// Returns:
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
BOOL FMoveSzToEndOfFile( PSTR pszAutoexecName, PSTR pszMatch )
{
FILE * hsrcfile = NULL;
FILE * hdesfile = NULL;
char * pszTempname = NULL;
char szInput[1000];
TraceTag(ttidNWClientCfgFn, ">> FMoveSzToEndOfFile");
// Get a temp name
//
pszTempname = tmpnam(NULL);
// Open the original and the destination files
//
hsrcfile = fopen(pszAutoexecName, "r");
hdesfile = fopen(pszTempname, "w");
if (( hsrcfile != NULL ) && ( hdesfile != NULL ))
{
while (fgets(szInput,1000,hsrcfile))
{
CHAR szInputCopy[1000];
// Copy to another temp buffer so that when we remove the
// trailing whitespace for the comparison, we won't lose the
// original text.
//
strcpy(szInputCopy, szInput);
// Remove the trailing whitespace, so we only have to compare the
// real text
//
KillTrailingWhitespace(szInputCopy);
// Compare the strings
//
if (lstrcmpiA(szInputCopy, pszMatch) != 0)
{
// If the strings weren't identical, then we still want
// to copy the line
//
fputs(szInput,hdesfile);
}
}
// Append the string to the end of the file.
fputs(pszMatch, hdesfile);
fputs("\r\n",hdesfile);
}
if (hsrcfile != NULL)
{
fclose(hsrcfile);
}
if (hdesfile != NULL)
{
fclose(hdesfile);
}
if (( hsrcfile != NULL ) && ( hdesfile != NULL ))
{
CopyFileA(pszTempname,pszAutoexecName, FALSE);
DeleteFileA(pszTempname);
}
TraceTag(ttidNWClientCfgFn, "<< FMoveSzToEndOfFile");
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Function: HrMungeAutoexecNT
//
// Purpose: Move the IPX stuff to the end of the autoexec.nt. Do this by
// calling FMoveSzToEndOfFile on each of our lines.
//
// Arguments:
// (none)
//
// Returns: S_OK or valid Win32 error code.
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
HRESULT HrMungeAutoexecNT()
{
HRESULT hr = S_OK;
CHAR szAutoNTPath[MAX_PATH+1] = {0};
CHAR szAutoTmpPath[MAX_PATH+1] = {0};
CHAR szWindowsDirANSI[MAX_PATH+1] = {0};
PSTR pszAutoPath = NULL;
BOOL fResult = FALSE;
PCWSTR pszRem1 = NULL;
PSTR pszaRem1MultiByte = NULL;
int iLength = 0;
TraceTag(ttidNWClientCfgFn, ">> HrMungeAutoexecNT");
// Get the windows directory
if (GetSystemWindowsDirectoryA(szWindowsDirANSI, sizeof(szWindowsDirANSI)) == 0)
{
TraceLastWin32Error("HrMungeAutoexecNT - Call to GetWindowsDirectoryA");
hr = HrFromLastWin32Error();
goto Exit;
}
// Build the path to the autoexec.nt
//
wsprintfA(szAutoNTPath, "%s\\system32\\%s", szWindowsDirANSI, "autoexec.nt");
if (FCheckForExistingFile(szAutoNTPath) == FALSE)
{
wsprintfA(szAutoTmpPath, "%s\\system32\\%s", szWindowsDirANSI, "autoexec.tmp");
if (FCheckForExistingFile(szAutoTmpPath) == FALSE)
{
// Per the old INF, skip the whole shebang.
goto Exit;
}
else
{
pszAutoPath = szAutoTmpPath;
}
}
else
{
pszAutoPath = szAutoNTPath;
}
// At this point, we should have found at least one valid
// autoexec.nt or .tmp file. If not, we should have dropped out of the
// function
Assert(pszAutoPath);
pszRem1 = SzLoadStringPcch(_Module.GetResourceInstance(), IDS_AUTOEXEC_REM1, &iLength);
if (!pszRem1 || iLength == 0)
{
AssertSz(FALSE, "Failed to load STR_AUTOEXEC_REM from the resources");
TraceTag(ttidNWClientCfg,
"ERROR: Failed to load STR_AUTOEXEC_REM from the resources");
hr = E_FAIL;
goto Exit;
}
// Allocate memory for the demoted string.
pszaRem1MultiByte = (PSTR) MemAlloc(lstrlenW(pszRem1) + 1);
if (!pszaRem1MultiByte)
{
TraceTag(ttidNWClientCfg, "ERROR: Failed to alloc memory for demoted string");
hr = E_OUTOFMEMORY;
goto Exit;
}
// Demote the loaded string to multibyte (single char)
WideCharToMultiByte(
CP_ACP, // ANSI code page
0, // flags for non-mapped character action
pszRem1, // source string
-1, // source string is NULL terminated
pszaRem1MultiByte, // destination string (multibyte)
lstrlenW(pszRem1) + 1, // size of destination string
NULL, // default char on non-mapped char
NULL); // return for default char mapping action
// Move the REM from the autoexec.nt
//
fResult = FMoveSzToEndOfFile(pszAutoPath, pszaRem1MultiByte);
if (!fResult)
{
// Traced in called function.
hr = E_FAIL;
goto Exit;
}
// Move the line that loads nw16
//
fResult = FMoveSzToEndOfFile(pszAutoPath, "lh %SystemRoot%\\system32\\nw16");
if (!fResult)
{
// Traced in called function.
hr = E_FAIL;
goto Exit;
}
// Move the line that loads vwipxspx
//
fResult = FMoveSzToEndOfFile(pszAutoPath, "lh %SystemRoot%\\system32\\vwipxspx");
if (!fResult)
{
// Traced in called function.
hr = E_FAIL;
goto Exit;
}
Exit:
MemFree(pszaRem1MultiByte);
TraceTag(ttidNWClientCfgFn, "<< HrMungeAutoexecNT");
TraceError("HrMungeAutoexecNT", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrAddNetWareToWOWKnownList
//
// Purpose: Add the netware.drv to the WOW "known DLLS" list.
//
// Arguments:
// (none)
//
// Returns: S_OK or valid Win32 error code.
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
HRESULT HrAddNetWareToWOWKnownList()
{
HRESULT hr = S_OK;
TraceTag(ttidNWClientCfgFn, ">> HrAddNetWareToWOWKnownList");
// Call the cool new AddString... function
//
hr = HrRegAddStringToSz(
L"netware.drv",
HKEY_LOCAL_MACHINE,
L"System\\CurrentControlSet\\Control\\WOW",
L"KnownDLLS",
L' ',
STRING_FLAG_ENSURE_AT_END,
0);
TraceTag(ttidNWClientCfgFn, "<< HrAddNetWareToWOWKnownList");
TraceError("HrAddNetWareToWOWKnownList", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRemoveNetWareFromWOWKnownList
//
// Purpose: Add the netware.drv to the WOW "known DLLS" list.
//
// Arguments:
// (none)
//
// Returns: S_OK or valid Win32 error code.
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
HRESULT HrRemoveNetWareFromWOWKnownList()
{
HRESULT hr = S_OK;
TraceTag(ttidNWClientCfgFn, ">> HrRemoveNetWareFromWOWKnownList");
// Call the cool new AddString... function
//
hr = HrRegRemoveStringFromSz(
L"netware.drv",
HKEY_LOCAL_MACHINE,
L"System\\CurrentControlSet\\Control\\WOW",
L"KnownDLLS",
L' ',
STRING_FLAG_REMOVE_SINGLE);
TraceTag(ttidNWClientCfgFn, "<< HrRemoveNetWareFromWOWKnownList");
TraceError("HrRemoveNetWareFromWOWKnownList", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrUpdateLanmanSharedDrivesValue
//
// Purpose: If the LanmanServer service exists, make sure that they have the
// EnableSharedNetDrives value turned on.
//
// Arguments:
// (none)
//
// Returns: S_OK or valid Win32 error code.
//
// Author: jeffspr 24 Jun 1997
//
// Notes:
//
HRESULT HrUpdateLanmanSharedDrivesValue()
{
HRESULT hr = S_OK;
const DWORD c_dwESNDValue = 1;
HKEY hkeyLMSP = NULL;
SERVER_INFO_1540 si1540 = {0};
NET_API_STATUS nas = ERROR_SUCCESS;
DWORD dwDisposition = 0;
TraceTag(ttidNWClientCfgFn, ">> HrUpdateLanmanSharedDrivesValue");
// Open the LanmanServer parameters key, if it exists. If it doesn't exist,
// it will still return S_OK, but the hkey will still be NULL.
//
hr = HrRegCreateKeyEx(
HKEY_LOCAL_MACHINE,
L"System\\CurrentControlSet\\Services\\LanmanServer\\Parameters",
REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE, // samDesired
NULL,
&hkeyLMSP,
&dwDisposition);
if (FAILED(hr))
{
TraceTag(ttidNWClientCfgFn, "Failed to create/open the "
"LanmanServer\\Parameters key");
goto Exit;
}
Assert(hkeyLMSP);
hr = HrRegSetDword(
hkeyLMSP,
L"EnableSharedNetDrives",
c_dwESNDValue);
if (FAILED(hr))
{
TraceTag(ttidNWClientCfgFn, "Failed to set the EnabledSharedNetDrives value in "
"HrUpdateLanmanSharedDrivesValue()");
goto Exit;
}
// Call the NetServerSetInfo with the Enable Shared Net Drives info (1540).
// This will allow this info to be set dynamically (so as not to require a
// restart of the "Server" service.
//
si1540.sv1540_enablesharednetdrives = TRUE;
// Set the server info for the EnableSharedDrives value. This will cause it to
// take effect if the service is running (and will do nothing if it is not).
//
nas = NetServerSetInfo(NULL, 1540, (LPBYTE) &si1540, NULL);
if (nas != NERR_Success)
{
// It's actually OK if this fails in one condition (0x842), because
// it WILL fail if the server service That's not a problem, because
// the value that I set in the registry above will be picked up the
// next time the server service starts.
//
// OK, cheesy, but I don't know the define, I just know that this is the
// right return code for our ignorable failure.
//
if (nas != 0x842)
{
AssertSz(nas == 0x842, "NetServerSetInfo failed for a reason other "
"than the service not running (which would have been ok)");
}
}
Exit:
// Close the hkey, if it's open
RegSafeCloseKey(hkeyLMSP);
TraceTag(ttidNWClientCfgFn, "<< HrUpdateLanmanSharedDrivesValue");
TraceError("HrUpdateLanmanSharedDrivesValue()", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRenameNWDocFiles
//
// Purpose: On the server install, rename the nwdocgw.* files, since
// whether we're on CSNW or GSNW, the files are always called
// nwdoc.*
//
// Arguments:
// (none)
//
// Returns:
//
// Author: jeffspr 13 Jul 1997
//
// Notes:
//
HRESULT HrRenameNWDocFiles()
{
HRESULT hr = S_OK;
WCHAR szWindowsDir[MAX_PATH+1];
WCHAR szSourceName[MAX_PATH+1];
WCHAR szTargetName[MAX_PATH+1];
// Get the windows directory
if (GetSystemWindowsDirectory(szWindowsDir, MAX_PATH) == 0)
{
TraceLastWin32Error("HrRenameNWDocFiles - Call to GetSystemWindowsDirectory");
hr = HrFromLastWin32Error();
goto Exit;
}
// Build the path for the first rename
//
wsprintfW(szSourceName, L"%s\\system32\\%s", szWindowsDir, c_szNwDocGWHelpName);
wsprintfW(szTargetName, L"%s\\system32\\%s", szWindowsDir, c_szNwDocHelpName);
// Rename the .HLP file. If this fails, no big deal.
//
if (!MoveFileEx(szSourceName, szTargetName, MOVEFILE_REPLACE_EXISTING))
{
// For debugging only.
//
DWORD dwLastError = GetLastError();
}
// Build the path for the second rename
//
wsprintfW(szSourceName, L"%s\\system32\\%s", szWindowsDir, c_szNwDocGWCNTName);
wsprintfW(szTargetName, L"%s\\system32\\%s", szWindowsDir, c_szNwDocCNTName);
// Rename the .CNT file. If this fails, no big deal.
//
if (!MoveFileEx(szSourceName, szTargetName, MOVEFILE_REPLACE_EXISTING))
{
// For debugging only.
//
DWORD dwLastError = GetLastError();
}
Exit:
return hr;
}