[SHELL32] Implement the CUserNotification class, which implements the IUserNotificati...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 7 Feb 2018 01:20:26 +0000 (02:20 +0100)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 15 Feb 2018 21:38:22 +0000 (22:38 +0100)
dll/win32/shell32/CMakeLists.txt
dll/win32/shell32/CUserNotification.cpp [new file with mode: 0644]
dll/win32/shell32/CUserNotification.h [new file with mode: 0644]
dll/win32/shell32/precomp.h
dll/win32/shell32/res/rgs/usernotification.rgs [new file with mode: 0644]
dll/win32/shell32/rgs_res.rc
dll/win32/shell32/shell32.cpp
dll/win32/shell32/shresdef.h
dll/win32/shell32/systray.cpp

index 8bdf3ee..76ebf22 100644 (file)
@@ -67,6 +67,7 @@ list(APPEND SOURCE
     CDefViewBckgrndMenu.cpp
     stubs.cpp
     systray.cpp
+    CUserNotification.cpp
     CDefaultContextMenu.cpp
     COpenWithMenu.cpp
     CNewMenu.cpp
diff --git a/dll/win32/shell32/CUserNotification.cpp b/dll/win32/shell32/CUserNotification.cpp
new file mode 100644 (file)
index 0000000..c76bd0b
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * Copyright 2018 Hermes Belusca-Maito
+ *
+ * Pass on icon notification messages to the systray implementation
+ * in the currently running shell.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "precomp.h"
+
+#include <mmsystem.h>
+#undef PlaySound
+
+WINE_DEFAULT_DEBUG_CHANNEL(shell_notify);
+
+
+/* Use Windows-compatible window callback message */
+#define WM_TRAYNOTIFY   (WM_USER + 100)
+
+/* Notification icon ID */
+#define ID_NOTIFY_ICON  0
+
+/* Balloon timers */
+#define ID_BALLOON_TIMEOUT      1
+#define ID_BALLOON_DELAYREMOVE  2
+#define ID_BALLOON_QUERYCONT    3
+#define ID_BALLOON_SHOWTIME     4
+
+#define BALLOON_DELAYREMOVE_TIMEOUT 250 // milliseconds
+
+
+CUserNotification::CUserNotification() :
+    m_hWorkerWnd(NULL),
+    m_hIcon(NULL),
+    m_dwInfoFlags(0),
+    m_uShowTime(15000),
+    m_uInterval(10000),
+    m_cRetryCount(-1),
+    m_uContinuePoolInterval(0),
+    m_bIsShown(FALSE),
+    m_hRes(S_OK),
+    m_pqc(NULL)
+{
+}
+
+CUserNotification::~CUserNotification()
+{
+    /* If we have a notification window... */
+    if (m_hWorkerWnd)
+    {
+        /* ... remove the notification icon and destroy the window */
+        RemoveIcon();
+        ::DestroyWindow(m_hWorkerWnd);
+        m_hWorkerWnd = NULL;
+    }
+
+    /* Destroy our local icon copy */
+    if (m_hIcon)
+        ::DestroyIcon(m_hIcon);
+}
+
+VOID CUserNotification::RemoveIcon()
+{
+    NOTIFYICONDATAW nid = {0};
+
+    nid.cbSize = NOTIFYICONDATAW_V3_SIZE; // sizeof(nid);
+    nid.hWnd = m_hWorkerWnd;
+    nid.uID  = ID_NOTIFY_ICON;
+
+    /* Remove the notification icon */
+    ::Shell_NotifyIconW(NIM_DELETE, &nid);
+}
+
+VOID CUserNotification::DelayRemoveIcon(IN HRESULT hRes)
+{
+    /* Set the return value for CUserNotification::Show() and defer icon removal */
+    m_hRes = hRes;
+    ::SetTimer(m_hWorkerWnd, ID_BALLOON_DELAYREMOVE,
+               BALLOON_DELAYREMOVE_TIMEOUT, NULL);
+}
+
+VOID CUserNotification::TimeoutIcon()
+{
+    /*
+     * The balloon timed out, we need to wait before showing it again.
+     * If we retried too many times, delete the notification icon.
+     */
+    if (m_cRetryCount > 0)
+    {
+        /* Decrement the retry count */
+        --m_cRetryCount;
+
+        /* Set the timeout interval timer */
+        ::SetTimer(m_hWorkerWnd, ID_BALLOON_TIMEOUT, m_uInterval, NULL);
+    }
+    else
+    {
+        /* No other retry: delete the notification icon */
+        DelayRemoveIcon(HRESULT_FROM_WIN32(ERROR_CANCELLED));
+    }
+}
+
+VOID CUserNotification::SetUpNotifyData(
+    IN UINT uFlags,
+    IN OUT PNOTIFYICONDATAW pnid)
+{
+    pnid->cbSize = NOTIFYICONDATAW_V3_SIZE; // sizeof(nid);
+    pnid->hWnd = m_hWorkerWnd;
+    pnid->uID  = ID_NOTIFY_ICON;
+    // pnid->uVersion = NOTIFYICON_VERSION;
+
+    if (uFlags & NIF_MESSAGE)
+    {
+        pnid->uFlags |= NIF_MESSAGE;
+        pnid->uCallbackMessage = WM_TRAYNOTIFY;
+    }
+
+    if (uFlags & NIF_ICON)
+    {
+        pnid->uFlags |= NIF_ICON;
+        /* Use a default icon if we do not have one already */
+        pnid->hIcon = (m_hIcon ? m_hIcon : LoadIcon(NULL, IDI_WINLOGO));
+    }
+
+    if (uFlags & NIF_TIP)
+    {
+        pnid->uFlags |= NIF_TIP;
+        ::StringCchCopyW(pnid->szTip, _countof(pnid->szTip), m_szTip);
+    }
+
+    if (uFlags & NIF_INFO)
+    {
+        pnid->uFlags |= NIF_INFO;
+
+        // pnid->uTimeout    = m_uShowTime; // NOTE: Deprecated
+        pnid->dwInfoFlags = m_dwInfoFlags;
+
+        ::StringCchCopyW(pnid->szInfo, _countof(pnid->szInfo), m_szInfo);
+        ::StringCchCopyW(pnid->szInfoTitle, _countof(pnid->szInfoTitle), m_szInfoTitle);
+    }
+}
+
+
+/* IUserNotification Implementation */
+
+HRESULT STDMETHODCALLTYPE
+CUserNotification::SetBalloonInfo(
+    IN LPCWSTR pszTitle,
+    IN LPCWSTR pszText,
+    IN DWORD dwInfoFlags)
+{
+    NOTIFYICONDATAW nid = {0};
+
+    m_szInfo      = pszText;
+    m_szInfoTitle = pszTitle;
+    m_dwInfoFlags = dwInfoFlags;
+
+    /* Update the notification icon if we have one */
+    if (!m_hWorkerWnd)
+        return S_OK;
+
+    /* Modify the notification icon */
+    SetUpNotifyData(NIF_INFO, &nid);
+    if (::Shell_NotifyIconW(NIM_MODIFY, &nid))
+        return S_OK;
+    else
+        return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE
+CUserNotification::SetBalloonRetry(
+    IN DWORD dwShowTime,  // Time intervals in milliseconds
+    IN DWORD dwInterval,
+    IN UINT cRetryCount)
+{
+    m_uShowTime   = dwShowTime;
+    m_uInterval   = dwInterval;
+    m_cRetryCount = cRetryCount;
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE
+CUserNotification::SetIconInfo(
+    IN HICON hIcon,
+    IN LPCWSTR pszToolTip)
+{
+    NOTIFYICONDATAW nid = {0};
+
+    /* Destroy our local icon copy */
+    if (m_hIcon)
+        ::DestroyIcon(m_hIcon);
+
+    if (hIcon)
+    {
+        /* Copy the icon from the user */
+        m_hIcon = ::CopyIcon(hIcon);
+    }
+    else
+    {
+        /* Use the same icon as the one for the balloon if specified */
+        UINT uIcon = (m_dwInfoFlags & NIIF_ICON_MASK);
+        LPCWSTR pIcon = NULL;
+
+        if (uIcon == NIIF_INFO)
+            pIcon = IDI_INFORMATION;
+        else if (uIcon == NIIF_WARNING)
+            pIcon = IDI_WARNING;
+        else if (uIcon == NIIF_ERROR)
+            pIcon = IDI_ERROR;
+        else if (uIcon == NIIF_USER)
+            pIcon = NULL;
+
+        m_hIcon = (pIcon ? ::LoadIconW(NULL, pIcon) : NULL);
+    }
+
+    m_szTip = pszToolTip;
+
+    /* Update the notification icon if we have one */
+    if (!m_hWorkerWnd)
+        return S_OK;
+
+    /* Modify the notification icon */
+    SetUpNotifyData(NIF_ICON | NIF_TIP, &nid);
+    if (::Shell_NotifyIconW(NIM_MODIFY, &nid))
+        return S_OK;
+    else
+        return E_FAIL;
+}
+
+
+LRESULT CALLBACK
+CUserNotification::WorkerWndProc(
+    IN HWND hWnd,
+    IN UINT uMsg,
+    IN WPARAM wParam,
+    IN LPARAM lParam)
+{
+    /* Retrieve the current user notification object stored in the window extra bits */
+    CUserNotification* pThis = reinterpret_cast<CUserNotification*>(::GetWindowLongPtrW(hWnd, 0));
+    ASSERT(pThis);
+    ASSERT(hWnd == pThis->m_hWorkerWnd);
+
+    TRACE("Msg = 0x%x\n", uMsg);
+    switch (uMsg)
+    {
+        /*
+         * We do not receive any WM_(NC)CREATE message since worker windows
+         * are first created using the default window procedure DefWindowProcW.
+         * The window procedure is changed only subsequently to the user one.
+         * We however receive WM_(NC)DESTROY messages.
+         */
+        case WM_DESTROY:
+        {
+            /* Post a WM_QUIT message only if the Show() method's message loop is running */
+            if (pThis->m_bIsShown)
+                ::PostQuitMessage(0);
+            return 0;
+        }
+
+        case WM_NCDESTROY:
+        {
+            ::SetWindowLongPtrW(hWnd, 0, (LONG_PTR)NULL);
+            pThis->m_hWorkerWnd = NULL;
+            return 0;
+        }
+
+        case WM_QUERYENDSESSION:
+        {
+            /*
+             * User session is ending or a shutdown is occurring: perform cleanup.
+             * Set the return value for CUserNotification::Show() and remove the notification.
+             */
+            pThis->m_hRes = HRESULT_FROM_WIN32(ERROR_CANCELLED);
+            pThis->RemoveIcon();
+            ::DestroyWindow(pThis->m_hWorkerWnd);
+            return TRUE;
+        }
+
+        case WM_TIMER:
+        {
+            TRACE("WM_TIMER(0x%lx)\n", wParam);
+
+            /* Destroy the associated timer */
+            ::KillTimer(hWnd, (UINT_PTR)wParam);
+
+            if (wParam == ID_BALLOON_TIMEOUT)
+            {
+                /* Timeout interval timer expired: display the balloon again */
+                NOTIFYICONDATAW nid = {0};
+                pThis->SetUpNotifyData(NIF_INFO, &nid);
+                ::Shell_NotifyIconW(NIM_MODIFY, &nid);
+            }
+            else if (wParam == ID_BALLOON_DELAYREMOVE)
+            {
+                /* Delay-remove timer expired: remove the notification */
+                pThis->RemoveIcon();
+                ::DestroyWindow(pThis->m_hWorkerWnd);
+            }
+            else if (wParam == ID_BALLOON_QUERYCONT)
+            {
+                /*
+                 * Query-continue timer expired: ask the user whether the
+                 * notification should continue to be displayed or not.
+                 */
+                if (pThis->m_pqc && pThis->m_pqc->QueryContinue() == S_OK)
+                {
+                    /* The notification can be displayed */
+                    ::SetTimer(hWnd, ID_BALLOON_QUERYCONT, pThis->m_uContinuePoolInterval, NULL);
+                }
+                else
+                {
+                    /* The notification should be removed */
+                    pThis->DelayRemoveIcon(S_FALSE);
+                }
+            }
+            else if (wParam == ID_BALLOON_SHOWTIME)
+            {
+                /* Show-time timer expired: wait before showing the balloon again */
+                pThis->TimeoutIcon();
+            }
+            return 0;
+        }
+
+        /*
+         * Shell User Notification message.
+         * We use NOTIFYICON_VERSION == 0 or 3 callback version, with:
+         * wParam == identifier of the taskbar icon in which the event occurred;
+         * lParam == holds the mouse or keyboard message associated with the event.
+         */
+        case WM_TRAYNOTIFY:
+        {
+            TRACE("WM_TRAYNOTIFY - wParam = 0x%lx ; lParam = 0x%lx\n", wParam, lParam);
+            ASSERT(wParam == ID_NOTIFY_ICON);
+
+            switch (lParam)
+            {
+                case NIN_BALLOONSHOW:
+                    TRACE("NIN_BALLOONSHOW\n");
+                    break;
+
+                case NIN_BALLOONHIDE:
+                    TRACE("NIN_BALLOONHIDE\n");
+                    break;
+
+                /* The balloon timed out, or the user closed it by clicking on the 'X' button */
+                case NIN_BALLOONTIMEOUT:
+                {
+                    TRACE("NIN_BALLOONTIMEOUT\n");
+                    pThis->TimeoutIcon();
+                    break;
+                }
+
+                /* The user clicked on the balloon: delete the notification icon */
+                case NIN_BALLOONUSERCLICK:
+                    TRACE("NIN_BALLOONUSERCLICK\n");
+                    /* Fall back to icon click behaviour */
+
+                /* The user clicked on the notification icon: delete it */
+                case WM_LBUTTONDOWN:
+                case WM_RBUTTONDOWN:
+                {
+                    pThis->DelayRemoveIcon(S_OK);
+                    break;
+                }
+
+                default:
+                    break;
+            }
+
+            return 0;
+        }
+    }
+
+    return ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
+}
+
+
+// Blocks until the notification times out.
+HRESULT STDMETHODCALLTYPE
+CUserNotification::Show(
+    IN IQueryContinue* pqc,
+    IN DWORD dwContinuePollInterval)
+{
+    NOTIFYICONDATAW nid = {0};
+    MSG msg;
+
+    /* Create the hidden notification message worker window if we do not have one already */
+    if (!m_hWorkerWnd)
+    {
+        m_hWorkerWnd = ::SHCreateWorkerWindowW(CUserNotification::WorkerWndProc,
+                                               NULL, 0, 0, NULL, (LONG_PTR)this);
+        if (!m_hWorkerWnd)
+        {
+            FAILED_UNEXPECTEDLY(E_FAIL);
+            return E_FAIL;
+        }
+
+        /* Add and display the notification icon */
+        SetUpNotifyData(NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_INFO, &nid);
+        if (!::Shell_NotifyIconW(NIM_ADD, &nid))
+        {
+            ::DestroyWindow(m_hWorkerWnd);
+            m_hWorkerWnd = NULL;
+            return E_FAIL;
+        }
+    }
+
+    m_hRes = S_OK;
+
+    /* Set up the user-continue callback mechanism */
+    m_pqc = pqc;
+    if (pqc)
+    {
+        m_uContinuePoolInterval = dwContinuePollInterval;
+        ::SetTimer(m_hWorkerWnd, ID_BALLOON_QUERYCONT, m_uContinuePoolInterval, NULL);
+    }
+
+    /* Control how long the balloon notification is displayed */
+    if ((nid.uFlags & NIF_INFO) && !*nid.szInfo /* && !*nid.szInfoTitle */)
+        ::SetTimer(m_hWorkerWnd, ID_BALLOON_SHOWTIME, m_uShowTime, NULL);
+
+    /* Dispatch messsages to the worker window */
+    m_bIsShown = TRUE;
+    while (::GetMessageW(&msg, NULL, 0, 0))
+    {
+        ::TranslateMessage(&msg);
+        ::DispatchMessageW(&msg);
+    }
+    m_bIsShown = FALSE;
+
+    /* Reset the user-continue callback mechanism */
+    if (pqc)
+    {
+        ::KillTimer(m_hWorkerWnd, ID_BALLOON_QUERYCONT);
+        m_uContinuePoolInterval = 0;
+    }
+    m_pqc = NULL;
+
+    /* Return the notification error code */
+    return m_hRes;
+}
+
+#if 0   // IUserNotification2
+// Blocks until the notification times out.
+HRESULT STDMETHODCALLTYPE
+CUserNotification::Show(
+    IN IQueryContinue* pqc,
+    IN DWORD dwContinuePollInterval,
+    IN IUserNotificationCallback* pSink)
+{
+    return S_OK;
+}
+#endif
+
+HRESULT STDMETHODCALLTYPE
+CUserNotification::PlaySound(
+    IN LPCWSTR pszSoundName)
+{
+    /* Call the Win32 API - Ignore the PlaySoundW() return value as on Windows */
+    ::PlaySoundW(pszSoundName,
+                 NULL,
+                 SND_ALIAS | SND_APPLICATION |
+                 SND_NOSTOP | SND_NODEFAULT | SND_ASYNC);
+    return S_OK;
+}
diff --git a/dll/win32/shell32/CUserNotification.h b/dll/win32/shell32/CUserNotification.h
new file mode 100644 (file)
index 0000000..4f01e0c
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2018 Hermes Belusca-Maito
+ *
+ * Pass on icon notification messages to the systray implementation
+ * in the currently running shell.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _USERNOTIFICATION_H_
+#define _USERNOTIFICATION_H_
+
+#undef PlaySound
+
+class CUserNotification :
+    public CComCoClass<CUserNotification, &CLSID_UserNotification>,
+    public CComObjectRootEx<CComMultiThreadModelNoCS>,
+    public IUserNotification
+//  public IUserNotification2   // On Vista+
+{
+private:
+    HWND  m_hWorkerWnd;
+    HICON m_hIcon;
+    DWORD m_dwInfoFlags;
+    UINT  m_uShowTime;
+    UINT  m_uInterval;
+    UINT  m_cRetryCount;
+    UINT  m_uContinuePoolInterval;
+    BOOL  m_bIsShown;
+    HRESULT m_hRes;
+    IQueryContinue* m_pqc;
+    CStringW m_szTip;
+    CStringW m_szInfo;
+    CStringW m_szInfoTitle;
+
+private:
+    VOID RemoveIcon();
+    VOID DelayRemoveIcon(IN HRESULT hRes);
+    VOID TimeoutIcon();
+
+    VOID SetUpNotifyData(
+        IN UINT uFlags,
+        IN OUT PNOTIFYICONDATAW pnid);
+
+    static LRESULT CALLBACK
+    WorkerWndProc(
+        IN HWND hWnd,
+        IN UINT uMsg,
+        IN WPARAM wParam,
+        IN LPARAM lParam);
+
+public:
+    CUserNotification();
+    ~CUserNotification();
+
+    // IUserNotification
+    virtual HRESULT STDMETHODCALLTYPE SetBalloonInfo(
+        IN LPCWSTR pszTitle,
+        IN LPCWSTR pszText,
+        IN DWORD dwInfoFlags);
+
+    virtual HRESULT STDMETHODCALLTYPE SetBalloonRetry(
+        IN DWORD dwShowTime,  // Time intervals in milliseconds
+        IN DWORD dwInterval,
+        IN UINT cRetryCount);
+
+    virtual HRESULT STDMETHODCALLTYPE SetIconInfo(
+        IN HICON hIcon,
+        IN LPCWSTR pszToolTip);
+
+    // Blocks until the notification times out.
+    virtual HRESULT STDMETHODCALLTYPE Show(
+        IN IQueryContinue* pqc,
+        IN DWORD dwContinuePollInterval);
+
+    virtual HRESULT STDMETHODCALLTYPE PlaySound(
+        IN LPCWSTR pszSoundName);
+
+#if 0
+    // IUserNotification2
+    // Blocks until the notification times out.
+    virtual HRESULT STDMETHODCALLTYPE Show(
+        IN IQueryContinue* pqc,
+        IN DWORD dwContinuePollInterval,
+        IN IUserNotificationCallback* pSink);
+#endif
+
+    DECLARE_REGISTRY_RESOURCEID(IDR_USERNOTIFICATION)
+    DECLARE_NOT_AGGREGATABLE(CUserNotification)
+
+    DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+    BEGIN_COM_MAP(CUserNotification)
+        COM_INTERFACE_ENTRY_IID(IID_IUserNotification , IUserNotification )
+    //  COM_INTERFACE_ENTRY_IID(IID_IUserNotification2, IUserNotification2)
+    END_COM_MAP()
+};
+
+#endif /* _USERNOTIFICATION_H_ */
index f059e5b..f85423e 100644 (file)
@@ -84,6 +84,7 @@
 #include "shellmenu/CMenuSite.h"
 #include "shellmenu/CMergedFolder.h"
 #include "shellmenu/shellmenu.h"
+#include "CUserNotification.h"
 
 #include <wine/debug.h>
 #include <wine/unicode.h>
diff --git a/dll/win32/shell32/res/rgs/usernotification.rgs b/dll/win32/shell32/res/rgs/usernotification.rgs
new file mode 100644 (file)
index 0000000..61c585f
--- /dev/null
@@ -0,0 +1,43 @@
+HKCR
+{
+       NoRemove AppID
+       {
+               {0010890E-8789-413C-ADBC-48F5B511B3AF}
+               {
+                       val DllSurrogate = s ''
+                       val RunAs = s 'Interactive User'
+               }
+       }
+       NoRemove CLSID
+       {
+               ForceRemove {0010890E-8789-413C-ADBC-48F5B511B3AF} = s 'User Notification'
+               {
+                       InprocServer32 = s '%MODULE%'
+                       {
+                               val ThreadingModel = s 'Apartment'
+                       }
+                       val AppID = s '{0010890E-8789-413C-ADBC-48F5B511B3AF}'
+               }
+               NoRemove Interface
+               {
+                       ForceRemove {7307055C-B24A-486B-9F25-163E597A28A9} = s 'IQueryContinue'
+                       {
+                               NumMethods = s '4'
+                               {
+                               }
+                               ProxyStubClsid32 = s '{B8DA6310-E19B-11D0-933C-00A0C90DCAA9}'
+                               {
+                               }
+                       }
+                       ForceRemove {BA9711BA-5893-4787-A7E1-41277151550B} = s 'IUserNotification'
+                       {
+                               NumMethods = s '8'
+                               {
+                               }
+                               ProxyStubClsid32 = s '{B8DA6310-E19B-11D0-933C-00A0C90DCAA9}'
+                               {
+                               }
+                       }
+               }
+       }
+}
index 118eb51..67e072d 100644 (file)
@@ -26,4 +26,5 @@ IDR_DRVDEFEXT REGISTRY "res/rgs/shelldrvdefext.rgs"
 IDR_EXEDROPHANDLER REGISTRY "res/rgs/exedrophandler.rgs"
 IDR_MERGEDFOLDER REGISTRY "res/rgs/mergedfolder.rgs"
 IDR_REBARBANDSITE REGISTRY "res/rgs/rebarbandsite.rgs"
+IDR_USERNOTIFICATION REGISTRY "res/rgs/usernotification.rgs"
 IDR_SHELL REGISTRY "res/rgs/shell.rgs"
index 12c5a1e..ac0a3bd 100644 (file)
@@ -253,9 +253,10 @@ BEGIN_OBJECT_MAP(ObjectMap)
     OBJECT_ENTRY(CLSID_MergedFolder, CMergedFolder)
     OBJECT_ENTRY(CLSID_ExeDropHandler, CExeDropHandler)
     OBJECT_ENTRY(CLSID_QueryAssociations, CQueryAssociations)
+    OBJECT_ENTRY(CLSID_UserNotification, CUserNotification)
 END_OBJECT_MAP()
 
-CShell32Module                                gModule;
+CShell32Module  gModule;
 
 
 /***********************************************************************
@@ -311,7 +312,7 @@ STDAPI DllGetVersion(DLLVERSIONINFO *pdvi)
  * all are once per process
  *
  */
-HINSTANCE    shell32_hInstance;
+HINSTANCE   shell32_hInstance;
 
 /*************************************************************************
  * SHELL32 DllMain
index 5b607a6..53e4896 100644 (file)
 #define IDR_QUERYASSOCIATIONS   152
 #define IDR_MERGEDFOLDER        153
 #define IDR_REBARBANDSITE       154
-#define IDR_SHELL               155
+#define IDR_USERNOTIFICATION    155
+#define IDR_SHELL               156
index 482abf0..a64d689 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "precomp.h"
 
-WINE_DEFAULT_DEBUG_CHANNEL(shell);
+WINE_DEFAULT_DEBUG_CHANNEL(shell_notify);
 
 /*************************************************************************
  * Shell_NotifyIcon             [SHELL32.296]