859 lines
24 KiB
C++
859 lines
24 KiB
C++
|
//
|
||
|
// N W C L I O B J . C P P
|
||
|
//
|
||
|
// Implementation of the CNWClient notify object model
|
||
|
//
|
||
|
|
||
|
#include "pch.h"
|
||
|
#pragma hdrstop
|
||
|
#include "ncerror.h"
|
||
|
#include "ncperms.h"
|
||
|
#include "ncreg.h"
|
||
|
#include "ncsetup.h"
|
||
|
#include "ncsvc.h"
|
||
|
#include "nwcliobj.h"
|
||
|
|
||
|
#include <ncshell.h>
|
||
|
|
||
|
extern const WCHAR c_szAfNWCWorkstationParameters[];
|
||
|
extern const WCHAR c_szAfNWCWorkstationShares[];
|
||
|
extern const WCHAR c_szAfNWCWorkstationDrives[];
|
||
|
extern const WCHAR c_szInfId_MS_NWIPX[];
|
||
|
extern const WCHAR c_szInfId_MS_Server[];
|
||
|
|
||
|
//---[ Constants ]-------------------------------------------------------------
|
||
|
|
||
|
static const WCHAR c_szNWClientParamPath[] = L"System\\CurrentControlSet\\Services\\NWCWorkstation\\Parameters";
|
||
|
static const WCHAR c_szNWClientSharesPath[] = L"System\\CurrentControlSet\\Services\\NWCWorkstation\\Shares";
|
||
|
static const WCHAR c_szNWClientDrivesPath[] = L"System\\CurrentControlSet\\Services\\NWCWorkstation\\Drives";
|
||
|
static const WCHAR c_szLMServerParamPath[] = L"System\\CurrentControlSet\\Services\\LanmanServer\\Parameters";
|
||
|
static const WCHAR c_szLMServerLinkagePath[] = L"System\\CurrentControlSet\\Services\\LanmanServer\\Linkage";
|
||
|
static const WCHAR c_szEnableSharedNetDrives[] = L"EnableSharedNetDrives";
|
||
|
static const WCHAR c_szOtherDependencies[] = L"OtherDependencies";
|
||
|
static const WCHAR c_szGWEnabledValue[] = L"GatewayEnabled";
|
||
|
|
||
|
extern const WCHAR c_szSvcLmServer[]; // L"LanmanServer";
|
||
|
extern const WCHAR c_szSvcNWCWorkstation[]; // L"NWCWorkstation";
|
||
|
|
||
|
HRESULT HrRefreshEntireNetwork();
|
||
|
HRESULT HrGetEntireNetworkPidl(LPITEMIDLIST *ppidlFolder);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Constructor
|
||
|
//
|
||
|
|
||
|
CNWClient::CNWClient()
|
||
|
{
|
||
|
// Initialize member variables.
|
||
|
m_pnc = NULL;
|
||
|
m_pncc = NULL;
|
||
|
m_eInstallAction = eActUnknown;
|
||
|
m_hlibConfig = NULL;
|
||
|
m_fUpgrade = FALSE;
|
||
|
|
||
|
// Get the product flavor (PF_WORKSTATION or PF_SERVER). Use this
|
||
|
// to decide whether or not we need to install the "server" component.
|
||
|
//
|
||
|
GetProductFlavor(NULL, &m_pf);
|
||
|
}
|
||
|
|
||
|
CNWClient::~CNWClient()
|
||
|
{
|
||
|
ReleaseObj(m_pncc);
|
||
|
ReleaseObj(m_pnc);
|
||
|
|
||
|
// Release KEY handles here.
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// INetCfgNotify
|
||
|
//
|
||
|
|
||
|
STDMETHODIMP CNWClient::Initialize( INetCfgComponent * pnccItem,
|
||
|
INetCfg* pnc,
|
||
|
BOOL fInstalling)
|
||
|
{
|
||
|
Validate_INetCfgNotify_Initialize(pnccItem, pnc, fInstalling);
|
||
|
|
||
|
TraceTag(ttidNWClientCfg, "CNWClient::Initialize");
|
||
|
|
||
|
m_pncc = pnccItem;
|
||
|
m_pnc = pnc;
|
||
|
|
||
|
AssertSz(m_pncc, "m_pncc NULL in CNWClient::Initialize");
|
||
|
AssertSz(m_pnc, "m_pnc NULL in CNWClient::Initialize");
|
||
|
|
||
|
// Addref the config objects
|
||
|
//
|
||
|
AddRefObj(m_pncc);
|
||
|
AddRefObj(m_pnc);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CNWClient::HrRestoreRegistry
|
||
|
//
|
||
|
// Purpose: Restores the contents of the registry for this component
|
||
|
//
|
||
|
// Arguments:
|
||
|
// (none)
|
||
|
//
|
||
|
// Returns: Win32 error if failed, otherwise S_OK
|
||
|
//
|
||
|
// Author: jeffspr 13 Aug 1997
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
HRESULT CNWClient::HrRestoreRegistry()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
HKEY hkey = NULL;
|
||
|
TOKEN_PRIVILEGES * ptpRestore = NULL;
|
||
|
DWORD dwDisp = 0;
|
||
|
static const WCHAR c_szSvcDLLName[] = L"%SystemRoot%\\System32\\nwwks.dll";
|
||
|
static const WCHAR c_szServiceDll[] = L"ServiceDll";
|
||
|
|
||
|
TraceTag(ttidNWClientCfg, "CNWClient::HrRestoreRegistry");
|
||
|
|
||
|
if (!m_strParamsRestoreFile.empty() ||
|
||
|
!m_strDrivesRestoreFile.empty() ||
|
||
|
!m_strSharesRestoreFile.empty())
|
||
|
{
|
||
|
hr = HrEnableAllPrivileges(&ptpRestore);
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr) && !m_strParamsRestoreFile.empty())
|
||
|
{
|
||
|
// Ensure key is there by creating it
|
||
|
hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szNWClientParamPath, 0,
|
||
|
KEY_ALL_ACCESS, NULL, &hkey, &dwDisp);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = HrRegRestoreKey(hkey, m_strParamsRestoreFile.c_str(), 0);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::HrRestoreRegistry - HrRestoreRegistry for "
|
||
|
"Parameters", hr);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Bug 182442. HrRegRestoreKey above overwrites the ServiceDll value added
|
||
|
// from the inf file. So, we manually save it.
|
||
|
//
|
||
|
|
||
|
hr = HrRegSetValueEx(hkey, c_szServiceDll, REG_EXPAND_SZ,
|
||
|
(const BYTE *)c_szSvcDLLName,
|
||
|
(wcslen(c_szSvcDLLName) + 1) * sizeof(WCHAR));
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::HrRestoreRegistry - HrRestoreRegistry for "
|
||
|
"ServiceDll", hr);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hkey);
|
||
|
hkey = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!m_strSharesRestoreFile.empty())
|
||
|
{
|
||
|
// Ensure key is there by creating it
|
||
|
hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szNWClientSharesPath, 0,
|
||
|
KEY_ALL_ACCESS, NULL, &hkey, &dwDisp);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = HrRegRestoreKey(hkey, m_strSharesRestoreFile.c_str(), 0);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::HrRestoreRegistry - HrRestoreRegistry for "
|
||
|
"Shares", hr);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hkey);
|
||
|
hkey = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!m_strDrivesRestoreFile.empty())
|
||
|
{
|
||
|
// Ensure key is there by creating it
|
||
|
hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szNWClientDrivesPath, 0,
|
||
|
KEY_ALL_ACCESS, NULL, &hkey, &dwDisp);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = HrRegRestoreKey(hkey, m_strDrivesRestoreFile.c_str(), 0);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::HrRestoreRegistry - HrRestoreRegistry for "
|
||
|
"Drives", hr);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hkey);
|
||
|
hkey = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ptpRestore)
|
||
|
{
|
||
|
hr = HrRestorePrivileges(ptpRestore);
|
||
|
|
||
|
delete [] reinterpret_cast<BYTE *>(ptpRestore);
|
||
|
}
|
||
|
|
||
|
TraceError("CNWClient::HrRestoreRegistry", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
static const WCHAR c_szDefaultLocation[] = L"DefaultLocation";
|
||
|
static const WCHAR c_szDefaultScriptOptions[] = L"DefaultScriptOptions";
|
||
|
|
||
|
HRESULT CNWClient::HrWriteAnswerFileParams()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
TraceTag(ttidNWClientCfg, "CNWClient::HrWriteAnswerFileParams");
|
||
|
|
||
|
// Don't do anything if we don't have anything to write to the
|
||
|
// registry
|
||
|
if (!m_strDefaultLocation.empty() || (m_dwLogonScript != 0xFFFFFFFF))
|
||
|
{
|
||
|
HKEY hkey;
|
||
|
DWORD dwDisp;
|
||
|
|
||
|
// Ensure key is there by creating it
|
||
|
hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szNWClientParamPath, 0,
|
||
|
KEY_ALL_ACCESS, NULL, &hkey, &dwDisp);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
if (!m_strDefaultLocation.empty())
|
||
|
{
|
||
|
hr = HrRegSetString(hkey, c_szDefaultLocation,
|
||
|
m_strDefaultLocation);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::HrWriteAnswerFileParams - Couldn't"
|
||
|
" set DefaultLocation", hr);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (m_dwLogonScript != 0xFFFFFFFF)
|
||
|
{
|
||
|
// 0x3 is combination of the following:
|
||
|
//
|
||
|
// #define NW_LOGONSCRIPT_DISABLED 0x00000000
|
||
|
// #define NW_LOGONSCRIPT_ENABLED 0x00000001
|
||
|
// #define NW_LOGONSCRIPT_4X_ENABLED 0x00000002
|
||
|
//
|
||
|
hr = HrRegSetDword(hkey, c_szDefaultScriptOptions,
|
||
|
m_dwLogonScript ? 0x3 : 0x0);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::HrWriteAnswerFileParams - Couldn't"
|
||
|
" set DefaultLocation", hr);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hkey);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TraceError("CNWClient::HrWriteAnswerFileParams", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
static const WCHAR c_szPreferredServer[] = L"PreferredServer";
|
||
|
static const WCHAR c_szDefaultTree[] = L"DefaultTree";
|
||
|
static const WCHAR c_szDefaultContext[] = L"DefaultContext";
|
||
|
static const WCHAR c_szLogonScript[] = L"LogonScript";
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CNWClient::HrProcessAnswerFile
|
||
|
//
|
||
|
// Purpose: Handles necessary processing of contents of the answer file.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// pszAnswerFile [in] Filename of answer file for upgrade.
|
||
|
// pszAnswerSection [in] Comma-separated list of sections in the
|
||
|
// file appropriate to this component.
|
||
|
//
|
||
|
// Returns: S_OK if successful, setup API error otherwise.
|
||
|
//
|
||
|
// Author: jeffspr 8 May 1997
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
HRESULT CNWClient::HrProcessAnswerFile( PCWSTR pszAnswerFile,
|
||
|
PCWSTR pszAnswerSection)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
CSetupInfFile csif;
|
||
|
|
||
|
TraceTag(ttidNWClientCfg, "CNWClient::HrProcessAnswerFile");
|
||
|
|
||
|
// Open the answer file.
|
||
|
hr = csif.HrOpen(pszAnswerFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
// Restore portions of the registry based on file names from the answer
|
||
|
// file
|
||
|
|
||
|
// Get restore file for "Parameters" key
|
||
|
hr = csif.HrGetString(pszAnswerSection, c_szAfNWCWorkstationParameters,
|
||
|
&m_strParamsRestoreFile);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::HrProcessAnswerFile - Error restoring "
|
||
|
"Parameters key", hr);
|
||
|
|
||
|
// oh well, just continue
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
// Get restore file for "Shares" key
|
||
|
hr = csif.HrGetString(pszAnswerSection, c_szAfNWCWorkstationShares,
|
||
|
&m_strSharesRestoreFile);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::HrProcessAnswerFile - Error restoring "
|
||
|
"Shares key", hr);
|
||
|
|
||
|
// oh well, just continue
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
// Get restore file for "Drives" key
|
||
|
hr = csif.HrGetString(pszAnswerSection, c_szAfNWCWorkstationDrives,
|
||
|
&m_strDrivesRestoreFile);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::HrProcessAnswerFile - Error restoring "
|
||
|
"Drives key", hr);
|
||
|
|
||
|
// oh well, just continue
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Read answer file parameters (these are all optional so no errors are
|
||
|
// saved)
|
||
|
//
|
||
|
|
||
|
TraceTag(ttidNWClientCfg, "Reading PreferredServer from answer file");
|
||
|
|
||
|
// Read contents of PreferredServer key.
|
||
|
if (FAILED(csif.HrGetString(pszAnswerSection, c_szPreferredServer,
|
||
|
&m_strDefaultLocation)))
|
||
|
{
|
||
|
// Couldn't read PreferredServer key, so we must assume that the other
|
||
|
// two values are present
|
||
|
tstring strDefaultTree;
|
||
|
tstring strDefaultContext;
|
||
|
|
||
|
TraceTag(ttidNWClientCfg, "PreferredServer not found so trying "
|
||
|
"DefaultTree and DefaultContext instead");
|
||
|
|
||
|
// Read contents of DefaultTree key.
|
||
|
if (SUCCEEDED(csif.HrGetString(pszAnswerSection, c_szDefaultTree,
|
||
|
&strDefaultTree)))
|
||
|
{
|
||
|
TraceTag(ttidNWClientCfg, "Got DefaultTree ok: %S",
|
||
|
strDefaultTree.c_str());
|
||
|
|
||
|
// Read contents of DefaultContext key.
|
||
|
hr = csif.HrGetString(pszAnswerSection, c_szDefaultContext,
|
||
|
&strDefaultContext);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
TraceTag(ttidNWClientCfg, "Got DefaultContext ok: %S",
|
||
|
strDefaultContext.c_str());
|
||
|
|
||
|
// Munge the DefaultLocation value with the DefaultTree and
|
||
|
// DefaultContext values read from the answer file
|
||
|
|
||
|
m_strDefaultLocation = L"*";
|
||
|
m_strDefaultLocation += strDefaultTree;
|
||
|
m_strDefaultLocation += L"\\";
|
||
|
m_strDefaultLocation += strDefaultContext;
|
||
|
|
||
|
TraceTag(ttidNWClientCfg, "DefaultLocation is: %S",
|
||
|
m_strDefaultLocation.c_str());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TraceError("CNWClient::HrProcessAnswerFile - error reading "
|
||
|
"DefaultContext", hr);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TraceTag(ttidNWClientCfg, "DefaultLocation is: %S",
|
||
|
m_strDefaultLocation.c_str());
|
||
|
}
|
||
|
|
||
|
// Init to impossible value so we know whether we read it or not
|
||
|
m_dwLogonScript = 0xFFFFFFFF;
|
||
|
|
||
|
// Read contents of LogonScript key.
|
||
|
(VOID) csif.HrGetStringAsBool(pszAnswerSection, c_szLogonScript,
|
||
|
reinterpret_cast<BOOL *>(&m_dwLogonScript));
|
||
|
|
||
|
TraceTag(ttidNWClientCfg, "LogonScript is: %ld", m_dwLogonScript);
|
||
|
|
||
|
Exit:
|
||
|
TraceError("CNWClient::HrProcessAnswerFile", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNWClient::Upgrade(DWORD dwSetupFlags, DWORD dwUpgradeFromBuildNo)
|
||
|
{
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNWClient::ReadAnswerFile(PCWSTR pszAnswerFile,
|
||
|
PCWSTR pszAnswerSection)
|
||
|
{
|
||
|
Validate_INetCfgNotify_ReadAnswerFile(pszAnswerFile,
|
||
|
pszAnswerSection);
|
||
|
|
||
|
TraceTag(ttidNWClientCfg, "CNWClient::ReadAnswerFile");
|
||
|
|
||
|
m_eInstallAction = eActInstall;
|
||
|
|
||
|
// If we're not already installed, do the work.
|
||
|
//
|
||
|
if (pszAnswerFile && pszAnswerSection)
|
||
|
{
|
||
|
HRESULT hr = HrProcessAnswerFile(pszAnswerFile, pszAnswerSection);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::NetworkInstall - Answer file has errors. Defaulting "
|
||
|
"all information as if answer file did not exist.",
|
||
|
hr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNWClient::Install(DWORD dw)
|
||
|
{
|
||
|
Validate_INetCfgNotify_Install(dw);
|
||
|
|
||
|
TraceTag(ttidNWClientCfg, "CNWClient::Install");
|
||
|
|
||
|
m_eInstallAction = eActInstall;
|
||
|
|
||
|
// Install the NWLink sub-component
|
||
|
HRESULT hr = HrInstallComponentOboComponent(m_pnc, NULL,
|
||
|
GUID_DEVCLASS_NETTRANS,
|
||
|
c_szInfId_MS_NWIPX,
|
||
|
m_pncc,
|
||
|
NULL);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
// If we're NT Server, we DO need to install it, as what we're
|
||
|
// installing is GSNW, not CSNW (and therefore, since we're sharing
|
||
|
// resources, we need to use the server service)
|
||
|
//
|
||
|
if (PF_SERVER == m_pf)
|
||
|
{
|
||
|
NETWORK_INSTALL_PARAMS nip;
|
||
|
|
||
|
nip.dwSetupFlags = dw;
|
||
|
nip.dwUpgradeFromBuildNo = -1;
|
||
|
nip.pszAnswerFile = NULL;
|
||
|
nip.pszAnswerSection = NULL;
|
||
|
|
||
|
// Install Server
|
||
|
hr = HrInstallComponentOboComponent(m_pnc, &nip,
|
||
|
GUID_DEVCLASS_NETSERVICE,
|
||
|
c_szInfId_MS_Server,
|
||
|
m_pncc,
|
||
|
NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TraceError("CNWClient::Install", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNWClient::Removing()
|
||
|
{
|
||
|
TraceTag(ttidNWClientCfg, "CNWClient::Removing");
|
||
|
|
||
|
m_eInstallAction = eActRemove;
|
||
|
|
||
|
// Remove the NWLink service
|
||
|
//
|
||
|
HRESULT hr = HrRemoveComponentOboComponent(m_pnc,
|
||
|
GUID_DEVCLASS_NETTRANS,
|
||
|
c_szInfId_MS_NWIPX,
|
||
|
m_pncc);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
if (PF_SERVER == m_pf)
|
||
|
{
|
||
|
// Remove our reference of the Server service
|
||
|
//
|
||
|
hr = HrRemoveComponentOboComponent(m_pnc,
|
||
|
GUID_DEVCLASS_NETSERVICE,
|
||
|
c_szInfId_MS_Server,
|
||
|
m_pncc);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (hr == NETCFG_S_STILL_REFERENCED)
|
||
|
{
|
||
|
// If services are still in use, that's OK, I just needed to make
|
||
|
// sure that I released my reference.
|
||
|
//
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
Validate_INetCfgNotify_Removing_Return(hr);
|
||
|
|
||
|
TraceError("CNWClient::Removing()", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNWClient::Validate()
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNWClient::CancelChanges()
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNWClient::ApplyRegistryChanges()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
TraceTag(ttidNWClientCfg, "CNWClient::ApplyRegistryChanges");
|
||
|
|
||
|
if (m_eInstallAction == eActRemove)
|
||
|
{
|
||
|
hr = HrRemoveCodeFromOldINF();
|
||
|
}
|
||
|
else if (m_eInstallAction == eActInstall)
|
||
|
{
|
||
|
hr = HrRestoreRegistry();
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::ApplyRegistryChanges - HrRestoreRegistry non-fatal error",
|
||
|
hr);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
hr = HrWriteAnswerFileParams();
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::ApplyRegistryChanges - HrWriteAnswerFileParams "
|
||
|
"non-fatal error", hr);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
// If gateway is enabled, modify lanmanserver appropriately
|
||
|
// Ignore the return code other than to trace it.
|
||
|
//
|
||
|
hr = HrEnableGatewayIfNeeded();
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::ApplyRegistryChanges - HrEnableGatewayIfNeeded non-fatal error", hr);
|
||
|
}
|
||
|
|
||
|
hr = HrInstallCodeFromOldINF();
|
||
|
}
|
||
|
|
||
|
Validate_INetCfgNotify_Apply_Return(hr);
|
||
|
|
||
|
TraceError("CNWClient::ApplyRegistryChanges",
|
||
|
(hr == S_FALSE) ? S_OK : hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNWClient::ApplyPnpChanges (
|
||
|
INetCfgPnpReconfigCallback* pICallback)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = HrRefreshEntireNetwork();
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("CNWClient::ApplyPnpChanges - HrRefreshEntireNetwork"
|
||
|
"non-fatal error", hr);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
// GlennC can't do the work to make NW Client PnP so we're forced to
|
||
|
// prompt for a reboot for any change.
|
||
|
//
|
||
|
return NETCFG_S_REBOOT;
|
||
|
}
|
||
|
|
||
|
// Note -- Don't convert this to a constant. We need copies of it within the
|
||
|
// functions because ParseDisplayName actually mangles the string.
|
||
|
//
|
||
|
#define ENTIRE_NETWORK_PATH L"::{208D2C60-3AEA-1069-A2D7-08002B30309D}\\EntireNetwork"
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: HrGetEntireNetworkPidl
|
||
|
//
|
||
|
// Purpose: Get the pidl for "Entire Network". Used in places where we're
|
||
|
// not folder specific, but we still need to update folder
|
||
|
// entries.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// ppidlFolder [out] Return parameter for the folder pidl
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Author: anbrad 08 Jun 1999
|
||
|
// jeffspr 13 Jun 1998
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
HRESULT HrGetEntireNetworkPidl(LPITEMIDLIST *ppidlFolder)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
LPSHELLFOLDER pshf = NULL;
|
||
|
LPITEMIDLIST pidlFolder = NULL;
|
||
|
|
||
|
Assert(ppidlFolder);
|
||
|
|
||
|
WCHAR szEntireNetworkPath[] = ENTIRE_NETWORK_PATH;
|
||
|
|
||
|
// Get the desktop folder, so we can parse the display name and get
|
||
|
// the UI object of the connections folder
|
||
|
//
|
||
|
hr = SHGetDesktopFolder(&pshf);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
ULONG chEaten;
|
||
|
|
||
|
hr = pshf->ParseDisplayName(NULL, 0, (WCHAR *) szEntireNetworkPath,
|
||
|
&chEaten, &pidlFolder, NULL);
|
||
|
|
||
|
ReleaseObj(pshf);
|
||
|
}
|
||
|
|
||
|
// If succeeded, fill in the return param.
|
||
|
//
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
*ppidlFolder = pidlFolder;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// If we failed, then delete the pidl if we already got it.
|
||
|
//
|
||
|
if (pidlFolder)
|
||
|
SHFree(pidlFolder);
|
||
|
}
|
||
|
|
||
|
TraceHr(ttidNWClientCfg, FAL, hr, FALSE, "HrGetEntireNetworkPidl");
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: HrRefreshEntireNetwork
|
||
|
//
|
||
|
// Purpose: Update the "Entire Network" portion of the shell due to
|
||
|
// the addition of a new networking client (NWClient)
|
||
|
//
|
||
|
// Arguments:
|
||
|
// (none)
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Author: anbrad 08 Jun 1999
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
HRESULT HrRefreshEntireNetwork()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
HCURSOR hcWait = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
||
|
LPITEMIDLIST pidlFolder = NULL;;
|
||
|
|
||
|
hr = HrGetEntireNetworkPidl(&pidlFolder);
|
||
|
|
||
|
// If we now have a pidl, send the GenerateEvent to update the item
|
||
|
//
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
Assert(pidlFolder);
|
||
|
// SHCNE_UPDATEDIR?ITEM
|
||
|
GenerateEvent(SHCNE_UPDATEDIR, pidlFolder, NULL, NULL);
|
||
|
}
|
||
|
|
||
|
if (hcWait)
|
||
|
{
|
||
|
SetCursor(hcWait);
|
||
|
}
|
||
|
|
||
|
if (pidlFolder)
|
||
|
{
|
||
|
SHFree(pidlFolder);
|
||
|
}
|
||
|
|
||
|
TraceHr(ttidError, FAL, hr, FALSE, "HrRefreshEntireNetwork");
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: HrEnableGatewayIfNeeded
|
||
|
//
|
||
|
// Purpose: Update the Lanman dependencies, if appropriate (meaning if
|
||
|
// gateway is enabled).
|
||
|
//
|
||
|
// Arguments:
|
||
|
// (none)
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Author: jeffspr 19 Aug 1999
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
HRESULT CNWClient::HrEnableGatewayIfNeeded()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
HKEY hKey = NULL;
|
||
|
DWORD dwValue = 0;
|
||
|
CServiceManager sm;
|
||
|
CService svc;
|
||
|
|
||
|
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||
|
c_szNWClientParamPath,
|
||
|
KEY_READ,
|
||
|
&hKey);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
TraceError("Couldn't open NWClient param key", hr);
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
hr = HrRegQueryDword(hKey,
|
||
|
c_szGWEnabledValue,
|
||
|
&dwValue);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
if (hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
|
||
|
{
|
||
|
TraceError("Couldn't query the GWEnabled Value", hr);
|
||
|
goto Exit;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
dwValue = 0;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Normalize to bool
|
||
|
//
|
||
|
dwValue = !!dwValue;
|
||
|
}
|
||
|
|
||
|
RegSafeCloseKey(hKey);
|
||
|
hKey = NULL;
|
||
|
|
||
|
// If there are gateway services present, then add the dependencies
|
||
|
// to LanmanServer
|
||
|
//
|
||
|
if (dwValue > 0)
|
||
|
{
|
||
|
// Set the value in the registry for the server paramaters.
|
||
|
//
|
||
|
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||
|
c_szLMServerParamPath,
|
||
|
KEY_WRITE,
|
||
|
&hKey);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = HrRegSetDword(hKey,
|
||
|
c_szEnableSharedNetDrives,
|
||
|
dwValue);
|
||
|
|
||
|
RegSafeCloseKey(hKey);
|
||
|
hKey = NULL;
|
||
|
}
|
||
|
|
||
|
hr = sm.HrOpen();
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = sm.HrOpenService(&svc, c_szSvcLmServer, NO_LOCK);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
// Add dependency of NWC Workstation to Server
|
||
|
//
|
||
|
hr = sm.HrAddServiceDependency(c_szSvcLmServer,
|
||
|
c_szSvcNWCWorkstation);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||
|
c_szLMServerLinkagePath,
|
||
|
KEY_READ | KEY_WRITE,
|
||
|
&hKey);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
// Add the "OtherDependencies" to LanmanServer for legacy reasons
|
||
|
//
|
||
|
hr = HrRegAddStringToMultiSz(c_szSvcNWCWorkstation,
|
||
|
hKey,
|
||
|
NULL,
|
||
|
c_szOtherDependencies,
|
||
|
STRING_FLAG_ENSURE_AT_END | STRING_FLAG_DONT_MODIFY_IF_PRESENT,
|
||
|
0);
|
||
|
|
||
|
RegSafeCloseKey(hKey);
|
||
|
hKey = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TraceError("Failed to open LanmanServer service for dependency mods", hr);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TraceError("Failed to open service control manager", hr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Exit:
|
||
|
TraceHr(ttidNWClientCfg, FAL, hr, FALSE, "HrEnableGatewayIfNeeded");
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|