Author: akhaldi
Date: Thu Nov  6 16:35:20 2014
New Revision: 65288
URL: 
http://svn.reactos.org/svn/reactos?rev=65288&view=rev
Log:
[SHELL32]
* Another partial sync of changenotify.c with Wine 1.7.27.
CORE-8540
Modified:
    branches/shell-experiments/dll/win32/shell32/wine/changenotify.c
Modified: branches/shell-experiments/dll/win32/shell32/wine/changenotify.c
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/dll/win32/she…
==============================================================================
--- branches/shell-experiments/dll/win32/shell32/wine/changenotify.c    [iso-8859-1]
(original)
+++ branches/shell-experiments/dll/win32/shell32/wine/changenotify.c    [iso-8859-1] Thu
Nov  6 16:35:20 2014
@@ -1,5 +1,5 @@
 /*
- *    shell change notification
+ *     shell change notification
  *
  * Copyright 2000 Juergen Schmied
  *
@@ -29,6 +29,7 @@
 #include <undocshell.h>
 #include <shlwapi.h>
 #include <wine/debug.h>
+#include <wine/list.h>
 #include "pidl.h"
@@ -48,20 +49,18 @@
 /* internal list of notification clients (internal) */
 typedef struct _NOTIFICATIONLIST
 {
-    struct _NOTIFICATIONLIST *next;
-    struct _NOTIFICATIONLIST *prev;
+       struct list entry;
        HWND hwnd;              /* window to notify */
        DWORD uMsg;             /* message to send */
        LPNOTIFYREGISTER apidl; /* array of entries to watch*/
        UINT cidl;              /* number of pidls in array */
        LONG wEventMask;        /* subscribed events */
-    LONG wSignalledEvent;   /* event that occurred */
        DWORD dwFlags;          /* client flags */
-    LPCITEMIDLIST pidlSignaled; /*pidl of the path that caused the signal*/
-
+       ULONG id;
 } NOTIFICATIONLIST, *LPNOTIFICATIONLIST;
-static NOTIFICATIONLIST *head, *tail;
+static struct list notifications = LIST_INIT( notifications );
+static LONG next_id;
 #define SHCNE_NOITEMEVENTS ( \
    SHCNE_ASSOCCHANGED )
@@ -121,44 +120,14 @@
     return str;
 }
-static void AddNode(LPNOTIFICATIONLIST item)
-{
-    TRACE("item %p\n", item );
-
-    /* link items */
-    item->prev = tail;
-    item->next = NULL;
-    if( tail )
-        tail->next = item;
-    else
-        head = item;
-    tail = item;
-}
-
-static LPNOTIFICATIONLIST FindNode( HANDLE hitem )
-{
-    LPNOTIFICATIONLIST ptr;
-    for( ptr = head; ptr; ptr = ptr->next )
-        if( ptr == (LPNOTIFICATIONLIST) hitem )
-            return ptr;
-    return NULL;
-}
-
 static void DeleteNode(LPNOTIFICATIONLIST item)
 {
     UINT i;
-    TRACE("item=%p prev=%p next=%p\n", item, item->prev, item->next);
+    TRACE("item=%p\n", item);
     /* remove item from list */
-    if( item->prev )
-        item->prev->next = item->next;
-    else
-        head = item->next;
-    if( item->next )
-        item->next->prev = item->prev;
-    else
-        tail = item->prev;
+    list_remove( &item->entry );
     /* free the item */
     for (i=0; i<item->cidl; i++)
@@ -173,16 +142,18 @@
 void FreeChangeNotifications(void)
 {
+    LPNOTIFICATIONLIST ptr, next;
+
     TRACE("\n");
     EnterCriticalSection(&SHELL32_ChangenotifyCS);
-    while( head )
-        DeleteNode( head );
+    LIST_FOR_EACH_ENTRY_SAFE( ptr, next, ¬ifications, NOTIFICATIONLIST, entry )
+        DeleteNode( ptr );
     LeaveCriticalSection(&SHELL32_ChangenotifyCS);
-    // DeleteCriticalSection(&SHELL32_ChangenotifyCS); // static
+    DeleteCriticalSection(&SHELL32_ChangenotifyCS);
 }
 /*************************************************************************
@@ -201,15 +172,13 @@
     LPNOTIFICATIONLIST item;
     int i;
-    item = (NOTIFICATIONLIST *)SHAlloc(sizeof(NOTIFICATIONLIST));
+    item = SHAlloc(sizeof(NOTIFICATIONLIST));
     TRACE("(%p,0x%08x,0x%08x,0x%08x,%d,%p) item=%p\n",
        hwnd, fSources, wEventMask, uMsg, cItems, lpItems, item);
-    item->next = NULL;
-    item->prev = NULL;
     item->cidl = cItems;
-    item->apidl = (SHChangeNotifyEntry *)SHAlloc(sizeof(SHChangeNotifyEntry) *
cItems);
+    item->apidl = SHAlloc(sizeof(SHChangeNotifyEntry) * cItems);
     for(i=0;i<cItems;i++)
     {
         item->apidl[i].pidl = ILClone(lpItems[i].pidl);
@@ -218,18 +187,18 @@
     item->hwnd = hwnd;
     item->uMsg = uMsg;
     item->wEventMask = wEventMask;
-    item->wSignalledEvent = 0;
     item->dwFlags = fSources;
+    item->id = InterlockedIncrement( &next_id );
     TRACE("new node: %s\n", NodeName( item ));
     EnterCriticalSection(&SHELL32_ChangenotifyCS);
-    AddNode(item);
+    list_add_tail( ¬ifications, &item->entry );
     LeaveCriticalSection(&SHELL32_ChangenotifyCS);
-    return (ULONG)item;
+    return item->id;
 }
 /*************************************************************************
@@ -243,25 +212,39 @@
     EnterCriticalSection(&SHELL32_ChangenotifyCS);
-    node = FindNode((HANDLE)hNotify);
-    if( node )
-        DeleteNode(node);
-
+    LIST_FOR_EACH_ENTRY( node, ¬ifications, NOTIFICATIONLIST, entry )
+    {
+        if (node->id == hNotify)
+        {
+            DeleteNode( node );
+            LeaveCriticalSection(&SHELL32_ChangenotifyCS);
+            return TRUE;
+        }
+    }
     LeaveCriticalSection(&SHELL32_ChangenotifyCS);
-    return node?TRUE:FALSE;
+    return FALSE;
 }
 /*************************************************************************
  * SHChangeNotifyUpdateEntryList                       [SHELL32.5]
  */
-EXTERN_C BOOL WINAPI SHChangeNotifyUpdateEntryList(DWORD unknown1, DWORD unknown2,
+BOOL WINAPI SHChangeNotifyUpdateEntryList(DWORD unknown1, DWORD unknown2,
                              DWORD unknown3, DWORD unknown4)
 {
     FIXME("(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
           unknown1, unknown2, unknown3, unknown4);
-    return -1;
-}
+    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 )
 {
@@ -270,8 +253,9 @@
         return FALSE;
     if (ILIsEqual( watched, changed ) )
         return TRUE;
-    if( sub && ILIsParent( watched, changed, TRUE ) )
+    if( sub && ILIsParent( watched, changed, FALSE ) )
         return TRUE;
+#ifdef __REACTOS__
     if (sub && _ILIsDesktop(watched)) {
         LPITEMIDLIST deskpidl;
         WCHAR wszPath[MAX_PATH];
@@ -292,6 +276,7 @@
         }
         ILFree(deskpidl);
     }
+#endif
     return FALSE;
 }
@@ -300,14 +285,25 @@
  */
 void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
 {
+    struct notification_recipients {
+        struct list entry;
+        HWND hwnd;
+        DWORD msg;
+        DWORD flags;
+    } *cur, *next;
+
+    HANDLE shared_data = NULL;
     LPITEMIDLIST Pidls[2];
     LPNOTIFICATIONLIST ptr;
-    UINT typeFlag = uFlags & SHCNF_TYPE;
+    struct list recipients;
     Pidls[0] = NULL;
     Pidls[1] = NULL;
-    TRACE("(0x%08x,0x%08x,%p,%p):stub.\n", wEventId, uFlags, dwItem1, dwItem2);
+    TRACE("(0x%08x,0x%08x,%p,%p)\n", wEventId, uFlags, dwItem1, dwItem2);
+
+    if(uFlags & ~(SHCNF_TYPE|SHCNF_FLUSH))
+        FIXME("ignoring unsupported flags: %x\n", uFlags);
     if( ( wEventId & SHCNE_NOITEMEVENTS ) && ( dwItem1 || dwItem2 ) )
     {
@@ -335,15 +331,16 @@
     }
     /* convert paths in IDLists*/
-    switch (typeFlag)
+    switch (uFlags & SHCNF_TYPE)
     {
     case SHCNF_PATHA:
-        if (dwItem1) Pidls[0] = SHSimpleIDListFromPathA((LPCSTR)dwItem1); //FIXME
-        if (dwItem2) Pidls[1] = SHSimpleIDListFromPathA((LPCSTR)dwItem2); //FIXME
+        if (dwItem1) Pidls[0] = SHSimpleIDListFromPathA(dwItem1); //FIXME
+        if (dwItem2) Pidls[1] = SHSimpleIDListFromPathA(dwItem2); //FIXME
         break;
     case SHCNF_PATHW:
-        if (dwItem1) Pidls[0] = SHSimpleIDListFromPathW((LPCWSTR)dwItem1);
-        if (dwItem2) Pidls[1] = SHSimpleIDListFromPathW((LPCWSTR)dwItem2);
+        if (dwItem1) Pidls[0] = SHSimpleIDListFromPathW(dwItem1);
+        if (dwItem2) Pidls[1] = SHSimpleIDListFromPathW(dwItem2);
+#ifdef __REACTOS__
         if (wEventId & (SHCNE_MKDIR | SHCNE_RMDIR | SHCNE_UPDATEDIR |
SHCNE_RENAMEFOLDER))
         {
             /*
@@ -379,10 +376,11 @@
                 ILFree(oldpidl);
             }
         }
+#endif
         break;
     case SHCNF_IDLIST:
-        Pidls[0] = (LPITEMIDLIST)dwItem1;
-        Pidls[1] = (LPITEMIDLIST)dwItem2;
+        Pidls[0] = ILClone(dwItem1);
+        Pidls[1] = ILClone(dwItem2);
         break;
     case SHCNF_PRINTERA:
     case SHCNF_PRINTERW:
@@ -390,31 +388,17 @@
         return;
     case SHCNF_DWORD:
     default:
-        FIXME("unknown type %08x\n",typeFlag);
+        FIXME("unknown type %08x\n", uFlags & SHCNF_TYPE);
         return;
     }
-    {
-        WCHAR path[MAX_PATH];
-
-        if( Pidls[0] && SHGetPathFromIDListW(Pidls[0], path ))
-            TRACE("notify %08x on item1 = %s\n", wEventId, debugstr_w(path));
-
-        if( Pidls[1] && SHGetPathFromIDListW(Pidls[1], path ))
-            TRACE("notify %08x on item2 = %s\n", wEventId, debugstr_w(path));
-    }
-
+    list_init(&recipients);
     EnterCriticalSection(&SHELL32_ChangenotifyCS);
-
-    /* loop through the list */
-    for( ptr = head; ptr; ptr = ptr->next )
-    {
-        BOOL notify;
+    LIST_FOR_EACH_ENTRY( ptr, ¬ifications, NOTIFICATIONLIST, entry )
+    {
+        struct notification_recipients *item;
+        BOOL notify = FALSE;
         DWORD i;
-
-        notify = FALSE;
-
-        TRACE("trying %p\n", ptr);
         for( i=0; (i<ptr->cidl) && !notify ; i++ )
         {
@@ -437,31 +421,71 @@
         if( !notify )
             continue;
-        ptr->pidlSignaled = ILClone(Pidls[0]);
-
-        TRACE("notifying %s, event %s(%x) before\n", NodeName( ptr ),
DumpEvent(
-               wEventId ),wEventId );
-
-        ptr->wSignalledEvent |= wEventId;
-
-        if (ptr->dwFlags  & SHCNRF_NewDelivery)
-            SendMessageW(ptr->hwnd, ptr->uMsg, (WPARAM) ptr, (LPARAM)
GetCurrentProcessId());
-        else
-            SendMessageW(ptr->hwnd, ptr->uMsg, (WPARAM)Pidls, wEventId);
-
-        TRACE("notifying %s, event %s(%x) after\n", NodeName( ptr ), DumpEvent(
-                wEventId ),wEventId );
-
-    }
-    TRACE("notify Done\n");
+        item = SHAlloc(sizeof(struct notification_recipients));
+        if(!item) {
+            ERR("out of memory\n");
+            continue;
+        }
+
+        item->hwnd = ptr->hwnd;
+        item->msg = ptr->uMsg;
+        item->flags = ptr->dwFlags;
+        list_add_tail(&recipients, &item->entry);
+    }
     LeaveCriticalSection(&SHELL32_ChangenotifyCS);
-    /* if we allocated it, free it. The ANSI flag is also set in its Unicode sibling. */
-    if ((typeFlag & SHCNF_PATHA) || (typeFlag & SHCNF_PRINTERA))
-    {
-        SHFree((LPITEMIDLIST)Pidls[0]);
-        SHFree((LPITEMIDLIST)Pidls[1]);
-    }
+    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);
+        }
+
+        list_remove(&cur->entry);
+        SHFree(cur);
+    }
+    SHFreeShared(shared_data, GetCurrentProcessId());
+    SHFree(Pidls[0]);
+    SHFree(Pidls[1]);
+
+#ifndef __REACTOS__
+    if (wEventId & SHCNE_ASSOCCHANGED)
+    {
+        static const WCHAR args[] = {' ','-','a',0 };
+        TRACE("refreshing file type associations\n");
+        run_winemenubuilder( args );
+    }
+#endif
 }
 /*************************************************************************
@@ -492,26 +516,28 @@
        LPITEMIDLIST **lppidls,
        LPLONG lpwEventId)
 {
-    DWORD i;
-    LPNOTIFICATIONLIST node;
-    LPCITEMIDLIST *idlist;
+    struct new_delivery_notification *ndn;
+    UINT offset;
     TRACE("%p %08x %p %p\n", hChange, dwProcessId, lppidls, lpwEventId);
-    node = FindNode( hChange );
-    if( node )
-    {
-        idlist = (LPCITEMIDLIST *)SHAlloc( sizeof(LPCITEMIDLIST *) * node->cidl );
-        for(i=0; i<node->cidl; i++)
-            idlist[i] = (LPCITEMIDLIST)node->pidlSignaled;
-        *lpwEventId = node->wSignalledEvent;
-        *lppidls = (LPITEMIDLIST*)idlist;
-        node->wSignalledEvent = 0;
-    }
-    else
-        ERR("Couldn't find %p\n", hChange );
-
-    return (HANDLE) node;
+    ndn = SHLockShared(hChange, dwProcessId);
+    if(!ndn) {
+        WARN("SHLockShared failed\n");
+        return NULL;
+    }
+
+    if(lppidls) {
+        offset = (ndn->pidl1_size+sizeof(int)-1)/sizeof(int)*sizeof(int);
+        ndn->pidls[0] = ndn->pidl1_size ? (LPITEMIDLIST)ndn->data : NULL;
+        ndn->pidls[1] = ndn->pidl2_size ? (LPITEMIDLIST)(ndn->data+offset) :
NULL;
+        *lppidls = ndn->pidls;
+    }
+
+    if(lpwEventId)
+        *lpwEventId = ndn->event;
+
+    return ndn;
 }
 /*************************************************************************
@@ -519,14 +545,14 @@
  */
 BOOL WINAPI SHChangeNotification_Unlock ( HANDLE hLock)
 {
-    TRACE("\n");
-    return 1;
+    TRACE("%p\n", hLock);
+    return SHUnlockShared(hLock);
 }
 /*************************************************************************
  * NTSHChangeNotifyDeregister                  [SHELL32.641]
  */
-EXTERN_C DWORD WINAPI NTSHChangeNotifyDeregister(ULONG x1)
+DWORD WINAPI NTSHChangeNotifyDeregister(ULONG x1)
 {
     FIXME("(0x%08x):semi stub.\n",x1);