* The Shell.. for a long time we dreamed of having a compatible, properly working...
[reactos.git] / reactos / dll / win32 / shell32 / wine / changenotify.c
similarity index 58%
rename from reactos/dll/win32/shell32/changenotify.cpp
rename to reactos/dll/win32/shell32/wine/changenotify.c
index 71eee58..8da87dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    shell change notification
+ *     shell change notification
  *
  * Copyright 2000 Juergen Schmied
  *
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "precomp.h"
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include <windef.h>
+#include <winbase.h>
+#include <shlobj.h>
+#include <undocshell.h>
+#include <shlwapi.h>
+#include <wine/debug.h>
+#include <wine/list.h>
+
+#include "pidl.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
-namespace
+static CRITICAL_SECTION SHELL32_ChangenotifyCS;
+static CRITICAL_SECTION_DEBUG critsect_debug =
 {
-    extern CRITICAL_SECTION SHELL32_ChangenotifyCS;
-    CRITICAL_SECTION_DEBUG critsect_debug =
-    {
-        0, 0, &SHELL32_ChangenotifyCS,
-        { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
-          0, 0, { (DWORD_PTR)(__FILE__ ": SHELL32_ChangenotifyCS") }
-    };
-    CRITICAL_SECTION SHELL32_ChangenotifyCS = { &critsect_debug, -1, 0, 0, 0, 0 };
-}
+    0, 0, &SHELL32_ChangenotifyCS,
+    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": SHELL32_ChangenotifyCS") }
+};
+static CRITICAL_SECTION SHELL32_ChangenotifyCS = { &critsect_debug, -1, 0, 0, 0, 0 };
 
 typedef SHChangeNotifyEntry *LPNOTIFYREGISTER;
 
 /* internal list of notification clients (internal) */
 typedef struct _NOTIFICATIONLIST
 {
-    struct _NOTIFICATIONLIST *next;
-    struct _NOTIFICATIONLIST *prev;
-    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*/
-
+       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 */
+       DWORD dwFlags;          /* client flags */
+       ULONG id;
 } NOTIFICATIONLIST, *LPNOTIFICATIONLIST;
 
-static NOTIFICATIONLIST *head, *tail;
+static struct list notifications = LIST_INIT( notifications );
+static LONG next_id;
 
 #define SHCNE_NOITEMEVENTS ( \
    SHCNE_ASSOCCHANGED )
@@ -112,44 +120,14 @@ static const char * NodeName(const NOTIFICATIONLIST *item)
     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++)
@@ -164,20 +142,22 @@ void InitChangeNotifications(void)
 
 void FreeChangeNotifications(void)
 {
+    LPNOTIFICATIONLIST ptr, next;
+
     TRACE("\n");
 
     EnterCriticalSection(&SHELL32_ChangenotifyCS);
 
-    while( head )
-        DeleteNode( head );
+    LIST_FOR_EACH_ENTRY_SAFE( ptr, next, &notifications, NOTIFICATIONLIST, entry )
+        DeleteNode( ptr );
 
     LeaveCriticalSection(&SHELL32_ChangenotifyCS);
 
-    // DeleteCriticalSection(&SHELL32_ChangenotifyCS); // static
+    DeleteCriticalSection(&SHELL32_ChangenotifyCS);
 }
 
 /*************************************************************************
- * SHChangeNotifyRegister            [SHELL32.2]
+ * SHChangeNotifyRegister                      [SHELL32.2]
  *
  */
 ULONG WINAPI
@@ -192,15 +172,13 @@ SHChangeNotifyRegister(
     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);
+       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);
@@ -209,22 +187,22 @@ SHChangeNotifyRegister(
     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( &notifications, &item->entry );
 
     LeaveCriticalSection(&SHELL32_ChangenotifyCS);
 
-    return (ULONG)item;
+    return item->id;
 }
 
 /*************************************************************************
- * SHChangeNotifyDeregister            [SHELL32.4]
+ * SHChangeNotifyDeregister                    [SHELL32.4]
  */
 BOOL WINAPI SHChangeNotifyDeregister(ULONG hNotify)
 {
@@ -234,27 +212,40 @@ BOOL WINAPI SHChangeNotifyDeregister(ULONG hNotify)
 
     EnterCriticalSection(&SHELL32_ChangenotifyCS);
 
-    node = FindNode((HANDLE)hNotify);
-    if( node )
-        DeleteNode(node);
-
+    LIST_FOR_EACH_ENTRY( node, &notifications, 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]
+ * SHChangeNotifyUpdateEntryList                       [SHELL32.5]
  */
-EXTERN_C BOOL WINAPI SHChangeNotifyUpdateEntryList(DWORD unknown1, DWORD unknown2,
-                  DWORD unknown3, DWORD unknown4)
+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 )
 {
     TRACE("%p %p %d\n", changed, watched, sub );
@@ -262,12 +253,14 @@ static BOOL should_notify( LPCITEMIDLIST changed, LPCITEMIDLIST watched, BOOL su
         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];
         SHGetSpecialFolderPathW(0, wszPath, CSIDL_DESKTOPDIRECTORY, FALSE);
-        LPITEMIDLIST deskpidl = SHSimpleIDListFromPathW(wszPath);
+        deskpidl = SHSimpleIDListFromPathW(wszPath);
         if (ILIsParent(deskpidl, changed, TRUE))
         {
             ILFree(deskpidl);
@@ -283,22 +276,34 @@ static BOOL should_notify( LPCITEMIDLIST changed, LPCITEMIDLIST watched, BOOL su
         }
         ILFree(deskpidl);
     }
+#endif
     return FALSE;
 }
 
 /*************************************************************************
- * SHChangeNotify                [SHELL32.@]
+ * SHChangeNotify                              [SHELL32.@]
  */
 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 ) )
     {
@@ -314,11 +319,11 @@ void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID
         return;
     }
 
-    if( ( ( wEventId & SHCNE_NOITEMEVENTS ) &&
+    if( ( ( wEventId & SHCNE_NOITEMEVENTS ) && 
           ( wEventId & ~SHCNE_NOITEMEVENTS ) ) ||
-        ( ( wEventId & SHCNE_ONEITEMEVENTS ) &&
+        ( ( wEventId & SHCNE_ONEITEMEVENTS ) && 
           ( wEventId & ~SHCNE_ONEITEMEVENTS ) ) ||
-        ( ( wEventId & SHCNE_TWOITEMEVENTS ) &&
+        ( ( wEventId & SHCNE_TWOITEMEVENTS ) && 
           ( wEventId & ~SHCNE_TWOITEMEVENTS ) ) )
     {
         WARN("mutually incompatible events listed\n");
@@ -326,15 +331,16 @@ void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID
     }
 
     /* 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))
         {
             /*
@@ -342,36 +348,39 @@ void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID
              * entry, and create a new one using a find data struct.
              */
             if (dwItem1 && Pidls[0]){
-                ILRemoveLastID(Pidls[0]);
                 WIN32_FIND_DATAW wfd;
+                LPITEMIDLIST oldpidl, newpidl;
                 LPWSTR p = PathFindFileNameW((LPCWSTR)dwItem1);
+                ILRemoveLastID(Pidls[0]);
                 lstrcpynW(&wfd.cFileName[0], p, MAX_PATH);
                 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
-                LPITEMIDLIST newpidl = _ILCreateFromFindDataW(&wfd);
-                LPITEMIDLIST oldpidl = ILClone(Pidls[0]);
+                newpidl = _ILCreateFromFindDataW(&wfd);
+                oldpidl = ILClone(Pidls[0]);
                 ILFree(Pidls[0]);
                 Pidls[0] = ILCombine(oldpidl, newpidl);
                 ILFree(newpidl);
                 ILFree(oldpidl);
             }
             if (dwItem2 && Pidls[1]){
-                ILRemoveLastID(Pidls[1]);
                 WIN32_FIND_DATAW wfd;
+                LPITEMIDLIST oldpidl, newpidl;
                 LPWSTR p = PathFindFileNameW((LPCWSTR)dwItem2);
+                ILRemoveLastID(Pidls[1]);
                 lstrcpynW(&wfd.cFileName[0], p, MAX_PATH);
                 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
-                LPITEMIDLIST newpidl = _ILCreateFromFindDataW(&wfd);
-                LPITEMIDLIST oldpidl = ILClone(Pidls[0]);
+                newpidl = _ILCreateFromFindDataW(&wfd);
+                oldpidl = ILClone(Pidls[0]);
                 ILFree(Pidls[1]);
                 Pidls[1] = ILCombine(oldpidl, newpidl);
                 ILFree(newpidl);
                 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:
@@ -379,32 +388,18 @@ void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID
         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 )
+    LIST_FOR_EACH_ENTRY( ptr, &notifications, NOTIFICATIONLIST, entry )
     {
-        BOOL notify;
+        struct notification_recipients *item;
+        BOOL notify = FALSE;
         DWORD i;
 
-        notify = FALSE;
-
-        TRACE("trying %p\n", ptr);
-
         for( i=0; (i<ptr->cidl) && !notify ; i++ )
         {
             LPCITEMIDLIST pidl = ptr->apidl[i].pidl;
@@ -426,31 +421,71 @@ void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID
         if( !notify )
             continue;
 
-        ptr->pidlSignaled = ILClone(Pidls[0]);
-
-        TRACE("notifying %s, event %s(%x) before\n", NodeName( ptr ), DumpEvent(
-               wEventId ),wEventId );
+        item = SHAlloc(sizeof(struct notification_recipients));
+        if(!item) {
+            ERR("out of memory\n");
+            continue;
+        }
 
-        ptr->wSignalledEvent |= wEventId;
+        item->hwnd = ptr->hwnd;
+        item->msg = ptr->uMsg;
+        item->flags = ptr->dwFlags;
+        list_add_tail(&recipients, &item->entry);
+    }
+    LeaveCriticalSection(&SHELL32_ChangenotifyCS);
 
-        if (ptr->dwFlags  & SHCNRF_NewDelivery)
-            SendMessageW(ptr->hwnd, ptr->uMsg, (WPARAM) ptr, (LPARAM) GetCurrentProcessId());
-        else
-            SendMessageW(ptr->hwnd, ptr->uMsg, (WPARAM)Pidls, wEventId);
+    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);
+                }
+            }
 
-        TRACE("notifying %s, event %s(%x) after\n", NodeName( ptr ), DumpEvent(
-                wEventId ),wEventId );
+            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);
     }
-    TRACE("notify Done\n");
-    LeaveCriticalSection(&SHELL32_ChangenotifyCS);
+    SHFreeShared(shared_data, GetCurrentProcessId());
+    SHFree(Pidls[0]);
+    SHFree(Pidls[1]);
 
-    /* if we allocated it, free it. The ANSI flag is also set in its Unicode sibling. */
-    if ((typeFlag & SHCNF_PATHA) || (typeFlag & SHCNF_PRINTERA))
+#ifndef __REACTOS__
+    if (wEventId & SHCNE_ASSOCCHANGED)
     {
-        SHFree((LPITEMIDLIST)Pidls[0]);
-        SHFree((LPITEMIDLIST)Pidls[1]);
+        static const WCHAR args[] = {' ','-','a',0 };
+        TRACE("refreshing file type associations\n");
+        run_winemenubuilder( args );
     }
+#endif
 }
 
 /*************************************************************************
@@ -473,53 +508,51 @@ EXTERN_C ULONG WINAPI NTSHChangeNotifyRegister(
 }
 
 /*************************************************************************
- * SHChangeNotification_Lock            [SHELL32.644]
+ * SHChangeNotification_Lock                   [SHELL32.644]
  */
 HANDLE WINAPI SHChangeNotification_Lock(
-    HANDLE hChange,
-    DWORD dwProcessId,
-    LPITEMIDLIST **lppidls,
-    LPLONG lpwEventId)
+       HANDLE hChange,
+       DWORD dwProcessId,
+       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);
 
-    /* EnterCriticalSection(&SHELL32_ChangenotifyCS); */
+    ndn = SHLockShared(hChange, dwProcessId);
+    if(!ndn) {
+        WARN("SHLockShared failed\n");
+        return NULL;
+    }
 
-    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;
+    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;
     }
-    else
-        ERR("Couldn't find %p\n", hChange );
 
-    /* LeaveCriticalSection(&SHELL32_ChangenotifyCS); */
+    if(lpwEventId)
+        *lpwEventId = ndn->event;
 
-    return (HANDLE) node;
+    return ndn;
 }
 
 /*************************************************************************
- * SHChangeNotification_Unlock            [SHELL32.645]
+ * SHChangeNotification_Unlock                 [SHELL32.645]
  */
 BOOL WINAPI SHChangeNotification_Unlock ( HANDLE hLock)
 {
-    TRACE("\n");
-    return 1;
+    TRACE("%p\n", hLock);
+    return SHUnlockShared(hLock);
 }
 
 /*************************************************************************
- * NTSHChangeNotifyDeregister            [SHELL32.641]
+ * NTSHChangeNotifyDeregister                  [SHELL32.641]
  */
-EXTERN_C DWORD WINAPI NTSHChangeNotifyDeregister(ULONG x1)
+DWORD WINAPI NTSHChangeNotifyDeregister(ULONG x1)
 {
     FIXME("(0x%08x):semi stub.\n",x1);