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.

2034 lines
59 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. opm.c
  5. Abstract:
  6. Implements the data apply portion of scanstate v1 compatiblity.
  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. #include <sddl.h>
  18. #define DBG_V1 "v1"
  19. //
  20. // Strings
  21. //
  22. #define S_RENAMEEX_START_CHAR TEXT('<')
  23. #define S_RENAMEEX_END_CHAR TEXT('>')
  24. //
  25. // Constants
  26. //
  27. // None
  28. //
  29. // Macros
  30. //
  31. // None
  32. //
  33. // Types
  34. //
  35. // None
  36. //
  37. // Globals
  38. //
  39. MIG_OPERATIONID g_V1MoveExOp;
  40. MIG_OPERATIONID g_V1MoveOp;
  41. MIG_OPERATIONID g_GeneralMoveOp;
  42. MIG_OPERATIONID g_DeleteOp;
  43. MIG_OPERATIONID g_RenameEx;
  44. MIG_OPERATIONID g_PartMoveOp;
  45. PMAPSTRUCT g_RegNodeFilterMap;
  46. PMAPSTRUCT g_RegLeafFilterMap;
  47. PMAPSTRUCT g_FileNodeFilterMap;
  48. PMAPSTRUCT g_FileLeafFilterMap;
  49. PMAPSTRUCT g_DestEnvMap;
  50. HASHTABLE g_RegCollisionDestTable;
  51. HASHTABLE g_RegCollisionSrcTable;
  52. //
  53. // Macro expansion list
  54. //
  55. // None
  56. //
  57. // Private function prototypes
  58. //
  59. OPMINITIALIZE ScriptOpmInitialize;
  60. OPMFILTERCALLBACK FilterV1MoveEx;
  61. OPMFILTERCALLBACK FilterV1Move;
  62. OPMFILTERCALLBACK FilterMove;
  63. OPMAPPLYCALLBACK DoRegAutoFilter;
  64. OPMFILTERCALLBACK FilterRegAutoFilter;
  65. OPMFILTERCALLBACK FilterFileAutoFilter;
  66. OPMFILTERCALLBACK FilterDelete;
  67. OPMAPPLYCALLBACK DoFixDefaultIcon;
  68. OPMFILTERCALLBACK FilterRenameExFilter;
  69. OPMFILTERCALLBACK FilterPartitionMove;
  70. OPMAPPLYCALLBACK DoDestAddObject;
  71. //
  72. // Macro expansion definition
  73. //
  74. // None
  75. //
  76. // Code
  77. //
  78. BOOL
  79. pParseInfForRemapEnvVar (
  80. IN HINF InfHandle
  81. )
  82. {
  83. INFSTRUCT is = INITINFSTRUCT_PMHANDLE;
  84. PCTSTR envVar;
  85. PTSTR envValue;
  86. UINT sizeNeeded;
  87. BOOL result = FALSE;
  88. __try {
  89. // on all systems, process "Delete Destination Settings"
  90. if (InfFindFirstLine (InfHandle, TEXT("RemapEnvVar"), NULL, &is)) {
  91. do {
  92. if (IsmCheckCancel()) {
  93. __leave;
  94. }
  95. envVar = InfGetStringField (&is, 1);
  96. if (!envVar) {
  97. LOG ((LOG_WARNING, (PCSTR) MSG_EMPTY_REG_SPEC));
  98. continue;
  99. }
  100. if (!IsmGetEnvironmentString (
  101. PLATFORM_DESTINATION,
  102. S_SYSENVVAR_GROUP,
  103. envVar,
  104. NULL,
  105. 0,
  106. &sizeNeeded
  107. )) {
  108. continue;
  109. }
  110. envValue = AllocPathString (sizeNeeded);
  111. if (!IsmGetEnvironmentString (
  112. PLATFORM_DESTINATION,
  113. S_SYSENVVAR_GROUP,
  114. envVar,
  115. envValue,
  116. sizeNeeded,
  117. NULL
  118. )) {
  119. FreePathString (envValue);
  120. continue;
  121. }
  122. AddRemappingEnvVar (g_DestEnvMap, g_FileNodeFilterMap, NULL, envVar, envValue);
  123. FreePathString (envValue);
  124. envValue = NULL;
  125. } while (InfFindNextLine (&is));
  126. }
  127. result = TRUE;
  128. }
  129. __finally {
  130. InfCleanUpInfStruct (&is);
  131. }
  132. return result;
  133. }
  134. BOOL
  135. pParseRemapEnvVar (
  136. VOID
  137. )
  138. {
  139. PTSTR multiSz = NULL;
  140. MULTISZ_ENUM e;
  141. UINT sizeNeeded;
  142. HINF infHandle = INVALID_HANDLE_VALUE;
  143. ENVENTRY_TYPE dataType;
  144. BOOL result = TRUE;
  145. if (IsmGetEnvironmentValue (
  146. IsmGetRealPlatform (),
  147. NULL,
  148. S_GLOBAL_INF_HANDLE,
  149. (PBYTE)(&infHandle),
  150. sizeof (HINF),
  151. &sizeNeeded,
  152. &dataType
  153. ) &&
  154. (sizeNeeded == sizeof (HINF)) &&
  155. (dataType == ENVENTRY_BINARY)
  156. ) {
  157. if (!pParseInfForRemapEnvVar (infHandle)) {
  158. result = FALSE;
  159. }
  160. } else {
  161. if (!IsmGetEnvironmentValue (IsmGetRealPlatform (), NULL, S_INF_FILE_MULTISZ, NULL, 0, &sizeNeeded, NULL)) {
  162. return TRUE; // no INF files specified
  163. }
  164. __try {
  165. multiSz = AllocText (sizeNeeded);
  166. if (!multiSz) {
  167. result = FALSE;
  168. __leave;
  169. }
  170. if (!IsmGetEnvironmentValue (IsmGetRealPlatform (), NULL, S_INF_FILE_MULTISZ, (PBYTE) multiSz, sizeNeeded, NULL, NULL)) {
  171. result = FALSE;
  172. __leave;
  173. }
  174. if (EnumFirstMultiSz (&e, multiSz)) {
  175. do {
  176. infHandle = InfOpenInfFile (e.CurrentString);
  177. if (infHandle != INVALID_HANDLE_VALUE) {
  178. if (!pParseInfForRemapEnvVar (infHandle)) {
  179. InfCloseInfFile (infHandle);
  180. infHandle = INVALID_HANDLE_VALUE;
  181. result = FALSE;
  182. __leave;
  183. }
  184. InfCloseInfFile (infHandle);
  185. infHandle = INVALID_HANDLE_VALUE;
  186. } else {
  187. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_INF, e.CurrentString));
  188. }
  189. } while (EnumNextMultiSz (&e));
  190. }
  191. }
  192. __finally {
  193. if (multiSz) {
  194. FreeText (multiSz);
  195. multiSz = NULL;
  196. }
  197. }
  198. }
  199. return result;
  200. }
  201. VOID
  202. pOutlookClearConvKeys (
  203. VOID
  204. )
  205. {
  206. MIG_CONTENT objectContent;
  207. MIG_OBJECT_ENUM objectEnum;
  208. MIG_OBJECTSTRINGHANDLE enumPattern = NULL;
  209. // This registry tree was needed only for conversion data. We don't want to
  210. // write them to the destination, so clear the apply attribute on each item.
  211. if ((IsmIsComponentSelected (S_OUTLOOK9798_COMPONENT, 0) &&
  212. IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OUTLOOK9798_APPDETECT)) ||
  213. (IsmIsComponentSelected (S_OFFICE_COMPONENT, 0) &&
  214. IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OFFICE9798_APPDETECT))) {
  215. enumPattern = IsmCreateSimpleObjectPattern (
  216. TEXT("HKLM\\Software\\Microsoft\\MS Setup (ACME)\\Table Files"),
  217. TRUE,
  218. NULL,
  219. TRUE);
  220. if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, enumPattern)) {
  221. do {
  222. IsmClearApplyOnObject (g_RegType | PLATFORM_SOURCE, objectEnum.ObjectName);
  223. } while (IsmEnumNextObject (&objectEnum));
  224. }
  225. IsmDestroyObjectHandle (enumPattern);
  226. }
  227. }
  228. BOOL
  229. WINAPI
  230. ScriptOpmInitialize (
  231. IN PMIG_LOGCALLBACK LogCallback,
  232. IN PVOID Reserved
  233. )
  234. {
  235. //
  236. // Get file and registry types
  237. //
  238. g_FileType = MIG_FILE_TYPE;
  239. g_RegType = MIG_REGISTRY_TYPE;
  240. //
  241. // Get attribute and operation types
  242. //
  243. g_V1MoveExOp = IsmRegisterOperation (S_OPERATION_V1_FILEMOVEEX, TRUE);
  244. g_V1MoveOp = IsmRegisterOperation (S_OPERATION_V1_FILEMOVE, TRUE);
  245. g_GeneralMoveOp = IsmRegisterOperation (S_OPERATION_MOVE, FALSE);
  246. g_DeleteOp = IsmRegisterOperation (S_OPERATION_DELETE, FALSE);
  247. g_DefaultIconOp = IsmRegisterOperation (S_OPERATION_DEFICON_FIXCONTENT, FALSE);
  248. g_DefaultIconData = IsmRegisterProperty (S_V1PROP_ICONDATA, FALSE);
  249. g_FileCollPatternData = IsmRegisterProperty (S_V1PROP_FILECOLLPATTERN, FALSE);
  250. g_RenameExOp = IsmRegisterOperation (S_OPERATION_ENHANCED_MOVE, FALSE);
  251. g_PartMoveOp = IsmRegisterOperation (S_OPERATION_PARTITION_MOVE, TRUE);
  252. g_DestAddObject = IsmRegisterOperation (S_OPERATION_DESTADDOBJ, FALSE);
  253. g_RegAutoFilterOp = IsmRegisterOperation (S_OPERATION_REG_AUTO_FILTER, FALSE);
  254. //
  255. // Register operation callbacks
  256. //
  257. // FYI: Filter callbacks adjust the name of the object
  258. // Apply callbacks adjust the content of the object
  259. // global operation callbacks
  260. IsmRegisterGlobalApplyCallback (g_RegType | PLATFORM_SOURCE, TEXT("AutoFilter"), DoRegAutoFilter);
  261. IsmRegisterGlobalFilterCallback (g_RegType | PLATFORM_SOURCE, TEXT("AutoFilter"), FilterRegAutoFilter, TRUE, FALSE);
  262. IsmRegisterGlobalFilterCallback (g_FileType | PLATFORM_SOURCE, TEXT("AutoFilter"), FilterFileAutoFilter, TRUE, TRUE);
  263. // operation-specific callbacks
  264. IsmRegisterOperationFilterCallback (g_V1MoveExOp, FilterV1MoveEx, TRUE, TRUE, FALSE);
  265. IsmRegisterOperationFilterCallback (g_V1MoveOp, FilterV1Move, TRUE, TRUE, FALSE);
  266. IsmRegisterOperationFilterCallback (g_GeneralMoveOp, FilterMove, TRUE, TRUE, FALSE);
  267. IsmRegisterOperationFilterCallback (g_DeleteOp, FilterDelete, FALSE, TRUE, FALSE);
  268. IsmRegisterOperationApplyCallback (g_DefaultIconOp, DoFixDefaultIcon, TRUE);
  269. IsmRegisterOperationFilterCallback (g_RenameExOp, FilterRenameExFilter, TRUE, TRUE, FALSE);
  270. IsmRegisterOperationFilterCallback (g_PartMoveOp, FilterPartitionMove, TRUE, TRUE, FALSE);
  271. IsmRegisterOperationApplyCallback (g_DestAddObject, DoDestAddObject, TRUE);
  272. IsmRegisterOperationApplyCallback (g_RegAutoFilterOp, DoRegAutoFilter, TRUE);
  273. //
  274. // Call special conversion entry point
  275. //
  276. InitSpecialConversion (PLATFORM_DESTINATION);
  277. InitSpecialRename (PLATFORM_DESTINATION);
  278. g_RegNodeFilterMap = CreateStringMapping();
  279. g_FileNodeFilterMap = CreateStringMapping();
  280. g_DestEnvMap = CreateStringMapping();
  281. SetIsmEnvironmentFromPhysicalMachine (g_DestEnvMap, FALSE, NULL);
  282. SetIsmEnvironmentFromPhysicalMachine (g_FileNodeFilterMap, TRUE, NULL);
  283. pParseRemapEnvVar ();
  284. g_RegLeafFilterMap = CreateStringMapping();
  285. g_FileLeafFilterMap = CreateStringMapping();
  286. if ((!g_EnvMap) || (!g_RevEnvMap) || (!g_UndefMap)) {
  287. g_EnvMap = CreateStringMapping();
  288. g_UndefMap = CreateStringMapping();
  289. g_RevEnvMap = CreateStringMapping();
  290. SetIsmEnvironmentFromVirtualMachine (g_EnvMap, g_RevEnvMap, g_UndefMap);
  291. }
  292. g_RegCollisionDestTable = HtAllocWithData (sizeof (MIG_OBJECTSTRINGHANDLE));
  293. g_RegCollisionSrcTable = HtAllocWithData (sizeof (HASHITEM));
  294. InitRestoreCallback (PLATFORM_DESTINATION);
  295. pOutlookClearConvKeys();
  296. return TRUE;
  297. }
  298. BOOL
  299. pDoesDifferentRegExist (
  300. IN MIG_OBJECTSTRINGHANDLE DestName
  301. )
  302. {
  303. BOOL result = FALSE;
  304. MIG_CONTENT content;
  305. if (IsmAcquireObject (g_RegType|PLATFORM_DESTINATION, DestName, &content)) {
  306. IsmReleaseObject (&content);
  307. result = TRUE;
  308. } else if (HtFindString (g_RegCollisionDestTable, DestName)) {
  309. result = TRUE;
  310. }
  311. return result;
  312. }
  313. BOOL
  314. WINAPI
  315. FilterV1MoveEx (
  316. IN PCMIG_FILTERINPUT InputData,
  317. OUT PMIG_FILTEROUTPUT OutputData,
  318. IN BOOL NoRestoreObject,
  319. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  320. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  321. )
  322. {
  323. PCTSTR orgSrcNode = NULL;
  324. PCTSTR orgSrcLeaf = NULL;
  325. PCTSTR srcNode = NULL;
  326. PCTSTR srcLeaf = NULL;
  327. PCTSTR destNode = NULL;
  328. PCTSTR destLeaf = NULL;
  329. PCTSTR newDestNode = NULL;
  330. PCTSTR destNodePtr = NULL;
  331. // NTRAID#NTBUG9-153274-2000/08/01-jimschm Static buffer size
  332. TCHAR expDestNode[MAX_PATH * 4];
  333. TCHAR expDestLeaf[MAX_PATH * 4];
  334. CHARTYPE ch;
  335. MIG_OBJECTSTRINGHANDLE destHandle;
  336. __try {
  337. //
  338. // For v1 compatibility, we support only a transformation from
  339. // original source to inf-specified destination. Chaining of
  340. // operations is not allowed (these are restrictions caused by the
  341. // existing INF syntax).
  342. //
  343. if (!DestinationOperationData) {
  344. DEBUGMSG ((DBG_ERROR, "Missing dest data in FilterV1MoveEx"));
  345. __leave;
  346. }
  347. if ((InputData->CurrentObject.ObjectTypeId & (~PLATFORM_MASK)) != g_FileType) {
  348. DEBUGMSG ((DBG_ERROR, "Unexpected object type in FilterV1MoveEx"));
  349. __leave;
  350. }
  351. if (!IsmCreateObjectStringsFromHandle (
  352. DestinationOperationData->String,
  353. &destNode,
  354. &destLeaf
  355. )) {
  356. DEBUGMSG ((DBG_ERROR, "Can't split dest object in FilterV1MoveEx"));
  357. __leave;
  358. }
  359. MYASSERT (destNode);
  360. if (!destNode) {
  361. DEBUGMSG ((DBG_ERROR, "Destination spec must be a node"));
  362. __leave;
  363. }
  364. //
  365. // Split the source object into node and leaf
  366. //
  367. if (!IsmCreateObjectStringsFromHandle (
  368. InputData->CurrentObject.ObjectName,
  369. &srcNode,
  370. &srcLeaf
  371. )) {
  372. DEBUGMSG ((DBG_ERROR, "Can't split v1 src object in FilterV1MoveEx"));
  373. __leave;
  374. }
  375. if (!srcNode) {
  376. MYASSERT (FALSE);
  377. __leave;
  378. }
  379. //
  380. // If not a local path, do not process
  381. //
  382. if (!_istalpha ((CHARTYPE) _tcsnextc (srcNode)) ||
  383. _tcsnextc (srcNode + 1) != TEXT(':')
  384. ) {
  385. DEBUGMSG ((DBG_WARNING, "Ignoring %s\\%s because it does not have a drive spec", srcNode, srcLeaf));
  386. __leave;
  387. }
  388. ch = (CHARTYPE) _tcsnextc (srcNode + 2);
  389. if (ch && ch != TEXT('\\')) {
  390. DEBUGMSG ((DBG_WARNING, "Ignoring %s\\%s because it does not have a drive spec (2)", srcNode, srcLeaf));
  391. __leave;
  392. }
  393. // let's see if the current name has something in common
  394. // with SourceOperationData->String. If so, get the extra part
  395. // and add it to the destNode
  396. //
  397. // Split the original rule source object into node and leaf
  398. //
  399. if (SourceOperationData) {
  400. if (IsmCreateObjectStringsFromHandle (
  401. SourceOperationData->String,
  402. &orgSrcNode,
  403. &orgSrcLeaf
  404. )) {
  405. if (orgSrcNode) {
  406. if (StringIPrefix (srcNode, orgSrcNode)) {
  407. destNodePtr = srcNode + TcharCount (orgSrcNode);
  408. if (destNodePtr && *destNodePtr) {
  409. if (_tcsnextc (destNodePtr) == TEXT('\\')) {
  410. destNodePtr = _tcsinc (destNodePtr);
  411. }
  412. if (destNodePtr) {
  413. newDestNode = JoinPaths (destNode, destNodePtr);
  414. }
  415. }
  416. }
  417. }
  418. }
  419. }
  420. if (!newDestNode) {
  421. newDestNode = destNode;
  422. }
  423. //
  424. // Expand the destination
  425. //
  426. MappingSearchAndReplaceEx (
  427. g_DestEnvMap,
  428. newDestNode,
  429. expDestNode,
  430. 0,
  431. NULL,
  432. MAX_PATH,
  433. STRMAP_FIRST_CHAR_MUST_MATCH,
  434. NULL,
  435. NULL
  436. );
  437. if (destLeaf) {
  438. MappingSearchAndReplaceEx (
  439. g_DestEnvMap,
  440. destLeaf,
  441. expDestLeaf,
  442. 0,
  443. NULL,
  444. MAX_PATH,
  445. STRMAP_FIRST_CHAR_MUST_MATCH,
  446. NULL,
  447. NULL
  448. );
  449. }
  450. if (destLeaf) {
  451. destHandle = IsmCreateObjectHandle (expDestNode, expDestLeaf);
  452. } else {
  453. destHandle = IsmCreateObjectHandle (expDestNode, srcLeaf);
  454. }
  455. if (destHandle) {
  456. OutputData->NewObject.ObjectName = destHandle;
  457. }
  458. }
  459. __finally {
  460. if (newDestNode && (newDestNode != destNode)) {
  461. FreePathString (newDestNode);
  462. newDestNode = NULL;
  463. }
  464. IsmDestroyObjectString (orgSrcNode);
  465. IsmDestroyObjectString (orgSrcLeaf);
  466. IsmDestroyObjectString (destNode);
  467. IsmDestroyObjectString (destLeaf);
  468. IsmDestroyObjectString (srcNode);
  469. IsmDestroyObjectString (srcLeaf);
  470. }
  471. return TRUE;
  472. }
  473. BOOL
  474. WINAPI
  475. FilterV1Move (
  476. IN PCMIG_FILTERINPUT InputData,
  477. OUT PMIG_FILTEROUTPUT OutputData,
  478. IN BOOL NoRestoreObject,
  479. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  480. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  481. )
  482. {
  483. PCTSTR destNode = NULL;
  484. // NTRAID#NTBUG9-153274-2000/08/01-jimschm Static buffer size
  485. TCHAR expDest[MAX_PATH * 4];
  486. PCTSTR destLeaf = NULL;
  487. PCTSTR srcNode = NULL;
  488. PCTSTR srcLeaf = NULL;
  489. PCTSTR pathStart;
  490. // NTRAID#NTBUG9-153274-2000/08/01-jimschm Static buffer size
  491. TCHAR pathCopy[MAX_PATH * 4];
  492. PCTSTR newDestNode = NULL;
  493. PCTSTR newerDestNode = NULL;
  494. PCTSTR subPath;
  495. BOOL b;
  496. CHARTYPE ch;
  497. MIG_OBJECTSTRINGHANDLE destHandle;
  498. __try {
  499. //
  500. // For v1 compatibility, we support only a transformation from
  501. // original source to inf-specified destination. Chaining of
  502. // operations is not allowed (these are restrictions caused by the
  503. // existing INF syntax).
  504. //
  505. if (!DestinationOperationData) {
  506. DEBUGMSG ((DBG_ERROR, "Missing dest data in FilterV1Move"));
  507. __leave;
  508. }
  509. if ((InputData->CurrentObject.ObjectTypeId & (~PLATFORM_MASK)) != g_FileType) {
  510. DEBUGMSG ((DBG_ERROR, "Unexpected object type in FilterV1Move"));
  511. __leave;
  512. }
  513. if (!IsmCreateObjectStringsFromHandle (
  514. DestinationOperationData->String,
  515. &destNode,
  516. &destLeaf
  517. )) {
  518. DEBUGMSG ((DBG_ERROR, "Can't split dest object in FilterV1Move"));
  519. __leave;
  520. }
  521. MYASSERT (destNode);
  522. if (!destNode) {
  523. DEBUGMSG ((DBG_ERROR, "Destination spec must be a node"));
  524. __leave;
  525. }
  526. if (destLeaf) {
  527. DEBUGMSG ((DBG_WARNING, "Dest leaf specification %s (in %s) ignored", destLeaf, destNode));
  528. }
  529. //
  530. // Find the longest CSIDL inside InputData. Take that as the base directory,
  531. // and take the rest as the subdirectory.
  532. //
  533. if (!IsmCreateObjectStringsFromHandle (
  534. InputData->CurrentObject.ObjectName,
  535. &srcNode,
  536. &srcLeaf
  537. )) {
  538. DEBUGMSG ((DBG_ERROR, "Can't split v1 src object in FilterV1Move"));
  539. __leave;
  540. }
  541. if (!srcNode) {
  542. MYASSERT (FALSE);
  543. __leave;
  544. }
  545. //
  546. // If not a local path, do not process
  547. //
  548. if (!_istalpha ((CHARTYPE) _tcsnextc (srcNode)) ||
  549. _tcsnextc (srcNode + 1) != TEXT(':')
  550. ) {
  551. DEBUGMSG ((DBG_WARNING, "Ignoring %s\\%s because it does not have a drive spec", srcNode, srcLeaf));
  552. __leave;
  553. }
  554. ch = (CHARTYPE) _tcsnextc (srcNode + 2);
  555. if (ch && ch != TEXT('\\')) {
  556. DEBUGMSG ((DBG_WARNING, "Ignoring %s\\%s because it does not have a drive spec (2)", srcNode, srcLeaf));
  557. __leave;
  558. }
  559. //
  560. // Expand the destination
  561. //
  562. b = MappingSearchAndReplaceEx (
  563. g_DestEnvMap,
  564. destNode,
  565. expDest,
  566. 0,
  567. NULL,
  568. MAX_PATH,
  569. STRMAP_FIRST_CHAR_MUST_MATCH,
  570. NULL,
  571. NULL
  572. );
  573. //
  574. // Skip over the drive spec
  575. //
  576. pathStart = srcNode;
  577. //
  578. // Find the longest CSIDL by using the reverse mapping table. This takes
  579. // our full path spec in pathStart and encodes it with an environment
  580. // variable.
  581. //
  582. b = MappingSearchAndReplaceEx (
  583. g_RevEnvMap,
  584. pathStart,
  585. pathCopy,
  586. 0,
  587. NULL,
  588. ARRAYSIZE(pathCopy),
  589. STRMAP_FIRST_CHAR_MUST_MATCH|
  590. STRMAP_RETURN_AFTER_FIRST_REPLACE|
  591. STRMAP_REQUIRE_WACK_OR_NUL,
  592. NULL,
  593. &subPath
  594. );
  595. #ifdef DEBUG
  596. if (!b) {
  597. TCHAR debugBuf[MAX_PATH];
  598. if (MappingSearchAndReplaceEx (
  599. g_RevEnvMap,
  600. pathStart,
  601. debugBuf,
  602. 0,
  603. NULL,
  604. ARRAYSIZE(debugBuf),
  605. STRMAP_FIRST_CHAR_MUST_MATCH|STRMAP_RETURN_AFTER_FIRST_REPLACE,
  606. NULL,
  607. NULL
  608. )) {
  609. DEBUGMSG ((DBG_WARNING, "Ignoring conversion: %s -> %s", pathStart, debugBuf));
  610. }
  611. }
  612. #endif
  613. if (!b) {
  614. subPath = pathStart + (UINT) (ch ? 3 : 2);
  615. *pathCopy = 0;
  616. } else {
  617. if (*subPath) {
  618. MYASSERT (_tcsnextc (subPath) == TEXT('\\'));
  619. *(PTSTR) subPath = 0;
  620. subPath++;
  621. }
  622. }
  623. //
  624. // pathCopy gives us the base, with CSIDL_ environment variables (might be an empty string)
  625. // subPath gives us the subdir (might also be an empty string)
  626. //
  627. // append subPath to the destination node
  628. //
  629. if (*subPath) {
  630. newDestNode = JoinPaths (expDest, subPath);
  631. } else {
  632. newDestNode = expDest;
  633. }
  634. destHandle = IsmCreateObjectHandle (newDestNode, srcLeaf);
  635. if (destHandle) {
  636. OutputData->NewObject.ObjectName = destHandle;
  637. }
  638. }
  639. __finally {
  640. IsmDestroyObjectString (destNode);
  641. IsmDestroyObjectString (destLeaf);
  642. IsmDestroyObjectString (srcNode);
  643. IsmDestroyObjectString (srcLeaf);
  644. if (newDestNode != expDest) {
  645. FreePathString (newDestNode);
  646. }
  647. }
  648. return TRUE;
  649. }
  650. BOOL
  651. WINAPI
  652. FilterMove (
  653. IN PCMIG_FILTERINPUT InputData,
  654. OUT PMIG_FILTEROUTPUT OutputData,
  655. IN BOOL NoRestoreObject,
  656. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  657. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  658. )
  659. {
  660. PCTSTR srcNode = NULL;
  661. PCTSTR srcLeaf = NULL;
  662. PCTSTR baseNode = NULL;
  663. PCTSTR baseLeaf = NULL;
  664. PCTSTR destNode = NULL;
  665. PCTSTR destLeaf = NULL;
  666. PCTSTR node;
  667. PCTSTR leaf;
  668. UINT baseNodeLen;
  669. __try {
  670. //
  671. // Take InputData, break it into node & leaf, take DestinationOperationData,
  672. // do the same, then replace InputData's node & leaf as appropriate.
  673. //
  674. if (!SourceOperationData) {
  675. DEBUGMSG ((DBG_ERROR, "Missing source data in general move operation"));
  676. __leave;
  677. }
  678. if (!DestinationOperationData) {
  679. DEBUGMSG ((DBG_ERROR, "Missing destination data in general move operation"));
  680. __leave;
  681. }
  682. if (!IsmCreateObjectStringsFromHandle (
  683. InputData->CurrentObject.ObjectName,
  684. &srcNode,
  685. &srcLeaf
  686. )) {
  687. DEBUGMSG ((DBG_ERROR, "Can't split src object in general move operation"));
  688. __leave;
  689. }
  690. if (!IsmCreateObjectStringsFromHandle (
  691. SourceOperationData->String,
  692. &baseNode,
  693. &baseLeaf
  694. )) {
  695. DEBUGMSG ((DBG_ERROR, "Can't split src object in general move operation"));
  696. __leave;
  697. }
  698. if (!IsmCreateObjectStringsFromHandle (
  699. DestinationOperationData->String,
  700. &destNode,
  701. &destLeaf
  702. )) {
  703. DEBUGMSG ((DBG_ERROR, "Can't split dest object in general move operation"));
  704. __leave;
  705. }
  706. baseNodeLen = TcharCount (baseNode);
  707. node = NULL;
  708. leaf = NULL;
  709. if (StringIMatchTcharCount (srcNode, baseNode, baseNodeLen)) {
  710. if (srcNode [baseNodeLen]) {
  711. node = JoinPaths (destNode, &(srcNode [baseNodeLen]));
  712. } else {
  713. node = DuplicatePathString (destNode, 0);
  714. }
  715. if (!baseLeaf && !destLeaf) {
  716. leaf = srcLeaf;
  717. } else if (baseLeaf && srcLeaf && StringIMatch (srcLeaf, baseLeaf)) {
  718. leaf = destLeaf?destLeaf:baseLeaf;
  719. } else if (!baseLeaf && destLeaf) {
  720. if (srcLeaf) {
  721. leaf = destLeaf;
  722. }
  723. } else {
  724. FreePathString (node);
  725. node = NULL;
  726. }
  727. }
  728. if (node) {
  729. OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, leaf);
  730. FreePathString (node);
  731. node = NULL;
  732. }
  733. }
  734. __finally {
  735. IsmDestroyObjectString (srcNode);
  736. IsmDestroyObjectString (srcLeaf);
  737. IsmDestroyObjectString (baseNode);
  738. IsmDestroyObjectString (baseLeaf);
  739. IsmDestroyObjectString (destNode);
  740. IsmDestroyObjectString (destLeaf);
  741. }
  742. return TRUE;
  743. }
  744. BOOL
  745. WINAPI
  746. FilterDelete (
  747. IN PCMIG_FILTERINPUT InputData,
  748. OUT PMIG_FILTEROUTPUT OutputData,
  749. IN BOOL NoRestoreObject,
  750. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  751. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  752. )
  753. {
  754. //
  755. // Mark the output data as deleted. That will be sufficient to
  756. // cause the object to be deleted (even if it was also marked as
  757. // "save")
  758. //
  759. OutputData->Deleted = TRUE;
  760. return TRUE;
  761. }
  762. BOOL
  763. WINAPI
  764. FilterRegAutoFilter (
  765. IN PCMIG_FILTERINPUT InputData,
  766. OUT PMIG_FILTEROUTPUT OutputData,
  767. IN BOOL NoRestoreObject,
  768. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  769. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  770. )
  771. {
  772. PCTSTR node = NULL;
  773. PCTSTR leaf = NULL;
  774. // NTRAID#NTBUG9-153275-2000/08/01-jimschm Static buffer size
  775. TCHAR newNode[MAX_PATH * 4];
  776. TCHAR newLeaf[MAX_PATH * 4];
  777. BOOL change = FALSE;
  778. //
  779. // Filter the object name
  780. //
  781. IsmCreateObjectStringsFromHandle (
  782. InputData->CurrentObject.ObjectName,
  783. &node,
  784. &leaf
  785. );
  786. if (node) {
  787. if (MappingSearchAndReplaceEx (
  788. g_RegNodeFilterMap, // map handle
  789. node, // source string
  790. newNode, // dest buffer
  791. 0, // source string bytes (0=unspecified)
  792. NULL, // dest bytes required
  793. ARRAYSIZE(newNode), // dest buffer size
  794. 0, // flags
  795. NULL, // extra data value
  796. NULL // end of string
  797. )) {
  798. IsmDestroyObjectString (node);
  799. node = newNode;
  800. change = TRUE;
  801. }
  802. }
  803. if (leaf) {
  804. if (MappingSearchAndReplaceEx (
  805. g_RegLeafFilterMap,
  806. leaf,
  807. newLeaf,
  808. 0,
  809. NULL,
  810. ARRAYSIZE(newLeaf),
  811. 0,
  812. NULL,
  813. NULL
  814. )) {
  815. IsmDestroyObjectString (leaf);
  816. leaf = newLeaf;
  817. change = TRUE;
  818. }
  819. }
  820. if (change) {
  821. OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, leaf);
  822. }
  823. if (node != newNode) {
  824. IsmDestroyObjectString (node);
  825. }
  826. if (leaf != newLeaf) {
  827. IsmDestroyObjectString (leaf);
  828. }
  829. return TRUE;
  830. }
  831. BOOL
  832. pOpmFindFile (
  833. IN PCTSTR FileName
  834. )
  835. {
  836. MIG_OBJECTSTRINGHANDLE objectName;
  837. PTSTR node, leaf, leafPtr;
  838. BOOL result = FALSE;
  839. objectName = IsmCreateObjectHandle (FileName, NULL);
  840. if (objectName) {
  841. if (IsmGetObjectIdFromName (MIG_FILE_TYPE | PLATFORM_SOURCE, objectName, TRUE) != 0) {
  842. result = TRUE;
  843. }
  844. IsmDestroyObjectHandle (objectName);
  845. }
  846. if (!result) {
  847. node = DuplicateText (FileName);
  848. leaf = _tcsrchr (node, TEXT('\\'));
  849. if (leaf) {
  850. leafPtr = (PTSTR) leaf;
  851. leaf = _tcsinc (leaf);
  852. *leafPtr = 0;
  853. objectName = IsmCreateObjectHandle (node, leaf);
  854. if (objectName) {
  855. if (IsmGetObjectIdFromName (MIG_FILE_TYPE | PLATFORM_SOURCE, objectName, TRUE) != 0) {
  856. result = TRUE;
  857. }
  858. IsmDestroyObjectHandle (objectName);
  859. }
  860. *leafPtr = TEXT('\\');
  861. }
  862. FreeText (node);
  863. }
  864. return result;
  865. }
  866. BOOL
  867. pOpmSearchPath (
  868. IN PCTSTR FileName,
  869. IN DWORD BufferLength,
  870. OUT PTSTR Buffer
  871. )
  872. {
  873. return FALSE;
  874. }
  875. MIG_OBJECTSTRINGHANDLE
  876. pSimpleTryHandle (
  877. IN PCTSTR FullPath
  878. )
  879. {
  880. PCTSTR buffer;
  881. PTSTR leafPtr, leaf;
  882. MIG_OBJECTSTRINGHANDLE source = NULL;
  883. MIG_OBJECTSTRINGHANDLE result = NULL;
  884. PTSTR workingPath;
  885. PCTSTR sanitizedPath;
  886. BOOL orgDeleted = FALSE;
  887. BOOL orgReplaced = FALSE;
  888. PCTSTR saved = NULL;
  889. sanitizedPath = SanitizePath (FullPath);
  890. if (!sanitizedPath) {
  891. return NULL;
  892. }
  893. source = IsmCreateObjectHandle (sanitizedPath, NULL);
  894. if (source) {
  895. result = IsmFilterObject (
  896. g_FileType | PLATFORM_SOURCE,
  897. source,
  898. NULL,
  899. &orgDeleted,
  900. &orgReplaced
  901. );
  902. // we do not want replaced directories
  903. // since they can be false hits
  904. if (orgDeleted && orgReplaced) {
  905. if (result) {
  906. saved = result;
  907. result = NULL;
  908. }
  909. }
  910. if (!result && !orgDeleted) {
  911. result = source;
  912. } else {
  913. IsmDestroyObjectHandle (source);
  914. source = NULL;
  915. }
  916. }
  917. if (result) {
  918. goto exit;
  919. }
  920. buffer = DuplicatePathString (sanitizedPath, 0);
  921. leaf = _tcsrchr (buffer, TEXT('\\'));
  922. if (leaf) {
  923. leafPtr = leaf;
  924. leaf = _tcsinc (leaf);
  925. *leafPtr = 0;
  926. source = IsmCreateObjectHandle (buffer, leaf);
  927. *leafPtr = TEXT('\\');
  928. }
  929. FreePathString (buffer);
  930. if (source) {
  931. result = IsmFilterObject (
  932. g_FileType | PLATFORM_SOURCE,
  933. source,
  934. NULL,
  935. &orgDeleted,
  936. &orgReplaced
  937. );
  938. if (!result && !orgDeleted) {
  939. result = source;
  940. } else {
  941. if (!result) {
  942. result = saved;
  943. }
  944. IsmDestroyObjectHandle (source);
  945. source = NULL;
  946. }
  947. }
  948. if (result != saved) {
  949. IsmDestroyObjectHandle (saved);
  950. saved = NULL;
  951. }
  952. exit:
  953. FreePathString (sanitizedPath);
  954. return result;
  955. }
  956. MIG_OBJECTSTRINGHANDLE
  957. pTryHandle (
  958. IN PCTSTR FullPath,
  959. IN PCTSTR Hint,
  960. OUT PCTSTR *TrimmedResult
  961. )
  962. {
  963. PATH_ENUM pathEnum;
  964. PCTSTR newPath;
  965. MIG_OBJECTSTRINGHANDLE result = NULL;
  966. PCTSTR nativeName = NULL;
  967. PCTSTR lastSegPtr;
  968. if (TrimmedResult) {
  969. *TrimmedResult = NULL;
  970. }
  971. result = pSimpleTryHandle (FullPath);
  972. if (result || (!Hint)) {
  973. return result;
  974. }
  975. if (EnumFirstPathEx (&pathEnum, Hint, NULL, NULL, FALSE)) {
  976. do {
  977. newPath = JoinPaths (pathEnum.PtrCurrPath, FullPath);
  978. result = pSimpleTryHandle (newPath);
  979. if (result) {
  980. AbortPathEnum (&pathEnum);
  981. FreePathString (newPath);
  982. // now, if the initial FullPath did not have any wack in it
  983. // we will take the last segment of the result and put it
  984. // in TrimmedResult
  985. if (TrimmedResult && (!_tcschr (FullPath, TEXT('\\')))) {
  986. nativeName = IsmGetNativeObjectName (g_FileType, result);
  987. if (nativeName) {
  988. lastSegPtr = _tcsrchr (nativeName, TEXT('\\'));
  989. if (lastSegPtr) {
  990. lastSegPtr = _tcsinc (lastSegPtr);
  991. if (lastSegPtr) {
  992. *TrimmedResult = DuplicatePathString (lastSegPtr, 0);
  993. }
  994. }
  995. }
  996. }
  997. return result;
  998. }
  999. FreePathString (newPath);
  1000. } while (EnumNextPath (&pathEnum));
  1001. }
  1002. AbortPathEnum (&pathEnum);
  1003. return NULL;
  1004. }
  1005. BOOL
  1006. WINAPI
  1007. DoRegAutoFilter (
  1008. IN MIG_OBJECTTYPEID SrcObjectTypeId,
  1009. IN MIG_OBJECTSTRINGHANDLE SrcObjectName,
  1010. IN PCMIG_CONTENT OriginalContent,
  1011. IN PCMIG_CONTENT CurrentContent,
  1012. OUT PMIG_CONTENT NewContent,
  1013. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1014. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1015. )
  1016. {
  1017. PTSTR leafPtr = NULL;
  1018. PDWORD valueType;
  1019. MIG_OBJECTSTRINGHANDLE source;
  1020. MIG_OBJECTSTRINGHANDLE destination;
  1021. PCTSTR leaf;
  1022. TCHAR expandBuffer[4096];
  1023. TCHAR hintBuffer[4096];
  1024. PTSTR buffer;
  1025. GROWBUFFER result = INIT_GROWBUFFER;
  1026. GROWBUFFER cmdLineBuffer = INIT_GROWBUFFER;
  1027. PCMDLINE cmdLine;
  1028. UINT u;
  1029. PCTSTR data, p, end;
  1030. PCTSTR nativeDest;
  1031. PCTSTR newData, oldData;
  1032. BOOL parsable;
  1033. BOOL replaced = FALSE;
  1034. BOOL orgDeleted = FALSE;
  1035. BOOL orgReplaced = FALSE;
  1036. PCTSTR trimmedResult = NULL;
  1037. BOOL newContent = TRUE;
  1038. PCTSTR destResult = NULL;
  1039. //
  1040. // Filter the data for any references to %windir%
  1041. //
  1042. if (!CurrentContent->ContentInFile) {
  1043. parsable = FALSE;
  1044. valueType = (PDWORD)(CurrentContent->Details.DetailsData);
  1045. if (valueType) {
  1046. if (*valueType == REG_EXPAND_SZ ||
  1047. *valueType == REG_SZ
  1048. ) {
  1049. parsable = TRUE;
  1050. }
  1051. } else {
  1052. parsable = IsmIsObjectHandleNodeOnly (SrcObjectName);
  1053. }
  1054. if (parsable) {
  1055. data = (PTSTR) CurrentContent->MemoryContent.ContentBytes;
  1056. end = (PCTSTR) (CurrentContent->MemoryContent.ContentBytes + CurrentContent->MemoryContent.ContentSize);
  1057. while (data < end) {
  1058. if (*data == 0) {
  1059. break;
  1060. }
  1061. data = _tcsinc (data);
  1062. }
  1063. if (data >= end) {
  1064. parsable = FALSE;
  1065. }
  1066. }
  1067. if (parsable) {
  1068. data = (PTSTR) CurrentContent->MemoryContent.ContentBytes;
  1069. if ((*valueType == REG_EXPAND_SZ) ||
  1070. (*valueType == REG_SZ)
  1071. ) {
  1072. //
  1073. // Expand the data
  1074. //
  1075. MappingSearchAndReplaceEx (
  1076. g_EnvMap,
  1077. data,
  1078. expandBuffer,
  1079. 0,
  1080. NULL,
  1081. ARRAYSIZE(expandBuffer),
  1082. 0,
  1083. NULL,
  1084. NULL
  1085. );
  1086. data = expandBuffer;
  1087. }
  1088. *hintBuffer = 0;
  1089. if (DestinationOperationData &&
  1090. (DestinationOperationData->Type == BLOBTYPE_STRING) &&
  1091. (DestinationOperationData->String)
  1092. ) {
  1093. MappingSearchAndReplaceEx (
  1094. g_EnvMap,
  1095. DestinationOperationData->String,
  1096. hintBuffer,
  1097. 0,
  1098. NULL,
  1099. ARRAYSIZE(hintBuffer),
  1100. 0,
  1101. NULL,
  1102. NULL
  1103. );
  1104. }
  1105. destination = pTryHandle (data, *hintBuffer?hintBuffer:NULL, &trimmedResult);
  1106. if (destination) {
  1107. replaced = TRUE;
  1108. if (trimmedResult) {
  1109. GbAppendString (&result, trimmedResult);
  1110. FreePathString (trimmedResult);
  1111. } else {
  1112. nativeDest = IsmGetNativeObjectName (g_FileType, destination);
  1113. GbAppendString (&result, nativeDest);
  1114. IsmReleaseMemory (nativeDest);
  1115. }
  1116. }
  1117. // finally, if we failed we are going to assume it's a command line
  1118. if (!replaced) {
  1119. newData = DuplicatePathString (data, 0);
  1120. cmdLine = ParseCmdLineEx (data, NULL, &pOpmFindFile, &pOpmSearchPath, &cmdLineBuffer);
  1121. if (cmdLine) {
  1122. //
  1123. // Find the file referenced in the list or command line
  1124. //
  1125. for (u = 0 ; u < cmdLine->ArgCount ; u++) {
  1126. p = cmdLine->Args[u].CleanedUpArg;
  1127. // first we try it as is
  1128. destination = pTryHandle (p, *hintBuffer?hintBuffer:NULL, &trimmedResult);
  1129. // maybe we have something like /m:c:\foo.txt
  1130. // we need to go forward until we find a sequence of
  1131. // <alpha>:\<something>
  1132. if (!destination && p[0] && p[1]) {
  1133. while (p[2]) {
  1134. if (_istalpha ((CHARTYPE) _tcsnextc (p)) &&
  1135. p[1] == TEXT(':') &&
  1136. p[2] == TEXT('\\')
  1137. ) {
  1138. destination = pTryHandle (p, *hintBuffer?hintBuffer:NULL, &trimmedResult);
  1139. if (destination) {
  1140. break;
  1141. }
  1142. }
  1143. p ++;
  1144. }
  1145. }
  1146. if (destination) {
  1147. replaced = TRUE;
  1148. if (trimmedResult) {
  1149. oldData = StringSearchAndReplace (newData, p, trimmedResult);
  1150. if (oldData) {
  1151. FreePathString (newData);
  1152. newData = oldData;
  1153. }
  1154. FreePathString (trimmedResult);
  1155. } else {
  1156. nativeDest = IsmGetNativeObjectName (g_FileType, destination);
  1157. oldData = StringSearchAndReplace (newData, p, nativeDest);
  1158. if (oldData) {
  1159. FreePathString (newData);
  1160. newData = oldData;
  1161. }
  1162. IsmReleaseMemory (nativeDest);
  1163. }
  1164. IsmDestroyObjectHandle (destination);
  1165. destination = NULL;
  1166. }
  1167. }
  1168. }
  1169. GbFree (&cmdLineBuffer);
  1170. if (!replaced) {
  1171. if (newData) {
  1172. FreePathString (newData);
  1173. }
  1174. } else {
  1175. if (newData) {
  1176. GbAppendString (&result, newData);
  1177. FreePathString (newData);
  1178. }
  1179. }
  1180. }
  1181. if (destination) {
  1182. IsmDestroyObjectHandle (destination);
  1183. destination = NULL;
  1184. }
  1185. if (replaced && result.Buf) {
  1186. // looks like we have new content
  1187. // Let's do one more check. If this is a REG_EXPAND_SZ we will do our best to
  1188. // keep the stuff unexpanded. So if the source string expanded on the destination
  1189. // machine is the same as the destination string we won't do anything.
  1190. newContent = TRUE;
  1191. if (*valueType == REG_EXPAND_SZ) {
  1192. destResult = IsmExpandEnvironmentString (
  1193. PLATFORM_DESTINATION,
  1194. S_SYSENVVAR_GROUP,
  1195. (PCTSTR) CurrentContent->MemoryContent.ContentBytes,
  1196. NULL
  1197. );
  1198. if (destResult && StringIMatch (destResult, (PCTSTR)result.Buf)) {
  1199. newContent = FALSE;
  1200. }
  1201. if (destResult) {
  1202. IsmReleaseMemory (destResult);
  1203. destResult = NULL;
  1204. }
  1205. }
  1206. if (newContent) {
  1207. NewContent->MemoryContent.ContentSize = SizeOfString ((PCTSTR)result.Buf);
  1208. NewContent->MemoryContent.ContentBytes = IsmGetMemory (NewContent->MemoryContent.ContentSize);
  1209. CopyMemory ((PTSTR)NewContent->MemoryContent.ContentBytes, result.Buf, NewContent->MemoryContent.ContentSize);
  1210. }
  1211. }
  1212. GbFree (&result);
  1213. }
  1214. }
  1215. return TRUE;
  1216. }
  1217. BOOL
  1218. WINAPI
  1219. DoFixDefaultIcon (
  1220. IN MIG_OBJECTTYPEID SrcObjectTypeId,
  1221. IN MIG_OBJECTSTRINGHANDLE SrcObjectName,
  1222. IN PCMIG_CONTENT OriginalContent,
  1223. IN PCMIG_CONTENT CurrentContent,
  1224. OUT PMIG_CONTENT NewContent,
  1225. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1226. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1227. )
  1228. {
  1229. MIG_PROPERTYDATAID propDataId;
  1230. MIG_BLOBTYPE propDataType;
  1231. UINT requiredSize;
  1232. PDWORD valueType;
  1233. PICON_GROUP iconGroup = NULL;
  1234. ICON_SGROUP iconSGroup = {0, NULL};
  1235. PTSTR iconLibPath = NULL;
  1236. INT iconNumber = 0;
  1237. PTSTR dataCopy;
  1238. if (CurrentContent->ContentInFile) {
  1239. return TRUE;
  1240. }
  1241. valueType = (PDWORD)(CurrentContent->Details.DetailsData);
  1242. if (*valueType != REG_SZ && *valueType != REG_EXPAND_SZ) {
  1243. return TRUE;
  1244. }
  1245. // let's see if we have our property attached
  1246. propDataId = IsmGetPropertyFromObject (SrcObjectTypeId, SrcObjectName, g_DefaultIconData);
  1247. if (!propDataId) {
  1248. return TRUE;
  1249. }
  1250. if (!IsmGetPropertyData (propDataId, NULL, 0, &requiredSize, &propDataType)) {
  1251. return TRUE;
  1252. }
  1253. iconSGroup.DataSize = requiredSize;
  1254. iconSGroup.Data = IsmGetMemory (requiredSize);
  1255. if (!IsmGetPropertyData (propDataId, (PBYTE)iconSGroup.Data, requiredSize, NULL, &propDataType)) {
  1256. IsmReleaseMemory (iconSGroup.Data);
  1257. return TRUE;
  1258. }
  1259. if (!iconSGroup.DataSize) {
  1260. IsmReleaseMemory (iconSGroup.Data);
  1261. return TRUE;
  1262. }
  1263. iconGroup = IcoDeSerializeIconGroup (&iconSGroup);
  1264. if (!iconGroup) {
  1265. IsmReleaseMemory (iconSGroup.Data);
  1266. return TRUE;
  1267. }
  1268. if (IsmGetEnvironmentString (
  1269. PLATFORM_DESTINATION,
  1270. NULL,
  1271. S_ENV_ICONLIB,
  1272. NULL,
  1273. 0,
  1274. &requiredSize
  1275. )) {
  1276. iconLibPath = IsmGetMemory (requiredSize);
  1277. if (IsmGetEnvironmentString (
  1278. PLATFORM_DESTINATION,
  1279. NULL,
  1280. S_ENV_ICONLIB,
  1281. iconLibPath,
  1282. requiredSize,
  1283. NULL
  1284. )) {
  1285. if (IcoWriteIconGroupToPeFile (iconLibPath, iconGroup, NULL, &iconNumber)) {
  1286. // finally we wrote the icon, fix the content and tell scanstate that
  1287. // we iconlib was used
  1288. dataCopy = IsmGetMemory (SizeOfString (iconLibPath) + sizeof (TCHAR) + 20 * sizeof (TCHAR));
  1289. wsprintf (dataCopy, TEXT("%s,%d"), iconLibPath, iconNumber);
  1290. NewContent->MemoryContent.ContentSize = SizeOfString (dataCopy);
  1291. NewContent->MemoryContent.ContentBytes = (PBYTE) dataCopy;
  1292. IsmSetEnvironmentFlag (PLATFORM_DESTINATION, NULL, S_ENV_SAVE_ICONLIB);
  1293. }
  1294. }
  1295. IsmReleaseMemory (iconLibPath);
  1296. }
  1297. IcoReleaseIconGroup (iconGroup);
  1298. IsmReleaseMemory (iconSGroup.Data);
  1299. return TRUE;
  1300. }
  1301. BOOL
  1302. WINAPI
  1303. FilterFileAutoFilter (
  1304. IN PCMIG_FILTERINPUT InputData,
  1305. OUT PMIG_FILTEROUTPUT OutputData,
  1306. IN BOOL NoRestoreObject,
  1307. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1308. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1309. )
  1310. {
  1311. PCTSTR node, nodeWack;
  1312. PCTSTR leaf;
  1313. // NTRAID#NTBUG9-153275-2000/08/01-jimschm Static buffer size
  1314. TCHAR newNode[MAX_PATH * 4];
  1315. TCHAR newLeaf[MAX_PATH * 4];
  1316. BOOL changed = FALSE;
  1317. if (InputData &&
  1318. InputData->OriginalObject.ObjectName &&
  1319. InputData->CurrentObject.ObjectName &&
  1320. (InputData->OriginalObject.ObjectName != InputData->CurrentObject.ObjectName)
  1321. ) {
  1322. // this was already modified. Let's not touch it.
  1323. return TRUE;
  1324. }
  1325. //
  1326. // Filter the object name
  1327. //
  1328. IsmCreateObjectStringsFromHandle (
  1329. InputData->CurrentObject.ObjectName,
  1330. &node,
  1331. &leaf
  1332. );
  1333. if (NoRestoreObject && leaf) {
  1334. IsmDestroyObjectString (node);
  1335. IsmDestroyObjectString (leaf);
  1336. return TRUE;
  1337. }
  1338. if (node) {
  1339. if (MappingSearchAndReplaceEx (
  1340. g_FileNodeFilterMap, // map handle
  1341. node, // source string
  1342. newNode, // dest buffer
  1343. 0, // source string bytes (0=unspecified)
  1344. NULL, // dest bytes required
  1345. ARRAYSIZE(newNode), // dest buffer size
  1346. 0, // flags
  1347. NULL, // extra data value
  1348. NULL // end of string
  1349. )) {
  1350. IsmDestroyObjectString (node);
  1351. node = newNode;
  1352. changed = TRUE;
  1353. } else {
  1354. nodeWack = JoinPaths (node, TEXT(""));
  1355. if (MappingSearchAndReplaceEx (
  1356. g_FileNodeFilterMap, // map handle
  1357. nodeWack, // source string
  1358. newNode, // dest buffer
  1359. 0, // source string bytes (0=unspecified)
  1360. NULL, // dest bytes required
  1361. ARRAYSIZE(newNode), // dest buffer size
  1362. 0, // flags
  1363. NULL, // extra data value
  1364. NULL // end of string
  1365. )) {
  1366. IsmDestroyObjectString (node);
  1367. node = newNode;
  1368. changed = TRUE;
  1369. }
  1370. FreePathString (nodeWack);
  1371. nodeWack = NULL;
  1372. }
  1373. }
  1374. if (leaf) {
  1375. if (MappingSearchAndReplaceEx (
  1376. g_FileLeafFilterMap,
  1377. leaf,
  1378. newLeaf,
  1379. 0,
  1380. NULL,
  1381. ARRAYSIZE(newLeaf),
  1382. 0,
  1383. NULL,
  1384. NULL
  1385. )) {
  1386. IsmDestroyObjectString (leaf);
  1387. leaf = newLeaf;
  1388. changed = TRUE;
  1389. }
  1390. }
  1391. if (changed) {
  1392. OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, leaf);
  1393. }
  1394. OutputData->Replaced = NoRestoreObject;
  1395. if (node != newNode) {
  1396. IsmDestroyObjectString (node);
  1397. }
  1398. if (leaf != newLeaf) {
  1399. IsmDestroyObjectString (leaf);
  1400. }
  1401. return TRUE;
  1402. }
  1403. PCTSTR
  1404. pProcessRenameExMacro (
  1405. IN PCTSTR Node,
  1406. IN PCTSTR Leaf, OPTIONAL
  1407. IN BOOL ZeroBase
  1408. )
  1409. {
  1410. PCTSTR workingStr;
  1411. PTSTR macroStartPtr = NULL;
  1412. PTSTR macroEndPtr = NULL;
  1413. PTSTR macroCopy = NULL;
  1414. DWORD macroLength = 0;
  1415. PTSTR macroParsePtr = NULL;
  1416. TCHAR macroReplacement[MAX_PATH];
  1417. MIG_OBJECTSTRINGHANDLE testHandle = NULL;
  1418. TCHAR regReplacement[MAX_PATH];
  1419. UINT index;
  1420. PCTSTR newString;
  1421. // If Leaf is supplied, we are working only on the Leaf
  1422. workingStr = Leaf ? Leaf : Node;
  1423. // Extract macro
  1424. macroStartPtr = _tcschr (workingStr, S_RENAMEEX_START_CHAR);
  1425. if (macroStartPtr) {
  1426. macroEndPtr = _tcschr (macroStartPtr + 1, S_RENAMEEX_END_CHAR);
  1427. }
  1428. if (macroEndPtr) {
  1429. macroCopy = DuplicateText (macroStartPtr + 1);
  1430. macroCopy[macroEndPtr-macroStartPtr-1] = 0;
  1431. }
  1432. if (macroCopy) {
  1433. // Build a possible destination
  1434. if (ZeroBase) {
  1435. index = 0;
  1436. } else {
  1437. index = 1;
  1438. }
  1439. do {
  1440. IsmDestroyObjectHandle (testHandle);
  1441. _stprintf (macroReplacement, macroCopy, index);
  1442. StringCopyByteCount (regReplacement, workingStr, (HALF_PTR) ((macroStartPtr - workingStr + 1) * sizeof (TCHAR)));
  1443. StringCat (regReplacement, macroReplacement);
  1444. StringCat (regReplacement, macroEndPtr + 1);
  1445. if (Leaf) {
  1446. testHandle = IsmCreateObjectHandle (Node, regReplacement);
  1447. } else {
  1448. testHandle = IsmCreateObjectHandle (regReplacement, NULL);
  1449. }
  1450. index++;
  1451. } while (pDoesDifferentRegExist (testHandle) ||
  1452. HtFindString (g_RegCollisionDestTable, testHandle));
  1453. IsmDestroyObjectHandle (testHandle);
  1454. FreeText (macroCopy);
  1455. newString = DuplicateText (regReplacement);
  1456. } else {
  1457. newString = DuplicateText (workingStr);
  1458. }
  1459. return newString;
  1460. }
  1461. BOOL
  1462. WINAPI
  1463. FilterRenameExFilter (
  1464. IN PCMIG_FILTERINPUT InputData,
  1465. OUT PMIG_FILTEROUTPUT OutputData,
  1466. IN BOOL NoRestoreObject,
  1467. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1468. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1469. )
  1470. {
  1471. PCTSTR doNode = NULL;
  1472. PCTSTR doLeaf = NULL;
  1473. PCTSTR destNode = NULL;
  1474. PCTSTR newNode = NULL;
  1475. PCTSTR rootNode;
  1476. PCTSTR destLeaf = NULL;
  1477. PCTSTR srcNode = NULL;
  1478. PCTSTR srcLeaf = NULL;
  1479. // NTRAID#NTBUG9-153274-2000/08/01-jimschm Static buffer size
  1480. TCHAR newSrcNode[MAX_PATH * 4];
  1481. TCHAR newSrcLeaf[MAX_PATH * 4];
  1482. HASHITEM hashItem;
  1483. MIG_OBJECTSTRINGHANDLE storeHandle;
  1484. MIG_OBJECTSTRINGHANDLE testHandle;
  1485. MIG_OBJECTSTRINGHANDLE nodeHandle;
  1486. PTSTR ptr = NULL;
  1487. PTSTR ptr2;
  1488. PTSTR workingStr;
  1489. BOOL fFoundMatch = FALSE;
  1490. BOOL zeroBase;
  1491. IsmCreateObjectStringsFromHandle (
  1492. InputData->CurrentObject.ObjectName,
  1493. &srcNode,
  1494. &srcLeaf
  1495. );
  1496. if (srcNode) {
  1497. if (MappingSearchAndReplaceEx (
  1498. g_RegNodeFilterMap,
  1499. srcNode,
  1500. newSrcNode,
  1501. 0,
  1502. NULL,
  1503. ARRAYSIZE(newSrcNode),
  1504. 0,
  1505. NULL,
  1506. NULL
  1507. )) {
  1508. IsmDestroyObjectString (srcNode);
  1509. srcNode = newSrcNode;
  1510. }
  1511. }
  1512. if (srcLeaf) {
  1513. if (MappingSearchAndReplaceEx (
  1514. g_RegLeafFilterMap,
  1515. srcLeaf,
  1516. newSrcLeaf,
  1517. 0,
  1518. NULL,
  1519. ARRAYSIZE(newSrcLeaf),
  1520. 0,
  1521. NULL,
  1522. NULL
  1523. )) {
  1524. IsmDestroyObjectString (srcLeaf);
  1525. srcLeaf = newSrcLeaf;
  1526. }
  1527. }
  1528. if (HtFindStringEx (g_RegCollisionSrcTable, InputData->OriginalObject.ObjectName, (PVOID)(&hashItem), FALSE)) {
  1529. // We've already renamed this object
  1530. HtCopyStringData (g_RegCollisionDestTable, hashItem, (PVOID)(&testHandle));
  1531. IsmCreateObjectStringsFromHandle (testHandle, &destNode, &destLeaf);
  1532. // Do not free testHandle here because it is a pointer into the hash table data
  1533. OutputData->NewObject.ObjectName = IsmCreateObjectHandle (destNode, destLeaf);
  1534. IsmDestroyObjectString (destNode);
  1535. IsmDestroyObjectString (destLeaf);
  1536. destNode;
  1537. destLeaf = NULL;
  1538. } else {
  1539. // We've never seen this object yet
  1540. IsmCreateObjectStringsFromHandle (DestinationOperationData->String, &doNode, &doLeaf);
  1541. // Pick a new node
  1542. // First check to see if this object's node has already been processed
  1543. workingStr = DuplicateText(srcNode);
  1544. if (workingStr) {
  1545. do {
  1546. nodeHandle = IsmCreateObjectHandle (workingStr, NULL);
  1547. if (HtFindStringEx (g_RegCollisionSrcTable, nodeHandle, (PVOID)(&hashItem), FALSE)) {
  1548. HtCopyStringData (g_RegCollisionDestTable, hashItem, (PVOID)(&testHandle));
  1549. IsmCreateObjectStringsFromHandle (testHandle, &rootNode, NULL);
  1550. // Do not free testHandle here because it is a pointer into the hash table data
  1551. if (ptr) {
  1552. // if ptr is valid it means we found a match for a subkey
  1553. *ptr = TEXT('\\');
  1554. newNode = JoinText(rootNode, ptr);
  1555. } else {
  1556. // if ptr is NULL, we found a match for the full keyname
  1557. newNode = DuplicateText(rootNode);
  1558. }
  1559. IsmDestroyObjectString(rootNode);
  1560. fFoundMatch = TRUE;
  1561. } else {
  1562. ptr2 = ptr;
  1563. ptr = (PTSTR)FindLastWack (workingStr);
  1564. if (ptr2) {
  1565. *ptr2 = TEXT('\\');
  1566. }
  1567. if (ptr) {
  1568. *ptr = 0;
  1569. }
  1570. }
  1571. IsmDestroyObjectHandle(nodeHandle);
  1572. } while (FALSE == fFoundMatch && ptr);
  1573. FreeText(workingStr);
  1574. }
  1575. zeroBase = (SourceOperationData &&
  1576. SourceOperationData->Type == BLOBTYPE_BINARY &&
  1577. SourceOperationData->BinarySize == sizeof(PCBYTE) &&
  1578. (BOOL)SourceOperationData->BinaryData == TRUE);
  1579. if (FALSE == fFoundMatch) {
  1580. // Nope, let's process the node
  1581. destNode = pProcessRenameExMacro (doNode, NULL, zeroBase);
  1582. newNode = DuplicateText(destNode);
  1583. IsmDestroyObjectHandle(destNode);
  1584. }
  1585. // Now process the leaf, if the original object had a leaf
  1586. if (srcLeaf) {
  1587. if (doLeaf) {
  1588. destLeaf = pProcessRenameExMacro (newNode, doLeaf, zeroBase);
  1589. IsmDestroyObjectString (doLeaf);
  1590. }
  1591. }
  1592. IsmDestroyObjectString (doNode);
  1593. // Add this in the collision table
  1594. testHandle = IsmCreateObjectHandle (newNode, destLeaf ? destLeaf : srcLeaf);
  1595. storeHandle = DuplicateText (testHandle);
  1596. hashItem = HtAddStringEx (g_RegCollisionDestTable, storeHandle, &storeHandle, FALSE);
  1597. HtAddStringEx (g_RegCollisionSrcTable, InputData->OriginalObject.ObjectName, &hashItem, FALSE);
  1598. // Update the output
  1599. OutputData->NewObject.ObjectName = testHandle;
  1600. }
  1601. if (srcNode != NULL) {
  1602. IsmDestroyObjectString (srcNode);
  1603. }
  1604. if (srcLeaf != NULL) {
  1605. IsmDestroyObjectString (srcLeaf);
  1606. }
  1607. if (destLeaf != NULL) {
  1608. IsmDestroyObjectString (destLeaf);
  1609. }
  1610. if (newNode != NULL) {
  1611. FreeText(newNode);
  1612. }
  1613. return TRUE;
  1614. }
  1615. BOOL
  1616. WINAPI
  1617. FilterPartitionMove (
  1618. IN PCMIG_FILTERINPUT InputData,
  1619. OUT PMIG_FILTEROUTPUT OutputData,
  1620. IN BOOL NoRestoreObject,
  1621. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1622. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1623. )
  1624. {
  1625. PCTSTR node = NULL;
  1626. PCTSTR leaf = NULL;
  1627. IsmCreateObjectStringsFromHandle (DestinationOperationData->String, &node, &leaf);
  1628. OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, leaf);
  1629. IsmDestroyObjectString (node);
  1630. IsmDestroyObjectString (leaf);
  1631. return TRUE;
  1632. }
  1633. BOOL
  1634. WINAPI
  1635. DoDestAddObject (
  1636. IN MIG_OBJECTTYPEID SrcObjectTypeId,
  1637. IN MIG_OBJECTSTRINGHANDLE SrcObjectName,
  1638. IN PCMIG_CONTENT OriginalContent,
  1639. IN PCMIG_CONTENT CurrentContent,
  1640. OUT PMIG_CONTENT NewContent,
  1641. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1642. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1643. )
  1644. {
  1645. PMIG_CONTENT finalContent;
  1646. if (DestinationOperationData == NULL) {
  1647. return TRUE;
  1648. }
  1649. if (DestinationOperationData->Type != BLOBTYPE_BINARY) {
  1650. return TRUE;
  1651. }
  1652. if (DestinationOperationData->BinarySize != sizeof (MIG_CONTENT)) {
  1653. return TRUE;
  1654. }
  1655. finalContent = (PMIG_CONTENT) DestinationOperationData->BinaryData;
  1656. CopyMemory (NewContent, finalContent, sizeof (MIG_CONTENT));
  1657. return TRUE;
  1658. }
  1659. VOID
  1660. OEWarning (
  1661. VOID
  1662. )
  1663. {
  1664. ERRUSER_EXTRADATA extraData;
  1665. if (TRUE == g_OERulesMigrated) {
  1666. // Send warning to app
  1667. extraData.Error = ERRUSER_WARNING_OERULES;
  1668. extraData.ErrorArea = ERRUSER_AREA_RESTORE;
  1669. extraData.ObjectTypeId = 0;
  1670. extraData.ObjectName = NULL;
  1671. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  1672. // Add to log
  1673. LOG ((LOG_WARNING, (PCSTR) MSG_OE_RULES));
  1674. }
  1675. }
  1676. VOID
  1677. OutlookWarning (
  1678. VOID
  1679. )
  1680. {
  1681. PCTSTR expandedPath;
  1682. MIG_OBJECT_ENUM objectEnum;
  1683. PCTSTR enumPattern;
  1684. ERRUSER_EXTRADATA extraData;
  1685. expandedPath = IsmExpandEnvironmentString (PLATFORM_SOURCE,
  1686. S_SYSENVVAR_GROUP,
  1687. TEXT("%CSIDL_APPDATA%\\Microsoft\\Outlook"),
  1688. NULL);
  1689. if (expandedPath) {
  1690. enumPattern = IsmCreateSimpleObjectPattern (expandedPath, FALSE, TEXT("*.rwz"), TRUE);
  1691. if (enumPattern) {
  1692. if (IsmEnumFirstSourceObject (&objectEnum, g_FileType, enumPattern)) {
  1693. // Send warning to app
  1694. extraData.Error = ERRUSER_WARNING_OUTLOOKRULES;
  1695. extraData.ErrorArea = ERRUSER_AREA_RESTORE;
  1696. extraData.ObjectTypeId = 0;
  1697. extraData.ObjectName = NULL;
  1698. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  1699. // Add to log
  1700. LOG ((LOG_WARNING, (PCSTR) MSG_OUTLOOK_RULES));
  1701. IsmAbortObjectEnum (&objectEnum);
  1702. }
  1703. IsmDestroyObjectHandle (enumPattern);
  1704. }
  1705. IsmReleaseMemory (expandedPath);
  1706. }
  1707. }
  1708. VOID
  1709. WINAPI
  1710. ScriptOpmTerminate (
  1711. VOID
  1712. )
  1713. {
  1714. //
  1715. // Temporary place to trigger setting refresh/upgrade
  1716. //
  1717. if (!IsmCheckCancel()) {
  1718. OEFixLastUser();
  1719. WABMerge();
  1720. OE4MergeStoreFolder();
  1721. OE5MergeStoreFolders();
  1722. OEWarning();
  1723. OutlookWarning();
  1724. }
  1725. TerminateRestoreCallback ();
  1726. TerminateSpecialRename();
  1727. TerminateSpecialConversion();
  1728. // LEAK: need to loop through table and FreeText the extra data
  1729. HtFree (g_RegCollisionDestTable);
  1730. g_RegCollisionDestTable = NULL;
  1731. HtFree (g_RegCollisionSrcTable);
  1732. g_RegCollisionSrcTable = NULL;
  1733. DestroyStringMapping (g_RegNodeFilterMap);
  1734. g_RegNodeFilterMap = NULL;
  1735. DestroyStringMapping (g_RegLeafFilterMap);
  1736. g_RegLeafFilterMap = NULL;
  1737. DestroyStringMapping (g_FileNodeFilterMap);
  1738. g_FileNodeFilterMap = NULL;
  1739. DestroyStringMapping (g_FileLeafFilterMap);
  1740. g_FileLeafFilterMap = NULL;
  1741. DestroyStringMapping (g_DestEnvMap);
  1742. g_DestEnvMap = NULL;
  1743. }