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.

1150 lines
37 KiB

  1. #include "StdAfx.h"
  2. #include <initguid.h>
  3. #include <wincrypt.h>
  4. #include "setupapi.h"
  5. #include <WinTrust.h>
  6. #include "mscat.h"
  7. #include "softpub.h"
  8. #include "devguid.h"
  9. #include "regstr.h"
  10. #include "cfgmgr32.h"
  11. //
  12. // This guid is used for file signing/verification.
  13. //
  14. GUID DriverVerifyGuid = DRIVER_ACTION_VERIFY;
  15. BOOL IsInfSigned(LPTSTR FullInfPath , IWbemClassObject *pInstance = NULL);
  16. typedef struct _NOCOPYLIST {
  17. PTSTR pListOfFiles;
  18. ULONG Size;
  19. BOOL MicrosoftDriver;
  20. } NOCOPYLIST, *PNOCOPYLIST;
  21. PCTSTR
  22. MyGetFileTitle(
  23. IN PCTSTR FilePath
  24. )
  25. /*++
  26. Routine Description:
  27. This routine returns a pointer to the first character in the
  28. filename part of the supplied path. If only a filename was given,
  29. then this will be a pointer to the first character in the string
  30. (i.e., the same as what was passed in).
  31. To find the filename part, the routine returns the last component of
  32. the string, beginning with the character immediately following the
  33. last '\', '/' or ':'. (NB NT treats '/' as equivalent to '\' )
  34. Arguments:
  35. FilePath - Supplies the file path from which to retrieve the filename
  36. portion.
  37. Return Value:
  38. A pointer to the beginning of the filename portion of the path.
  39. --*/
  40. {
  41. PCTSTR LastComponent = FilePath;
  42. TCHAR CurChar;
  43. while(CurChar = *FilePath) {
  44. FilePath = CharNext(FilePath);
  45. if((CurChar == TEXT('\\')) || (CurChar == TEXT('/')) || (CurChar == TEXT(':'))) {
  46. LastComponent = FilePath;
  47. }
  48. }
  49. return LastComponent;
  50. }
  51. BOOL
  52. pGetOriginalInfName(
  53. LPTSTR InfName,
  54. LPTSTR OriginalInfName,
  55. LPTSTR OriginalCatalogName
  56. )
  57. {
  58. SP_ORIGINAL_FILE_INFO InfOriginalFileInformation;
  59. PSP_INF_INFORMATION pInfInformation;
  60. DWORD InfInformationSize;
  61. DWORD Error;
  62. BOOL bRet;
  63. //
  64. // Assume that this INF has not been renamed
  65. //
  66. lstrcpy(OriginalInfName, MyGetFileTitle(InfName));
  67. ZeroMemory(&InfOriginalFileInformation, sizeof(InfOriginalFileInformation));
  68. InfInformationSize = 8192; // I'd rather have this too big and succeed first time, than read the INF twice
  69. pInfInformation = (PSP_INF_INFORMATION)LocalAlloc(LPTR, InfInformationSize);
  70. if (pInfInformation != NULL) {
  71. bRet = SetupGetInfInformation(InfName,
  72. INFINFO_INF_NAME_IS_ABSOLUTE,
  73. pInfInformation,
  74. InfInformationSize,
  75. &InfInformationSize
  76. );
  77. Error = GetLastError();
  78. //
  79. // If buffer was too small then make the buffer larger and try again.
  80. //
  81. if (!bRet && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  82. PVOID newbuff = LocalReAlloc(pInfInformation, InfInformationSize, LPTR);
  83. if (!newbuff) {
  84. LocalFree(pInfInformation);
  85. pInfInformation = NULL;
  86. } else {
  87. pInfInformation = (PSP_INF_INFORMATION)newbuff;
  88. bRet = SetupGetInfInformation(InfName,
  89. INFINFO_INF_NAME_IS_ABSOLUTE,
  90. pInfInformation,
  91. InfInformationSize,
  92. &InfInformationSize
  93. );
  94. }
  95. }
  96. if (bRet) {
  97. InfOriginalFileInformation.cbSize = sizeof(InfOriginalFileInformation);
  98. if (SetupQueryInfOriginalFileInformation(pInfInformation, 0, NULL, &InfOriginalFileInformation)) {
  99. if (InfOriginalFileInformation.OriginalInfName[0]!=0) {
  100. //
  101. // we have a "real" inf name
  102. //
  103. lstrcpy(OriginalInfName, InfOriginalFileInformation.OriginalInfName);
  104. lstrcpy(OriginalCatalogName, InfOriginalFileInformation.OriginalCatalogName);
  105. }
  106. }
  107. }
  108. if (pInfInformation != NULL) {
  109. LocalFree(pInfInformation);
  110. pInfInformation = NULL;
  111. }
  112. }
  113. return TRUE;
  114. }
  115. BOOL
  116. IsInfSigned(
  117. LPTSTR FullInfPath , IWbemClassObject *pInstance
  118. )
  119. {
  120. TCHAR OriginalInfName[MAX_PATH];
  121. TCHAR Catalog[MAX_PATH];
  122. LPBYTE Hash;
  123. DWORD HashSize;
  124. CATALOG_INFO CatInfo;
  125. HANDLE hFile;
  126. HCATADMIN hCatAdmin;
  127. HCATINFO hCatInfo;
  128. HCATINFO PrevCat;
  129. DWORD Err;
  130. WINTRUST_DATA WintrustData;
  131. WINTRUST_CATALOG_INFO WintrustCatalogInfo;
  132. DRIVER_VER_INFO VersionInfo;
  133. OSVERSIONINFO OSVer;
  134. LPTSTR CatalogFullPath;
  135. CRYPT_PROVIDER_DATA const * pProvData = NULL;
  136. CRYPT_PROVIDER_SGNR * pProvSigner = NULL;
  137. GUID defaultProviderGUID = DRIVER_ACTION_VERIFY;
  138. HRESULT hr;
  139. BYTE rgbHash[20];
  140. DWORD cbData;
  141. BOOL bIsSigned = FALSE;
  142. ZeroMemory(Catalog, sizeof(Catalog));
  143. //
  144. // Get the INFs original name (this is needed since it is the hash key)
  145. //
  146. pGetOriginalInfName(FullInfPath, OriginalInfName, Catalog);
  147. //
  148. // Calculate the hash value for the inf.
  149. //
  150. if(CryptCATAdminAcquireContext(&hCatAdmin, &DriverVerifyGuid, 0)) {
  151. hFile = CreateFile(FullInfPath,
  152. GENERIC_READ,
  153. FILE_SHARE_READ,
  154. NULL,
  155. OPEN_EXISTING,
  156. 0,
  157. NULL
  158. );
  159. if(hFile == INVALID_HANDLE_VALUE) {
  160. Err = GetLastError();
  161. } else {
  162. //
  163. // Start out with a hash buffer size that should be large enough for
  164. // most requests.
  165. //
  166. HashSize = 100;
  167. do {
  168. Hash = (LPBYTE)LocalAlloc(LPTR, HashSize);
  169. if(!Hash) {
  170. Err = ERROR_NOT_ENOUGH_MEMORY;
  171. break;
  172. }
  173. if(CryptCATAdminCalcHashFromFileHandle(hFile, &HashSize, Hash, 0)) {
  174. Err = NO_ERROR;
  175. } else {
  176. Err = GetLastError();
  177. //
  178. // If this API did screw up and not set last error, go ahead
  179. // and set something.
  180. //
  181. if(Err == NO_ERROR) {
  182. Err = ERROR_INVALID_DATA;
  183. }
  184. LocalFree(Hash);
  185. if(Err != ERROR_INSUFFICIENT_BUFFER) {
  186. //
  187. // The API failed for some reason other than
  188. // buffer-too-small. We gotta bail.
  189. //
  190. Hash = NULL; // reset this so we won't try to free it later
  191. break;
  192. }
  193. }
  194. } while(Err != NO_ERROR);
  195. CloseHandle(hFile);
  196. if(Err == NO_ERROR) {
  197. //
  198. // Now we have the file's hash. Initialize the structures that
  199. // will be used later on in calls to WinVerifyTrust.
  200. //
  201. ZeroMemory(&WintrustData, sizeof(WINTRUST_DATA));
  202. WintrustData.cbStruct = sizeof(WINTRUST_DATA);
  203. WintrustData.dwUIChoice = WTD_UI_NONE;
  204. WintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
  205. WintrustData.dwUnionChoice = WTD_CHOICE_CATALOG;
  206. //WintrustData.dwStateAction = WTD_STATEACTION_AUTO_CACHE;
  207. WintrustData.dwStateAction = WTD_STATEACTION_VERIFY;
  208. WintrustData.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
  209. WintrustData.pCatalog = &WintrustCatalogInfo;
  210. ZeroMemory(&WintrustCatalogInfo, sizeof(WINTRUST_CATALOG_INFO));
  211. WintrustCatalogInfo.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
  212. WintrustCatalogInfo.pbCalculatedFileHash = Hash;
  213. WintrustCatalogInfo.cbCalculatedFileHash = HashSize;
  214. WintrustData.pPolicyCallbackData = (LPVOID)&VersionInfo;
  215. ZeroMemory(&VersionInfo, sizeof(DRIVER_VER_INFO));
  216. VersionInfo.cbStruct = sizeof(DRIVER_VER_INFO);
  217. ZeroMemory(&OSVer, sizeof(OSVERSIONINFO));
  218. OSVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  219. if (GetVersionEx(&OSVer)) {
  220. VersionInfo.dwPlatform = OSVer.dwPlatformId;
  221. VersionInfo.dwVersion = OSVer.dwMajorVersion;
  222. VersionInfo.sOSVersionLow.dwMajor = OSVer.dwMajorVersion;
  223. VersionInfo.sOSVersionLow.dwMinor = OSVer.dwMinorVersion;
  224. VersionInfo.sOSVersionHigh.dwMajor = OSVer.dwMajorVersion;
  225. VersionInfo.sOSVersionHigh.dwMinor = OSVer.dwMinorVersion;
  226. }
  227. //
  228. // WinVerifyTrust is case-sensitive, so ensure that the key
  229. // being used is all lower-case!
  230. //
  231. CharLower(OriginalInfName);
  232. WintrustCatalogInfo.pcwszMemberTag = OriginalInfName;
  233. //
  234. // Search through installed catalogs looking for those that
  235. // contain data for a file with the hash we just calculated.
  236. //
  237. PrevCat = NULL;
  238. hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin,
  239. Hash,
  240. HashSize,
  241. 0,
  242. &PrevCat
  243. );
  244. //
  245. // Enumerate through all of the catalogs installed on the system
  246. //CryptCATCatalogInfoFromContext
  247. while(hCatInfo) {
  248. CatInfo.cbStruct = sizeof(CATALOG_INFO);
  249. if(CryptCATCatalogInfoFromContext(hCatInfo, &CatInfo, 0)) {
  250. CatalogFullPath = CatInfo.wszCatalogFile;
  251. DEBUGTRACE(L"Catalog file is %s\n" , CatalogFullPath);
  252. //
  253. // If we have a catalog name we're looking for,
  254. // see if the current catalog matches. If we
  255. // are not validating against a specific catalog, then
  256. // just attempt to validate against each catalog we
  257. // enumerate. Note that the catalog file info we
  258. // get back gives us a fully qualified path.
  259. //
  260. if((Catalog[0] == TEXT('\0')) ||
  261. (!lstrcmpi(MyGetFileTitle(CatalogFullPath), (LPTSTR)Catalog)))
  262. {
  263. //
  264. // We found an applicable catalog, now
  265. // validate the file against that catalog.
  266. //
  267. // NOTE: Because we're using cached
  268. // catalog information (i.e., the
  269. // WTD_STATEACTION_AUTO_CACHE flag), we
  270. // don't need to explicitly validate the
  271. // catalog itself first.
  272. //
  273. WintrustCatalogInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
  274. Err = (DWORD)WinVerifyTrust(NULL,
  275. &DriverVerifyGuid,
  276. &WintrustData
  277. );
  278. //
  279. // If WinVerifyTrust suceeded
  280. //
  281. if (Err == NO_ERROR) {
  282. //BugBug: Changes to the original code
  283. //
  284. bIsSigned = TRUE;
  285. DEBUGTRACE(L"%ws is signed by %ws\n", FullInfPath, VersionInfo.wszSignedBy);
  286. //lstrcpy(FullInfPath , VersionInfo.wszSignedBy);
  287. if(NULL != pInstance)
  288. {
  289. VARIANT v;
  290. VariantInit(&v);
  291. /*v.vt = VT_BOOL;
  292. v.boolVal = bIsSigned;
  293. hr = pInstance->Put(L"IsSigned", 0, &v, 0 );
  294. VariantClear(&v);*/
  295. v.vt = VT_BSTR;
  296. v.bstrVal = VersionInfo.wszSignedBy;
  297. hr = pInstance->Put(L"Signer", 0, &v, 0 );
  298. VariantClear(&v);
  299. CRYPTCATATTRIBUTE *pCatAttribute = NULL;
  300. HANDLE hCat = CryptCATOpen(CatalogFullPath,
  301. GENERIC_READ,
  302. NULL,
  303. NULL,
  304. NULL);
  305. if(hCat != INVALID_HANDLE_VALUE)
  306. do
  307. {
  308. pCatAttribute = CryptCATEnumerateCatAttr(hCat , pCatAttribute);
  309. if(pCatAttribute && pCatAttribute->pbValue && pCatAttribute->pwszReferenceTag)
  310. {
  311. v.vt = VT_BSTR;
  312. v.bstrVal = (LPTSTR)pCatAttribute->pbValue;
  313. hr = pInstance->Put(pCatAttribute->pwszReferenceTag, 0, &v, 0 );
  314. VariantClear(&v);
  315. TRACE(L"Attribute ReferenceTag = %s Value = %s\n" , pCatAttribute->pwszReferenceTag , (LPTSTR)pCatAttribute->pbValue);
  316. }
  317. }while(pCatAttribute);
  318. if(hCat != INVALID_HANDLE_VALUE)
  319. CryptCATClose(hCat);
  320. }
  321. //pProvData = WTHelperProvDataFromStateData(WintrustData.hWVTStateData);
  322. //
  323. // Get the first signer from the chain
  324. //
  325. //pProvSigner = WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA)pProvData,
  326. // 0,
  327. // FALSE,
  328. // 0
  329. // );
  330. if ((pProvData = WTHelperProvDataFromStateData(WintrustData.hWVTStateData)) == NULL ){
  331. DEBUGTRACE(L"WTHelperProvDataDFromStateData failed\n");
  332. break;
  333. }
  334. //
  335. // Get the first signer from the chain
  336. //
  337. if ((pProvSigner = WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA)pProvData,
  338. 0,
  339. FALSE,
  340. 0
  341. )) == NULL) {
  342. DEBUGTRACE(L"NO Signer\n");
  343. break;
  344. }
  345. //
  346. // Get the sha1 hash from the signing cert
  347. //
  348. //assert(pProvSigner->pChainContext->cChain >= 1);
  349. //assert(pProvSigner->pChainContext->rgpChain[0]->rgpElement[0]->cElement >= 1);
  350. cbData = 20;
  351. if (CertGetCertificateContextProperty(
  352. pProvSigner->pChainContext->rgpChain[0]->rgpElement[0]->pCertContext,
  353. CERT_SHA1_HASH_PROP_ID,
  354. &(rgbHash[0]),
  355. &cbData)) {
  356. DEBUGTRACE(L"rgbHash:\n%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  357. rgbHash[0], rgbHash[1], rgbHash[2], rgbHash[3], rgbHash[4],
  358. rgbHash[5], rgbHash[6], rgbHash[7], rgbHash[8], rgbHash[9],
  359. rgbHash[10], rgbHash[11], rgbHash[12], rgbHash[13], rgbHash[14],
  360. rgbHash[15], rgbHash[16], rgbHash[17], rgbHash[18], rgbHash[19]);
  361. //
  362. // BUGBUG:
  363. // Compare the Hash to the Microsoft Windows 2000 hash only. If it matches
  364. // then this is NOT an OEM Hal, otherwise it is.
  365. //
  366. //
  367. // if (memcmp(&(rgbHash[0]), &MSHASH, 20) {
  368. // bIsSigned = TRUE;
  369. // } else {
  370. // bIsSignedByMicorsoft = FALSE;
  371. // }
  372. }
  373. }
  374. //
  375. // Free the pcSignerCertContext member of the DRIVER_VER_INFO struct
  376. // that was allocated in our call to WinVerifyTrust.
  377. //
  378. if (VersionInfo.pcSignerCertContext != NULL) {
  379. CertFreeCertificateContext(VersionInfo.pcSignerCertContext);
  380. VersionInfo.pcSignerCertContext = NULL;
  381. }
  382. //
  383. // If we had a specific catalog to compare against then we are
  384. // done.
  385. //
  386. if (Catalog[0] != TEXT('\0')) {
  387. CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
  388. break;
  389. }
  390. //
  391. // If we validated against a catalog and it is NOT signed by Microsoft then
  392. // we are done.
  393. //
  394. // Note that if we did validate against a Microsoft catalog then we want
  395. // to keep going in case the file validates against both a Microsoft
  396. // and OEM catalog.
  397. //
  398. if ((Err == NO_ERROR) && !bIsSigned) {
  399. CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
  400. break;
  401. }
  402. }
  403. }
  404. PrevCat = hCatInfo;
  405. hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin, Hash, HashSize, 0, &PrevCat);
  406. WintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
  407. Err = (DWORD)WinVerifyTrust(NULL,
  408. &DriverVerifyGuid,
  409. &WintrustData
  410. );
  411. }
  412. //else
  413. //{
  414. if(NULL != pInstance)
  415. {
  416. //VARIANT v;
  417. CComVariant v;
  418. //VariantInit(&v);
  419. //v.vt = VT_BOOL;
  420. v = bIsSigned;
  421. hr = pInstance->Put(L"IsSigned", 0, &v, 0 );
  422. //VariantClear(&v);
  423. v.Clear();
  424. }
  425. //}
  426. }
  427. if(Hash) {
  428. LocalFree(Hash);
  429. }
  430. }
  431. CryptCATAdminReleaseContext(hCatAdmin,0);
  432. }
  433. //BugBug: Changes to the original code
  434. //
  435. return bIsSigned;
  436. }
  437. BOOL
  438. IsOemHalInstalled(
  439. VOID
  440. )
  441. {
  442. HDEVINFO DeviceInfoSet;
  443. SP_DEVINFO_DATA DeviceInfoData;
  444. HKEY hKey;
  445. DWORD dwType, cbData;
  446. TCHAR InfName[MAX_PATH];
  447. TCHAR InfPath[MAX_PATH];
  448. BOOL isHalOem = TRUE;
  449. //
  450. // First get the "computer class" devnode
  451. //
  452. DeviceInfoSet = SetupDiGetClassDevs(&GUID_DEVCLASS_COMPUTER,
  453. NULL,
  454. NULL,
  455. DIGCF_PRESENT
  456. );
  457. if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
  458. goto clean0;
  459. }
  460. DeviceInfoData.cbSize = sizeof(DeviceInfoData);
  461. //
  462. // There should only be one device in the "computer class" so just
  463. // get the 1st device in the DeviceInfoSet.
  464. //
  465. if (!SetupDiEnumDeviceInfo(DeviceInfoSet,
  466. 0,
  467. &DeviceInfoData
  468. )) {
  469. goto clean0;
  470. }
  471. //
  472. // Open the device's driver (software) registry key so we can get the InfPath
  473. //
  474. hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
  475. &DeviceInfoData,
  476. DICS_FLAG_GLOBAL,
  477. 0,
  478. DIREG_DRV,
  479. KEY_READ
  480. );
  481. if (hKey != INVALID_HANDLE_VALUE) {
  482. dwType = REG_SZ;
  483. cbData = sizeof(InfPath);
  484. if (RegQueryValueEx(hKey,
  485. REGSTR_VAL_INFPATH,
  486. NULL,
  487. &dwType,
  488. (LPBYTE)InfName,
  489. &cbData
  490. ) == ERROR_SUCCESS) {
  491. if (GetWindowsDirectory(InfPath, sizeof(InfPath)/sizeof(TCHAR))) {
  492. if (lstrlen(InfPath)) {
  493. //
  494. // Tack on an extra back slash if one is needed
  495. //
  496. if (InfPath[lstrlen(InfPath) - 1] != TEXT('\\')) {
  497. lstrcat(InfPath, TEXT("\\"));
  498. }
  499. lstrcat(InfPath, TEXT("INF\\"));
  500. lstrcat(InfPath, InfName);
  501. DEBUGTRACE(L"IsOemHalInstalled() HAL Inf is %ws\n", InfPath);
  502. IsInfSigned(InfPath);
  503. }
  504. }
  505. }
  506. RegCloseKey(hKey);
  507. }
  508. clean0:
  509. return isHalOem;
  510. }
  511. DWORD
  512. pSetupGetCurrentlyInstalledDriverNode(
  513. IN HDEVINFO DeviceInfoSet,
  514. IN PSP_DEVINFO_DATA DeviceInfoData,
  515. IN OUT PTSTR InfPath
  516. )
  517. {
  518. HKEY hKey = NULL;
  519. DWORD RegDataType, RegDataLength;
  520. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  521. SP_DRVINFO_DATA DriverInfoData;
  522. DWORD Err = ERROR_SUCCESS;
  523. ZeroMemory(&DeviceInstallParams, sizeof(DeviceInstallParams));
  524. DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
  525. //
  526. // Retrieve the current device install parameters so we can modify them to
  527. // target the driver search to a particular INF.
  528. //
  529. if (!SetupDiGetDeviceInstallParams(DeviceInfoSet,
  530. DeviceInfoData,
  531. &DeviceInstallParams
  532. )) {
  533. return GetLastError();
  534. }
  535. //
  536. // In order to select the currently installed driver we will need to get the
  537. // devices description, manufacturer, and provider. So we will first open the
  538. // devices registry key to retrieve some of this information.
  539. //
  540. hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
  541. DeviceInfoData,
  542. DICS_FLAG_GLOBAL,
  543. 0,
  544. DIREG_DRV,
  545. KEY_READ
  546. );
  547. //
  548. // If we can't open the device's registry key then return FALSE. This means
  549. // we will be on the safe side and treat this as a 3rd party driver.
  550. //
  551. if (hKey == INVALID_HANDLE_VALUE) {
  552. return GetLastError();
  553. }
  554. RegDataLength = sizeof(DeviceInstallParams.DriverPath);
  555. if ((Err = RegQueryValueEx(hKey,
  556. REGSTR_VAL_INFPATH,
  557. NULL,
  558. &RegDataType,
  559. (PBYTE)DeviceInstallParams.DriverPath,
  560. &RegDataLength
  561. )) != ERROR_SUCCESS) {
  562. goto clean0;
  563. }
  564. //
  565. // Save the DriverPath in the InfPath parameter.
  566. //
  567. if (InfPath) {
  568. lstrcpy(InfPath, DeviceInstallParams.DriverPath);
  569. }
  570. //
  571. // Set the DeviceInstallParams flags that indicate DriverPath represents a
  572. // single INF to be searched, and set the flag that says to include all drivers,
  573. // even drivers that are normally excluded.
  574. //
  575. DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
  576. DeviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
  577. //
  578. // Build up a list of drivers from this device's INF.
  579. //
  580. if (!SetupDiBuildDriverInfoList(DeviceInfoSet,
  581. DeviceInfoData,
  582. SPDIT_CLASSDRIVER
  583. )) {
  584. Err = GetLastError();
  585. goto clean0;
  586. }
  587. //
  588. // Now we need to select the driver node from the INF that was used to install
  589. // this device. The three parameters that uniquely identify a driver node are
  590. // INF provider, Device Manufacturer, and Device Description. We will retrieve
  591. // these three pieces of information in preparation for selecting the correct
  592. // driver node in the class list we just built.
  593. //
  594. ZeroMemory(&DriverInfoData, sizeof(SP_DRVINFO_DATA));
  595. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  596. RegDataLength = sizeof(DriverInfoData.ProviderName);
  597. RegQueryValueEx(hKey,
  598. REGSTR_VAL_PROVIDER_NAME,
  599. NULL,
  600. &RegDataType,
  601. (PBYTE)DriverInfoData.ProviderName,
  602. &RegDataLength
  603. );
  604. SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
  605. DeviceInfoData,
  606. SPDRP_MFG,
  607. NULL,
  608. (PBYTE)DriverInfoData.MfgName,
  609. sizeof(DriverInfoData.MfgName),
  610. NULL
  611. );
  612. SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
  613. DeviceInfoData,
  614. SPDRP_DEVICEDESC,
  615. NULL,
  616. (PBYTE)DriverInfoData.Description,
  617. sizeof(DriverInfoData.Description),
  618. NULL
  619. );
  620. //
  621. // Set the DriverInfoData.Reserved field to 0 to tell setupapi to match the
  622. // specified criteria and select it if found.
  623. //
  624. DriverInfoData.DriverType = SPDIT_CLASSDRIVER;
  625. DriverInfoData.Reserved = 0;
  626. if (!SetupDiSetSelectedDriver(DeviceInfoSet,
  627. DeviceInfoData,
  628. &DriverInfoData
  629. )) {
  630. //
  631. // This means we could not find the currently installed driver for this
  632. // device.
  633. //
  634. Err = GetLastError();
  635. goto clean0;
  636. }
  637. //
  638. // At this point we have successfully selected the currently installed driver for the specified
  639. // device innformation element.
  640. //
  641. Err = ERROR_SUCCESS;
  642. clean0:
  643. if (hKey != NULL) {
  644. RegCloseKey(hKey);
  645. }
  646. return Err;
  647. }
  648. UINT
  649. pFileQueueCallback(
  650. PVOID Context,
  651. UINT Notification,
  652. UINT Param1,
  653. UINT Param2
  654. )
  655. {
  656. PFILEPATHS FilePaths = (PFILEPATHS)Param1;
  657. if ((Notification == SPFILENOTIFY_QUEUESCAN_EX) && Param1) {
  658. PNOCOPYLIST pncl = (PNOCOPYLIST)Context;
  659. BOOL bAlreadyExists = FALSE;
  660. PTSTR p;
  661. //
  662. // If there is any sort of file not found error or crypto error then
  663. // we'll treat this as a non-MS package.
  664. //
  665. if (FilePaths->Win32Error != NO_ERROR) {
  666. pncl->MicrosoftDriver = FALSE;
  667. }
  668. if (pncl->Size == 0) {
  669. pncl->Size = (lstrlen(FilePaths->Source) + 2) * sizeof(TCHAR);
  670. pncl->pListOfFiles = (PTSTR)HeapAlloc(GetProcessHeap(),
  671. HEAP_ZERO_MEMORY,
  672. pncl->Size
  673. );
  674. if (pncl->pListOfFiles) {
  675. lstrcpy(pncl->pListOfFiles, FilePaths->Source);
  676. } else {
  677. pncl->Size = 0;
  678. }
  679. } else {
  680. //
  681. // First check to see if this filename already exists in the list.
  682. //
  683. for (p = pncl->pListOfFiles; *p; p += (lstrlen(p) + 1)) {
  684. if (lstrcmpi(p, FilePaths->Source) == 0) {
  685. bAlreadyExists = TRUE;
  686. }
  687. }
  688. if (!bAlreadyExists) {
  689. PTSTR TempBuffer;
  690. ULONG ulOldSize = pncl->Size;
  691. pncl->Size += (lstrlen(FilePaths->Source) + 1) * sizeof(TCHAR);
  692. //
  693. // Lets add this file to our multi-sz string.
  694. //
  695. TempBuffer = (PTSTR)HeapReAlloc(GetProcessHeap(),
  696. HEAP_ZERO_MEMORY,
  697. pncl->pListOfFiles,
  698. pncl->Size
  699. );
  700. if (TempBuffer) {
  701. pncl->pListOfFiles = TempBuffer;
  702. lstrcpy(&(pncl->pListOfFiles[ulOldSize/sizeof(TCHAR) - 1]), FilePaths->Source);
  703. }
  704. }
  705. }
  706. }
  707. return NO_ERROR;
  708. }
  709. DWORD
  710. pGetListOfFilesForDevice(
  711. IN HDEVINFO DeviceInfoSet,
  712. IN PSP_DEVINFO_DATA DeviceInfoData,
  713. PNOCOPYLIST pncl
  714. )
  715. {
  716. DWORD Err = NO_ERROR;
  717. TCHAR InfName[MAX_PATH];
  718. HSPFILEQ FileQueueHandle = (HSPFILEQ)INVALID_HANDLE_VALUE;
  719. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  720. DWORD dwResult;
  721. BOOL bIsDriverMicrosoft = FALSE;
  722. //
  723. // Get the currently-installed driver node for this element
  724. //
  725. InfName[0] = TEXT('\0');
  726. if (pSetupGetCurrentlyInstalledDriverNode(DeviceInfoSet,
  727. DeviceInfoData,
  728. InfName
  729. ) != NO_ERROR) {
  730. Err = GetLastError();
  731. goto clean0;
  732. }
  733. //
  734. // Now queue all files to be copied by this driver node into our own file queue.
  735. //
  736. FileQueueHandle = SetupOpenFileQueue();
  737. if (FileQueueHandle == (HSPFILEQ)INVALID_HANDLE_VALUE) {
  738. Err = GetLastError();
  739. goto clean0;
  740. }
  741. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  742. if (!SetupDiGetDeviceInstallParams(DeviceInfoSet,
  743. DeviceInfoData,
  744. &DeviceInstallParams
  745. )) {
  746. Err = GetLastError();
  747. goto clean0;
  748. }
  749. DeviceInstallParams.FileQueue = FileQueueHandle;
  750. DeviceInstallParams.Flags |= DI_NOVCP;
  751. if (!SetupDiSetDeviceInstallParams(DeviceInfoSet,
  752. DeviceInfoData,
  753. &DeviceInstallParams
  754. )) {
  755. Err = GetLastError();
  756. goto clean0;
  757. }
  758. //
  759. // Tell setupapi (and class/co-installers to build up a list of driver files
  760. // for this device.
  761. //
  762. if (!SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES,
  763. DeviceInfoSet,
  764. DeviceInfoData
  765. )) {
  766. Err = GetLastError();
  767. goto clean0;
  768. }
  769. //
  770. // Scan the FileQueue adding files to the list.
  771. //
  772. if (!SetupScanFileQueue(FileQueueHandle,
  773. SPQ_SCAN_USE_CALLBACKEX,
  774. NULL,
  775. (PSP_FILE_CALLBACK)pFileQueueCallback,
  776. (PVOID)pncl,
  777. &dwResult
  778. )) {
  779. Err = GetLastError();
  780. goto clean0;
  781. }
  782. //
  783. // If we haven't encountered any errors then the MicrosoftDriver BOOL will
  784. // still be TRUE. That means that we need to verify the INF associated with
  785. // this driver package to make sure it is signed by the build lab.
  786. //
  787. if (pncl->MicrosoftDriver) {
  788. TCHAR FullInfPath[MAX_PATH];
  789. if (GetWindowsDirectory(FullInfPath, sizeof(FullInfPath)/sizeof(TCHAR))) {
  790. if (lstrlen(FullInfPath)) {
  791. //
  792. // Tack on an extra back slash if one is needed
  793. //
  794. if (FullInfPath[lstrlen(FullInfPath) - 1] != TEXT('\\')) {
  795. lstrcat(FullInfPath, TEXT("\\"));
  796. }
  797. lstrcat(FullInfPath, TEXT("INF\\"));
  798. lstrcat(FullInfPath, InfName);
  799. //
  800. // If the INF for this driver node is not signed by the Microsoft build
  801. // lab, then set the MicrosoftDriver BOOL to FALSE.
  802. //
  803. if (!IsInfSigned(FullInfPath)) {
  804. pncl->MicrosoftDriver = FALSE;
  805. }
  806. }
  807. }
  808. }
  809. clean0:
  810. if (FileQueueHandle != (HSPFILEQ)INVALID_HANDLE_VALUE) {
  811. SetupCloseFileQueue(FileQueueHandle);
  812. }
  813. DEBUGTRACE(L"pGetListOfFilesForDevice returned error 0x%X\n", Err);
  814. return Err;
  815. }
  816. BOOL
  817. IsDriverThirdParty(
  818. IN PCTSTR ServiceName
  819. )
  820. {
  821. ULONG ulLen;
  822. PTCHAR deviceList = NULL;
  823. PTCHAR p;
  824. BOOL bIsDriverMicrosoft = FALSE;
  825. HDEVINFO DeviceInfoSet;
  826. SP_DEVINFO_DATA DeviceInfoData;
  827. NOCOPYLIST ncl;
  828. ncl.Size = 0;
  829. ncl.MicrosoftDriver = TRUE;
  830. //
  831. // Get the size of the buffer needed to hold all of the device instance Ids
  832. // that have the specified service.
  833. //
  834. if (CM_Get_Device_ID_List_Size(&ulLen,
  835. ServiceName,
  836. CM_GETIDLIST_FILTER_SERVICE
  837. ) != CR_SUCCESS) {
  838. goto clean0;
  839. }
  840. deviceList = (PTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (ulLen * sizeof(TCHAR)));
  841. if (!deviceList) {
  842. goto clean0;
  843. }
  844. //
  845. // Get the multi-sz list of all of the device instance Ids that use the
  846. // specified service.
  847. //
  848. if (CM_Get_Device_ID_List(ServiceName,
  849. deviceList,
  850. ulLen,
  851. CM_GETIDLIST_FILTER_SERVICE
  852. ) != CR_SUCCESS) {
  853. goto clean0;
  854. }
  855. //
  856. // Enumerate through the multi_sz list of all of the devices that are using
  857. // the speicifed service.
  858. //
  859. for (p=deviceList; *p; p += (lstrlen(p) + 1)) {
  860. DEBUGTRACE(L"%ws\n", p);
  861. //
  862. // Create a new empty DeviceInfoSet.
  863. //
  864. DeviceInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL);
  865. if (DeviceInfoSet != INVALID_HANDLE_VALUE) {
  866. DeviceInfoData.cbSize = sizeof(DeviceInfoData);
  867. //
  868. // Add the device to the DeviceInfoSet.
  869. //
  870. if (SetupDiOpenDeviceInfo(DeviceInfoSet,
  871. p,
  872. NULL,
  873. 0,
  874. &DeviceInfoData
  875. )) {
  876. pGetListOfFilesForDevice(DeviceInfoSet,
  877. &DeviceInfoData,
  878. &ncl
  879. );
  880. }
  881. //
  882. // Destroy the DeviceInfoSet.
  883. //
  884. SetupDiDestroyDeviceInfoList(DeviceInfoSet);
  885. }
  886. }
  887. //
  888. // By this point we will have all of the files copied for all devices with a
  889. // service name that matches that passed in to this function. The NOCOPYLIST
  890. // MicrosoftDriver parameter will specify whether this is a Microsoft driver
  891. // or NOT. If it is a Microsoft Driver then we will free the lpfileList field
  892. // of this structure and return FALSE to this API, otherwise we will return TRUE
  893. // along with the size of the multi-sz file list.
  894. //
  895. if (ncl.MicrosoftDriver) {
  896. //
  897. // This is a Microsoft driver so we can free the memory allocated to hold all
  898. // of the files.
  899. //
  900. bIsDriverMicrosoft = TRUE;
  901. HeapFree(GetProcessHeap(), 0, ncl.pListOfFiles);
  902. } else {
  903. bIsDriverMicrosoft = FALSE;
  904. }
  905. clean0:
  906. if (deviceList) {
  907. HeapFree(GetProcessHeap(), 0, deviceList);
  908. }
  909. return !bIsDriverMicrosoft;
  910. }
  911. /*int
  912. __cdecl
  913. wmain(
  914. IN int argc,
  915. IN TCHAR **argv
  916. )
  917. {
  918. IsOemHalInstalled();
  919. if (argc > 0) {
  920. IsDriverThirdParty((PCTSTR)argv[1]);
  921. }
  922. return 0;
  923. }
  924. */