Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

384 lines
9.7 KiB

  1. #include "stdafx.h"
  2. #include "systray.h"
  3. #include <stdio.h>
  4. #include <initguid.h>
  5. #include <usbioctl.h>
  6. #include <wmium.h>
  7. #include <tchar.h>
  8. #include <setupapi.h>
  9. #define USBUIMENU 100
  10. #define NUM_HCS_TO_CHECK 10
  11. typedef int (CALLBACK *USBERRORMESSAGESCALLBACK)
  12. (PUSB_CONNECTION_NOTIFICATION,LPTSTR);
  13. extern HINSTANCE g_hInstance;
  14. static BOOL g_bUSBUIEnabled = FALSE;
  15. static BOOL g_bUSBUIIconShown = FALSE;
  16. static HINSTANCE g_hUsbWatch = NULL;
  17. static USBERRORMESSAGESCALLBACK g_UsbHandler = NULL;
  18. static BOOL g_bSubstituteDll = FALSE;
  19. static TCHAR g_strSubstituteDll[MAX_PATH];
  20. static HANDLE g_hWait = NULL;
  21. int _cdecl main(){
  22. return 0;
  23. }
  24. #define USBUI_OffsetToPtr(Base, Offset) ((PBYTE)((PBYTE)Base + Offset))
  25. LPTSTR USBUI_CountedStringToSz(LPTSTR lpString)
  26. {
  27. SHORT usNameLength;
  28. LPTSTR lpStringPlusNull;
  29. usNameLength = * (USHORT *) lpString;
  30. lpStringPlusNull = (LPTSTR) LocalAlloc(LMEM_ZEROINIT,
  31. sizeof(TCHAR) * (usNameLength+1));
  32. if (lpStringPlusNull != NULL) {
  33. lpString = (LPTSTR) USBUI_OffsetToPtr(lpString, sizeof(USHORT));
  34. wcsncpy( lpStringPlusNull, lpString, usNameLength );
  35. lpStringPlusNull[usNameLength] = TEXT('0');
  36. // _tcscpy( lpStringPlusNull + usNameLength, _TEXT("") );
  37. }
  38. return lpStringPlusNull;
  39. }
  40. void USBUI_EventCallbackRoutine(PWNODE_HEADER WnodeHeader, UINT_PTR NotificationContext)
  41. {
  42. PWNODE_SINGLE_INSTANCE wNode = (PWNODE_SINGLE_INSTANCE)WnodeHeader;
  43. PUSB_CONNECTION_NOTIFICATION usbConnectionNotification;
  44. LPGUID eventGuid = &WnodeHeader->Guid;
  45. LPTSTR strInstanceName;
  46. if (memcmp(&GUID_USB_WMI_STD_DATA, eventGuid, sizeof(GUID)) == 0) {
  47. usbConnectionNotification = (PUSB_CONNECTION_NOTIFICATION)
  48. USBUI_OffsetToPtr(wNode,
  49. wNode->DataBlockOffset);
  50. //
  51. // Get the instance name
  52. //
  53. strInstanceName =
  54. USBUI_CountedStringToSz((LPTSTR)
  55. USBUI_OffsetToPtr(wNode,
  56. wNode->OffsetInstanceName));
  57. if (strInstanceName) {
  58. if (g_hUsbWatch && g_UsbHandler) {
  59. USBUIEngageHandler:
  60. g_UsbHandler(usbConnectionNotification, strInstanceName);
  61. } else {
  62. if (g_bSubstituteDll) {
  63. g_hUsbWatch = LoadLibrary(g_strSubstituteDll);
  64. } else {
  65. g_hUsbWatch = LoadLibrary(TEXT("usbui.dll"));
  66. }
  67. g_UsbHandler = (USBERRORMESSAGESCALLBACK)
  68. GetProcAddress(g_hUsbWatch, "USBErrorHandler");
  69. goto USBUIEngageHandler;
  70. }
  71. LocalFree(strInstanceName);
  72. }
  73. }
  74. }
  75. VOID USBUI_WaitRoutineCallback(WMIHANDLE Handle, BOOLEAN Unused) {
  76. ASSERT(!Unused);
  77. UnregisterWaitEx(g_hWait, NULL);
  78. g_hWait = NULL;
  79. WmiReceiveNotifications(1, &Handle, USBUI_EventCallbackRoutine, (ULONG_PTR)NULL);
  80. RegisterWaitForSingleObject(&g_hWait,
  81. Handle,
  82. USBUI_WaitRoutineCallback,
  83. Handle, // context
  84. INFINITE,
  85. WT_EXECUTELONGFUNCTION | WT_EXECUTEONLYONCE);
  86. }
  87. int USBUI_ErrorMessagesEnable(BOOL fEnable)
  88. {
  89. ULONG status = ERROR_SUCCESS;
  90. BOOL result;
  91. static WMIHANDLE hWmi = NULL;
  92. if (fEnable) {
  93. ASSERT(!g_hWait);
  94. ASSERT(!hWmi);
  95. status = WmiOpenBlock((LPGUID) &GUID_USB_WMI_STD_DATA,
  96. WMIGUID_NOTIFICATION | SYNCHRONIZE,
  97. &hWmi);
  98. if (!status) {
  99. result = RegisterWaitForSingleObject(&g_hWait,
  100. hWmi,
  101. USBUI_WaitRoutineCallback,
  102. hWmi, // context
  103. INFINITE,
  104. WT_EXECUTELONGFUNCTION | WT_EXECUTEONLYONCE);
  105. status = result ? 0 : ERROR_INVALID_FUNCTION;
  106. }
  107. } else {
  108. ASSERT(hWmi);
  109. if (g_hWait) {
  110. result = UnregisterWait(g_hWait);
  111. }
  112. if (hWmi) {
  113. status = WmiCloseBlock(hWmi);
  114. }
  115. hWmi = NULL;
  116. g_hWait = NULL;
  117. if (g_hUsbWatch) {
  118. // This allows us to replace the library
  119. FreeLibrary(g_hUsbWatch);
  120. g_hUsbWatch = NULL;
  121. g_UsbHandler = NULL;
  122. }
  123. }
  124. return status;
  125. }
  126. void USBUI_Notify(HWND hwnd, WPARAM wParam, LPARAM lParam)
  127. {
  128. switch (lParam)
  129. {
  130. case WM_RBUTTONUP:
  131. {
  132. USBUI_Menu(hwnd, 1, TPM_RIGHTBUTTON);
  133. }
  134. break;
  135. case WM_LBUTTONDOWN:
  136. {
  137. SetTimer(hwnd, USBUI_TIMER_ID, GetDoubleClickTime()+100, NULL);
  138. }
  139. break;
  140. case WM_LBUTTONDBLCLK:
  141. {
  142. KillTimer(hwnd, USBUI_TIMER_ID);
  143. USBUI_Toggle();
  144. }
  145. break;
  146. }
  147. }
  148. void USBUI_Toggle()
  149. {
  150. USBUI_SetState(!g_bUSBUIEnabled);
  151. }
  152. void USBUI_Timer(HWND hwnd)
  153. {
  154. KillTimer(hwnd, USBUI_TIMER_ID);
  155. USBUI_Menu(hwnd, 0, TPM_LEFTBUTTON);
  156. }
  157. /*
  158. HMENU USBUI_CreateMenu()
  159. {
  160. HMENU hmenu;
  161. LPSTR lpszMenu1;
  162. hmenu = CreatePopupMenu();
  163. if (!hmenu)
  164. {
  165. return NULL;
  166. }
  167. lpszMenu1 = LoadDynamicString(g_bUSBUIEnabled?IDS_USBUIDISABLE:IDS_USBUIENABLE);
  168. // AppendMenu(hmenu,MF_STRING,USBUIMENU,lpszMenu1);
  169. SysTray_AppendMenuString (hmenu,USBUIMENU,lpszMenu1);
  170. SetMenuDefaultItem(hmenu,USBUIMENU,FALSE);
  171. DeleteDynamicString(lpszMenu1);
  172. return hmenu;
  173. }
  174. */
  175. void USBUI_Menu(HWND hwnd, UINT uMenuNum, UINT uButton)
  176. {
  177. POINT pt;
  178. UINT iCmd;
  179. HMENU hmenu = 0;
  180. GetCursorPos(&pt);
  181. // hmenu = USBUI_CreateMenu();
  182. if (!hmenu)
  183. {
  184. return;
  185. }
  186. SetForegroundWindow(hwnd);
  187. iCmd = TrackPopupMenu(hmenu, uButton | TPM_RETURNCMD | TPM_NONOTIFY, pt.x, pt.y, 0, hwnd, NULL);
  188. DestroyMenu(hmenu);
  189. switch (iCmd)
  190. {
  191. case USBUIMENU:
  192. {
  193. USBUI_Toggle();
  194. }
  195. break;
  196. }
  197. }
  198. BOOL USBUI_SetState(BOOL NewState)
  199. {
  200. int retValue;
  201. if (g_bUSBUIEnabled != NewState) {
  202. //
  203. // Only enable it if not already enabled
  204. //
  205. retValue = (int) USBUI_ErrorMessagesEnable (NewState);
  206. g_bUSBUIEnabled = retValue ? g_bUSBUIEnabled : NewState;
  207. }
  208. return g_bUSBUIEnabled;
  209. }
  210. BOOL
  211. IsErrorCheckingEnabled()
  212. {
  213. DWORD ErrorCheckingEnabled = TRUE, size;
  214. HKEY hKey;
  215. //
  216. // Check the registry value ErrorCheckingEnabled to make sure that we should
  217. // be enabling this.
  218. //
  219. if (ERROR_SUCCESS ==
  220. RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  221. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Usb"),
  222. 0,
  223. KEY_READ,
  224. &hKey)) {
  225. // Get the ErrorCheckingEnabled value
  226. size = sizeof(DWORD);
  227. RegQueryValueEx(hKey,
  228. TEXT("ErrorCheckingEnabled"),
  229. 0,
  230. NULL,
  231. (LPBYTE) &ErrorCheckingEnabled,
  232. &size);
  233. if (ErrorCheckingEnabled) {
  234. // Look for a substitute dll for usbui.dll
  235. size = MAX_PATH*sizeof(TCHAR);
  236. if (ERROR_SUCCESS ==
  237. RegQueryValueEx(hKey,
  238. TEXT("SubstituteDll"),
  239. 0,
  240. NULL,
  241. (LPBYTE) g_strSubstituteDll,
  242. &size)) {
  243. g_bSubstituteDll = TRUE;
  244. } else {
  245. g_bSubstituteDll = FALSE;
  246. }
  247. }
  248. }
  249. return (BOOL) ErrorCheckingEnabled;
  250. }
  251. BOOL USBUI_Init(HWND hWnd)
  252. {
  253. TCHAR HCName[16];
  254. BOOL ControllerFound = FALSE;
  255. int HCNum;
  256. HDEVINFO hHCDev;
  257. //
  258. // Check the registry to make sure that it is turned on
  259. //
  260. if (!IsErrorCheckingEnabled()) {
  261. return FALSE;
  262. }
  263. //
  264. // Check for the existence of a USB controller.
  265. // If there is one, load and initialize USBUI.dll which will check for
  266. // usb error messages. If we can't open a controller, than we shouldn't
  267. // load a USB watch dll.
  268. //
  269. for (HCNum = 0; HCNum < NUM_HCS_TO_CHECK; HCNum++)
  270. {
  271. wsprintf(HCName, TEXT("\\\\.\\HCD%d"), HCNum);
  272. hHCDev = CreateFile(HCName,
  273. GENERIC_READ,
  274. FILE_SHARE_READ,
  275. NULL,
  276. OPEN_EXISTING,
  277. 0,
  278. NULL);
  279. //
  280. // If the handle is valid, then we've successfully opened a Host
  281. // Controller.
  282. //
  283. if (hHCDev != INVALID_HANDLE_VALUE) {
  284. CloseHandle(hHCDev);
  285. return TRUE;
  286. }
  287. }
  288. hHCDev = SetupDiGetClassDevs(&GUID_CLASS_USB_HOST_CONTROLLER,
  289. NULL,
  290. NULL,
  291. (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
  292. if(hHCDev == INVALID_HANDLE_VALUE) {
  293. return FALSE;
  294. }
  295. SetupDiDestroyDeviceInfoList(hHCDev);
  296. return TRUE;
  297. }
  298. //
  299. // Called at init time and whenever services are enabled/disabled.
  300. //
  301. BOOL USBUI_CheckEnable(HWND hWnd, BOOL bSvcEnabled)
  302. {
  303. BOOL bEnable = bSvcEnabled && USBUI_Init(hWnd);
  304. if (bEnable != g_bUSBUIEnabled)
  305. {
  306. //
  307. // state change
  308. //
  309. USBUI_SetState(bEnable);
  310. }
  311. return(bEnable);
  312. }