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.

656 lines
16 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. attrib.c
  5. Abstract:
  6. Implements the v1 script application attributes.
  7. Author:
  8. Jim Schmidt (jimschm) 08-Jun-2000
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include "v1p.h"
  17. #define DBG_ATTRIB "Attrib"
  18. //
  19. // Strings
  20. //
  21. // None
  22. //
  23. // Constants
  24. //
  25. // None
  26. //
  27. // Macros
  28. //
  29. // None
  30. //
  31. // Types
  32. //
  33. typedef struct _MIGDB_ATTRIB {
  34. INT AttribIndex;
  35. UINT ArgCount;
  36. PCTSTR Arguments;
  37. BOOL NotOperator;
  38. struct _MIGDB_ATTRIB *Next;
  39. } MIGDB_ATTRIB, *PMIGDB_ATTRIB;
  40. typedef BOOL(ATTRIBUTE_FUNCTION)(PCTSTR ArgMultiSz, PATTRIB_DATA Content);
  41. typedef ATTRIBUTE_FUNCTION *PATTRIBUTE_FUNCTION;
  42. typedef struct {
  43. PCTSTR AttributeName;
  44. PATTRIBUTE_FUNCTION Function;
  45. UINT RequiredArgs;
  46. } ATTRIBUTE_FUNCTION_ITEM, *PATTRIBUTE_FUNCTION_ITEM;
  47. //
  48. // Globals
  49. //
  50. extern BOOL g_VcmMode; // in sgmqueue.c
  51. //
  52. // Macro expansion list
  53. //
  54. #define ATTRIBUTE_LIST \
  55. DEFMAC(EXISTS, pExists, 0) \
  56. DEFMAC(SAMEOBJECTNAME, pSameObjectName, 1) \
  57. DEFMAC(SAMEOBJECTCONTENT, pSameObjectContent, 2) \
  58. DEFMAC(ISREGFLAGSET, pIsRegFlagSet, 1) \
  59. DEFMAC(MATCHES, pMatches, 1) \
  60. DEFMAC(SET_PERSIST_FLAG, pSetPersistFlag, 0) \
  61. DEFMAC(NOTEMPTY, pNotEmpty, 0) \
  62. DEFMAC(VERSION, pVersion, 2) \
  63. //
  64. // Private function prototypes
  65. //
  66. // None
  67. //
  68. // Macro expansion definition
  69. //
  70. #define DEFMAC(name,fn,req_args) ATTRIBUTE_FUNCTION fn;
  71. ATTRIBUTE_LIST
  72. #undef DEFMAC
  73. #define DEFMAC(name,fn,req_args) TEXT(#name), fn, req_args,
  74. ATTRIBUTE_FUNCTION_ITEM g_FnList[] = {
  75. ATTRIBUTE_LIST /* , */
  76. NULL, NULL, 0
  77. };
  78. //
  79. // Code
  80. //
  81. #define STATE_ATTRNAME 1
  82. #define STATE_ATTRARG 2
  83. INT
  84. pGetAttribIndex (
  85. IN PCTSTR AttribName
  86. )
  87. /*++
  88. Routine Description:
  89. This routine returns the index in attribute functions array for a specified
  90. attribute.
  91. Arguments:
  92. AttribName - Attribute name
  93. Return value:
  94. -1 - no such attribute in attribute table
  95. --*/
  96. {
  97. INT attribIndex;
  98. INT rc = 0;
  99. PTSTR attrEnd = NULL;
  100. TCHAR savedChar = 0;
  101. attrEnd = (PTSTR) SkipSpaceR (AttribName, GetEndOfString (AttribName));
  102. if (attrEnd != NULL) {
  103. attrEnd = _tcsinc (attrEnd);
  104. savedChar = attrEnd [0];
  105. attrEnd [0] = 0;
  106. }
  107. __try {
  108. for (attribIndex = 0 ; g_FnList[attribIndex].AttributeName ; attribIndex++) {
  109. if (StringIMatch (g_FnList[attribIndex].AttributeName, AttribName)) {
  110. break;
  111. }
  112. }
  113. if (!g_FnList[attribIndex].AttributeName) {
  114. attribIndex = -1;
  115. LOG ((LOG_ERROR, (PCSTR) MSG_DETECT_ATTRIB_NOT_FOUND, AttribName));
  116. }
  117. rc = attribIndex;
  118. }
  119. __finally {
  120. if (attrEnd != NULL) {
  121. attrEnd [0] = savedChar;
  122. }
  123. }
  124. return rc;
  125. }
  126. UINT
  127. pGetReqArgCount (
  128. IN INT AttributeIndex
  129. )
  130. {
  131. if (AttributeIndex < 0 || AttributeIndex > ARRAYSIZE(g_FnList)) {
  132. return 0;
  133. }
  134. return g_FnList[AttributeIndex].RequiredArgs;
  135. }
  136. BOOL
  137. pValidateArg (
  138. IN OUT PMIGDB_ATTRIB AttribStruct
  139. )
  140. {
  141. //
  142. // Validate all AttribStruct members
  143. //
  144. MYASSERT (AttribStruct);
  145. if (AttribStruct->ArgCount != pGetReqArgCount (AttribStruct->AttribIndex)) {
  146. AttribStruct->AttribIndex = -1;
  147. return FALSE;
  148. }
  149. return TRUE;
  150. }
  151. PMIGDB_ATTRIB
  152. pLoadAttribData (
  153. IN PMHANDLE Pool,
  154. IN PCTSTR MultiSzStr
  155. )
  156. /*++
  157. Routine Description:
  158. This routine creates a list of MIGDB_ATTRIBs from a multisz.
  159. Arguments:
  160. Pool - Specifies a pool that temporary structures and the return value
  161. will be allocated from
  162. MultiSzStr - Specifies the multisz to be processed. The multi-sz must
  163. be in the form of ATTRIB or ATTRIB(arg[,arg,...])
  164. Return value:
  165. MIGDB_ATTRIB nodes
  166. --*/
  167. {
  168. MULTISZ_ENUM multiSzEnum;
  169. PMIGDB_ATTRIB result = NULL;
  170. PMIGDB_ATTRIB tmpAttr = NULL;
  171. INT state = STATE_ATTRNAME;
  172. PTSTR currStrPtr = NULL;
  173. PTSTR currArgPtr = NULL;
  174. PTSTR endArgPtr = NULL;
  175. TCHAR savedChar = 0;
  176. GROWBUFFER argList = INIT_GROWBUFFER;
  177. if (EnumFirstMultiSz (&multiSzEnum, MultiSzStr)) {
  178. do {
  179. currStrPtr = (PTSTR) SkipSpace (multiSzEnum.CurrentString);
  180. if (state == STATE_ATTRNAME) {
  181. tmpAttr = (PMIGDB_ATTRIB) PmGetMemory (Pool, sizeof (MIGDB_ATTRIB));
  182. ZeroMemory (tmpAttr, sizeof (MIGDB_ATTRIB));
  183. if (_tcsnextc (currStrPtr) == TEXT('!')) {
  184. currStrPtr = _tcsinc (currStrPtr);
  185. currStrPtr = (PTSTR) SkipSpace (currStrPtr);
  186. tmpAttr->NotOperator = TRUE;
  187. }
  188. currArgPtr = _tcschr (currStrPtr, TEXT('('));
  189. if (currArgPtr) {
  190. endArgPtr = _tcsdec (currStrPtr, currArgPtr);
  191. if (endArgPtr) {
  192. endArgPtr = (PTSTR) SkipSpaceR (currStrPtr, endArgPtr);
  193. endArgPtr = _tcsinc (endArgPtr);
  194. }
  195. else {
  196. endArgPtr = currStrPtr;
  197. }
  198. savedChar = *endArgPtr;
  199. *endArgPtr = 0;
  200. tmpAttr->AttribIndex = pGetAttribIndex (currStrPtr);
  201. *endArgPtr = savedChar;
  202. currStrPtr = _tcsinc (currArgPtr);
  203. state = STATE_ATTRARG;
  204. }
  205. else {
  206. // this attribute has no arguments.
  207. tmpAttr->AttribIndex = pGetAttribIndex (currStrPtr);
  208. tmpAttr->Next = result;
  209. result = tmpAttr;
  210. pValidateArg (result);
  211. continue;
  212. }
  213. }
  214. if (state == STATE_ATTRARG) {
  215. currStrPtr = (PTSTR) SkipSpace (currStrPtr);
  216. endArgPtr = _tcsrchr (currStrPtr, TEXT(')'));
  217. if (endArgPtr && endArgPtr[1] == 0) {
  218. endArgPtr = _tcsdec (currStrPtr, endArgPtr);
  219. if (endArgPtr) {
  220. endArgPtr = (PTSTR) SkipSpaceR (currStrPtr, endArgPtr);
  221. endArgPtr = _tcsinc (endArgPtr);
  222. }
  223. else {
  224. endArgPtr = currStrPtr;
  225. }
  226. savedChar = *endArgPtr;
  227. *endArgPtr = 0;
  228. } else {
  229. endArgPtr = NULL;
  230. }
  231. GbMultiSzAppend (&argList, currStrPtr);
  232. tmpAttr->ArgCount++;
  233. if (endArgPtr) {
  234. *endArgPtr = savedChar;
  235. tmpAttr->Arguments = PmDuplicateMultiSz (Pool, (PTSTR) argList.Buf);
  236. GbFree (&argList);
  237. state = STATE_ATTRNAME;
  238. tmpAttr->Next = result;
  239. result = tmpAttr;
  240. pValidateArg (result);
  241. }
  242. }
  243. } while (EnumNextMultiSz (&multiSzEnum));
  244. }
  245. return result;
  246. }
  247. BOOL
  248. TestAttributes (
  249. IN PMHANDLE WorkPool,
  250. IN PCTSTR ArgumentMultiSz,
  251. IN PATTRIB_DATA AttribData
  252. )
  253. /*++
  254. Routine Description:
  255. TestAttributes executes the attribute functions specified in the
  256. ArgumentMultiSz parameter. Each argument is tested until they all succeed
  257. or until one fails.
  258. Arguments:
  259. WorkPool - Specifies a pool handle for fast allocations
  260. ArgumentMultiSz - Specifies the multi-sz that contains argument
  261. specifications
  262. AttribData - Specifies the object name, script specifications and
  263. object content
  264. Return Value:
  265. TRUE if all attributes pass (or if zero attributes were specified), FALSE
  266. otherwise.
  267. --*/
  268. {
  269. PMIGDB_ATTRIB attrib;
  270. PMIGDB_ATTRIB tmpAttrib;
  271. BOOL result = TRUE;
  272. attrib = pLoadAttribData (WorkPool, ArgumentMultiSz);
  273. tmpAttrib = attrib;
  274. while (result && attrib) {
  275. if (attrib->AttribIndex < 0 || attrib->AttribIndex >= ARRAYSIZE(g_FnList)) {
  276. DEBUGMSG ((DBG_WHOOPS, "Invalid attribute index %i", attrib->AttribIndex));
  277. result = FALSE;
  278. } else {
  279. result = g_FnList[attrib->AttribIndex].Function (attrib->Arguments, AttribData);
  280. if (attrib->NotOperator) {
  281. result = !result;
  282. }
  283. }
  284. attrib = attrib->Next;
  285. }
  286. // now free the attribute list
  287. attrib = tmpAttrib;
  288. while (attrib) {
  289. tmpAttrib = attrib->Next;
  290. if (attrib->Arguments) {
  291. PmReleaseMemory (WorkPool, attrib->Arguments);
  292. }
  293. PmReleaseMemory (WorkPool, attrib);
  294. attrib = tmpAttrib;
  295. }
  296. return result;
  297. }
  298. //
  299. // Attribute functions (see ATTRIBUTE_LIST)
  300. //
  301. BOOL
  302. pExists (
  303. IN PCTSTR FunctionArguments,
  304. IN PATTRIB_DATA Data
  305. )
  306. {
  307. return (Data->ReturnString != NULL);
  308. }
  309. BOOL
  310. pSameObjectName (
  311. IN PCTSTR FunctionArguments,
  312. IN PATTRIB_DATA Data
  313. )
  314. {
  315. return (StringIMatch (FunctionArguments, Data->ScriptSpecifiedObject));
  316. }
  317. BOOL
  318. pSameObjectContent (
  319. IN PCTSTR FunctionArguments,
  320. IN PATTRIB_DATA Data
  321. )
  322. {
  323. PCTSTR scriptObjectType = NULL;
  324. PCTSTR scriptObjectName = NULL;
  325. ATTRIB_DATA attribData;
  326. BOOL result = FALSE;
  327. scriptObjectType = FunctionArguments;
  328. scriptObjectName = GetEndOfString (FunctionArguments);
  329. if (scriptObjectName) {
  330. scriptObjectName ++;
  331. }
  332. if (!scriptObjectType || !scriptObjectName) {
  333. return FALSE;
  334. }
  335. ZeroMemory (&attribData, sizeof (ATTRIB_DATA));
  336. attribData.ScriptSpecifiedType = scriptObjectType;
  337. attribData.ScriptSpecifiedObject = scriptObjectName;
  338. attribData.ApplicationName = Data->ApplicationName;
  339. if (!AllocScriptType (&attribData)) {
  340. return FALSE;
  341. }
  342. // let's persist the object in VCM mode so we can look at it later
  343. if (g_VcmMode && attribData.ObjectName) {
  344. if (IsmDoesObjectExist (attribData.ObjectTypeId, attribData.ObjectName)) {
  345. IsmMakePersistentObject (attribData.ObjectTypeId, attribData.ObjectName);
  346. }
  347. }
  348. if (Data->ObjectContent && attribData.ObjectContent) {
  349. if (Data->ObjectContent->ObjectTypeId == attribData.ObjectContent->ObjectTypeId) {
  350. if (Data->ObjectContent->Details.DetailsSize == attribData.ObjectContent->Details.DetailsSize) {
  351. if (!Data->ObjectContent->Details.DetailsSize ||
  352. TestBuffer (
  353. Data->ObjectContent->Details.DetailsData,
  354. attribData.ObjectContent->Details.DetailsData,
  355. Data->ObjectContent->Details.DetailsSize
  356. )
  357. ) {
  358. if (Data->ObjectContent->ContentInFile == attribData.ObjectContent->ContentInFile) {
  359. if (Data->ObjectContent->ContentInFile) {
  360. if (StringIMatch (
  361. Data->ObjectContent->FileContent.ContentPath,
  362. attribData.ObjectContent->FileContent.ContentPath
  363. )
  364. ) {
  365. result = TRUE;
  366. }
  367. } else {
  368. if (Data->ObjectContent->MemoryContent.ContentSize == attribData.ObjectContent->MemoryContent.ContentSize) {
  369. if (!Data->ObjectContent->MemoryContent.ContentSize ||
  370. TestBuffer (
  371. Data->ObjectContent->MemoryContent.ContentBytes,
  372. attribData.ObjectContent->MemoryContent.ContentBytes,
  373. Data->ObjectContent->MemoryContent.ContentSize
  374. )
  375. ) {
  376. result = TRUE;
  377. }
  378. }
  379. }
  380. }
  381. }
  382. }
  383. }
  384. }
  385. FreeScriptType (&attribData);
  386. return result;
  387. }
  388. BOOL
  389. pIsRegFlagSet (
  390. IN PCTSTR FunctionArguments,
  391. IN PATTRIB_DATA Data
  392. )
  393. {
  394. DWORD inValue;
  395. DWORD value;
  396. if (!Data) {
  397. return FALSE;
  398. }
  399. if (!FunctionArguments) {
  400. return FALSE;
  401. }
  402. if (!Data->ObjectContent) {
  403. return FALSE;
  404. }
  405. if ((Data->ObjectContent->ObjectTypeId & ~PLATFORM_MASK) != MIG_REGISTRY_TYPE) {
  406. return FALSE;
  407. }
  408. if (Data->ObjectContent->Details.DetailsSize != sizeof (DWORD)) {
  409. return FALSE;
  410. }
  411. if ((*((PDWORD)(Data->ObjectContent->Details.DetailsData)) != REG_DWORD) &&
  412. (*((PDWORD)(Data->ObjectContent->Details.DetailsData)) != REG_SZ)
  413. ) {
  414. return FALSE;
  415. }
  416. if (Data->ObjectContent->ContentInFile) {
  417. return FALSE;
  418. }
  419. if (Data->ObjectContent->MemoryContent.ContentSize == 0) {
  420. return FALSE;
  421. }
  422. if (Data->ObjectContent->MemoryContent.ContentBytes == NULL) {
  423. return FALSE;
  424. }
  425. if (*((PDWORD)(Data->ObjectContent->Details.DetailsData)) == REG_DWORD) {
  426. inValue = *((PDWORD)(Data->ObjectContent->MemoryContent.ContentBytes));
  427. } else {
  428. _stscanf ((PCTSTR)Data->ObjectContent->MemoryContent.ContentBytes, TEXT("%ld"), &inValue);
  429. }
  430. _stscanf (FunctionArguments, TEXT("%lx"), &value);
  431. if (!(inValue & value)) {
  432. return FALSE;
  433. }
  434. return TRUE;
  435. }
  436. BOOL
  437. pMatches (
  438. IN PCTSTR FunctionArguments,
  439. IN PATTRIB_DATA Data
  440. )
  441. {
  442. if (!Data->ReturnString) {
  443. return FALSE;
  444. }
  445. return (StringIMatch (FunctionArguments, Data->ReturnString));
  446. }
  447. BOOL
  448. pSetPersistFlag (
  449. IN PCTSTR FunctionArguments,
  450. IN PATTRIB_DATA Data
  451. )
  452. {
  453. if (IsmDoesObjectExist (Data->ObjectTypeId, Data->ObjectName)) {
  454. IsmMakePersistentObject (Data->ObjectTypeId, Data->ObjectName);
  455. }
  456. return TRUE;
  457. }
  458. BOOL
  459. pNotEmpty (
  460. IN PCTSTR FunctionArguments,
  461. IN PATTRIB_DATA Data
  462. )
  463. {
  464. if (!Data->ReturnString) {
  465. return FALSE;
  466. }
  467. return (Data->ReturnString[0] != 0);
  468. }
  469. BOOL
  470. pVersion (
  471. IN PCTSTR FunctionArguments,
  472. IN PATTRIB_DATA Data
  473. )
  474. {
  475. PCTSTR versionStr = NULL;
  476. PCTSTR versionValue = NULL;
  477. ATTRIB_DATA attribData;
  478. BOOL result = FALSE;
  479. versionStr = FunctionArguments;
  480. if (!versionStr) {
  481. return FALSE;
  482. }
  483. versionValue = GetEndOfString (FunctionArguments);
  484. if (!versionValue) {
  485. return FALSE;
  486. }
  487. versionValue ++;
  488. if (!Data) {
  489. return FALSE;
  490. }
  491. if (!Data->ReturnString) {
  492. return FALSE;
  493. }
  494. ZeroMemory (&attribData, sizeof (ATTRIB_DATA));
  495. attribData.ScriptSpecifiedType = TEXT("File");
  496. attribData.ScriptSpecifiedObject = Data->ReturnString;
  497. attribData.ApplicationName = Data->ApplicationName;
  498. if (!AllocScriptType (&attribData)) {
  499. return FALSE;
  500. }
  501. // let's persist the object in VCM mode so we can look at it later
  502. if (g_VcmMode && attribData.ObjectName) {
  503. if (IsmDoesObjectExist (attribData.ObjectTypeId, attribData.ObjectName)) {
  504. IsmMakePersistentObject (attribData.ObjectTypeId, attribData.ObjectName);
  505. }
  506. }
  507. if (attribData.ObjectContent &&
  508. attribData.ObjectContent->ContentInFile &&
  509. attribData.ObjectContent->FileContent.ContentPath
  510. ) {
  511. result = VrCheckFileVersion (attribData.ObjectContent->FileContent.ContentPath, versionStr, versionValue);
  512. }
  513. FreeScriptType (&attribData);
  514. return result;
  515. }