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.

435 lines
15 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. devids.c
  5. Abstract:
  6. Builds a list of device ID and INF name pairs, based on a device class, and or
  7. INI file list.
  8. The list will be built as follows:
  9. If the list exists in the specified INI file, then the INI file will be used.
  10. If the specified INI file section exists, but is empty, then the local INF files
  11. will be used
  12. If the specified INI section does not exists, then no list will be built
  13. Author:
  14. Donald McNamara (donaldm) 02/08/2000
  15. Revision History:
  16. --*/
  17. #include "pch.h"
  18. #include <spsyslib.h>
  19. /*++
  20. ===============================================================================
  21. Routine Description:
  22. BOOL bIniSectionExists
  23. This routine will determine if the specified INI sections exists in the
  24. specificed INI file
  25. Arguments:
  26. lpszSectionName - The section name to look for
  27. lpszIniFile - The INI file to search
  28. Return Value:
  29. TRUE if the section name exists
  30. FALSE if the section name does not exist
  31. FALSE and LastError != 0 if there was a critical failure.
  32. ===============================================================================
  33. --*/
  34. #ifndef LOG
  35. #define LogFactoryInstallError
  36. #endif
  37. // ISSUE-2002/03/27-acosma,robertko - Check for NULL input parameters.
  38. //
  39. BOOL bINISectionExists
  40. (
  41. LPTSTR lpszSectionName,
  42. LPTSTR lpszIniFile
  43. )
  44. {
  45. BOOL bRet = FALSE; // Assume it does not exists
  46. LPTSTR lpBuffer;
  47. LPTSTR lpNew;
  48. LPTSTR lpSections;
  49. DWORD dwSectionLen;
  50. DWORD dwBufferSize;
  51. DWORD dwResult;
  52. SetLastError(0); // Assume no errors so far
  53. // Allocate a buffer to hold the section names
  54. if(lpBuffer = (LPTSTR)LocalAlloc(LPTR, (INIBUF_SIZE*sizeof(TCHAR))))
  55. {
  56. dwBufferSize = INIBUF_SIZE;
  57. }
  58. else
  59. {
  60. LogFactoryInstallError(TEXT("FACTORY:: Failed to allocate a buffer for reading the WINBOM file"));
  61. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  62. goto Clean0;
  63. }
  64. while((dwResult = GetPrivateProfileSectionNames(lpBuffer,
  65. dwBufferSize,
  66. lpszIniFile)) == (dwBufferSize-2))
  67. {
  68. if(lpNew = LocalReAlloc(lpBuffer,
  69. ((dwBufferSize+INIBUF_GROW)*sizeof(TCHAR)),
  70. LMEM_MOVEABLE))
  71. {
  72. lpBuffer = lpNew;
  73. dwBufferSize += INIBUF_GROW;
  74. }
  75. else
  76. {
  77. LogFactoryInstallError(TEXT("FACTORY:: Failed to Re-allocate a buffer for reading the WINBOM file"));
  78. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  79. goto Clean0;
  80. }
  81. }
  82. // Enumerate all sections
  83. for(lpSections = lpBuffer; *lpSections; lpSections+=dwSectionLen)
  84. {
  85. dwSectionLen = lstrlen(lpSections)+1;
  86. if (lstrcmpi(lpSections, lpszSectionName) == 0)
  87. {
  88. bRet = TRUE;
  89. break;
  90. }
  91. }
  92. Clean0:
  93. if (lpBuffer)
  94. {
  95. LocalFree(lpBuffer);
  96. }
  97. return bRet;
  98. }
  99. /*++
  100. ===============================================================================
  101. Routine Description:
  102. BOOL BuildDeviceIDList
  103. This routine will build the list of device IDs
  104. Arguments:
  105. lpszSectionName - The section name that might contain a list of device IDs and INFs
  106. lpszIniFile - The INI file to search
  107. lpDeviceClassGUID - The device class to use to generate a list of all possible IDs
  108. lpDeviceIDList - A pointer to be allocated and filled in with the list of IDs
  109. lpdwNumDeviceIDs - A pointer to a DWORD that will recieve the number of IDs found
  110. bForceIDScan - If TRUE a scan of IDs will be forced, even if the Section name is
  111. not empty.
  112. bForceAlwaysSecExist - Do a Scan for all IDs even if the section name does not exist.
  113. Return Value:
  114. TRUE if the list is build with no problem, or the list is empty because there
  115. was no INI file section. lpdwNumDeviceIDs is valid in this case
  116. FALSE if the list cannot be built.
  117. ===============================================================================
  118. --*/
  119. // ISSUE-2002/03/27-acosma,robertko - Check for NULL input parameters.
  120. //
  121. BOOL BuildDeviceIDList
  122. (
  123. LPTSTR lpszSectionName,
  124. LPTSTR lpszIniFileName,
  125. LPGUID lpDeviceClassGUID,
  126. LPDEVIDLIST *lplpDeviceIDList,
  127. LPDWORD lpdwNumDeviceIDs,
  128. BOOL bForceIDScan,
  129. BOOL bForceAlwaysSecExist
  130. )
  131. {
  132. BOOL bRet = TRUE;
  133. LPTSTR lpNew;
  134. LPTSTR lpBuffer;
  135. LPTSTR lpKeys;
  136. DWORD dwBufferSize;
  137. DWORD dwKeyLen;
  138. DWORD dwResult;
  139. HDEVINFO DeviceInfoSet;
  140. SP_DRVINFO_DATA DrvInfoData;
  141. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  142. PSP_DRVINFO_DETAIL_DATA lpDrvInfoDetailData;
  143. DWORD cbBytesNeeded = 0;
  144. int i;
  145. LPTSTR lpszHwIDs;
  146. LPDEVIDLIST lpDevIDList;
  147. DWORD dwSizeDevIDList;
  148. WCHAR szINFFileName[MAX_PATH];
  149. // Allocate a buffer to hold the section names
  150. if(lpBuffer = (LPTSTR)LocalAlloc(LPTR, (INIBUF_SIZE*sizeof(TCHAR))))
  151. {
  152. dwBufferSize = INIBUF_SIZE;
  153. }
  154. else
  155. {
  156. LogFactoryInstallError(TEXT("FACTORY:: Failed to allocate a buffer for reading the WINBOM file"));
  157. bRet = FALSE;
  158. goto Clean1;
  159. }
  160. // Iniitalize the number of device ID's found
  161. *lpdwNumDeviceIDs = 0;
  162. // See if the INI section exists. We don't do anything if it does not
  163. if (bForceAlwaysSecExist || bINISectionExists(lpszSectionName, lpszIniFileName))
  164. {
  165. // Allocate the Initial ID array
  166. *lplpDeviceIDList = LocalAlloc(LPTR, DEVID_ARRAY_SIZE * sizeof(DEVIDLIST));
  167. lpDevIDList = *lplpDeviceIDList;
  168. dwSizeDevIDList = DEVID_ARRAY_SIZE;
  169. // Make sure there was not an error
  170. if (!lpDevIDList)
  171. {
  172. LogFactoryInstallError(TEXT("FACTORY:: Failed to allocate a buffer for reading the WINBOM file"));
  173. bRet = FALSE;
  174. goto Clean1;
  175. }
  176. dwResult = GetPrivateProfileString(lpszSectionName,
  177. NULL, // Get all keys
  178. TEXT(""),
  179. lpBuffer,
  180. dwBufferSize,
  181. lpszIniFileName);
  182. if (bForceIDScan || dwResult == 0)
  183. {
  184. // Allocate a DeviceInfo Set, for the specific device class GUID
  185. DeviceInfoSet = SetupDiCreateDeviceInfoList(lpDeviceClassGUID, NULL);
  186. if(DeviceInfoSet == INVALID_HANDLE_VALUE)
  187. {
  188. bRet = FALSE;
  189. goto Clean1;
  190. }
  191. // OR in the DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE flag to ensure we populate
  192. // the list with all of the device id's
  193. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  194. if (SetupDiGetDeviceInstallParams(DeviceInfoSet,
  195. NULL,
  196. &DeviceInstallParams))
  197. {
  198. DeviceInstallParams.FlagsEx |= DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE;
  199. SetupDiSetDeviceInstallParams(DeviceInfoSet,
  200. NULL,
  201. &DeviceInstallParams);
  202. }
  203. if (!SetupDiBuildDriverInfoList(DeviceInfoSet, NULL, SPDIT_CLASSDRIVER))
  204. {
  205. bRet = FALSE;
  206. goto Clean1;
  207. }
  208. i = 0;
  209. DrvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  210. while (SetupDiEnumDriverInfo(DeviceInfoSet,
  211. NULL,
  212. SPDIT_CLASSDRIVER,
  213. i,
  214. &DrvInfoData))
  215. {
  216. if (!SetupDiGetDriverInfoDetail(DeviceInfoSet,
  217. NULL,
  218. &DrvInfoData,
  219. NULL,
  220. 0,
  221. &cbBytesNeeded))
  222. {
  223. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  224. {
  225. continue;
  226. }
  227. }
  228. lpDrvInfoDetailData = LocalAlloc(LPTR, cbBytesNeeded);
  229. lpDrvInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  230. lpDrvInfoDetailData->HardwareID[0] = (TCHAR)NULL;
  231. lpDrvInfoDetailData->CompatIDsLength = 0;
  232. if (!SetupDiGetDriverInfoDetail(DeviceInfoSet,
  233. NULL,
  234. &DrvInfoData,
  235. lpDrvInfoDetailData,
  236. cbBytesNeeded,
  237. NULL))
  238. {
  239. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  240. {
  241. LocalFree(lpDrvInfoDetailData);
  242. continue;
  243. }
  244. }
  245. //
  246. // Init
  247. //
  248. lpDevIDList[*lpdwNumDeviceIDs].szHardwareID[0] = _T('\0');
  249. lpDevIDList[*lpdwNumDeviceIDs].szCompatibleID[0] = _T('\0');
  250. //
  251. // Process only devices with valid HardWareID
  252. //
  253. if (lpDrvInfoDetailData->HardwareID[0] || lpDrvInfoDetailData->CompatIDsLength)
  254. {
  255. // Copy the HW ID
  256. if (lpDrvInfoDetailData->HardwareID[0])
  257. lstrcpy(lpDevIDList[*lpdwNumDeviceIDs].szHardwareID, lpDrvInfoDetailData->HardwareID);
  258. // Copy the Compat ID
  259. if (lpDrvInfoDetailData->CompatIDsLength)
  260. {
  261. lstrcpyn(lpDevIDList[*lpdwNumDeviceIDs].szCompatibleID,
  262. (LPCTSTR)lpDrvInfoDetailData->HardwareID + lpDrvInfoDetailData->CompatIDsOffset,
  263. lpDrvInfoDetailData->CompatIDsLength);
  264. }
  265. // Copy the INF file name
  266. lstrcpy(lpDevIDList[*lpdwNumDeviceIDs].szINFFileName, lpDrvInfoDetailData->InfFileName);
  267. //
  268. // Increment PnP devices count
  269. //
  270. ++(*lpdwNumDeviceIDs);
  271. // See if the device ID buffer needs to be reallocated
  272. if (*lpdwNumDeviceIDs == dwSizeDevIDList)
  273. {
  274. if(lpNew = LocalReAlloc(*lplpDeviceIDList,
  275. ((dwSizeDevIDList + DEVID_ARRAY_GROW)*sizeof(DEVIDLIST)),
  276. LMEM_MOVEABLE))
  277. {
  278. *lplpDeviceIDList = (LPDEVIDLIST)lpNew;
  279. lpDevIDList = *lplpDeviceIDList;
  280. dwSizeDevIDList += DEVID_ARRAY_GROW;
  281. }
  282. else
  283. {
  284. LogFactoryInstallError(TEXT("FACTORY:: Failed to Re-allocate a buffer for reading the WINBOM file"));
  285. bRet = FALSE;
  286. goto Clean1;
  287. }
  288. }
  289. }
  290. LocalFree(lpDrvInfoDetailData);
  291. ++i;
  292. }
  293. }
  294. else
  295. {
  296. // See if we got the whole section, and while we don't keep
  297. // making lpbuffer biffer
  298. while (dwResult == (dwBufferSize-2))
  299. {
  300. if(lpNew = LocalReAlloc(lpBuffer,
  301. ((dwBufferSize+INIBUF_GROW)*sizeof(TCHAR)),
  302. LMEM_MOVEABLE))
  303. {
  304. lpBuffer = lpNew;
  305. dwBufferSize += INIBUF_GROW;
  306. }
  307. else
  308. {
  309. LogFactoryInstallError(TEXT("FACTORY:: Failed to Re-allocate a buffer for reading the WINBOM file"));
  310. bRet = FALSE;
  311. goto Clean1;
  312. }
  313. dwResult = GetPrivateProfileString(lpszSectionName,
  314. NULL, // Get all keys
  315. TEXT(""),
  316. lpBuffer,
  317. dwBufferSize,
  318. lpszIniFileName);
  319. }
  320. // Walk the list, building the DeviceIDList
  321. for(lpKeys = lpBuffer; *lpKeys; lpKeys+=dwKeyLen)
  322. {
  323. dwKeyLen = lstrlen(lpKeys)+1;
  324. // Copy the HW ID
  325. // NTRAID#NTBUG9-551266-2002/02/26-acosma - Buffer overrun possibility.
  326. //
  327. lstrcpy(lpDevIDList[*lpdwNumDeviceIDs].szHardwareID, lpKeys);
  328. // Get the INF name
  329. GetPrivateProfileString(lpszSectionName,
  330. lpKeys,
  331. TEXT(""),
  332. szINFFileName,
  333. MAX_PATH,
  334. lpszIniFileName);
  335. ExpandEnvironmentStrings(szINFFileName, lpDevIDList[*lpdwNumDeviceIDs].szINFFileName, MAX_PATH);
  336. ++(*lpdwNumDeviceIDs);
  337. // See if the device ID buffer needs to be reallocated
  338. if (*lpdwNumDeviceIDs == dwSizeDevIDList)
  339. {
  340. if(lpNew = LocalReAlloc(*lplpDeviceIDList,
  341. ((dwSizeDevIDList + DEVID_ARRAY_GROW)*sizeof(DEVIDLIST)),
  342. LMEM_MOVEABLE))
  343. {
  344. *lplpDeviceIDList = (LPDEVIDLIST)lpNew;
  345. lpDevIDList = *lplpDeviceIDList;
  346. dwSizeDevIDList += DEVID_ARRAY_GROW;
  347. }
  348. else
  349. {
  350. LogFactoryInstallError(TEXT("FACTORY:: Failed to Re-allocate a buffer for reading the WINBOM file"));
  351. bRet = FALSE;
  352. goto Clean1;
  353. }
  354. }
  355. }
  356. }
  357. }
  358. else
  359. {
  360. // See if there was an error, or the section just does not exist
  361. if (GetLastError() != 0)
  362. {
  363. bRet = FALSE;
  364. }
  365. }
  366. Clean1:
  367. if (lpBuffer)
  368. {
  369. LocalFree(lpBuffer);
  370. }
  371. return bRet;
  372. }