Leaked source code of windows server 2003
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.

1134 lines
40 KiB

  1. //
  2. // DEVNODE.C
  3. //
  4. #include "sigverif.h"
  5. #include <initguid.h>
  6. #include <devguid.h>
  7. //
  8. // Given the full path to a driver, add it to the file list.
  9. //
  10. LPFILENODE
  11. AddDriverFileToList(
  12. LPTSTR lpDirName,
  13. LPTSTR lpFullPathName
  14. )
  15. {
  16. DWORD Err = ERROR_SUCCESS;
  17. LPFILENODE lpFileNode = NULL;
  18. TCHAR szDirName[MAX_PATH];
  19. TCHAR szFileName[MAX_PATH];
  20. LPTSTR lpFilePart = NULL;
  21. *szDirName = 0;
  22. *szFileName = 0;
  23. //
  24. // If no directory is passed in, try to get the full path
  25. //
  26. if (!lpDirName || !*lpDirName) {
  27. if (GetFullPathName(lpFullPathName, cA(szDirName), szDirName, &lpFilePart)) {
  28. if (lpFilePart && *lpFilePart) {
  29. if (SUCCEEDED(StringCchCopy(szFileName, cA(szFileName), lpFilePart))) {
  30. *lpFilePart = 0;
  31. if (lstrlen(szDirName) > 3) {
  32. *(lpFilePart - 1) = 0;
  33. }
  34. } else {
  35. *szFileName = 0;
  36. }
  37. }
  38. } else {
  39. *szDirName = 0;
  40. }
  41. } else {
  42. //
  43. // Use the directory and filename that was passed in to us
  44. // Expand out lpDirName in case there are any ".." entries
  45. //
  46. if (!GetFullPathName(lpDirName, cA(szDirName), szDirName, NULL)) {
  47. //
  48. // If we can't get the full path, then just use the one
  49. // that was passed in. This could happen if the directory
  50. // is missing for instance.
  51. //
  52. if (FAILED(StringCchCopy(szDirName, cA(szDirName), lpDirName))) {
  53. //
  54. // If we can't fit the directory name into our buffer then
  55. // clear szDirName so this node won't be added to the list.
  56. //
  57. *szDirName = 0;
  58. }
  59. }
  60. if (FAILED(StringCchCopy(szFileName, cA(szFileName), lpFullPathName))) {
  61. //
  62. // If we can't fit the file name into our buffer then
  63. // clear szFileName so this node won't be added to the list.
  64. //
  65. *szFileName = 0;
  66. }
  67. }
  68. if (*szDirName && *szFileName && !IsFileAlreadyInList(szDirName, szFileName)) {
  69. //
  70. // Create a filenode, based on the directory and filename
  71. //
  72. lpFileNode = CreateFileNode(szDirName, szFileName);
  73. if (lpFileNode) {
  74. InsertFileNodeIntoList(lpFileNode);
  75. //
  76. // Increment the total number of files we've found that meet the
  77. // search criteria.
  78. //
  79. g_App.dwFiles++;
  80. } else {
  81. Err = GetLastError();
  82. }
  83. }
  84. SetLastError(Err);
  85. return lpFileNode;
  86. }
  87. BOOL
  88. GetFullPathFromImagePath(
  89. LPCTSTR ImagePath,
  90. LPTSTR FullPath,
  91. UINT FullPathLength
  92. )
  93. {
  94. TCHAR OriginalCurrentDirectory[MAX_PATH];
  95. LPTSTR pRelativeString;
  96. LPTSTR lpFilePart;
  97. if (!ImagePath || (ImagePath[0] == TEXT('\0'))) {
  98. return FALSE;
  99. }
  100. //
  101. // First check if the ImagePath happens to be a valid full path.
  102. //
  103. if (GetFileAttributes(ImagePath) != 0xFFFFFFFF) {
  104. GetFullPathName(ImagePath, FullPathLength, FullPath, &lpFilePart);
  105. return TRUE;
  106. }
  107. pRelativeString = (LPTSTR)ImagePath;
  108. //
  109. // If the ImagePath starts with "\SystemRoot" or "%SystemRoot%" then
  110. // remove those values.
  111. //
  112. if (StrCmpNI(ImagePath, TEXT("\\SystemRoot\\"), lstrlen(TEXT("\\SystemRoot\\"))) == 0) {
  113. pRelativeString += lstrlen(TEXT("\\SystemRoot\\"));
  114. } else if (StrCmpNI(ImagePath, TEXT("%SystemRoot%\\"), lstrlen(TEXT("%SystemRoot%\\"))) == 0) {
  115. pRelativeString += lstrlen(TEXT("%SystemRoot%\\"));
  116. }
  117. //
  118. // At this point pRelativeString should point to the image path relative to
  119. // the windows directory.
  120. //
  121. if (!GetSystemWindowsDirectory(FullPath, FullPathLength)) {
  122. return FALSE;
  123. }
  124. if (!GetCurrentDirectory(cA(OriginalCurrentDirectory), OriginalCurrentDirectory)) {
  125. OriginalCurrentDirectory[0] = TEXT('\0');
  126. }
  127. if (!SetCurrentDirectory(FullPath)) {
  128. return FALSE;
  129. }
  130. GetFullPathName(pRelativeString, FullPathLength, FullPath, &lpFilePart);
  131. if (OriginalCurrentDirectory[0] != TEXT('\0')) {
  132. SetCurrentDirectory(OriginalCurrentDirectory);
  133. }
  134. return TRUE;
  135. }
  136. DWORD
  137. CreateFromService(
  138. SC_HANDLE hscManager,
  139. PCTSTR ServiceName
  140. )
  141. {
  142. DWORD Err = ERROR_SUCCESS;
  143. SC_HANDLE hscService = NULL;
  144. DWORD BytesRequired, Size;
  145. TCHAR FullPath[MAX_PATH];
  146. LPQUERY_SERVICE_CONFIG pqsc;
  147. PBYTE BufferPtr = NULL;
  148. if (hscManager == NULL) {
  149. //
  150. // This should never happen.
  151. //
  152. goto clean0;
  153. }
  154. if (!ServiceName ||
  155. (ServiceName[0] == TEXT('\0'))) {
  156. //
  157. // This should also never happen.
  158. //
  159. goto clean0;
  160. }
  161. hscService = OpenService(hscManager, ServiceName, GENERIC_READ);
  162. if (NULL == hscService) {
  163. //
  164. // This service does not exist. We won't return an error in this case
  165. // since if the service doesn't exist then the driver won't get
  166. // loaded.
  167. //
  168. goto clean0;
  169. }
  170. //
  171. // First, probe for buffer size
  172. //
  173. if (!QueryServiceConfig(hscService, NULL, 0, &BytesRequired) &&
  174. ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
  175. BufferPtr = MALLOC(BytesRequired);
  176. if (!BufferPtr) {
  177. Err = ERROR_NOT_ENOUGH_MEMORY;
  178. goto clean0;
  179. }
  180. pqsc = (LPQUERY_SERVICE_CONFIG)(PBYTE)BufferPtr;
  181. if (QueryServiceConfig(hscService, pqsc, BytesRequired, &Size) &&
  182. pqsc->lpBinaryPathName &&
  183. (TEXT('\0') != pqsc->lpBinaryPathName[0])) {
  184. //
  185. // Make sure we have a valid full path.
  186. //
  187. if (GetFullPathFromImagePath(pqsc->lpBinaryPathName,
  188. FullPath,
  189. cA(FullPath))) {
  190. AddDriverFileToList(NULL, FullPath);
  191. }
  192. }
  193. FREE(BufferPtr);
  194. }
  195. clean0:
  196. if (hscService) {
  197. CloseServiceHandle(hscService);
  198. hscService = NULL;
  199. }
  200. if (BufferPtr) {
  201. FREE(BufferPtr);
  202. }
  203. return Err;
  204. }
  205. UINT
  206. ScanQueueCallback(
  207. PVOID Context,
  208. UINT Notification,
  209. UINT_PTR Param1,
  210. UINT_PTR Param2
  211. )
  212. {
  213. LPFILENODE lpFileNode;
  214. TCHAR szBuffer[MAX_PATH];
  215. LPTSTR lpFilePart;
  216. ULONG BufCbSize;
  217. HRESULT hr;
  218. UNREFERENCED_PARAMETER(Param2);
  219. if ((Notification == SPFILENOTIFY_QUEUESCAN_SIGNERINFO) &&
  220. Param1) {
  221. //
  222. // Special case for printers:
  223. // After setupapi copies files from the file queue into their destination
  224. // location, the printer class installer moves some of these files into
  225. // other 'special' locations. This can lead to the callback Win32Error
  226. // returning ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND since the file
  227. // is not present in the location where setupapi put it. So, we will
  228. // catch this case for printers and not add the file to our list of
  229. // files to scan. These 'special' printer files will get added later
  230. // when we call the spooler APIs.
  231. // Also note that we can't just skip getting the list of files for printers
  232. // altogether since the printer class installer only moves some of the
  233. // files that setupapi copies and not all of them.
  234. //
  235. if (Context &&
  236. (IsEqualGUID((LPGUID)Context, &GUID_DEVCLASS_PRINTER)) &&
  237. ((((PFILEPATHS_SIGNERINFO)Param1)->Win32Error == ERROR_FILE_NOT_FOUND) ||
  238. (((PFILEPATHS_SIGNERINFO)Param1)->Win32Error == ERROR_PATH_NOT_FOUND))) {
  239. //
  240. // Assume this was a file moved by the printer class installer. Don't
  241. // add it to the list of files to be scanned at this time.
  242. //
  243. return NO_ERROR;
  244. }
  245. lpFileNode = AddDriverFileToList(NULL,
  246. (LPTSTR)((PFILEPATHS_SIGNERINFO)Param1)->Target);
  247. //
  248. // Fill in some information into the FILENODE structure since we already
  249. // scanned the file.
  250. //
  251. if (lpFileNode) {
  252. lpFileNode->bScanned = TRUE;
  253. if ((((PFILEPATHS_SIGNERINFO)Param1)->Win32Error == NO_ERROR) ||
  254. ((!g_App.bNoAuthenticode) &&
  255. ((((PFILEPATHS_SIGNERINFO)Param1)->Win32Error == ERROR_AUTHENTICODE_TRUSTED_PUBLISHER) ||
  256. (((PFILEPATHS_SIGNERINFO)Param1)->Win32Error == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)))) {
  257. lpFileNode->bSigned = TRUE;
  258. } else {
  259. lpFileNode->bSigned = FALSE;
  260. }
  261. if (lpFileNode->bSigned) {
  262. if (((PFILEPATHS_SIGNERINFO)Param1)->CatalogFile) {
  263. GetFullPathName(((PFILEPATHS_SIGNERINFO)Param1)->CatalogFile, cA(szBuffer), szBuffer, &lpFilePart);
  264. BufCbSize = (lstrlen(lpFilePart) + 1) * sizeof(TCHAR);
  265. lpFileNode->lpCatalog = MALLOC(BufCbSize);
  266. if (lpFileNode->lpCatalog) {
  267. hr = StringCbCopy(lpFileNode->lpCatalog, BufCbSize, lpFilePart);
  268. if (FAILED(hr) && (hr != STRSAFE_E_INSUFFICIENT_BUFFER)) {
  269. //
  270. // If we fail for some reason other than insufficient
  271. // buffer, then free the string and set the pointer
  272. // to NULL, since the string is undefined.
  273. //
  274. FREE(lpFileNode->lpCatalog);
  275. lpFileNode->lpCatalog = NULL;
  276. }
  277. }
  278. }
  279. if (((PFILEPATHS_SIGNERINFO)Param1)->DigitalSigner) {
  280. BufCbSize = (lstrlen(((PFILEPATHS_SIGNERINFO)Param1)->DigitalSigner) + 1) * sizeof(TCHAR);
  281. lpFileNode->lpSignedBy = MALLOC(BufCbSize);
  282. if (lpFileNode->lpSignedBy) {
  283. hr = StringCbCopy(lpFileNode->lpSignedBy, BufCbSize, ((PFILEPATHS_SIGNERINFO)Param1)->DigitalSigner);
  284. if (FAILED(hr) && (hr != STRSAFE_E_INSUFFICIENT_BUFFER)) {
  285. //
  286. // If we fail for some reason other than insufficient
  287. // buffer, then free the string and set the pointer
  288. // to NULL, since the string is undefined.
  289. //
  290. FREE(lpFileNode->lpSignedBy);
  291. lpFileNode->lpSignedBy = NULL;
  292. }
  293. }
  294. }
  295. if (((PFILEPATHS_SIGNERINFO)Param1)->Version) {
  296. BufCbSize = (lstrlen(((PFILEPATHS_SIGNERINFO)Param1)->Version) + 1) * sizeof(TCHAR);
  297. lpFileNode->lpVersion = MALLOC(BufCbSize);
  298. if (lpFileNode->lpVersion) {
  299. hr = StringCbCopy(lpFileNode->lpVersion, BufCbSize, ((PFILEPATHS_SIGNERINFO)Param1)->Version);
  300. if (FAILED(hr) && (hr != STRSAFE_E_INSUFFICIENT_BUFFER)) {
  301. //
  302. // If we fail for some reason other than insufficient
  303. // buffer, then free the string and set the pointer
  304. // to NULL, since the string is undefined.
  305. //
  306. FREE(lpFileNode->lpVersion);
  307. lpFileNode->lpVersion = NULL;
  308. }
  309. }
  310. }
  311. } else {
  312. //
  313. // Get the icon (if the file isn't signed) so we can display it in the listview faster.
  314. //
  315. MyGetFileInfo(lpFileNode);
  316. }
  317. }
  318. }
  319. return NO_ERROR;
  320. }
  321. void
  322. AddClassInstallerToList(
  323. LPCTSTR ClassInstallerString
  324. )
  325. {
  326. DWORD BufferSize;
  327. TCHAR ModulePath[MAX_PATH];
  328. TCHAR TempBuffer[MAX_PATH];
  329. PTSTR StringPtr;
  330. if ((ClassInstallerString == NULL) ||
  331. (ClassInstallerString[0] == TEXT('\0'))) {
  332. return;
  333. }
  334. if (FAILED(StringCchCopy(TempBuffer, cA(TempBuffer), ClassInstallerString))) {
  335. return;
  336. }
  337. //
  338. // Class/Co-installers are always based under the %windir%\system32
  339. // directory.
  340. //
  341. if (GetSystemDirectory(ModulePath, cA(ModulePath)) == 0) {
  342. return;
  343. }
  344. //
  345. // Find the beginning of the entry point name, if present.
  346. //
  347. BufferSize = (lstrlen(TempBuffer) + 1) * sizeof(TCHAR);
  348. for(StringPtr = TempBuffer + ((BufferSize / sizeof(TCHAR)) - 2);
  349. StringPtr >= TempBuffer;
  350. StringPtr--) {
  351. if(*StringPtr == TEXT(',')) {
  352. *(StringPtr++) = TEXT('\0');
  353. break;
  354. }
  355. //
  356. // If we hit a double-quote mark, then set the character pointer
  357. // to the beginning of the string so we'll terminate the search.
  358. //
  359. if(*StringPtr == TEXT('\"')) {
  360. StringPtr = TempBuffer;
  361. }
  362. }
  363. if (pSetupConcatenatePaths(ModulePath, TempBuffer, MAX_PATH, NULL)) {
  364. AddDriverFileToList(NULL, ModulePath);
  365. }
  366. }
  367. DWORD
  368. BuildDriverFileList(
  369. void
  370. )
  371. {
  372. DWORD Err = ERROR_SUCCESS;
  373. HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
  374. SP_DEVINFO_DATA DeviceInfoData;
  375. SP_DRVINFO_DATA DriverInfoData;
  376. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  377. DWORD DeviceMemberIndex;
  378. HSPFILEQ hFileQueue;
  379. DWORD ScanResult;
  380. DWORD Status, Problem;
  381. SC_HANDLE hscManager = NULL;
  382. TCHAR Buffer[MAX_PATH];
  383. ULONG BufferSize;
  384. DWORD dwType;
  385. HKEY hKey = INVALID_HANDLE_VALUE, hKeyClassCoInstallers = INVALID_HANDLE_VALUE;
  386. PTSTR pItemList = NULL, pSingleItem;
  387. LPGUID ClassGuidList = NULL;
  388. DWORD i, NumberClassGuids, CurrentClassGuid;
  389. TCHAR GuidString[MAX_GUID_STRING_LEN];
  390. //
  391. // Build up a list of all the devices in the system.
  392. //
  393. hDeviceInfo = SetupDiGetClassDevs(NULL,
  394. NULL,
  395. NULL,
  396. DIGCF_ALLCLASSES
  397. );
  398. if (hDeviceInfo == INVALID_HANDLE_VALUE) {
  399. Err = GetLastError();
  400. goto clean0;
  401. }
  402. DeviceInfoData.cbSize = sizeof(DeviceInfoData);
  403. DeviceMemberIndex = 0;
  404. //
  405. // Enumerate through the list of devices and get a list of all
  406. // the files they copy, if they are signed or not, and which catalog
  407. // signed them.
  408. //
  409. while (SetupDiEnumDeviceInfo(hDeviceInfo,
  410. DeviceMemberIndex++,
  411. &DeviceInfoData
  412. ) &&
  413. !g_App.bStopScan) {
  414. //
  415. // We will only build up a driver list for swenum phantoms. All other
  416. // phantoms will be skipped.
  417. //
  418. if (CM_Get_DevNode_Status(&Status,
  419. &Problem,
  420. DeviceInfoData.DevInst,
  421. 0) == CR_NO_SUCH_DEVINST) {
  422. //
  423. // This device is a phantom, if it is not a swenum device, then
  424. // skip it.
  425. //
  426. if (!SetupDiGetDeviceRegistryProperty(hDeviceInfo,
  427. &DeviceInfoData,
  428. SPDRP_ENUMERATOR_NAME,
  429. NULL,
  430. (PBYTE)Buffer,
  431. sizeof(Buffer),
  432. NULL) ||
  433. (_wcsicmp(Buffer, TEXT("SW")) != 0)) {
  434. //
  435. // Either we couldn't get the enumerator name, or it is not
  436. // SW.
  437. //
  438. continue;
  439. }
  440. }
  441. DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
  442. //
  443. // Before we call SetupDiBuildDriverInfoList to build up a list of drivers
  444. // for this device we first need to set the DI_FLAGSEX_INSTALLEDDRIVER flag
  445. // (which tells the API to only include the currently installed driver in
  446. // the list) and the DI_FLAGSEX_ALLOWEXCLUDEDRVS (allow ExcludeFromSelect
  447. // devices in the list).
  448. //
  449. if (SetupDiGetDeviceInstallParams(hDeviceInfo,
  450. &DeviceInfoData,
  451. &DeviceInstallParams
  452. )) {
  453. DeviceInstallParams.FlagsEx = (DI_FLAGSEX_INSTALLEDDRIVER |
  454. DI_FLAGSEX_ALLOWEXCLUDEDDRVS);
  455. if (SetupDiSetDeviceInstallParams(hDeviceInfo,
  456. &DeviceInfoData,
  457. &DeviceInstallParams
  458. ) &&
  459. SetupDiBuildDriverInfoList(hDeviceInfo,
  460. &DeviceInfoData,
  461. SPDIT_CLASSDRIVER
  462. )) {
  463. //
  464. // Now we will get the one driver node that is in the list that
  465. // was just built and make it the selected driver node.
  466. //
  467. DriverInfoData.cbSize = sizeof(DriverInfoData);
  468. if (SetupDiEnumDriverInfo(hDeviceInfo,
  469. &DeviceInfoData,
  470. SPDIT_CLASSDRIVER,
  471. 0,
  472. &DriverInfoData
  473. ) &&
  474. SetupDiSetSelectedDriver(hDeviceInfo,
  475. &DeviceInfoData,
  476. &DriverInfoData
  477. )) {
  478. hFileQueue = SetupOpenFileQueue();
  479. if (hFileQueue != INVALID_HANDLE_VALUE) {
  480. //
  481. // Set the FileQueue parameter to the file queue we just
  482. // created and set the DI_NOVCP flag.
  483. //
  484. // The call SetupDiCallClassInstaller with DIF_INSTALLDEVICEFILES
  485. // to build up a queue of all the files that are copied for
  486. // this driver node.
  487. //
  488. DeviceInstallParams.FileQueue = hFileQueue;
  489. DeviceInstallParams.Flags |= DI_NOVCP;
  490. if (SetupDiSetDeviceInstallParams(hDeviceInfo,
  491. &DeviceInfoData,
  492. &DeviceInstallParams
  493. ) &&
  494. SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES,
  495. hDeviceInfo,
  496. &DeviceInfoData
  497. )) {
  498. //
  499. // Scan the file queue and have it call our callback
  500. // function for each file in the queue.
  501. //
  502. SetupScanFileQueue(hFileQueue,
  503. SPQ_SCAN_USE_CALLBACK_SIGNERINFO,
  504. NULL,
  505. ScanQueueCallback,
  506. (PVOID)&(DeviceInfoData.ClassGuid),
  507. &ScanResult
  508. );
  509. //
  510. // Dereference the file queue so we can close it.
  511. //
  512. DeviceInstallParams.FileQueue = NULL;
  513. DeviceInstallParams.Flags &= ~DI_NOVCP;
  514. SetupDiSetDeviceInstallParams(hDeviceInfo,
  515. &DeviceInfoData,
  516. &DeviceInstallParams
  517. );
  518. }
  519. SetupCloseFileQueue(hFileQueue);
  520. }
  521. }
  522. SetupDiDestroyDriverInfoList(hDeviceInfo,
  523. &DeviceInfoData,
  524. SPDIT_CLASSDRIVER
  525. );
  526. }
  527. }
  528. }
  529. //
  530. // Enumerate through the list of devices and add any function, device
  531. // upper/lower filters, and class upper/lower filter drivers to the list
  532. // that aren't already in the list.
  533. // We are doing this after we get all the files copied by the INF, because
  534. // these files can only be validated globally, where the INF copied files
  535. // can be validated using the catalog associated with their package.
  536. //
  537. hscManager = OpenSCManager(NULL, NULL, GENERIC_READ);
  538. if (hscManager) {
  539. DeviceInfoData.cbSize = sizeof(DeviceInfoData);
  540. DeviceMemberIndex = 0;
  541. while (SetupDiEnumDeviceInfo(hDeviceInfo,
  542. DeviceMemberIndex++,
  543. &DeviceInfoData
  544. ) &&
  545. !g_App.bStopScan) {
  546. //
  547. // Only look at SWENUM phantoms
  548. //
  549. if (CM_Get_DevNode_Status(&Status,
  550. &Problem,
  551. DeviceInfoData.DevInst,
  552. 0) == CR_NO_SUCH_DEVINST) {
  553. //
  554. // This device is a phantom, if it is not a swenum device, then
  555. // skip it.
  556. //
  557. if (!SetupDiGetDeviceRegistryProperty(hDeviceInfo,
  558. &DeviceInfoData,
  559. SPDRP_ENUMERATOR_NAME,
  560. NULL,
  561. (PBYTE)Buffer,
  562. sizeof(Buffer),
  563. NULL) ||
  564. (_wcsicmp(Buffer, TEXT("SW")) != 0)) {
  565. //
  566. // Either we couldn't get the enumerator name, or it is not
  567. // SW.
  568. //
  569. continue;
  570. }
  571. }
  572. if (g_App.bStopScan) {
  573. continue;
  574. }
  575. //
  576. // Function driver.
  577. //
  578. if (SetupDiGetDeviceRegistryProperty(hDeviceInfo,
  579. &DeviceInfoData,
  580. SPDRP_SERVICE,
  581. NULL,
  582. (PBYTE)Buffer,
  583. sizeof(Buffer),
  584. NULL)) {
  585. CreateFromService(hscManager, Buffer);
  586. }
  587. if (g_App.bStopScan) {
  588. continue;
  589. }
  590. //
  591. // Upper and Lower device filters
  592. //
  593. for (i=0; i<2; i++) {
  594. BufferSize = 0;
  595. SetupDiGetDeviceRegistryProperty(hDeviceInfo,
  596. &DeviceInfoData,
  597. i ? SPDRP_LOWERFILTERS : SPDRP_UPPERFILTERS,
  598. NULL,
  599. NULL,
  600. BufferSize,
  601. &BufferSize);
  602. if (BufferSize > 0) {
  603. pItemList = MALLOC(BufferSize + (2 * sizeof(TCHAR)));
  604. if (!pItemList) {
  605. Err = ERROR_NOT_ENOUGH_MEMORY;
  606. goto clean0;
  607. }
  608. if (SetupDiGetDeviceRegistryProperty(hDeviceInfo,
  609. &DeviceInfoData,
  610. i ? SPDRP_LOWERFILTERS : SPDRP_UPPERFILTERS,
  611. NULL,
  612. (PBYTE)pItemList,
  613. BufferSize,
  614. &BufferSize)) {
  615. for (pSingleItem=pItemList;
  616. *pSingleItem;
  617. pSingleItem += (lstrlen(pSingleItem) + 1)) {
  618. CreateFromService(hscManager, pSingleItem);
  619. }
  620. }
  621. FREE(pItemList);
  622. }
  623. }
  624. if (g_App.bStopScan) {
  625. continue;
  626. }
  627. //
  628. // Device co-installers.
  629. //
  630. hKey = SetupDiOpenDevRegKey(hDeviceInfo,
  631. &DeviceInfoData,
  632. DICS_FLAG_GLOBAL,
  633. 0,
  634. DIREG_DRV,
  635. KEY_READ);
  636. if (hKey != INVALID_HANDLE_VALUE) {
  637. BufferSize = 0;
  638. RegQueryValueEx(hKey,
  639. REGSTR_VAL_COINSTALLERS_32,
  640. NULL,
  641. &dwType,
  642. NULL,
  643. &BufferSize);
  644. if (BufferSize > 0) {
  645. pItemList = MALLOC(BufferSize + (2 * sizeof(TCHAR)));
  646. if (!pItemList) {
  647. Err = ERROR_NOT_ENOUGH_MEMORY;
  648. goto clean0;
  649. }
  650. dwType = REG_MULTI_SZ;
  651. if (RegQueryValueEx(hKey,
  652. REGSTR_VAL_COINSTALLERS_32,
  653. NULL,
  654. &dwType,
  655. (PBYTE)pItemList,
  656. &BufferSize) == ERROR_SUCCESS) {
  657. for (pSingleItem=pItemList;
  658. *pSingleItem;
  659. pSingleItem += (lstrlen(pSingleItem) + 1)) {
  660. AddClassInstallerToList(pSingleItem);
  661. }
  662. }
  663. FREE(pItemList);
  664. }
  665. RegCloseKey(hKey);
  666. hKey = INVALID_HANDLE_VALUE;
  667. }
  668. }
  669. //
  670. // Enumerate through the classes so we can get the class upper and
  671. // lower filters and the class installers.
  672. //
  673. NumberClassGuids = 0;
  674. SetupDiBuildClassInfoList(0, NULL, 0, &NumberClassGuids);
  675. if (NumberClassGuids > 0) {
  676. ClassGuidList = MALLOC(NumberClassGuids * sizeof(GUID));
  677. if (!ClassGuidList) {
  678. Err = ERROR_NOT_ENOUGH_MEMORY;
  679. goto clean0;
  680. }
  681. if (SetupDiBuildClassInfoList(0, ClassGuidList, NumberClassGuids, &NumberClassGuids)) {
  682. //
  683. // Open the class co-installer key since we will go through that
  684. // list while we have the class guids handy.
  685. //
  686. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  687. REGSTR_PATH_CODEVICEINSTALLERS,
  688. 0,
  689. KEY_READ,
  690. &hKeyClassCoInstallers) != ERROR_SUCCESS) {
  691. hKeyClassCoInstallers = INVALID_HANDLE_VALUE;
  692. }
  693. for (CurrentClassGuid=0; CurrentClassGuid<NumberClassGuids; CurrentClassGuid++) {
  694. //
  695. // Open the class key.
  696. //
  697. hKey = SetupDiOpenClassRegKey(&(ClassGuidList[CurrentClassGuid]),
  698. KEY_READ);
  699. if (hKey != INVALID_HANDLE_VALUE) {
  700. //
  701. // Upper and Lower class filters
  702. //
  703. for (i=0; i<2; i++) {
  704. BufferSize = 0;
  705. RegQueryValueEx(hKey,
  706. i ? REGSTR_VAL_LOWERFILTERS : REGSTR_VAL_UPPERFILTERS,
  707. NULL,
  708. &dwType,
  709. NULL,
  710. &BufferSize);
  711. if (BufferSize > 0) {
  712. pItemList = MALLOC(BufferSize + (2 * sizeof(TCHAR)));
  713. if (!pItemList) {
  714. Err = ERROR_NOT_ENOUGH_MEMORY;
  715. goto clean0;
  716. }
  717. dwType = REG_MULTI_SZ;
  718. if (RegQueryValueEx(hKey,
  719. i ? REGSTR_VAL_LOWERFILTERS : REGSTR_VAL_UPPERFILTERS,
  720. NULL,
  721. &dwType,
  722. (PBYTE)pItemList,
  723. &BufferSize) == ERROR_SUCCESS) {
  724. for (pSingleItem=pItemList;
  725. *pSingleItem;
  726. pSingleItem += (lstrlen(pSingleItem) + 1)) {
  727. CreateFromService(hscManager, pSingleItem);
  728. }
  729. }
  730. FREE(pItemList);
  731. }
  732. }
  733. //
  734. // Class installer
  735. //
  736. dwType = REG_SZ;
  737. BufferSize = sizeof(Buffer);
  738. if (RegQueryValueEx(hKey,
  739. REGSTR_VAL_INSTALLER_32,
  740. NULL,
  741. &dwType,
  742. (PBYTE)Buffer,
  743. &BufferSize) == ERROR_SUCCESS) {
  744. AddClassInstallerToList(Buffer);
  745. }
  746. RegCloseKey(hKey);
  747. hKey = INVALID_HANDLE_VALUE;
  748. }
  749. //
  750. // Class co-installers.
  751. //
  752. if (hKeyClassCoInstallers != INVALID_HANDLE_VALUE) {
  753. if (pSetupStringFromGuid(&(ClassGuidList[CurrentClassGuid]),
  754. GuidString,
  755. cA(GuidString)) == ERROR_SUCCESS) {
  756. BufferSize = 0;
  757. RegQueryValueEx(hKeyClassCoInstallers,
  758. GuidString,
  759. NULL,
  760. &dwType,
  761. NULL,
  762. &BufferSize);
  763. if (BufferSize > 0) {
  764. pItemList = MALLOC(BufferSize + (2 * sizeof(TCHAR)));
  765. if (!pItemList) {
  766. Err = ERROR_NOT_ENOUGH_MEMORY;
  767. goto clean0;
  768. }
  769. dwType = REG_MULTI_SZ;
  770. if (RegQueryValueEx(hKeyClassCoInstallers,
  771. GuidString,
  772. NULL,
  773. &dwType,
  774. (PBYTE)pItemList,
  775. &BufferSize) == ERROR_SUCCESS) {
  776. for (pSingleItem=pItemList;
  777. *pSingleItem;
  778. pSingleItem += (lstrlen(pSingleItem) + 1)) {
  779. AddClassInstallerToList(pSingleItem);
  780. }
  781. }
  782. FREE(pItemList);
  783. }
  784. }
  785. }
  786. }
  787. }
  788. if (hKeyClassCoInstallers != INVALID_HANDLE_VALUE) {
  789. RegCloseKey(hKeyClassCoInstallers);
  790. hKeyClassCoInstallers = INVALID_HANDLE_VALUE;
  791. }
  792. FREE(ClassGuidList);
  793. }
  794. CloseServiceHandle(hscManager);
  795. }
  796. clean0:
  797. if (hscManager) {
  798. CloseServiceHandle(hscManager);
  799. }
  800. if (pItemList) {
  801. FREE(pItemList);
  802. }
  803. if (ClassGuidList) {
  804. FREE(ClassGuidList);
  805. }
  806. if (hDeviceInfo != INVALID_HANDLE_VALUE) {
  807. SetupDiDestroyDeviceInfoList(hDeviceInfo);
  808. }
  809. if (hKeyClassCoInstallers != INVALID_HANDLE_VALUE) {
  810. RegCloseKey(hKeyClassCoInstallers);
  811. hKeyClassCoInstallers = INVALID_HANDLE_VALUE;
  812. }
  813. if (hKey != INVALID_HANDLE_VALUE) {
  814. RegCloseKey(hKey);
  815. hKey = INVALID_HANDLE_VALUE;
  816. }
  817. return Err;
  818. }
  819. DWORD
  820. BuildPrinterFileList(
  821. void
  822. )
  823. {
  824. DWORD Err = ERROR_SUCCESS;
  825. BOOL bRet;
  826. DWORD dwBytesNeeded = 0;
  827. DWORD dwDrivers = 0;
  828. LPBYTE lpBuffer = NULL, lpTemp = NULL;
  829. LPTSTR lpFileName;
  830. DRIVER_INFO_3 DriverInfo;
  831. PDRIVER_INFO_3 lpDriverInfo;
  832. TCHAR szBuffer[MAX_PATH];
  833. LPFILENODE lpFileNode = NULL;
  834. ZeroMemory(&DriverInfo, sizeof(DRIVER_INFO_3));
  835. bRet = EnumPrinterDrivers( NULL,
  836. SIGVERIF_PRINTER_ENV,
  837. 3,
  838. (LPBYTE) &DriverInfo,
  839. sizeof(DRIVER_INFO_3),
  840. &dwBytesNeeded,
  841. &dwDrivers);
  842. if (!bRet && dwBytesNeeded > 0) {
  843. lpBuffer = MALLOC(dwBytesNeeded);
  844. //
  845. // If we can't get any memory then just bail out of this function
  846. //
  847. if (!lpBuffer) {
  848. Err = ERROR_NOT_ENOUGH_MEMORY;
  849. goto clean0;
  850. }
  851. bRet = EnumPrinterDrivers( NULL,
  852. SIGVERIF_PRINTER_ENV,
  853. 3,
  854. (LPBYTE) lpBuffer,
  855. dwBytesNeeded,
  856. &dwBytesNeeded,
  857. &dwDrivers);
  858. }
  859. if (dwDrivers > 0) {
  860. //
  861. // By default, go into the System directory, since Win9x doesn't give full paths to drivers.
  862. //
  863. GetSystemDirectory(szBuffer, cA(szBuffer));
  864. SetCurrentDirectory(szBuffer);
  865. for (lpTemp = lpBuffer; dwDrivers > 0; dwDrivers--) {
  866. lpDriverInfo = (PDRIVER_INFO_3) lpTemp;
  867. if (lpDriverInfo->pName) {
  868. if (lpDriverInfo->pDriverPath && *lpDriverInfo->pDriverPath) {
  869. lpFileNode = AddDriverFileToList(NULL, lpDriverInfo->pDriverPath);
  870. if (lpFileNode) {
  871. lpFileNode->bValidateAgainstAnyOs = TRUE;
  872. }
  873. }
  874. if (lpDriverInfo->pDataFile && *lpDriverInfo->pDataFile) {
  875. lpFileNode = AddDriverFileToList(NULL, lpDriverInfo->pDataFile);
  876. if (lpFileNode) {
  877. lpFileNode->bValidateAgainstAnyOs = TRUE;
  878. }
  879. }
  880. if (lpDriverInfo->pConfigFile && *lpDriverInfo->pConfigFile) {
  881. lpFileNode = AddDriverFileToList(NULL, lpDriverInfo->pConfigFile);
  882. if (lpFileNode) {
  883. lpFileNode->bValidateAgainstAnyOs = TRUE;
  884. }
  885. }
  886. if (lpDriverInfo->pHelpFile && *lpDriverInfo->pHelpFile) {
  887. lpFileNode = AddDriverFileToList(NULL, lpDriverInfo->pHelpFile);
  888. if (lpFileNode) {
  889. lpFileNode->bValidateAgainstAnyOs = TRUE;
  890. }
  891. }
  892. lpFileName = lpDriverInfo->pDependentFiles;
  893. while (lpFileName && *lpFileName) {
  894. lpFileNode = AddDriverFileToList(NULL, lpFileName);
  895. if (lpFileNode) {
  896. lpFileNode->bValidateAgainstAnyOs = TRUE;
  897. }
  898. for (;*lpFileName;lpFileName++);
  899. lpFileName++;
  900. }
  901. }
  902. lpTemp += sizeof(DRIVER_INFO_3);
  903. }
  904. }
  905. clean0:
  906. if (lpBuffer) {
  907. FREE(lpBuffer);
  908. }
  909. return Err;
  910. }
  911. DWORD
  912. BuildCoreFileList(
  913. void
  914. )
  915. {
  916. DWORD Err = ERROR_SUCCESS;
  917. PROTECTED_FILE_DATA pfd;
  918. pfd.FileNumber = 0;
  919. while (SfcGetNextProtectedFile(NULL, &pfd)) {
  920. if (g_App.bStopScan) {
  921. Err = ERROR_CANCELLED;
  922. break;
  923. }
  924. AddDriverFileToList(NULL, pfd.FileName);
  925. }
  926. //
  927. // See if SfcGetNextProtectedFile failed from some reason other than
  928. // ERROR_NO_MORE_FILES.
  929. //
  930. if ((Err == ERROR_SUCCESS) &&
  931. (GetLastError() != ERROR_NO_MORE_FILES)) {
  932. //
  933. // SfcGetNextProtectedFile failed before we reached then end of the
  934. // list of protected file list. This means we won't scan all the
  935. // protected files, so we should fail up front!
  936. //
  937. Err = GetLastError();
  938. }
  939. return Err;
  940. }