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.

1060 lines
30 KiB

  1. /*++
  2. Copyright (C) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. CDriver.cpp
  5. Abstract:
  6. This module implements CDriver and CService classes
  7. Author:
  8. William Hsieh (williamh) created
  9. Revision History:
  10. --*/
  11. #include "devmgr.h"
  12. #include "cdriver.h"
  13. const TCHAR* tszStringFileInfo = TEXT("StringFileInfo\\%04X%04X\\");
  14. const TCHAR* tszFileVersion = TEXT("FileVersion");
  15. const TCHAR* tszLegalCopyright = TEXT("LegalCopyright");
  16. const TCHAR* tszCompanyName = TEXT("CompanyName");
  17. const TCHAR* tszTranslation = TEXT("VarFileInfo\\Translation");
  18. const TCHAR* tszStringFileInfoDefault = TEXT("StringFileInfo\\040904B0\\");
  19. BOOL
  20. CDriver::Create(
  21. CDevice* pDevice,
  22. PSP_DRVINFO_DATA pDrvInfoData
  23. )
  24. {
  25. HKEY hKey;
  26. TCHAR InfPath[MAX_PATH];
  27. TCHAR InfName[MAX_PATH];
  28. ASSERT(pDevice);
  29. m_pDevice = pDevice;
  30. m_OnLocalMachine = pDevice->m_pMachine->IsLocal();
  31. CMachine* pMachine = m_pDevice->m_pMachine;
  32. ASSERT(pMachine);
  33. //
  34. // We can't get the digital signer on remote machines
  35. //
  36. if (!m_OnLocalMachine) {
  37. return TRUE;
  38. }
  39. m_hSDBDrvMain = SdbInitDatabase(SDB_DATABASE_MAIN_DRIVERS, NULL);
  40. //
  41. // Open drvice's driver registry key to get the InfPath
  42. //
  43. hKey = pMachine->DiOpenDevRegKey(*m_pDevice, DICS_FLAG_GLOBAL,
  44. 0, DIREG_DRV, KEY_READ);
  45. if (INVALID_HANDLE_VALUE != hKey) {
  46. DWORD regType;
  47. DWORD Len = sizeof(InfName);
  48. CSafeRegistry regDrv(hKey);
  49. //
  50. // Get the inf path from the driver key
  51. //
  52. if (regDrv.GetValue(REGSTR_VAL_INFPATH,
  53. &regType,
  54. (PBYTE)InfName,
  55. &Len)) {
  56. if (GetSystemWindowsDirectory(InfPath, ARRAYLEN(InfPath))) {
  57. if (lstrlen(InfPath))
  58. {
  59. //
  60. // Tack on an extra back slash if one is needed
  61. //
  62. if (_T('\\') != InfPath[lstrlen(InfPath) - 1])
  63. {
  64. lstrcat(InfPath, TEXT("\\"));
  65. }
  66. lstrcat(InfPath, TEXT("INF\\"));
  67. lstrcat(InfPath, InfName);
  68. pMachine->GetDigitalSigner(InfPath, m_DigitalSigner);
  69. }
  70. }
  71. }
  72. }
  73. return TRUE;
  74. }
  75. BOOL
  76. CDriver::BuildDriverList(
  77. PSP_DRVINFO_DATA pDrvInfoData,
  78. BOOL bFunctionAndFiltersOnly
  79. )
  80. {
  81. SP_DRVINFO_DATA DrvInfoData;
  82. HSPFILEQ hFileQueue = INVALID_HANDLE_VALUE;
  83. SP_DEVINSTALL_PARAMS DevInstParams;
  84. //
  85. // If we already built up the list of driver files then we don't need
  86. // to do it again.
  87. //
  88. if (m_DriverListBuilt) {
  89. return m_listDriverFile.GetCount();
  90. }
  91. ASSERT(m_pDevice);
  92. if (!m_OnLocalMachine) {
  93. AddFunctionAndFilterDrivers(m_pDevice);
  94. return m_listDriverFile.GetCount();
  95. }
  96. CMachine* pMachine = m_pDevice->m_pMachine;
  97. ASSERT(pMachine);
  98. hFileQueue = SetupOpenFileQueue();
  99. //
  100. // Only build up the list of files from the INF if bFunctionAndFiltersOnly
  101. // is not TRUE.
  102. //
  103. if (!bFunctionAndFiltersOnly) {
  104. DevInstParams.cbSize = sizeof(DevInstParams);
  105. if (!pDrvInfoData) {
  106. pMachine->DiGetDeviceInstallParams(*m_pDevice, &DevInstParams);
  107. //
  108. // Set the DI_FLAGSEX_INSTALLEDDRIVER flag before calling SetupDiBuildDriverInfoList.
  109. // This will have it only put the installed driver into the list.
  110. //
  111. DevInstParams.FlagsEx |= (DI_FLAGSEX_INSTALLEDDRIVER |
  112. DI_FLAGSEX_ALLOWEXCLUDEDDRVS);
  113. if (pMachine->DiSetDeviceInstallParams(*m_pDevice,
  114. &DevInstParams) &&
  115. pMachine->DiBuildDriverInfoList(*m_pDevice,
  116. SPDIT_CLASSDRIVER)) {
  117. DrvInfoData.cbSize = sizeof(DrvInfoData);
  118. //
  119. // There should only be one driver in this list. If there isn't any
  120. // drivers in this list then there must not be a driver currently
  121. // installed on this device.
  122. //
  123. if (pMachine->DiEnumDriverInfo(*m_pDevice, SPDIT_CLASSDRIVER, 0, &DrvInfoData)) {
  124. //
  125. // Set this as the selected driver
  126. //
  127. pMachine->DiSetSelectedDriver(*m_pDevice, &DrvInfoData);
  128. pDrvInfoData = &DrvInfoData;
  129. } else {
  130. //
  131. // We did not find a match...so just destroy it.
  132. //
  133. pMachine->DiDestroyDriverInfoList(*m_pDevice,
  134. SPDIT_CLASSDRIVER);
  135. pDrvInfoData = NULL;
  136. }
  137. }
  138. }
  139. if (pDrvInfoData) {
  140. //
  141. // Get a list of all the files installed for this device
  142. //
  143. if (INVALID_HANDLE_VALUE != hFileQueue) {
  144. DevInstParams.FileQueue = hFileQueue;
  145. DevInstParams.Flags |= DI_NOVCP;
  146. if (pMachine->DiSetDeviceInstallParams(*m_pDevice, &DevInstParams) &&
  147. pMachine->DiCallClassInstaller(DIF_INSTALLDEVICEFILES, *m_pDevice)) {
  148. //
  149. // Dereference the file queue so that we can close it
  150. //
  151. DevInstParams.FileQueue = NULL;
  152. DevInstParams.Flags &= ~DI_NOVCP;
  153. pMachine->DiSetDeviceInstallParams(*m_pDevice, &DevInstParams);
  154. }
  155. }
  156. if (pDrvInfoData == &DrvInfoData) {
  157. pMachine->DiDestroyDriverInfoList(*m_pDevice, SPDIT_CLASSDRIVER);
  158. }
  159. }
  160. }
  161. //
  162. // Add the funtion and device and class upper and lower filters, sometimes
  163. // these aren't added via the INF file directly so this makes sure they
  164. // show up in the list.
  165. //
  166. AddFunctionAndFilterDrivers(m_pDevice, hFileQueue);
  167. if (hFileQueue != INVALID_HANDLE_VALUE) {
  168. //
  169. // Scan the file queue.
  170. //
  171. DWORD ScanResult;
  172. SetupScanFileQueue(hFileQueue,
  173. SPQ_SCAN_USE_CALLBACK_SIGNERINFO,
  174. NULL,
  175. ScanQueueCallback,
  176. (PVOID)this,
  177. &ScanResult
  178. );
  179. //
  180. // Close the file queue
  181. //
  182. SetupCloseFileQueue(hFileQueue);
  183. }
  184. m_DriverListBuilt = TRUE;
  185. return m_listDriverFile.GetCount();
  186. }
  187. void
  188. CDriver::AddDriverFile(
  189. CDriverFile* pNewDrvFile
  190. )
  191. {
  192. //
  193. // Check to see if this driver already exists in the list.
  194. //
  195. POSITION pos = m_listDriverFile.GetHeadPosition();
  196. while (NULL != pos) {
  197. CDriverFile* pDrvFile = m_listDriverFile.GetNext(pos);
  198. if (lstrcmpi(pDrvFile->GetFullPathName(), pNewDrvFile->GetFullPathName()) == 0) {
  199. //
  200. // This file already exists in the list so just return without
  201. // adding it.
  202. //
  203. return;
  204. }
  205. }
  206. m_listDriverFile.AddTail(pNewDrvFile);
  207. }
  208. void
  209. CDriver::AddFunctionAndFilterDrivers(
  210. CDevice* pDevice,
  211. HSPFILEQ hFileQueue
  212. )
  213. {
  214. TCHAR ServiceName[MAX_PATH];
  215. ULONG BufferLen;
  216. HKEY hKey;
  217. DWORD regType;
  218. //
  219. // Get the function driver
  220. //
  221. if (pDevice->m_pMachine->DiGetDeviceRegistryProperty(*pDevice,
  222. SPDRP_SERVICE,
  223. NULL,
  224. (PBYTE)ServiceName,
  225. sizeof(ServiceName),
  226. NULL
  227. )) {
  228. CreateFromService(pDevice, ServiceName, hFileQueue);
  229. }
  230. //
  231. // Add the upper and lower device filters
  232. //
  233. for (int i = 0; i<2; i++) {
  234. BufferLen = 0;
  235. pDevice->m_pMachine->DiGetDeviceRegistryProperty(
  236. *pDevice,
  237. i ? SPDRP_LOWERFILTERS : SPDRP_UPPERFILTERS,
  238. NULL,
  239. NULL,
  240. BufferLen,
  241. &BufferLen
  242. );
  243. if (BufferLen != 0) {
  244. PTSTR Buffer = new TCHAR[BufferLen+2];
  245. if (Buffer) {
  246. ZeroMemory(Buffer, BufferLen+2);
  247. if (pDevice->m_pMachine->DiGetDeviceRegistryProperty(
  248. *pDevice,
  249. i ? SPDRP_LOWERFILTERS : SPDRP_UPPERFILTERS,
  250. NULL,
  251. (PBYTE)Buffer,
  252. BufferLen,
  253. &BufferLen
  254. )) {
  255. for (PTSTR SingleItem = Buffer; *SingleItem; SingleItem += (lstrlen(SingleItem) + 1)) {
  256. CreateFromService(pDevice, SingleItem, hFileQueue);
  257. }
  258. }
  259. delete Buffer;
  260. }
  261. }
  262. }
  263. //
  264. // Add the upper and lower class filters
  265. //
  266. GUID ClassGuid;
  267. pDevice->ClassGuid(ClassGuid);
  268. hKey = m_pDevice->m_pMachine->DiOpenClassRegKey(&ClassGuid, KEY_READ, DIOCR_INSTALLER);
  269. if (INVALID_HANDLE_VALUE != hKey) {
  270. CSafeRegistry regClass(hKey);
  271. for (int i = 0; i<2; i++) {
  272. BufferLen = 0;
  273. regClass.GetValue(i ? REGSTR_VAL_LOWERFILTERS : REGSTR_VAL_UPPERFILTERS,
  274. &regType,
  275. NULL,
  276. &BufferLen
  277. );
  278. if (BufferLen != 0) {
  279. PTSTR Buffer = new TCHAR[BufferLen+2];
  280. if (Buffer) {
  281. ZeroMemory(Buffer, BufferLen+2);
  282. if (regClass.GetValue(i ? REGSTR_VAL_LOWERFILTERS : REGSTR_VAL_UPPERFILTERS,
  283. &regType,
  284. (PBYTE)Buffer,
  285. &BufferLen
  286. )) {
  287. for (PTSTR SingleItem = Buffer; *SingleItem; SingleItem += (lstrlen(SingleItem) + 1)) {
  288. CreateFromService(pDevice, SingleItem, hFileQueue);
  289. }
  290. }
  291. delete Buffer;
  292. }
  293. }
  294. }
  295. }
  296. }
  297. void
  298. CDriver::CreateFromService(
  299. CDevice* pDevice,
  300. PCTSTR ServiceName,
  301. HSPFILEQ hFileQueue
  302. )
  303. {
  304. SC_HANDLE hscManager = NULL;
  305. SC_HANDLE hscService = NULL;
  306. if (!ServiceName) {
  307. return;
  308. }
  309. try
  310. {
  311. BOOL ComposePathNameFromServiceName = TRUE;
  312. // open default database on local machine for now
  313. hscManager = OpenSCManager(m_OnLocalMachine ? NULL : pDevice->m_pMachine->GetMachineFullName(),
  314. NULL, GENERIC_READ);
  315. if (NULL != hscManager)
  316. {
  317. hscService = OpenService(hscManager, ServiceName, GENERIC_READ);
  318. if (NULL != hscService)
  319. {
  320. QUERY_SERVICE_CONFIG qsc;
  321. DWORD BytesRequired;
  322. // first, probe for buffer size
  323. if (!QueryServiceConfig(hscService, NULL, 0, &BytesRequired) &&
  324. ERROR_INSUFFICIENT_BUFFER == GetLastError())
  325. {
  326. TCHAR FullPath[MAX_PATH];
  327. BufferPtr<BYTE> BufPtr(BytesRequired);
  328. LPQUERY_SERVICE_CONFIG pqsc;
  329. pqsc = (LPQUERY_SERVICE_CONFIG)(PBYTE)BufPtr;
  330. DWORD Size;
  331. if (QueryServiceConfig(hscService, pqsc, BytesRequired, &Size) &&
  332. pqsc->lpBinaryPathName &&
  333. (TEXT('\0') != pqsc->lpBinaryPathName[0]))
  334. {
  335. ComposePathNameFromServiceName = FALSE;
  336. //
  337. // Make sure we have a valid full path.
  338. //
  339. if (GetFullPathFromImagePath(pqsc->lpBinaryPathName,
  340. FullPath,
  341. ARRAYLEN(FullPath))) {
  342. if (hFileQueue != INVALID_HANDLE_VALUE) {
  343. //
  344. // Add the file to the queue.
  345. //
  346. TCHAR TargetPath[MAX_PATH];
  347. lstrcpy(TargetPath, FullPath);
  348. PTSTR p = (PTSTR)StrRChr(TargetPath, NULL, TEXT('\\'));
  349. if (p) {
  350. *p = TEXT('\0');
  351. }
  352. SetupQueueCopy(hFileQueue,
  353. NULL,
  354. NULL,
  355. MyGetFileTitle(FullPath),
  356. NULL,
  357. NULL,
  358. TargetPath,
  359. NULL,
  360. 0
  361. );
  362. } else {
  363. //
  364. // No file queue was passed in so just manually
  365. // add this to our list of driver files.
  366. //
  367. SafePtr<CDriverFile> DrvFilePtr;
  368. CDriverFile* pDrvFile = new CDriverFile();
  369. DrvFilePtr.Attach(pDrvFile);
  370. //
  371. // We will set the GetWin32Error to 0xFFFFFFFF which will
  372. // cause the UI to say 'not available' for the
  373. // signature.
  374. //
  375. if (pDrvFile->Create(FullPath,
  376. m_OnLocalMachine,
  377. 0xFFFFFFFF,
  378. NULL,
  379. m_hSDBDrvMain))
  380. {
  381. AddDriverFile(pDrvFile);
  382. DrvFilePtr.Detach();
  383. }
  384. }
  385. }
  386. }
  387. }
  388. CloseServiceHandle(hscService);
  389. hscService = NULL;
  390. }
  391. CloseServiceHandle(hscManager);
  392. hscManager = NULL;
  393. }
  394. if (ComposePathNameFromServiceName)
  395. {
  396. TCHAR FullPathName[MAX_PATH];
  397. TCHAR SysDir[MAX_PATH];
  398. if ((GetSystemDirectory(SysDir, ARRAYLEN(SysDir)) != 0) &&
  399. SUCCEEDED(StringCchCopy(FullPathName, ARRAYLEN(FullPathName), SysDir)) &&
  400. SUCCEEDED(StringCchCat(FullPathName, ARRAYLEN(FullPathName), TEXT("\\drivers\\"))) &&
  401. SUCCEEDED(StringCchCat(FullPathName, ARRAYLEN(FullPathName), ServiceName)) &&
  402. SUCCEEDED(StringCchCat(FullPathName, ARRAYLEN(FullPathName), TEXT(".sys")))) {
  403. if (hFileQueue != INVALID_HANDLE_VALUE) {
  404. //
  405. // Add the file to the queue.
  406. //
  407. TCHAR TargetPath[MAX_PATH];
  408. lstrcpy(TargetPath, FullPathName);
  409. PTSTR p = (PTSTR)StrRChr(TargetPath, NULL, TEXT('\\'));
  410. if (p) {
  411. *p = TEXT('\0');
  412. }
  413. SetupQueueCopy(hFileQueue,
  414. NULL,
  415. NULL,
  416. MyGetFileTitle(FullPathName),
  417. NULL,
  418. NULL,
  419. TargetPath,
  420. NULL,
  421. 0
  422. );
  423. } else {
  424. //
  425. // No file queue was passed in so just manually
  426. // add this to our list of driver files.
  427. //
  428. SafePtr<CDriverFile> DrvFilePtr;
  429. CDriverFile* pDrvFile = new CDriverFile();
  430. DrvFilePtr.Attach(pDrvFile);
  431. //
  432. // We will set the GetWin32Error to 0xFFFFFFFF which will
  433. // cause the UI to say 'not available' for the
  434. // signature.
  435. //
  436. if (pDrvFile->Create(FullPathName,
  437. m_OnLocalMachine,
  438. 0xFFFFFFFF,
  439. NULL,
  440. m_hSDBDrvMain))
  441. {
  442. AddDriverFile(pDrvFile);
  443. DrvFilePtr.Detach();
  444. }
  445. }
  446. }
  447. }
  448. }
  449. catch (CMemoryException* e)
  450. {
  451. if (hscService)
  452. {
  453. CloseServiceHandle(hscService);
  454. }
  455. if (hscManager)
  456. {
  457. CloseServiceHandle(hscManager);
  458. }
  459. throw;
  460. }
  461. }
  462. CDriver::~CDriver()
  463. {
  464. if (!m_listDriverFile.IsEmpty())
  465. {
  466. POSITION pos = m_listDriverFile.GetHeadPosition();
  467. while (NULL != pos) {
  468. CDriverFile* pDrvFile = m_listDriverFile.GetNext(pos);
  469. delete pDrvFile;
  470. }
  471. m_listDriverFile.RemoveAll();
  472. }
  473. if (m_hSDBDrvMain) {
  474. SdbReleaseDatabase(m_hSDBDrvMain);
  475. }
  476. }
  477. BOOL
  478. CDriver::operator ==(
  479. CDriver& OtherDriver
  480. )
  481. {
  482. CDriverFile* pThisDrvFile;
  483. CDriverFile* pOtherDrvFile;
  484. BOOL DrvFileFound = FALSE;
  485. PVOID ThisContext, OtherContext;
  486. if (GetFirstDriverFile(&pThisDrvFile, ThisContext))
  487. {
  488. do {
  489. DrvFileFound = FALSE;
  490. if (OtherDriver.GetFirstDriverFile(&pOtherDrvFile, OtherContext))
  491. {
  492. do {
  493. if (*pThisDrvFile == *pOtherDrvFile)
  494. {
  495. DrvFileFound = TRUE;
  496. break;
  497. }
  498. } while (OtherDriver.GetNextDriverFile(&pOtherDrvFile, OtherContext));
  499. }
  500. } while (DrvFileFound && GetNextDriverFile(&pThisDrvFile, ThisContext));
  501. return DrvFileFound;
  502. }
  503. else
  504. {
  505. // if both do not have driver file, they are equal.
  506. return !OtherDriver.GetFirstDriverFile(&pOtherDrvFile, OtherContext);
  507. }
  508. }
  509. //
  510. // Can not throw a exception from this function because it is a callback
  511. //
  512. UINT
  513. CDriver::ScanQueueCallback(
  514. PVOID Context,
  515. UINT Notification,
  516. UINT_PTR Param1,
  517. UINT_PTR Param2
  518. )
  519. {
  520. try
  521. {
  522. if (SPFILENOTIFY_QUEUESCAN_SIGNERINFO == Notification && Param1)
  523. {
  524. CDriver* pDriver = (CDriver*)Context;
  525. if (pDriver)
  526. {
  527. SafePtr<CDriverFile> DrvFilePtr;
  528. CDriverFile* pDrvFile = new CDriverFile();
  529. DrvFilePtr.Attach(pDrvFile);
  530. //
  531. // When creating the CDriver set the Win32Error to 0xFFFFFFFF
  532. // if the user is loged in as a guest. This is because we
  533. // cannot tell if a file is digitally signed if the user is
  534. // a guest. If the user is not a guest then use the Win32Error
  535. // returned from setupapi.
  536. //
  537. if (pDrvFile->Create((LPCTSTR)((PFILEPATHS_SIGNERINFO)Param1)->Target,
  538. pDriver->IsLocal(),
  539. pDriver->m_pDevice->m_pMachine->IsUserAGuest()
  540. ? 0xFFFFFFFF
  541. : ((PFILEPATHS_SIGNERINFO)Param1)->Win32Error,
  542. ((PFILEPATHS_SIGNERINFO)Param1)->DigitalSigner,
  543. pDriver->m_hSDBDrvMain
  544. ))
  545. {
  546. pDriver->AddDriverFile(pDrvFile);
  547. DrvFilePtr.Detach();
  548. }
  549. }
  550. }
  551. }
  552. catch (CMemoryException* e)
  553. {
  554. e->Delete();
  555. return ERROR_NOT_ENOUGH_MEMORY;
  556. }
  557. return NO_ERROR;
  558. }
  559. BOOL
  560. CDriver::GetFirstDriverFile(
  561. CDriverFile** ppDrvFile,
  562. PVOID& Context
  563. )
  564. {
  565. ASSERT(ppDrvFile);
  566. if (!m_listDriverFile.IsEmpty())
  567. {
  568. POSITION pos = m_listDriverFile.GetHeadPosition();
  569. *ppDrvFile = m_listDriverFile.GetNext(pos);
  570. Context = pos;
  571. return TRUE;
  572. }
  573. Context = NULL;
  574. *ppDrvFile = NULL;
  575. return FALSE;
  576. }
  577. BOOL
  578. CDriver::GetNextDriverFile(
  579. CDriverFile** ppDrvFile,
  580. PVOID& Context
  581. )
  582. {
  583. ASSERT(ppDrvFile);
  584. POSITION pos = (POSITION)Context;
  585. if (NULL != pos)
  586. {
  587. *ppDrvFile = m_listDriverFile.GetNext(pos);
  588. Context = pos;
  589. return TRUE;
  590. }
  591. *ppDrvFile = NULL;
  592. return FALSE;
  593. }
  594. void
  595. CDriver::GetDriverSignerString(
  596. String& strDriverSigner
  597. )
  598. {
  599. if (m_DigitalSigner.IsEmpty()) {
  600. strDriverSigner.LoadString(g_hInstance, IDS_NO_DIGITALSIGNATURE);
  601. } else {
  602. strDriverSigner = m_DigitalSigner;
  603. }
  604. }
  605. BOOL
  606. CDriver::GetFullPathFromImagePath(
  607. LPCTSTR ImagePath,
  608. LPTSTR FullPath,
  609. UINT FullPathLength
  610. )
  611. {
  612. TCHAR OriginalCurrentDirectory[MAX_PATH];
  613. LPTSTR pRelativeString;
  614. LPTSTR lpFilePart;
  615. if (!ImagePath || (ImagePath[0] == TEXT('\0'))) {
  616. return FALSE;
  617. }
  618. //
  619. // If we aren't on a local machine then just return the file name and not
  620. // the full path.
  621. //
  622. if (!m_OnLocalMachine) {
  623. lstrcpyn(FullPath, MyGetFileTitle(ImagePath), FullPathLength);
  624. return TRUE;
  625. }
  626. //
  627. // First check if the ImagePath happens to be a valid full path.
  628. //
  629. if (GetFileAttributes(ImagePath) != 0xFFFFFFFF) {
  630. ::GetFullPathName(ImagePath, FullPathLength, FullPath, &lpFilePart);
  631. return TRUE;
  632. }
  633. pRelativeString = (LPTSTR)ImagePath;
  634. //
  635. // If the ImagePath starts with "\SystemRoot" or "%SystemRoot%" then
  636. // remove those values.
  637. //
  638. if (StrCmpNI(ImagePath, TEXT("\\SystemRoot\\"), lstrlen(TEXT("\\SystemRoot\\"))) == 0) {
  639. pRelativeString += lstrlen(TEXT("\\SystemRoot\\"));
  640. } else if (StrCmpNI(ImagePath, TEXT("%SystemRoot%\\"), lstrlen(TEXT("%SystemRoot%\\"))) == 0) {
  641. pRelativeString += lstrlen(TEXT("%SystemRoot%\\"));
  642. }
  643. //
  644. // At this point pRelativeString should point to the image path relative to
  645. // the windows directory.
  646. //
  647. if (!GetSystemWindowsDirectory(FullPath, FullPathLength)) {
  648. return FALSE;
  649. }
  650. if (!GetCurrentDirectory(ARRAYLEN(OriginalCurrentDirectory), OriginalCurrentDirectory)) {
  651. OriginalCurrentDirectory[0] = TEXT('\0');
  652. }
  653. if (!SetCurrentDirectory(FullPath)) {
  654. return FALSE;
  655. }
  656. ::GetFullPathName(pRelativeString, FullPathLength, FullPath, &lpFilePart);
  657. if (OriginalCurrentDirectory[0] != TEXT('\0')) {
  658. SetCurrentDirectory(OriginalCurrentDirectory);
  659. }
  660. return TRUE;
  661. }
  662. BOOL
  663. CDriverFile::Create(
  664. LPCTSTR ServiceName,
  665. BOOL LocalMachine,
  666. DWORD Win32Error,
  667. LPCTSTR DigitalSigner,
  668. HSDB hSDBDrvMain
  669. )
  670. {
  671. if (!ServiceName || (TEXT('\0') == ServiceName[0]))
  672. {
  673. return FALSE;
  674. }
  675. m_Win32Error = Win32Error;
  676. if (DigitalSigner) {
  677. m_strDigitalSigner = DigitalSigner;
  678. }
  679. //
  680. // For remote machine, we can not verify if the driver file exits.
  681. // we only show the driver name.
  682. //
  683. if (LocalMachine) {
  684. m_Attributes = GetFileAttributes(ServiceName);
  685. if (0xFFFFFFFF != m_Attributes) {
  686. m_strFullPathName = ServiceName;
  687. } else {
  688. //
  689. // The driver is a service. Do not search for the current director --
  690. // GetFullPathName is useless here.
  691. // Search for Windows dir and System directory
  692. //
  693. TCHAR BaseDir[MAX_PATH];
  694. BaseDir[0] = TEXT('\0');
  695. if (GetSystemWindowsDirectory(BaseDir, ARRAYLEN(BaseDir))) {
  696. int Len;
  697. Len = lstrlen(BaseDir);
  698. if (Len)
  699. {
  700. if (_T('\\') != BaseDir[Len - 1])
  701. {
  702. lstrcat(BaseDir, TEXT("\\"));
  703. }
  704. lstrcat(BaseDir, MyGetFileTitle(ServiceName));
  705. m_Attributes = GetFileAttributes(BaseDir);
  706. }
  707. if (0xFFFFFFFF == m_Attributes)
  708. {
  709. if (GetSystemDirectory(BaseDir, ARRAYLEN(BaseDir))) {
  710. Len = lstrlen(BaseDir);
  711. if (Len)
  712. {
  713. if (_T('\\') != BaseDir[Len - 1])
  714. {
  715. lstrcat(BaseDir, TEXT("\\"));
  716. }
  717. lstrcat(BaseDir, MyGetFileTitle(ServiceName));
  718. m_Attributes = GetFileAttributes(BaseDir);
  719. }
  720. }
  721. }
  722. //
  723. // hopeless, we could find the path
  724. //
  725. if (0xFFFFFFFF == m_Attributes)
  726. {
  727. return FALSE;
  728. }
  729. m_strFullPathName = BaseDir;
  730. } else {
  731. return FALSE;
  732. }
  733. }
  734. m_HasVersionInfo = GetVersionInfo();
  735. }
  736. else {
  737. m_strFullPathName = ServiceName;
  738. //
  739. //we do not have version info
  740. //
  741. m_HasVersionInfo = FALSE;
  742. }
  743. if (!m_strFullPathName.IsEmpty() && hSDBDrvMain != NULL) {
  744. TAGREF tagref = TAGREF_NULL;
  745. HAPPHELPINFOCONTEXT hAppHelpInfoContext = NULL;
  746. SDBENTRYINFO entryinfo;
  747. DWORD cbSize;
  748. tagref = SdbGetDatabaseMatch(hSDBDrvMain,
  749. (LPTSTR)m_strFullPathName,
  750. INVALID_HANDLE_VALUE,
  751. NULL,
  752. 0
  753. );
  754. if (tagref != TAGREF_NULL) {
  755. //
  756. // This driver is in the database.
  757. //
  758. m_IsDriverBlocked = TRUE;
  759. //
  760. // Call SdbReadDriverInformation to get the database GUID and the
  761. // driver GUID for this entry.
  762. //
  763. ZeroMemory(&entryinfo, sizeof(entryinfo));
  764. if (SdbReadDriverInformation(hSDBDrvMain,
  765. tagref,
  766. &entryinfo)) {
  767. //
  768. // Open up the App help information database and query for the
  769. // html link.
  770. //
  771. hAppHelpInfoContext = SdbOpenApphelpInformation(&(entryinfo.guidDB),
  772. &(entryinfo.guidID));
  773. if (hAppHelpInfoContext) {
  774. cbSize = 0;
  775. PBYTE pBuffer = NULL;
  776. cbSize = SdbQueryApphelpInformation(hAppHelpInfoContext,
  777. ApphelpHelpCenterURL,
  778. NULL,
  779. 0);
  780. if (cbSize &&
  781. (pBuffer = new BYTE[cbSize])) {
  782. cbSize = SdbQueryApphelpInformation(hAppHelpInfoContext,
  783. ApphelpHelpCenterURL,
  784. (LPVOID)pBuffer,
  785. cbSize);
  786. if (cbSize) {
  787. m_strHtmlHelpID = (LPTSTR)pBuffer;
  788. }
  789. delete pBuffer;
  790. }
  791. SdbCloseApphelpInformation(hAppHelpInfoContext);
  792. }
  793. }
  794. }
  795. }
  796. return TRUE;
  797. }
  798. BOOL
  799. CDriverFile::GetVersionInfo()
  800. {
  801. DWORD Size, dwHandle;
  802. Size = GetFileVersionInfoSize((LPTSTR)(LPCTSTR)m_strFullPathName, &dwHandle);
  803. if (!Size)
  804. {
  805. return FALSE;
  806. }
  807. BufferPtr<BYTE> BufPtr(Size);
  808. PVOID pVerInfo = BufPtr;
  809. if (GetFileVersionInfo((LPTSTR)(LPCTSTR)m_strFullPathName, dwHandle, Size,
  810. pVerInfo))
  811. {
  812. // get VarFileInfo\Translation
  813. PVOID pBuffer;
  814. UINT Len;
  815. String strStringFileInfo;
  816. if (!VerQueryValue(pVerInfo, (LPTSTR)tszTranslation, &pBuffer, &Len))
  817. {
  818. strStringFileInfo = tszStringFileInfoDefault;
  819. }
  820. else
  821. {
  822. strStringFileInfo.Format(tszStringFileInfo, *((WORD*)pBuffer),
  823. *(((WORD*)pBuffer) + 1));
  824. }
  825. String str;
  826. str = strStringFileInfo + tszFileVersion;
  827. if (VerQueryValue(pVerInfo, (LPTSTR)(LPCTSTR)str, &pBuffer, &Len))
  828. {
  829. m_strVersion = (LPTSTR)pBuffer;
  830. str = strStringFileInfo + tszLegalCopyright;
  831. if (VerQueryValue(pVerInfo, (LPTSTR)(LPCTSTR)str, &pBuffer, &Len))
  832. {
  833. m_strCopyright = (LPTSTR)pBuffer;
  834. str = strStringFileInfo + tszCompanyName;
  835. if (VerQueryValue(pVerInfo, (LPTSTR)(LPCTSTR)str, &pBuffer, &Len))
  836. {
  837. m_strProvider = (LPTSTR)pBuffer;
  838. }
  839. }
  840. }
  841. }
  842. return TRUE;
  843. }
  844. BOOL
  845. CDriverFile::operator ==(
  846. CDriverFile& OtherDrvFile
  847. )
  848. {
  849. return \
  850. m_HasVersionInfo == OtherDrvFile.HasVersionInfo() &&
  851. (GetFullPathName() == OtherDrvFile.GetFullPathName() ||
  852. (GetFullPathName() && OtherDrvFile.GetFullPathName() &&
  853. !lstrcmpi(GetFullPathName(), OtherDrvFile.GetFullPathName())
  854. )
  855. ) &&
  856. (GetProvider() == OtherDrvFile.GetProvider() ||
  857. (GetProvider() && OtherDrvFile.GetProvider() &&
  858. !lstrcmpi(GetProvider(), OtherDrvFile.GetProvider())
  859. )
  860. ) &&
  861. (GetCopyright() == OtherDrvFile.GetCopyright() ||
  862. (GetCopyright() && OtherDrvFile.GetCopyright() &&
  863. !lstrcmpi(GetCopyright(), OtherDrvFile.GetCopyright())
  864. )
  865. ) &&
  866. (GetVersion() == OtherDrvFile.GetVersion() ||
  867. (GetVersion() && OtherDrvFile.GetVersion() &&
  868. !lstrcmpi(GetVersion(), OtherDrvFile.GetVersion())
  869. )
  870. );
  871. }