[PATCH 2/5] shell32: Factor shell notification code into separate function.

Nigel Baillie metreckk at gmail.com
Tue Feb 26 18:19:23 CST 2019


Additionally, SendMessageTimeoutA is used instead of SendMessageA
because notify_recipient will be called from another thread and may need
to be canceled when the window is being destroyed.

Signed-off-by: Nigel Baillie <metreckk at gmaill.com>
---
 dlls/shell32/changenotify.c | 106 +++++++++++++++++++++---------------
 1 file changed, 62 insertions(+), 44 deletions(-)

diff --git a/dlls/shell32/changenotify.c b/dlls/shell32/changenotify.c
index 2efb297ad5..7656f43fee 100644
--- a/dlls/shell32/changenotify.c
+++ b/dlls/shell32/changenotify.c
@@ -56,6 +56,15 @@ typedef struct _NOTIFICATIONLIST
 static struct list notifications = LIST_INIT( notifications );
 static LONG next_id;
 
+struct new_delivery_notification
+{
+    LONG event;
+    DWORD pidl1_size;
+    DWORD pidl2_size;
+    LPITEMIDLIST pidls[2];
+    BYTE data[1];
+};
+
 #define SHCNE_NOITEMEVENTS ( \
    SHCNE_ASSOCCHANGED )
 
@@ -150,6 +159,58 @@ void FreeChangeNotifications(void)
     DeleteCriticalSection(&SHELL32_ChangenotifyCS);
 }
 
+static BOOL notify_recipient(
+    HWND hwnd, DWORD msg, DWORD flags, LONG event_id,
+    LPITEMIDLIST pidls[2], HANDLE *shared_data)
+{
+    LRESULT sendmsg_result = 0;
+    TRACE("notifying %p, event %s(%x)\n", hwnd, DumpEvent(event_id), event_id);
+
+    if (flags & SHCNRF_NewDelivery) {
+        if(!(*shared_data)) {
+            struct new_delivery_notification *notification;
+            UINT size1 = ILGetSize(pidls[0]), size2 = ILGetSize(pidls[1]);
+            UINT offset = (size1+sizeof(int)-1)/sizeof(int)*sizeof(int);
+
+            notification = SHAlloc(sizeof(struct new_delivery_notification)+offset+size2);
+            if(!notification) {
+                ERR("out of memory\n");
+            } else {
+                notification->event = event_id;
+                notification->pidl1_size = size1;
+                notification->pidl2_size = size2;
+                if(size1)
+                    memcpy(notification->data, pidls[0], size1);
+                if(size2)
+                    memcpy(notification->data+offset, pidls[1], size2);
+
+                *shared_data = SHAllocShared(notification,
+                    sizeof(struct new_delivery_notification)+size1+size2,
+                    GetCurrentProcessId());
+                SHFree(notification);
+            }
+        }
+
+        if(*shared_data) {
+            sendmsg_result = SendMessageTimeoutA(
+                hwnd, msg, (WPARAM)*shared_data, GetCurrentProcessId(),
+                SMTO_NOTIMEOUTIFNOTHUNG | SMTO_ERRORONEXIT,
+                10000, NULL
+            );
+        }
+        else
+            ERR("out of memory\n");
+    } else {
+        sendmsg_result = SendMessageTimeoutA(
+            hwnd, msg, (WPARAM)pidls, event_id,
+            SMTO_NOTIMEOUTIFNOTHUNG | SMTO_ERRORONEXIT,
+            10000, NULL
+        );
+    }
+
+    return sendmsg_result != 0;
+}
+
 /*************************************************************************
  * SHChangeNotifyRegister			[SHELL32.2]
  *
@@ -231,15 +292,6 @@ BOOL WINAPI SHChangeNotifyUpdateEntryList(DWORD unknown1, DWORD unknown2,
     return TRUE;
 }
 
-struct new_delivery_notification
-{
-    LONG event;
-    DWORD pidl1_size;
-    DWORD pidl2_size;
-    LPITEMIDLIST pidls[2];
-    BYTE data[1];
-};
-
 static BOOL should_notify( LPCITEMIDLIST changed, LPCITEMIDLIST watched, BOOL sub )
 {
     TRACE("%p %p %d\n", changed, watched, sub );
@@ -371,41 +423,7 @@ void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID
 
     LIST_FOR_EACH_ENTRY_SAFE(cur, next, &recipients, struct notification_recipients, entry)
     {
-        TRACE("notifying %p, event %s(%x)\n", cur->hwnd, DumpEvent(wEventId), wEventId);
-
-        if (cur->flags  & SHCNRF_NewDelivery) {
-            if(!shared_data) {
-                struct new_delivery_notification *notification;
-                UINT size1 = ILGetSize(Pidls[0]), size2 = ILGetSize(Pidls[1]);
-                UINT offset = (size1+sizeof(int)-1)/sizeof(int)*sizeof(int);
-
-                notification = SHAlloc(sizeof(struct new_delivery_notification)+offset+size2);
-                if(!notification) {
-                    ERR("out of memory\n");
-                } else {
-                    notification->event = wEventId;
-                    notification->pidl1_size = size1;
-                    notification->pidl2_size = size2;
-                    if(size1)
-                        memcpy(notification->data, Pidls[0], size1);
-                    if(size2)
-                        memcpy(notification->data+offset, Pidls[1], size2);
-
-                    shared_data = SHAllocShared(notification,
-                        sizeof(struct new_delivery_notification)+size1+size2,
-                        GetCurrentProcessId());
-                    SHFree(notification);
-                }
-            }
-
-            if(shared_data)
-                SendMessageA(cur->hwnd, cur->msg, (WPARAM)shared_data, GetCurrentProcessId());
-            else
-                ERR("out of memory\n");
-        } else {
-            SendMessageA(cur->hwnd, cur->msg, (WPARAM)Pidls, wEventId);
-        }
-
+        notify_recipient(cur->hwnd, cur->msg, cur->flags, wEventId, Pidls, &shared_data);
         list_remove(&cur->entry);
         SHFree(cur);
     }
-- 
2.20.1




More information about the wine-devel mailing list