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.

376 lines
9.4 KiB

  1. /*++
  2. Copyright (c) Microsoft 1998, All Rights Reserved
  3. Module Name:
  4. logpnp.c
  5. Abstract:
  6. This module contains the code for finding, loading and building logical
  7. hid device structures to be used for extended client calls.
  8. Environment:
  9. User mode
  10. Revision History:
  11. May-98 : Created
  12. --*/
  13. #ifndef __LOGPNP_C__
  14. #define __LOGPNP_C__
  15. #endif
  16. #include <windows.h>
  17. #include <wtypes.h>
  18. #include <commdlg.h>
  19. #include <stdlib.h>
  20. #include "hid.h"
  21. #include "logpnp.h"
  22. #define OPENFILE_FILTER "Preparsed Data Files\0*.PPD\0"
  23. CHAR LogPnP_PpdFileName[MAX_PATH+1];
  24. BOOL
  25. LogPnP_BuildLogicalHIDDevice(
  26. IN PHIDP_PREPARSED_DATA HidPpd,
  27. IN OUT PHID_DEVICE HidDevice
  28. );
  29. VOID
  30. LogPnP_CloseLogicalDevice(
  31. IN PHID_DEVICE LogicalDevice
  32. );
  33. BOOL
  34. LogPnP_LoadLogicalDevice(
  35. IN PCHAR OptFileName,
  36. IN OUT PHID_DEVICE HidDevice
  37. )
  38. /*++
  39. RoutineDescription:
  40. This routine creates a HidDevice object that corresponds to a "logical" device
  41. A logical device is actually preparsed data that has been saved to disk. The
  42. most common method of saving preparsed data to disk is using that feature in a
  43. post 3.0 version of HIDView after retrieving/parsing with report descriptor with
  44. the OS provided parser. Because the preparsed data structure is available,
  45. all of the HidP_Xxx routines can be used.
  46. OptFileName is an optional file name to specify. If it is NULL, an OPENFILE
  47. dialog box is displayed to allow the user to select which Ppd structure to
  48. load.
  49. Return value indicates the success or failure of the device load
  50. --*/
  51. {
  52. OPENFILENAME OpenInfo;
  53. BOOL Result;
  54. PHIDP_PREPARSED_DATA PpdBuffer;
  55. ULONG PpdLength;
  56. /*
  57. // LoadLogicalDevice consists of three steps.
  58. // First it builds the structure needed to get the filename and calls
  59. // the standard LoadFile dialog box.
  60. //
  61. // Then it uses that file name to get the Preparsed Data that is stored
  62. // on disk.
  63. //
  64. // Lastly, it fills in the the HidDevice Info block to create the logical
  65. // device
  66. */
  67. if (NULL == HidDevice)
  68. {
  69. return (FALSE);
  70. }
  71. if (NULL != OptFileName)
  72. {
  73. strcpy(LogPnP_PpdFileName, OptFileName);
  74. }
  75. else
  76. {
  77. /*
  78. // Initialize the OpenInfo structure
  79. */
  80. LogPnP_PpdFileName[0] = '\0';
  81. OpenInfo.lStructSize = sizeof(OPENFILENAME);
  82. OpenInfo.hwndOwner = GetTopWindow(NULL);
  83. OpenInfo.hInstance = NULL;
  84. OpenInfo.lpstrFilter = OPENFILE_FILTER;
  85. OpenInfo.lpstrCustomFilter = NULL;
  86. OpenInfo.nMaxCustFilter = 0;
  87. OpenInfo.nFilterIndex = 1;
  88. OpenInfo.lpstrFile = LogPnP_PpdFileName;
  89. OpenInfo.nMaxFile = MAX_PATH+1;
  90. OpenInfo.lpstrFileTitle = NULL;
  91. OpenInfo.nMaxFileTitle = 0;
  92. OpenInfo.lpstrInitialDir = NULL;
  93. OpenInfo.lpstrTitle = "Load Preparsed Data File";
  94. OpenInfo.Flags = OFN_PATHMUSTEXIST;
  95. OpenInfo.nFileOffset = 0;
  96. OpenInfo.nFileExtension = 0;
  97. OpenInfo.lpstrDefExt = "PPD";
  98. OpenInfo.lCustData = 0;
  99. OpenInfo.lpfnHook = NULL;
  100. OpenInfo.lpTemplateName = NULL;
  101. /*
  102. // Call the open dialog box routine
  103. */
  104. Result = GetOpenFileName(&OpenInfo);
  105. if (!Result) {
  106. return (FALSE);
  107. }
  108. }
  109. /*
  110. // At this point, we should have a valid path and filename stored in
  111. // LogPnP_PpdFileName. Next step is to load the prepased data from
  112. // that file
  113. */
  114. Result = LogPnP_LoadPpdFromFile(LogPnP_PpdFileName,
  115. &PpdBuffer,
  116. &PpdLength);
  117. if (!Result)
  118. {
  119. return (FALSE);
  120. }
  121. /*
  122. // Now, we've opened the file, got the preparsed data into our buffer and
  123. // closed the file. We probably want to verify the Preparsed Data
  124. // somehow at this point. Since I'm not sure exactly how I want to do
  125. // this and time is of the essence, I'm skipping that for now (ISSUE);
  126. */
  127. Result = LogPnP_BuildLogicalHIDDevice(PpdBuffer, HidDevice);
  128. if (!Result)
  129. {
  130. free(PpdBuffer);
  131. return (FALSE);
  132. }
  133. /*
  134. // Hey, we've gotten all the way to the end and have succeeded. Return (TRUE);
  135. */
  136. return (TRUE);
  137. }
  138. BOOL
  139. LogPnP_BuildLogicalHIDDevice(
  140. IN PHIDP_PREPARSED_DATA HidPpd,
  141. IN OUT PHID_DEVICE HidDevice
  142. )
  143. /*++
  144. RoutineDescription:
  145. This routine fills in all the data fields of a HID_DEVICE structure that are
  146. related to logical devices. In other words, everything but a file handle and
  147. the attributes structure.
  148. It returns FALSE if for some reason, it cannot accoomplish its assigned task.
  149. --*/
  150. {
  151. BOOLEAN bSuccess;
  152. HidDevice -> HidDevice = INVALID_HANDLE_VALUE;
  153. HidDevice -> Ppd = HidPpd;
  154. if (!HidP_GetCaps (HidDevice->Ppd, &HidDevice->Caps))
  155. {
  156. return FALSE;
  157. }
  158. FillMemory(&(HidDevice -> Attributes), sizeof(HIDD_ATTRIBUTES), 0x00 );
  159. bSuccess = FillDeviceInfo(HidDevice);
  160. if (FALSE == bSuccess)
  161. {
  162. return (FALSE);
  163. }
  164. return (TRUE);
  165. }
  166. BOOL
  167. LogPnP_LoadPpdFromFile(
  168. IN PCHAR FileName,
  169. OUT PHIDP_PREPARSED_DATA *PpdBuffer,
  170. OUT PULONG PpdBufferLength
  171. )
  172. /*++
  173. RoutineDescription:
  174. This routine takes the passed in filename, opens it for read, and reads the
  175. preparsed data structure from the file. It determines the size of the
  176. parparsed data based on the size of the file so no extraneous bytes should
  177. be added to preparsed data blocks without modifying this routine.
  178. This routine will return TRUE if everything goes as planned, FALSE otherwise
  179. --*/
  180. {
  181. HANDLE FileHandle;
  182. BOOL ReadStatus;
  183. DWORD FileSize;
  184. DWORD BytesRead;
  185. *PpdBuffer = NULL;
  186. *PpdBufferLength = 0;
  187. FileHandle = CreateFile(FileName,
  188. GENERIC_READ,
  189. FILE_SHARE_READ,
  190. NULL,
  191. OPEN_EXISTING,
  192. 0,
  193. NULL);
  194. if (INVALID_HANDLE_VALUE == FileHandle)
  195. {
  196. return (FALSE);
  197. }
  198. /*
  199. // Call GetFileSize to get the size of the file so we know how many
  200. // bytes we need to allocate for the preparsed data buffer.
  201. // GetFileSize returns 0xFFFFFFFF on error, so that gets checked as
  202. // well after the call is made
  203. */
  204. FileSize = GetFileSize(FileHandle, NULL);
  205. if (0xFFFFFFFF == FileSize)
  206. {
  207. CloseHandle(FileHandle);
  208. return (FALSE);
  209. }
  210. /*
  211. // Now, let's allocate the buffer space needed to store the preparsed data
  212. // in the file
  213. */
  214. *PpdBuffer = (PHIDP_PREPARSED_DATA) malloc(FileSize);
  215. if (NULL == *PpdBuffer)
  216. {
  217. CloseHandle(FileHandle);
  218. return (FALSE);
  219. }
  220. /*
  221. // OK, the buffer has been allocated, let's read in our data from the file
  222. */
  223. ReadStatus = ReadFile(FileHandle,
  224. *PpdBuffer,
  225. FileSize,
  226. &BytesRead,
  227. NULL);
  228. /*
  229. // We are done with the file handle now, so let's close it before we
  230. // proceed any farther.
  231. */
  232. CloseHandle(FileHandle);
  233. if (BytesRead != FileSize || !ReadStatus)
  234. {
  235. free(*PpdBuffer);
  236. *PpdBuffer = NULL;
  237. return (FALSE);
  238. }
  239. /*
  240. // If we got to this point, everything is perfect. Close the file handle
  241. // and set the size of the buffer and return TRUE.
  242. */
  243. *PpdBufferLength = FileSize;
  244. return (TRUE);
  245. }
  246. VOID
  247. LogPnP_CloseLogicalHIDDevices(
  248. IN PHID_DEVICE LogicalDeviceList,
  249. IN ULONG NumLogicalDevices
  250. )
  251. /*++
  252. RoutineDescription:
  253. This routine takes a list of HID_DEVICE structures that are all logical
  254. devices and frees up any resources that were associated with the given
  255. logical device.
  256. --*/
  257. {
  258. ULONG Index;
  259. for (Index = 0; Index < NumLogicalDevices; Index++)
  260. {
  261. LogPnP_CloseLogicalDevice(LogicalDeviceList+Index);
  262. }
  263. return;
  264. }
  265. VOID
  266. LogPnP_CloseLogicalDevice(
  267. IN PHID_DEVICE LogicalDevice
  268. )
  269. /*++
  270. RoutineDescription:
  271. This routine performs the task of freeing up the resources of HID_DEVICE
  272. structure for a given logical device.
  273. --*/
  274. {
  275. /*
  276. // To close the logical device, we need to undo all that was done by
  277. // the FillDeviceInfo routine. This can be accomplished by calling
  278. // CloseHidDevice. However, for this to succeed we need to free the
  279. // preparsed data itself because it was not allocated by HID.DLL.
  280. // Therefore, we cannot call HidD_FreePreparsedData. Instead, we free
  281. // it ourselves and set it to NULL so that won't attempt to free it
  282. // in the close routine
  283. */
  284. free(LogicalDevice -> Ppd);
  285. LogicalDevice -> Ppd = NULL;
  286. CloseHidDevice(LogicalDevice, TRUE);
  287. return;
  288. }
  289. BOOL
  290. LogPnP_IsLogicalDevice(
  291. IN PHID_DEVICE HidDevice
  292. )
  293. /*++
  294. RoutineDescription:
  295. This routine returns TRUE if the passed in HID_DEVICE structure is a logical
  296. device and FALSE if it is a physical device.
  297. --*/
  298. {
  299. /*
  300. // In the current implementation, a HID_DEVICE block is marked as a logical
  301. // device by setting the HidDevice field of the block to INVALID_HANDLE_VALUE
  302. */
  303. return (INVALID_HANDLE_VALUE == HidDevice -> HidDevice);
  304. }