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.

1419 lines
42 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, 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, 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 (IsmGetRealPlatform () == PLATFORM_SOURCE) {
  223. attribs = GetFileAttributes (sanitizedPath);
  224. } else {
  225. attribs = INVALID_ATTRIBUTES;
  226. }
  227. if (attribs != INVALID_ATTRIBUTES) {
  228. result = TRUE;
  229. } else {
  230. test = IsmCreateObjectHandle (sanitizedPath, NULL);
  231. if (IsmGetObjectIdFromName (g_FileType, test, TRUE)) {
  232. result = TRUE;
  233. }
  234. IsmDestroyObjectHandle (test);
  235. test = NULL;
  236. if (!result) {
  237. buffer = DuplicatePathString (sanitizedPath, 0);
  238. leaf = _tcsrchr (buffer, TEXT('\\'));
  239. if (leaf) {
  240. leafPtr = leaf;
  241. leaf = _tcsinc (leaf);
  242. *leafPtr = 0;
  243. test = IsmCreateObjectHandle (buffer, leaf);
  244. }
  245. if (test) {
  246. if (IsmGetObjectIdFromName (g_FileType, test, TRUE)) {
  247. result = TRUE;
  248. }
  249. IsmDestroyObjectHandle (test);
  250. test = NULL;
  251. }
  252. FreePathString (buffer);
  253. }
  254. }
  255. FreePathString (sanitizedPath);
  256. return result;
  257. }
  258. BOOL
  259. pOurSearchPath (
  260. IN PCTSTR FileName,
  261. IN DWORD BufferLength,
  262. OUT PTSTR Buffer
  263. )
  264. {
  265. TCHAR pathEnv[] = TEXT("%system%;%system16%;%windir%;%path%");
  266. PCTSTR pathExp = NULL;
  267. PCTSTR fileName = NULL;
  268. PATH_ENUM pathEnum;
  269. BOOL result = FALSE;
  270. pathExp = IsmExpandEnvironmentString (
  271. PLATFORM_SOURCE,
  272. S_SYSENVVAR_GROUP,
  273. pathEnv,
  274. NULL
  275. );
  276. if (pathExp) {
  277. if (EnumFirstPathEx (&pathEnum, pathExp, NULL, NULL, FALSE)) {
  278. do {
  279. fileName = JoinPaths (pathEnum.PtrCurrPath, FileName);
  280. result = pOurFindFile (fileName);
  281. if (result) {
  282. StringCopyTcharCount (Buffer, fileName, BufferLength);
  283. FreePathString (fileName);
  284. AbortPathEnum (&pathEnum);
  285. break;
  286. }
  287. FreePathString (fileName);
  288. } while (EnumNextPath (&pathEnum));
  289. }
  290. IsmReleaseMemory (pathExp);
  291. pathExp = NULL;
  292. }
  293. return result;
  294. }
  295. PCTSTR
  296. pGetObjectNameForDebug (
  297. IN MIG_OBJECTSTRINGHANDLE ObjectName
  298. )
  299. {
  300. static TCHAR debugBuffer[2048];
  301. PCTSTR node, leaf;
  302. IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf);
  303. if (node && leaf) {
  304. wsprintf (debugBuffer, TEXT("[Node:%s Leaf:%s]"), node, leaf);
  305. } else if (node) {
  306. wsprintf (debugBuffer, TEXT("[Node:%s]"), node);
  307. } else if (leaf) {
  308. wsprintf (debugBuffer, TEXT("[Leaf:%s]"), leaf);
  309. } else {
  310. StringCopy (debugBuffer, TEXT("[nul]"));
  311. }
  312. return debugBuffer;
  313. }
  314. VOID
  315. pSaveObjectAndFileItReferences (
  316. IN MIG_OBJECTTYPEID ObjectTypeId,
  317. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  318. IN PACTION_STRUCT RegActionStruct,
  319. IN BOOL VcmMode,
  320. IN BOOL Recursive
  321. )
  322. {
  323. MIG_CONTENT content;
  324. GROWBUFFER cmdLineBuffer = INIT_GROWBUFFER;
  325. PCMDLINE cmdLine;
  326. PTSTR pathData;
  327. PCTSTR p;
  328. PCTSTR end;
  329. PCTSTR expandPath = NULL;
  330. PCTSTR expandHint = NULL;
  331. UINT u;
  332. BOOL foundFile = FALSE;
  333. PDWORD valueType;
  334. MIG_OBJECTSTRINGHANDLE handle;
  335. MIG_OBJECTSTRINGHANDLE nodeHandle;
  336. BOOL parsable;
  337. BOOL firstPass = TRUE;
  338. ACTION_STRUCT actionStruct;
  339. DWORD actionFlags;
  340. BOOL hintUsed = FALSE;
  341. MIG_BLOB blob;
  342. //
  343. // Obtain the object data
  344. //
  345. if (IsmAcquireObjectEx (ObjectTypeId, ObjectName, &content, CONTENTTYPE_MEMORY, 4096)) {
  346. //
  347. // Parse the data for a file
  348. //
  349. pathData = (PTSTR) content.MemoryContent.ContentBytes;
  350. parsable = FALSE;
  351. if ((ObjectTypeId & (~PLATFORM_MASK)) == g_RegType) {
  352. valueType = (PDWORD)(content.Details.DetailsData);
  353. if (valueType) {
  354. if (*valueType == REG_EXPAND_SZ ||
  355. *valueType == REG_SZ
  356. ) {
  357. parsable = TRUE;
  358. }
  359. } else {
  360. MYASSERT (IsmIsObjectHandleNodeOnly (ObjectName));
  361. }
  362. }
  363. if (parsable) {
  364. p = pathData;
  365. end = (PCTSTR) (content.MemoryContent.ContentBytes + content.MemoryContent.ContentSize);
  366. while (p < end) {
  367. if (*p == 0) {
  368. break;
  369. }
  370. p = _tcsinc (p);
  371. }
  372. if (p >= end) {
  373. pathData = NULL;
  374. }
  375. } else {
  376. pathData = NULL;
  377. }
  378. if (pathData) {
  379. if ((*valueType == REG_EXPAND_SZ) ||
  380. (*valueType == REG_SZ)
  381. ) {
  382. //
  383. // Expand the data
  384. //
  385. expandPath = IsmExpandEnvironmentString (
  386. PLATFORM_SOURCE,
  387. S_SYSENVVAR_GROUP,
  388. pathData,
  389. NULL
  390. );
  391. pathData = (PTSTR)expandPath;
  392. }
  393. if (RegActionStruct && RegActionStruct->ObjectHint) {
  394. expandHint = IsmExpandEnvironmentString (
  395. PLATFORM_SOURCE,
  396. S_SYSENVVAR_GROUP,
  397. RegActionStruct->ObjectHint,
  398. NULL
  399. );
  400. }
  401. // first we try it as is
  402. handle = pTryHandle (pathData, expandHint, Recursive, &hintUsed);
  403. if (handle) {
  404. ZeroMemory (&actionStruct, sizeof (ACTION_STRUCT));
  405. actionStruct.ObjectBase = handle;
  406. actionFlags = ACTION_PERSIST;
  407. if (RegActionStruct) {
  408. actionStruct.ObjectDest = RegActionStruct->AddnlDest;
  409. }
  410. if (Recursive) {
  411. nodeHandle = IsmCreateObjectHandle (pathData, NULL);
  412. AddRule (
  413. g_FileType,
  414. nodeHandle,
  415. handle,
  416. ACTIONGROUP_REGFOLDER,
  417. actionFlags,
  418. &actionStruct
  419. );
  420. IsmQueueEnumeration (
  421. g_FileType,
  422. nodeHandle,
  423. VcmMode ? GatherVirtualComputer : PrepareActions,
  424. 0,
  425. NULL
  426. );
  427. IsmDestroyObjectHandle (nodeHandle);
  428. } else {
  429. AddRule (
  430. g_FileType,
  431. handle,
  432. handle,
  433. ACTIONGROUP_REGFILE,
  434. actionFlags,
  435. &actionStruct
  436. );
  437. }
  438. IsmQueueEnumeration (
  439. g_FileType,
  440. handle,
  441. VcmMode ? GatherVirtualComputer : PrepareActions,
  442. 0,
  443. NULL
  444. );
  445. foundFile = TRUE;
  446. IsmDestroyObjectHandle (handle);
  447. if (hintUsed && expandHint) {
  448. // we need to add extra data for the content fix operation
  449. blob.Type = BLOBTYPE_STRING;
  450. blob.String = expandHint;
  451. IsmSetOperationOnObject (
  452. ObjectTypeId,
  453. ObjectName,
  454. g_RegAutoFilterOp,
  455. NULL,
  456. &blob
  457. );
  458. }
  459. } else {
  460. cmdLine = ParseCmdLineEx (pathData, NULL, pOurFindFile, pOurSearchPath, &cmdLineBuffer);
  461. if (cmdLine) {
  462. //
  463. // Find the file referenced in the list or command line
  464. //
  465. for (u = 0 ; u < cmdLine->ArgCount ; u++) {
  466. p = cmdLine->Args[u].CleanedUpArg;
  467. // first we try it as is
  468. handle = pTryHandle (p, expandHint, Recursive, &hintUsed);
  469. if (handle) {
  470. ZeroMemory (&actionStruct, sizeof (ACTION_STRUCT));
  471. actionStruct.ObjectBase = handle;
  472. actionFlags = ACTION_PERSIST;
  473. if (RegActionStruct) {
  474. actionStruct.ObjectDest = RegActionStruct->AddnlDest;
  475. }
  476. AddRule (
  477. g_FileType,
  478. handle,
  479. handle,
  480. ACTIONGROUP_REGFILE,
  481. actionFlags,
  482. &actionStruct
  483. );
  484. IsmQueueEnumeration (
  485. g_FileType,
  486. handle,
  487. VcmMode ? GatherVirtualComputer : PrepareActions,
  488. 0,
  489. NULL
  490. );
  491. foundFile = TRUE;
  492. IsmDestroyObjectHandle (handle);
  493. if (hintUsed && expandHint) {
  494. // we need to add extra data for the content fix operation
  495. blob.Type = BLOBTYPE_STRING;
  496. blob.String = expandHint;
  497. IsmSetOperationOnObject (
  498. ObjectTypeId,
  499. ObjectName,
  500. g_RegAutoFilterOp,
  501. NULL,
  502. &blob
  503. );
  504. }
  505. } else {
  506. // maybe we have something like /m:c:\foo.txt
  507. // we need to go forward until we find a sequence of
  508. // <alpha>:\<something>
  509. if (p[0] && p[1]) {
  510. while (p[2]) {
  511. if (_istalpha ((CHARTYPE) _tcsnextc (p)) &&
  512. p[1] == TEXT(':') &&
  513. p[2] == TEXT('\\')
  514. ) {
  515. handle = pTryHandle (p, expandHint, Recursive, &hintUsed);
  516. if (handle) {
  517. ZeroMemory (&actionStruct, sizeof (ACTION_STRUCT));
  518. actionStruct.ObjectBase = handle;
  519. actionFlags = ACTION_PERSIST;
  520. if (RegActionStruct) {
  521. actionStruct.ObjectDest = RegActionStruct->AddnlDest;
  522. }
  523. AddRule (
  524. g_FileType,
  525. handle,
  526. handle,
  527. ACTIONGROUP_REGFILE,
  528. actionFlags,
  529. &actionStruct
  530. );
  531. IsmQueueEnumeration (
  532. g_FileType,
  533. handle,
  534. VcmMode ? GatherVirtualComputer : PrepareActions,
  535. 0,
  536. NULL
  537. );
  538. foundFile = TRUE;
  539. IsmDestroyObjectHandle (handle);
  540. if (hintUsed && expandHint) {
  541. // we need to add extra data for the content fix operation
  542. blob.Type = BLOBTYPE_STRING;
  543. blob.String = expandHint;
  544. IsmSetOperationOnObject (
  545. ObjectTypeId,
  546. ObjectName,
  547. g_RegAutoFilterOp,
  548. NULL,
  549. &blob
  550. );
  551. }
  552. break;
  553. }
  554. }
  555. p ++;
  556. }
  557. }
  558. }
  559. }
  560. }
  561. }
  562. }
  563. //
  564. // We persist the registry object at all times
  565. //
  566. if (VcmMode) {
  567. IsmMakePersistentObject (ObjectTypeId, ObjectName);
  568. } else {
  569. IsmMakeApplyObject (ObjectTypeId, ObjectName);
  570. }
  571. if (!foundFile && !expandHint && pathData && _tcschr (pathData, TEXT('.')) && !_tcschr (pathData, TEXT('\\'))) {
  572. // we assume that the value is a file name by itself
  573. // If we are in VcmMode we are going to persist this
  574. // key and all files that have the name equal with
  575. // the value of this key
  576. if (VcmMode && pathData) {
  577. handle = IsmCreateSimpleObjectPattern (NULL, FALSE, pathData, FALSE);
  578. AddRule (
  579. g_FileType,
  580. handle,
  581. handle,
  582. ACTIONGROUP_REGFILE,
  583. ACTION_PERSIST,
  584. NULL
  585. );
  586. DEBUGMSG ((
  587. DBG_SCRIPT,
  588. "RegFile %s triggered enumeration of entire file system because of %s",
  589. pGetObjectNameForDebug (ObjectName),
  590. pathData
  591. ));
  592. QueueAllFiles();
  593. IsmHookEnumeration (
  594. g_FileType,
  595. handle,
  596. GatherVirtualComputer,
  597. 0,
  598. NULL
  599. );
  600. IsmDestroyObjectHandle (handle);
  601. }
  602. }
  603. IsmReleaseObject (&content);
  604. if (expandPath) {
  605. IsmReleaseMemory (expandPath);
  606. expandPath = NULL;
  607. }
  608. if (expandHint) {
  609. IsmReleaseMemory (expandHint);
  610. expandHint = NULL;
  611. }
  612. }
  613. GbFree (&cmdLineBuffer);
  614. }
  615. VOID
  616. pSaveObjectAndIconItReferences (
  617. IN MIG_OBJECTTYPEID ObjectTypeId,
  618. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  619. IN PACTION_STRUCT RegActionStruct,
  620. IN BOOL VcmMode
  621. )
  622. {
  623. MIG_CONTENT content;
  624. GROWBUFFER cmdLineBuffer = INIT_GROWBUFFER;
  625. PCMDLINE cmdLine;
  626. PTSTR pathData;
  627. BOOL parsable;
  628. PDWORD valueType;
  629. PCTSTR p;
  630. PCTSTR end;
  631. PCTSTR expandPath = NULL;
  632. PCTSTR expandHint = NULL;
  633. MIG_OBJECTSTRINGHANDLE handle;
  634. BOOL foundFile = FALSE;
  635. INT iconNumber = 0;
  636. PICON_GROUP iconGroup = NULL;
  637. ICON_SGROUP iconSGroup;
  638. PCTSTR iconResId = NULL;
  639. MIG_CONTENT iconContent;
  640. MIG_BLOB migBlob;
  641. //
  642. // Obtain the object data
  643. //
  644. if (IsmAcquireObjectEx (ObjectTypeId, ObjectName, &content, CONTENTTYPE_MEMORY, 4096)) {
  645. //
  646. // Parse the data for a file
  647. //
  648. pathData = (PTSTR) content.MemoryContent.ContentBytes;
  649. parsable = FALSE;
  650. if ((ObjectTypeId & (~PLATFORM_MASK)) == g_RegType) {
  651. valueType = (PDWORD)(content.Details.DetailsData);
  652. if (valueType) {
  653. if (*valueType == REG_EXPAND_SZ ||
  654. *valueType == REG_SZ
  655. ) {
  656. parsable = TRUE;
  657. }
  658. } else {
  659. MYASSERT (IsmIsObjectHandleNodeOnly (ObjectName));
  660. }
  661. }
  662. if (parsable) {
  663. p = pathData;
  664. end = (PCTSTR) (content.MemoryContent.ContentBytes + content.MemoryContent.ContentSize);
  665. while (p < end) {
  666. if (*p == 0) {
  667. break;
  668. }
  669. p = _tcsinc (p);
  670. }
  671. if (p >= end) {
  672. pathData = NULL;
  673. }
  674. } else {
  675. pathData = NULL;
  676. }
  677. if (pathData) {
  678. if ((*valueType == REG_EXPAND_SZ) ||
  679. (*valueType == REG_SZ)
  680. ) {
  681. //
  682. // Expand the data
  683. //
  684. expandPath = IsmExpandEnvironmentString (
  685. PLATFORM_SOURCE,
  686. S_SYSENVVAR_GROUP,
  687. pathData,
  688. NULL
  689. );
  690. pathData = (PTSTR)expandPath;
  691. }
  692. if (RegActionStruct && RegActionStruct->ObjectHint) {
  693. expandHint = IsmExpandEnvironmentString (
  694. PLATFORM_SOURCE,
  695. S_SYSENVVAR_GROUP,
  696. RegActionStruct->ObjectHint,
  697. NULL
  698. );
  699. }
  700. cmdLine = ParseCmdLineEx (pathData, TEXT(","), pOurFindFile, pOurSearchPath, &cmdLineBuffer);
  701. if (cmdLine) {
  702. // we only expect two args, the icon file name and the icon number
  703. if (cmdLine->ArgCount <= 2) {
  704. p = cmdLine->Args[0].CleanedUpArg;
  705. handle = pTryHandle (p, expandHint, FALSE, NULL);
  706. if (handle) {
  707. if (VcmMode) {
  708. // we are just going to persist the object so we can look at it later
  709. IsmMakePersistentObject (g_FileType, handle);
  710. } else {
  711. iconNumber = 0;
  712. if (cmdLine->ArgCount == 2) {
  713. // get the icon number
  714. iconNumber = _ttoi (cmdLine->Args[1].CleanedUpArg);
  715. }
  716. // now acquire the object and extract the icon
  717. if (IsmAcquireObjectEx (
  718. MIG_FILE_TYPE,
  719. handle,
  720. &iconContent,
  721. CONTENTTYPE_FILE,
  722. 0
  723. )) {
  724. if (iconNumber >= 0) {
  725. iconGroup = IcoExtractIconGroupByIndexFromFile (
  726. iconContent.FileContent.ContentPath,
  727. iconNumber,
  728. NULL
  729. );
  730. } else {
  731. iconResId = (PCTSTR) (LONG_PTR) (-iconNumber);
  732. iconGroup = IcoExtractIconGroupFromFile (
  733. iconContent.FileContent.ContentPath,
  734. iconResId,
  735. NULL
  736. );
  737. }
  738. if (iconGroup) {
  739. if (IcoSerializeIconGroup (iconGroup, &iconSGroup)) {
  740. // save the icon data as a property
  741. migBlob.Type = BLOBTYPE_BINARY;
  742. migBlob.BinaryData = (PCBYTE)(iconSGroup.Data);
  743. migBlob.BinarySize = iconSGroup.DataSize;
  744. IsmAddPropertyToObject (ObjectTypeId, ObjectName, g_DefaultIconData, &migBlob);
  745. IcoReleaseIconSGroup (&iconSGroup);
  746. // now add the appropriate operation
  747. IsmSetOperationOnObject (
  748. ObjectTypeId,
  749. ObjectName,
  750. g_DefaultIconOp,
  751. NULL,
  752. NULL
  753. );
  754. foundFile = TRUE;
  755. }
  756. IcoReleaseIconGroup (iconGroup);
  757. }
  758. IsmReleaseObject (&iconContent);
  759. }
  760. }
  761. IsmDestroyObjectHandle (handle);
  762. }
  763. }
  764. }
  765. GbFree (&cmdLineBuffer);
  766. if (expandPath) {
  767. IsmReleaseMemory (expandPath);
  768. expandPath = NULL;
  769. }
  770. if (expandHint) {
  771. IsmReleaseMemory (expandHint);
  772. expandHint = NULL;
  773. }
  774. }
  775. //
  776. // We persist the registry object at all times
  777. //
  778. if (VcmMode) {
  779. IsmMakePersistentObject (ObjectTypeId, ObjectName);
  780. } else {
  781. if (foundFile) {
  782. IsmMakeApplyObject (ObjectTypeId, ObjectName);
  783. }
  784. }
  785. IsmReleaseObject (&content);
  786. }
  787. }
  788. UINT
  789. GatherVirtualComputer (
  790. IN PCMIG_OBJECTENUMDATA Data,
  791. IN ULONG_PTR CallerArg
  792. )
  793. {
  794. ACTIONGROUP actionGroup;
  795. DWORD actionFlags;
  796. BOOL match;
  797. PCTSTR encodedNodeOnly;
  798. ACTION_STRUCT actionStruct;
  799. MIG_OBJECTID objectId = 0;
  800. //
  801. // Obtain the best rule for this object
  802. //
  803. match = QueryRule (
  804. Data->ObjectTypeId,
  805. Data->ObjectName,
  806. Data->ObjectNode,
  807. &actionGroup,
  808. &actionFlags,
  809. &actionStruct
  810. );
  811. if (!match && !Data->ObjectLeaf) {
  812. //
  813. // If this is a node only, try matching with an empty leaf
  814. //
  815. encodedNodeOnly = IsmCreateObjectHandle (Data->ObjectNode, TEXT(""));
  816. match = QueryRule (
  817. Data->ObjectTypeId,
  818. encodedNodeOnly,
  819. Data->ObjectNode,
  820. &actionGroup,
  821. &actionFlags,
  822. &actionStruct
  823. );
  824. IsmDestroyObjectHandle (encodedNodeOnly);
  825. }
  826. if (match) {
  827. //
  828. // Mark all objects necessary for the rule to be processed. We
  829. // will do the rule's action(s) on the right side.
  830. //
  831. if ((actionGroup == ACTIONGROUP_INCLUDE) ||
  832. (actionGroup == ACTIONGROUP_INCLUDEEX) ||
  833. (actionGroup == ACTIONGROUP_RENAME) ||
  834. (actionGroup == ACTIONGROUP_RENAMEEX) ||
  835. (actionGroup == ACTIONGROUP_INCLUDERELEVANT) ||
  836. (actionGroup == ACTIONGROUP_INCLUDERELEVANTEX) ||
  837. (actionGroup == ACTIONGROUP_RENAMERELEVANT) ||
  838. (actionGroup == ACTIONGROUP_RENAMERELEVANTEX) ||
  839. (actionGroup == ACTIONGROUP_REGFILE) ||
  840. (actionGroup == ACTIONGROUP_REGFILEEX) ||
  841. (actionGroup == ACTIONGROUP_REGFOLDER) ||
  842. (actionGroup == ACTIONGROUP_REGFOLDEREX) ||
  843. (actionGroup == ACTIONGROUP_REGICON) ||
  844. (actionGroup == ACTIONGROUP_REGICONEX)
  845. ) {
  846. objectId = IsmGetObjectIdFromName (Data->ObjectTypeId, Data->ObjectName, FALSE);
  847. if (objectId) {
  848. if (actionFlags & ACTION_PERSIST) {
  849. if (!IsmIsAttributeSetOnObjectId (objectId, g_OsFileAttribute)) {
  850. IsmMakePersistentObjectId (objectId);
  851. }
  852. }
  853. if ((actionGroup == ACTIONGROUP_INCLUDERELEVANT) ||
  854. (actionGroup == ACTIONGROUP_RENAMERELEVANT)
  855. ) {
  856. IsmSetAttributeOnObjectId (objectId, g_CopyIfRelevantAttr);
  857. }
  858. if (actionFlags & ACTION_PERSIST_PATH_IN_DATA) {
  859. pSaveObjectAndFileItReferences (Data->ObjectTypeId, Data->ObjectName, &actionStruct, TRUE, actionGroup == ACTIONGROUP_REGFOLDER);
  860. }
  861. if (actionFlags & ACTION_PERSIST_ICON_IN_DATA) {
  862. pSaveObjectAndIconItReferences (Data->ObjectTypeId, Data->ObjectName, &actionStruct, TRUE);
  863. }
  864. }
  865. }
  866. }
  867. return CALLBACK_ENUM_CONTINUE;
  868. }
  869. MIG_DATAHANDLE
  870. pGetDataHandleForSrc (
  871. IN PCTSTR RenameSrc
  872. )
  873. {
  874. MIG_DATAHANDLE dataHandle;
  875. MIG_BLOB blob;
  876. //
  877. // First check hash table to see if we have an ID
  878. //
  879. if (!HtFindStringEx (g_RenameSrcTable, RenameSrc, &dataHandle, FALSE)) {
  880. blob.Type = BLOBTYPE_STRING;
  881. blob.String = RenameSrc;
  882. dataHandle = IsmRegisterOperationData (&blob);
  883. HtAddStringEx (g_RenameSrcTable, RenameSrc, &dataHandle, FALSE);
  884. }
  885. return dataHandle;
  886. }
  887. MIG_DATAHANDLE
  888. pGetDataHandleForDest (
  889. IN PCTSTR RenameDest
  890. )
  891. {
  892. MIG_DATAHANDLE dataHandle;
  893. MIG_BLOB blob;
  894. //
  895. // First check hash table to see if we have an ID
  896. //
  897. if (!HtFindStringEx (g_RenameDestTable, RenameDest, &dataHandle, FALSE)) {
  898. blob.Type = BLOBTYPE_STRING;
  899. blob.String = RenameDest;
  900. dataHandle = IsmRegisterOperationData (&blob);
  901. HtAddStringEx (g_RenameDestTable, RenameDest, &dataHandle, FALSE);
  902. }
  903. return dataHandle;
  904. }
  905. UINT
  906. PrepareActions (
  907. IN PCMIG_OBJECTENUMDATA Data,
  908. IN ULONG_PTR CallerArg
  909. )
  910. {
  911. ACTIONGROUP actionGroup;
  912. DWORD actionFlags;
  913. BOOL match;
  914. PCTSTR encodedNodeOnly;
  915. MIG_DATAHANDLE srcDataHandle;
  916. MIG_DATAHANDLE destDataHandle;
  917. ACTION_STRUCT actionStruct;
  918. MIG_OBJECTID objectId = 0;
  919. //
  920. // Obtain the best rule for this object
  921. //
  922. match = QueryRule (
  923. Data->ObjectTypeId,
  924. Data->ObjectName,
  925. Data->ObjectNode,
  926. &actionGroup,
  927. &actionFlags,
  928. &actionStruct
  929. );
  930. if (!match && !Data->ObjectLeaf) {
  931. //
  932. // If this is a node only, try matching with an empty leaf
  933. //
  934. encodedNodeOnly = IsmCreateObjectHandle (Data->ObjectNode, TEXT(""));
  935. match = QueryRule (
  936. Data->ObjectTypeId,
  937. encodedNodeOnly,
  938. Data->ObjectNode,
  939. &actionGroup,
  940. &actionFlags,
  941. &actionStruct
  942. );
  943. IsmDestroyObjectHandle (encodedNodeOnly);
  944. }
  945. if (match) {
  946. //
  947. // Mark the objects for the designated operations.
  948. //
  949. if ((actionGroup == ACTIONGROUP_INCLUDE) ||
  950. (actionGroup == ACTIONGROUP_INCLUDEEX) ||
  951. (actionGroup == ACTIONGROUP_RENAME) ||
  952. (actionGroup == ACTIONGROUP_RENAMEEX) ||
  953. (actionGroup == ACTIONGROUP_INCLUDERELEVANT) ||
  954. (actionGroup == ACTIONGROUP_INCLUDERELEVANTEX) ||
  955. (actionGroup == ACTIONGROUP_RENAMERELEVANT) ||
  956. (actionGroup == ACTIONGROUP_RENAMERELEVANTEX) ||
  957. (actionGroup == ACTIONGROUP_REGFILE) ||
  958. (actionGroup == ACTIONGROUP_REGFILEEX) ||
  959. (actionGroup == ACTIONGROUP_REGFOLDER) ||
  960. (actionGroup == ACTIONGROUP_REGFOLDEREX) ||
  961. (actionGroup == ACTIONGROUP_REGICON) ||
  962. (actionGroup == ACTIONGROUP_REGICONEX)
  963. ) {
  964. objectId = IsmGetObjectIdFromName (Data->ObjectTypeId, Data->ObjectName, FALSE);
  965. if (objectId) {
  966. if (actionFlags & ACTION_PERSIST) {
  967. if (!IsmIsAttributeSetOnObjectId (objectId, g_OsFileAttribute)) {
  968. IsmMakeApplyObjectId (objectId);
  969. }
  970. }
  971. if ((actionGroup == ACTIONGROUP_INCLUDERELEVANT) ||
  972. (actionGroup == ACTIONGROUP_RENAMERELEVANT)
  973. ) {
  974. IsmSetAttributeOnObjectId (objectId, g_CopyIfRelevantAttr);
  975. }
  976. if (actionFlags & ACTION_PERSIST_PATH_IN_DATA) {
  977. pSaveObjectAndFileItReferences (Data->ObjectTypeId, Data->ObjectName, &actionStruct, FALSE, actionGroup == ACTIONGROUP_REGFOLDER);
  978. }
  979. if (actionFlags & ACTION_PERSIST_ICON_IN_DATA) {
  980. pSaveObjectAndIconItReferences (Data->ObjectTypeId, Data->ObjectName, &actionStruct, FALSE);
  981. }
  982. }
  983. }
  984. if ((actionGroup == ACTIONGROUP_RENAME) ||
  985. (actionGroup == ACTIONGROUP_RENAMEEX) ||
  986. (actionGroup == ACTIONGROUP_RENAMERELEVANT) ||
  987. (actionGroup == ACTIONGROUP_RENAMERELEVANTEX) ||
  988. (actionGroup == ACTIONGROUP_REGFILE) ||
  989. (actionGroup == ACTIONGROUP_REGFILEEX) ||
  990. (actionGroup == ACTIONGROUP_REGFOLDER) ||
  991. (actionGroup == ACTIONGROUP_REGFOLDEREX) ||
  992. (actionGroup == ACTIONGROUP_REGICON) ||
  993. (actionGroup == ACTIONGROUP_REGICONEX)
  994. ) {
  995. if (actionStruct.ObjectDest) {
  996. if (actionStruct.ObjectBase) {
  997. srcDataHandle = pGetDataHandleForSrc (actionStruct.ObjectBase);
  998. } else {
  999. srcDataHandle = 0;
  1000. }
  1001. destDataHandle = pGetDataHandleForDest (actionStruct.ObjectDest);
  1002. if (!objectId) {
  1003. objectId = IsmGetObjectIdFromName (Data->ObjectTypeId, Data->ObjectName, FALSE);
  1004. }
  1005. if (objectId) {
  1006. if ((Data->ObjectTypeId & (~PLATFORM_MASK)) == g_FileType) {
  1007. if ((actionGroup == ACTIONGROUP_RENAMERELEVANTEX) ||
  1008. (actionGroup == ACTIONGROUP_RENAMEEX)
  1009. ) {
  1010. IsmSetOperationOnObjectId2 (
  1011. objectId,
  1012. g_RenameFileExOp,
  1013. srcDataHandle,
  1014. destDataHandle
  1015. );
  1016. } else {
  1017. IsmSetOperationOnObjectId2 (
  1018. objectId,
  1019. g_RenameFileOp,
  1020. srcDataHandle,
  1021. destDataHandle
  1022. );
  1023. }
  1024. } else {
  1025. IsmSetOperationOnObjectId2 (
  1026. objectId,
  1027. (actionGroup == ACTIONGROUP_RENAMEEX ? g_RenameExOp : g_RenameOp),
  1028. srcDataHandle,
  1029. destDataHandle
  1030. );
  1031. }
  1032. }
  1033. }
  1034. }
  1035. }
  1036. return CALLBACK_ENUM_CONTINUE;
  1037. }
  1038. UINT
  1039. NulCallback (
  1040. IN PCMIG_OBJECTENUMDATA Data,
  1041. IN ULONG_PTR CallerArg
  1042. )
  1043. {
  1044. return CALLBACK_ENUM_CONTINUE;
  1045. }
  1046. UINT
  1047. ObjectPriority (
  1048. IN PCMIG_OBJECTENUMDATA Data,
  1049. IN ULONG_PTR CallerArg
  1050. )
  1051. {
  1052. ACTIONGROUP actionGroup;
  1053. DWORD actionFlags;
  1054. BOOL match;
  1055. match = QueryRuleEx (
  1056. Data->ObjectTypeId,
  1057. Data->ObjectName,
  1058. Data->ObjectNode,
  1059. &actionGroup,
  1060. &actionFlags,
  1061. NULL,
  1062. RULEGROUP_PRIORITY
  1063. );
  1064. if (match) {
  1065. MYASSERT ((actionFlags == ACTION_PRIORITYSRC) || (actionFlags == ACTION_PRIORITYDEST));
  1066. if (actionFlags == ACTION_PRIORITYSRC) {
  1067. IsmClearAbandonObjectOnCollision (
  1068. (Data->ObjectTypeId & (~PLATFORM_MASK)) | PLATFORM_SOURCE,
  1069. Data->ObjectName
  1070. );
  1071. IsmAbandonObjectOnCollision (
  1072. (Data->ObjectTypeId & (~PLATFORM_MASK)) | PLATFORM_DESTINATION,
  1073. Data->ObjectName
  1074. );
  1075. } else {
  1076. IsmAbandonObjectOnCollision (
  1077. (Data->ObjectTypeId & (~PLATFORM_MASK)) | PLATFORM_SOURCE,
  1078. Data->ObjectName
  1079. );
  1080. IsmClearAbandonObjectOnCollision (
  1081. (Data->ObjectTypeId & (~PLATFORM_MASK)) | PLATFORM_DESTINATION,
  1082. Data->ObjectName
  1083. );
  1084. }
  1085. }
  1086. return CALLBACK_ENUM_CONTINUE;
  1087. }
  1088. UINT
  1089. FileCollPattern (
  1090. IN PCMIG_OBJECTENUMDATA Data,
  1091. IN ULONG_PTR CallerArg
  1092. )
  1093. {
  1094. ACTIONGROUP actionGroup;
  1095. DWORD actionFlags;
  1096. ACTION_STRUCT actionStruct;
  1097. BOOL match;
  1098. MIG_BLOB migBlob;
  1099. match = QueryRuleEx (
  1100. Data->ObjectTypeId,
  1101. Data->ObjectName,
  1102. Data->ObjectNode,
  1103. &actionGroup,
  1104. &actionFlags,
  1105. &actionStruct,
  1106. RULEGROUP_COLLPATTERN
  1107. );
  1108. if (match && (!(IsmIsObjectHandleNodeOnly (Data->ObjectName)))) {
  1109. // Let's set a property on this file (we don't need this for nodes)
  1110. migBlob.Type = BLOBTYPE_STRING;
  1111. migBlob.String = actionStruct.ObjectHint;
  1112. IsmAddPropertyToObject (Data->ObjectTypeId, Data->ObjectName, g_FileCollPatternData, &migBlob);
  1113. }
  1114. return CALLBACK_ENUM_CONTINUE;
  1115. }
  1116. UINT
  1117. LockPartition (
  1118. IN PCMIG_OBJECTENUMDATA Data,
  1119. IN ULONG_PTR CallerArg
  1120. )
  1121. {
  1122. IsmSetAttributeOnObject (Data->ObjectTypeId, Data->ObjectName, g_LockPartitionAttr);
  1123. return CALLBACK_ENUM_CONTINUE;
  1124. }
  1125. UINT
  1126. ExcludeKeyIfValueExists (
  1127. IN PCMIG_OBJECTENUMDATA Data,
  1128. IN ULONG_PTR CallerArg
  1129. )
  1130. {
  1131. PCTSTR srcNode = NULL;
  1132. PCTSTR srcLeaf = NULL;
  1133. // This function is only called for each registry key/value pair that
  1134. // indicates we want to cause the exclusion of the entire key.
  1135. IsmCreateObjectStringsFromHandle (Data->ObjectName, &srcNode, &srcLeaf);
  1136. // This is also called for all keys (not including a value) so we need
  1137. // to make sure a value is passed in
  1138. if (srcLeaf && *srcLeaf) {
  1139. // Exclude the srcNode
  1140. HtAddString (g_DePersistTable, srcNode);
  1141. }
  1142. IsmDestroyObjectString (srcNode);
  1143. IsmDestroyObjectString (srcLeaf);
  1144. return CALLBACK_ENUM_CONTINUE;
  1145. }
  1146. BOOL
  1147. PostDelregKeyCallback (
  1148. VOID
  1149. )
  1150. {
  1151. static BOOL called = FALSE;
  1152. HASHTABLE_ENUM hashData;
  1153. MIG_OBJECT_ENUM objectEnum;
  1154. MIG_OBJECTSTRINGHANDLE pattern;
  1155. if (called) {
  1156. return TRUE;
  1157. }
  1158. // Enumerate all Excluded keys
  1159. if (EnumFirstHashTableString (&hashData, g_DePersistTable)) {
  1160. do {
  1161. // Remove Persistence on the key
  1162. pattern = IsmCreateObjectHandle (hashData.String, NULL);
  1163. IsmClearPersistenceOnObject (g_RegType, pattern);
  1164. IsmDestroyObjectHandle (pattern);
  1165. // Enumerate each value in this key
  1166. pattern = IsmCreateSimpleObjectPattern (hashData.String, TRUE, NULL, TRUE);
  1167. if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, pattern)) {
  1168. do {
  1169. // Remove Persistence on each value
  1170. IsmClearPersistenceOnObject (objectEnum.ObjectTypeId, objectEnum.ObjectName);
  1171. } while (IsmEnumNextObject (&objectEnum));
  1172. }
  1173. IsmDestroyObjectHandle (pattern);
  1174. } while (EnumNextHashTableString (&hashData));
  1175. }
  1176. HtFree (g_DePersistTable);
  1177. g_DePersistTable = NULL;
  1178. called = TRUE;
  1179. return TRUE;
  1180. }