From 0dd998f1a2d1ca3a3fca9bc6ea85c40ccfeae850 Mon Sep 17 00:00:00 2001
From: George Hazan <ghazan@miranda.im>
Date: Sun, 12 May 2019 20:38:09 +0300
Subject: fixes #1948 (memory allocation problem in Scriver)

---
 plugins/Scriver/src/cmdlist.cpp   |   7 +--
 plugins/Scriver/src/msgdialog.cpp |   2 +-
 plugins/Scriver/src/sendqueue.cpp | 122 +++++++++++++-------------------------
 plugins/Scriver/src/sendqueue.h   |  16 +++--
 4 files changed, 56 insertions(+), 91 deletions(-)

(limited to 'plugins')

diff --git a/plugins/Scriver/src/cmdlist.cpp b/plugins/Scriver/src/cmdlist.cpp
index 4b8b66da7d..509b1f503f 100644
--- a/plugins/Scriver/src/cmdlist.cpp
+++ b/plugins/Scriver/src/cmdlist.cpp
@@ -57,7 +57,7 @@ TCmdList* tcmdlist_remove_first(TCmdList *list)
 	return list;
 }
 
-TCmdList *tcmdlist_remove(TCmdList *list, TCmdList *n)
+TCmdList* tcmdlist_remove(TCmdList *list, TCmdList *n)
 {
 	if (n->next) n->next->prev = n->prev;
 	if (n->prev) n->prev->next = n->next;
@@ -87,10 +87,9 @@ TCmdList* tcmdlist_last(TCmdList *list)
 
 void tcmdlist_free(TCmdList *&list)
 {
-	TCmdList *n = list, *next;
-
+	TCmdList *n = list;
 	while (n != nullptr) {
-		next = n->next;
+		auto *next = n->next;
 		mir_free(n->szCmd);
 		mir_free(n);
 		n = next;
diff --git a/plugins/Scriver/src/msgdialog.cpp b/plugins/Scriver/src/msgdialog.cpp
index 9444c5078b..ab2d569f71 100644
--- a/plugins/Scriver/src/msgdialog.cpp
+++ b/plugins/Scriver/src/msgdialog.cpp
@@ -460,7 +460,7 @@ void CSrmmWindow::onClick_Ok(CCtrlButton *pButton)
 		cmdListNew = tcmdlist_last(cmdList);
 	}
 	if (msi.sendBuffer != nullptr)
-		cmdList = tcmdlist_append(cmdList, rtrim(msi.sendBuffer), 20, FALSE);
+		cmdList = tcmdlist_append(cmdList, mir_strdup(rtrim(msi.sendBuffer)), 20, FALSE);
 
 	cmdListCurrent = nullptr;
 
diff --git a/plugins/Scriver/src/sendqueue.cpp b/plugins/Scriver/src/sendqueue.cpp
index c1278c1353..886dd1fc3c 100644
--- a/plugins/Scriver/src/sendqueue.cpp
+++ b/plugins/Scriver/src/sendqueue.cpp
@@ -23,29 +23,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "stdafx.h"
 
-static MessageSendQueueItem *global_sendQueue = nullptr;
+static OBJLIST<MessageSendQueueItem> arQueue(1, PtrKeySortT);
 static mir_cs queueMutex;
 
 MessageSendQueueItem* CreateSendQueueItem(HWND hwndSender)
 {
-	MessageSendQueueItem *item = (MessageSendQueueItem*)mir_calloc(sizeof(MessageSendQueueItem));
-
-	mir_cslock lck(queueMutex);
+	MessageSendQueueItem *item = new MessageSendQueueItem();
 	item->hwndSender = hwndSender;
-	item->next = global_sendQueue;
-	if (global_sendQueue != nullptr)
-		global_sendQueue->prev = item;
 
-	global_sendQueue = item;
+	mir_cslock lck(queueMutex);
+	arQueue.insert(item);
 	return item;
 }
 
 MessageSendQueueItem* FindOldestPendingSendQueueItem(HWND hwndSender, MCONTACT hContact)
 {
 	mir_cslock lck(queueMutex);
-	for (MessageSendQueueItem *item = global_sendQueue; item != nullptr; item = item->next)
-		if (item->hwndSender == hwndSender && item->hContact == hContact && item->hwndErrorDlg == nullptr)
-			return item;
+	for (auto &it : arQueue)
+		if (it->hwndSender == hwndSender && it->hContact == hContact && it->hwndErrorDlg == nullptr)
+			return it;
 
 	return nullptr;
 }
@@ -53,61 +49,47 @@ MessageSendQueueItem* FindOldestPendingSendQueueItem(HWND hwndSender, MCONTACT h
 MessageSendQueueItem* FindSendQueueItem(MCONTACT hContact, HANDLE hSendId)
 {
 	mir_cslock lock(queueMutex);
-	for (MessageSendQueueItem *item = global_sendQueue; item != nullptr; item = item->next)
-		if (item->hContact == hContact && HANDLE(item->hSendId) == hSendId)
-			return item;
+	for (auto &it : arQueue)
+		if (it->hContact == hContact && HANDLE(it->hSendId) == hSendId)
+			return it;
 
 	return nullptr;
 }
 
-BOOL RemoveSendQueueItem(MessageSendQueueItem* item)
+bool RemoveSendQueueItem(MessageSendQueueItem *item)
 {
 	HWND hwndSender = item->hwndSender;
+	{
+		mir_cslock lock(queueMutex);
+		arQueue.remove(item);
+	}
 
-	mir_cslock lock(queueMutex);
-	if (item->prev != nullptr)
-		item->prev->next = item->next;
-	else
-		global_sendQueue = item->next;
-
-	if (item->next != nullptr)
-		item->next->prev = item->prev;
-
-	mir_free(item->sendBuffer);
-	mir_free(item->proto);
-	mir_free(item);
-
-	for (item = global_sendQueue; item != nullptr; item = item->next)
-		if (item->hwndSender == hwndSender)
-			return FALSE;
+	for (auto &it : arQueue)
+		if (it->hwndSender == hwndSender)
+			return false;
 
-	return TRUE;
+	return true;
 }
 
 void ReportSendQueueTimeouts(HWND hwndSender)
 {
-	MessageSendQueueItem *item, *item2;
 	int timeout = g_plugin.getDword(SRMSGSET_MSGTIMEOUT, SRMSGDEFSET_MSGTIMEOUT);
 
 	mir_cslock lock(queueMutex);
 
-	for (item = global_sendQueue; item != nullptr; item = item2) {
-		item2 = item->next;
-		if (item->timeout < timeout) {
-			item->timeout += 1000;
-			if (item->timeout >= timeout) {
-				if (item->hwndSender == hwndSender && item->hwndErrorDlg == nullptr) {
-					if (hwndSender != nullptr) {
-						CErrorDlg *pDlg = new CErrorDlg(TranslateT("The message send timed out."), hwndSender, item);
-						PostMessage(hwndSender, DM_SHOWERRORMESSAGE, 0, (LPARAM)pDlg);
-					}
-					else {
-						/* TODO: Handle errors outside messaging window in a better way */
-						RemoveSendQueueItem(item);
-					}
-				}
-			}
+	for (auto &it : arQueue.rev_iter()) {
+		if (it->timeout >= timeout)
+			continue;
+			
+		it->timeout += 1000;
+		if (it->timeout < timeout || it->hwndSender != hwndSender || it->hwndErrorDlg != nullptr)
+			continue;
+
+		if (hwndSender != nullptr) {
+			CErrorDlg *pDlg = new CErrorDlg(TranslateT("The message send timed out."), hwndSender, it);
+			PostMessage(hwndSender, DM_SHOWERRORMESSAGE, 0, (LPARAM)pDlg);
 		}
+		else arQueue.remove(arQueue.indexOf(&it));
 	}
 }
 
@@ -115,13 +97,13 @@ void ReleaseSendQueueItems(HWND hwndSender)
 {
 	mir_cslock lock(queueMutex);
 
-	for (MessageSendQueueItem *item = global_sendQueue; item != nullptr; item = item->next) {
-		if (item->hwndSender == hwndSender) {
-			item->hwndSender = nullptr;
-			if (item->hwndErrorDlg != nullptr)
-				DestroyWindow(item->hwndErrorDlg);
+	for (auto &it : arQueue) {
+		if (it->hwndSender == hwndSender) {
+			it->hwndSender = nullptr;
 
-			item->hwndErrorDlg = nullptr;
+			if (it->hwndErrorDlg != nullptr)
+				DestroyWindow(it->hwndErrorDlg);
+			it->hwndErrorDlg = nullptr;
 		}
 	}
 }
@@ -132,10 +114,10 @@ int ReattachSendQueueItems(HWND hwndSender, MCONTACT hContact)
 
 	mir_cslock lock(queueMutex);
 
-	for (MessageSendQueueItem *item = global_sendQueue; item != nullptr; item = item->next) {
-		if (item->hContact == hContact && item->hwndSender == nullptr) {
-			item->hwndSender = hwndSender;
-			item->timeout = 0;
+	for (auto &it : arQueue) {
+		if (it->hContact == hContact && it->hwndSender == nullptr) {
+			it->hwndSender = hwndSender;
+			it->timeout = 0;
 			count++;
 		}
 	}
@@ -144,32 +126,12 @@ int ReattachSendQueueItems(HWND hwndSender, MCONTACT hContact)
 
 void RemoveAllSendQueueItems()
 {
-	MessageSendQueueItem *item, *item2;
 	mir_cslock lock(queueMutex);
-	for (item = global_sendQueue; item != nullptr; item = item2) {
-		item2 = item->next;
-		RemoveSendQueueItem(item);
-	}
+	arQueue.destroy();
 }
 
 void SendSendQueueItem(MessageSendQueueItem* item)
 {
-	mir_cslockfull lock(queueMutex);
 	item->timeout = 0;
-
-	if (item->prev != nullptr) {
-		item->prev->next = item->next;
-		if (item->next != nullptr)
-			item->next->prev = item->prev;
-
-		item->next = global_sendQueue;
-		item->prev = nullptr;
-		if (global_sendQueue != nullptr)
-			global_sendQueue->prev = item;
-
-		global_sendQueue = item;
-	}
-	lock.unlock();
-
 	item->hSendId = ProtoChainSend(item->hContact, PSS_MESSAGE, item->flags, (LPARAM)item->sendBuffer);
 }
diff --git a/plugins/Scriver/src/sendqueue.h b/plugins/Scriver/src/sendqueue.h
index 1efb70dbe4..092d43a602 100644
--- a/plugins/Scriver/src/sendqueue.h
+++ b/plugins/Scriver/src/sendqueue.h
@@ -24,8 +24,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #ifndef SRMM_SENDQUEUE_H
 #define SRMM_SENDQUEUE_H
 
-struct MessageSendQueueItem
+struct MessageSendQueueItem : public MZeroedObject
 {
+	~MessageSendQueueItem()
+	{
+		mir_free(proto);
+		mir_free(sendBuffer);
+	}
+
 	HWND	hwndSender;
 	MCONTACT hContact;
 	char  *proto;
@@ -36,18 +42,16 @@ struct MessageSendQueueItem
 	int    codepage;
 	int    flags;
 	HWND   hwndErrorDlg;
-	
-	MessageSendQueueItem *prev, *next;
 };
 
 MessageSendQueueItem* CreateSendQueueItem(HWND hwndSender);
-wchar_t * GetSendBufferMsg(MessageSendQueueItem *item);
 MessageSendQueueItem* FindOldestPendingSendQueueItem(HWND hwndSender, MCONTACT hContact);
 MessageSendQueueItem* FindSendQueueItem(MCONTACT hContact, HANDLE hSendId);
-BOOL RemoveSendQueueItem(MessageSendQueueItem* item);
+
+bool RemoveSendQueueItem(MessageSendQueueItem* item);
 void ReportSendQueueTimeouts(HWND hwndSender);
 void ReleaseSendQueueItems(HWND hwndSender);
-int ReattachSendQueueItems(HWND hwndSender, MCONTACT hContact);
+int  ReattachSendQueueItems(HWND hwndSender, MCONTACT hContact);
 void RemoveAllSendQueueItems();
 void SendSendQueueItem(MessageSendQueueItem* item);
 
-- 
cgit v1.2.3