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.

1510 lines
48 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. sgmcallback.c
  5. Abstract:
  6. Implements the callbacks that are queued in sgmqueue.c.
  7. Author:
  8. Jim Schmidt (jimschm) 12-Mar-2000
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include "v1p.h"
  17. #define DBG_SCRIPT "Script"
  18. //
  19. // Strings
  20. //
  21. // None
  22. //
  23. // Constants
  24. //
  25. // None
  26. //
  27. // Macros
  28. //
  29. // None
  30. //
  31. // Types
  32. //
  33. // None
  34. //
  35. // Globals
  36. //
  37. // None
  38. //
  39. // Macro expansion list
  40. //
  41. // None
  42. //
  43. // Private function prototypes
  44. //
  45. // None
  46. //
  47. // Macro expansion definition
  48. //
  49. // None
  50. //
  51. // Code
  52. //
  53. MIG_OBJECTSTRINGHANDLE
  54. pSimpleTryHandle (
  55. IN PCTSTR FullPath,
  56. IN BOOL Recursive
  57. )
  58. {
  59. DWORD attribs;
  60. PCTSTR buffer;
  61. PTSTR leafPtr, leaf;
  62. MIG_OBJECTSTRINGHANDLE result = NULL;
  63. MIG_OBJECTSTRINGHANDLE longResult = NULL;
  64. PTSTR workingPath;
  65. PCTSTR sanitizedPath;
  66. PCTSTR longPath;
  67. PCTSTR objNode = NULL, objLeaf = NULL;
  68. sanitizedPath = SanitizePath (FullPath);
  69. if (!sanitizedPath) {
  70. return NULL;
  71. }
  72. if (IsmGetRealPlatform () == PLATFORM_SOURCE) {
  73. attribs = GetFileAttributes (sanitizedPath);
  74. } else {
  75. attribs = INVALID_ATTRIBUTES;
  76. }
  77. if (attribs != INVALID_ATTRIBUTES) {
  78. longPath = BfGetLongFileName (sanitizedPath);
  79. if (!longPath) {
  80. longPath = sanitizedPath;
  81. }
  82. if (attribs & FILE_ATTRIBUTE_DIRECTORY) {
  83. if (Recursive) {
  84. workingPath = DuplicatePathString (longPath, 0);
  85. RemoveWackAtEnd (workingPath);
  86. result = IsmCreateSimpleObjectPattern (workingPath, TRUE, NULL, TRUE);
  87. FreePathString (workingPath);
  88. } else {
  89. result = IsmCreateObjectHandle (longPath, NULL);
  90. }
  91. } else {
  92. buffer = DuplicatePathString (longPath, 0);
  93. leaf = _tcsrchr (buffer, TEXT('\\'));
  94. if (leaf) {
  95. leafPtr = leaf;
  96. leaf = _tcsinc (leaf);
  97. *leafPtr = 0;
  98. result = IsmCreateObjectHandle (buffer, leaf);
  99. }
  100. FreePathString (buffer);
  101. }
  102. if (longPath != sanitizedPath) {
  103. FreePathString (longPath);
  104. longPath = NULL;
  105. }
  106. } else {
  107. result = IsmCreateObjectHandle (sanitizedPath, NULL);
  108. if (result) {
  109. longResult = IsmGetLongName (MIG_FILE_TYPE|PLATFORM_SOURCE, result);
  110. if (!longResult) {
  111. longResult = result;
  112. }
  113. if (IsmGetObjectIdFromName (g_FileType, longResult, TRUE)) {
  114. if (Recursive) {
  115. if (IsmCreateObjectStringsFromHandle (longResult, &objNode, &objLeaf)) {
  116. if (longResult != result) {
  117. IsmDestroyObjectHandle (longResult);
  118. longResult = NULL;
  119. }
  120. IsmDestroyObjectHandle (result);
  121. result = IsmCreateSimpleObjectPattern (objNode, TRUE, NULL, TRUE);
  122. IsmDestroyObjectString (objNode);
  123. IsmDestroyObjectString (objLeaf);
  124. }
  125. }
  126. return result;
  127. } else {
  128. if (longResult != result) {
  129. IsmDestroyObjectHandle (longResult);
  130. longResult = NULL;
  131. }
  132. IsmDestroyObjectHandle (result);
  133. result = NULL;
  134. }
  135. }
  136. if (!result) {
  137. buffer = DuplicatePathString (sanitizedPath, 0);
  138. leaf = _tcsrchr (buffer, TEXT('\\'));
  139. if (leaf) {
  140. leafPtr = leaf;
  141. leaf = _tcsinc (leaf);
  142. *leafPtr = 0;
  143. result = IsmCreateObjectHandle (buffer, leaf);
  144. }
  145. if (result) {
  146. longResult = IsmGetLongName (MIG_FILE_TYPE|PLATFORM_SOURCE, result);
  147. if (!longResult) {
  148. longResult = result;
  149. }
  150. if (!IsmGetObjectIdFromName (g_FileType, longResult, TRUE)) {
  151. if (longResult != result) {
  152. IsmDestroyObjectHandle (longResult);
  153. longResult = NULL;
  154. }
  155. IsmDestroyObjectHandle (result);
  156. result = NULL;
  157. }
  158. }
  159. if (result != longResult) {
  160. IsmDestroyObjectHandle (result);
  161. result = longResult;
  162. }
  163. FreePathString (buffer);
  164. }
  165. }
  166. FreePathString (sanitizedPath);
  167. return result;
  168. }
  169. MIG_OBJECTSTRINGHANDLE
  170. pTryHandle (
  171. IN PCTSTR FullPath,
  172. IN PCTSTR Hint,
  173. IN BOOL Recursive,
  174. OUT PBOOL HintUsed OPTIONAL
  175. )
  176. {
  177. PATH_ENUM pathEnum;
  178. PCTSTR newPath;
  179. MIG_OBJECTSTRINGHANDLE result = NULL;
  180. if (HintUsed) {
  181. *HintUsed = FALSE;
  182. }
  183. if (!(*FullPath)) {
  184. // nothing to do, not even the hint can help us
  185. return NULL;
  186. }
  187. result = pSimpleTryHandle (FullPath, Recursive);
  188. if (result || (!Hint)) {
  189. return result;
  190. }
  191. if (EnumFirstPathEx (&pathEnum, Hint, NULL, NULL, FALSE)) {
  192. do {
  193. newPath = JoinPaths (pathEnum.PtrCurrPath, FullPath);
  194. result = pSimpleTryHandle (newPath, Recursive);
  195. if (result) {
  196. AbortPathEnum (&pathEnum);
  197. FreePathString (newPath);
  198. if (HintUsed) {
  199. *HintUsed = TRUE;
  200. }
  201. return result;
  202. }
  203. FreePathString (newPath);
  204. } while (EnumNextPath (&pathEnum));
  205. }
  206. AbortPathEnum (&pathEnum);
  207. return NULL;
  208. }
  209. BOOL
  210. pOurFindFile (
  211. IN PCTSTR FileName
  212. )
  213. {
  214. DWORD attribs;
  215. PCTSTR buffer;
  216. PTSTR leafPtr, leaf;
  217. PTSTR workingPath;
  218. PCTSTR sanitizedPath;
  219. MIG_OBJECTSTRINGHANDLE test = NULL;
  220. BOOL result = FALSE;
  221. sanitizedPath = SanitizePath (FileName);
  222. if (sanitizedPath == NULL) {
  223. return FALSE;
  224. }
  225. if (IsmGetRealPlatform () == PLATFORM_SOURCE) {
  226. attribs = GetFileAttributes (sanitizedPath);
  227. } else {
  228. attribs = INVALID_ATTRIBUTES;
  229. }
  230. if (attribs != INVALID_ATTRIBUTES) {
  231. result = TRUE;
  232. } else {
  233. test = IsmCreateObjectHandle (sanitizedPath, NULL);
  234. if (IsmGetObjectIdFromName (g_FileType, test, TRUE)) {
  235. result = TRUE;
  236. }
  237. IsmDestroyObjectHandle (test);
  238. test = NULL;
  239. if (!result) {
  240. buffer = DuplicatePathString (sanitizedPath, 0);
  241. leaf = _tcsrchr (buffer, TEXT('\\'));
  242. if (leaf) {
  243. leafPtr = leaf;
  244. leaf = _tcsinc (leaf);
  245. *leafPtr = 0;
  246. test = IsmCreateObjectHandle (buffer, leaf);
  247. }
  248. if (test) {
  249. if (IsmGetObjectIdFromName (g_FileType, test, TRUE)) {
  250. result = TRUE;
  251. }
  252. IsmDestroyObjectHandle (test);
  253. test = NULL;
  254. }
  255. FreePathString (buffer);
  256. }
  257. }
  258. FreePathString (sanitizedPath);
  259. return result;
  260. }
  261. BOOL
  262. pOurSearchPath (
  263. IN PCTSTR FileName,
  264. IN DWORD BufferLength,
  265. OUT PTSTR Buffer
  266. )
  267. {
  268. TCHAR pathEnv[] = TEXT("%system%;%system16%;%windir%;%path%");
  269. PCTSTR pathExp = NULL;
  270. PCTSTR fileName = NULL;
  271. PATH_ENUM pathEnum;
  272. BOOL result = FALSE;
  273. pathExp = IsmExpandEnvironmentString (
  274. PLATFORM_SOURCE,
  275. S_SYSENVVAR_GROUP,
  276. pathEnv,
  277. NULL
  278. );
  279. if (pathExp) {
  280. if (EnumFirstPathEx (&pathEnum, pathExp, NULL, NULL, FALSE)) {
  281. do {
  282. fileName = JoinPaths (pathEnum.PtrCurrPath, FileName);
  283. result = pOurFindFile (fileName);
  284. if (result) {
  285. StringCopyTcharCount (Buffer, fileName, BufferLength);
  286. FreePathString (fileName);
  287. AbortPathEnum (&pathEnum);
  288. break;
  289. }
  290. FreePathString (fileName);
  291. } while (EnumNextPath (&pathEnum));
  292. }
  293. IsmReleaseMemory (pathExp);
  294. pathExp = NULL;
  295. }
  296. return result;
  297. }
  298. PCTSTR
  299. pGetObjectNameForDebug (
  300. IN MIG_OBJECTSTRINGHANDLE ObjectName
  301. )
  302. {
  303. static TCHAR debugBuffer[2048];
  304. PCTSTR node, leaf;
  305. IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf);
  306. if (node && leaf) {
  307. wsprintf (debugBuffer, TEXT("[Node:%s Leaf:%s]"), node, leaf);
  308. } else if (node) {
  309. wsprintf (debugBuffer, TEXT("[Node:%s]"), node);
  310. } else if (leaf) {
  311. wsprintf (debugBuffer, TEXT("[Leaf:%s]"), leaf);
  312. } else {
  313. StringCopy (debugBuffer, TEXT("[nul]"));
  314. }
  315. return debugBuffer;
  316. }
  317. VOID
  318. pSaveObjectAndFileItReferences (
  319. IN MIG_OBJECTTYPEID ObjectTypeId,
  320. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  321. IN PACTION_STRUCT RegActionStruct,
  322. IN BOOL VcmMode,
  323. IN BOOL Recursive
  324. )
  325. {
  326. MIG_CONTENT content;
  327. GROWBUFFER cmdLineBuffer = INIT_GROWBUFFER;
  328. PCMDLINE cmdLine;
  329. PTSTR pathData;
  330. PCTSTR p;
  331. PCTSTR end;
  332. PCTSTR expandPath = NULL;
  333. PCTSTR expandHint = NULL;
  334. UINT u;
  335. BOOL foundFile = FALSE;
  336. PDWORD valueType;
  337. MIG_OBJECTSTRINGHANDLE handle;
  338. MIG_OBJECTSTRINGHANDLE nodeHandle;
  339. BOOL parsable;
  340. BOOL firstPass = TRUE;
  341. ACTION_STRUCT actionStruct;
  342. DWORD actionFlags;
  343. BOOL hintUsed = FALSE;
  344. MIG_BLOB blob;
  345. PCTSTR node, leaf, filePattern;
  346. //
  347. // Obtain the object data
  348. //
  349. if (IsmAcquireObjectEx (ObjectTypeId, ObjectName, &content, CONTENTTYPE_MEMORY, 4096)) {
  350. //
  351. // Parse the data for a file
  352. //
  353. pathData = (PTSTR) content.MemoryContent.ContentBytes;
  354. parsable = FALSE;
  355. if ((ObjectTypeId & (~PLATFORM_MASK)) == g_RegType) {
  356. valueType = (PDWORD)(content.Details.DetailsData);
  357. if (valueType) {
  358. if (*valueType == REG_EXPAND_SZ ||
  359. *valueType == REG_SZ
  360. ) {
  361. parsable = TRUE;
  362. }
  363. } else {
  364. MYASSERT (IsmIsObjectHandleNodeOnly (ObjectName));
  365. }
  366. }
  367. if ((ObjectTypeId & (~PLATFORM_MASK)) == g_IniType) {
  368. parsable = TRUE;
  369. }
  370. if (parsable) {
  371. p = pathData;
  372. end = (PCTSTR) (content.MemoryContent.ContentBytes + content.MemoryContent.ContentSize);
  373. while (p < end) {
  374. if (*p == 0) {
  375. break;
  376. }
  377. p = _tcsinc (p);
  378. }
  379. if (p >= end) {
  380. pathData = NULL;
  381. }
  382. } else {
  383. pathData = NULL;
  384. }
  385. if (pathData) {
  386. //
  387. // Expand the data
  388. //
  389. expandPath = IsmExpandEnvironmentString (
  390. PLATFORM_SOURCE,
  391. S_SYSENVVAR_GROUP,
  392. pathData,
  393. NULL
  394. );
  395. pathData = (PTSTR)expandPath;
  396. if (RegActionStruct && RegActionStruct->ObjectHint) {
  397. expandHint = IsmExpandEnvironmentString (
  398. PLATFORM_SOURCE,
  399. S_SYSENVVAR_GROUP,
  400. RegActionStruct->ObjectHint,
  401. NULL
  402. );
  403. }
  404. // first we try it as is
  405. handle = pTryHandle (pathData, expandHint, Recursive, &hintUsed);
  406. if (handle) {
  407. ZeroMemory (&actionStruct, sizeof (ACTION_STRUCT));
  408. actionStruct.ObjectBase = handle;
  409. actionFlags = ACTION_PERSIST;
  410. if (RegActionStruct) {
  411. actionStruct.ObjectDest = RegActionStruct->AddnlDest;
  412. }
  413. if (Recursive) {
  414. // let's build the base handle but not from pathData,
  415. // because we might have used the hint field. Let's just
  416. // build it from the handle itself
  417. if (IsmCreateObjectStringsFromHandle (handle, &node, &leaf)) {
  418. filePattern = JoinPathsInPoolEx ((NULL, node, leaf, NULL));
  419. if (filePattern) {
  420. nodeHandle = TurnFileStringIntoHandle (
  421. filePattern,
  422. PFF_COMPUTE_BASE|
  423. PFF_NO_SUBDIR_PATTERN|
  424. PFF_NO_LEAF_AT_ALL
  425. );
  426. if (nodeHandle) {
  427. AddRule (
  428. g_FileType,
  429. nodeHandle,
  430. handle,
  431. ACTIONGROUP_INCFOLDER,
  432. actionFlags,
  433. &actionStruct
  434. );
  435. IsmQueueEnumeration (
  436. g_FileType,
  437. nodeHandle,
  438. VcmMode ? GatherVirtualComputer : PrepareActions,
  439. 0,
  440. NULL
  441. );
  442. IsmQueueEnumeration (
  443. g_FileType,
  444. handle,
  445. VcmMode ? GatherVirtualComputer : PrepareActions,
  446. 0,
  447. NULL
  448. );
  449. IsmDestroyObjectHandle (nodeHandle);
  450. } else {
  451. // Out of memory?
  452. LOG ((LOG_ERROR, (PCSTR)MSG_UNEXPECTED_ERROR));
  453. }
  454. FreePathString (filePattern);
  455. } else {
  456. // Out of memory?
  457. LOG ((LOG_ERROR, (PCSTR)MSG_UNEXPECTED_ERROR));
  458. }
  459. } else {
  460. // Out of memory?
  461. LOG ((LOG_ERROR, (PCSTR)MSG_UNEXPECTED_ERROR));
  462. }
  463. } else {
  464. AddRule (
  465. g_FileType,
  466. handle,
  467. handle,
  468. ACTIONGROUP_INCFILE,
  469. actionFlags,
  470. &actionStruct
  471. );
  472. IsmQueueEnumeration (
  473. g_FileType,
  474. handle,
  475. VcmMode ? GatherVirtualComputer : PrepareActions,
  476. 0,
  477. NULL
  478. );
  479. }
  480. foundFile = TRUE;
  481. IsmDestroyObjectHandle (handle);
  482. if (hintUsed && expandHint) {
  483. // we need to add extra data for the content fix operation
  484. blob.Type = BLOBTYPE_STRING;
  485. blob.String = expandHint;
  486. if ((ObjectTypeId & (~PLATFORM_MASK)) == g_RegType) {
  487. IsmSetOperationOnObject (
  488. ObjectTypeId,
  489. ObjectName,
  490. g_RegAutoFilterOp,
  491. NULL,
  492. &blob
  493. );
  494. }
  495. if ((ObjectTypeId & (~PLATFORM_MASK)) == g_IniType) {
  496. IsmSetOperationOnObject (
  497. ObjectTypeId,
  498. ObjectName,
  499. g_IniAutoFilterOp,
  500. NULL,
  501. &blob
  502. );
  503. }
  504. }
  505. } else {
  506. cmdLine = ParseCmdLineEx (pathData, NULL, pOurFindFile, pOurSearchPath, &cmdLineBuffer);
  507. if (cmdLine) {
  508. //
  509. // Find the file referenced in the list or command line
  510. //
  511. for (u = 0 ; u < cmdLine->ArgCount ; u++) {
  512. p = cmdLine->Args[u].CleanedUpArg;
  513. // first we try it as is
  514. handle = pTryHandle (p, expandHint, Recursive, &hintUsed);
  515. if (handle) {
  516. ZeroMemory (&actionStruct, sizeof (ACTION_STRUCT));
  517. actionStruct.ObjectBase = handle;
  518. actionFlags = ACTION_PERSIST;
  519. if (RegActionStruct) {
  520. actionStruct.ObjectDest = RegActionStruct->AddnlDest;
  521. }
  522. AddRule (
  523. g_FileType,
  524. handle,
  525. handle,
  526. ACTIONGROUP_INCFILE,
  527. actionFlags,
  528. &actionStruct
  529. );
  530. IsmQueueEnumeration (
  531. g_FileType,
  532. handle,
  533. VcmMode ? GatherVirtualComputer : PrepareActions,
  534. 0,
  535. NULL
  536. );
  537. foundFile = TRUE;
  538. IsmDestroyObjectHandle (handle);
  539. if (hintUsed && expandHint) {
  540. // we need to add extra data for the content fix operation
  541. blob.Type = BLOBTYPE_STRING;
  542. blob.String = expandHint;
  543. if ((ObjectTypeId & (~PLATFORM_MASK)) == g_RegType) {
  544. IsmSetOperationOnObject (
  545. ObjectTypeId,
  546. ObjectName,
  547. g_RegAutoFilterOp,
  548. NULL,
  549. &blob
  550. );
  551. }
  552. if ((ObjectTypeId & (~PLATFORM_MASK)) == g_IniType) {
  553. IsmSetOperationOnObject (
  554. ObjectTypeId,
  555. ObjectName,
  556. g_IniAutoFilterOp,
  557. NULL,
  558. &blob
  559. );
  560. }
  561. }
  562. } else {
  563. // maybe we have something like /m:c:\foo.txt
  564. // we need to go forward until we find a sequence of
  565. // <alpha>:\<something>
  566. if (p[0] && p[1]) {
  567. while (p[2]) {
  568. if (_istalpha ((CHARTYPE) _tcsnextc (p)) &&
  569. p[1] == TEXT(':') &&
  570. p[2] == TEXT('\\')
  571. ) {
  572. handle = pTryHandle (p, expandHint, Recursive, &hintUsed);
  573. if (handle) {
  574. ZeroMemory (&actionStruct, sizeof (ACTION_STRUCT));
  575. actionStruct.ObjectBase = handle;
  576. actionFlags = ACTION_PERSIST;
  577. if (RegActionStruct) {
  578. actionStruct.ObjectDest = RegActionStruct->AddnlDest;
  579. }
  580. AddRule (
  581. g_FileType,
  582. handle,
  583. handle,
  584. ACTIONGROUP_INCFILE,
  585. actionFlags,
  586. &actionStruct
  587. );
  588. IsmQueueEnumeration (
  589. g_FileType,
  590. handle,
  591. VcmMode ? GatherVirtualComputer : PrepareActions,
  592. 0,
  593. NULL
  594. );
  595. foundFile = TRUE;
  596. IsmDestroyObjectHandle (handle);
  597. if (hintUsed && expandHint) {
  598. // we need to add extra data for the content fix operation
  599. blob.Type = BLOBTYPE_STRING;
  600. blob.String = expandHint;
  601. if ((ObjectTypeId & (~PLATFORM_MASK)) == g_RegType) {
  602. IsmSetOperationOnObject (
  603. ObjectTypeId,
  604. ObjectName,
  605. g_RegAutoFilterOp,
  606. NULL,
  607. &blob
  608. );
  609. }
  610. if ((ObjectTypeId & (~PLATFORM_MASK)) == g_IniType) {
  611. IsmSetOperationOnObject (
  612. ObjectTypeId,
  613. ObjectName,
  614. g_IniAutoFilterOp,
  615. NULL,
  616. &blob
  617. );
  618. }
  619. }
  620. break;
  621. }
  622. }
  623. p ++;
  624. }
  625. }
  626. }
  627. }
  628. }
  629. }
  630. }
  631. //
  632. // We persist the registry object at all times
  633. //
  634. if (VcmMode) {
  635. IsmMakePersistentObject (ObjectTypeId, ObjectName);
  636. } else {
  637. IsmMakeApplyObject (ObjectTypeId, ObjectName);
  638. }
  639. if (!foundFile && !expandHint && pathData && _tcschr (pathData, TEXT('.')) && !_tcschr (pathData, TEXT('\\'))) {
  640. // we assume that the value is a file name by itself
  641. // If we are in VcmMode we are going to persist this
  642. // key and all files that have the name equal with
  643. // the value of this key
  644. if (VcmMode && pathData) {
  645. handle = IsmCreateSimpleObjectPattern (NULL, FALSE, pathData, FALSE);
  646. AddRule (
  647. g_FileType,
  648. handle,
  649. handle,
  650. ACTIONGROUP_INCFILE,
  651. ACTION_PERSIST,
  652. NULL
  653. );
  654. DEBUGMSG ((
  655. DBG_SCRIPT,
  656. "RegFile %s triggered enumeration of entire file system because of %s",
  657. pGetObjectNameForDebug (ObjectName),
  658. pathData
  659. ));
  660. QueueAllFiles (VcmMode);
  661. IsmHookEnumeration (
  662. g_FileType,
  663. handle,
  664. GatherVirtualComputer,
  665. 0,
  666. NULL
  667. );
  668. IsmDestroyObjectHandle (handle);
  669. }
  670. }
  671. IsmReleaseObject (&content);
  672. if (expandPath) {
  673. IsmReleaseMemory (expandPath);
  674. expandPath = NULL;
  675. }
  676. if (expandHint) {
  677. IsmReleaseMemory (expandHint);
  678. expandHint = NULL;
  679. }
  680. }
  681. GbFree (&cmdLineBuffer);
  682. }
  683. VOID
  684. pSaveObjectAndIconItReferences (
  685. IN MIG_OBJECTTYPEID ObjectTypeId,
  686. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  687. IN PACTION_STRUCT RegActionStruct,
  688. IN BOOL VcmMode
  689. )
  690. {
  691. MIG_CONTENT content;
  692. GROWBUFFER cmdLineBuffer = INIT_GROWBUFFER;
  693. PCMDLINE cmdLine;
  694. PTSTR pathData;
  695. BOOL parsable;
  696. PDWORD valueType;
  697. PCTSTR p;
  698. PCTSTR end;
  699. PCTSTR expandPath = NULL;
  700. PCTSTR expandHint = NULL;
  701. MIG_OBJECTSTRINGHANDLE handle;
  702. BOOL foundFile = FALSE;
  703. INT iconNumber = 0;
  704. PICON_GROUP iconGroup = NULL;
  705. ICON_SGROUP iconSGroup;
  706. PCTSTR iconResId = NULL;
  707. MIG_CONTENT iconContent;
  708. MIG_BLOB migBlob;
  709. //
  710. // Obtain the object data
  711. //
  712. if (IsmAcquireObjectEx (ObjectTypeId, ObjectName, &content, CONTENTTYPE_MEMORY, 4096)) {
  713. //
  714. // Parse the data for a file
  715. //
  716. pathData = (PTSTR) content.MemoryContent.ContentBytes;
  717. parsable = FALSE;
  718. if ((ObjectTypeId & (~PLATFORM_MASK)) == g_RegType) {
  719. valueType = (PDWORD)(content.Details.DetailsData);
  720. if (valueType) {
  721. if (*valueType == REG_EXPAND_SZ ||
  722. *valueType == REG_SZ
  723. ) {
  724. parsable = TRUE;
  725. }
  726. } else {
  727. MYASSERT (IsmIsObjectHandleNodeOnly (ObjectName));
  728. }
  729. }
  730. if ((ObjectTypeId & (~PLATFORM_MASK)) == g_IniType) {
  731. parsable = TRUE;
  732. }
  733. if (parsable) {
  734. p = pathData;
  735. end = (PCTSTR) (content.MemoryContent.ContentBytes + content.MemoryContent.ContentSize);
  736. while (p < end) {
  737. if (*p == 0) {
  738. break;
  739. }
  740. p = _tcsinc (p);
  741. }
  742. if (p >= end) {
  743. pathData = NULL;
  744. }
  745. } else {
  746. pathData = NULL;
  747. }
  748. if (pathData) {
  749. //
  750. // Expand the data
  751. //
  752. expandPath = IsmExpandEnvironmentString (
  753. PLATFORM_SOURCE,
  754. S_SYSENVVAR_GROUP,
  755. pathData,
  756. NULL
  757. );
  758. pathData = (PTSTR)expandPath;
  759. if (RegActionStruct && RegActionStruct->ObjectHint) {
  760. expandHint = IsmExpandEnvironmentString (
  761. PLATFORM_SOURCE,
  762. S_SYSENVVAR_GROUP,
  763. RegActionStruct->ObjectHint,
  764. NULL
  765. );
  766. }
  767. cmdLine = ParseCmdLineEx (pathData, TEXT(","), pOurFindFile, pOurSearchPath, &cmdLineBuffer);
  768. if (cmdLine) {
  769. // we only expect two args, the icon file name and the icon number
  770. if (cmdLine->ArgCount <= 2) {
  771. p = cmdLine->Args[0].CleanedUpArg;
  772. handle = pTryHandle (p, expandHint, FALSE, NULL);
  773. if (handle) {
  774. if (VcmMode) {
  775. // we are just going to persist the object so we can look at it later
  776. IsmMakePersistentObject (g_FileType, handle);
  777. } else {
  778. iconNumber = 0;
  779. if (cmdLine->ArgCount == 2) {
  780. // get the icon number
  781. iconNumber = _ttoi (cmdLine->Args[1].CleanedUpArg);
  782. }
  783. // now acquire the object and extract the icon
  784. if (IsmAcquireObjectEx (
  785. MIG_FILE_TYPE,
  786. handle,
  787. &iconContent,
  788. CONTENTTYPE_FILE,
  789. 0
  790. )) {
  791. if (iconNumber >= 0) {
  792. iconGroup = IcoExtractIconGroupByIndexFromFile (
  793. iconContent.FileContent.ContentPath,
  794. iconNumber,
  795. NULL
  796. );
  797. } else {
  798. iconResId = (PCTSTR) (LONG_PTR) (-iconNumber);
  799. iconGroup = IcoExtractIconGroupFromFile (
  800. iconContent.FileContent.ContentPath,
  801. iconResId,
  802. NULL
  803. );
  804. }
  805. if (iconGroup) {
  806. if (IcoSerializeIconGroup (iconGroup, &iconSGroup)) {
  807. // save the icon data as a property
  808. migBlob.Type = BLOBTYPE_BINARY;
  809. migBlob.BinaryData = (PCBYTE)(iconSGroup.Data);
  810. migBlob.BinarySize = iconSGroup.DataSize;
  811. IsmAddPropertyToObject (ObjectTypeId, ObjectName, g_DefaultIconData, &migBlob);
  812. IcoReleaseIconSGroup (&iconSGroup);
  813. // now add the appropriate operation
  814. IsmSetOperationOnObject (
  815. ObjectTypeId,
  816. ObjectName,
  817. g_DefaultIconOp,
  818. NULL,
  819. NULL
  820. );
  821. foundFile = TRUE;
  822. }
  823. IcoReleaseIconGroup (iconGroup);
  824. }
  825. IsmReleaseObject (&iconContent);
  826. }
  827. }
  828. IsmDestroyObjectHandle (handle);
  829. }
  830. }
  831. }
  832. GbFree (&cmdLineBuffer);
  833. if (expandPath) {
  834. IsmReleaseMemory (expandPath);
  835. expandPath = NULL;
  836. }
  837. if (expandHint) {
  838. IsmReleaseMemory (expandHint);
  839. expandHint = NULL;
  840. }
  841. }
  842. //
  843. // We persist the registry object at all times
  844. //
  845. if (VcmMode) {
  846. IsmMakePersistentObject (ObjectTypeId, ObjectName);
  847. } else {
  848. if (foundFile) {
  849. IsmMakeApplyObject (ObjectTypeId, ObjectName);
  850. }
  851. }
  852. IsmReleaseObject (&content);
  853. }
  854. }
  855. UINT
  856. GatherVirtualComputer (
  857. IN PCMIG_OBJECTENUMDATA Data,
  858. IN ULONG_PTR CallerArg
  859. )
  860. {
  861. ACTIONGROUP actionGroup;
  862. DWORD actionFlags;
  863. BOOL match;
  864. PCTSTR encodedNodeOnly;
  865. ACTION_STRUCT actionStruct;
  866. MIG_OBJECTID objectId = 0;
  867. //
  868. // Obtain the best rule for this object
  869. //
  870. match = QueryRule (
  871. Data->ObjectTypeId,
  872. Data->ObjectName,
  873. Data->ObjectNode,
  874. &actionGroup,
  875. &actionFlags,
  876. &actionStruct
  877. );
  878. if (!match && !Data->ObjectLeaf) {
  879. //
  880. // If this is a node only, try matching with an empty leaf
  881. //
  882. encodedNodeOnly = IsmCreateObjectHandle (Data->ObjectNode, TEXT(""));
  883. match = QueryRule (
  884. Data->ObjectTypeId,
  885. encodedNodeOnly,
  886. Data->ObjectNode,
  887. &actionGroup,
  888. &actionFlags,
  889. &actionStruct
  890. );
  891. IsmDestroyObjectHandle (encodedNodeOnly);
  892. }
  893. if (match) {
  894. //
  895. // Mark all objects necessary for the rule to be processed. We
  896. // will do the rule's action(s) on the right side.
  897. //
  898. if ((actionGroup == ACTIONGROUP_INCLUDE) ||
  899. (actionGroup == ACTIONGROUP_INCLUDEEX) ||
  900. (actionGroup == ACTIONGROUP_RENAME) ||
  901. (actionGroup == ACTIONGROUP_RENAMEEX) ||
  902. (actionGroup == ACTIONGROUP_INCLUDERELEVANT) ||
  903. (actionGroup == ACTIONGROUP_INCLUDERELEVANTEX) ||
  904. (actionGroup == ACTIONGROUP_RENAMERELEVANT) ||
  905. (actionGroup == ACTIONGROUP_RENAMERELEVANTEX) ||
  906. (actionGroup == ACTIONGROUP_INCFILE) ||
  907. (actionGroup == ACTIONGROUP_INCFILEEX) ||
  908. (actionGroup == ACTIONGROUP_INCFOLDER) ||
  909. (actionGroup == ACTIONGROUP_INCFOLDEREX) ||
  910. (actionGroup == ACTIONGROUP_INCICON) ||
  911. (actionGroup == ACTIONGROUP_INCICONEX)
  912. ) {
  913. objectId = IsmGetObjectIdFromName (Data->ObjectTypeId, Data->ObjectName, FALSE);
  914. if (objectId) {
  915. if (actionFlags & ACTION_PERSIST) {
  916. if (!IsmIsAttributeSetOnObjectId (objectId, g_OsFileAttribute)) {
  917. IsmMakePersistentObjectId (objectId);
  918. }
  919. }
  920. if ((actionGroup == ACTIONGROUP_INCLUDERELEVANT) ||
  921. (actionGroup == ACTIONGROUP_RENAMERELEVANT)
  922. ) {
  923. IsmSetAttributeOnObjectId (objectId, g_CopyIfRelevantAttr);
  924. }
  925. if (actionFlags & ACTION_PERSIST_PATH_IN_DATA) {
  926. pSaveObjectAndFileItReferences (Data->ObjectTypeId, Data->ObjectName, &actionStruct, TRUE, actionGroup == ACTIONGROUP_INCFOLDER);
  927. }
  928. if (actionFlags & ACTION_PERSIST_ICON_IN_DATA) {
  929. pSaveObjectAndIconItReferences (Data->ObjectTypeId, Data->ObjectName, &actionStruct, TRUE);
  930. }
  931. }
  932. }
  933. }
  934. return CALLBACK_ENUM_CONTINUE;
  935. }
  936. MIG_DATAHANDLE
  937. pGetDataHandleForSrc (
  938. IN PCTSTR RenameSrc
  939. )
  940. {
  941. MIG_DATAHANDLE dataHandle;
  942. MIG_BLOB blob;
  943. //
  944. // First check hash table to see if we have an ID
  945. //
  946. if (!HtFindStringEx (g_RenameSrcTable, RenameSrc, &dataHandle, FALSE)) {
  947. blob.Type = BLOBTYPE_STRING;
  948. blob.String = RenameSrc;
  949. dataHandle = IsmRegisterOperationData (&blob);
  950. HtAddStringEx (g_RenameSrcTable, RenameSrc, &dataHandle, FALSE);
  951. }
  952. return dataHandle;
  953. }
  954. MIG_DATAHANDLE
  955. pGetDataHandleForDest (
  956. IN PCTSTR RenameDest
  957. )
  958. {
  959. MIG_DATAHANDLE dataHandle;
  960. MIG_BLOB blob;
  961. //
  962. // First check hash table to see if we have an ID
  963. //
  964. if (!HtFindStringEx (g_RenameDestTable, RenameDest, &dataHandle, FALSE)) {
  965. blob.Type = BLOBTYPE_STRING;
  966. blob.String = RenameDest;
  967. dataHandle = IsmRegisterOperationData (&blob);
  968. HtAddStringEx (g_RenameDestTable, RenameDest, &dataHandle, FALSE);
  969. }
  970. return dataHandle;
  971. }
  972. UINT
  973. PrepareActions (
  974. IN PCMIG_OBJECTENUMDATA Data,
  975. IN ULONG_PTR CallerArg
  976. )
  977. {
  978. ACTIONGROUP actionGroup;
  979. DWORD actionFlags;
  980. BOOL match;
  981. PCTSTR encodedNodeOnly;
  982. MIG_DATAHANDLE srcDataHandle;
  983. MIG_DATAHANDLE destDataHandle;
  984. ACTION_STRUCT actionStruct;
  985. MIG_OBJECTID objectId = 0;
  986. //
  987. // Obtain the best rule for this object
  988. //
  989. match = QueryRule (
  990. Data->ObjectTypeId,
  991. Data->ObjectName,
  992. Data->ObjectNode,
  993. &actionGroup,
  994. &actionFlags,
  995. &actionStruct
  996. );
  997. if (!match && !Data->ObjectLeaf) {
  998. //
  999. // If this is a node only, try matching with an empty leaf
  1000. //
  1001. encodedNodeOnly = IsmCreateObjectHandle (Data->ObjectNode, TEXT(""));
  1002. match = QueryRule (
  1003. Data->ObjectTypeId,
  1004. encodedNodeOnly,
  1005. Data->ObjectNode,
  1006. &actionGroup,
  1007. &actionFlags,
  1008. &actionStruct
  1009. );
  1010. IsmDestroyObjectHandle (encodedNodeOnly);
  1011. }
  1012. if (match) {
  1013. //
  1014. // Mark the objects for the designated operations.
  1015. //
  1016. if ((actionGroup == ACTIONGROUP_INCLUDE) ||
  1017. (actionGroup == ACTIONGROUP_INCLUDEEX) ||
  1018. (actionGroup == ACTIONGROUP_RENAME) ||
  1019. (actionGroup == ACTIONGROUP_RENAMEEX) ||
  1020. (actionGroup == ACTIONGROUP_INCLUDERELEVANT) ||
  1021. (actionGroup == ACTIONGROUP_INCLUDERELEVANTEX) ||
  1022. (actionGroup == ACTIONGROUP_RENAMERELEVANT) ||
  1023. (actionGroup == ACTIONGROUP_RENAMERELEVANTEX) ||
  1024. (actionGroup == ACTIONGROUP_INCFILE) ||
  1025. (actionGroup == ACTIONGROUP_INCFILEEX) ||
  1026. (actionGroup == ACTIONGROUP_INCFOLDER) ||
  1027. (actionGroup == ACTIONGROUP_INCFOLDEREX) ||
  1028. (actionGroup == ACTIONGROUP_INCICON) ||
  1029. (actionGroup == ACTIONGROUP_INCICONEX)
  1030. ) {
  1031. objectId = IsmGetObjectIdFromName (Data->ObjectTypeId, Data->ObjectName, FALSE);
  1032. if (objectId) {
  1033. if (actionFlags & ACTION_PERSIST) {
  1034. if (!IsmIsAttributeSetOnObjectId (objectId, g_OsFileAttribute)) {
  1035. IsmMakeApplyObjectId (objectId);
  1036. }
  1037. }
  1038. if ((actionGroup == ACTIONGROUP_INCLUDERELEVANT) ||
  1039. (actionGroup == ACTIONGROUP_RENAMERELEVANT)
  1040. ) {
  1041. IsmSetAttributeOnObjectId (objectId, g_CopyIfRelevantAttr);
  1042. }
  1043. if (actionFlags & ACTION_PERSIST_PATH_IN_DATA) {
  1044. pSaveObjectAndFileItReferences (Data->ObjectTypeId, Data->ObjectName, &actionStruct, FALSE, actionGroup == ACTIONGROUP_INCFOLDER);
  1045. }
  1046. if (actionFlags & ACTION_PERSIST_ICON_IN_DATA) {
  1047. pSaveObjectAndIconItReferences (Data->ObjectTypeId, Data->ObjectName, &actionStruct, FALSE);
  1048. }
  1049. }
  1050. }
  1051. if ((actionGroup == ACTIONGROUP_RENAME) ||
  1052. (actionGroup == ACTIONGROUP_RENAMEEX) ||
  1053. (actionGroup == ACTIONGROUP_RENAMERELEVANT) ||
  1054. (actionGroup == ACTIONGROUP_RENAMERELEVANTEX) ||
  1055. (actionGroup == ACTIONGROUP_INCFILE) ||
  1056. (actionGroup == ACTIONGROUP_INCFILEEX) ||
  1057. (actionGroup == ACTIONGROUP_INCFOLDER) ||
  1058. (actionGroup == ACTIONGROUP_INCFOLDEREX) ||
  1059. (actionGroup == ACTIONGROUP_INCICON) ||
  1060. (actionGroup == ACTIONGROUP_INCICONEX)
  1061. ) {
  1062. if (actionStruct.ObjectDest) {
  1063. if (actionStruct.ObjectBase) {
  1064. srcDataHandle = pGetDataHandleForSrc (actionStruct.ObjectBase);
  1065. } else {
  1066. srcDataHandle = 0;
  1067. }
  1068. destDataHandle = pGetDataHandleForDest (actionStruct.ObjectDest);
  1069. if (!objectId) {
  1070. objectId = IsmGetObjectIdFromName (Data->ObjectTypeId, Data->ObjectName, FALSE);
  1071. }
  1072. if (objectId) {
  1073. if ((Data->ObjectTypeId & (~PLATFORM_MASK)) == g_FileType) {
  1074. if ((actionGroup == ACTIONGROUP_RENAMERELEVANTEX) ||
  1075. (actionGroup == ACTIONGROUP_RENAMEEX)
  1076. ) {
  1077. IsmSetOperationOnObjectId2 (
  1078. objectId,
  1079. g_RenameFileExOp,
  1080. srcDataHandle,
  1081. destDataHandle
  1082. );
  1083. } else {
  1084. IsmSetOperationOnObjectId2 (
  1085. objectId,
  1086. g_RenameFileOp,
  1087. srcDataHandle,
  1088. destDataHandle
  1089. );
  1090. }
  1091. } else {
  1092. if ((Data->ObjectTypeId & (~PLATFORM_MASK)) == g_IniType) {
  1093. IsmSetOperationOnObjectId2 (
  1094. objectId,
  1095. (actionGroup == ACTIONGROUP_RENAMEEX ? g_RenameIniExOp : g_RenameIniOp),
  1096. srcDataHandle,
  1097. destDataHandle
  1098. );
  1099. } else {
  1100. if ((actionGroup == ACTIONGROUP_INCFILEEX) ||
  1101. (actionGroup == ACTIONGROUP_INCFOLDEREX) ||
  1102. (actionGroup == ACTIONGROUP_INCICONEX) ||
  1103. (actionGroup == ACTIONGROUP_RENAMEEX)
  1104. ) {
  1105. IsmSetOperationOnObjectId2 (
  1106. objectId,
  1107. g_RenameExOp,
  1108. srcDataHandle,
  1109. destDataHandle
  1110. );
  1111. } else {
  1112. IsmSetOperationOnObjectId2 (
  1113. objectId,
  1114. g_RenameOp,
  1115. srcDataHandle,
  1116. destDataHandle
  1117. );
  1118. }
  1119. }
  1120. }
  1121. }
  1122. }
  1123. }
  1124. }
  1125. return CALLBACK_ENUM_CONTINUE;
  1126. }
  1127. UINT
  1128. NulCallback (
  1129. IN PCMIG_OBJECTENUMDATA Data,
  1130. IN ULONG_PTR CallerArg
  1131. )
  1132. {
  1133. return CALLBACK_ENUM_CONTINUE;
  1134. }
  1135. UINT
  1136. ObjectPriority (
  1137. IN PCMIG_OBJECTENUMDATA Data,
  1138. IN ULONG_PTR CallerArg
  1139. )
  1140. {
  1141. ACTIONGROUP actionGroup;
  1142. DWORD actionFlags;
  1143. BOOL match;
  1144. match = QueryRuleEx (
  1145. Data->ObjectTypeId,
  1146. Data->ObjectName,
  1147. Data->ObjectNode,
  1148. &actionGroup,
  1149. &actionFlags,
  1150. NULL,
  1151. RULEGROUP_PRIORITY
  1152. );
  1153. if (match) {
  1154. MYASSERT ((actionFlags == ACTION_PRIORITYSRC) || (actionFlags == ACTION_PRIORITYDEST));
  1155. if (actionFlags == ACTION_PRIORITYSRC) {
  1156. IsmClearAbandonObjectOnCollision (
  1157. (Data->ObjectTypeId & (~PLATFORM_MASK)) | PLATFORM_SOURCE,
  1158. Data->ObjectName
  1159. );
  1160. IsmAbandonObjectOnCollision (
  1161. (Data->ObjectTypeId & (~PLATFORM_MASK)) | PLATFORM_DESTINATION,
  1162. Data->ObjectName
  1163. );
  1164. } else {
  1165. IsmAbandonObjectOnCollision (
  1166. (Data->ObjectTypeId & (~PLATFORM_MASK)) | PLATFORM_SOURCE,
  1167. Data->ObjectName
  1168. );
  1169. IsmClearAbandonObjectOnCollision (
  1170. (Data->ObjectTypeId & (~PLATFORM_MASK)) | PLATFORM_DESTINATION,
  1171. Data->ObjectName
  1172. );
  1173. }
  1174. }
  1175. return CALLBACK_ENUM_CONTINUE;
  1176. }
  1177. UINT
  1178. FileCollPattern (
  1179. IN PCMIG_OBJECTENUMDATA Data,
  1180. IN ULONG_PTR CallerArg
  1181. )
  1182. {
  1183. ACTIONGROUP actionGroup;
  1184. DWORD actionFlags;
  1185. ACTION_STRUCT actionStruct;
  1186. BOOL match;
  1187. MIG_BLOB migBlob;
  1188. match = QueryRuleEx (
  1189. Data->ObjectTypeId,
  1190. Data->ObjectName,
  1191. Data->ObjectNode,
  1192. &actionGroup,
  1193. &actionFlags,
  1194. &actionStruct,
  1195. RULEGROUP_COLLPATTERN
  1196. );
  1197. if (match && (!(IsmIsObjectHandleNodeOnly (Data->ObjectName)))) {
  1198. // Let's set a property on this file (we don't need this for nodes)
  1199. migBlob.Type = BLOBTYPE_STRING;
  1200. migBlob.String = actionStruct.ObjectHint;
  1201. IsmAddPropertyToObject (Data->ObjectTypeId, Data->ObjectName, g_FileCollPatternData, &migBlob);
  1202. }
  1203. return CALLBACK_ENUM_CONTINUE;
  1204. }
  1205. UINT
  1206. LockPartition (
  1207. IN PCMIG_OBJECTENUMDATA Data,
  1208. IN ULONG_PTR CallerArg
  1209. )
  1210. {
  1211. IsmSetAttributeOnObject (Data->ObjectTypeId, Data->ObjectName, g_LockPartitionAttr);
  1212. return CALLBACK_ENUM_CONTINUE;
  1213. }
  1214. UINT
  1215. ExcludeKeyIfValueExists (
  1216. IN PCMIG_OBJECTENUMDATA Data,
  1217. IN ULONG_PTR CallerArg
  1218. )
  1219. {
  1220. PCTSTR srcNode = NULL;
  1221. PCTSTR srcLeaf = NULL;
  1222. // This function is only called for each registry key/value pair that
  1223. // indicates we want to cause the exclusion of the entire key.
  1224. IsmCreateObjectStringsFromHandle (Data->ObjectName, &srcNode, &srcLeaf);
  1225. // This is also called for all keys (not including a value) so we need
  1226. // to make sure a value is passed in
  1227. if (srcLeaf && *srcLeaf) {
  1228. // Exclude the srcNode
  1229. HtAddString (g_DePersistTable, srcNode);
  1230. }
  1231. IsmDestroyObjectString (srcNode);
  1232. IsmDestroyObjectString (srcLeaf);
  1233. return CALLBACK_ENUM_CONTINUE;
  1234. }
  1235. BOOL
  1236. PostDelregKeyCallback (
  1237. VOID
  1238. )
  1239. {
  1240. static BOOL called = FALSE;
  1241. HASHTABLE_ENUM hashData;
  1242. MIG_OBJECT_ENUM objectEnum;
  1243. MIG_OBJECTSTRINGHANDLE pattern;
  1244. if (called) {
  1245. return TRUE;
  1246. }
  1247. // Enumerate all Excluded keys
  1248. if (EnumFirstHashTableString (&hashData, g_DePersistTable)) {
  1249. do {
  1250. // Remove Persistence on the key
  1251. pattern = IsmCreateObjectHandle (hashData.String, NULL);
  1252. IsmClearPersistenceOnObject (g_RegType, pattern);
  1253. IsmDestroyObjectHandle (pattern);
  1254. // Enumerate each value in this key
  1255. pattern = IsmCreateSimpleObjectPattern (hashData.String, TRUE, NULL, TRUE);
  1256. if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, pattern)) {
  1257. do {
  1258. // Remove Persistence on each value
  1259. IsmClearPersistenceOnObject (objectEnum.ObjectTypeId, objectEnum.ObjectName);
  1260. } while (IsmEnumNextObject (&objectEnum));
  1261. }
  1262. IsmDestroyObjectHandle (pattern);
  1263. } while (EnumNextHashTableString (&hashData));
  1264. }
  1265. HtFree (g_DePersistTable);
  1266. g_DePersistTable = NULL;
  1267. called = TRUE;
  1268. return TRUE;
  1269. }