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.

1824 lines
38 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. dbattrib.c
  5. Abstract:
  6. This source implements attribute functions used by MigDb
  7. Author:
  8. Calin Negreanu (calinn) 07-Jan-1998
  9. Revision History:
  10. 28-May-1999 ovidiut Added SECTIONKEY attribute
  11. 22-Apr-1999 jimschm Added UPTOBIN*VER attributes
  12. 07-Jan-1999 jimschm Added HASVERSION attribute
  13. 18-May-1998 jimschm Added INPARENTDIR attribute
  14. 08-Apr-1998 calinn Added two more attributes (ExeType and Description)
  15. 29-Jan-1998 calinn Modified CheckSum and FileSize to work with hex numbers
  16. 19-Jan-1998 calinn added CheckSum attribute
  17. --*/
  18. #include "pch.h"
  19. #include "migdbp.h"
  20. /*++
  21. Macro Expansion List Description:
  22. ATTRIBUTE_FUNCTIONS lists all valid attributes to query for a specific file.
  23. They are used by migdb in it's attempt to locate files.
  24. Line Syntax:
  25. DEFMAC(AttribFn, AttribName, ReqArgs)
  26. Arguments:
  27. AttribFn - This is a boolean function that returnes TRUE if a specified file has
  28. the specified attribute. You must implement a function with this name
  29. and required parameters.
  30. AttribName - This is the string that identifies the attribute function. It should
  31. have the same value as listed in migdb.inf
  32. ReqArgs - Specifies the number of args that are required for the action. Used
  33. by the parser.
  34. Variables Generated From List:
  35. g_AttributeFunctions - do not touch!
  36. For accessing the array there are the following functions:
  37. MigDb_GetAttributeAddr
  38. MigDb_GetAttributeIdx
  39. MigDb_GetAttributeName
  40. MigDb_GetReqArgCount
  41. --*/
  42. #define ATTRIBUTE_FUNCTIONS \
  43. DEFMAC(CompanyName, COMPANYNAME, 1) \
  44. DEFMAC(FileDescription, FILEDESCRIPTION, 1) \
  45. DEFMAC(FileVersion, FILEVERSION, 1) \
  46. DEFMAC(InternalName, INTERNALNAME, 1) \
  47. DEFMAC(LegalCopyright, LEGALCOPYRIGHT, 1) \
  48. DEFMAC(OriginalFilename, ORIGINALFILENAME, 1) \
  49. DEFMAC(ProductName, PRODUCTNAME, 1) \
  50. DEFMAC(ProductVersion, PRODUCTVERSION, 1) \
  51. DEFMAC(FileSize, FILESIZE, 1) \
  52. DEFMAC(IsMsBinary, ISMSBINARY, 0) \
  53. DEFMAC(IsWin9xBinary, ISWIN9XBINARY, 0) \
  54. DEFMAC(InWinDir, INWINDIR, 0) \
  55. DEFMAC(InCatDir, INCATDIR, 0) \
  56. DEFMAC(InHlpDir, INHLPDIR, 0) \
  57. DEFMAC(InSysDir, INSYSDIR, 0) \
  58. DEFMAC(InProgramFiles, INPROGRAMFILES, 0) \
  59. DEFMAC(IsNotSysRoot, ISNOTSYSROOT, 0) \
  60. DEFMAC(CheckSum, CHECKSUM, 1) \
  61. DEFMAC(ExeType, EXETYPE, 1) \
  62. DEFMAC(Description, DESCRIPTION, 1) \
  63. DEFMAC(InParentDir, INPARENTDIR, 1) \
  64. DEFMAC(InRootDir, INROOTDIR, 0) \
  65. DEFMAC(PnpIdAttrib, PNPID, 1) \
  66. DEFMAC(HlpTitle, HLPTITLE, 1) \
  67. DEFMAC(IsWin98, ISWIN98, 0) \
  68. DEFMAC(HasVersion, HASVERSION, 0) \
  69. DEFMAC(ReqFile, REQFILE, 1) \
  70. DEFMAC(BinFileVer, BINFILEVER, 1) \
  71. DEFMAC(BinProductVer, BINPRODUCTVER, 1) \
  72. DEFMAC(FileDateHi, FILEDATEHI, 1) \
  73. DEFMAC(FileDateLo, FILEDATELO, 1) \
  74. DEFMAC(FileVerOs, FILEVEROS, 1) \
  75. DEFMAC(FileVerType, FILEVERTYPE, 1) \
  76. DEFMAC(SizeCheckSum, FC, 2) \
  77. DEFMAC(UpToBinProductVer, UPTOBINPRODUCTVER, 1) \
  78. DEFMAC(UpToBinFileVer, UPTOBINFILEVER, 1) \
  79. DEFMAC(SectionKey, SECTIONKEY, 1) \
  80. DEFMAC(RegKeyPresent, REGKEYPRESENT, 1) \
  81. DEFMAC(AtLeastWin98, ATLEASTWIN98, 0) \
  82. DEFMAC(HasUninstall, HASUNINSTALL, 1) \
  83. DEFMAC(IsItInstalled, ISITINSTALLED, 1) \
  84. typedef struct {
  85. PCSTR AttributeName;
  86. PATTRIBUTE_PROTOTYPE AttributeFunction;
  87. UINT RequiredArgs;
  88. } ATTRIBUTE_STRUCT, *PATTRIBUTE_STRUCT;
  89. //
  90. // Declare the attribute functions
  91. //
  92. #define DEFMAC(fn,id,reqargs) ATTRIBUTE_PROTOTYPE fn;
  93. ATTRIBUTE_FUNCTIONS
  94. #undef DEFMAC
  95. //
  96. // Declare a global array of functions and name identifiers for attribute functions
  97. //
  98. #define DEFMAC(fn,id,regargs) {#id, fn, regargs},
  99. static ATTRIBUTE_STRUCT g_AttributeFunctions[] = {
  100. ATTRIBUTE_FUNCTIONS
  101. {NULL, NULL}
  102. };
  103. #undef DEFMAC
  104. //
  105. // if this is TRUE, all attributes that check directories (InWinDir, InHlpDir, InCatDir, InSysDir)
  106. // will return TRUE, otherwise will actually do the appropriate tests.
  107. //
  108. BOOL g_InAnyDir = FALSE;
  109. BOOL
  110. pAlwaysFalseAttribute (
  111. IN PDBATTRIB_PARAMS AttribParams,
  112. IN PCSTR Args
  113. )
  114. {
  115. return FALSE;
  116. }
  117. PATTRIBUTE_PROTOTYPE
  118. MigDb_GetAttributeAddr (
  119. IN INT AttributeIdx
  120. )
  121. /*++
  122. Routine Description:
  123. MigDb_GetAttributeAddr returns the address of the attribute function based on the attribute index
  124. Arguments:
  125. AttributeIdx - Attribute index.
  126. Return value:
  127. Attribute function address. Note that no checking is made so the address returned could be invalid.
  128. This is not a problem since the parsing code did the right job.
  129. --*/
  130. {
  131. if (AttributeIdx == -1) {
  132. return &pAlwaysFalseAttribute;
  133. }
  134. return g_AttributeFunctions[AttributeIdx].AttributeFunction;
  135. }
  136. INT
  137. MigDb_GetAttributeIdx (
  138. IN PCSTR AttributeName
  139. )
  140. /*++
  141. Routine Description:
  142. MigDb_GetAttributeIdx returns the attribute index based on the attribute name
  143. Arguments:
  144. AttributeName - Attribute name.
  145. Return value:
  146. Attribute index. If the name is not found, the index returned is -1.
  147. --*/
  148. {
  149. PATTRIBUTE_STRUCT p = g_AttributeFunctions;
  150. INT i = 0;
  151. while (p->AttributeName != NULL) {
  152. if (StringIMatch (p->AttributeName, AttributeName)) {
  153. return i;
  154. }
  155. p++;
  156. i++;
  157. }
  158. return -1;
  159. }
  160. PCSTR
  161. MigDb_GetAttributeName (
  162. IN INT AttributeIdx
  163. )
  164. /*++
  165. Routine Description:
  166. MigDb_GetAttributeName returns the name of an attribute based on the attribute index
  167. Arguments:
  168. AttributeIdx - Attribute index.
  169. Return value:
  170. Attribute name. Note that no checking is made so the returned pointer could be invalid.
  171. This is not a problem since the parsing code did the right job.
  172. --*/
  173. {
  174. if (AttributeIdx == -1) {
  175. return "nul";
  176. }
  177. return g_AttributeFunctions[AttributeIdx].AttributeName;
  178. }
  179. UINT
  180. MigDb_GetReqArgCount (
  181. IN INT AttributeIndex
  182. )
  183. /*++
  184. Routine Description:
  185. MigDb_GetReqArgCount is called by the migdb parser to get the required
  186. argument count. When the parser sees arguments that lack the required
  187. arguments, it skips them.
  188. Arguments:
  189. Index - Specifies the argument index
  190. Return Value:
  191. The required argument count, which can be zero or more.
  192. --*/
  193. {
  194. if (AttributeIndex == -1) {
  195. return 0;
  196. }
  197. return g_AttributeFunctions[AttributeIndex].RequiredArgs;
  198. }
  199. ULONGLONG
  200. GetBinFileVer (
  201. IN PCSTR FileName
  202. )
  203. {
  204. VERSION_STRUCT Version;
  205. ULONGLONG result = 0;
  206. if (CreateVersionStruct (&Version, FileName)) {
  207. result = VerGetFileVer (&Version);
  208. DestroyVersionStruct (&Version);
  209. }
  210. return result;
  211. }
  212. ULONGLONG
  213. GetBinProductVer (
  214. IN PCSTR FileName
  215. )
  216. {
  217. VERSION_STRUCT Version;
  218. ULONGLONG result = 0;
  219. if (CreateVersionStruct (&Version, FileName)) {
  220. result = VerGetProductVer (&Version);
  221. DestroyVersionStruct (&Version);
  222. }
  223. return result;
  224. }
  225. DWORD
  226. GetFileDateHi (
  227. IN PCSTR FileName
  228. )
  229. {
  230. VERSION_STRUCT Version;
  231. DWORD result = 0;
  232. if (CreateVersionStruct (&Version, FileName)) {
  233. result = VerGetFileDateHi (&Version);
  234. DestroyVersionStruct (&Version);
  235. }
  236. return result;
  237. }
  238. DWORD
  239. GetFileDateLo (
  240. IN PCSTR FileName
  241. )
  242. {
  243. VERSION_STRUCT Version;
  244. DWORD result = 0;
  245. if (CreateVersionStruct (&Version, FileName)) {
  246. result = VerGetFileDateLo (&Version);
  247. DestroyVersionStruct (&Version);
  248. }
  249. return result;
  250. }
  251. DWORD
  252. GetFileVerOs (
  253. IN PCSTR FileName
  254. )
  255. {
  256. VERSION_STRUCT Version;
  257. DWORD result = 0;
  258. if (CreateVersionStruct (&Version, FileName)) {
  259. result = VerGetFileVerOs (&Version);
  260. DestroyVersionStruct (&Version);
  261. }
  262. return result;
  263. }
  264. DWORD
  265. GetFileVerType (
  266. IN PCSTR FileName
  267. )
  268. {
  269. VERSION_STRUCT Version;
  270. DWORD result = 0;
  271. if (CreateVersionStruct (&Version, FileName)) {
  272. result = VerGetFileVerType (&Version);
  273. DestroyVersionStruct (&Version);
  274. }
  275. return result;
  276. }
  277. PSTR
  278. QueryVersionEntry (
  279. IN PCSTR FileName,
  280. IN PCSTR VersionEntry
  281. )
  282. /*++
  283. Routine Description:
  284. QueryVersionEntry queries the file's version structure returning the
  285. value for a specific entry
  286. Arguments:
  287. FileName - File to query for version struct.
  288. VersionEntry - Name to query in version structure.
  289. Return value:
  290. Value of specified entry or NULL if unsuccessful
  291. --*/
  292. {
  293. VERSION_STRUCT Version;
  294. PCSTR CurrentStr;
  295. PSTR result = NULL;
  296. MYASSERT (VersionEntry);
  297. if (CreateVersionStruct (&Version, FileName)) {
  298. __try {
  299. CurrentStr = EnumFirstVersionValue (&Version, VersionEntry);
  300. if (CurrentStr) {
  301. CurrentStr = SkipSpace (CurrentStr);
  302. result = DuplicatePathString (CurrentStr, 0);
  303. }
  304. else {
  305. __leave;
  306. }
  307. }
  308. __finally {
  309. DestroyVersionStruct (&Version);
  310. }
  311. }
  312. return result;
  313. }
  314. BOOL
  315. GlobalVersionCheck (
  316. IN PCSTR FileName,
  317. IN PCSTR NameToCheck,
  318. IN PCSTR ValueToCheck
  319. )
  320. /*++
  321. Routine Description:
  322. GlobalVersionCheck queries the file's version structure trying to
  323. see if a specific name has a specific value.
  324. Arguments:
  325. FileName - File to query for version struct.
  326. NameToCheck - Name to query in version structure.
  327. ValueToCheck - Value to query in version structure.
  328. Return value:
  329. TRUE - the query was successful
  330. FALSE - the query failed
  331. --*/
  332. {
  333. VERSION_STRUCT Version;
  334. PCSTR CurrentStr;
  335. BOOL result = FALSE;
  336. MYASSERT (NameToCheck);
  337. MYASSERT (ValueToCheck);
  338. if (CreateVersionStruct (&Version, FileName)) {
  339. __try {
  340. CurrentStr = EnumFirstVersionValue (&Version, NameToCheck);
  341. while (CurrentStr) {
  342. CurrentStr = SkipSpace (CurrentStr);
  343. TruncateTrailingSpace ((PSTR) CurrentStr);
  344. if (IsPatternMatchA (ValueToCheck, CurrentStr)) {
  345. result = TRUE;
  346. __leave;
  347. }
  348. CurrentStr = EnumNextVersionValue (&Version);
  349. }
  350. }
  351. __finally {
  352. DestroyVersionStruct (&Version);
  353. }
  354. }
  355. return result;
  356. }
  357. /*++
  358. CompanyName, FileDescription, FileVersion, InternalName, LegalCopyright, OriginalFilename,
  359. ProductName, ProductVersion are attribute functions that are querying the version structure
  360. for their specific entries. They all return TRUE if the specific entry has specific value,
  361. FALSE otherwise.
  362. --*/
  363. BOOL
  364. CompanyName (
  365. IN PDBATTRIB_PARAMS AttribParams,
  366. IN PCSTR Args
  367. )
  368. {
  369. return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "CompanyName", Args);
  370. }
  371. BOOL
  372. FileDescription (
  373. IN PDBATTRIB_PARAMS AttribParams,
  374. IN PCSTR Args
  375. )
  376. {
  377. return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "FileDescription", Args);
  378. }
  379. BOOL
  380. FileVersion (
  381. IN PDBATTRIB_PARAMS AttribParams,
  382. IN PCSTR Args
  383. )
  384. {
  385. return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "FileVersion", Args);
  386. }
  387. BOOL
  388. InternalName (
  389. IN PDBATTRIB_PARAMS AttribParams,
  390. IN PCSTR Args
  391. )
  392. {
  393. return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "InternalName", Args);
  394. }
  395. BOOL
  396. LegalCopyright (
  397. IN PDBATTRIB_PARAMS AttribParams,
  398. IN PCSTR Args
  399. )
  400. {
  401. return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "LegalCopyright", Args);
  402. }
  403. BOOL
  404. OriginalFilename (
  405. IN PDBATTRIB_PARAMS AttribParams,
  406. IN PCSTR Args
  407. )
  408. {
  409. return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "OriginalFilename", Args);
  410. }
  411. BOOL
  412. ProductName (
  413. IN PDBATTRIB_PARAMS AttribParams,
  414. IN PCSTR Args
  415. )
  416. {
  417. return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "ProductName", Args);
  418. }
  419. BOOL
  420. ProductVersion (
  421. IN PDBATTRIB_PARAMS AttribParams,
  422. IN PCSTR Args
  423. )
  424. {
  425. return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "ProductVersion", Args);
  426. }
  427. BOOL
  428. FileSize (
  429. IN PDBATTRIB_PARAMS AttribParams,
  430. IN PCSTR Args
  431. )
  432. /*++
  433. Routine Description:
  434. FileSize checks for the size of a file.
  435. Arguments:
  436. Params - See definition.
  437. Args - MultiSz. First Sz is the file size we need to check.
  438. Return value:
  439. TRUE - the file size matches Args
  440. FALSE - otherwise
  441. --*/
  442. {
  443. DWORD fileSize;
  444. if (!sscanf (Args, "%lx", &fileSize)) {
  445. DEBUGMSG ((DBG_ERROR, "FileSize: Invalid argument value (%s) in migdb.inf", Args));
  446. return FALSE;
  447. }
  448. if (fileSize == AttribParams->FileParams->FindData->nFileSizeLow) {
  449. return TRUE;
  450. }
  451. else {
  452. return (_atoi64 (Args) == AttribParams->FileParams->FindData->nFileSizeLow);
  453. }
  454. }
  455. BOOL
  456. IsMsBinary (
  457. PDBATTRIB_PARAMS AttribParams,
  458. IN PCSTR Args
  459. )
  460. /*++
  461. Routine Description:
  462. IsMsBinary checks to see if a certain file is Microsoft stuff. For 32 bit modules
  463. we query CompanyName for "Microsoft" somewhere inside. For other modules we are
  464. relying on InWinDir attribute
  465. Arguments:
  466. Params - See definition.
  467. Args - MultiSz. Not used.
  468. Return value:
  469. TRUE - the file is MS stuff
  470. FALSE - otherwise
  471. --*/
  472. {
  473. VERSION_STRUCT Version;
  474. PCTSTR CompanyStr;
  475. BOOL result = FALSE;
  476. //
  477. // InWinDir has some collision risks. But for some files, we have no other
  478. // choice. We know the file was shipped by Microsoft.
  479. //
  480. if (InWinDir (AttribParams, Args)) {
  481. result = TRUE;
  482. }
  483. //
  484. // If it's not in %WinDir%, then it has to have Microsoft in the company name
  485. //
  486. else if (CreateVersionStruct (
  487. &Version,
  488. AttribParams->FileParams->FullFileSpec
  489. )) {
  490. __try {
  491. CompanyStr = EnumFirstVersionValue (&Version, TEXT("CompanyName"));
  492. while (CompanyStr) {
  493. if (_mbsistr (CompanyStr, TEXT("Microsoft"))) {
  494. result = TRUE;
  495. __leave;
  496. }
  497. CompanyStr = EnumNextVersionValue (&Version);
  498. }
  499. }
  500. __finally {
  501. DestroyVersionStruct (&Version);
  502. }
  503. }
  504. return result;
  505. }
  506. BOOL
  507. IsWin9xBinary (
  508. PDBATTRIB_PARAMS AttribParams,
  509. IN PCSTR Args
  510. )
  511. /*++
  512. Routine Description:
  513. IsWon9xBinary checks to see if a certain file is Microsoft Win9x stuff. It works only for
  514. 16 and 32 bit modules with version stamp. The COMPANYNAME is checked against *Microsoft* and
  515. the PRODUCTVERSION is checked against 4.*
  516. Arguments:
  517. Params - See definition.
  518. Args - MultiSz. Not used.
  519. Return value:
  520. TRUE - the file is MS stuff
  521. FALSE - otherwise
  522. --*/
  523. {
  524. VERSION_STRUCT Version;
  525. PCTSTR CurrentStr;
  526. BOOL result;
  527. if (CreateVersionStruct (&Version, AttribParams->FileParams->FullFileSpec)) {
  528. result = FALSE;
  529. CurrentStr = EnumFirstVersionValue (&Version, TEXT("CompanyName"));
  530. while (CurrentStr) {
  531. CurrentStr = SkipSpace (CurrentStr);
  532. TruncateTrailingSpace ((PSTR) CurrentStr);
  533. if (IsPatternMatchA (TEXT("*Microsoft*"), CurrentStr)) {
  534. result = TRUE;
  535. break;
  536. }
  537. CurrentStr = EnumNextVersionValue (&Version);
  538. }
  539. if (result) {
  540. result = FALSE;
  541. CurrentStr = EnumFirstVersionValue (&Version, TEXT("ProductVersion"));
  542. while (CurrentStr) {
  543. CurrentStr = SkipSpace (CurrentStr);
  544. TruncateTrailingSpace ((PSTR) CurrentStr);
  545. if (IsPatternMatchA (TEXT("4.*"), CurrentStr)) {
  546. result = TRUE;
  547. break;
  548. }
  549. CurrentStr = EnumNextVersionValue (&Version);
  550. }
  551. }
  552. DestroyVersionStruct (&Version);
  553. }
  554. else {
  555. result = FALSE;
  556. }
  557. return result;
  558. }
  559. BOOL
  560. InWinDir (
  561. PDBATTRIB_PARAMS AttribParams,
  562. IN PCSTR Args
  563. )
  564. /*++
  565. Routine Description:
  566. InWinDir returns TRUE if file is located in %Windir% or one of it's subdirectories
  567. Arguments:
  568. Params - See definition.
  569. Args - MultiSz. Not used.
  570. Return value:
  571. TRUE - the file is located in %Windir%
  572. FALSE - otherwise
  573. --*/
  574. {
  575. if (g_InAnyDir) {
  576. return TRUE;
  577. }
  578. return (StringIMatchCharCount (AttribParams->FileParams->FullFileSpec, g_WinDirWack, g_WinDirWackChars));
  579. }
  580. BOOL
  581. InCatDir (
  582. PDBATTRIB_PARAMS AttribParams,
  583. IN PCSTR Args
  584. )
  585. /*++
  586. Routine Description:
  587. InCatDir returns TRUE if file is located in %Windir%\CATROOT or one of it's subdirectories
  588. Arguments:
  589. Params - See definition.
  590. Args - MultiSz. Not used.
  591. Return value:
  592. TRUE - the file is located in %Windir%
  593. FALSE - otherwise
  594. --*/
  595. {
  596. if (g_InAnyDir) {
  597. return TRUE;
  598. }
  599. return (StringIMatchCharCount (AttribParams->FileParams->FullFileSpec, g_CatRootDirWack, g_CatRootDirWackChars));
  600. }
  601. BOOL
  602. InHlpDir (
  603. PDBATTRIB_PARAMS AttribParams,
  604. IN PCSTR Args
  605. )
  606. /*++
  607. Routine Description:
  608. InHlpDir returns TRUE if file is located in %Windir%\HELP or one of it's subdirectories
  609. Arguments:
  610. Params - See definition.
  611. Args - MultiSz. Not used.
  612. Return value:
  613. TRUE - the file is located in %Windir%
  614. FALSE - otherwise
  615. --*/
  616. {
  617. if (g_InAnyDir) {
  618. return TRUE;
  619. }
  620. return (StringIMatchCharCount (AttribParams->FileParams->FullFileSpec, g_HelpDirWack, g_HelpDirWackChars));
  621. }
  622. BOOL
  623. InSysDir (
  624. PDBATTRIB_PARAMS AttribParams,
  625. IN PCSTR Args
  626. )
  627. /*++
  628. Routine Description:
  629. InSysDir returns TRUE if file is located in %Windir%\SYSTEM or one of it's subdirectories
  630. Arguments:
  631. Params - See definition.
  632. Args - MultiSz. Not used.
  633. Return value:
  634. TRUE - the file is located in %Windir%
  635. FALSE - otherwise
  636. --*/
  637. {
  638. if (g_InAnyDir) {
  639. return TRUE;
  640. }
  641. return (StringIMatchCharCount (AttribParams->FileParams->FullFileSpec, g_SystemDirWack, g_SystemDirWackChars));
  642. }
  643. BOOL
  644. InProgramFiles (
  645. PDBATTRIB_PARAMS AttribParams,
  646. IN PCSTR Args
  647. )
  648. /*++
  649. Routine Description:
  650. InProgramFiles returns TRUE if file is located in Program Files or one of it's subdirectories
  651. Arguments:
  652. Params - See definition.
  653. Args - MultiSz. Not used.
  654. Return value:
  655. TRUE - the file is located in Program Files
  656. FALSE - otherwise
  657. --*/
  658. {
  659. if (g_InAnyDir) {
  660. return TRUE;
  661. }
  662. return (StringIMatchCharCount (AttribParams->FileParams->FullFileSpec, g_ProgramFilesDirWack, g_ProgramFilesDirWackChars));
  663. }
  664. BOOL
  665. IsNotSysRoot (
  666. PDBATTRIB_PARAMS AttribParams,
  667. IN PCSTR Args
  668. )
  669. /*++
  670. Routine Description:
  671. IsNotSysRoot returns TRUE if file is not located in C:\ directory
  672. Arguments:
  673. Params - See definition.
  674. Args - MultiSz. Not used.
  675. Return value:
  676. TRUE - the file is not located in C:\ directory
  677. FALSE - otherwise
  678. --*/
  679. {
  680. PSTR pathEnd;
  681. CHAR savedChar;
  682. BOOL result = FALSE;
  683. pathEnd = (PSTR)GetFileNameFromPath (AttribParams->FileParams->FullFileSpec);
  684. if (pathEnd == NULL) {
  685. return TRUE;
  686. }
  687. savedChar = pathEnd [0];
  688. __try {
  689. pathEnd [0] = 0;
  690. result = (!StringIMatch (AttribParams->FileParams->FullFileSpec, g_BootDrivePath));
  691. }
  692. __finally {
  693. pathEnd [0] = savedChar;
  694. }
  695. return result;
  696. }
  697. UINT
  698. ComputeCheckSum (
  699. PFILE_HELPER_PARAMS Params
  700. )
  701. /*++
  702. Routine Description:
  703. ComputeCheckSum will compute the check sum for 4096 bytes starting at offset 512. The offset and the size of
  704. the chunk are modified if the file size is too small.
  705. Arguments:
  706. Params - See definition.
  707. Return value:
  708. The computed checksum
  709. --*/
  710. {
  711. INT i,size = 4096;
  712. DWORD startAddr = 512;
  713. HANDLE fileHandle = INVALID_HANDLE_VALUE;
  714. PCHAR buffer = NULL;
  715. UINT checkSum = 0;
  716. DWORD dontCare;
  717. if (Params->FindData->nFileSizeLow < (ULONG)size) {
  718. //
  719. // File size is less than 4096. We set the start address to 0 and set the size for the checksum
  720. // to the actual file size.
  721. //
  722. startAddr = 0;
  723. size = Params->FindData->nFileSizeLow;
  724. }
  725. else
  726. if (startAddr + size > Params->FindData->nFileSizeLow) {
  727. //
  728. // File size is too small. We set the start address so that size of checksum can be 4096 bytes
  729. //
  730. startAddr = Params->FindData->nFileSizeLow - size;
  731. }
  732. if (size <= 3) {
  733. //
  734. // we need at least 3 bytes to be able to do something here.
  735. //
  736. return 0;
  737. }
  738. __try {
  739. buffer = MemAlloc (g_hHeap, 0, size);
  740. if (buffer == NULL) {
  741. __leave;
  742. }
  743. fileHandle = CreateFile (Params->FullFileSpec, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  744. if (fileHandle == INVALID_HANDLE_VALUE) {
  745. __leave;
  746. }
  747. if (SetFilePointer (fileHandle, startAddr, NULL, FILE_BEGIN) != startAddr) {
  748. __leave;
  749. }
  750. if (!ReadFile (fileHandle, buffer, size, &dontCare, NULL)) {
  751. __leave;
  752. }
  753. for (i = 0; i<(size - 3); i+=4) {
  754. checkSum += *((PDWORD) (buffer + i));
  755. checkSum = _rotr (checkSum ,1);
  756. }
  757. }
  758. __finally {
  759. if (fileHandle != INVALID_HANDLE_VALUE) {
  760. CloseHandle (fileHandle);
  761. }
  762. if (buffer != NULL) {
  763. MemFree (g_hHeap, 0, buffer);
  764. }
  765. }
  766. return checkSum;
  767. }
  768. BOOL
  769. CheckSum (
  770. PDBATTRIB_PARAMS AttribParams,
  771. IN PCSTR Args
  772. )
  773. /*++
  774. Routine Description:
  775. CheckSum returns TRUE if file's checksum equals the value in Args
  776. Arguments:
  777. Params - See definition.
  778. Args - checksum value.
  779. Return value:
  780. TRUE - the file's checksum equals the value in Args
  781. FALSE - otherwise
  782. --*/
  783. {
  784. UINT checkSum = 0;
  785. UINT oldSum = 0;
  786. checkSum = ComputeCheckSum (AttribParams->FileParams);
  787. if (!sscanf (Args, "%lx", &oldSum)) {
  788. DEBUGMSG ((DBG_ERROR, "Invalid checksum value (%s) in migdb.inf", Args));
  789. return FALSE;
  790. }
  791. if (oldSum == checkSum) {
  792. return TRUE;
  793. }
  794. else {
  795. return (_atoi64 (Args) == checkSum);
  796. }
  797. }
  798. BOOL
  799. SizeCheckSum (
  800. PDBATTRIB_PARAMS AttribParams,
  801. IN PCSTR Args
  802. )
  803. /*++
  804. Routine Description:
  805. Returns TRUE if file's size equals first arg and checksum equals to the second arg
  806. Arguments:
  807. Params - See definition.
  808. Args - checksum value.
  809. Return value:
  810. TRUE - the file's checksum equals the value in Args
  811. FALSE - otherwise
  812. --*/
  813. {
  814. PCSTR currArg = Args;
  815. if (!FileSize (AttribParams, currArg)) {
  816. return FALSE;
  817. }
  818. currArg = GetEndOfString (currArg);
  819. if (!currArg) {
  820. return FALSE;
  821. }
  822. currArg = _mbsinc (currArg);
  823. if (!currArg) {
  824. return FALSE;
  825. }
  826. return (CheckSum (AttribParams, currArg));
  827. }
  828. PSTR g_ExeTypes[] = {
  829. "NONE",
  830. "DOS",
  831. "WIN16",
  832. "WIN32"
  833. };
  834. BOOL
  835. ExeType (
  836. PDBATTRIB_PARAMS AttribParams,
  837. IN PCSTR Args
  838. )
  839. /*++
  840. Routine Description:
  841. ExeType returns TRUE if file's type is according with Args. This can be:
  842. NONE, DOS, WIN16, WIN32
  843. Arguments:
  844. Params - See definition.
  845. Args - type of module.
  846. Return value:
  847. TRUE - the file's type is the same as Args
  848. FALSE - otherwise
  849. --*/
  850. {
  851. return IsPatternMatch (Args, g_ExeTypes[GetModuleType (AttribParams->FileParams->FullFileSpec)]);
  852. }
  853. BOOL
  854. Description (
  855. PDBATTRIB_PARAMS AttribParams,
  856. IN PCSTR Args
  857. )
  858. /*++
  859. Routine Description:
  860. Description returns TRUE if file's description matches Args
  861. Arguments:
  862. Params - See definition.
  863. Args - description
  864. Return value:
  865. TRUE - the file's description matches Args
  866. FALSE - otherwise
  867. --*/
  868. {
  869. PCSTR descr = NULL;
  870. BOOL result = FALSE;
  871. descr = Get16ModuleDescription (AttribParams->FileParams->FullFileSpec);
  872. if (descr != NULL) {
  873. result = IsPatternMatch (Args, descr);
  874. FreePathString (descr);
  875. }
  876. return result;
  877. }
  878. BOOL
  879. InParentDir (
  880. IN PDBATTRIB_PARAMS AttribParams,
  881. IN PCSTR Args
  882. )
  883. /*++
  884. Routine Description:
  885. InParentDir compares the sub directory of the matching file against the arg
  886. specified. This is used for apps that maintain static subdirs off their
  887. main app dir.
  888. Arguments:
  889. Params - Specifies parameters for current file being processed.
  890. Args - Specifies multi-sz of args passed in migdb.inf.
  891. Return Value:
  892. TRUE - the file's subdirectory matches Args
  893. FALSE - otherwise
  894. --*/
  895. {
  896. PCTSTR stop = NULL;
  897. PCTSTR start = NULL;
  898. TCHAR lastDir[MAX_TCHAR_PATH];
  899. // _tcsrchr validates the multibyte characters
  900. stop = _tcsrchr (AttribParams->FileParams->FullFileSpec, TEXT('\\'));
  901. if (stop) {
  902. //
  903. // Go back to previous wack
  904. //
  905. start = _tcsdec2 (AttribParams->FileParams->FullFileSpec, stop);
  906. if (start) {
  907. start = GetPrevChar (AttribParams->FileParams->FullFileSpec, start, TEXT('\\'));
  908. }
  909. }
  910. if (start) {
  911. //
  912. // Check string against arg
  913. //
  914. start = _tcsinc (start);
  915. _tcssafecpyab (lastDir, start, stop, MAX_TCHAR_PATH);
  916. if (Args) {
  917. return (IsPatternMatch (Args, lastDir));
  918. } else {
  919. DEBUGMSG ((DBG_WHOOPS, "InParentDir requires arg"));
  920. }
  921. }
  922. return FALSE;
  923. }
  924. BOOL
  925. InRootDir (
  926. IN PDBATTRIB_PARAMS AttribParams,
  927. IN PCSTR Args
  928. )
  929. /*++
  930. Routine Description:
  931. InRootDir returns TRUE is the file is located in root dir of the drive, FALSE otherwise.
  932. Arguments:
  933. Params - Specifies parameters for current file being processed.
  934. Args - Specifies multi-sz of args passed in migdb.inf.
  935. Return Value:
  936. TRUE - the file is in root dir of the drive
  937. FALSE - otherwise
  938. --*/
  939. {
  940. PCTSTR p1,p2;
  941. p1 = _tcschr (AttribParams->FileParams->FullFileSpec, TEXT('\\'));
  942. p2 = _tcsrchr (AttribParams->FileParams->FullFileSpec, TEXT('\\'));
  943. if (p1 && p2) {
  944. return (p1==p2);
  945. }
  946. return FALSE;
  947. }
  948. BOOL
  949. PnpIdAttrib (
  950. IN PDBATTRIB_PARAMS AttribParams,
  951. IN PCSTR Args
  952. )
  953. /*++
  954. Routine Description:
  955. PnpIdAttrib implements the PNPID() attribute, which is TRUE if the
  956. specified ID exists on the machine. The ID can be a complete instance ID
  957. (enumerator\PNPID\instance), or part of the ID (PNPID for example).
  958. Arguments:
  959. Params - Specifies parameters for current file being processed
  960. Args - Specifies the PNP ID argument
  961. Return Value:
  962. TRUE if the specified argument exists on the machine, otherwise FALSE.
  963. --*/
  964. {
  965. BOOL Result = FALSE;
  966. MULTISZ_ENUM e;
  967. TCHAR Node[MEMDB_MAX];
  968. if (EnumFirstMultiSz (&e, Args)) {
  969. Result = TRUE;
  970. do {
  971. MemDbBuildKey (Node, MEMDB_CATEGORY_PNPIDS, e.CurrentString, NULL, NULL);
  972. if (!MemDbGetValue (Node, NULL)) {
  973. Result = FALSE;
  974. break;
  975. }
  976. } while (EnumNextMultiSz (&e));
  977. }
  978. return Result;
  979. }
  980. BOOL
  981. HlpTitle (
  982. IN PDBATTRIB_PARAMS AttribParams,
  983. IN PCSTR Args
  984. )
  985. {
  986. PSTR title = NULL;
  987. BOOL result=FALSE;
  988. title = GetHlpFileTitle (AttribParams->FileParams->FullFileSpec);
  989. if (title) {
  990. result = StringIMatch (title, Args);
  991. }
  992. if (title) {
  993. FreePathString (title);
  994. }
  995. return result;
  996. }
  997. BOOL
  998. IsWin98 (
  999. IN PDBATTRIB_PARAMS AttribParams,
  1000. IN PCSTR Args
  1001. )
  1002. {
  1003. return ISMEMPHIS();
  1004. }
  1005. BOOL
  1006. HasVersion (
  1007. IN PDBATTRIB_PARAMS AttribParams,
  1008. IN PCSTR Args
  1009. )
  1010. /*++
  1011. Routine Description:
  1012. HasVersion determines if a file has any entries in its version
  1013. stamp.
  1014. Arguments:
  1015. Params - Specifies the helper params that give the files to test.
  1016. Args - Unused
  1017. Return Value:
  1018. TRUE if the specified file has an entry in its version stamp,
  1019. FALSE otherwsie.
  1020. --*/
  1021. {
  1022. VERSION_STRUCT Version;
  1023. BOOL Result = FALSE;
  1024. if (CreateVersionStruct (&Version, AttribParams->FileParams->FullFileSpec)) {
  1025. Result = TRUE;
  1026. DestroyVersionStruct (&Version);
  1027. }
  1028. return Result;
  1029. }
  1030. BOOL
  1031. ReqFile (
  1032. IN PDBATTRIB_PARAMS AttribParams,
  1033. IN PCSTR Args
  1034. )
  1035. {
  1036. static INT reqFileSeq = 0;
  1037. TCHAR reqFileSeqStr [20];
  1038. PMIGDB_REQ_FILE reqFile;
  1039. DBATTRIB_PARAMS reqFileAttribs;
  1040. PMIGDB_ATTRIB migDbAttrib;
  1041. FILE_HELPER_PARAMS newParams;
  1042. WIN32_FIND_DATA findData;
  1043. HANDLE findHandle;
  1044. PSTR oldFileSpec;
  1045. PSTR oldFilePtr;
  1046. BOOL result = TRUE;
  1047. if (!AttribParams->ExtraData) {
  1048. return TRUE;
  1049. }
  1050. reqFile = (PMIGDB_REQ_FILE)AttribParams->ExtraData;
  1051. while (reqFile) {
  1052. newParams.Handled = 0;
  1053. oldFileSpec = DuplicatePathString (AttribParams->FileParams->FullFileSpec, 0);
  1054. oldFilePtr = (PSTR)GetFileNameFromPath (oldFileSpec);
  1055. if (oldFilePtr) {
  1056. *oldFilePtr = 0;
  1057. }
  1058. newParams.FullFileSpec = JoinPaths (oldFileSpec, reqFile->ReqFilePath);
  1059. FreePathString (oldFileSpec);
  1060. newParams.Extension = GetFileExtensionFromPath (reqFile->ReqFilePath);
  1061. findHandle = FindFirstFile (newParams.FullFileSpec, &findData);
  1062. if (findHandle == INVALID_HANDLE_VALUE) {
  1063. result = FALSE;
  1064. break;
  1065. }
  1066. newParams.IsDirectory = ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
  1067. newParams.FindData = &findData;
  1068. newParams.VirtualFile = FALSE;
  1069. newParams.CurrentDirData = AttribParams->FileParams->CurrentDirData;
  1070. reqFileAttribs.FileParams = &newParams;
  1071. reqFileAttribs.ExtraData = NULL;
  1072. migDbAttrib = reqFile->FileAttribs;
  1073. while (migDbAttrib) {
  1074. if (!CallAttribute (migDbAttrib, &reqFileAttribs)) {
  1075. result = FALSE;
  1076. break;
  1077. }
  1078. migDbAttrib = migDbAttrib->Next;
  1079. }
  1080. if (newParams.FullFileSpec) {
  1081. FreePathString (newParams.FullFileSpec);
  1082. newParams.FullFileSpec = NULL;
  1083. }
  1084. if (migDbAttrib == NULL) {
  1085. reqFileSeq ++;
  1086. _itoa (reqFileSeq, reqFileSeqStr, 10);
  1087. if (MemDbSetValueEx (
  1088. MEMDB_CATEGORY_REQFILES_MAIN,
  1089. AttribParams->FileParams->FullFileSpec,
  1090. reqFileSeqStr,
  1091. NULL,
  1092. 0,
  1093. NULL
  1094. )) {
  1095. MemDbSetValueEx (
  1096. MEMDB_CATEGORY_REQFILES_ADDNL,
  1097. reqFileSeqStr,
  1098. reqFile->ReqFilePath,
  1099. NULL,
  1100. 0,
  1101. NULL
  1102. );
  1103. }
  1104. }
  1105. reqFile = reqFile->Next;
  1106. }
  1107. if (newParams.FullFileSpec) {
  1108. FreePathString (newParams.FullFileSpec);
  1109. }
  1110. return result;
  1111. }
  1112. BOOL
  1113. pHexMatch (
  1114. IN DWORD NewValue,
  1115. IN PCSTR Args
  1116. )
  1117. {
  1118. DWORD oldValue;
  1119. if (!sscanf (Args, "%lx", &oldValue)) {
  1120. DEBUGMSG ((DBG_ERROR, "pHexMatch: Invalid argument value (%s) in migdb.inf", Args));
  1121. return FALSE;
  1122. }
  1123. if (oldValue == NewValue) {
  1124. return TRUE;
  1125. }
  1126. else {
  1127. return (_atoi64 (Args) == NewValue);
  1128. }
  1129. }
  1130. BOOL
  1131. pConvertDotStringToValue (
  1132. IN PCSTR String,
  1133. OUT ULONGLONG *Value
  1134. )
  1135. {
  1136. PWORD valueIdx;
  1137. UINT index;
  1138. valueIdx = (PWORD) Value + 3;
  1139. for (index = 0 ; index < 4 ; index++) {
  1140. if (*String == 0) {
  1141. *valueIdx = 0xFFFF;
  1142. valueIdx--;
  1143. continue;
  1144. }
  1145. *valueIdx = (WORD) strtoul (String, &(PSTR) String, 10);
  1146. if (*String && (_mbsnextc (String) != '.')) {
  1147. return FALSE;
  1148. }
  1149. String = _mbsinc (String);
  1150. valueIdx--;
  1151. }
  1152. return TRUE;
  1153. }
  1154. BOOL
  1155. pMaskHexMatch (
  1156. IN ULONGLONG NewValue,
  1157. IN PCSTR Args
  1158. )
  1159. {
  1160. ULONGLONG oldValue = 0;
  1161. ULONGLONG mask = 0;
  1162. PWORD maskIdx;
  1163. PWORD valueIdx;
  1164. UINT index;
  1165. maskIdx = (PWORD)&mask + 3;
  1166. valueIdx = (PWORD)&oldValue + 3;
  1167. index = 0;
  1168. while (Args && *Args) {
  1169. if (index >= 4) {
  1170. return FALSE;
  1171. }
  1172. *valueIdx = (WORD) strtoul ((PSTR)Args, &((PSTR)Args), 10);
  1173. if (*Args) {
  1174. if (_mbsnextc (Args) != '.') {
  1175. return FALSE;
  1176. }
  1177. Args = _mbsinc (Args);
  1178. }
  1179. *maskIdx = 65535;
  1180. valueIdx--;
  1181. maskIdx--;
  1182. index++;
  1183. }
  1184. NewValue = NewValue & mask;
  1185. return (oldValue == NewValue);
  1186. }
  1187. BOOL
  1188. BinFileVer (
  1189. IN PDBATTRIB_PARAMS AttribParams,
  1190. IN PCSTR Args
  1191. )
  1192. {
  1193. return pMaskHexMatch (GetBinFileVer (AttribParams->FileParams->FullFileSpec), Args);
  1194. }
  1195. BOOL
  1196. BinProductVer (
  1197. IN PDBATTRIB_PARAMS AttribParams,
  1198. IN PCSTR Args
  1199. )
  1200. {
  1201. return pMaskHexMatch (GetBinProductVer (AttribParams->FileParams->FullFileSpec), Args);
  1202. }
  1203. BOOL
  1204. FileDateHi (
  1205. IN PDBATTRIB_PARAMS AttribParams,
  1206. IN PCSTR Args
  1207. )
  1208. {
  1209. return pHexMatch (GetFileDateHi (AttribParams->FileParams->FullFileSpec), Args);
  1210. }
  1211. BOOL
  1212. FileDateLo (
  1213. IN PDBATTRIB_PARAMS AttribParams,
  1214. IN PCSTR Args
  1215. )
  1216. {
  1217. return pHexMatch (GetFileDateLo (AttribParams->FileParams->FullFileSpec), Args);
  1218. }
  1219. BOOL
  1220. FileVerOs (
  1221. IN PDBATTRIB_PARAMS AttribParams,
  1222. IN PCSTR Args
  1223. )
  1224. {
  1225. return pHexMatch (GetFileVerOs (AttribParams->FileParams->FullFileSpec), Args);
  1226. }
  1227. BOOL
  1228. FileVerType (
  1229. IN PDBATTRIB_PARAMS AttribParams,
  1230. IN PCSTR Args
  1231. )
  1232. {
  1233. return pHexMatch (GetFileVerType (AttribParams->FileParams->FullFileSpec), Args);
  1234. }
  1235. BOOL
  1236. UpToBinProductVer (
  1237. IN PDBATTRIB_PARAMS AttribParams,
  1238. IN PCSTR Args
  1239. )
  1240. {
  1241. VERSION_STRUCT Version;
  1242. ULONGLONG versionStampValue = 0;
  1243. ULONGLONG maxValue;
  1244. if (CreateVersionStruct (&Version, AttribParams->FileParams->FullFileSpec)) {
  1245. versionStampValue = VerGetProductVer (&Version);
  1246. DestroyVersionStruct (&Version);
  1247. } else {
  1248. return FALSE;
  1249. }
  1250. if (!pConvertDotStringToValue (Args, &maxValue)) {
  1251. DEBUGMSG ((DBG_WHOOPS, "Invalid value of %s caused UpToBinProductVer to fail", Args));
  1252. return FALSE;
  1253. }
  1254. return versionStampValue <= maxValue;
  1255. }
  1256. BOOL
  1257. UpToBinFileVer (
  1258. IN PDBATTRIB_PARAMS AttribParams,
  1259. IN PCSTR Args
  1260. )
  1261. {
  1262. VERSION_STRUCT Version;
  1263. ULONGLONG versionStampValue = 0;
  1264. ULONGLONG maxValue;
  1265. if (CreateVersionStruct (&Version, AttribParams->FileParams->FullFileSpec)) {
  1266. versionStampValue = VerGetFileVer (&Version);
  1267. DestroyVersionStruct (&Version);
  1268. } else {
  1269. return FALSE;
  1270. }
  1271. if (!pConvertDotStringToValue (Args, &maxValue)) {
  1272. DEBUGMSG ((DBG_WHOOPS, "Invalid value of %s caused UpToBinFileVer to fail", Args));
  1273. return FALSE;
  1274. }
  1275. return versionStampValue <= maxValue;
  1276. }
  1277. BOOL
  1278. SectionKey (
  1279. IN PDBATTRIB_PARAMS AttribParams,
  1280. IN PCSTR Args
  1281. )
  1282. {
  1283. PSTR Section, Key;
  1284. PSTR Value = NULL;
  1285. CHAR Return[1024];
  1286. DWORD Count;
  1287. BOOL b = FALSE;
  1288. Section = DuplicateText (Args);
  1289. MYASSERT (Section);
  1290. Key = _mbschr (Section, '\\');
  1291. if (Key) {
  1292. *Key = 0;
  1293. Key++;
  1294. Value = _mbschr (Key, '\\');
  1295. if (Value) {
  1296. *Value = 0;
  1297. Value++;
  1298. }
  1299. }
  1300. Count = GetPrivateProfileString (
  1301. Section,
  1302. Key,
  1303. "",
  1304. Return,
  1305. sizeof (Return),
  1306. AttribParams->FileParams->FullFileSpec
  1307. );
  1308. if (Count > 0) {
  1309. if (!Value || StringIMatch (Value, Return)) {
  1310. b = TRUE;
  1311. }
  1312. }
  1313. FreeText (Section);
  1314. return b;
  1315. }
  1316. BOOL
  1317. IsItInstalled (
  1318. IN PDBATTRIB_PARAMS AttribParams,
  1319. IN PCSTR Args
  1320. )
  1321. {
  1322. TCHAR RegKey[MAX_REGISTRY_KEY] = "HKLM\\SOFTWARE\\Microsoft\\";
  1323. StringCat(RegKey, Args);
  1324. return RegKeyPresent(AttribParams, RegKey);
  1325. }
  1326. BOOL
  1327. HasUninstall (
  1328. IN PDBATTRIB_PARAMS AttribParams,
  1329. IN PCSTR Args
  1330. )
  1331. {
  1332. TCHAR RegKey[MAX_REGISTRY_KEY] = "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
  1333. StringCat(RegKey, Args);
  1334. StringCat(RegKey, TEXT("\\[UninstallString]"));
  1335. return RegKeyPresent(AttribParams, RegKey);
  1336. }
  1337. BOOL
  1338. RegKeyPresent (
  1339. IN PDBATTRIB_PARAMS AttribParams,
  1340. IN PCSTR Args
  1341. )
  1342. {
  1343. BOOL b = FALSE;
  1344. CHAR RegKey[MAX_REGISTRY_KEY];
  1345. CHAR RegValue[MAX_REGISTRY_VALUE_NAME];
  1346. BOOL HasValue;
  1347. INT Index;
  1348. PCSTR p;
  1349. BOOL IsHkr;
  1350. BOOL Present;
  1351. HKEY Key;
  1352. PBYTE Data;
  1353. HasValue = DecodeRegistryString (Args, RegKey, RegValue, NULL);
  1354. //
  1355. // Is this HKR?
  1356. //
  1357. Index = GetOffsetOfRootString (RegKey, NULL);
  1358. p = GetRootStringFromOffset (Index);
  1359. if (!p) {
  1360. DEBUGMSG ((DBG_WHOOPS, "Parse error: %s is not a valid key", Args));
  1361. return FALSE;
  1362. }
  1363. IsHkr = !StringICompare (p, "HKR") || !StringICompare (p, "HKEY_ROOT");
  1364. //
  1365. // Verify value is present
  1366. //
  1367. if (IsHkr) {
  1368. //
  1369. // Check global table for the root
  1370. //
  1371. if (!g_PerUserRegKeys) {
  1372. return FALSE;
  1373. }
  1374. if (HtFindStringAndData (g_PerUserRegKeys, Args, &Present)) {
  1375. b = Present;
  1376. }
  1377. ELSE_DEBUGMSG ((DBG_WHOOPS, "Arg %s is not in the HKR hash table", Args));
  1378. } else {
  1379. //
  1380. // Ping the registry
  1381. //
  1382. Key = OpenRegKeyStr (RegKey);
  1383. if (Key) {
  1384. if (HasValue) {
  1385. Data = GetRegValueData (Key, RegValue);
  1386. if (Data) {
  1387. b = TRUE;
  1388. MemFree (g_hHeap, 0, Data);
  1389. }
  1390. } else {
  1391. b = TRUE;
  1392. }
  1393. CloseRegKey (Key);
  1394. }
  1395. }
  1396. return b;
  1397. }
  1398. BOOL
  1399. AtLeastWin98 (
  1400. IN PDBATTRIB_PARAMS AttribParams,
  1401. IN PCSTR Args
  1402. )
  1403. {
  1404. return ISATLEASTWIN98();
  1405. }