/**********************************************************************/ /** RemCfg.cpp : Implementation of CRemCfg **/ /** **/ /** Microsoft Windows/NT **/ /** Copyright(C) Microsoft Corporation, 1997 - 1999 **/ /**********************************************************************/ #include "stdafx.h" #include #include #define _PNP_POWER_ #include #define _USTRINGP_NO_UNICODE_STRING #include "ustringp.h" #include #include #include "ndisutil.h" #include "assert.h" #include "remras.h" #include "atlapp.h" #include "atltmp.h" #include "RemCfg.h" #include "netcfgp.h" // private INetCfg stuff #include "devguid.h" EXTERN_C const CLSID CLSID_CNetCfg; #include "update.h" ///////////////////////////////////////////////////////////////////////////// // CRemCfg BOOL s_fWriteIPConfig; BOOL s_fRestartRouter; RemCfgIPEntryList s_IPEntryList; extern DWORD g_dwTraceHandle; CRemCfg::~CRemCfg() { TraceSz("CRemCfg destructor"); DeleteCriticalSection(&m_critsec); } STDMETHODIMP CRemCfg::NotifyChanges(/* [in] */ BOOL fEnableRouter, /* [in] */ BYTE uPerformRouterDiscovery) { //Do nothing to fix bug 405636 and 345700 //But still keep to method for compatibility with old builds return S_OK; } /*!-------------------------------------------------------------------------- CRemCfg::SetRasEndpoints - Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP CRemCfg::SetRasEndpoints(DWORD dwFlags, DWORD dwTotalEndpoints, DWORD dwTotalIncoming, DWORD dwTotalOutgoing) { return E_NOTIMPL; } /*!-------------------------------------------------------------------------- CRemCfg::GetIpxVirtualNetworkNumber - Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP CRemCfg::GetIpxVirtualNetworkNumber(DWORD * pdwVNetworkNumber) { //$ TODO : need to add a try/catch block around the whole thing! INetCfg * pNetCfg = NULL; IIpxAdapterInfo * pIpxAdapterInfo = NULL; DWORD dwNetwork; HRESULT hr = S_OK; TraceSz("CRemCfg::GetIpxVirtualNetworkNumber entered"); if (pdwVNetworkNumber == NULL) return E_INVALIDARG; // Create the INetCfg, we're only reading so we don't // need to grab the write lock. hr = HrCreateAndInitializeINetCfg(NULL, /* &fInitCom, */ &pNetCfg, FALSE /* fGetWriteLock */, 0 /* cmsTimeout */, NULL /* swzClientDesc */, NULL /* ppszwClientDesc */); if (hr == S_OK) hr = HrGetIpxPrivateInterface(pNetCfg, &pIpxAdapterInfo); if (hr == S_OK) hr = pIpxAdapterInfo->GetVirtualNetworkNumber(&dwNetwork); if (hr == S_OK) *pdwVNetworkNumber = dwNetwork; if (pIpxAdapterInfo) pIpxAdapterInfo->Release(); if (pNetCfg) { HrUninitializeAndReleaseINetCfg(FALSE, /* fInitCom, */ pNetCfg, FALSE /* fHasLock */); pNetCfg = NULL; } TraceResult("CRemCfg::GetIpxVirtualNetworkNumber", hr); return hr; } /*!-------------------------------------------------------------------------- CRemCfg::SetIpxVirtualNetworkNumber - Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP CRemCfg::SetIpxVirtualNetworkNumber(DWORD dwVNetworkNumber) { //$ TODO : need to add a try/catch block around the whole thing! INetCfg * pNetCfg = NULL; IIpxAdapterInfo * pIpxAdapterInfo = NULL; HRESULT hr = S_OK; CString st; TraceSz("CRemCfg::SetIpxVirtualNetworkNumber entered"); try { st.LoadString(IDS_CLIENT_DESC); } catch(...) { hr = E_OUTOFMEMORY; }; // Create the INetCfg, we're only reading so we don't // need to grab the write lock. if (hr == S_OK) hr = HrCreateAndInitializeINetCfg(NULL, /* &fInitCom, */ &pNetCfg, TRUE /* fGetWriteLock */, 500 /* cmsTimeout */, (LPCTSTR) st /* swzClientDesc */, NULL /* ppszwClientDesc */); if (hr == S_OK) hr = HrGetIpxPrivateInterface(pNetCfg, &pIpxAdapterInfo); if (hr == S_OK) hr = pIpxAdapterInfo->SetVirtualNetworkNumber(dwVNetworkNumber); if (hr == S_OK) hr = pNetCfg->Apply(); if (pIpxAdapterInfo) pIpxAdapterInfo->Release(); if (pNetCfg) { HrUninitializeAndReleaseINetCfg(FALSE, /*fInitCom, */ pNetCfg, TRUE /* fHasLock */); pNetCfg = NULL; } TraceResult("CRemCfg::SetIpxVirtualNetworkNumber", hr); return hr; } /*!-------------------------------------------------------------------------- CRemCfg::GetIpInfo - Author: TongLu, KennT ---------------------------------------------------------------------------*/ STDMETHODIMP CRemCfg::GetIpInfo(const GUID *pGuid, REMOTE_RRAS_IPINFO * * ppInfo) { // TODO: Add your implementation code here INetCfg * pNetCfg = NULL; ITcpipProperties * pTcpipProperties = NULL; DWORD dwNetwork; HRESULT hr = S_OK; REMOTE_IPINFO *pRemoteIpInfo = NULL; REMOTE_RRAS_IPINFO * pRemoteRrasIpInfo = NULL; TraceSz("CRemCfg::GetIpInfo entered"); if ((pGuid == NULL) || (ppInfo == NULL)) return E_INVALIDARG; // Create the INetCfg, we're only reading so we don't // need to grab the write lock. hr = HrCreateAndInitializeINetCfg(NULL, /* &fInitCom, */ &pNetCfg, FALSE /* fGetWriteLock */, 0 /* cmsTimeout */, NULL /* swzClientDesc */, NULL /* ppszwClientDesc */); if (hr == S_OK) { hr = HrGetIpPrivateInterface(pNetCfg, &pTcpipProperties); TraceResult("HrGetIpPrivateInterface", hr); } if (hr == S_OK) { hr = pTcpipProperties->GetIpInfoForAdapter(pGuid, &pRemoteIpInfo); if (hr != S_OK) { OLECHAR szBuffer[256]; CHAR szOutBuffer[256]; StringFromGUID2(*pGuid, szBuffer, 256); wsprintfA(szOutBuffer, "ITcpipProperties::GetIpInfoForAdapter(%ls)", szBuffer); TraceResult(szOutBuffer, hr); } } if (hr == S_OK) { // Need to duplicate the functionality (best to keep the // memory allocations separate). // Need to allocate the memory for the structure pRemoteRrasIpInfo = (REMOTE_RRAS_IPINFO *) CoTaskMemAlloc(sizeof(REMOTE_RRAS_IPINFO)); if (!pRemoteRrasIpInfo) { hr = E_OUTOFMEMORY; goto Error; } ::ZeroMemory(pRemoteRrasIpInfo, sizeof(*pRemoteRrasIpInfo)); // Set dhcp pRemoteRrasIpInfo->dwEnableDhcp = pRemoteIpInfo->dwEnableDhcp; // pRemoteRrasIpInfo->dwEnableDhcp = FALSE; // Allocate space for each string and copy the data // pRemoteRrasIpInfo->bstrIpAddrList = // SysAllocString(_T("1.2.3.4,1.2.3.5")); // pRemoteRrasIpInfo->bstrSubnetMaskList = // SysAllocString(_T("255.0.0.0,255.0.0.0")); // pRemoteRrasIpInfo->bstrOptionList = // SysAllocString(_T("12.12.13.15,12.12.13.14")); pRemoteRrasIpInfo->bstrIpAddrList = SysAllocString(pRemoteIpInfo->pszwIpAddrList); if (!pRemoteRrasIpInfo->bstrIpAddrList && pRemoteIpInfo->pszwIpAddrList) { hr = E_OUTOFMEMORY; goto Error; } pRemoteRrasIpInfo->bstrSubnetMaskList = SysAllocString(pRemoteIpInfo->pszwSubnetMaskList); if (!pRemoteRrasIpInfo->bstrSubnetMaskList && pRemoteIpInfo->pszwSubnetMaskList) { hr = E_OUTOFMEMORY; goto Error; } pRemoteRrasIpInfo->bstrOptionList = SysAllocString(pRemoteIpInfo->pszwOptionList); if (!pRemoteRrasIpInfo->bstrOptionList && pRemoteIpInfo->pszwOptionList) { hr = E_OUTOFMEMORY; goto Error; } } Error: if (!SUCCEEDED(hr)) { if (pRemoteRrasIpInfo) { SysFreeString(pRemoteRrasIpInfo->bstrIpAddrList); SysFreeString(pRemoteRrasIpInfo->bstrSubnetMaskList); SysFreeString(pRemoteRrasIpInfo->bstrOptionList); CoTaskMemFree(pRemoteRrasIpInfo); } } else { *ppInfo = pRemoteRrasIpInfo; pRemoteRrasIpInfo = NULL; } if (pRemoteIpInfo) { CoTaskMemFree(pRemoteIpInfo); pRemoteIpInfo = NULL; } if (pTcpipProperties) pTcpipProperties->Release(); if (pNetCfg) { HrUninitializeAndReleaseINetCfg(FALSE, pNetCfg, FALSE /* fHasLock */); pNetCfg = NULL; } TraceResult("CRemCfg::GetIpInfo", hr); return hr; } /*!-------------------------------------------------------------------------- CRemCfg::SetIpInfo - Author: TongLu, KennT ---------------------------------------------------------------------------*/ STDMETHODIMP CRemCfg::SetIpInfo(const GUID *pGuid, REMOTE_RRAS_IPINFO * pIpInfo) { // TODO: Add your implementation code here INetCfg * pNetCfg = NULL; ITcpipProperties * pTcpipProperties = NULL; DWORD dwNetwork; HRESULT hr = S_OK; CString st; RemCfgIPEntry * pIpEntry = NULL; RtrCriticalSection cs(&m_critsec); TraceSz("CRemCfg::SetIpInfo entered"); if ((pGuid == NULL) || (pIpInfo == NULL)) { TraceResult("CRemCfg::SetIpInfo", E_INVALIDARG); return E_INVALIDARG; } try { st.LoadString(IDS_CLIENT_DESC); pIpEntry = new RemCfgIPEntry; pIpEntry->m_newIPInfo.pszwIpAddrList = NULL; pIpEntry->m_newIPInfo.pszwSubnetMaskList = NULL; pIpEntry->m_newIPInfo.pszwOptionList = NULL; } catch(...) { hr = E_OUTOFMEMORY; }; // Create the INetCfg, we're only reading so we don't // need to grab the write lock. if (hr == S_OK) hr = HrCreateAndInitializeINetCfg(NULL, &pNetCfg, TRUE /* fGetWriteLock */, 500 /* cmsTimeout */, (LPCTSTR) st /* swzClientDesc */, NULL /* ppszwClientDesc */); if (hr == S_OK) hr = HrGetIpPrivateInterface(pNetCfg, &pTcpipProperties); if (hr == S_OK) { pIpEntry->m_IPGuid = *pGuid; pIpEntry->m_newIPInfo.dwEnableDhcp = pIpInfo->dwEnableDhcp; pIpEntry->m_newIPInfo.pszwIpAddrList = StrDupW((LPWSTR) pIpInfo->bstrIpAddrList); pIpEntry->m_newIPInfo.pszwSubnetMaskList = StrDupW((LPWSTR) pIpInfo->bstrSubnetMaskList); pIpEntry->m_newIPInfo.pszwOptionList = StrDupW((LPWSTR) pIpInfo->bstrOptionList); hr = pTcpipProperties->SetIpInfoForAdapter(pGuid, &(pIpEntry->m_newIPInfo)); } if (hr == S_OK) { // Add this to the list of OK IP address changes s_IPEntryList.Add(pIpEntry); pIpEntry = NULL; s_fWriteIPConfig = TRUE; } // this now gets done in CommitIPInfo // if (hr == S_OK) // hr = pNetCfg->Apply(); //Error: if (pTcpipProperties) pTcpipProperties->Release(); if (pIpEntry) { delete pIpEntry->m_newIPInfo.pszwIpAddrList; delete pIpEntry->m_newIPInfo.pszwSubnetMaskList; delete pIpEntry->m_newIPInfo.pszwOptionList; delete pIpEntry; } if (pNetCfg) { HrUninitializeAndReleaseINetCfg(FALSE, pNetCfg, TRUE /* fHasLock */); pNetCfg = NULL; } TraceResult("CRemCfg::SetIpInfo", hr); return hr; } //+--------------------------------------------------------------------------- // // Member: HrCleanRouterManagerEntries // // Purpose: Remove all Router Manager entries from the registry. // // Arguments: // // Returns: // // Author: MikeG (a-migall) 6 Nov 1998 // // Notes: // HRESULT HrCleanRouterManagerEntries() { // Open a connection to the registry key so we can "clean" // the registry entries before an install/update to ensure // that we can start with a "clean" state. CRegKey rk; long lRes = rk.Open(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Services\\RemoteAccess\\RouterManagers")); Assert(rk.m_hKey != NULL); HRESULT hr = S_OK; if (lRes == ERROR_FILE_NOT_FOUND) // if key doesn't exist, exit... return hr; if (lRes != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lRes); TraceError ("HrCleanRouterManagerEntries", hr); return hr; } // Eliminate the IP transport subkey. lRes = rk.DeleteSubKey(_T("Ip")); if (lRes > ERROR_FILE_NOT_FOUND) { hr = HRESULT_FROM_WIN32(lRes); TraceError ("HrCleanRouterManagerEntries", hr); return hr; } // Eliminate the IPX transport subkey. lRes = rk.DeleteSubKey(_T("Ipx")); if (lRes > ERROR_FILE_NOT_FOUND) hr = HRESULT_FROM_WIN32(lRes); TraceError ("HrCleanRouterManagerEntries", hr); return hr; } //+--------------------------------------------------------------------------- // // Member: RecurseDeleteKey // // Purpose: Delete a named registry key and all of its subkeys. // // Arguments: // // Returns: // // Author: MikeG (a-migall) 6 Nov 1998 // // Notes: Shamelessly stolen from Kenn's code in ...\tfscore\tregkey.h. // long RecurseDeleteKey( IN CRegKey &rk, IN LPCTSTR lpszKey) { Assert(!::IsBadReadPtr(&rk, sizeof(CRegKey))); Assert(rk.m_hKey != NULL); Assert(!::IsBadStringPtr(lpszKey, ::lstrlen(lpszKey))); CRegKey key; long lRes = key.Open(HKEY(rk), lpszKey); if (lRes != ERROR_SUCCESS) return lRes; FILETIME time; TCHAR szBuffer[256]; DWORD dwSize = 256; while (::RegEnumKeyEx(HKEY(key), 0, szBuffer, &dwSize, NULL, NULL, NULL, &time) == ERROR_SUCCESS) { lRes = RecurseDeleteKey(key, szBuffer); if (lRes != ERROR_SUCCESS) return lRes; dwSize = 256; } key.Close(); return rk.DeleteSubKey(lpszKey); } //+--------------------------------------------------------------------------- // // Member: HrCleanRouterInterfacesEntries // // Purpose: Remove all Router Interface entries from the registry. // // Arguments: // // Returns: // // Author: MikeG (a-migall) 6 Nov 1998 // // Notes: // HRESULT HrCleanRouterInterfacesEntries() { // Open a connection to the registry key so we can "clean" the // registry entries before an install/update to ensure that we // can start with a "clean" state. CRegKey rk; long lRes = rk.Open(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Services\\RemoteAccess\\Interfaces")); Assert(rk.m_hKey != NULL); HRESULT hr = S_OK; if (lRes == ERROR_FILE_NOT_FOUND) // if key doesn't exist, exit... return hr; if (lRes != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lRes); TraceError ("HrCleanRouterInterfacesEntries", hr); return hr; } // Determine how many interfaces have been defined. DWORD dwSubKeyCnt = 0; lRes = ::RegQueryInfoKey(HKEY(rk), // handle to key to query NULL, // address of buffer for class string NULL, // address of size of class string buffer NULL, // reserved... &dwSubKeyCnt, // address of buffer for number of subkeys NULL, // address of buffer for longest subkey name length NULL, // address of buffer for longest class string length NULL, // address of buffer for number of value entries NULL, // address of buffer for longest value name length NULL, // address of buffer for longest value data length NULL, // address of buffer for security descriptor length NULL); // address of buffer for last write time if (lRes != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lRes); TraceError ("HrCleanRouterInterfacesEntries", hr); return hr; } // Eliminate each of the subkeys. CString st; DWORD dwStrSize = 256; LPTSTR pszKeyName = st.GetBuffer(dwStrSize); // while (dwSubKeyCnt >= 0) while (TRUE) // change from above to TRUE, and lRes from the API will cause loop to end { // Get the name of the subkey to be deleted. lRes = ::RegEnumKeyEx(HKEY(rk), // handle to key to enumerate --dwSubKeyCnt, // index of subkey to enumerate pszKeyName, // address of buffer for subkey name &dwStrSize, // address for size of subkey buffer NULL, // reserved... NULL, // address of buffer for class string NULL, // address for size of class buffer NULL); // address for time key last written to if (lRes != ERROR_SUCCESS) { if ((lRes == ERROR_FILE_NOT_FOUND) || (lRes == ERROR_NO_MORE_ITEMS)) { lRes = 0; // we've run out of keys; so, we can successfuly exit. } break; } // Delete the key and all of its children. lRes = RecurseDeleteKey(rk, pszKeyName); if (lRes > ERROR_FILE_NOT_FOUND) break; // Cleanup for next pass. dwStrSize = 256; ::ZeroMemory(pszKeyName, (dwStrSize*sizeof(TCHAR))); } st.ReleaseBuffer(); hr = HRESULT_FROM_WIN32(lRes); TraceError ("HrCleanRouterInterfacesEntries", hr); return hr; } STDMETHODIMP CRemCfg::UpgradeRouterConfig() { HRESULT hr = S_OK; INetCfg * pNetCfg = NULL; TraceSz("CRemCfg::UpgradeRouterConfig entered"); try { // This is a two-step process CSteelhead update; CString st; st.LoadString(IDS_CLIENT_DESC); // First get the INetCfg hr = HrCreateAndInitializeINetCfg(NULL, /* &fInitCom, */ &pNetCfg, FALSE /* fGetWriteLock */, 500 /* cmsTimeout */, (LPCTSTR) st /* swzClientDesc */, NULL /* ppszwClientDesc */); if (hr == S_OK) { update.Initialize(pNetCfg); hr = update.HrFindOtherComponents(); } if (hr == S_OK) { // Delete all previous router configs so we can get back // to a "clean" install point. hr = HrCleanRouterManagerEntries(); Assert(SUCCEEDED(hr)); hr = HrCleanRouterInterfacesEntries(); Assert(SUCCEEDED(hr)); // Now create the router config info. hr = update.HrUpdateRouterConfiguration(); Assert(SUCCEEDED(hr)); update.ReleaseOtherComponents(); RegFlushKey(HKEY_LOCAL_MACHINE); } } catch(...) { hr = E_FAIL; } if (pNetCfg) { HrUninitializeAndReleaseINetCfg(FALSE, /* fInitCom, */ pNetCfg, FALSE /* fHasLock */); pNetCfg = NULL; } TraceResult("CRemCfg::UpgradeRouterConfig", hr); return hr; } STDMETHODIMP CRemCfg::SetUserConfig(LPCOLESTR pszService, LPCOLESTR pszNewGroup) { DWORD err; HRESULT hr = S_OK; try { err = SvchostChangeSvchostGroup(pszService, pszNewGroup); hr = HRESULT_FROM_WIN32(err); } catch(...) { hr = E_OUTOFMEMORY; } TraceResult("CRemCfg::SetUserConfig", hr); return hr; } /*!-------------------------------------------------------------------------- CRemCfg::RestartRouter Implementation of IRemoteRouterRestart::RestartRouter Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP CRemCfg::RestartRouter(DWORD dwFlags) { HRESULT hr = S_OK; try { // the router will be restarted when remrras.exe shuts down // ------------------------------------------------------------ s_fRestartRouter = TRUE; } catch(...) { hr = E_OUTOFMEMORY; } return hr; } HRESULT CommitIPInfo() { // TODO: Add your implementation code here INetCfg * pNetCfg = NULL; ITcpipProperties * pTcpipProperties = NULL; DWORD dwNetwork; HRESULT hr = S_OK; CString st; WCHAR swzGuid[256]; TraceSz("CRemCfg::CommitIpInfo entered"); try { st.LoadString(IDS_CLIENT_DESC); } catch(...) { hr = E_OUTOFMEMORY; }; // Create the INetCfg, we're only reading so we don't // need to grab the write lock. if (hr == S_OK) hr = HrCreateAndInitializeINetCfg(NULL, &pNetCfg, TRUE /* fGetWriteLock */, 500 /* cmsTimeout */, (LPCTSTR) st /* swzClientDesc */, NULL /* ppszwClientDesc */); if (hr == S_OK) hr = HrGetIpPrivateInterface(pNetCfg, &pTcpipProperties); if (hr == S_OK) { RemCfgIPEntry * pIpEntry = NULL; for (int i=0; iSetIpInfoForAdapter( &(pIpEntry->m_IPGuid), &(pIpEntry->m_newIPInfo)); StringFromGUID2(pIpEntry->m_IPGuid, swzGuid, 128); TracePrintf(g_dwTraceHandle, _T("Setting IP info for %ls returned 0x%08lx"), swzGuid, hr); TracePrintf(g_dwTraceHandle, _T("DHCP Enabled : %d"), pIpEntry->m_newIPInfo.dwEnableDhcp); if (pIpEntry->m_newIPInfo.pszwIpAddrList) TracePrintf(g_dwTraceHandle, _T(" IP Address : %ls"), pIpEntry->m_newIPInfo.pszwIpAddrList); if (pIpEntry->m_newIPInfo.pszwSubnetMaskList) TracePrintf(g_dwTraceHandle, _T(" Subnet masks : %ls"), pIpEntry->m_newIPInfo.pszwSubnetMaskList); if (pIpEntry->m_newIPInfo.pszwOptionList) TracePrintf(g_dwTraceHandle, _T(" Gateway List : %ls"), pIpEntry->m_newIPInfo.pszwOptionList); } } if (hr == S_OK) { hr = pNetCfg->Apply(); TraceResult("CRemCfg::CommitIpInfo calling Apply", hr); } if (hr == S_OK) { // Release all memory for (int i=0; im_newIPInfo.pszwIpAddrList; delete pIpEntry->m_newIPInfo.pszwSubnetMaskList; delete pIpEntry->m_newIPInfo.pszwOptionList; delete pIpEntry; } s_IPEntryList.RemoveAll(); s_fWriteIPConfig = FALSE; } //Error: if (pTcpipProperties) pTcpipProperties->Release(); if (pNetCfg) { HrUninitializeAndReleaseINetCfg(FALSE, pNetCfg, TRUE /* fHasLock */); pNetCfg = NULL; } TraceResult("CRemCfg::CommitIpInfo", hr); return hr; } /*!-------------------------------------------------------------------------- HrGetIpxPrivateInterface - Author: ScottBri, KennT ---------------------------------------------------------------------------*/ HRESULT HrGetIpxPrivateInterface(INetCfg* pNetCfg, IIpxAdapterInfo** ppIpxAdapterInfo) { HRESULT hr; INetCfgClass* pncclass = NULL; if ((pNetCfg == NULL) || (ppIpxAdapterInfo == NULL)) return E_INVALIDARG; hr = pNetCfg->QueryNetCfgClass (&GUID_DEVCLASS_NETTRANS, IID_INetCfgClass, reinterpret_cast(&pncclass)); if (SUCCEEDED(hr)) { INetCfgComponent * pnccItem = NULL; // Find the component. hr = pncclass->FindComponent(TEXT("MS_NWIPX"), &pnccItem); //AssertSz (SUCCEEDED(hr), "pncclass->Find failed."); if (S_OK == hr) { INetCfgComponentPrivate* pinccp = NULL; hr = pnccItem->QueryInterface(IID_INetCfgComponentPrivate, reinterpret_cast(&pinccp)); if (SUCCEEDED(hr)) { hr = pinccp->QueryNotifyObject(IID_IIpxAdapterInfo, reinterpret_cast(ppIpxAdapterInfo)); pinccp->Release(); } } if (pnccItem) pnccItem->Release(); } if (pncclass) pncclass->Release(); // S_OK indicates success (interface returned) // S_FALSE indicates Ipx not installed // other values are errors TraceResult("HrGetIpxPrivateInterface", hr); return hr; } /*!-------------------------------------------------------------------------- HrGetIpPrivateInterface - Author: TongLu, KennT ---------------------------------------------------------------------------*/ HRESULT HrGetIpPrivateInterface(INetCfg* pNetCfg, ITcpipProperties **ppTcpProperties) { HRESULT hr; INetCfgClass* pncclass = NULL; if ((pNetCfg == NULL) || (ppTcpProperties == NULL)) return E_INVALIDARG; hr = pNetCfg->QueryNetCfgClass (&GUID_DEVCLASS_NETTRANS, IID_INetCfgClass, reinterpret_cast(&pncclass)); if (SUCCEEDED(hr)) { INetCfgComponent * pnccItem = NULL; // Find the component. hr = pncclass->FindComponent(TEXT("MS_TCPIP"), &pnccItem); //AssertSz (SUCCEEDED(hr), "pncclass->Find failed."); if (S_OK == hr) { INetCfgComponentPrivate* pinccp = NULL; hr = pnccItem->QueryInterface(IID_INetCfgComponentPrivate, reinterpret_cast(&pinccp)); if (SUCCEEDED(hr)) { hr = pinccp->QueryNotifyObject(IID_ITcpipProperties, reinterpret_cast(ppTcpProperties)); pinccp->Release(); } } if (pnccItem) pnccItem->Release(); } if (pncclass) pncclass->Release(); // S_OK indicates success (interface returned) // S_FALSE indicates Ipx not installed // other values are errors TraceResult("HrGetIpPrivateInterface", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrCreateAndInitializeINetCfg // // Purpose: Cocreate and initialize the root INetCfg object. This will // optionally initialize COM for the caller too. // // Arguments: // pfInitCom [in,out] TRUE to call CoInitialize before creating. // returns TRUE if COM was successfully // initialized FALSE if not. If NULL, means // don't initialize COM. // ppnc [out] The returned INetCfg object. // fGetWriteLock [in] TRUE if a writable INetCfg is needed // cmsTimeout [in] See INetCfg::LockForWrite // szwClientDesc [in] See INetCfg::LockForWrite // ppszwClientDesc [out] See INetCfg::LockForWrite // // Returns: S_OK or an error code. // // Author: shaunco 7 May 1997 // // Notes: // HRESULT HrCreateAndInitializeINetCfg ( BOOL* pfInitCom, INetCfg** ppnc, BOOL fGetWriteLock, DWORD cmsTimeout, LPCWSTR szwClientDesc, LPWSTR * ppszwClientDesc) { // ASSERT (ppnc); // Initialize the output parameter. *ppnc = NULL; if (ppszwClientDesc) *ppszwClientDesc = NULL; // Initialize COM if the caller requested. HRESULT hr = S_OK; if (pfInitCom && *pfInitCom) { hr = CoInitializeEx( NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED ); if (RPC_E_CHANGED_MODE == hr) { hr = S_OK; if (pfInitCom) { *pfInitCom = FALSE; } } } if (SUCCEEDED(hr)) { // Create the object implementing INetCfg. // INetCfg* pnc; hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, reinterpret_cast(&pnc)); TraceResult("HrCreateAndInitializeINetCfg - CoCreateInstance(CLSID_CNetCfg)", hr); if (SUCCEEDED(hr)) { INetCfgLock * pnclock = NULL; if (fGetWriteLock) { // Get the locking interface hr = pnc->QueryInterface(IID_INetCfgLock, reinterpret_cast(&pnclock)); TraceResult("HrCreateAndInitializeINetCfg - QueryInterface(IID_INetCfgLock", hr); if (SUCCEEDED(hr)) { // Attempt to lock the INetCfg for read/write hr = pnclock->AcquireWriteLock(cmsTimeout, szwClientDesc, ppszwClientDesc); TraceResult("HrCreateAndInitializeINetCfg - INetCfgLock::LockForWrite", hr); if (S_FALSE == hr) { // Couldn't acquire the lock hr = NETCFG_E_NO_WRITE_LOCK; } } } if (SUCCEEDED(hr)) { // Initialize the INetCfg object. // hr = pnc->Initialize (NULL); TraceResult("HrCreateAndInitializeINetCfg - Initialize", hr); if (SUCCEEDED(hr)) { *ppnc = pnc; if (pnc) pnc->AddRef(); } else { if (pnclock) { pnclock->ReleaseWriteLock(); } } // Transfer reference to caller. } ReleaseObj(pnclock); pnclock = NULL; ReleaseObj(pnc); pnc = NULL; } // If we failed anything above, and we've initialized COM, // be sure an uninitialize it. // if (FAILED(hr) && pfInitCom && *pfInitCom) { CoUninitialize (); } } TraceResult("HrCreateAndInitializeINetCfg", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrUninitializeAndReleaseINetCfg // // Purpose: Unintialize and release an INetCfg object. This will // optionally uninitialize COM for the caller too. // // Arguments: // fUninitCom [in] TRUE to uninitialize COM after the INetCfg is // uninitialized and released. // pnc [in] The INetCfg object. // fHasLock [in] TRUE if the INetCfg was locked for write and // must be unlocked. // // Returns: S_OK or an error code. // // Author: shaunco 7 May 1997 // // Notes: The return value is the value returned from // INetCfg::Uninitialize. Even if this fails, the INetCfg // is still released. Therefore, the return value is for // informational purposes only. You can't touch the INetCfg // object after this call returns. // HRESULT HrUninitializeAndReleaseINetCfg ( BOOL fUninitCom, INetCfg* pnc, BOOL fHasLock) { // Assert (pnc); HRESULT hr = S_OK; if (fHasLock) { hr = HrUninitializeAndUnlockINetCfg(pnc); } else { hr = pnc->Uninitialize (); } ReleaseObj (pnc); pnc = NULL; if (fUninitCom) { CoUninitialize (); } TraceResult("HrUninitializeAndReleaseINetCfg", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrUninitializeAndUnlockINetCfg // // Purpose: Uninitializes and unlocks the INetCfg object // // Arguments: // pnc [in] INetCfg to uninitialize and unlock // // Returns: S_OK if success, OLE or Win32 error otherwise // // Author: danielwe 13 Nov 1997 // // Notes: // HRESULT HrUninitializeAndUnlockINetCfg ( INetCfg* pnc) { HRESULT hr = S_OK; hr = pnc->Uninitialize(); if (SUCCEEDED(hr)) { INetCfgLock * pnclock; // Get the locking interface hr = pnc->QueryInterface(IID_INetCfgLock, reinterpret_cast(&pnclock)); if (SUCCEEDED(hr)) { // Attempt to lock the INetCfg for read/write hr = pnclock->ReleaseWriteLock(); ReleaseObj(pnclock); pnclock = NULL; } } TraceResult("HrUninitializeAndUnlockINetCfg", hr); return hr; }