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.

456 lines
14 KiB

  1. /***************************************************************************************************
  2. **
  3. ** MODULE:
  4. **
  5. **
  6. ** DESCRIPTION:
  7. **
  8. **
  9. ** AUTHOR: Daniel Dean.
  10. **
  11. **
  12. **
  13. ** CREATED:
  14. **
  15. **
  16. **
  17. **
  18. ** (C) C O P Y R I G H T D A N I E L D E A N 1 9 9 6.
  19. ***************************************************************************************************/
  20. #include <WINDOWS.H>
  21. #include <string.h> // for strncmp() and wcstrok()
  22. #include <crtdbg.h>
  23. #include <hidsdi.h> // HID parsing library
  24. #include <hidusage.h>
  25. #include <HID.H>
  26. #include "public.h"
  27. #include "CLASS.H"
  28. #include "IOCTL.H"
  29. PWSTR wcGetNullDelimitedItemFromList( PWSTR pszzList );
  30. PWSTR UnicodeString = L"This is Unicode\0Dis is more\0\0";
  31. char szFrame[] = "HIDMON frame"; // Class name for "frame" window
  32. char szChild[] = "HIDMON child"; // Class name for MDI window
  33. /****************
  34. TESTING!!!!!!!
  35. ****************/
  36. typedef char* PGUID;
  37. NTSTATUS
  38. IoGetDeviceClassAssociations(
  39. IN PGUID ClassGuid,
  40. OUT PWSTR *SymbolicLinkList
  41. );
  42. /****
  43. NTSTATUS
  44. IoGetDeviceClassAssociations(
  45. IN PGUID ClassGuid,
  46. OUT PWSTR *SymbolicLinkList
  47. )
  48. {
  49. *SymbolicLinkList = UnicodeString;
  50. return TRUE;
  51. }
  52. ****/
  53. /***
  54. BOOLEAN
  55. HidD_GetGuidString (
  56. OUT PCHAR * GuidClassInputString
  57. )
  58. { return TRUE; }
  59. ***/
  60. /***************************************************************************************************
  61. **
  62. ** InitializeApplication.
  63. **
  64. ** DESCRIPTION: Sets up the class data structures and does a one-time,
  65. ** initialization of the app by registering the window classes
  66. **
  67. ** PARAMETERS:
  68. **
  69. ** RETURNS: TRUE if successful else FALSE.
  70. **
  71. ***************************************************************************************************/
  72. ULONG InitializeApplication(VOID)
  73. {
  74. WNDCLASS wc;
  75. // Register the frame class
  76. wc.style = CS_DBLCLKS;
  77. wc.lpfnWndProc = HIDFrameWndProc;
  78. wc.cbClsExtra = 0;
  79. wc.cbWndExtra = 0;
  80. wc.hInstance = hInst;
  81. wc.hIcon = LoadIcon(hInst, IDHIDFRAME);
  82. wc.hCursor = LoadCursor(NULL,IDC_ARROW);
  83. wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE+1);
  84. wc.lpszMenuName = IDHIDMENU;
  85. wc.lpszClassName = szFrame;
  86. if(RegisterClass(&wc))
  87. {
  88. // Register the MDI child class
  89. wc.lpfnWndProc = HIDMDIChildWndProc;
  90. wc.hIcon = LoadIcon(hInst,IDHIDCHILD);
  91. wc.lpszMenuName = NULL;
  92. wc.cbWndExtra = CBWNDEXTRA;
  93. wc.lpszClassName = szChild;
  94. if(RegisterClass(&wc))
  95. return TRUE;
  96. }
  97. return FALSE;
  98. }
  99. /***************************************************************************************************
  100. **
  101. ** InitializeInstance.
  102. **
  103. ** DESCRIPTION: Performs a per-instance initialization of HIDMDI. It
  104. ** also creates the frame and one MDI child window.
  105. **
  106. ** PARAMETERS:
  107. **
  108. ** RETURNS: TRUE if successful else FALSE.
  109. **
  110. ***************************************************************************************************/
  111. ULONG InitializeInstance(LPSTR lpCmdLine, INT WindowState)
  112. {
  113. extern HWND hWndMDIClient;
  114. CHAR sz[80];
  115. // Get the base window title
  116. LoadString (hInst, IDS_APPNAME, sz, sizeof(sz));
  117. // Create the frame
  118. // MDI Client window is created in frame's WM_CREATE case
  119. hWndFrame = CreateWindow(szFrame,
  120. sz,
  121. WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  122. CW_USEDEFAULT,
  123. 0,
  124. CW_USEDEFAULT,
  125. 0,
  126. NULL,
  127. NULL,
  128. hInst,
  129. NULL);
  130. if(hWndFrame && hWndMDIClient)
  131. {
  132. // Display the frame window
  133. ShowWindow (hWndFrame, WindowState);
  134. UpdateWindow (hWndFrame);
  135. // Open all the Class device objects
  136. OpenClassObjects();
  137. return TRUE;
  138. }
  139. return FALSE;
  140. }
  141. /***************************************************************************************************
  142. **
  143. ** OpenClassObjects.
  144. **
  145. ** DESCRIPTION: Creates a new MDI child window.
  146. **
  147. ** PARAMETERS:
  148. **
  149. ** RETURNS: TRUE if successful else FALSE.
  150. **
  151. ***************************************************************************************************/
  152. #define MAX_DEVICE_NAME_LEN 255
  153. VOID OpenClassObjects(VOID)
  154. {
  155. HANDLE hDevice,hGetDeviceClassDriver;
  156. BOOL rc;
  157. //PWSTR pwszDeviceList; // UNICODE strings
  158. WORD wszDeviceList[1024];
  159. PWSTR pwszDeviceName;
  160. PCHAR pszGUID;
  161. char pszDeviceName[MAX_DEVICE_NAME_LEN];
  162. char pszHumanName[MAX_DEVICE_NAME_LEN];
  163. DWORD dwReturn;
  164. if( 1 )//rc = HidD_GetGuidString( &pszGUID ) )
  165. {
  166. //
  167. // If we got a GUID string, retrieve a list of null terminated device
  168. // name UNICODE strings similar to \\.\Device. This list is terminated
  169. // by a double NULL
  170. //rc = IoGetDeviceClassAssociations(pszGUID,&pwszDeviceList);
  171. hGetDeviceClassDriver = CreateFile(TEST_DEVICE,
  172. GENERIC_READ | GENERIC_WRITE,
  173. 0,
  174. NULL,
  175. OPEN_EXISTING,
  176. 0,
  177. NULL);
  178. if( hGetDeviceClassDriver != INVALID_HANDLE_VALUE)
  179. rc = DeviceIoControl(hGetDeviceClassDriver,
  180. IOCTL_GET_DEVICE_CLASS_ASSOC,
  181. NULL,
  182. 0,
  183. wszDeviceList,
  184. 1024*2,
  185. &dwReturn,
  186. NULL);
  187. else
  188. MessageBox(NULL,"Failed to load Test driver TEST.SYS","Error",MB_OK);
  189. CloseHandle(hGetDeviceClassDriver);
  190. pwszDeviceName = wcGetNullDelimitedItemFromList( wszDeviceList );
  191. do{
  192. // Convert the device name to ANSI
  193. WideCharToMultiByte( CP_ACP, // ANSI Code Page
  194. 0, // No flags
  195. pwszDeviceName, // UNICODE string
  196. -1, // String is NULL terminated
  197. pszDeviceName, // ANSI string
  198. MAX_DEVICE_NAME_LEN, // Lenght of ANSI string buffer
  199. NULL, // No default character
  200. NULL );
  201. // Open the Class device
  202. hDevice = CreateFile(pszDeviceName,
  203. GENERIC_READ | GENERIC_WRITE,
  204. 0,
  205. NULL,
  206. OPEN_EXISTING,
  207. 0,
  208. NULL);
  209. if(hDevice != INVALID_HANDLE_VALUE )
  210. {
  211. // Turn our DeviceName into a Human Readable name
  212. GetDeviceDescription(pszDeviceName, pszHumanName);
  213. // Create the window
  214. MakeNewChild(pszHumanName, hDevice);
  215. }
  216. else
  217. MessageBox(NULL,"CreateFile(pszDeviceName) failed","Get On The Bus!",MB_OK);
  218. // Get the next device name
  219. }while( pwszDeviceName = wcGetNullDelimitedItemFromList( NULL ) ); //wcstok(NULL,L"\0") );
  220. // TESTING!!!! remove comments from free()
  221. // Remember to free the GUID string memory
  222. //free(pszGUID);
  223. }
  224. }
  225. /***************************************************************************************************
  226. **
  227. ** GetDeviceDescription( char *pszDevice, char *pszName)
  228. **
  229. ** DESCRIPTION: Given DeviceName string as returned from IoGetDeviceClassAssociations,
  230. ** place a NULL terminated string retrieved from HKLM\Enum\USB(...)\DeviceDescription
  231. ** in pszName
  232. **
  233. ** PARAMETERS: char* pszDevice - Pointer to an ANSII string returned from IoGetDeviceClassAssociations
  234. ** char* pszName - Pointer to string to return name of device in
  235. **
  236. ** RETURNS: void
  237. **
  238. ***************************************************************************************************/
  239. void GetDeviceDescription(char *pszDevice, char *pszName)
  240. {
  241. HKEY hkReg;
  242. LONG rc;
  243. LONG BytesWritten=MAX_DEVICE_NAME_LEN;
  244. char *head;
  245. char szRegPath[MAX_DEVICE_NAME_LEN];
  246. head = pszDevice;
  247. // first whack off the \\.\USB#
  248. while( *head++ != '#' );
  249. pszDevice = head;
  250. // then replace all instances of # with \
  251. while( *head )
  252. {
  253. if( *head == '#' )
  254. *head = '\\';
  255. head++;
  256. }
  257. // now, whack off the GUID string (begins with a { ) and preceding \
  258. head = pszDevice;
  259. while( *head != '{' )
  260. head++;
  261. // null terminate it
  262. *--head = '\0';
  263. // Create our registry path
  264. wsprintf(szRegPath,"ENUM\\USB\\%s",pszDevice);
  265. // open up the Reg and get our human readable name
  266. rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,szRegPath,0,KEY_ALL_ACCESS,&hkReg);
  267. if( rc == ERROR_SUCCESS )
  268. {
  269. // add on the Named value we are looking for
  270. rc = RegQueryValueEx(hkReg,"DeviceDesc",0,NULL,pszName,&BytesWritten);
  271. RegCloseKey(hkReg);
  272. }
  273. }
  274. /***************************************************************************************************
  275. **
  276. ** wcGetNullDelimitedItemFromList( PWSTR pszzList)
  277. **
  278. ** DESCRIPTION: Given a list of NULL terminated strings with the last member being a
  279. ** double NULL, will return the next string in the list. Operation is similar
  280. ** to strtok(): the first time the function is called, a valid list must be passed,
  281. ** there after to retrieve member strings, pass NULL in the pszzList param.
  282. **
  283. ** PARAMETERS: PWSTR pszzList - Pointer to a UNICODE double null terminated list of
  284. ** NULL terminated strings.
  285. **
  286. **
  287. ** RETURNS: PWSTR Pointer to the next member of the list or NULL if at end of list.
  288. **
  289. ***************************************************************************************************/
  290. PWSTR wcGetNullDelimitedItemFromList( PWSTR pszzList )
  291. {
  292. static PWSTR CurrentMember=NULL; // Current pointer into the list
  293. PWSTR tmp;
  294. //
  295. // Make sure pszzList is not NULL the first time in
  296. if( !pszzList && !CurrentMember )
  297. return NULL;
  298. //
  299. // If pszzList is not NULL, we are starting from scratch
  300. if( pszzList )
  301. CurrentMember = pszzList;
  302. //
  303. // If we have 2 NULL's then we are at the end of the list
  304. if( (*CurrentMember == L'\0') && (*(CurrentMember+1) == L'\0') )
  305. {
  306. CurrentMember=NULL;
  307. return NULL;
  308. }
  309. else
  310. {
  311. // Save a pointer to the current member
  312. tmp = CurrentMember;
  313. // Incriment to the next member
  314. while( *CurrentMember++ );
  315. // Return the current member
  316. return tmp;
  317. }
  318. }
  319. /***************************************************************************************************
  320. **
  321. ** MakeNewChild.
  322. **
  323. ** DESCRIPTION: Creates a new MDI child window.
  324. **
  325. ** PARAMETERS:
  326. **
  327. ** RETURNS: TRUE if successful else FALSE.
  328. **
  329. ***************************************************************************************************/
  330. /*
  331. BOOLEAN __stdcall
  332. HidD_MyGetPreparsedData (
  333. IN HANDLE HidDeviceObject,
  334. OUT PHIDP_PREPARSED_DATA * PreparsedData
  335. );
  336. */
  337. HWND MakeNewChild(char *pName, HANDLE hDevice)
  338. {
  339. HWND hWnd = 0;
  340. MDICREATESTRUCT mcs;
  341. PCHILD_INFO pChildInfo;
  342. PHIDP_PREPARSED_DATA hidPreParsedData;
  343. DWORD err;
  344. NTSTATUS rc;
  345. if(pName)
  346. {
  347. mcs.szTitle = (LPSTR)pName; // Fully qualified pathname
  348. mcs.szClass = szChild;
  349. mcs.hOwner = hInst;
  350. mcs.x = mcs.cx = CW_USEDEFAULT; // Use the default size for the window
  351. mcs.y = mcs.cy = CW_USEDEFAULT;
  352. mcs.style = styleDefault; // Set the style DWORD of the window to default
  353. // tell the MDI Client to create the child
  354. hWnd = (HWND)SendMessage(hWndMDIClient,
  355. WM_MDICREATE,
  356. 0,
  357. (LONG)(LPMDICREATESTRUCT)&mcs);
  358. if(hWnd)
  359. {
  360. //
  361. // Create and fill in a device info struct for this window
  362. pChildInfo = (PCHILD_INFO) GlobalAlloc(GPTR,sizeof(CHILD_INFO));
  363. pChildInfo->hidCaps = (PHIDP_CAPS) GlobalAlloc(GPTR,sizeof(HIDP_CAPS));
  364. // rc = HidD_MyGetPreparsedData( hDevice,&pChildInfo->hidPPData );
  365. rc = HidD_GetPreparsedData( hDevice,&pChildInfo->hidPPData );
  366. if( !rc )
  367. err = GetLastError();
  368. // Get a pointer to this devices capabilities
  369. rc = HidP_GetCaps( pChildInfo->hidPPData, pChildInfo->hidCaps );
  370. // Allocate space for and get a list of Value channel descriptions for this device
  371. pChildInfo->pValueCaps = (PHIDP_VALUE_CAPS) GlobalAlloc(GPTR,pChildInfo->hidCaps->NumberInputValueCaps*sizeof(HIDP_VALUE_CAPS));
  372. pChildInfo->NumValues = pChildInfo->hidCaps->NumberInputValueCaps;
  373. rc = HidP_GetValueCaps( HidP_Input,
  374. pChildInfo->pValueCaps,
  375. &pChildInfo->NumValues,
  376. pChildInfo->hidPPData
  377. );
  378. // Allocate space for and get a list of Button channel descriptions for this device
  379. pChildInfo->pButtonCaps = (PHIDP_BUTTON_CAPS) GlobalAlloc(GPTR,pChildInfo->hidCaps->NumberInputButtonCaps*sizeof(HIDP_BUTTON_CAPS));
  380. pChildInfo->NumButtons = pChildInfo->hidCaps->NumberInputButtonCaps;
  381. rc = HidP_GetButtonCaps(HidP_Input,
  382. pChildInfo->pButtonCaps,
  383. &pChildInfo->NumButtons,
  384. pChildInfo->hidPPData
  385. );
  386. // Save the info!
  387. SetDeviceInfo(hWnd, pChildInfo);
  388. SetDeviceHandle(hWnd, hDevice);
  389. ShowWindow(hWnd, SW_SHOW);
  390. //TESTING!!
  391. //IOCTLRead(hWnd);
  392. }
  393. }
  394. return hWnd;
  395. }