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.

658 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.Platform = Data->Platform;
  337. attribData.ScriptSpecifiedType = scriptObjectType;
  338. attribData.ScriptSpecifiedObject = scriptObjectName;
  339. attribData.ApplicationName = Data->ApplicationName;
  340. if (!AllocScriptType (&attribData)) {
  341. return FALSE;
  342. }
  343. // let's persist the object in VCM mode so we can look at it later
  344. if (g_VcmMode && attribData.ObjectName) {
  345. if (IsmDoesObjectExist (attribData.ObjectTypeId, attribData.ObjectName)) {
  346. IsmMakePersistentObject (attribData.ObjectTypeId, attribData.ObjectName);
  347. }
  348. }
  349. if (Data->ObjectContent && attribData.ObjectContent) {
  350. if (Data->ObjectContent->ObjectTypeId == attribData.ObjectContent->ObjectTypeId) {
  351. if (Data->ObjectContent->Details.DetailsSize == attribData.ObjectContent->Details.DetailsSize) {
  352. if (!Data->ObjectContent->Details.DetailsSize ||
  353. TestBuffer (
  354. Data->ObjectContent->Details.DetailsData,
  355. attribData.ObjectContent->Details.DetailsData,
  356. Data->ObjectContent->Details.DetailsSize
  357. )
  358. ) {
  359. if (Data->ObjectContent->ContentInFile == attribData.ObjectContent->ContentInFile) {
  360. if (Data->ObjectContent->ContentInFile) {
  361. if (StringIMatch (
  362. Data->ObjectContent->FileContent.ContentPath,
  363. attribData.ObjectContent->FileContent.ContentPath
  364. )
  365. ) {
  366. result = TRUE;
  367. }
  368. } else {
  369. if (Data->ObjectContent->MemoryContent.ContentSize == attribData.ObjectContent->MemoryContent.ContentSize) {
  370. if (!Data->ObjectContent->MemoryContent.ContentSize ||
  371. TestBuffer (
  372. Data->ObjectContent->MemoryContent.ContentBytes,
  373. attribData.ObjectContent->MemoryContent.ContentBytes,
  374. Data->ObjectContent->MemoryContent.ContentSize
  375. )
  376. ) {
  377. result = TRUE;
  378. }
  379. }
  380. }
  381. }
  382. }
  383. }
  384. }
  385. }
  386. FreeScriptType (&attribData);
  387. return result;
  388. }
  389. BOOL
  390. pIsRegFlagSet (
  391. IN PCTSTR FunctionArguments,
  392. IN PATTRIB_DATA Data
  393. )
  394. {
  395. DWORD inValue;
  396. DWORD value;
  397. if (!Data) {
  398. return FALSE;
  399. }
  400. if (!FunctionArguments) {
  401. return FALSE;
  402. }
  403. if (!Data->ObjectContent) {
  404. return FALSE;
  405. }
  406. if ((Data->ObjectContent->ObjectTypeId & ~PLATFORM_MASK) != MIG_REGISTRY_TYPE) {
  407. return FALSE;
  408. }
  409. if (Data->ObjectContent->Details.DetailsSize != sizeof (DWORD)) {
  410. return FALSE;
  411. }
  412. if ((*((PDWORD)(Data->ObjectContent->Details.DetailsData)) != REG_DWORD) &&
  413. (*((PDWORD)(Data->ObjectContent->Details.DetailsData)) != REG_SZ)
  414. ) {
  415. return FALSE;
  416. }
  417. if (Data->ObjectContent->ContentInFile) {
  418. return FALSE;
  419. }
  420. if (Data->ObjectContent->MemoryContent.ContentSize == 0) {
  421. return FALSE;
  422. }
  423. if (Data->ObjectContent->MemoryContent.ContentBytes == NULL) {
  424. return FALSE;
  425. }
  426. if (*((PDWORD)(Data->ObjectContent->Details.DetailsData)) == REG_DWORD) {
  427. inValue = *((PDWORD)(Data->ObjectContent->MemoryContent.ContentBytes));
  428. } else {
  429. _stscanf ((PCTSTR)Data->ObjectContent->MemoryContent.ContentBytes, TEXT("%ld"), &inValue);
  430. }
  431. _stscanf (FunctionArguments, TEXT("%lx"), &value);
  432. if (!(inValue & value)) {
  433. return FALSE;
  434. }
  435. return TRUE;
  436. }
  437. BOOL
  438. pMatches (
  439. IN PCTSTR FunctionArguments,
  440. IN PATTRIB_DATA Data
  441. )
  442. {
  443. if (!Data->ReturnString) {
  444. return FALSE;
  445. }
  446. return (StringIMatch (FunctionArguments, Data->ReturnString));
  447. }
  448. BOOL
  449. pSetPersistFlag (
  450. IN PCTSTR FunctionArguments,
  451. IN PATTRIB_DATA Data
  452. )
  453. {
  454. if (IsmDoesObjectExist (Data->ObjectTypeId, Data->ObjectName)) {
  455. IsmMakePersistentObject (Data->ObjectTypeId, Data->ObjectName);
  456. }
  457. return TRUE;
  458. }
  459. BOOL
  460. pNotEmpty (
  461. IN PCTSTR FunctionArguments,
  462. IN PATTRIB_DATA Data
  463. )
  464. {
  465. if (!Data->ReturnString) {
  466. return FALSE;
  467. }
  468. return (Data->ReturnString[0] != 0);
  469. }
  470. BOOL
  471. pVersion (
  472. IN PCTSTR FunctionArguments,
  473. IN PATTRIB_DATA Data
  474. )
  475. {
  476. PCTSTR versionStr = NULL;
  477. PCTSTR versionValue = NULL;
  478. ATTRIB_DATA attribData;
  479. BOOL result = FALSE;
  480. versionStr = FunctionArguments;
  481. if (!versionStr) {
  482. return FALSE;
  483. }
  484. versionValue = GetEndOfString (FunctionArguments);
  485. if (!versionValue) {
  486. return FALSE;
  487. }
  488. versionValue ++;
  489. if (!Data) {
  490. return FALSE;
  491. }
  492. if (!Data->ReturnString) {
  493. return FALSE;
  494. }
  495. ZeroMemory (&attribData, sizeof (ATTRIB_DATA));
  496. attribData.Platform = Data->Platform;
  497. attribData.ScriptSpecifiedType = TEXT("File");
  498. attribData.ScriptSpecifiedObject = Data->ReturnString;
  499. attribData.ApplicationName = Data->ApplicationName;
  500. if (!AllocScriptType (&attribData)) {
  501. return FALSE;
  502. }
  503. // let's persist the object in VCM mode so we can look at it later
  504. if (g_VcmMode && attribData.ObjectName) {
  505. if (IsmDoesObjectExist (attribData.ObjectTypeId, attribData.ObjectName)) {
  506. IsmMakePersistentObject (attribData.ObjectTypeId, attribData.ObjectName);
  507. }
  508. }
  509. if (attribData.ObjectContent &&
  510. attribData.ObjectContent->ContentInFile &&
  511. attribData.ObjectContent->FileContent.ContentPath
  512. ) {
  513. result = VrCheckFileVersion (attribData.ObjectContent->FileContent.ContentPath, versionStr, versionValue);
  514. }
  515. FreeScriptType (&attribData);
  516. return result;
  517. }