xref: /reactos/dll/shellext/stobject/hotplug.cpp (revision 8c30fdab)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:     ReactOS system libraries
3c2c66affSColin Finck  * LICENSE:     GPL - See COPYING in the top level directory
4c2c66affSColin Finck  * FILE:        dll/shellext/stobject/hotplug.cpp
57fbc5f42SShriraj Sawant  * PURPOSE:     Removable devices notification icon handler
67fbc5f42SShriraj Sawant  * PROGRAMMERS: Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com>
7c2c66affSColin Finck  */
8e15874b4SAmine Khaldi 
9c2c66affSColin Finck #include "precomp.h"
10e15874b4SAmine Khaldi 
117fbc5f42SShriraj Sawant #include <atlsimpcoll.h>
127fbc5f42SShriraj Sawant #include <dbt.h>
137fbc5f42SShriraj Sawant #include <cfgmgr32.h>
14e15874b4SAmine Khaldi #include <shlwapi.h>
15c2c66affSColin Finck 
167fbc5f42SShriraj Sawant #define DISPLAY_NAME_LEN 40
17c2c66affSColin Finck 
187fbc5f42SShriraj Sawant //BOOL WINAPI UnregisterDeviceNotification(HDEVNOTIFY Handle);
197fbc5f42SShriraj Sawant 
207fbc5f42SShriraj Sawant CSimpleArray<DEVINST> g_devList;
217fbc5f42SShriraj Sawant /*static HDEVNOTIFY g_hDevNotify = NULL;*/
22c2c66affSColin Finck static HICON g_hIconHotplug = NULL;
237fbc5f42SShriraj Sawant static LPCWSTR g_strTooltip = L"Safely Remove Hardware and Eject Media";
247fbc5f42SShriraj Sawant static WCHAR g_strMenuSel[DISPLAY_NAME_LEN];
257fbc5f42SShriraj Sawant static BOOL g_IsRemoving = FALSE;
26c2c66affSColin Finck 
277fbc5f42SShriraj Sawant /*++
287fbc5f42SShriraj Sawant * @name EnumHotpluggedDevices
297fbc5f42SShriraj Sawant *
307fbc5f42SShriraj Sawant * Enumerates the connected safely removable devices.
317fbc5f42SShriraj Sawant *
327fbc5f42SShriraj Sawant * @param devList
337fbc5f42SShriraj Sawant *        List of device instances, representing the currently attached devices.
347fbc5f42SShriraj Sawant *
357fbc5f42SShriraj Sawant * @return The error code.
367fbc5f42SShriraj Sawant *
377fbc5f42SShriraj Sawant *--*/
387fbc5f42SShriraj Sawant HRESULT EnumHotpluggedDevices(CSimpleArray<DEVINST> &devList)
397fbc5f42SShriraj Sawant {
407fbc5f42SShriraj Sawant     devList.RemoveAll(); // Clear current devList
417fbc5f42SShriraj Sawant     HDEVINFO hdev = SetupDiGetClassDevs(NULL, NULL, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT);
427fbc5f42SShriraj Sawant     if (INVALID_HANDLE_VALUE == hdev)
437fbc5f42SShriraj Sawant         return E_HANDLE;
447fbc5f42SShriraj Sawant     SP_DEVINFO_DATA did = { 0 };
457fbc5f42SShriraj Sawant     did.cbSize = sizeof(did);
467fbc5f42SShriraj Sawant 
477fbc5f42SShriraj Sawant     // Enumerate all the attached devices.
487fbc5f42SShriraj Sawant     for (int idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); idev++)
497fbc5f42SShriraj Sawant     {
507fbc5f42SShriraj Sawant         DWORD dwCapabilities = 0, dwSize = sizeof(dwCapabilities);
517fbc5f42SShriraj Sawant         WCHAR dispName[DISPLAY_NAME_LEN];
527fbc5f42SShriraj Sawant         ULONG ulStatus = 0, ulPnum = 0, ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR);
537fbc5f42SShriraj Sawant         CONFIGRET cr = CM_Get_DevNode_Status(&ulStatus, &ulPnum, did.DevInst, 0);
547fbc5f42SShriraj Sawant         if (cr != CR_SUCCESS)
557fbc5f42SShriraj Sawant             continue;
567fbc5f42SShriraj Sawant         cr = CM_Get_DevNode_Registry_Property(did.DevInst, CM_DRP_DEVICEDESC, NULL, dispName, &ulLength, 0);
577fbc5f42SShriraj Sawant         if (cr != CR_SUCCESS)
587fbc5f42SShriraj Sawant             continue;
597fbc5f42SShriraj Sawant         cr = CM_Get_DevNode_Registry_Property(did.DevInst, CM_DRP_CAPABILITIES, NULL, &dwCapabilities, &dwSize, 0);
607fbc5f42SShriraj Sawant         if (cr != CR_SUCCESS)
617fbc5f42SShriraj Sawant             continue;
627fbc5f42SShriraj Sawant 
637fbc5f42SShriraj Sawant         // Filter and make list of only the appropriate safely removable devices.
647fbc5f42SShriraj Sawant         if ( (dwCapabilities & CM_DEVCAP_REMOVABLE) &&
657fbc5f42SShriraj Sawant             !(dwCapabilities & CM_DEVCAP_DOCKDEVICE) &&
667fbc5f42SShriraj Sawant             !(dwCapabilities & CM_DEVCAP_SURPRISEREMOVALOK) &&
677fbc5f42SShriraj Sawant             ((dwCapabilities & CM_DEVCAP_EJECTSUPPORTED) || (ulStatus & DN_DISABLEABLE)) &&
687fbc5f42SShriraj Sawant             !ulPnum)
697fbc5f42SShriraj Sawant         {
707fbc5f42SShriraj Sawant             devList.Add(did.DevInst);
717fbc5f42SShriraj Sawant         }
727fbc5f42SShriraj Sawant     }
737fbc5f42SShriraj Sawant     SetupDiDestroyDeviceInfoList(hdev);
747fbc5f42SShriraj Sawant 
757fbc5f42SShriraj Sawant     if (NO_ERROR != GetLastError() && ERROR_NO_MORE_ITEMS != GetLastError())
767fbc5f42SShriraj Sawant     {
777fbc5f42SShriraj Sawant         return E_UNEXPECTED;
787fbc5f42SShriraj Sawant     }
797fbc5f42SShriraj Sawant 
807fbc5f42SShriraj Sawant     return S_OK;
817fbc5f42SShriraj Sawant }
827fbc5f42SShriraj Sawant 
837fbc5f42SShriraj Sawant /*++
847fbc5f42SShriraj Sawant * @name NotifyBalloon
857fbc5f42SShriraj Sawant *
867fbc5f42SShriraj Sawant * Pops the balloon notification of the given notification icon.
877fbc5f42SShriraj Sawant *
887fbc5f42SShriraj Sawant * @param pSysTray
897fbc5f42SShriraj Sawant *        Provides interface for acquiring CSysTray information as required.
907fbc5f42SShriraj Sawant * @param szTitle
917fbc5f42SShriraj Sawant *        Title for the balloon notification.
927fbc5f42SShriraj Sawant * @param szInfo
937fbc5f42SShriraj Sawant *        Main content for the balloon notification.
947fbc5f42SShriraj Sawant * @param uId
957fbc5f42SShriraj Sawant *        Represents the particular notification icon.
967fbc5f42SShriraj Sawant *
977fbc5f42SShriraj Sawant * @return The error code.
987fbc5f42SShriraj Sawant *
997fbc5f42SShriraj Sawant *--*/
1007fbc5f42SShriraj Sawant HRESULT NotifyBalloon(CSysTray* pSysTray, LPCWSTR szTitle = NULL, LPCWSTR szInfo = NULL, UINT uId = ID_ICON_HOTPLUG)
1017fbc5f42SShriraj Sawant {
1025de33ab0SHermès Bélusca-Maïto     NOTIFYICONDATA nim = { 0 };
10342073979SHermès Bélusca-Maïto 
10442073979SHermès Bélusca-Maïto     nim.cbSize = sizeof(nim);
1057fbc5f42SShriraj Sawant     nim.uID = uId;
1067fbc5f42SShriraj Sawant     nim.hWnd = pSysTray->GetHWnd();
1077fbc5f42SShriraj Sawant 
1087fbc5f42SShriraj Sawant     nim.uFlags = NIF_INFO;
1097fbc5f42SShriraj Sawant     nim.uTimeout = 10;
1107fbc5f42SShriraj Sawant     nim.dwInfoFlags = NIIF_INFO;
1117fbc5f42SShriraj Sawant 
1127fbc5f42SShriraj Sawant     StringCchCopy(nim.szInfoTitle, _countof(nim.szInfoTitle), szTitle);
1137fbc5f42SShriraj Sawant     StringCchCopy(nim.szInfo, _countof(nim.szInfo), szInfo);
1147fbc5f42SShriraj Sawant     BOOL ret = Shell_NotifyIcon(NIM_MODIFY, &nim);
1157fbc5f42SShriraj Sawant 
1167fbc5f42SShriraj Sawant     Sleep(10000); /* As per windows, the balloon notification remains visible for atleast 10 sec.
1177fbc5f42SShriraj Sawant                      This timer maintains the same condition.
1187fbc5f42SShriraj Sawant                      Also it is required so that the icon doesn't hide instantly after last device is removed,
1197fbc5f42SShriraj Sawant                      as that will prevent popping of notification.
1207fbc5f42SShriraj Sawant                   */
1217fbc5f42SShriraj Sawant     StringCchCopy(nim.szInfoTitle, _countof(nim.szInfoTitle), L"");
1227fbc5f42SShriraj Sawant     StringCchCopy(nim.szInfo, _countof(nim.szInfo), L"");
1237fbc5f42SShriraj Sawant     ret = Shell_NotifyIcon(NIM_MODIFY, &nim);
1247fbc5f42SShriraj Sawant     g_IsRemoving = FALSE; /* This flag is used to prevent instant icon hiding after last device is removed.
1257fbc5f42SShriraj Sawant                              The above timer maintains the required state for the same.
1267fbc5f42SShriraj Sawant                           */
1277fbc5f42SShriraj Sawant     return ret ? S_OK : E_FAIL;
1287fbc5f42SShriraj Sawant }
129c2c66affSColin Finck 
130c2c66affSColin Finck HRESULT STDMETHODCALLTYPE Hotplug_Init(_In_ CSysTray * pSysTray)
131c2c66affSColin Finck {
132c2c66affSColin Finck     TRACE("Hotplug_Init\n");
1337fbc5f42SShriraj Sawant     g_hIconHotplug = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_HOTPLUG_OK));
1347fbc5f42SShriraj Sawant     EnumHotpluggedDevices(g_devList);
135c2c66affSColin Finck 
1367fbc5f42SShriraj Sawant     return pSysTray->NotifyIcon(NIM_ADD, ID_ICON_HOTPLUG, g_hIconHotplug, g_strTooltip, NIS_HIDDEN);
137c2c66affSColin Finck }
138c2c66affSColin Finck 
139c2c66affSColin Finck HRESULT STDMETHODCALLTYPE Hotplug_Update(_In_ CSysTray * pSysTray)
140c2c66affSColin Finck {
141c2c66affSColin Finck     TRACE("Hotplug_Update\n");
1427fbc5f42SShriraj Sawant 
1437fbc5f42SShriraj Sawant     if(g_devList.GetSize() || g_IsRemoving)
1447fbc5f42SShriraj Sawant         return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_HOTPLUG, g_hIconHotplug, g_strTooltip);
1457fbc5f42SShriraj Sawant     else
1467fbc5f42SShriraj Sawant         return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_HOTPLUG, g_hIconHotplug, g_strTooltip, NIS_HIDDEN);
147c2c66affSColin Finck }
148c2c66affSColin Finck 
149c2c66affSColin Finck HRESULT STDMETHODCALLTYPE Hotplug_Shutdown(_In_ CSysTray * pSysTray)
150c2c66affSColin Finck {
151c2c66affSColin Finck     TRACE("Hotplug_Shutdown\n");
152c2c66affSColin Finck 
153c2c66affSColin Finck     return pSysTray->NotifyIcon(NIM_DELETE, ID_ICON_HOTPLUG, NULL, NULL);
154c2c66affSColin Finck }
155c2c66affSColin Finck 
1567fbc5f42SShriraj Sawant static void _RunHotplug(CSysTray * pSysTray)
157c2c66affSColin Finck {
1587fbc5f42SShriraj Sawant     ShellExecuteW(pSysTray->GetHWnd(), L"open", L"rundll32.exe shell32.dll,Control_RunDLL hotplug.dll", NULL, NULL, SW_SHOWNORMAL);
159c2c66affSColin Finck }
160c2c66affSColin Finck 
1617fbc5f42SShriraj Sawant static void _ShowContextMenu(CSysTray * pSysTray)
162c2c66affSColin Finck {
1637fbc5f42SShriraj Sawant     HMENU hPopup = CreatePopupMenu();
1647fbc5f42SShriraj Sawant     ULONG ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR);
165c2c66affSColin Finck 
1667fbc5f42SShriraj Sawant     for (INT index = 0; index < g_devList.GetSize(); index++)
1677fbc5f42SShriraj Sawant     {
1687fbc5f42SShriraj Sawant         WCHAR dispName[DISPLAY_NAME_LEN], menuName[DISPLAY_NAME_LEN + 10];
1697fbc5f42SShriraj Sawant         CONFIGRET cr = CM_Get_DevNode_Registry_Property(g_devList[index], CM_DRP_DEVICEDESC, NULL, dispName, &ulLength, 0);
1707fbc5f42SShriraj Sawant         if (cr != CR_SUCCESS)
1717fbc5f42SShriraj Sawant             StrCpyW(dispName, L"Unknown Device");
172c2c66affSColin Finck 
1737fbc5f42SShriraj Sawant         swprintf(menuName, L"Eject %wS", dispName);
1747fbc5f42SShriraj Sawant         AppendMenuW(hPopup, MF_STRING, index+1, menuName);
1757fbc5f42SShriraj Sawant     }
176c2c66affSColin Finck 
177c2c66affSColin Finck     SetForegroundWindow(pSysTray->GetHWnd());
1787fbc5f42SShriraj Sawant     DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN;
1797fbc5f42SShriraj Sawant     POINT pt;
1807fbc5f42SShriraj Sawant     GetCursorPos(&pt);
181c2c66affSColin Finck 
1827fbc5f42SShriraj Sawant     DWORD id = TrackPopupMenuEx(hPopup, flags,
1837fbc5f42SShriraj Sawant         pt.x, pt.y,
1847fbc5f42SShriraj Sawant         pSysTray->GetHWnd(), NULL);
185c2c66affSColin Finck 
1867fbc5f42SShriraj Sawant     if (id > 0)
1877fbc5f42SShriraj Sawant     {
1887fbc5f42SShriraj Sawant         id--; // since array indices starts from zero.
1897fbc5f42SShriraj Sawant         CONFIGRET cr = CM_Get_DevNode_Registry_Property(g_devList[id], CM_DRP_DEVICEDESC, NULL, g_strMenuSel, &ulLength, 0);
1907fbc5f42SShriraj Sawant         if (cr != CR_SUCCESS)
1917fbc5f42SShriraj Sawant             StrCpyW(g_strMenuSel, L"Unknown Device");
1927fbc5f42SShriraj Sawant 
1937fbc5f42SShriraj Sawant         cr = CM_Request_Device_Eject_Ex(g_devList[id], 0, 0, 0, 0, 0);
1947fbc5f42SShriraj Sawant         if (cr != CR_SUCCESS)
1957fbc5f42SShriraj Sawant         {
1967fbc5f42SShriraj Sawant             WCHAR strInfo[128];
1977fbc5f42SShriraj Sawant             swprintf(strInfo, L"Problem Ejecting %wS", g_strMenuSel);
1987fbc5f42SShriraj Sawant             MessageBox(0, L"The device cannot be stopped right now! Try stopping it again later!", strInfo, MB_OKCANCEL | MB_ICONEXCLAMATION);
1997fbc5f42SShriraj Sawant         }
2007fbc5f42SShriraj Sawant         else
2017fbc5f42SShriraj Sawant         {
2027fbc5f42SShriraj Sawant             //MessageBox(0, L"Device ejected successfully!! You can safely remove the device now!", L"Safely Remove Hardware", MB_OKCANCEL | MB_ICONINFORMATION);
2037fbc5f42SShriraj Sawant             g_IsRemoving = TRUE;
2047fbc5f42SShriraj Sawant             g_devList.RemoveAt(id); /* thing is.. even after removing id at this point, the devnode_change occurs after some seconds of sucessful removal
2057fbc5f42SShriraj Sawant                                        and since pendrive is still plugged in it gets enumerated, if problem number is not filtered.
2067fbc5f42SShriraj Sawant                                     */
2077fbc5f42SShriraj Sawant         }
208c2c66affSColin Finck     }
209c2c66affSColin Finck 
2107fbc5f42SShriraj Sawant     DestroyMenu(hPopup);
2117fbc5f42SShriraj Sawant }
212c2c66affSColin Finck 
2137fbc5f42SShriraj Sawant static void _ShowContextMenuR(CSysTray * pSysTray)
2147fbc5f42SShriraj Sawant {
2157fbc5f42SShriraj Sawant     CString strMenu((LPWSTR)IDS_HOTPLUG_REMOVE_2);
216c2c66affSColin Finck     HMENU hPopup = CreatePopupMenu();
2177fbc5f42SShriraj Sawant     AppendMenuW(hPopup, MF_STRING, IDS_HOTPLUG_REMOVE_2, strMenu);
218754a35b2SEric Kohl     SetMenuDefaultItem(hPopup, IDS_HOTPLUG_REMOVE_2, FALSE);
219c2c66affSColin Finck 
2207fbc5f42SShriraj Sawant     SetForegroundWindow(pSysTray->GetHWnd());
2217fbc5f42SShriraj Sawant     DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN;
2227fbc5f42SShriraj Sawant     POINT pt;
2237fbc5f42SShriraj Sawant     GetCursorPos(&pt);
224c2c66affSColin Finck 
2257fbc5f42SShriraj Sawant     DWORD id = TrackPopupMenuEx(hPopup, flags,
2267fbc5f42SShriraj Sawant         pt.x, pt.y,
2277fbc5f42SShriraj Sawant         pSysTray->GetHWnd(), NULL);
228c2c66affSColin Finck 
2297fbc5f42SShriraj Sawant     if (id == IDS_HOTPLUG_REMOVE_2)
2307fbc5f42SShriraj Sawant     {
2317fbc5f42SShriraj Sawant         _RunHotplug(pSysTray);
2327fbc5f42SShriraj Sawant     }
233c2c66affSColin Finck 
234c2c66affSColin Finck     DestroyMenu(hPopup);
235c2c66affSColin Finck }
236c2c66affSColin Finck 
237c2c66affSColin Finck HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult)
238c2c66affSColin Finck {
2397fbc5f42SShriraj Sawant     HRESULT hr = E_FAIL;
240c2c66affSColin Finck     TRACE("Hotplug_Message uMsg=%d, wParam=%x, lParam=%x\n", uMsg, wParam, lParam);
241c2c66affSColin Finck 
242c2c66affSColin Finck     switch (uMsg)
243c2c66affSColin Finck     {
2447fbc5f42SShriraj Sawant         /*case WM_CREATE:
2457fbc5f42SShriraj Sawant             TRACE("Hotplug_Message: WM_CREATE\n");
2467fbc5f42SShriraj Sawant             DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
2477fbc5f42SShriraj Sawant 
2487fbc5f42SShriraj Sawant             ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
2497fbc5f42SShriraj Sawant             NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
2507fbc5f42SShriraj Sawant             NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
2517fbc5f42SShriraj Sawant 
2527fbc5f42SShriraj Sawant             g_hDevNotify = RegisterDeviceNotification(pSysTray->GetHWnd(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
2537fbc5f42SShriraj Sawant             if (g_hDevNotify != NULL)
2547fbc5f42SShriraj Sawant             {
2557fbc5f42SShriraj Sawant                 lResult = true;
2567fbc5f42SShriraj Sawant                 return S_OK;
2577fbc5f42SShriraj Sawant             }
2587fbc5f42SShriraj Sawant             return S_FALSE;*/
2597fbc5f42SShriraj Sawant 
260c2c66affSColin Finck         case WM_USER + 220:
261c2c66affSColin Finck             TRACE("Hotplug_Message: WM_USER+220\n");
262*8c30fdabSEric Kohl             if (wParam == HOTPLUG_SERVICE_FLAG)
263c2c66affSColin Finck             {
264*8c30fdabSEric Kohl                 if (lParam)
265*8c30fdabSEric Kohl                 {
266*8c30fdabSEric Kohl                     pSysTray->EnableService(HOTPLUG_SERVICE_FLAG, TRUE);
267c2c66affSColin Finck                     return Hotplug_Init(pSysTray);
268*8c30fdabSEric Kohl                 }
269c2c66affSColin Finck                 else
270*8c30fdabSEric Kohl                 {
271*8c30fdabSEric Kohl                     pSysTray->EnableService(HOTPLUG_SERVICE_FLAG, FALSE);
272c2c66affSColin Finck                     return Hotplug_Shutdown(pSysTray);
273c2c66affSColin Finck                 }
274*8c30fdabSEric Kohl             }
275c2c66affSColin Finck             return S_FALSE;
276c2c66affSColin Finck 
277c2c66affSColin Finck         case WM_USER + 221:
278c2c66affSColin Finck             TRACE("Hotplug_Message: WM_USER+221\n");
279*8c30fdabSEric Kohl             if (wParam == HOTPLUG_SERVICE_FLAG)
280c2c66affSColin Finck             {
281*8c30fdabSEric Kohl                 lResult = (LRESULT)pSysTray->IsServiceEnabled(HOTPLUG_SERVICE_FLAG);
282c2c66affSColin Finck                 return S_OK;
283c2c66affSColin Finck             }
284c2c66affSColin Finck             return S_FALSE;
285c2c66affSColin Finck 
2862baafa61SEric Kohl         case WM_TIMER:
2872baafa61SEric Kohl             if (wParam == HOTPLUG_TIMER_ID)
2882baafa61SEric Kohl             {
2892baafa61SEric Kohl                 KillTimer(pSysTray->GetHWnd(), HOTPLUG_TIMER_ID);
2902baafa61SEric Kohl                 _ShowContextMenu(pSysTray);
2912baafa61SEric Kohl             }
2922baafa61SEric Kohl             break;
2932baafa61SEric Kohl 
294c2c66affSColin Finck         case ID_ICON_HOTPLUG:
295c2c66affSColin Finck             Hotplug_Update(pSysTray);
296c2c66affSColin Finck 
297c2c66affSColin Finck             switch (lParam)
298c2c66affSColin Finck             {
299c2c66affSColin Finck                 case WM_LBUTTONDOWN:
300282b4397SEric Kohl                     SetTimer(pSysTray->GetHWnd(), HOTPLUG_TIMER_ID, GetDoubleClickTime(), NULL);
301c2c66affSColin Finck                     break;
302c2c66affSColin Finck 
303c2c66affSColin Finck                 case WM_LBUTTONUP:
304c2c66affSColin Finck                     break;
305c2c66affSColin Finck 
306c2c66affSColin Finck                 case WM_LBUTTONDBLCLK:
3072baafa61SEric Kohl                     KillTimer(pSysTray->GetHWnd(), HOTPLUG_TIMER_ID);
3087fbc5f42SShriraj Sawant                     _RunHotplug(pSysTray);
309c2c66affSColin Finck                     break;
310c2c66affSColin Finck 
311c2c66affSColin Finck                 case WM_RBUTTONDOWN:
312c2c66affSColin Finck                     break;
313c2c66affSColin Finck 
314c2c66affSColin Finck                 case WM_RBUTTONUP:
3157fbc5f42SShriraj Sawant                     _ShowContextMenuR(pSysTray);
316c2c66affSColin Finck                     break;
317c2c66affSColin Finck 
318c2c66affSColin Finck                 case WM_RBUTTONDBLCLK:
319c2c66affSColin Finck                     break;
320c2c66affSColin Finck 
321c2c66affSColin Finck                 case WM_MOUSEMOVE:
322c2c66affSColin Finck                     break;
323c2c66affSColin Finck             }
324c2c66affSColin Finck             return S_OK;
325c2c66affSColin Finck 
3267fbc5f42SShriraj Sawant         case WM_DEVICECHANGE:
3277fbc5f42SShriraj Sawant             switch (wParam)
3287fbc5f42SShriraj Sawant             {
3297fbc5f42SShriraj Sawant                 case DBT_DEVNODES_CHANGED:
3307fbc5f42SShriraj Sawant                     hr = EnumHotpluggedDevices(g_devList);
3317fbc5f42SShriraj Sawant                     if (FAILED(hr))
3327fbc5f42SShriraj Sawant                         return hr;
3337fbc5f42SShriraj Sawant 
3347fbc5f42SShriraj Sawant                     lResult = true;
3357fbc5f42SShriraj Sawant                     break;
3367fbc5f42SShriraj Sawant                 case DBT_DEVICEARRIVAL:
3377fbc5f42SShriraj Sawant                     break;
3387fbc5f42SShriraj Sawant                 case DBT_DEVICEQUERYREMOVE:
3397fbc5f42SShriraj Sawant                     break;
3407fbc5f42SShriraj Sawant                 case DBT_DEVICEQUERYREMOVEFAILED:
3417fbc5f42SShriraj Sawant                     break;
3427fbc5f42SShriraj Sawant                 case DBT_DEVICEREMOVECOMPLETE:
3437fbc5f42SShriraj Sawant                     WCHAR strInfo[128];
3447fbc5f42SShriraj Sawant                     swprintf(strInfo, L"The %wS can now be safely removed from the system.", g_strMenuSel);
3457fbc5f42SShriraj Sawant                     NotifyBalloon(pSysTray, L"Safe to Remove Hardware", strInfo);
3467fbc5f42SShriraj Sawant 
3477fbc5f42SShriraj Sawant                     lResult = true;
3487fbc5f42SShriraj Sawant                     break;
3497fbc5f42SShriraj Sawant                 case DBT_DEVICEREMOVEPENDING:
3507fbc5f42SShriraj Sawant                     break;
3517fbc5f42SShriraj Sawant             }
3527fbc5f42SShriraj Sawant             return S_OK;
3537fbc5f42SShriraj Sawant 
3547fbc5f42SShriraj Sawant         /*case WM_CLOSE:
3557fbc5f42SShriraj Sawant             if (!UnregisterDeviceNotification(hDeviceNotify))
3567fbc5f42SShriraj Sawant             {
3577fbc5f42SShriraj Sawant                 return S_FALSE;
3587fbc5f42SShriraj Sawant             }
3597fbc5f42SShriraj Sawant             return S_OK;*/
3607fbc5f42SShriraj Sawant 
361c2c66affSColin Finck         default:
362c2c66affSColin Finck             TRACE("Hotplug_Message received for unknown ID %d, ignoring.\n");
363c2c66affSColin Finck             return S_FALSE;
364c2c66affSColin Finck     }
365c2c66affSColin Finck 
366c2c66affSColin Finck     return S_FALSE;
367c2c66affSColin Finck }
368