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 5*7fbc5f42SShriraj Sawant * PURPOSE: Removable devices notification icon handler 6*7fbc5f42SShriraj Sawant * PROGRAMMERS: Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com> 7c2c66affSColin Finck */ 8*7fbc5f42SShriraj Sawant #include <windows.h> 9c2c66affSColin Finck #include "precomp.h" 10*7fbc5f42SShriraj Sawant #include <mmsystem.h> 11*7fbc5f42SShriraj Sawant #include <mmddk.h> 12*7fbc5f42SShriraj Sawant #include <atlstr.h> 13*7fbc5f42SShriraj Sawant #include <atlsimpcoll.h> 14*7fbc5f42SShriraj Sawant #include <dbt.h> 15*7fbc5f42SShriraj Sawant #include <setupapi.h> 16*7fbc5f42SShriraj Sawant #include <cfgmgr32.h> 17c2c66affSColin Finck 18c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(stobject); 19*7fbc5f42SShriraj Sawant #define DISPLAY_NAME_LEN 40 20c2c66affSColin Finck 21*7fbc5f42SShriraj Sawant //BOOL WINAPI UnregisterDeviceNotification(HDEVNOTIFY Handle); 22*7fbc5f42SShriraj Sawant 23*7fbc5f42SShriraj Sawant CSimpleArray<DEVINST> g_devList; 24*7fbc5f42SShriraj Sawant /*static HDEVNOTIFY g_hDevNotify = NULL;*/ 25c2c66affSColin Finck static HICON g_hIconHotplug = NULL; 26*7fbc5f42SShriraj Sawant static LPCWSTR g_strTooltip = L"Safely Remove Hardware and Eject Media"; 27*7fbc5f42SShriraj Sawant static WCHAR g_strMenuSel[DISPLAY_NAME_LEN]; 28c2c66affSColin Finck static BOOL g_IsRunning = FALSE; 29*7fbc5f42SShriraj Sawant static BOOL g_IsRemoving = FALSE; 30c2c66affSColin Finck 31*7fbc5f42SShriraj Sawant /*++ 32*7fbc5f42SShriraj Sawant * @name EnumHotpluggedDevices 33*7fbc5f42SShriraj Sawant * 34*7fbc5f42SShriraj Sawant * Enumerates the connected safely removable devices. 35*7fbc5f42SShriraj Sawant * 36*7fbc5f42SShriraj Sawant * @param devList 37*7fbc5f42SShriraj Sawant * List of device instances, representing the currently attached devices. 38*7fbc5f42SShriraj Sawant * 39*7fbc5f42SShriraj Sawant * @return The error code. 40*7fbc5f42SShriraj Sawant * 41*7fbc5f42SShriraj Sawant *--*/ 42*7fbc5f42SShriraj Sawant HRESULT EnumHotpluggedDevices(CSimpleArray<DEVINST> &devList) 43*7fbc5f42SShriraj Sawant { 44*7fbc5f42SShriraj Sawant devList.RemoveAll(); // Clear current devList 45*7fbc5f42SShriraj Sawant HDEVINFO hdev = SetupDiGetClassDevs(NULL, NULL, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT); 46*7fbc5f42SShriraj Sawant if (INVALID_HANDLE_VALUE == hdev) 47*7fbc5f42SShriraj Sawant return E_HANDLE; 48*7fbc5f42SShriraj Sawant SP_DEVINFO_DATA did = { 0 }; 49*7fbc5f42SShriraj Sawant did.cbSize = sizeof(did); 50*7fbc5f42SShriraj Sawant 51*7fbc5f42SShriraj Sawant // Enumerate all the attached devices. 52*7fbc5f42SShriraj Sawant for (int idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); idev++) 53*7fbc5f42SShriraj Sawant { 54*7fbc5f42SShriraj Sawant DWORD dwCapabilities = 0, dwSize = sizeof(dwCapabilities); 55*7fbc5f42SShriraj Sawant WCHAR dispName[DISPLAY_NAME_LEN]; 56*7fbc5f42SShriraj Sawant ULONG ulStatus = 0, ulPnum = 0, ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR); 57*7fbc5f42SShriraj Sawant CONFIGRET cr = CM_Get_DevNode_Status(&ulStatus, &ulPnum, did.DevInst, 0); 58*7fbc5f42SShriraj Sawant if (cr != CR_SUCCESS) 59*7fbc5f42SShriraj Sawant continue; 60*7fbc5f42SShriraj Sawant cr = CM_Get_DevNode_Registry_Property(did.DevInst, CM_DRP_DEVICEDESC, NULL, dispName, &ulLength, 0); 61*7fbc5f42SShriraj Sawant if (cr != CR_SUCCESS) 62*7fbc5f42SShriraj Sawant continue; 63*7fbc5f42SShriraj Sawant cr = CM_Get_DevNode_Registry_Property(did.DevInst, CM_DRP_CAPABILITIES, NULL, &dwCapabilities, &dwSize, 0); 64*7fbc5f42SShriraj Sawant if (cr != CR_SUCCESS) 65*7fbc5f42SShriraj Sawant continue; 66*7fbc5f42SShriraj Sawant 67*7fbc5f42SShriraj Sawant // Filter and make list of only the appropriate safely removable devices. 68*7fbc5f42SShriraj Sawant if ( (dwCapabilities & CM_DEVCAP_REMOVABLE) && 69*7fbc5f42SShriraj Sawant !(dwCapabilities & CM_DEVCAP_DOCKDEVICE) && 70*7fbc5f42SShriraj Sawant !(dwCapabilities & CM_DEVCAP_SURPRISEREMOVALOK) && 71*7fbc5f42SShriraj Sawant ((dwCapabilities & CM_DEVCAP_EJECTSUPPORTED) || (ulStatus & DN_DISABLEABLE)) && 72*7fbc5f42SShriraj Sawant !ulPnum) 73*7fbc5f42SShriraj Sawant { 74*7fbc5f42SShriraj Sawant devList.Add(did.DevInst); 75*7fbc5f42SShriraj Sawant } 76*7fbc5f42SShriraj Sawant } 77*7fbc5f42SShriraj Sawant SetupDiDestroyDeviceInfoList(hdev); 78*7fbc5f42SShriraj Sawant 79*7fbc5f42SShriraj Sawant if (NO_ERROR != GetLastError() && ERROR_NO_MORE_ITEMS != GetLastError()) 80*7fbc5f42SShriraj Sawant { 81*7fbc5f42SShriraj Sawant return E_UNEXPECTED; 82*7fbc5f42SShriraj Sawant } 83*7fbc5f42SShriraj Sawant 84*7fbc5f42SShriraj Sawant return S_OK; 85*7fbc5f42SShriraj Sawant } 86*7fbc5f42SShriraj Sawant 87*7fbc5f42SShriraj Sawant /*++ 88*7fbc5f42SShriraj Sawant * @name NotifyBalloon 89*7fbc5f42SShriraj Sawant * 90*7fbc5f42SShriraj Sawant * Pops the balloon notification of the given notification icon. 91*7fbc5f42SShriraj Sawant * 92*7fbc5f42SShriraj Sawant * @param pSysTray 93*7fbc5f42SShriraj Sawant * Provides interface for acquiring CSysTray information as required. 94*7fbc5f42SShriraj Sawant * @param szTitle 95*7fbc5f42SShriraj Sawant * Title for the balloon notification. 96*7fbc5f42SShriraj Sawant * @param szInfo 97*7fbc5f42SShriraj Sawant * Main content for the balloon notification. 98*7fbc5f42SShriraj Sawant * @param uId 99*7fbc5f42SShriraj Sawant * Represents the particular notification icon. 100*7fbc5f42SShriraj Sawant * 101*7fbc5f42SShriraj Sawant * @return The error code. 102*7fbc5f42SShriraj Sawant * 103*7fbc5f42SShriraj Sawant *--*/ 104*7fbc5f42SShriraj Sawant HRESULT NotifyBalloon(CSysTray* pSysTray, LPCWSTR szTitle = NULL, LPCWSTR szInfo = NULL, UINT uId = ID_ICON_HOTPLUG) 105*7fbc5f42SShriraj Sawant { 106*7fbc5f42SShriraj Sawant NOTIFYICONDATA nim = { 0 }; 107*7fbc5f42SShriraj Sawant nim.cbSize = sizeof(NOTIFYICONDATA); 108*7fbc5f42SShriraj Sawant nim.uID = uId; 109*7fbc5f42SShriraj Sawant nim.hWnd = pSysTray->GetHWnd(); 110*7fbc5f42SShriraj Sawant 111*7fbc5f42SShriraj Sawant nim.uFlags = NIF_INFO; 112*7fbc5f42SShriraj Sawant nim.uTimeout = 10; 113*7fbc5f42SShriraj Sawant nim.dwInfoFlags = NIIF_INFO; 114*7fbc5f42SShriraj Sawant 115*7fbc5f42SShriraj Sawant StringCchCopy(nim.szInfoTitle, _countof(nim.szInfoTitle), szTitle); 116*7fbc5f42SShriraj Sawant StringCchCopy(nim.szInfo, _countof(nim.szInfo), szInfo); 117*7fbc5f42SShriraj Sawant BOOL ret = Shell_NotifyIcon(NIM_MODIFY, &nim); 118*7fbc5f42SShriraj Sawant 119*7fbc5f42SShriraj Sawant Sleep(10000); /* As per windows, the balloon notification remains visible for atleast 10 sec. 120*7fbc5f42SShriraj Sawant This timer maintains the same condition. 121*7fbc5f42SShriraj Sawant Also it is required so that the icon doesn't hide instantly after last device is removed, 122*7fbc5f42SShriraj Sawant as that will prevent popping of notification. 123*7fbc5f42SShriraj Sawant */ 124*7fbc5f42SShriraj Sawant StringCchCopy(nim.szInfoTitle, _countof(nim.szInfoTitle), L""); 125*7fbc5f42SShriraj Sawant StringCchCopy(nim.szInfo, _countof(nim.szInfo), L""); 126*7fbc5f42SShriraj Sawant ret = Shell_NotifyIcon(NIM_MODIFY, &nim); 127*7fbc5f42SShriraj Sawant g_IsRemoving = FALSE; /* This flag is used to prevent instant icon hiding after last device is removed. 128*7fbc5f42SShriraj Sawant The above timer maintains the required state for the same. 129*7fbc5f42SShriraj Sawant */ 130*7fbc5f42SShriraj Sawant return ret ? S_OK : E_FAIL; 131*7fbc5f42SShriraj Sawant } 132c2c66affSColin Finck 133c2c66affSColin Finck HRESULT STDMETHODCALLTYPE Hotplug_Init(_In_ CSysTray * pSysTray) 134c2c66affSColin Finck { 135c2c66affSColin Finck TRACE("Hotplug_Init\n"); 136*7fbc5f42SShriraj Sawant g_hIconHotplug = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_HOTPLUG_OK)); 137c2c66affSColin Finck g_IsRunning = TRUE; 138*7fbc5f42SShriraj Sawant EnumHotpluggedDevices(g_devList); 139c2c66affSColin Finck 140*7fbc5f42SShriraj Sawant return pSysTray->NotifyIcon(NIM_ADD, ID_ICON_HOTPLUG, g_hIconHotplug, g_strTooltip, NIS_HIDDEN); 141c2c66affSColin Finck } 142c2c66affSColin Finck 143c2c66affSColin Finck HRESULT STDMETHODCALLTYPE Hotplug_Update(_In_ CSysTray * pSysTray) 144c2c66affSColin Finck { 145c2c66affSColin Finck TRACE("Hotplug_Update\n"); 146*7fbc5f42SShriraj Sawant 147*7fbc5f42SShriraj Sawant if(g_devList.GetSize() || g_IsRemoving) 148*7fbc5f42SShriraj Sawant return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_HOTPLUG, g_hIconHotplug, g_strTooltip); 149*7fbc5f42SShriraj Sawant else 150*7fbc5f42SShriraj Sawant return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_HOTPLUG, g_hIconHotplug, g_strTooltip, NIS_HIDDEN); 151c2c66affSColin Finck } 152c2c66affSColin Finck 153c2c66affSColin Finck HRESULT STDMETHODCALLTYPE Hotplug_Shutdown(_In_ CSysTray * pSysTray) 154c2c66affSColin Finck { 155c2c66affSColin Finck TRACE("Hotplug_Shutdown\n"); 156c2c66affSColin Finck 157c2c66affSColin Finck g_IsRunning = FALSE; 158c2c66affSColin Finck 159c2c66affSColin Finck return pSysTray->NotifyIcon(NIM_DELETE, ID_ICON_HOTPLUG, NULL, NULL); 160c2c66affSColin Finck } 161c2c66affSColin Finck 162*7fbc5f42SShriraj Sawant static void _RunHotplug(CSysTray * pSysTray) 163c2c66affSColin Finck { 164*7fbc5f42SShriraj Sawant ShellExecuteW(pSysTray->GetHWnd(), L"open", L"rundll32.exe shell32.dll,Control_RunDLL hotplug.dll", NULL, NULL, SW_SHOWNORMAL); 165c2c66affSColin Finck } 166c2c66affSColin Finck 167*7fbc5f42SShriraj Sawant static void _ShowContextMenu(CSysTray * pSysTray) 168c2c66affSColin Finck { 169*7fbc5f42SShriraj Sawant HMENU hPopup = CreatePopupMenu(); 170*7fbc5f42SShriraj Sawant ULONG ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR); 171c2c66affSColin Finck 172*7fbc5f42SShriraj Sawant for (INT index = 0; index < g_devList.GetSize(); index++) 173*7fbc5f42SShriraj Sawant { 174*7fbc5f42SShriraj Sawant WCHAR dispName[DISPLAY_NAME_LEN], menuName[DISPLAY_NAME_LEN + 10]; 175*7fbc5f42SShriraj Sawant CONFIGRET cr = CM_Get_DevNode_Registry_Property(g_devList[index], CM_DRP_DEVICEDESC, NULL, dispName, &ulLength, 0); 176*7fbc5f42SShriraj Sawant if (cr != CR_SUCCESS) 177*7fbc5f42SShriraj Sawant StrCpyW(dispName, L"Unknown Device"); 178c2c66affSColin Finck 179*7fbc5f42SShriraj Sawant swprintf(menuName, L"Eject %wS", dispName); 180*7fbc5f42SShriraj Sawant AppendMenuW(hPopup, MF_STRING, index+1, menuName); 181*7fbc5f42SShriraj Sawant } 182c2c66affSColin Finck 183c2c66affSColin Finck SetForegroundWindow(pSysTray->GetHWnd()); 184*7fbc5f42SShriraj Sawant DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN; 185*7fbc5f42SShriraj Sawant POINT pt; 186*7fbc5f42SShriraj Sawant GetCursorPos(&pt); 187c2c66affSColin Finck 188*7fbc5f42SShriraj Sawant DWORD id = TrackPopupMenuEx(hPopup, flags, 189*7fbc5f42SShriraj Sawant pt.x, pt.y, 190*7fbc5f42SShriraj Sawant pSysTray->GetHWnd(), NULL); 191c2c66affSColin Finck 192*7fbc5f42SShriraj Sawant if (id > 0) 193*7fbc5f42SShriraj Sawant { 194*7fbc5f42SShriraj Sawant id--; // since array indices starts from zero. 195*7fbc5f42SShriraj Sawant CONFIGRET cr = CM_Get_DevNode_Registry_Property(g_devList[id], CM_DRP_DEVICEDESC, NULL, g_strMenuSel, &ulLength, 0); 196*7fbc5f42SShriraj Sawant if (cr != CR_SUCCESS) 197*7fbc5f42SShriraj Sawant StrCpyW(g_strMenuSel, L"Unknown Device"); 198*7fbc5f42SShriraj Sawant 199*7fbc5f42SShriraj Sawant cr = CM_Request_Device_Eject_Ex(g_devList[id], 0, 0, 0, 0, 0); 200*7fbc5f42SShriraj Sawant if (cr != CR_SUCCESS) 201*7fbc5f42SShriraj Sawant { 202*7fbc5f42SShriraj Sawant WCHAR strInfo[128]; 203*7fbc5f42SShriraj Sawant swprintf(strInfo, L"Problem Ejecting %wS", g_strMenuSel); 204*7fbc5f42SShriraj Sawant MessageBox(0, L"The device cannot be stopped right now! Try stopping it again later!", strInfo, MB_OKCANCEL | MB_ICONEXCLAMATION); 205*7fbc5f42SShriraj Sawant } 206*7fbc5f42SShriraj Sawant else 207*7fbc5f42SShriraj Sawant { 208*7fbc5f42SShriraj Sawant //MessageBox(0, L"Device ejected successfully!! You can safely remove the device now!", L"Safely Remove Hardware", MB_OKCANCEL | MB_ICONINFORMATION); 209*7fbc5f42SShriraj Sawant g_IsRemoving = TRUE; 210*7fbc5f42SShriraj Sawant g_devList.RemoveAt(id); /* thing is.. even after removing id at this point, the devnode_change occurs after some seconds of sucessful removal 211*7fbc5f42SShriraj Sawant and since pendrive is still plugged in it gets enumerated, if problem number is not filtered. 212*7fbc5f42SShriraj Sawant */ 213*7fbc5f42SShriraj Sawant } 214c2c66affSColin Finck } 215c2c66affSColin Finck 216*7fbc5f42SShriraj Sawant DestroyMenu(hPopup); 217*7fbc5f42SShriraj Sawant } 218c2c66affSColin Finck 219*7fbc5f42SShriraj Sawant static void _ShowContextMenuR(CSysTray * pSysTray) 220*7fbc5f42SShriraj Sawant { 221*7fbc5f42SShriraj Sawant CString strMenu((LPWSTR)IDS_HOTPLUG_REMOVE_2); 222c2c66affSColin Finck HMENU hPopup = CreatePopupMenu(); 223*7fbc5f42SShriraj Sawant AppendMenuW(hPopup, MF_STRING, IDS_HOTPLUG_REMOVE_2, strMenu); 224c2c66affSColin Finck 225*7fbc5f42SShriraj Sawant SetForegroundWindow(pSysTray->GetHWnd()); 226*7fbc5f42SShriraj Sawant DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN; 227*7fbc5f42SShriraj Sawant POINT pt; 228*7fbc5f42SShriraj Sawant GetCursorPos(&pt); 229c2c66affSColin Finck 230*7fbc5f42SShriraj Sawant DWORD id = TrackPopupMenuEx(hPopup, flags, 231*7fbc5f42SShriraj Sawant pt.x, pt.y, 232*7fbc5f42SShriraj Sawant pSysTray->GetHWnd(), NULL); 233c2c66affSColin Finck 234*7fbc5f42SShriraj Sawant if (id == IDS_HOTPLUG_REMOVE_2) 235*7fbc5f42SShriraj Sawant { 236*7fbc5f42SShriraj Sawant _RunHotplug(pSysTray); 237*7fbc5f42SShriraj Sawant } 238c2c66affSColin Finck 239c2c66affSColin Finck DestroyMenu(hPopup); 240c2c66affSColin Finck } 241c2c66affSColin Finck 242c2c66affSColin Finck HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult) 243c2c66affSColin Finck { 244*7fbc5f42SShriraj Sawant HRESULT hr = E_FAIL; 245c2c66affSColin Finck TRACE("Hotplug_Message uMsg=%d, wParam=%x, lParam=%x\n", uMsg, wParam, lParam); 246c2c66affSColin Finck 247c2c66affSColin Finck switch (uMsg) 248c2c66affSColin Finck { 249*7fbc5f42SShriraj Sawant /*case WM_CREATE: 250*7fbc5f42SShriraj Sawant TRACE("Hotplug_Message: WM_CREATE\n"); 251*7fbc5f42SShriraj Sawant DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; 252*7fbc5f42SShriraj Sawant 253*7fbc5f42SShriraj Sawant ZeroMemory(&NotificationFilter, sizeof(NotificationFilter)); 254*7fbc5f42SShriraj Sawant NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); 255*7fbc5f42SShriraj Sawant NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; 256*7fbc5f42SShriraj Sawant 257*7fbc5f42SShriraj Sawant g_hDevNotify = RegisterDeviceNotification(pSysTray->GetHWnd(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES); 258*7fbc5f42SShriraj Sawant if (g_hDevNotify != NULL) 259*7fbc5f42SShriraj Sawant { 260*7fbc5f42SShriraj Sawant lResult = true; 261*7fbc5f42SShriraj Sawant return S_OK; 262*7fbc5f42SShriraj Sawant } 263*7fbc5f42SShriraj Sawant return S_FALSE;*/ 264*7fbc5f42SShriraj Sawant 265c2c66affSColin Finck case WM_USER + 220: 266c2c66affSColin Finck TRACE("Hotplug_Message: WM_USER+220\n"); 267*7fbc5f42SShriraj Sawant if (wParam == 1) 268c2c66affSColin Finck { 269c2c66affSColin Finck if (lParam == FALSE) 270c2c66affSColin Finck return Hotplug_Init(pSysTray); 271c2c66affSColin Finck else 272c2c66affSColin Finck return Hotplug_Shutdown(pSysTray); 273c2c66affSColin Finck } 274c2c66affSColin Finck return S_FALSE; 275c2c66affSColin Finck 276c2c66affSColin Finck case WM_USER + 221: 277c2c66affSColin Finck TRACE("Hotplug_Message: WM_USER+221\n"); 278*7fbc5f42SShriraj Sawant if (wParam == 1) 279c2c66affSColin Finck { 280c2c66affSColin Finck lResult = (LRESULT)g_IsRunning; 281c2c66affSColin Finck return S_OK; 282c2c66affSColin Finck } 283c2c66affSColin Finck return S_FALSE; 284c2c66affSColin Finck 285c2c66affSColin Finck case ID_ICON_HOTPLUG: 286c2c66affSColin Finck Hotplug_Update(pSysTray); 287c2c66affSColin Finck 288c2c66affSColin Finck switch (lParam) 289c2c66affSColin Finck { 290c2c66affSColin Finck case WM_LBUTTONDOWN: 291c2c66affSColin Finck break; 292c2c66affSColin Finck 293c2c66affSColin Finck case WM_LBUTTONUP: 294*7fbc5f42SShriraj Sawant _ShowContextMenu(pSysTray); 295c2c66affSColin Finck break; 296c2c66affSColin Finck 297c2c66affSColin Finck case WM_LBUTTONDBLCLK: 298*7fbc5f42SShriraj Sawant _RunHotplug(pSysTray); 299c2c66affSColin Finck break; 300c2c66affSColin Finck 301c2c66affSColin Finck case WM_RBUTTONDOWN: 302c2c66affSColin Finck break; 303c2c66affSColin Finck 304c2c66affSColin Finck case WM_RBUTTONUP: 305*7fbc5f42SShriraj Sawant _ShowContextMenuR(pSysTray); 306c2c66affSColin Finck break; 307c2c66affSColin Finck 308c2c66affSColin Finck case WM_RBUTTONDBLCLK: 309c2c66affSColin Finck break; 310c2c66affSColin Finck 311c2c66affSColin Finck case WM_MOUSEMOVE: 312c2c66affSColin Finck break; 313c2c66affSColin Finck } 314c2c66affSColin Finck return S_OK; 315c2c66affSColin Finck 316*7fbc5f42SShriraj Sawant case WM_DEVICECHANGE: 317*7fbc5f42SShriraj Sawant switch (wParam) 318*7fbc5f42SShriraj Sawant { 319*7fbc5f42SShriraj Sawant case DBT_DEVNODES_CHANGED: 320*7fbc5f42SShriraj Sawant hr = EnumHotpluggedDevices(g_devList); 321*7fbc5f42SShriraj Sawant if (FAILED(hr)) 322*7fbc5f42SShriraj Sawant return hr; 323*7fbc5f42SShriraj Sawant 324*7fbc5f42SShriraj Sawant lResult = true; 325*7fbc5f42SShriraj Sawant break; 326*7fbc5f42SShriraj Sawant case DBT_DEVICEARRIVAL: 327*7fbc5f42SShriraj Sawant break; 328*7fbc5f42SShriraj Sawant case DBT_DEVICEQUERYREMOVE: 329*7fbc5f42SShriraj Sawant break; 330*7fbc5f42SShriraj Sawant case DBT_DEVICEQUERYREMOVEFAILED: 331*7fbc5f42SShriraj Sawant break; 332*7fbc5f42SShriraj Sawant case DBT_DEVICEREMOVECOMPLETE: 333*7fbc5f42SShriraj Sawant WCHAR strInfo[128]; 334*7fbc5f42SShriraj Sawant swprintf(strInfo, L"The %wS can now be safely removed from the system.", g_strMenuSel); 335*7fbc5f42SShriraj Sawant NotifyBalloon(pSysTray, L"Safe to Remove Hardware", strInfo); 336*7fbc5f42SShriraj Sawant 337*7fbc5f42SShriraj Sawant lResult = true; 338*7fbc5f42SShriraj Sawant break; 339*7fbc5f42SShriraj Sawant case DBT_DEVICEREMOVEPENDING: 340*7fbc5f42SShriraj Sawant break; 341*7fbc5f42SShriraj Sawant } 342*7fbc5f42SShriraj Sawant return S_OK; 343*7fbc5f42SShriraj Sawant 344*7fbc5f42SShriraj Sawant /*case WM_CLOSE: 345*7fbc5f42SShriraj Sawant if (!UnregisterDeviceNotification(hDeviceNotify)) 346*7fbc5f42SShriraj Sawant { 347*7fbc5f42SShriraj Sawant return S_FALSE; 348*7fbc5f42SShriraj Sawant } 349*7fbc5f42SShriraj Sawant return S_OK;*/ 350*7fbc5f42SShriraj Sawant 351c2c66affSColin Finck default: 352c2c66affSColin Finck TRACE("Hotplug_Message received for unknown ID %d, ignoring.\n"); 353c2c66affSColin Finck return S_FALSE; 354c2c66affSColin Finck } 355c2c66affSColin Finck 356c2c66affSColin Finck return S_FALSE; 357c2c66affSColin Finck } 358