From 5470a3a4533c8b382fab958bf16fe33942dc24e4 Mon Sep 17 00:00:00 2001 From: Vort Date: Fri, 3 Mar 2023 21:02:54 +0200 Subject: [PATCH] Eliminate memory leak in Win32NetState --- Win32/DaemonWin32.cpp | 2 +- Win32/Win32App.cpp | 11 ++++++++--- Win32/Win32App.h | 2 +- Win32/Win32NetState.cpp | 9 +++++++-- Win32/Win32NetState.h | 7 ++----- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Win32/DaemonWin32.cpp b/Win32/DaemonWin32.cpp index affc301a..e8052f14 100644 --- a/Win32/DaemonWin32.cpp +++ b/Win32/DaemonWin32.cpp @@ -64,7 +64,7 @@ namespace util //setlocale(LC_ALL, "Russian"); setlocale(LC_TIME, "C"); #ifdef WIN32_APP - if (!i2p::win32::StartWin32App ()) return false; + if (!i2p::win32::StartWin32App (isDaemon)) return false; #endif bool ret = Daemon_Singleton::start(); if (ret && i2p::log::Logger().GetLogType() == eLogFile) diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp index 37458046..9eae7a95 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -45,6 +45,7 @@ namespace i2p namespace win32 { DWORD g_GracefulShutdownEndtime = 0; + bool g_isWinService; static void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem) { @@ -416,8 +417,9 @@ namespace win32 return DefWindowProc( hWnd, uMsg, wParam, lParam); } - bool StartWin32App () + bool StartWin32App (bool isWinService) { + g_isWinService = isWinService; if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"))) { MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK); @@ -446,7 +448,9 @@ namespace win32 MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST); return false; } - SubscribeToEvents(); + // COM requires message loop to work, which is not implemented in service mode + if (!g_isWinService) + SubscribeToEvents(); return true; } @@ -466,7 +470,8 @@ namespace win32 HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")); if (hWnd) PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0); - // UnSubscribeFromEvents(); // TODO: understand why unsubscribing crashes app + else if(!g_isWinService) + UnSubscribeFromEvents(); UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL)); } diff --git a/Win32/Win32App.h b/Win32/Win32App.h index ebe49efd..614de738 100644 --- a/Win32/Win32App.h +++ b/Win32/Win32App.h @@ -17,7 +17,7 @@ namespace win32 { extern DWORD g_GracefulShutdownEndtime; - bool StartWin32App (); + bool StartWin32App (bool isWinService); void StopWin32App (); int RunWin32App (); bool GracefulShutdown (); diff --git a/Win32/Win32NetState.cpp b/Win32/Win32NetState.cpp index 216c36b6..794dc4b9 100644 --- a/Win32/Win32NetState.cpp +++ b/Win32/Win32NetState.cpp @@ -15,6 +15,7 @@ IUnknown *pUnknown = nullptr; INetworkListManager *pNetworkListManager = nullptr; IConnectionPointContainer *pCPContainer = nullptr; IConnectionPoint *pConnectPoint = nullptr; +CNetworkListManagerEvent *pNetEvent = nullptr; DWORD Cookie = 0; void SubscribeToEvents() @@ -45,8 +46,8 @@ void SubscribeToEvents() Result = pCPContainer->FindConnectionPoint(IID_INetworkListManagerEvents, &pConnectPoint); if(SUCCEEDED(Result)) { - CNetworkListManagerEvent *NetEvent = new CNetworkListManagerEvent; - Result = pConnectPoint->Advise((IUnknown *)NetEvent, &Cookie); + pNetEvent = new CNetworkListManagerEvent; + Result = pConnectPoint->Advise((IUnknown *)pNetEvent, &Cookie); if (SUCCEEDED(Result)) LogPrint(eLogInfo, "NetState: Successfully subscribed to NetworkListManagerEvent messages"); else @@ -63,6 +64,7 @@ void SubscribeToEvents() void UnSubscribeFromEvents() { + LogPrint(eLogInfo, "NetState: Unsubscribing from NetworkListManagerEvents"); try { if (pConnectPoint) { @@ -70,6 +72,9 @@ void UnSubscribeFromEvents() pConnectPoint->Release(); } + if (pNetEvent) + pNetEvent->Release(); + if (pCPContainer) pCPContainer->Release(); diff --git a/Win32/Win32NetState.h b/Win32/Win32NetState.h index c2ddaee4..1414a324 100644 --- a/Win32/Win32NetState.h +++ b/Win32/Win32NetState.h @@ -19,21 +19,18 @@ class CNetworkListManagerEvent : public INetworkListManagerEvents { public: CNetworkListManagerEvent() : m_ref(1) { } - ~CNetworkListManagerEvent() { } HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) { - HRESULT Result = S_OK; if (IsEqualIID(riid, IID_IUnknown)) { *ppvObject = (IUnknown *)this; } else if (IsEqualIID(riid ,IID_INetworkListManagerEvents)) { *ppvObject = (INetworkListManagerEvents *)this; } else { - Result = E_NOINTERFACE; + return E_NOINTERFACE; } AddRef(); - - return Result; + return S_OK; } ULONG STDMETHODCALLTYPE AddRef()