shell32: Implement IExplorerBrowser::Advise and IExplorerBrowser::Unadvise.
diff --git a/dlls/shell32/ebrowser.c b/dlls/shell32/ebrowser.c
index e4e132b..3e56ce0 100644
--- a/dlls/shell32/ebrowser.c
+++ b/dlls/shell32/ebrowser.c
@@ -28,6 +28,7 @@
 #include "windef.h"
 #include "winbase.h"
 
+#include "wine/list.h"
 #include "wine/debug.h"
 #include "debughlp.h"
 
@@ -35,6 +36,12 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
+typedef struct _event_client {
+    struct list entry;
+    IExplorerBrowserEvents *pebe;
+    DWORD cookie;
+} event_client;
+
 typedef struct _ExplorerBrowserImpl {
     const IExplorerBrowserVtbl *lpVtbl;
     const IShellBrowserVtbl *lpsbVtbl;
@@ -47,11 +54,31 @@
     EXPLORER_BROWSER_OPTIONS eb_options;
     FOLDERSETTINGS fs;
 
+    struct list event_clients;
+    DWORD events_next_cookie;
+
     IShellView *psv;
     RECT sv_rc;
 } ExplorerBrowserImpl;
 
 /**************************************************************************
+ * Event functions.
+ */
+static void events_unadvise_all(ExplorerBrowserImpl *This)
+{
+    event_client *client, *curs;
+    TRACE("%p\n", This);
+
+    LIST_FOR_EACH_ENTRY_SAFE(client, curs, &This->event_clients, event_client, entry)
+    {
+        TRACE("Removing %p\n", client);
+        list_remove(&client->entry);
+        IExplorerBrowserEvents_Release(client->pebe);
+        HeapFree(GetProcessHeap(), 0, client);
+    }
+}
+
+/**************************************************************************
  * Helper functions
  */
 static void update_layout(ExplorerBrowserImpl *This)
@@ -248,6 +275,8 @@
         This->hwnd_sv = NULL;
     }
 
+    events_unadvise_all(This);
+
     DestroyWindow(This->hwnd_main);
     This->destroyed = TRUE;
 
@@ -314,18 +343,40 @@
                                                 DWORD *pdwCookie)
 {
     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
-    FIXME("stub, %p (%p, %p)\n", This, psbe, pdwCookie);
+    event_client *client;
+    TRACE("%p (%p, %p)\n", This, psbe, pdwCookie);
 
-    return E_NOTIMPL;
+    client = HeapAlloc(GetProcessHeap(), 0, sizeof(event_client));
+    client->pebe = psbe;
+    client->cookie = ++This->events_next_cookie;
+
+    IExplorerBrowserEvents_AddRef(psbe);
+    *pdwCookie = client->cookie;
+
+    list_add_tail(&This->event_clients, &client->entry);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI IExplorerBrowser_fnUnadvise(IExplorerBrowser *iface,
                                                   DWORD dwCookie)
 {
     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
-    FIXME("stub, %p (0x%x)\n", This, dwCookie);
+    event_client *client;
+    TRACE("%p (0x%x)\n", This, dwCookie);
 
-    return E_NOTIMPL;
+    LIST_FOR_EACH_ENTRY(client, &This->event_clients, event_client, entry)
+    {
+        if(client->cookie == dwCookie)
+        {
+            list_remove(&client->entry);
+            IExplorerBrowserEvents_Release(client->pebe);
+            HeapFree(GetProcessHeap(), 0, client);
+            return S_OK;
+        }
+    }
+
+    return E_INVALIDARG;
 }
 
 static HRESULT WINAPI IExplorerBrowser_fnSetOptions(IExplorerBrowser *iface,
@@ -652,6 +703,8 @@
     eb->lpVtbl = &vt_IExplorerBrowser;
     eb->lpsbVtbl = &vt_IShellBrowser;
 
+    list_init(&eb->event_clients);
+
     ret = IExplorerBrowser_QueryInterface((IExplorerBrowser*)eb, riid, ppv);
     IExplorerBrowser_Release((IExplorerBrowser*)eb);