#include #include "netconn.h" #include "globals.h" #include "localstr.h" #include #include #include #define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0])) #pragma warning(disable:4100) // unreferenced formal parameter enum NetApplyChanges { Apply, Cancel, Nothing }; HRESULT UninitNetCfg(INetCfg* pnetcfg, INetCfgLock* pnetcfglock, NetApplyChanges applychanges) { HRESULT hr = S_OK; if (Apply == applychanges) { hr = pnetcfg->Apply(); } else if (Cancel == applychanges) { hr = pnetcfg->Cancel(); } // Note: Don't set hr to anything after this point. We want to preserve the value from Apply // or Cancel - especially Apply which may signal a reboot is necessary. // Release even if this stuff above fails. Caller probably won't check return. pnetcfg->Uninitialize(); if (pnetcfglock) { pnetcfglock->ReleaseWriteLock(); pnetcfglock->Release(); } pnetcfg->Release(); CoUninitialize(); return hr; } HRESULT InitNetCfg(INetCfg** ppnetcfg, INetCfgLock** ppnetcfglock) { BOOL fLockAquired = FALSE; *ppnetcfg = NULL; if (ppnetcfglock) { *ppnetcfglock = NULL; } HRESULT hr = CoInitialize(NULL); if (SUCCEEDED(hr)) { hr = CoCreateInstance( CLSID_CNetCfg, NULL, CLSCTX_SERVER, IID_INetCfg, (void**) ppnetcfg); if (SUCCEEDED(hr)) { if (ppnetcfglock) { hr = (*ppnetcfg)->QueryInterface(IID_INetCfgLock, (void**) ppnetcfglock); if (SUCCEEDED(hr)) { LPWSTR pszCurrentLockHolder; hr = (*ppnetcfglock)->AcquireWriteLock(5, WIZARDNAME, &pszCurrentLockHolder); if (S_OK == hr) { fLockAquired = TRUE; } else { hr = NETCFG_E_NO_WRITE_LOCK; } } } if (SUCCEEDED(hr)) { hr = (*ppnetcfg)->Initialize(NULL); } } // Clean up our mess if we failed if (FAILED(hr)) { if (ppnetcfglock) { if (*ppnetcfglock) { if (fLockAquired) { (*ppnetcfglock)->ReleaseWriteLock(); } (*ppnetcfglock)->Release(); *ppnetcfglock = NULL; } } if (*ppnetcfg) { (*ppnetcfg)->Release(); *ppnetcfg = NULL; } } } return hr; } LPWSTR NineXIdToComponentId(LPCWSTR psz9xid) { LPWSTR pszComponentId = NULL; if (0 == StrCmpI(psz9xid, SZ_PROTOCOL_TCPIP)) { pszComponentId = &NETCFG_TRANS_CID_MS_TCPIP; } else if (0 == StrCmpI(psz9xid, SZ_CLIENT_MICROSOFT)) { pszComponentId = &NETCFG_CLIENT_CID_MS_MSClient; } return pszComponentId; } // EnumComponents and TestRunDll are test-only stuff and should be removed - TODO void EnumComponents(INetCfg* pnetcfg, const GUID* pguid) { IEnumNetCfgComponent* penum; HRESULT hr = pnetcfg->EnumComponents(pguid, &penum); if (SUCCEEDED(hr)) { INetCfgComponent* pcomponent; while (S_OK == (hr = penum->Next(1, &pcomponent, NULL))) { LPWSTR pszId; LPWSTR pszName; hr = pcomponent->GetId(&pszId); if (SUCCEEDED(hr)) { OutputDebugString(pszId); CoTaskMemFree(pszId); } hr = pcomponent->GetDisplayName(&pszName); if (SUCCEEDED(hr)) { OutputDebugString(L" - "); OutputDebugString(pszName); CoTaskMemFree(pszName); } OutputDebugString(L"\n"); pcomponent->Release(); } penum->Release(); } } void APIENTRY TestRunDll(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow) { HRESULT hr = S_OK; CoInitialize(NULL); INetCfg *pnetcfg = NULL; hr = CoCreateInstance( CLSID_CNetCfg, NULL, CLSCTX_SERVER, IID_INetCfg, (LPVOID*)&pnetcfg); if (SUCCEEDED(hr)) { hr = pnetcfg->Initialize(NULL); if (SUCCEEDED(hr)) { OutputDebugString(L"GUID_DEVCLASS_NET\n"); EnumComponents(pnetcfg, &GUID_DEVCLASS_NET); OutputDebugString(L"\nGUID_DEVCLASS_NETTRANS\n"); EnumComponents(pnetcfg, &GUID_DEVCLASS_NETTRANS); OutputDebugString(L"\nGUID_DEVCLASS_NETCLIENT\n"); EnumComponents(pnetcfg, &GUID_DEVCLASS_NETCLIENT); OutputDebugString(L"\nGUID_DEVCLASS_NETSERVICE\n"); EnumComponents(pnetcfg, &GUID_DEVCLASS_NETSERVICE); pnetcfg->Uninitialize(); } pnetcfg->Release(); } CoUninitialize(); } BOOL IsComponentInstalled(LPCWSTR pszId) { BOOL fInstalled = FALSE; INetCfg* pnetcfg; HRESULT hr = InitNetCfg(&pnetcfg, NULL); if (SUCCEEDED(hr)) { INetCfgComponent* pcomponent; HRESULT hr = pnetcfg->FindComponent(pszId, &pcomponent); if (S_OK == hr) { // Component found pcomponent->Release(); fInstalled = TRUE; } hr = UninitNetCfg(pnetcfg, NULL, Nothing); } return fInstalled; } HRESULT InstallComponent(const GUID* pguidType, LPCWSTR pszId) { INetCfg* pnetcfg; INetCfgLock* pnetcfglock; // Init & aquire a write lock HRESULT hr = InitNetCfg(&pnetcfg, &pnetcfglock); if (SUCCEEDED(hr)) { INetCfgClassSetup* pnetcfgclasssetup; hr = pnetcfg->QueryNetCfgClass(pguidType, IID_INetCfgClassSetup, (void**) &pnetcfgclasssetup); if (SUCCEEDED(hr)) { INetCfgComponent* pNewComp; OBO_TOKEN obotoken; ZeroMemory(&obotoken, sizeof(OBO_TOKEN)); obotoken.Type = OBO_USER; hr = pnetcfgclasssetup->Install( pszId, &obotoken, 0, /* NSF_POSTSYSINSTALL ? */ 0, NULL, NULL, &pNewComp); if (SUCCEEDED(hr)) { pNewComp->Release(); } pnetcfgclasssetup->Release(); } // Free our mess and apply changes if we succeeded in installing our component hr = UninitNetCfg(pnetcfg, pnetcfglock, (SUCCEEDED(hr)) ? Apply : Cancel); } return hr; } // NOT USED. But keep around since NetConnFree is used. // LPVOID WINAPI NetConnAlloc(DWORD cbAlloc) { return LocalAlloc(LMEM_FIXED, cbAlloc); } // USED. // VOID WINAPI NetConnFree(LPVOID pMem) { if (pMem) LocalFree(pMem); } // USED. Only one call with (SZ_PROTOCOL_TCPIP, TRUE). // BOOL WINAPI IsProtocolInstalled(LPCWSTR pszProtocolDeviceID, BOOL bExhaustive) { BOOL fSuccess = FALSE; LPCWSTR pszTransportId = NineXIdToComponentId(pszProtocolDeviceID); if (pszTransportId) { fSuccess = IsComponentInstalled(pszTransportId); } return fSuccess; } // USED. Called once with (FALSE) // BOOL WINAPI IsMSClientInstalled(BOOL bExhaustive) { return IsComponentInstalled(NETCFG_CLIENT_CID_MS_MSClient); } // USED. Only one call with (hwnd, NULL, NULL) // HRESULT WINAPI InstallTCPIP(HWND hwndParent, PROGRESS_CALLBACK pfnProgress, LPVOID pvProgressParam) { HRESULT hr = InstallComponent(&GUID_DEVCLASS_NETTRANS, NETCFG_TRANS_CID_MS_TCPIP); // Map the reboot result code if (NETCFG_S_REBOOT == hr) { hr = NETCONN_NEED_RESTART; } return hr; } // USED. Called once with (hwnd, NULL, NULL) // HRESULT WINAPI InstallMSClient(HWND hwndParent, PROGRESS_CALLBACK pfnProgress, LPVOID pvProgressParam) { HRESULT hr = InstallComponent(&GUID_DEVCLASS_NETCLIENT, NETCFG_CLIENT_CID_MS_MSClient); // Map the reboot result code if (NETCFG_S_REBOOT == hr) { hr = NETCONN_NEED_RESTART; } return hr; } // USED. Called once with (hwnd, NULL, NULL). // HRESULT WINAPI InstallSharing(HWND hwndParent, PROGRESS_CALLBACK pfnProgress, LPVOID pvProgressParam) { HRESULT hr = InstallComponent(&GUID_DEVCLASS_NETSERVICE, NETCFG_SERVICE_CID_MS_SERVER); // Map the reboot result code if (NETCFG_S_REBOOT == hr) { hr = NETCONN_NEED_RESTART; } return hr; } // USED. Called once with (TRUE) // BOOL WINAPI IsSharingInstalled(BOOL bExhaustive) { return IsComponentInstalled(NETCFG_SERVICE_CID_MS_SERVER); } // USED. Called once with (SZ_CLIENT_MICROSOFT, TRUE). // BOOL WINAPI IsClientInstalled(LPCWSTR pszClient, BOOL bExhaustive) { BOOL fSuccess = FALSE; LPCWSTR pszClientId = NineXIdToComponentId(pszClient); if (pszClientId) { fSuccess = IsComponentInstalled(pszClientId); } return fSuccess; } // USED. Called four times. // This is always TRUE on NT? BOOL WINAPI IsAccessControlUserLevel() { return TRUE; } // USED. Called once. // This can't be disabled on NT HRESULT WINAPI DisableUserLevelAccessControl() { return E_NOTIMPL; } #define CopyStrMacro(Dest) if (SUCCEEDED(hr)) {StrCpyNW((Dest), pszTemp, ARRAYSIZE((Dest))); CoTaskMemFree(pszTemp);} HRESULT FillAdapterInfo(INetCfgComponent* pcomponent, NETADAPTER* pNetAdapter) { HRESULT hr = S_OK; LPWSTR pszTemp; DWORD dwCharacteristics; // szDisplayName hr = pcomponent->GetDisplayName(&pszTemp); if (SUCCEEDED(hr)) { OutputDebugString(L"\n\nDisplayName:"); OutputDebugString(pszTemp); StrCpyNW(pNetAdapter->szDisplayName, pszTemp, ARRAYSIZE(pNetAdapter->szDisplayName)); CoTaskMemFree(pszTemp); } // szDeviceID hr = pcomponent->GetId(&pszTemp); if (SUCCEEDED(hr)) { OutputDebugString(L"\nId:"); OutputDebugString(pszTemp); StrCpyNW(pNetAdapter->szDeviceID, pszTemp, ARRAYSIZE(pNetAdapter->szDeviceID)); CoTaskMemFree(pszTemp); } // review - unused as of now - maybe remove hr = pcomponent->GetPnpDevNodeId(&pszTemp); if (SUCCEEDED(hr)) { OutputDebugString(L"\nPnpDevNodeId:"); OutputDebugString(pszTemp); } // review - assuming szEnumKey is actually the BindName since it is used in EnumMatchingNetBindings. hr = pcomponent->GetBindName(&pszTemp); if (SUCCEEDED(hr)) { OutputDebugString(L"\nBindName:"); OutputDebugString(pszTemp); StrCpyNW(pNetAdapter->szEnumKey, pszTemp, ARRAYSIZE(pNetAdapter->szEnumKey)); CoTaskMemFree(pszTemp); } // Also usused DWORD dwStatus; hr = pcomponent->GetDeviceStatus(&dwStatus); if (SUCCEEDED(hr)) { WCHAR szTemp[20]; wnsprintf(szTemp, ARRAYSIZE(szTemp), L"%x", dwStatus); OutputDebugString(L"\nDeviceStatus:"); OutputDebugString(szTemp); } hr = pcomponent->GetCharacteristics(&dwCharacteristics); if (SUCCEEDED(hr)) { WCHAR szTemp[20]; wnsprintf(szTemp, ARRAYSIZE(szTemp), L"%x", dwCharacteristics); OutputDebugString(L"\nCharacteristics:"); OutputDebugString(szTemp); } // szClassKey ?? // szManufacturer - don't care pNetAdapter->szManufacturer[0] = 0; // szInfFileName - don't care pNetAdapter->szInfFileName[0] = 0; // bNicType - review pNetAdapter->bNicType = (BYTE)((dwCharacteristics & NCF_VIRTUAL) ? NIC_VIRTUAL : NIC_UNKNOWN); // bNetType - review pNetAdapter->bNetType = (BYTE)((dwCharacteristics & NCF_PHYSICAL) ? NETTYPE_LAN : NETTYPE_PPTP); // bNetSubType - review pNetAdapter->bNetSubType = SUBTYPE_NONE; // bIcsStatus (internet connection sharing??)- review pNetAdapter->bIcsStatus = ICS_NONE; // bError - review pNetAdapter->bError = NICERR_NONE; // bWarning - review pNetAdapter->bWarning = NICWARN_NONE; return S_OK; } #define ALLOCGROWBY 10 int AllocAndGetAdapterInfo(IEnumNetCfgComponent* penum, NETADAPTER** pprgNetAdapters) { *pprgNetAdapters = NULL; UINT iMaxItems = 0; UINT iCurrentItem = 0; HRESULT hr = S_OK; while (S_OK == hr) { INetCfgComponent* pnetadapter; hr = penum->Next(1, &pnetadapter, NULL); if (S_OK == hr) { if (iCurrentItem == iMaxItems) { // Time to allocate some memory iMaxItems += ALLOCGROWBY; if (*pprgNetAdapters) { NETADAPTER* pTemp = (NETADAPTER*) LocalReAlloc(*pprgNetAdapters, sizeof(NETADAPTER) * iMaxItems, LMEM_ZEROINIT); if (!pTemp) { hr = E_OUTOFMEMORY; LocalFree(*pprgNetAdapters); *pprgNetAdapters = NULL; } else { *pprgNetAdapters = pTemp; } } else { *pprgNetAdapters = (NETADAPTER*) LocalAlloc(LMEM_ZEROINIT, sizeof(NETADAPTER) * iMaxItems); if (!*pprgNetAdapters) { hr = E_OUTOFMEMORY; } } } if (SUCCEEDED(hr)) { hr = FillAdapterInfo(pnetadapter, (*pprgNetAdapters) + iCurrentItem); } pnetadapter->Release(); iCurrentItem ++; } else { // We've got as many as we can; we're done } } return iCurrentItem; } // USED. Called four times - out parameter is never NULL. // int WINAPI EnumNetAdapters(NETADAPTER FAR** pprgNetAdapters) { *pprgNetAdapters = NULL; int iAdapters = 0; INetCfg* pnetcfg; HRESULT hr = InitNetCfg(&pnetcfg, NULL); if (SUCCEEDED(hr)) { IEnumNetCfgComponent* penum; hr = pnetcfg->EnumComponents(&GUID_DEVCLASS_NET, &penum); if (SUCCEEDED(hr)) { iAdapters = AllocAndGetAdapterInfo(penum, pprgNetAdapters); } hr = UninitNetCfg(pnetcfg, NULL, Nothing); } return iAdapters; } // USED. Called once with bAutodial TRUE or FALSE and szConnection not used. // void WINAPI EnableAutodial(BOOL bAutodial, LPCWSTR szConnection = NULL) { } // USED. Called twice. // BOOL WINAPI IsAutodialEnabled() { return FALSE; } // USED. Called once. // void WINAPI SetDefaultDialupConnection(LPCWSTR pszConnectionName) { } // Used. Called once. // void WINAPI GetDefaultDialupConnection(LPWSTR pszConnectionName, int cchMax) { } // Used. Called four times. Second parameter is always SZ_PROTOCOL_TCPIP. // Update: Actually only called once from SetHomeConnection. The other three are #if 0'd. // Update2: SetHomeConnection needs to have a different implementation for NT, so this is never really called. // int WINAPI EnumMatchingNetBindings(LPCWSTR pszParentBinding, LPCWSTR pszDeviceID, LPWSTR** pprgBindings) { return 0; } HRESULT WINAPI RestartNetAdapter(DWORD devnode) { return E_NOTIMPL; } // NOT USED. // /* HRESULT WINAPI InstallProtocol(LPCWSTR pszProtocol, HWND hwndParent, PROGRESS_CALLBACK pfnCallback, LPVOID pvCallbackParam) { return E_NOTIMPL; } */ // NOT USED. // /* HRESULT WINAPI RemoveProtocol(LPCWSTR pszProtocol) { return E_NOTIMPL; } */ // NOT USED. // /* HRESULT WINAPI EnableBrowseMaster() { return E_NOTIMPL; } */ // NOT USED. // /* BOOL WINAPI IsFileSharingEnabled() { return FALSE; } */ // NOT USED. // /* BOOL WINAPI IsPrinterSharingEnabled() { return FALSE; } */ // NOT USED. // /* BOOL WINAPI FindConflictingService(LPCWSTR pszWantService, NETSERVICE* pConflict) { return FALSE; } */ // NOT USED. // /* HRESULT WINAPI EnableSharingAppropriately() { return E_NOTIMPL; } */ // NOT USED. // /* HRESULT WINAPI InstallNetAdapter(LPCWSTR pszDeviceID, LPCWSTR pszInfPath, HWND hwndParent, PROGRESS_CALLBACK pfnProgress, LPVOID pvCallbackParam) { return E_NOTIMPL; } */ // NOT USED. // /* HRESULT WINAPI EnableQuickLogon() { return E_NOTIMPL; } */ // NOT USED. // /* HRESULT WINAPI DetectHardware(LPCWSTR pszDeviceID) { return E_NOTIMPL; } */ // NOT USED. // /* BOOL WINAPI IsProtocolBoundToAdapter(LPCWSTR pszProtocolID, const NETADAPTER* pAdapter) { return FALSE; } */ // NOT USED. // /* HRESULT WINAPI EnableNetAdapter(const NETADAPTER* pAdapter) { return E_NOTIMPL; } */ // NOT USED. // /* HRESULT WINAPI RemoveClient(LPCWSTR pszClient) { return E_NOTIMPL; } */ // NOT USED. // /* HRESULT WINAPI RemoveGhostedAdapters(LPCWSTR pszDeviceID) { return E_NOTIMPL; } */ // NOT USED. // /* HRESULT WINAPI RemoveUnknownAdapters(LPCWSTR pszDeviceID) { return E_NOTIMPL; } */ // NOT USED. // /* BOOL WINAPI DoesAdapterMatchDeviceID(const NETADAPTER* pAdapter, LPCWSTR pszDeviceID) { return FALSE; } */ // NOT USED. // /* BOOL WINAPI IsAdapterBroadband(const NETADAPTER* pAdapter) { return FALSE; } */ // NOT USED. // /* void WINAPI SaveBroadbandSettings(LPCWSTR pszBroadbandAdapterNumber) { } */ // NOT USED. // /* BOOL WINAPI UpdateBroadbandSettings(LPWSTR pszEnumKeyBuf, int cchEnumKeyBuf) { return FALSE; } */