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.

1175 lines
38 KiB

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