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.

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