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.

2829 lines
90 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. #define MAXINISIZE 65536
  20. //
  21. // Strings
  22. //
  23. #define S_RENAMEEX_START_CHAR TEXT('<')
  24. #define S_RENAMEEX_END_CHAR TEXT('>')
  25. //
  26. // Constants
  27. //
  28. // None
  29. //
  30. // Macros
  31. //
  32. // None
  33. //
  34. // Types
  35. //
  36. // None
  37. //
  38. // Globals
  39. //
  40. MIG_OPERATIONID g_V1MoveExOp;
  41. MIG_OPERATIONID g_V1MoveOp;
  42. MIG_OPERATIONID g_DeleteOp;
  43. MIG_OPERATIONID g_PartMoveOp;
  44. PMAPSTRUCT g_RegNodeFilterMap;
  45. PMAPSTRUCT g_RegLeafFilterMap;
  46. PMAPSTRUCT g_FileNodeFilterMap;
  47. PMAPSTRUCT g_FileLeafFilterMap;
  48. PMAPSTRUCT g_IniSectFilterMap;
  49. PMAPSTRUCT g_IniKeyFilterMap;
  50. PMAPSTRUCT g_DestEnvMap;
  51. HASHTABLE g_RegCollisionDestTable;
  52. HASHTABLE g_RegCollisionSrcTable;
  53. //
  54. // Macro expansion list
  55. //
  56. // None
  57. //
  58. // Private function prototypes
  59. //
  60. OPMINITIALIZE ScriptOpmInitialize;
  61. OPMFILTERCALLBACK FilterV1MoveEx;
  62. OPMFILTERCALLBACK FilterV1Move;
  63. OPMFILTERCALLBACK FilterMove;
  64. OPMFILTERCALLBACK FilterIniMove;
  65. OPMAPPLYCALLBACK DoRegAutoFilter;
  66. OPMAPPLYCALLBACK DoIniAutoFilter;
  67. OPMFILTERCALLBACK FilterRegAutoFilter;
  68. OPMFILTERCALLBACK FilterIniAutoFilter;
  69. OPMFILTERCALLBACK FilterFileAutoFilter;
  70. OPMFILTERCALLBACK FilterDelete;
  71. OPMAPPLYCALLBACK DoFixDefaultIcon;
  72. OPMFILTERCALLBACK FilterRenameExFilter;
  73. OPMFILTERCALLBACK FilterRenameIniExFilter;
  74. OPMFILTERCALLBACK FilterPartitionMove;
  75. OPMAPPLYCALLBACK DoDestAddObject;
  76. //
  77. // Macro expansion definition
  78. //
  79. // None
  80. //
  81. // Code
  82. //
  83. BOOL
  84. pParseInfForRemapEnvVar (
  85. IN HINF InfHandle
  86. )
  87. {
  88. INFSTRUCT is = INITINFSTRUCT_PMHANDLE;
  89. PCTSTR envVar;
  90. PTSTR envValue;
  91. UINT sizeNeeded;
  92. PTSTR encodedVariableName;
  93. BOOL result = FALSE;
  94. __try {
  95. // on all systems, process "Delete Destination Settings"
  96. if (InfFindFirstLine (InfHandle, TEXT("RemapEnvVar"), NULL, &is)) {
  97. do {
  98. if (IsmCheckCancel()) {
  99. __leave;
  100. }
  101. envVar = InfGetStringField (&is, 1);
  102. if (!envVar) {
  103. LOG ((LOG_WARNING, (PCSTR) MSG_EMPTY_REG_SPEC));
  104. continue;
  105. }
  106. if (IsmGetEnvironmentString (
  107. PLATFORM_DESTINATION,
  108. S_SYSENVVAR_GROUP,
  109. envVar,
  110. NULL,
  111. 0,
  112. &sizeNeeded
  113. )) {
  114. envValue = AllocPathString (sizeNeeded);
  115. if (envValue) {
  116. if (IsmGetEnvironmentString (
  117. PLATFORM_DESTINATION,
  118. S_SYSENVVAR_GROUP,
  119. envVar,
  120. envValue,
  121. sizeNeeded,
  122. NULL
  123. )) {
  124. AddRemappingEnvVar (g_DestEnvMap, g_FileNodeFilterMap, NULL, envVar, envValue);
  125. }
  126. FreePathString (envValue);
  127. envValue = NULL;
  128. }
  129. }
  130. // now let's see if this env. variable was present on the source machine.
  131. // If it was, we are going to add it into g_RevEnvMap to allow file move
  132. // to create subdirectories only from this variable up.
  133. if (IsmGetEnvironmentString (
  134. PLATFORM_SOURCE,
  135. S_SYSENVVAR_GROUP,
  136. envVar,
  137. NULL,
  138. 0,
  139. &sizeNeeded
  140. )) {
  141. envValue = AllocPathString (sizeNeeded);
  142. if (envValue) {
  143. if (IsmGetEnvironmentString (
  144. PLATFORM_SOURCE,
  145. S_SYSENVVAR_GROUP,
  146. envVar,
  147. envValue,
  148. sizeNeeded,
  149. NULL
  150. )) {
  151. encodedVariableName = AllocPathString (TcharCount (envVar) + 3);
  152. if (encodedVariableName) {
  153. wsprintf (encodedVariableName, TEXT("%%%s%%"), envVar);
  154. AddStringMappingPair (g_RevEnvMap, envValue, encodedVariableName);
  155. FreePathString (encodedVariableName);
  156. encodedVariableName = NULL;
  157. }
  158. }
  159. FreePathString (envValue);
  160. envValue = NULL;
  161. }
  162. }
  163. } while (InfFindNextLine (&is));
  164. }
  165. result = TRUE;
  166. }
  167. __finally {
  168. InfCleanUpInfStruct (&is);
  169. }
  170. return result;
  171. }
  172. BOOL
  173. pParseRemapEnvVar (
  174. VOID
  175. )
  176. {
  177. PTSTR multiSz = NULL;
  178. MULTISZ_ENUM e;
  179. UINT sizeNeeded;
  180. HINF infHandle = INVALID_HANDLE_VALUE;
  181. ENVENTRY_TYPE dataType;
  182. BOOL result = TRUE;
  183. if (IsmGetEnvironmentValue (
  184. IsmGetRealPlatform (),
  185. NULL,
  186. S_GLOBAL_INF_HANDLE,
  187. (PBYTE)(&infHandle),
  188. sizeof (HINF),
  189. &sizeNeeded,
  190. &dataType
  191. ) &&
  192. (sizeNeeded == sizeof (HINF)) &&
  193. (dataType == ENVENTRY_BINARY)
  194. ) {
  195. if (!pParseInfForRemapEnvVar (infHandle)) {
  196. result = FALSE;
  197. }
  198. } else {
  199. if (!IsmGetEnvironmentValue (IsmGetRealPlatform (), NULL, S_INF_FILE_MULTISZ, NULL, 0, &sizeNeeded, NULL)) {
  200. return TRUE; // no INF files specified
  201. }
  202. __try {
  203. multiSz = AllocText (sizeNeeded);
  204. if (!multiSz) {
  205. result = FALSE;
  206. __leave;
  207. }
  208. if (!IsmGetEnvironmentValue (IsmGetRealPlatform (), NULL, S_INF_FILE_MULTISZ, (PBYTE) multiSz, sizeNeeded, NULL, NULL)) {
  209. result = FALSE;
  210. __leave;
  211. }
  212. if (EnumFirstMultiSz (&e, multiSz)) {
  213. do {
  214. infHandle = InfOpenInfFile (e.CurrentString);
  215. if (infHandle != INVALID_HANDLE_VALUE) {
  216. if (!pParseInfForRemapEnvVar (infHandle)) {
  217. InfCloseInfFile (infHandle);
  218. infHandle = INVALID_HANDLE_VALUE;
  219. result = FALSE;
  220. __leave;
  221. }
  222. InfCloseInfFile (infHandle);
  223. infHandle = INVALID_HANDLE_VALUE;
  224. } else {
  225. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_INF, e.CurrentString));
  226. }
  227. } while (EnumNextMultiSz (&e));
  228. }
  229. }
  230. __finally {
  231. if (multiSz) {
  232. FreeText (multiSz);
  233. multiSz = NULL;
  234. }
  235. }
  236. }
  237. return result;
  238. }
  239. VOID
  240. pOutlookClearConvKeys (
  241. VOID
  242. )
  243. {
  244. MIG_CONTENT objectContent;
  245. MIG_OBJECT_ENUM objectEnum;
  246. MIG_OBJECTSTRINGHANDLE enumPattern = NULL;
  247. // This registry tree was needed only for conversion data. We don't want to
  248. // write them to the destination, so clear the apply attribute on each item.
  249. if ((IsmIsComponentSelected (S_OUTLOOK9798_COMPONENT, 0) &&
  250. IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OUTLOOK9798_APPDETECT)) ||
  251. (IsmIsComponentSelected (S_OFFICE_COMPONENT, 0) &&
  252. IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OFFICE9798_APPDETECT))) {
  253. enumPattern = IsmCreateSimpleObjectPattern (
  254. TEXT("HKLM\\Software\\Microsoft\\MS Setup (ACME)\\Table Files"),
  255. TRUE,
  256. NULL,
  257. TRUE);
  258. if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, enumPattern)) {
  259. do {
  260. IsmClearApplyOnObject (g_RegType | PLATFORM_SOURCE, objectEnum.ObjectName);
  261. } while (IsmEnumNextObject (&objectEnum));
  262. }
  263. IsmDestroyObjectHandle (enumPattern);
  264. }
  265. }
  266. BOOL
  267. WINAPI
  268. ScriptOpmInitialize (
  269. IN PMIG_LOGCALLBACK LogCallback,
  270. IN PVOID Reserved
  271. )
  272. {
  273. //
  274. // Get file and registry types
  275. //
  276. g_FileType = MIG_FILE_TYPE;
  277. g_RegType = MIG_REGISTRY_TYPE;
  278. g_IniType = MIG_INI_TYPE;
  279. //
  280. // Get attribute and operation types
  281. //
  282. g_V1MoveExOp = IsmRegisterOperation (S_OPERATION_V1_FILEMOVEEX, TRUE);
  283. g_V1MoveOp = IsmRegisterOperation (S_OPERATION_V1_FILEMOVE, TRUE);
  284. g_RenameOp = IsmRegisterOperation (S_OPERATION_MOVE, FALSE);
  285. g_RenameIniOp = IsmRegisterOperation (S_OPERATION_INIMOVE, FALSE);
  286. g_DeleteOp = IsmRegisterOperation (S_OPERATION_DELETE, FALSE);
  287. g_DefaultIconOp = IsmRegisterOperation (S_OPERATION_DEFICON_FIXCONTENT, FALSE);
  288. g_DefaultIconData = IsmRegisterProperty (S_V1PROP_ICONDATA, FALSE);
  289. g_FileCollPatternData = IsmRegisterProperty (S_V1PROP_FILECOLLPATTERN, FALSE);
  290. g_RenameExOp = IsmRegisterOperation (S_OPERATION_ENHANCED_MOVE, FALSE);
  291. g_RenameIniExOp = IsmRegisterOperation (S_OPERATION_ENHANCED_INIMOVE, FALSE);
  292. g_PartMoveOp = IsmRegisterOperation (S_OPERATION_PARTITION_MOVE, TRUE);
  293. g_DestAddObject = IsmRegisterOperation (S_OPERATION_DESTADDOBJ, FALSE);
  294. g_RegAutoFilterOp = IsmRegisterOperation (S_OPERATION_REG_AUTO_FILTER, FALSE);
  295. g_IniAutoFilterOp = IsmRegisterOperation (S_OPERATION_INI_AUTO_FILTER, FALSE);
  296. //
  297. // Register operation callbacks
  298. //
  299. // FYI: Filter callbacks adjust the name of the object
  300. // Apply callbacks adjust the content of the object
  301. // global operation callbacks
  302. IsmRegisterGlobalApplyCallback (g_RegType | PLATFORM_SOURCE, TEXT("ContentAutoFilter"), DoRegAutoFilter);
  303. IsmRegisterGlobalApplyCallback (g_IniType | PLATFORM_SOURCE, TEXT("ContentAutoFilter"), DoIniAutoFilter);
  304. IsmRegisterGlobalFilterCallback (g_RegType | PLATFORM_SOURCE, TEXT("AutoFilter"), FilterRegAutoFilter, TRUE, FALSE);
  305. IsmRegisterGlobalFilterCallback (g_IniType | PLATFORM_SOURCE, TEXT("AutoFilter"), FilterIniAutoFilter, TRUE, FALSE);
  306. IsmRegisterGlobalFilterCallback (g_FileType | PLATFORM_SOURCE, TEXT("AutoFilter"), FilterFileAutoFilter, TRUE, TRUE);
  307. // operation-specific callbacks
  308. IsmRegisterOperationFilterCallback (g_V1MoveExOp, FilterV1MoveEx, TRUE, TRUE, FALSE);
  309. IsmRegisterOperationFilterCallback (g_V1MoveOp, FilterV1Move, TRUE, TRUE, FALSE);
  310. IsmRegisterOperationFilterCallback (g_RenameOp, FilterMove, TRUE, TRUE, FALSE);
  311. IsmRegisterOperationFilterCallback (g_RenameIniOp, FilterIniMove, TRUE, TRUE, FALSE);
  312. IsmRegisterOperationFilterCallback (g_DeleteOp, FilterDelete, FALSE, TRUE, FALSE);
  313. IsmRegisterOperationApplyCallback (g_DefaultIconOp, DoFixDefaultIcon, TRUE);
  314. IsmRegisterOperationFilterCallback (g_RenameExOp, FilterRenameExFilter, TRUE, TRUE, FALSE);
  315. IsmRegisterOperationFilterCallback (g_RenameIniExOp, FilterRenameIniExFilter, TRUE, TRUE, FALSE);
  316. IsmRegisterOperationFilterCallback (g_PartMoveOp, FilterPartitionMove, TRUE, TRUE, FALSE);
  317. IsmRegisterOperationApplyCallback (g_DestAddObject, DoDestAddObject, TRUE);
  318. IsmRegisterOperationApplyCallback (g_RegAutoFilterOp, DoRegAutoFilter, TRUE);
  319. IsmRegisterOperationApplyCallback (g_IniAutoFilterOp, DoIniAutoFilter, TRUE);
  320. //
  321. // Call special conversion entry point
  322. //
  323. InitSpecialConversion (PLATFORM_DESTINATION);
  324. InitSpecialRename (PLATFORM_DESTINATION);
  325. g_RegNodeFilterMap = CreateStringMapping();
  326. g_FileNodeFilterMap = CreateStringMapping();
  327. g_DestEnvMap = CreateStringMapping();
  328. SetIsmEnvironmentFromPhysicalMachine (g_DestEnvMap, FALSE, NULL);
  329. SetIsmEnvironmentFromPhysicalMachine (g_FileNodeFilterMap, TRUE, NULL);
  330. pParseRemapEnvVar ();
  331. g_RegLeafFilterMap = CreateStringMapping();
  332. g_FileLeafFilterMap = CreateStringMapping();
  333. if ((!g_EnvMap) || (!g_RevEnvMap) || (!g_UndefMap)) {
  334. g_EnvMap = CreateStringMapping();
  335. g_UndefMap = CreateStringMapping();
  336. g_RevEnvMap = CreateStringMapping();
  337. SetIsmEnvironmentFromVirtualMachine (g_EnvMap, g_RevEnvMap, g_UndefMap);
  338. }
  339. g_IniSectFilterMap = CreateStringMapping ();
  340. g_IniKeyFilterMap = CreateStringMapping ();
  341. g_RegCollisionDestTable = HtAllocWithData (sizeof (MIG_OBJECTSTRINGHANDLE));
  342. g_RegCollisionSrcTable = HtAllocWithData (sizeof (HASHITEM));
  343. InitRestoreCallback (PLATFORM_DESTINATION);
  344. pOutlookClearConvKeys();
  345. return TRUE;
  346. }
  347. BOOL
  348. pDoesDifferentRegExist (
  349. IN MIG_OBJECTSTRINGHANDLE DestName
  350. )
  351. {
  352. BOOL result = FALSE;
  353. MIG_CONTENT content;
  354. if (IsmAcquireObject (g_RegType|PLATFORM_DESTINATION, DestName, &content)) {
  355. IsmReleaseObject (&content);
  356. result = TRUE;
  357. } else if (HtFindString (g_RegCollisionDestTable, DestName)) {
  358. result = TRUE;
  359. }
  360. return result;
  361. }
  362. BOOL
  363. WINAPI
  364. FilterV1MoveEx (
  365. IN PCMIG_FILTERINPUT InputData,
  366. OUT PMIG_FILTEROUTPUT OutputData,
  367. IN BOOL NoRestoreObject,
  368. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  369. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  370. )
  371. {
  372. PCTSTR orgSrcNode = NULL;
  373. PCTSTR orgSrcLeaf = NULL;
  374. PCTSTR srcNode = NULL;
  375. PCTSTR srcLeaf = NULL;
  376. PCTSTR destNode = NULL;
  377. PCTSTR destLeaf = NULL;
  378. PCTSTR newDestNode = NULL;
  379. PCTSTR destNodePtr = NULL;
  380. // NTRAID#NTBUG9-153274-2000/08/01-jimschm Static buffer size
  381. TCHAR expDestNode[MAX_PATH * 4];
  382. PCTSTR ismExpDestNode = NULL;
  383. TCHAR expDestLeaf[MAX_PATH * 4];
  384. PCTSTR ismExpDestLeaf = NULL;
  385. CHARTYPE ch;
  386. MIG_OBJECTSTRINGHANDLE destHandle;
  387. __try {
  388. //
  389. // For v1 compatibility, we support only a transformation from
  390. // original source to inf-specified destination. Chaining of
  391. // operations is not allowed (these are restrictions caused by the
  392. // existing INF syntax).
  393. //
  394. if (!DestinationOperationData) {
  395. DEBUGMSG ((DBG_ERROR, "Missing dest data in FilterV1MoveEx"));
  396. __leave;
  397. }
  398. if ((InputData->CurrentObject.ObjectTypeId & (~PLATFORM_MASK)) != g_FileType) {
  399. DEBUGMSG ((DBG_ERROR, "Unexpected object type in FilterV1MoveEx"));
  400. __leave;
  401. }
  402. if (!IsmCreateObjectStringsFromHandle (
  403. DestinationOperationData->String,
  404. &destNode,
  405. &destLeaf
  406. )) {
  407. DEBUGMSG ((DBG_ERROR, "Can't split dest object in FilterV1MoveEx"));
  408. __leave;
  409. }
  410. MYASSERT (destNode);
  411. if (!destNode) {
  412. DEBUGMSG ((DBG_ERROR, "Destination spec must be a node"));
  413. __leave;
  414. }
  415. //
  416. // Split the source object into node and leaf
  417. //
  418. if (!IsmCreateObjectStringsFromHandle (
  419. InputData->CurrentObject.ObjectName,
  420. &srcNode,
  421. &srcLeaf
  422. )) {
  423. DEBUGMSG ((DBG_ERROR, "Can't split v1 src object in FilterV1MoveEx"));
  424. __leave;
  425. }
  426. if (!srcNode) {
  427. MYASSERT (FALSE);
  428. __leave;
  429. }
  430. //
  431. // If not a local path, do not process
  432. //
  433. if (!_istalpha ((CHARTYPE) _tcsnextc (srcNode)) ||
  434. _tcsnextc (srcNode + 1) != TEXT(':')
  435. ) {
  436. DEBUGMSG ((DBG_WARNING, "Ignoring %s\\%s because it does not have a drive spec", srcNode, srcLeaf));
  437. __leave;
  438. }
  439. ch = (CHARTYPE) _tcsnextc (srcNode + 2);
  440. if (ch && ch != TEXT('\\')) {
  441. DEBUGMSG ((DBG_WARNING, "Ignoring %s\\%s because it does not have a drive spec (2)", srcNode, srcLeaf));
  442. __leave;
  443. }
  444. // let's see if the current name has something in common
  445. // with SourceOperationData->String. If so, get the extra part
  446. // and add it to the destNode
  447. //
  448. // Split the original rule source object into node and leaf
  449. //
  450. if (SourceOperationData) {
  451. if (IsmCreateObjectStringsFromHandle (
  452. SourceOperationData->String,
  453. &orgSrcNode,
  454. &orgSrcLeaf
  455. )) {
  456. if (orgSrcNode) {
  457. if (StringIPrefix (srcNode, orgSrcNode)) {
  458. destNodePtr = srcNode + TcharCount (orgSrcNode);
  459. if (destNodePtr && *destNodePtr) {
  460. if (_tcsnextc (destNodePtr) == TEXT('\\')) {
  461. destNodePtr = _tcsinc (destNodePtr);
  462. }
  463. if (destNodePtr) {
  464. newDestNode = JoinPaths (destNode, destNodePtr);
  465. }
  466. }
  467. }
  468. }
  469. }
  470. }
  471. if (!newDestNode) {
  472. newDestNode = destNode;
  473. }
  474. //
  475. // Expand the destination
  476. //
  477. MappingSearchAndReplaceEx (
  478. g_DestEnvMap,
  479. newDestNode,
  480. expDestNode,
  481. 0,
  482. NULL,
  483. MAX_PATH,
  484. STRMAP_FIRST_CHAR_MUST_MATCH,
  485. NULL,
  486. NULL
  487. );
  488. ismExpDestNode = IsmExpandEnvironmentString (
  489. PLATFORM_DESTINATION,
  490. S_SYSENVVAR_GROUP,
  491. expDestNode,
  492. NULL
  493. );
  494. if (destLeaf) {
  495. MappingSearchAndReplaceEx (
  496. g_DestEnvMap,
  497. destLeaf,
  498. expDestLeaf,
  499. 0,
  500. NULL,
  501. MAX_PATH,
  502. STRMAP_FIRST_CHAR_MUST_MATCH,
  503. NULL,
  504. NULL
  505. );
  506. ismExpDestLeaf = IsmExpandEnvironmentString (
  507. PLATFORM_DESTINATION,
  508. S_SYSENVVAR_GROUP,
  509. expDestLeaf,
  510. NULL
  511. );
  512. }
  513. if (destLeaf) {
  514. destHandle = IsmCreateObjectHandle (
  515. ismExpDestNode?ismExpDestNode:expDestNode,
  516. ismExpDestLeaf?ismExpDestLeaf:expDestLeaf
  517. );
  518. } else {
  519. destHandle = IsmCreateObjectHandle (
  520. ismExpDestNode?ismExpDestNode:expDestNode,
  521. srcLeaf
  522. );
  523. }
  524. if (ismExpDestNode) {
  525. IsmReleaseMemory (ismExpDestNode);
  526. ismExpDestNode = NULL;
  527. }
  528. if (ismExpDestLeaf) {
  529. IsmReleaseMemory (ismExpDestLeaf);
  530. ismExpDestLeaf = NULL;
  531. }
  532. if (destHandle) {
  533. OutputData->NewObject.ObjectName = destHandle;
  534. }
  535. }
  536. __finally {
  537. if (newDestNode && (newDestNode != destNode)) {
  538. FreePathString (newDestNode);
  539. newDestNode = NULL;
  540. }
  541. IsmDestroyObjectString (orgSrcNode);
  542. IsmDestroyObjectString (orgSrcLeaf);
  543. IsmDestroyObjectString (destNode);
  544. IsmDestroyObjectString (destLeaf);
  545. IsmDestroyObjectString (srcNode);
  546. IsmDestroyObjectString (srcLeaf);
  547. }
  548. return TRUE;
  549. }
  550. BOOL
  551. WINAPI
  552. FilterV1Move (
  553. IN PCMIG_FILTERINPUT InputData,
  554. OUT PMIG_FILTEROUTPUT OutputData,
  555. IN BOOL NoRestoreObject,
  556. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  557. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  558. )
  559. {
  560. PCTSTR destNode = NULL;
  561. // NTRAID#NTBUG9-153274-2000/08/01-jimschm Static buffer size
  562. TCHAR expDest[MAX_PATH * 4];
  563. PCTSTR destLeaf = NULL;
  564. PCTSTR srcNode = NULL;
  565. PCTSTR srcLeaf = NULL;
  566. PCTSTR pathStart;
  567. // NTRAID#NTBUG9-153274-2000/08/01-jimschm Static buffer size
  568. TCHAR pathCopy[MAX_PATH * 4];
  569. PCTSTR newDestNode = NULL;
  570. PCTSTR newerDestNode = NULL;
  571. PCTSTR subPath;
  572. BOOL b;
  573. CHARTYPE ch;
  574. MIG_OBJECTSTRINGHANDLE destHandle;
  575. __try {
  576. //
  577. // For v1 compatibility, we support only a transformation from
  578. // original source to inf-specified destination. Chaining of
  579. // operations is not allowed (these are restrictions caused by the
  580. // existing INF syntax).
  581. //
  582. if (!DestinationOperationData) {
  583. DEBUGMSG ((DBG_ERROR, "Missing dest data in FilterV1Move"));
  584. __leave;
  585. }
  586. if ((InputData->CurrentObject.ObjectTypeId & (~PLATFORM_MASK)) != g_FileType) {
  587. DEBUGMSG ((DBG_ERROR, "Unexpected object type in FilterV1Move"));
  588. __leave;
  589. }
  590. if (!IsmCreateObjectStringsFromHandle (
  591. DestinationOperationData->String,
  592. &destNode,
  593. &destLeaf
  594. )) {
  595. DEBUGMSG ((DBG_ERROR, "Can't split dest object in FilterV1Move"));
  596. __leave;
  597. }
  598. MYASSERT (destNode);
  599. if (!destNode) {
  600. DEBUGMSG ((DBG_ERROR, "Destination spec must be a node"));
  601. __leave;
  602. }
  603. if (destLeaf) {
  604. DEBUGMSG ((DBG_WARNING, "Dest leaf specification %s (in %s) ignored", destLeaf, destNode));
  605. }
  606. //
  607. // Find the longest CSIDL inside InputData. Take that as the base directory,
  608. // and take the rest as the subdirectory.
  609. //
  610. if (!IsmCreateObjectStringsFromHandle (
  611. InputData->CurrentObject.ObjectName,
  612. &srcNode,
  613. &srcLeaf
  614. )) {
  615. DEBUGMSG ((DBG_ERROR, "Can't split v1 src object in FilterV1Move"));
  616. __leave;
  617. }
  618. if (!srcNode) {
  619. MYASSERT (FALSE);
  620. __leave;
  621. }
  622. //
  623. // If not a local path, do not process
  624. //
  625. if (!_istalpha ((CHARTYPE) _tcsnextc (srcNode)) ||
  626. _tcsnextc (srcNode + 1) != TEXT(':')
  627. ) {
  628. DEBUGMSG ((DBG_WARNING, "Ignoring %s\\%s because it does not have a drive spec", srcNode, srcLeaf));
  629. __leave;
  630. }
  631. ch = (CHARTYPE) _tcsnextc (srcNode + 2);
  632. if (ch && ch != TEXT('\\')) {
  633. DEBUGMSG ((DBG_WARNING, "Ignoring %s\\%s because it does not have a drive spec (2)", srcNode, srcLeaf));
  634. __leave;
  635. }
  636. //
  637. // Expand the destination
  638. //
  639. b = MappingSearchAndReplaceEx (
  640. g_DestEnvMap,
  641. destNode,
  642. expDest,
  643. 0,
  644. NULL,
  645. MAX_PATH,
  646. STRMAP_FIRST_CHAR_MUST_MATCH,
  647. NULL,
  648. NULL
  649. );
  650. //
  651. // Skip over the drive spec
  652. //
  653. pathStart = srcNode;
  654. //
  655. // Find the longest CSIDL by using the reverse mapping table. This takes
  656. // our full path spec in pathStart and encodes it with an environment
  657. // variable.
  658. //
  659. b = MappingSearchAndReplaceEx (
  660. g_RevEnvMap,
  661. pathStart,
  662. pathCopy,
  663. 0,
  664. NULL,
  665. ARRAYSIZE(pathCopy),
  666. STRMAP_FIRST_CHAR_MUST_MATCH|
  667. STRMAP_RETURN_AFTER_FIRST_REPLACE|
  668. STRMAP_REQUIRE_WACK_OR_NUL,
  669. NULL,
  670. &subPath
  671. );
  672. #ifdef DEBUG
  673. if (!b) {
  674. TCHAR debugBuf[MAX_PATH];
  675. if (MappingSearchAndReplaceEx (
  676. g_RevEnvMap,
  677. pathStart,
  678. debugBuf,
  679. 0,
  680. NULL,
  681. ARRAYSIZE(debugBuf),
  682. STRMAP_FIRST_CHAR_MUST_MATCH|STRMAP_RETURN_AFTER_FIRST_REPLACE,
  683. NULL,
  684. NULL
  685. )) {
  686. DEBUGMSG ((DBG_WARNING, "Ignoring conversion: %s -> %s", pathStart, debugBuf));
  687. }
  688. }
  689. #endif
  690. if (!b) {
  691. subPath = pathStart + (UINT) (ch ? 3 : 2);
  692. *pathCopy = 0;
  693. } else {
  694. if (*subPath) {
  695. MYASSERT (_tcsnextc (subPath) == TEXT('\\'));
  696. *(PTSTR) subPath = 0;
  697. subPath++;
  698. }
  699. }
  700. //
  701. // pathCopy gives us the base, with CSIDL_ environment variables (might be an empty string)
  702. // subPath gives us the subdir (might also be an empty string)
  703. //
  704. // append subPath to the destination node
  705. //
  706. if (*subPath) {
  707. newDestNode = JoinPaths (expDest, subPath);
  708. } else {
  709. newDestNode = expDest;
  710. }
  711. destHandle = IsmCreateObjectHandle (newDestNode, srcLeaf);
  712. if (destHandle) {
  713. OutputData->NewObject.ObjectName = destHandle;
  714. }
  715. }
  716. __finally {
  717. IsmDestroyObjectString (destNode);
  718. IsmDestroyObjectString (destLeaf);
  719. IsmDestroyObjectString (srcNode);
  720. IsmDestroyObjectString (srcLeaf);
  721. if (newDestNode != expDest) {
  722. FreePathString (newDestNode);
  723. }
  724. }
  725. return TRUE;
  726. }
  727. BOOL
  728. WINAPI
  729. FilterMove (
  730. IN PCMIG_FILTERINPUT InputData,
  731. OUT PMIG_FILTEROUTPUT OutputData,
  732. IN BOOL NoRestoreObject,
  733. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  734. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  735. )
  736. {
  737. PCTSTR srcNode = NULL;
  738. PCTSTR srcLeaf = NULL;
  739. PCTSTR baseNode = NULL;
  740. PCTSTR baseLeaf = NULL;
  741. PCTSTR destNode = NULL;
  742. PCTSTR destLeaf = NULL;
  743. PCTSTR node;
  744. PCTSTR leaf;
  745. UINT baseNodeLen;
  746. __try {
  747. //
  748. // Take InputData, break it into node & leaf, take DestinationOperationData,
  749. // do the same, then replace InputData's node & leaf as appropriate.
  750. //
  751. if (!SourceOperationData) {
  752. DEBUGMSG ((DBG_ERROR, "Missing source data in general move operation"));
  753. __leave;
  754. }
  755. if (!DestinationOperationData) {
  756. DEBUGMSG ((DBG_ERROR, "Missing destination data in general move operation"));
  757. __leave;
  758. }
  759. if (!IsmCreateObjectStringsFromHandle (
  760. InputData->CurrentObject.ObjectName,
  761. &srcNode,
  762. &srcLeaf
  763. )) {
  764. DEBUGMSG ((DBG_ERROR, "Can't split src object in general move operation"));
  765. __leave;
  766. }
  767. if (!IsmCreateObjectStringsFromHandle (
  768. SourceOperationData->String,
  769. &baseNode,
  770. &baseLeaf
  771. )) {
  772. DEBUGMSG ((DBG_ERROR, "Can't split src object in general move operation"));
  773. __leave;
  774. }
  775. if (!IsmCreateObjectStringsFromHandle (
  776. DestinationOperationData->String,
  777. &destNode,
  778. &destLeaf
  779. )) {
  780. DEBUGMSG ((DBG_ERROR, "Can't split dest object in general move operation"));
  781. __leave;
  782. }
  783. baseNodeLen = TcharCount (baseNode);
  784. node = NULL;
  785. leaf = NULL;
  786. if (StringIMatchTcharCount (srcNode, baseNode, baseNodeLen)) {
  787. if (srcNode [baseNodeLen]) {
  788. node = JoinPaths (destNode, &(srcNode [baseNodeLen]));
  789. } else {
  790. node = DuplicatePathString (destNode, 0);
  791. }
  792. if (!baseLeaf && !destLeaf) {
  793. leaf = srcLeaf;
  794. } else if (baseLeaf && srcLeaf && StringIMatch (srcLeaf, baseLeaf)) {
  795. leaf = destLeaf?destLeaf:baseLeaf;
  796. } else if (!baseLeaf && destLeaf) {
  797. if (srcLeaf) {
  798. leaf = destLeaf;
  799. }
  800. } else {
  801. FreePathString (node);
  802. node = NULL;
  803. }
  804. }
  805. if (node) {
  806. OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, leaf);
  807. FreePathString (node);
  808. node = NULL;
  809. }
  810. }
  811. __finally {
  812. IsmDestroyObjectString (srcNode);
  813. IsmDestroyObjectString (srcLeaf);
  814. IsmDestroyObjectString (baseNode);
  815. IsmDestroyObjectString (baseLeaf);
  816. IsmDestroyObjectString (destNode);
  817. IsmDestroyObjectString (destLeaf);
  818. }
  819. return TRUE;
  820. }
  821. BOOL
  822. WINAPI
  823. FilterIniMove (
  824. IN PCMIG_FILTERINPUT InputData,
  825. OUT PMIG_FILTEROUTPUT OutputData,
  826. IN BOOL NoRestoreObject,
  827. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  828. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  829. )
  830. {
  831. PCTSTR srcNode = NULL;
  832. PCTSTR srcFile = NULL;
  833. PTSTR srcSect = NULL;
  834. PTSTR srcKey = NULL;
  835. PCTSTR baseNode = NULL;
  836. PCTSTR baseFile = NULL;
  837. PTSTR baseSect = NULL;
  838. PTSTR baseKey = NULL;
  839. PCTSTR destNode = NULL;
  840. PCTSTR destFile = NULL;
  841. PTSTR destSect = NULL;
  842. PTSTR destKey = NULL;
  843. UINT baseNodeLen;
  844. BOOL nodeAlloc = FALSE;
  845. BOOL fileAlloc = FALSE;
  846. PCTSTR node = NULL;
  847. PCTSTR file = NULL;
  848. PCTSTR destSectKey = NULL;
  849. PCTSTR destLeaf = NULL;
  850. MIG_OBJECTSTRINGHANDLE baseNodeHandle = NULL;
  851. MIG_OBJECTSTRINGHANDLE newBaseNode = NULL;
  852. PCTSTR tempStr = NULL;
  853. __try {
  854. //
  855. // Take InputData, break it into node & leaf, take DestinationOperationData,
  856. // do the same, then replace InputData's node & leaf as appropriate.
  857. //
  858. if (!SourceOperationData) {
  859. DEBUGMSG ((DBG_ERROR, "Missing source data in general move operation"));
  860. __leave;
  861. }
  862. if (!DestinationOperationData) {
  863. DEBUGMSG ((DBG_ERROR, "Missing destination data in general move operation"));
  864. __leave;
  865. }
  866. if (!IsmCreateObjectStringsFromHandle (
  867. InputData->CurrentObject.ObjectName,
  868. &srcNode,
  869. &srcFile
  870. )) {
  871. DEBUGMSG ((DBG_ERROR, "Can't split src object in general move operation"));
  872. __leave;
  873. }
  874. if (srcFile [0] == 0) {
  875. IsmDestroyObjectString (srcFile);
  876. srcFile = NULL;
  877. }
  878. if (srcFile) {
  879. srcSect = _tcschr (srcFile, TEXT('\\'));
  880. if (srcSect) {
  881. *srcSect = 0;
  882. srcSect ++;
  883. srcKey = _tcsrchr (srcSect, TEXT('='));
  884. if (srcKey) {
  885. *srcKey = 0;
  886. srcKey ++;
  887. }
  888. }
  889. }
  890. if (!srcNode || !srcFile || !srcSect || !srcKey) {
  891. DEBUGMSG ((DBG_ERROR, "INI src object expected to have node, file, section and key"));
  892. __leave;
  893. }
  894. if (!IsmCreateObjectStringsFromHandle (
  895. SourceOperationData->String,
  896. &baseNode,
  897. &baseFile
  898. )) {
  899. DEBUGMSG ((DBG_ERROR, "Can't split base object in general move operation"));
  900. __leave;
  901. }
  902. if (baseFile [0] == 0) {
  903. IsmDestroyObjectString (baseFile);
  904. baseFile = NULL;
  905. }
  906. if (baseFile) {
  907. baseSect = _tcschr (baseFile, TEXT('\\'));
  908. if (baseSect) {
  909. *baseSect = 0;
  910. baseSect ++;
  911. baseKey = _tcsrchr (baseSect, TEXT('='));
  912. if (baseKey) {
  913. *baseKey = 0;
  914. baseKey ++;
  915. }
  916. }
  917. }
  918. if (!baseNode) {
  919. DEBUGMSG ((DBG_ERROR, "INI base object expected to have at least a node"));
  920. __leave;
  921. }
  922. if (!IsmCreateObjectStringsFromHandle (
  923. DestinationOperationData->String,
  924. &destNode,
  925. &destFile
  926. )) {
  927. DEBUGMSG ((DBG_ERROR, "Can't split dest object in general move operation"));
  928. __leave;
  929. }
  930. if (destFile [0] == 0) {
  931. IsmDestroyObjectString (destFile);
  932. destFile = NULL;
  933. }
  934. if (destFile) {
  935. destSect = _tcschr (destFile, TEXT('\\'));
  936. if (destSect) {
  937. *destSect = 0;
  938. destSect ++;
  939. destKey = _tcsrchr (destSect, TEXT('='));
  940. if (destKey) {
  941. *destKey = 0;
  942. destKey ++;
  943. }
  944. }
  945. }
  946. if (!destNode || (destNode [0] == 0)) {
  947. // We need to use the src node, there was no specification of
  948. // the node where the INI file is supposed to end up.
  949. if (!destFile || (destFile [0] == 0)) {
  950. // destFile is not specified. Let's filter the whole thing
  951. baseNodeHandle = IsmCreateObjectHandle (srcNode, srcFile);
  952. if (baseNodeHandle) {
  953. newBaseNode = IsmFilterObject (
  954. g_FileType | PLATFORM_SOURCE,
  955. baseNodeHandle,
  956. NULL,
  957. NULL,
  958. NULL
  959. );
  960. if (newBaseNode) {
  961. IsmCreateObjectStringsFromHandle (newBaseNode, &node, &file);
  962. nodeAlloc = TRUE;
  963. fileAlloc = TRUE;
  964. IsmDestroyObjectHandle (newBaseNode);
  965. } else {
  966. node = srcNode;
  967. file = srcFile;
  968. }
  969. IsmDestroyObjectHandle (baseNodeHandle);
  970. }
  971. } else {
  972. // destFile is explicitely specified. Let's just filter the node
  973. baseNodeHandle = IsmCreateObjectHandle (srcNode, NULL);
  974. if (baseNodeHandle) {
  975. newBaseNode = IsmFilterObject (
  976. g_FileType | PLATFORM_SOURCE,
  977. baseNodeHandle,
  978. NULL,
  979. NULL,
  980. NULL
  981. );
  982. if (newBaseNode) {
  983. IsmCreateObjectStringsFromHandle (newBaseNode, &node, &tempStr);
  984. nodeAlloc = TRUE;
  985. MYASSERT (!tempStr);
  986. IsmDestroyObjectString (tempStr);
  987. IsmDestroyObjectHandle (newBaseNode);
  988. } else {
  989. node = IsmDuplicateString (srcNode);
  990. }
  991. IsmDestroyObjectHandle (baseNodeHandle);
  992. }
  993. }
  994. }
  995. if (!node) {
  996. if (destNode && (destNode [0] != 0)) {
  997. node = destNode;
  998. } else {
  999. node = srcNode;
  1000. }
  1001. }
  1002. if (!file) {
  1003. if (destFile && (destFile [0] != 0)) {
  1004. file = destFile;
  1005. } else {
  1006. file = srcFile;
  1007. }
  1008. }
  1009. if (!destSect || (destSect [0] == 0)) {
  1010. destSect = srcSect;
  1011. }
  1012. if (!destKey || (destKey [0] == 0)) {
  1013. destKey = srcKey;
  1014. }
  1015. destSectKey = JoinTextEx (NULL, destSect, destKey, TEXT("="), 0, NULL);
  1016. destLeaf = JoinPaths (file, destSectKey);
  1017. OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, destLeaf);
  1018. FreePathString (destLeaf);
  1019. destLeaf = NULL;
  1020. FreeText (destSectKey);
  1021. destSectKey = NULL;
  1022. }
  1023. __finally {
  1024. IsmDestroyObjectString (srcNode);
  1025. IsmDestroyObjectString (srcFile);
  1026. IsmDestroyObjectString (baseNode);
  1027. IsmDestroyObjectString (baseFile);
  1028. IsmDestroyObjectString (destNode);
  1029. IsmDestroyObjectString (destFile);
  1030. if (fileAlloc) {
  1031. IsmDestroyObjectString (file);
  1032. }
  1033. if (nodeAlloc) {
  1034. IsmDestroyObjectString (node);
  1035. }
  1036. }
  1037. return TRUE;
  1038. }
  1039. BOOL
  1040. WINAPI
  1041. FilterDelete (
  1042. IN PCMIG_FILTERINPUT InputData,
  1043. OUT PMIG_FILTEROUTPUT OutputData,
  1044. IN BOOL NoRestoreObject,
  1045. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1046. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1047. )
  1048. {
  1049. //
  1050. // Mark the output data as deleted. That will be sufficient to
  1051. // cause the object to be deleted (even if it was also marked as
  1052. // "save")
  1053. //
  1054. OutputData->Deleted = TRUE;
  1055. return TRUE;
  1056. }
  1057. BOOL
  1058. WINAPI
  1059. FilterRegAutoFilter (
  1060. IN PCMIG_FILTERINPUT InputData,
  1061. OUT PMIG_FILTEROUTPUT OutputData,
  1062. IN BOOL NoRestoreObject,
  1063. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1064. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1065. )
  1066. {
  1067. PCTSTR node = NULL;
  1068. PCTSTR leaf = NULL;
  1069. // NTRAID#NTBUG9-153275-2000/08/01-jimschm Static buffer size
  1070. TCHAR newNode[MAX_PATH * 4];
  1071. TCHAR newLeaf[MAX_PATH * 4];
  1072. BOOL change = FALSE;
  1073. //
  1074. // Filter the object name
  1075. //
  1076. IsmCreateObjectStringsFromHandle (
  1077. InputData->CurrentObject.ObjectName,
  1078. &node,
  1079. &leaf
  1080. );
  1081. if (node) {
  1082. if (MappingSearchAndReplaceEx (
  1083. g_RegNodeFilterMap, // map handle
  1084. node, // source string
  1085. newNode, // dest buffer
  1086. 0, // source string bytes (0=unspecified)
  1087. NULL, // dest bytes required
  1088. ARRAYSIZE(newNode), // dest buffer size
  1089. 0, // flags
  1090. NULL, // extra data value
  1091. NULL // end of string
  1092. )) {
  1093. IsmDestroyObjectString (node);
  1094. node = newNode;
  1095. change = TRUE;
  1096. }
  1097. }
  1098. if (leaf) {
  1099. if (MappingSearchAndReplaceEx (
  1100. g_RegLeafFilterMap,
  1101. leaf,
  1102. newLeaf,
  1103. 0,
  1104. NULL,
  1105. ARRAYSIZE(newLeaf),
  1106. 0,
  1107. NULL,
  1108. NULL
  1109. )) {
  1110. IsmDestroyObjectString (leaf);
  1111. leaf = newLeaf;
  1112. change = TRUE;
  1113. }
  1114. }
  1115. if (change) {
  1116. OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, leaf);
  1117. }
  1118. if (node != newNode) {
  1119. IsmDestroyObjectString (node);
  1120. }
  1121. if (leaf != newLeaf) {
  1122. IsmDestroyObjectString (leaf);
  1123. }
  1124. return TRUE;
  1125. }
  1126. BOOL
  1127. WINAPI
  1128. FilterIniAutoFilter (
  1129. IN PCMIG_FILTERINPUT InputData,
  1130. OUT PMIG_FILTEROUTPUT OutputData,
  1131. IN BOOL NoRestoreObject,
  1132. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1133. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1134. )
  1135. {
  1136. // This function will split the INI object, filter the INI file
  1137. // so we know where it ends up, get section and key through the
  1138. // mapping so they can be potentially changed and rebuild the
  1139. // object name.
  1140. PCTSTR srcNode = NULL;
  1141. PCTSTR srcFile = NULL;
  1142. PTSTR srcSect = NULL;
  1143. PTSTR srcKey = NULL;
  1144. PCTSTR newNode = NULL;
  1145. PCTSTR newFile = NULL;
  1146. PCTSTR newSect = NULL;
  1147. PCTSTR newKey = NULL;
  1148. // NTRAID#NTBUG9-153275-2000/08/01-jimschm Static buffer size
  1149. TCHAR sectBuff [MAXINISIZE];
  1150. TCHAR keyBuff [MAXINISIZE];
  1151. MIG_OBJECTSTRINGHANDLE iniFile = NULL;
  1152. MIG_OBJECTSTRINGHANDLE newIniFile = NULL;
  1153. PCTSTR sectKey = NULL;
  1154. PCTSTR newLeaf = NULL;
  1155. BOOL orgDeleted = FALSE;
  1156. BOOL orgReplaced = FALSE;
  1157. BOOL change = FALSE;
  1158. //
  1159. // Filter the object name
  1160. //
  1161. IsmCreateObjectStringsFromHandle (
  1162. InputData->CurrentObject.ObjectName,
  1163. &srcNode,
  1164. &srcFile
  1165. );
  1166. if (srcNode && srcFile) {
  1167. srcSect = _tcschr (srcFile, TEXT('\\'));
  1168. if (srcSect) {
  1169. *srcSect = 0;
  1170. srcSect ++;
  1171. srcKey = _tcsrchr (srcSect, TEXT('='));
  1172. if (srcKey) {
  1173. *srcKey = 0;
  1174. srcKey ++;
  1175. // let's see if the section is replaced
  1176. if (MappingSearchAndReplaceEx (
  1177. g_IniSectFilterMap, // map handle
  1178. srcSect, // source string
  1179. sectBuff, // dest buffer
  1180. 0, // source string bytes (0=unspecified)
  1181. NULL, // dest bytes required
  1182. ARRAYSIZE(sectBuff), // dest buffer size
  1183. 0, // flags
  1184. NULL, // extra data value
  1185. NULL // end of string
  1186. )) {
  1187. newSect = sectBuff;
  1188. change = TRUE;
  1189. }
  1190. // let's see if the key is replaced
  1191. if (MappingSearchAndReplaceEx (
  1192. g_IniSectFilterMap, // map handle
  1193. srcKey, // source string
  1194. keyBuff, // dest buffer
  1195. 0, // source string bytes (0=unspecified)
  1196. NULL, // dest bytes required
  1197. ARRAYSIZE(keyBuff), // dest buffer size
  1198. 0, // flags
  1199. NULL, // extra data value
  1200. NULL // end of string
  1201. )) {
  1202. newKey = keyBuff;
  1203. change = TRUE;
  1204. }
  1205. iniFile = IsmCreateObjectHandle (srcNode, srcFile);
  1206. if (iniFile) {
  1207. newIniFile = IsmFilterObject (
  1208. g_FileType | PLATFORM_SOURCE,
  1209. iniFile,
  1210. NULL,
  1211. &orgDeleted,
  1212. &orgReplaced
  1213. );
  1214. if (newIniFile) {
  1215. if (IsmCreateObjectStringsFromHandle (newIniFile, &newNode, &newFile)) {
  1216. change = TRUE;
  1217. }
  1218. IsmDestroyObjectHandle (newIniFile);
  1219. }
  1220. IsmDestroyObjectHandle (iniFile);
  1221. }
  1222. }
  1223. }
  1224. }
  1225. if (change) {
  1226. sectKey = JoinTextEx (NULL, newSect?newSect:srcSect, newKey?newKey:srcKey, TEXT("="), 0, NULL);
  1227. if (sectKey) {
  1228. newLeaf = JoinPaths (newFile?newFile:srcFile, sectKey);
  1229. if (newLeaf) {
  1230. OutputData->NewObject.ObjectName = IsmCreateObjectHandle (newNode?newNode:srcNode, newLeaf);
  1231. FreePathString (newLeaf);
  1232. newLeaf = NULL;
  1233. }
  1234. FreeText (sectKey);
  1235. sectKey = NULL;
  1236. }
  1237. }
  1238. IsmDestroyObjectString (srcNode);
  1239. IsmDestroyObjectString (srcFile);
  1240. if (newNode) {
  1241. IsmDestroyObjectString (newNode);
  1242. newNode = NULL;
  1243. }
  1244. if (newFile) {
  1245. IsmDestroyObjectString (newFile);
  1246. newFile = NULL;
  1247. }
  1248. return TRUE;
  1249. }
  1250. BOOL
  1251. pOpmFindFile (
  1252. IN PCTSTR FileName
  1253. )
  1254. {
  1255. MIG_OBJECTSTRINGHANDLE objectName;
  1256. PTSTR node, leaf, leafPtr;
  1257. BOOL result = FALSE;
  1258. objectName = IsmCreateObjectHandle (FileName, NULL);
  1259. if (objectName) {
  1260. if (IsmGetObjectIdFromName (MIG_FILE_TYPE | PLATFORM_SOURCE, objectName, TRUE) != 0) {
  1261. result = TRUE;
  1262. }
  1263. IsmDestroyObjectHandle (objectName);
  1264. }
  1265. if (!result) {
  1266. node = DuplicateText (FileName);
  1267. leaf = _tcsrchr (node, TEXT('\\'));
  1268. if (leaf) {
  1269. leafPtr = (PTSTR) leaf;
  1270. leaf = _tcsinc (leaf);
  1271. *leafPtr = 0;
  1272. objectName = IsmCreateObjectHandle (node, leaf);
  1273. if (objectName) {
  1274. if (IsmGetObjectIdFromName (MIG_FILE_TYPE | PLATFORM_SOURCE, objectName, TRUE) != 0) {
  1275. result = TRUE;
  1276. }
  1277. IsmDestroyObjectHandle (objectName);
  1278. }
  1279. *leafPtr = TEXT('\\');
  1280. }
  1281. FreeText (node);
  1282. }
  1283. return result;
  1284. }
  1285. BOOL
  1286. pOpmSearchPath (
  1287. IN PCTSTR FileName,
  1288. IN DWORD BufferLength,
  1289. OUT PTSTR Buffer
  1290. )
  1291. {
  1292. return FALSE;
  1293. }
  1294. MIG_OBJECTSTRINGHANDLE
  1295. pSimpleTryHandle (
  1296. IN PCTSTR FullPath
  1297. )
  1298. {
  1299. PCTSTR buffer;
  1300. PTSTR leafPtr, leaf;
  1301. MIG_OBJECTSTRINGHANDLE source = NULL;
  1302. MIG_OBJECTSTRINGHANDLE result = NULL;
  1303. PTSTR workingPath;
  1304. PCTSTR sanitizedPath;
  1305. BOOL orgDeleted = FALSE;
  1306. BOOL orgReplaced = FALSE;
  1307. PCTSTR saved = NULL;
  1308. sanitizedPath = SanitizePath (FullPath);
  1309. if (!sanitizedPath) {
  1310. return NULL;
  1311. }
  1312. source = IsmCreateObjectHandle (sanitizedPath, NULL);
  1313. if (source) {
  1314. result = IsmFilterObject (
  1315. g_FileType | PLATFORM_SOURCE,
  1316. source,
  1317. NULL,
  1318. &orgDeleted,
  1319. &orgReplaced
  1320. );
  1321. // we do not want replaced directories
  1322. // since they can be false hits
  1323. if (orgDeleted) {
  1324. if (result) {
  1325. saved = result;
  1326. result = NULL;
  1327. }
  1328. }
  1329. if (!result && !orgDeleted) {
  1330. result = source;
  1331. } else {
  1332. IsmDestroyObjectHandle (source);
  1333. source = NULL;
  1334. }
  1335. }
  1336. if (result) {
  1337. goto exit;
  1338. }
  1339. buffer = DuplicatePathString (sanitizedPath, 0);
  1340. leaf = _tcsrchr (buffer, TEXT('\\'));
  1341. if (leaf) {
  1342. leafPtr = leaf;
  1343. leaf = _tcsinc (leaf);
  1344. *leafPtr = 0;
  1345. source = IsmCreateObjectHandle (buffer, leaf);
  1346. *leafPtr = TEXT('\\');
  1347. }
  1348. FreePathString (buffer);
  1349. if (source) {
  1350. result = IsmFilterObject (
  1351. g_FileType | PLATFORM_SOURCE,
  1352. source,
  1353. NULL,
  1354. &orgDeleted,
  1355. &orgReplaced
  1356. );
  1357. if (!result && !orgDeleted) {
  1358. result = source;
  1359. } else {
  1360. if (!result) {
  1361. result = saved;
  1362. }
  1363. IsmDestroyObjectHandle (source);
  1364. source = NULL;
  1365. }
  1366. }
  1367. if (result != saved) {
  1368. IsmDestroyObjectHandle (saved);
  1369. saved = NULL;
  1370. }
  1371. exit:
  1372. FreePathString (sanitizedPath);
  1373. return result;
  1374. }
  1375. MIG_OBJECTSTRINGHANDLE
  1376. pTryHandle (
  1377. IN PCTSTR FullPath,
  1378. IN PCTSTR Hint,
  1379. OUT PCTSTR *TrimmedResult
  1380. )
  1381. {
  1382. PATH_ENUM pathEnum;
  1383. PCTSTR newPath;
  1384. MIG_OBJECTSTRINGHANDLE result = NULL;
  1385. PCTSTR nativeName = NULL;
  1386. PCTSTR lastSegPtr;
  1387. if (TrimmedResult) {
  1388. *TrimmedResult = NULL;
  1389. }
  1390. result = pSimpleTryHandle (FullPath);
  1391. if (result || (!Hint)) {
  1392. return result;
  1393. }
  1394. if (EnumFirstPathEx (&pathEnum, Hint, NULL, NULL, FALSE)) {
  1395. do {
  1396. newPath = JoinPaths (pathEnum.PtrCurrPath, FullPath);
  1397. result = pSimpleTryHandle (newPath);
  1398. if (result) {
  1399. AbortPathEnum (&pathEnum);
  1400. FreePathString (newPath);
  1401. // now, if the initial FullPath did not have any wack in it
  1402. // we will take the last segment of the result and put it
  1403. // in TrimmedResult
  1404. if (TrimmedResult && (!_tcschr (FullPath, TEXT('\\')))) {
  1405. nativeName = IsmGetNativeObjectName (g_FileType, result);
  1406. if (nativeName) {
  1407. lastSegPtr = _tcsrchr (nativeName, TEXT('\\'));
  1408. if (lastSegPtr) {
  1409. lastSegPtr = _tcsinc (lastSegPtr);
  1410. if (lastSegPtr) {
  1411. *TrimmedResult = DuplicatePathString (lastSegPtr, 0);
  1412. }
  1413. }
  1414. }
  1415. }
  1416. return result;
  1417. }
  1418. FreePathString (newPath);
  1419. } while (EnumNextPath (&pathEnum));
  1420. }
  1421. AbortPathEnum (&pathEnum);
  1422. return NULL;
  1423. }
  1424. BOOL
  1425. WINAPI
  1426. DoRegAutoFilter (
  1427. IN MIG_OBJECTTYPEID SrcObjectTypeId,
  1428. IN MIG_OBJECTSTRINGHANDLE SrcObjectName,
  1429. IN PCMIG_CONTENT OriginalContent,
  1430. IN PCMIG_CONTENT CurrentContent,
  1431. OUT PMIG_CONTENT NewContent,
  1432. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1433. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1434. )
  1435. {
  1436. PTSTR leafPtr = NULL;
  1437. PDWORD valueType;
  1438. MIG_OBJECTSTRINGHANDLE source;
  1439. MIG_OBJECTSTRINGHANDLE destination;
  1440. PCTSTR leaf;
  1441. TCHAR expandBuffer[4096];
  1442. TCHAR hintBuffer[4096];
  1443. PTSTR buffer;
  1444. GROWBUFFER result = INIT_GROWBUFFER;
  1445. GROWBUFFER cmdLineBuffer = INIT_GROWBUFFER;
  1446. PCMDLINE cmdLine;
  1447. UINT u;
  1448. PCTSTR data, p, end;
  1449. PCTSTR nativeDest;
  1450. PCTSTR newData, oldData;
  1451. BOOL parsable;
  1452. BOOL replaced = FALSE;
  1453. BOOL orgDeleted = FALSE;
  1454. BOOL orgReplaced = FALSE;
  1455. PCTSTR trimmedResult = NULL;
  1456. BOOL newContent = TRUE;
  1457. PCTSTR destResult = NULL;
  1458. //
  1459. // Filter the data for any references to %windir%
  1460. //
  1461. if (!CurrentContent->ContentInFile) {
  1462. parsable = FALSE;
  1463. valueType = (PDWORD)(CurrentContent->Details.DetailsData);
  1464. if (valueType) {
  1465. if (*valueType == REG_EXPAND_SZ ||
  1466. *valueType == REG_SZ
  1467. ) {
  1468. parsable = TRUE;
  1469. }
  1470. } else {
  1471. parsable = IsmIsObjectHandleNodeOnly (SrcObjectName);
  1472. }
  1473. if (parsable) {
  1474. data = (PTSTR) CurrentContent->MemoryContent.ContentBytes;
  1475. end = (PCTSTR) (CurrentContent->MemoryContent.ContentBytes + CurrentContent->MemoryContent.ContentSize);
  1476. while (data < end) {
  1477. if (*data == 0) {
  1478. break;
  1479. }
  1480. data = _tcsinc (data);
  1481. }
  1482. if (data >= end) {
  1483. parsable = FALSE;
  1484. }
  1485. }
  1486. if (parsable) {
  1487. data = (PTSTR) CurrentContent->MemoryContent.ContentBytes;
  1488. if ((*valueType == REG_EXPAND_SZ) ||
  1489. (*valueType == REG_SZ)
  1490. ) {
  1491. //
  1492. // Expand the data
  1493. //
  1494. MappingSearchAndReplaceEx (
  1495. g_EnvMap,
  1496. data,
  1497. expandBuffer,
  1498. 0,
  1499. NULL,
  1500. ARRAYSIZE(expandBuffer),
  1501. 0,
  1502. NULL,
  1503. NULL
  1504. );
  1505. data = expandBuffer;
  1506. }
  1507. *hintBuffer = 0;
  1508. if (DestinationOperationData &&
  1509. (DestinationOperationData->Type == BLOBTYPE_STRING) &&
  1510. (DestinationOperationData->String)
  1511. ) {
  1512. MappingSearchAndReplaceEx (
  1513. g_EnvMap,
  1514. DestinationOperationData->String,
  1515. hintBuffer,
  1516. 0,
  1517. NULL,
  1518. ARRAYSIZE(hintBuffer),
  1519. 0,
  1520. NULL,
  1521. NULL
  1522. );
  1523. }
  1524. destination = pTryHandle (data, *hintBuffer?hintBuffer:NULL, &trimmedResult);
  1525. if (destination) {
  1526. replaced = TRUE;
  1527. if (trimmedResult) {
  1528. GbAppendString (&result, trimmedResult);
  1529. FreePathString (trimmedResult);
  1530. } else {
  1531. nativeDest = IsmGetNativeObjectName (g_FileType, destination);
  1532. GbAppendString (&result, nativeDest);
  1533. IsmReleaseMemory (nativeDest);
  1534. }
  1535. }
  1536. // finally, if we failed we are going to assume it's a command line
  1537. if (!replaced) {
  1538. newData = DuplicatePathString (data, 0);
  1539. cmdLine = ParseCmdLineEx (data, NULL, &pOpmFindFile, &pOpmSearchPath, &cmdLineBuffer);
  1540. if (cmdLine) {
  1541. //
  1542. // Find the file referenced in the list or command line
  1543. //
  1544. for (u = 0 ; u < cmdLine->ArgCount ; u++) {
  1545. p = cmdLine->Args[u].CleanedUpArg;
  1546. // first we try it as is
  1547. destination = pTryHandle (p, *hintBuffer?hintBuffer:NULL, &trimmedResult);
  1548. // maybe we have something like /m:c:\foo.txt
  1549. // we need to go forward until we find a sequence of
  1550. // <alpha>:\<something>
  1551. if (!destination && p[0] && p[1]) {
  1552. while (p[2]) {
  1553. if (_istalpha ((CHARTYPE) _tcsnextc (p)) &&
  1554. p[1] == TEXT(':') &&
  1555. p[2] == TEXT('\\')
  1556. ) {
  1557. destination = pTryHandle (p, *hintBuffer?hintBuffer:NULL, &trimmedResult);
  1558. if (destination) {
  1559. break;
  1560. }
  1561. }
  1562. p ++;
  1563. }
  1564. }
  1565. if (destination) {
  1566. replaced = TRUE;
  1567. if (trimmedResult) {
  1568. oldData = StringSearchAndReplace (newData, p, trimmedResult);
  1569. if (oldData) {
  1570. FreePathString (newData);
  1571. newData = oldData;
  1572. }
  1573. FreePathString (trimmedResult);
  1574. } else {
  1575. nativeDest = IsmGetNativeObjectName (g_FileType, destination);
  1576. oldData = StringSearchAndReplace (newData, p, nativeDest);
  1577. if (oldData) {
  1578. FreePathString (newData);
  1579. newData = oldData;
  1580. }
  1581. IsmReleaseMemory (nativeDest);
  1582. }
  1583. IsmDestroyObjectHandle (destination);
  1584. destination = NULL;
  1585. }
  1586. }
  1587. }
  1588. GbFree (&cmdLineBuffer);
  1589. if (!replaced) {
  1590. if (newData) {
  1591. FreePathString (newData);
  1592. }
  1593. } else {
  1594. if (newData) {
  1595. GbAppendString (&result, newData);
  1596. FreePathString (newData);
  1597. }
  1598. }
  1599. }
  1600. if (destination) {
  1601. IsmDestroyObjectHandle (destination);
  1602. destination = NULL;
  1603. }
  1604. if (replaced && result.Buf) {
  1605. // looks like we have new content
  1606. // Let's do one more check. If this is a REG_EXPAND_SZ we will do our best to
  1607. // keep the stuff unexpanded. So if the source string expanded on the destination
  1608. // machine is the same as the destination string we won't do anything.
  1609. newContent = TRUE;
  1610. if (*valueType == REG_EXPAND_SZ) {
  1611. destResult = IsmExpandEnvironmentString (
  1612. PLATFORM_DESTINATION,
  1613. S_SYSENVVAR_GROUP,
  1614. (PCTSTR) CurrentContent->MemoryContent.ContentBytes,
  1615. NULL
  1616. );
  1617. if (destResult && StringIMatch (destResult, (PCTSTR)result.Buf)) {
  1618. newContent = FALSE;
  1619. }
  1620. if (destResult) {
  1621. IsmReleaseMemory (destResult);
  1622. destResult = NULL;
  1623. }
  1624. }
  1625. if (newContent) {
  1626. NewContent->MemoryContent.ContentSize = SizeOfString ((PCTSTR)result.Buf);
  1627. NewContent->MemoryContent.ContentBytes = IsmGetMemory (NewContent->MemoryContent.ContentSize);
  1628. CopyMemory ((PTSTR)NewContent->MemoryContent.ContentBytes, result.Buf, NewContent->MemoryContent.ContentSize);
  1629. }
  1630. }
  1631. GbFree (&result);
  1632. }
  1633. }
  1634. return TRUE;
  1635. }
  1636. BOOL
  1637. WINAPI
  1638. DoIniAutoFilter (
  1639. IN MIG_OBJECTTYPEID SrcObjectTypeId,
  1640. IN MIG_OBJECTSTRINGHANDLE SrcObjectName,
  1641. IN PCMIG_CONTENT OriginalContent,
  1642. IN PCMIG_CONTENT CurrentContent,
  1643. OUT PMIG_CONTENT NewContent,
  1644. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1645. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1646. )
  1647. {
  1648. // This function will get the content of an INI key and see if there is
  1649. // a path there somewhere. If yes, it will attempt to find the new
  1650. // location for the file and replace it in the INI key content.
  1651. PTSTR leafPtr = NULL;
  1652. PDWORD valueType;
  1653. MIG_OBJECTSTRINGHANDLE source;
  1654. MIG_OBJECTSTRINGHANDLE destination;
  1655. PCTSTR leaf;
  1656. TCHAR expandBuffer[4096];
  1657. TCHAR hintBuffer[4096];
  1658. PTSTR buffer;
  1659. GROWBUFFER result = INIT_GROWBUFFER;
  1660. GROWBUFFER cmdLineBuffer = INIT_GROWBUFFER;
  1661. PCMDLINE cmdLine;
  1662. UINT u;
  1663. PCTSTR data, p, end;
  1664. PCTSTR nativeDest;
  1665. PCTSTR newData, oldData;
  1666. BOOL parsable;
  1667. BOOL replaced = FALSE;
  1668. BOOL orgDeleted = FALSE;
  1669. BOOL orgReplaced = FALSE;
  1670. PCTSTR trimmedResult = NULL;
  1671. BOOL newContent = TRUE;
  1672. PCTSTR destResult = NULL;
  1673. //
  1674. // Filter the data for any references to %windir%
  1675. //
  1676. if (!CurrentContent->ContentInFile) {
  1677. data = (PTSTR) CurrentContent->MemoryContent.ContentBytes;
  1678. end = (PCTSTR) (CurrentContent->MemoryContent.ContentBytes + CurrentContent->MemoryContent.ContentSize);
  1679. parsable = TRUE;
  1680. while (data < end) {
  1681. if (*data == 0) {
  1682. break;
  1683. }
  1684. data = _tcsinc (data);
  1685. }
  1686. if (data >= end) {
  1687. parsable = FALSE;
  1688. }
  1689. if (parsable) {
  1690. data = (PTSTR) CurrentContent->MemoryContent.ContentBytes;
  1691. MappingSearchAndReplaceEx (
  1692. g_EnvMap,
  1693. data,
  1694. expandBuffer,
  1695. 0,
  1696. NULL,
  1697. ARRAYSIZE(expandBuffer),
  1698. 0,
  1699. NULL,
  1700. NULL
  1701. );
  1702. data = expandBuffer;
  1703. *hintBuffer = 0;
  1704. if (DestinationOperationData &&
  1705. (DestinationOperationData->Type == BLOBTYPE_STRING) &&
  1706. (DestinationOperationData->String)
  1707. ) {
  1708. MappingSearchAndReplaceEx (
  1709. g_EnvMap,
  1710. DestinationOperationData->String,
  1711. hintBuffer,
  1712. 0,
  1713. NULL,
  1714. ARRAYSIZE(hintBuffer),
  1715. 0,
  1716. NULL,
  1717. NULL
  1718. );
  1719. }
  1720. destination = pTryHandle (data, *hintBuffer?hintBuffer:NULL, &trimmedResult);
  1721. if (destination) {
  1722. replaced = TRUE;
  1723. if (trimmedResult) {
  1724. GbAppendString (&result, trimmedResult);
  1725. FreePathString (trimmedResult);
  1726. } else {
  1727. nativeDest = IsmGetNativeObjectName (g_FileType, destination);
  1728. GbAppendString (&result, nativeDest);
  1729. IsmReleaseMemory (nativeDest);
  1730. }
  1731. }
  1732. // finally, if we failed we are going to assume it's a command line
  1733. if (!replaced) {
  1734. newData = DuplicatePathString (data, 0);
  1735. cmdLine = ParseCmdLineEx (data, NULL, &pOpmFindFile, &pOpmSearchPath, &cmdLineBuffer);
  1736. if (cmdLine) {
  1737. //
  1738. // Find the file referenced in the list or command line
  1739. //
  1740. for (u = 0 ; u < cmdLine->ArgCount ; u++) {
  1741. p = cmdLine->Args[u].CleanedUpArg;
  1742. // first we try it as is
  1743. destination = pTryHandle (p, *hintBuffer?hintBuffer:NULL, &trimmedResult);
  1744. // maybe we have something like /m:c:\foo.txt
  1745. // we need to go forward until we find a sequence of
  1746. // <alpha>:\<something>
  1747. if (!destination && p[0] && p[1]) {
  1748. while (p[2]) {
  1749. if (_istalpha ((CHARTYPE) _tcsnextc (p)) &&
  1750. p[1] == TEXT(':') &&
  1751. p[2] == TEXT('\\')
  1752. ) {
  1753. destination = pTryHandle (p, *hintBuffer?hintBuffer:NULL, &trimmedResult);
  1754. if (destination) {
  1755. break;
  1756. }
  1757. }
  1758. p ++;
  1759. }
  1760. }
  1761. if (destination) {
  1762. replaced = TRUE;
  1763. if (trimmedResult) {
  1764. oldData = StringSearchAndReplace (newData, p, trimmedResult);
  1765. if (oldData) {
  1766. FreePathString (newData);
  1767. newData = oldData;
  1768. }
  1769. FreePathString (trimmedResult);
  1770. } else {
  1771. nativeDest = IsmGetNativeObjectName (g_FileType, destination);
  1772. oldData = StringSearchAndReplace (newData, p, nativeDest);
  1773. if (oldData) {
  1774. FreePathString (newData);
  1775. newData = oldData;
  1776. }
  1777. IsmReleaseMemory (nativeDest);
  1778. }
  1779. IsmDestroyObjectHandle (destination);
  1780. destination = NULL;
  1781. }
  1782. }
  1783. }
  1784. GbFree (&cmdLineBuffer);
  1785. if (!replaced) {
  1786. if (newData) {
  1787. FreePathString (newData);
  1788. }
  1789. } else {
  1790. if (newData) {
  1791. GbAppendString (&result, newData);
  1792. FreePathString (newData);
  1793. }
  1794. }
  1795. }
  1796. if (destination) {
  1797. IsmDestroyObjectHandle (destination);
  1798. destination = NULL;
  1799. }
  1800. if (replaced && result.Buf) {
  1801. // looks like we have new content
  1802. // Let's do one more check. If the source string has environment variables in it,
  1803. // we will do our best to keep the stuff unexpanded. So if the source string
  1804. // expanded on the destination machine is the same as the destination string
  1805. // we won't do anything.
  1806. newContent = TRUE;
  1807. destResult = IsmExpandEnvironmentString (
  1808. PLATFORM_DESTINATION,
  1809. S_SYSENVVAR_GROUP,
  1810. (PCTSTR) CurrentContent->MemoryContent.ContentBytes,
  1811. NULL
  1812. );
  1813. if (destResult && StringIMatch (destResult, (PCTSTR)result.Buf)) {
  1814. newContent = FALSE;
  1815. }
  1816. if (destResult) {
  1817. IsmReleaseMemory (destResult);
  1818. destResult = NULL;
  1819. }
  1820. if (newContent) {
  1821. NewContent->MemoryContent.ContentSize = SizeOfString ((PCTSTR)result.Buf);
  1822. NewContent->MemoryContent.ContentBytes = IsmGetMemory (NewContent->MemoryContent.ContentSize);
  1823. CopyMemory ((PTSTR)NewContent->MemoryContent.ContentBytes, result.Buf, NewContent->MemoryContent.ContentSize);
  1824. }
  1825. }
  1826. GbFree (&result);
  1827. }
  1828. }
  1829. return TRUE;
  1830. }
  1831. BOOL
  1832. WINAPI
  1833. DoFixDefaultIcon (
  1834. IN MIG_OBJECTTYPEID SrcObjectTypeId,
  1835. IN MIG_OBJECTSTRINGHANDLE SrcObjectName,
  1836. IN PCMIG_CONTENT OriginalContent,
  1837. IN PCMIG_CONTENT CurrentContent,
  1838. OUT PMIG_CONTENT NewContent,
  1839. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1840. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1841. )
  1842. {
  1843. MIG_PROPERTYDATAID propDataId;
  1844. MIG_BLOBTYPE propDataType;
  1845. UINT requiredSize;
  1846. PDWORD valueType;
  1847. PICON_GROUP iconGroup = NULL;
  1848. ICON_SGROUP iconSGroup = {0, NULL};
  1849. PTSTR iconLibPath = NULL;
  1850. INT iconNumber = 0;
  1851. PTSTR dataCopy;
  1852. if (CurrentContent->ContentInFile) {
  1853. return TRUE;
  1854. }
  1855. valueType = (PDWORD)(CurrentContent->Details.DetailsData);
  1856. if (*valueType != REG_SZ && *valueType != REG_EXPAND_SZ) {
  1857. return TRUE;
  1858. }
  1859. // let's see if we have our property attached
  1860. propDataId = IsmGetPropertyFromObject (SrcObjectTypeId, SrcObjectName, g_DefaultIconData);
  1861. if (!propDataId) {
  1862. return TRUE;
  1863. }
  1864. if (!IsmGetPropertyData (propDataId, NULL, 0, &requiredSize, &propDataType)) {
  1865. return TRUE;
  1866. }
  1867. iconSGroup.DataSize = requiredSize;
  1868. iconSGroup.Data = IsmGetMemory (requiredSize);
  1869. if (!IsmGetPropertyData (propDataId, (PBYTE)iconSGroup.Data, requiredSize, NULL, &propDataType)) {
  1870. IsmReleaseMemory (iconSGroup.Data);
  1871. return TRUE;
  1872. }
  1873. if (!iconSGroup.DataSize) {
  1874. IsmReleaseMemory (iconSGroup.Data);
  1875. return TRUE;
  1876. }
  1877. iconGroup = IcoDeSerializeIconGroup (&iconSGroup);
  1878. if (!iconGroup) {
  1879. IsmReleaseMemory (iconSGroup.Data);
  1880. return TRUE;
  1881. }
  1882. if (IsmGetEnvironmentString (
  1883. PLATFORM_DESTINATION,
  1884. NULL,
  1885. S_ENV_ICONLIB,
  1886. NULL,
  1887. 0,
  1888. &requiredSize
  1889. )) {
  1890. iconLibPath = IsmGetMemory (requiredSize);
  1891. if (IsmGetEnvironmentString (
  1892. PLATFORM_DESTINATION,
  1893. NULL,
  1894. S_ENV_ICONLIB,
  1895. iconLibPath,
  1896. requiredSize,
  1897. NULL
  1898. )) {
  1899. if (IcoWriteIconGroupToPeFile (iconLibPath, iconGroup, NULL, &iconNumber)) {
  1900. // finally we wrote the icon, fix the content and tell scanstate that
  1901. // we iconlib was used
  1902. dataCopy = IsmGetMemory (SizeOfString (iconLibPath) + sizeof (TCHAR) + 20 * sizeof (TCHAR));
  1903. wsprintf (dataCopy, TEXT("%s,%d"), iconLibPath, iconNumber);
  1904. NewContent->MemoryContent.ContentSize = SizeOfString (dataCopy);
  1905. NewContent->MemoryContent.ContentBytes = (PBYTE) dataCopy;
  1906. IsmSetEnvironmentFlag (PLATFORM_DESTINATION, NULL, S_ENV_SAVE_ICONLIB);
  1907. }
  1908. }
  1909. IsmReleaseMemory (iconLibPath);
  1910. }
  1911. IcoReleaseIconGroup (iconGroup);
  1912. IsmReleaseMemory (iconSGroup.Data);
  1913. return TRUE;
  1914. }
  1915. BOOL
  1916. pDoesDestObjectExist (
  1917. IN MIG_OBJECTSTRINGHANDLE ObjectName
  1918. )
  1919. {
  1920. PCTSTR nativeName;
  1921. BOOL result = FALSE;
  1922. nativeName = IsmGetNativeObjectName (PLATFORM_DESTINATION | MIG_FILE_TYPE, ObjectName);
  1923. if (nativeName) {
  1924. if (IsmGetRealPlatform () == PLATFORM_DESTINATION) {
  1925. result = DoesFileExist (nativeName);
  1926. }
  1927. IsmReleaseMemory (nativeName);
  1928. nativeName = NULL;
  1929. }
  1930. return result;
  1931. }
  1932. BOOL
  1933. WINAPI
  1934. FilterFileAutoFilter (
  1935. IN PCMIG_FILTERINPUT InputData,
  1936. OUT PMIG_FILTEROUTPUT OutputData,
  1937. IN BOOL NoRestoreObject,
  1938. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1939. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1940. )
  1941. {
  1942. PCTSTR node, nodeWack;
  1943. PCTSTR leaf;
  1944. // NTRAID#NTBUG9-153275-2000/08/01-jimschm Static buffer size
  1945. TCHAR newNode[MAX_PATH * 4];
  1946. TCHAR newLeaf[MAX_PATH * 4];
  1947. BOOL fullChanged = FALSE;
  1948. PCTSTR nativeName;
  1949. PTSTR leafPtr;
  1950. BOOL changed = FALSE;
  1951. if (InputData &&
  1952. InputData->OriginalObject.ObjectName &&
  1953. InputData->CurrentObject.ObjectName &&
  1954. (InputData->OriginalObject.ObjectName != InputData->CurrentObject.ObjectName)
  1955. ) {
  1956. // this was already modified. Let's not touch it.
  1957. return TRUE;
  1958. }
  1959. //
  1960. // Filter the object name
  1961. //
  1962. IsmCreateObjectStringsFromHandle (
  1963. InputData->CurrentObject.ObjectName,
  1964. &node,
  1965. &leaf
  1966. );
  1967. /*
  1968. // I am taking this out. The point is,
  1969. // even if we are not restoring the file,
  1970. // we should get the best guess as to where
  1971. // this file would end up in case it would
  1972. // get moved.
  1973. if (NoRestoreObject && leaf) {
  1974. IsmDestroyObjectString (node);
  1975. IsmDestroyObjectString (leaf);
  1976. return TRUE;
  1977. }
  1978. */
  1979. if (node && leaf) {
  1980. // let's do a trick here. Let's build the native name and
  1981. // see if we can find an env replacement for the entire
  1982. // path
  1983. nativeName = IsmGetNativeObjectName (InputData->CurrentObject.ObjectTypeId, InputData->CurrentObject.ObjectName);
  1984. if (nativeName) {
  1985. if (MappingSearchAndReplaceEx (
  1986. g_FileNodeFilterMap, // map handle
  1987. nativeName, // source string
  1988. newNode, // dest buffer
  1989. 0, // source string bytes (0=unspecified)
  1990. NULL, // dest bytes required
  1991. ARRAYSIZE(newNode), // dest buffer size
  1992. STRMAP_COMPLETE_MATCH_ONLY, // flags
  1993. NULL, // extra data value
  1994. NULL // end of string
  1995. )) {
  1996. // we have a replacement. Let's split it into node and leaf
  1997. leafPtr = _tcsrchr (newNode, TEXT('\\'));
  1998. if (leafPtr) {
  1999. *leafPtr = 0;
  2000. leafPtr ++;
  2001. StringCopy (newLeaf, leafPtr);
  2002. IsmDestroyObjectString (node);
  2003. node = newNode;
  2004. IsmDestroyObjectString (leaf);
  2005. leaf = newLeaf;
  2006. fullChanged = TRUE;
  2007. }
  2008. }
  2009. IsmReleaseMemory (nativeName);
  2010. nativeName = NULL;
  2011. }
  2012. }
  2013. if (!fullChanged && node) {
  2014. nodeWack = JoinPaths (node, TEXT(""));
  2015. if (MappingSearchAndReplaceEx (
  2016. g_FileNodeFilterMap, // map handle
  2017. nodeWack, // source string
  2018. newNode, // dest buffer
  2019. 0, // source string bytes (0=unspecified)
  2020. NULL, // dest bytes required
  2021. ARRAYSIZE(newNode), // dest buffer size
  2022. STRMAP_FIRST_CHAR_MUST_MATCH|
  2023. STRMAP_RETURN_AFTER_FIRST_REPLACE|
  2024. STRMAP_REQUIRE_WACK_OR_NUL, // flags
  2025. NULL, // extra data value
  2026. NULL // end of string
  2027. )) {
  2028. IsmDestroyObjectString (node);
  2029. node = newNode;
  2030. changed = TRUE;
  2031. } else {
  2032. if (MappingSearchAndReplaceEx (
  2033. g_FileNodeFilterMap, // map handle
  2034. node, // source string
  2035. newNode, // dest buffer
  2036. 0, // source string bytes (0=unspecified)
  2037. NULL, // dest bytes required
  2038. ARRAYSIZE(newNode), // dest buffer size
  2039. STRMAP_FIRST_CHAR_MUST_MATCH|
  2040. STRMAP_RETURN_AFTER_FIRST_REPLACE|
  2041. STRMAP_REQUIRE_WACK_OR_NUL, // flags
  2042. NULL, // extra data value
  2043. NULL // end of string
  2044. )) {
  2045. IsmDestroyObjectString (node);
  2046. node = newNode;
  2047. changed = TRUE;
  2048. }
  2049. }
  2050. FreePathString (nodeWack);
  2051. nodeWack = NULL;
  2052. }
  2053. if (!fullChanged && leaf) {
  2054. if (MappingSearchAndReplaceEx (
  2055. g_FileLeafFilterMap,
  2056. leaf,
  2057. newLeaf,
  2058. 0,
  2059. NULL,
  2060. ARRAYSIZE(newLeaf),
  2061. 0,
  2062. NULL,
  2063. NULL
  2064. )) {
  2065. IsmDestroyObjectString (leaf);
  2066. leaf = newLeaf;
  2067. changed = TRUE;
  2068. }
  2069. }
  2070. if (fullChanged || changed) {
  2071. OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, leaf);
  2072. }
  2073. OutputData->Replaced = (NoRestoreObject||OutputData->Deleted)?pDoesDestObjectExist (OutputData->NewObject.ObjectName):0;
  2074. if (node != newNode) {
  2075. IsmDestroyObjectString (node);
  2076. }
  2077. if (leaf != newLeaf) {
  2078. IsmDestroyObjectString (leaf);
  2079. }
  2080. return TRUE;
  2081. }
  2082. PCTSTR
  2083. pProcessRenameExMacro (
  2084. IN PCTSTR Node,
  2085. IN PCTSTR Leaf, OPTIONAL
  2086. IN BOOL ZeroBase
  2087. )
  2088. {
  2089. PCTSTR workingStr;
  2090. PTSTR macroStartPtr = NULL;
  2091. PTSTR macroEndPtr = NULL;
  2092. PTSTR macroCopy = NULL;
  2093. DWORD macroLength = 0;
  2094. PTSTR macroParsePtr = NULL;
  2095. TCHAR macroBuffer [MAX_PATH];
  2096. HRESULT hr;
  2097. MIG_OBJECTSTRINGHANDLE testHandle = NULL;
  2098. UINT index;
  2099. PTSTR newString = NULL;
  2100. // If Leaf is supplied, we are working only on the Leaf
  2101. workingStr = Leaf ? Leaf : Node;
  2102. // Extract macro
  2103. macroStartPtr = _tcschr (workingStr, S_RENAMEEX_START_CHAR);
  2104. if (macroStartPtr) {
  2105. macroEndPtr = _tcschr (macroStartPtr + 1, S_RENAMEEX_END_CHAR);
  2106. }
  2107. if (macroEndPtr) {
  2108. macroCopy = DuplicateText (macroStartPtr + 1);
  2109. macroCopy[macroEndPtr-macroStartPtr-1] = 0;
  2110. }
  2111. if (macroCopy) {
  2112. // Build a possible destination
  2113. if (ZeroBase) {
  2114. index = 0;
  2115. } else {
  2116. index = 1;
  2117. }
  2118. do {
  2119. if (newString) {
  2120. FreeText (newString);
  2121. newString = NULL;
  2122. }
  2123. IsmDestroyObjectHandle (testHandle);
  2124. __try {
  2125. hr = StringCbPrintf (macroBuffer, sizeof (macroBuffer), macroCopy, index);
  2126. }
  2127. __except (EXCEPTION_EXECUTE_HANDLER) {
  2128. // something went wrong. The pattern might have been terribly wrong
  2129. hr = S_FALSE;
  2130. }
  2131. if (hr != S_OK) {
  2132. // something is wrong with the rename pattern. Let's just get out of here.
  2133. break;
  2134. }
  2135. newString = AllocText (
  2136. (HALF_PTR) (macroStartPtr - workingStr) +
  2137. TcharCount (macroBuffer) +
  2138. TcharCount (macroEndPtr) +
  2139. 1
  2140. );
  2141. if (newString) {
  2142. StringCopyTcharCount (newString, workingStr, (HALF_PTR) (macroStartPtr - workingStr) + 1);
  2143. StringCat (newString, macroBuffer);
  2144. StringCat (newString, macroEndPtr + 1);
  2145. }
  2146. if (Leaf) {
  2147. testHandle = IsmCreateObjectHandle (Node, newString);
  2148. } else {
  2149. testHandle = IsmCreateObjectHandle (newString, NULL);
  2150. }
  2151. index++;
  2152. } while (pDoesDifferentRegExist (testHandle) ||
  2153. HtFindString (g_RegCollisionDestTable, testHandle));
  2154. if (testHandle) {
  2155. IsmDestroyObjectHandle (testHandle);
  2156. }
  2157. FreeText (macroCopy);
  2158. }
  2159. if (!newString) {
  2160. newString = DuplicateText (workingStr);
  2161. }
  2162. return newString;
  2163. }
  2164. BOOL
  2165. WINAPI
  2166. FilterRenameExFilter (
  2167. IN PCMIG_FILTERINPUT InputData,
  2168. OUT PMIG_FILTEROUTPUT OutputData,
  2169. IN BOOL NoRestoreObject,
  2170. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  2171. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  2172. )
  2173. {
  2174. PCTSTR doNode = NULL;
  2175. PCTSTR doLeaf = NULL;
  2176. PCTSTR destNode = NULL;
  2177. PCTSTR newNode = NULL;
  2178. PCTSTR rootNode;
  2179. PCTSTR destLeaf = NULL;
  2180. PCTSTR srcNode = NULL;
  2181. PCTSTR srcLeaf = NULL;
  2182. // NTRAID#NTBUG9-153274-2000/08/01-jimschm Static buffer size
  2183. TCHAR newSrcNode[MAX_PATH * 4];
  2184. TCHAR newSrcLeaf[MAX_PATH * 4];
  2185. HASHITEM hashItem;
  2186. MIG_OBJECTSTRINGHANDLE storeHandle;
  2187. MIG_OBJECTSTRINGHANDLE testHandle;
  2188. MIG_OBJECTSTRINGHANDLE nodeHandle;
  2189. PTSTR ptr = NULL;
  2190. PTSTR ptr2;
  2191. PTSTR workingStr;
  2192. BOOL fFoundMatch = FALSE;
  2193. BOOL zeroBase;
  2194. IsmCreateObjectStringsFromHandle (
  2195. InputData->CurrentObject.ObjectName,
  2196. &srcNode,
  2197. &srcLeaf
  2198. );
  2199. if (srcNode) {
  2200. if (MappingSearchAndReplaceEx (
  2201. g_RegNodeFilterMap,
  2202. srcNode,
  2203. newSrcNode,
  2204. 0,
  2205. NULL,
  2206. ARRAYSIZE(newSrcNode),
  2207. 0,
  2208. NULL,
  2209. NULL
  2210. )) {
  2211. IsmDestroyObjectString (srcNode);
  2212. srcNode = newSrcNode;
  2213. }
  2214. }
  2215. if (srcLeaf) {
  2216. if (MappingSearchAndReplaceEx (
  2217. g_RegLeafFilterMap,
  2218. srcLeaf,
  2219. newSrcLeaf,
  2220. 0,
  2221. NULL,
  2222. ARRAYSIZE(newSrcLeaf),
  2223. 0,
  2224. NULL,
  2225. NULL
  2226. )) {
  2227. IsmDestroyObjectString (srcLeaf);
  2228. srcLeaf = newSrcLeaf;
  2229. }
  2230. }
  2231. if (HtFindStringEx (g_RegCollisionSrcTable, InputData->OriginalObject.ObjectName, (PVOID)(&hashItem), FALSE)) {
  2232. // We've already renamed this object
  2233. HtCopyStringData (g_RegCollisionDestTable, hashItem, (PVOID)(&testHandle));
  2234. IsmCreateObjectStringsFromHandle (testHandle, &destNode, &destLeaf);
  2235. // Do not free testHandle here because it is a pointer into the hash table data
  2236. OutputData->NewObject.ObjectName = IsmCreateObjectHandle (destNode, destLeaf);
  2237. IsmDestroyObjectString (destNode);
  2238. IsmDestroyObjectString (destLeaf);
  2239. destNode;
  2240. destLeaf = NULL;
  2241. } else {
  2242. // We've never seen this object yet
  2243. IsmCreateObjectStringsFromHandle (DestinationOperationData->String, &doNode, &doLeaf);
  2244. // Pick a new node
  2245. // First check to see if this object's node has already been processed
  2246. workingStr = DuplicateText(srcNode);
  2247. if (workingStr) {
  2248. do {
  2249. nodeHandle = IsmCreateObjectHandle (workingStr, NULL);
  2250. if (HtFindStringEx (g_RegCollisionSrcTable, nodeHandle, (PVOID)(&hashItem), FALSE)) {
  2251. HtCopyStringData (g_RegCollisionDestTable, hashItem, (PVOID)(&testHandle));
  2252. IsmCreateObjectStringsFromHandle (testHandle, &rootNode, NULL);
  2253. // Do not free testHandle here because it is a pointer into the hash table data
  2254. if (ptr) {
  2255. // if ptr is valid it means we found a match for a subkey
  2256. *ptr = TEXT('\\');
  2257. newNode = JoinText(rootNode, ptr);
  2258. } else {
  2259. // if ptr is NULL, we found a match for the full keyname
  2260. newNode = DuplicateText(rootNode);
  2261. }
  2262. IsmDestroyObjectString(rootNode);
  2263. fFoundMatch = TRUE;
  2264. } else {
  2265. ptr2 = ptr;
  2266. ptr = (PTSTR)FindLastWack (workingStr);
  2267. if (ptr2) {
  2268. *ptr2 = TEXT('\\');
  2269. }
  2270. if (ptr) {
  2271. *ptr = 0;
  2272. }
  2273. }
  2274. IsmDestroyObjectHandle(nodeHandle);
  2275. } while (FALSE == fFoundMatch && ptr);
  2276. FreeText(workingStr);
  2277. }
  2278. zeroBase = (SourceOperationData &&
  2279. SourceOperationData->Type == BLOBTYPE_BINARY &&
  2280. SourceOperationData->BinarySize == sizeof(PCBYTE) &&
  2281. (BOOL)SourceOperationData->BinaryData == TRUE);
  2282. if (FALSE == fFoundMatch) {
  2283. // Nope, let's process the node
  2284. destNode = pProcessRenameExMacro (doNode, NULL, zeroBase);
  2285. newNode = DuplicateText(destNode);
  2286. IsmDestroyObjectHandle(destNode);
  2287. }
  2288. // Now process the leaf, if the original object had a leaf
  2289. if (srcLeaf) {
  2290. if (doLeaf) {
  2291. destLeaf = pProcessRenameExMacro (newNode, doLeaf, zeroBase);
  2292. IsmDestroyObjectString (doLeaf);
  2293. }
  2294. }
  2295. IsmDestroyObjectString (doNode);
  2296. // Add this in the collision table
  2297. testHandle = IsmCreateObjectHandle (newNode, destLeaf ? destLeaf : srcLeaf);
  2298. storeHandle = DuplicateText (testHandle);
  2299. hashItem = HtAddStringEx (g_RegCollisionDestTable, storeHandle, &storeHandle, FALSE);
  2300. HtAddStringEx (g_RegCollisionSrcTable, InputData->OriginalObject.ObjectName, &hashItem, FALSE);
  2301. // Update the output
  2302. OutputData->NewObject.ObjectName = testHandle;
  2303. }
  2304. if (srcNode != NULL) {
  2305. IsmDestroyObjectString (srcNode);
  2306. }
  2307. if (srcLeaf != NULL) {
  2308. IsmDestroyObjectString (srcLeaf);
  2309. }
  2310. if (destLeaf != NULL) {
  2311. IsmDestroyObjectString (destLeaf);
  2312. }
  2313. if (newNode != NULL) {
  2314. FreeText(newNode);
  2315. }
  2316. return TRUE;
  2317. }
  2318. BOOL
  2319. WINAPI
  2320. FilterRenameIniExFilter (
  2321. IN PCMIG_FILTERINPUT InputData,
  2322. OUT PMIG_FILTEROUTPUT OutputData,
  2323. IN BOOL NoRestoreObject,
  2324. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  2325. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  2326. )
  2327. {
  2328. // we should never get here since there is no INF rule
  2329. // that would trigger this filter
  2330. MYASSERT(FALSE);
  2331. // As we said, we should never get here. If we do however, we
  2332. // will just continue
  2333. return TRUE;
  2334. }
  2335. BOOL
  2336. WINAPI
  2337. FilterPartitionMove (
  2338. IN PCMIG_FILTERINPUT InputData,
  2339. OUT PMIG_FILTEROUTPUT OutputData,
  2340. IN BOOL NoRestoreObject,
  2341. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  2342. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  2343. )
  2344. {
  2345. PCTSTR node = NULL;
  2346. PCTSTR leaf = NULL;
  2347. IsmCreateObjectStringsFromHandle (DestinationOperationData->String, &node, &leaf);
  2348. OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, leaf);
  2349. IsmDestroyObjectString (node);
  2350. IsmDestroyObjectString (leaf);
  2351. return TRUE;
  2352. }
  2353. BOOL
  2354. WINAPI
  2355. DoDestAddObject (
  2356. IN MIG_OBJECTTYPEID SrcObjectTypeId,
  2357. IN MIG_OBJECTSTRINGHANDLE SrcObjectName,
  2358. IN PCMIG_CONTENT OriginalContent,
  2359. IN PCMIG_CONTENT CurrentContent,
  2360. OUT PMIG_CONTENT NewContent,
  2361. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  2362. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  2363. )
  2364. {
  2365. PMIG_CONTENT finalContent;
  2366. if (DestinationOperationData == NULL) {
  2367. return TRUE;
  2368. }
  2369. if (DestinationOperationData->Type != BLOBTYPE_BINARY) {
  2370. return TRUE;
  2371. }
  2372. if (DestinationOperationData->BinarySize != sizeof (MIG_CONTENT)) {
  2373. return TRUE;
  2374. }
  2375. finalContent = (PMIG_CONTENT) DestinationOperationData->BinaryData;
  2376. CopyMemory (NewContent, finalContent, sizeof (MIG_CONTENT));
  2377. return TRUE;
  2378. }
  2379. VOID
  2380. OEWarning (
  2381. VOID
  2382. )
  2383. {
  2384. ERRUSER_EXTRADATA extraData;
  2385. if (TRUE == g_OERulesMigrated) {
  2386. // Send warning to app
  2387. extraData.Error = ERRUSER_WARNING_OERULES;
  2388. extraData.ErrorArea = ERRUSER_AREA_RESTORE;
  2389. extraData.ObjectTypeId = 0;
  2390. extraData.ObjectName = NULL;
  2391. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  2392. // Add to log
  2393. LOG ((LOG_WARNING, (PCSTR) MSG_OE_RULES));
  2394. }
  2395. }
  2396. VOID
  2397. OutlookWarning (
  2398. VOID
  2399. )
  2400. {
  2401. PCTSTR expandedPath;
  2402. MIG_OBJECT_ENUM objectEnum;
  2403. PCTSTR enumPattern;
  2404. ERRUSER_EXTRADATA extraData;
  2405. expandedPath = IsmExpandEnvironmentString (PLATFORM_SOURCE,
  2406. S_SYSENVVAR_GROUP,
  2407. TEXT("%CSIDL_APPDATA%\\Microsoft\\Outlook"),
  2408. NULL);
  2409. if (expandedPath) {
  2410. enumPattern = IsmCreateSimpleObjectPattern (expandedPath, FALSE, TEXT("*.rwz"), TRUE);
  2411. if (enumPattern) {
  2412. if (IsmEnumFirstSourceObject (&objectEnum, g_FileType, enumPattern)) {
  2413. // Send warning to app
  2414. extraData.Error = ERRUSER_WARNING_OUTLOOKRULES;
  2415. extraData.ErrorArea = ERRUSER_AREA_RESTORE;
  2416. extraData.ObjectTypeId = 0;
  2417. extraData.ObjectName = NULL;
  2418. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  2419. // Add to log
  2420. LOG ((LOG_WARNING, (PCSTR) MSG_OUTLOOK_RULES));
  2421. IsmAbortObjectEnum (&objectEnum);
  2422. }
  2423. IsmDestroyObjectHandle (enumPattern);
  2424. }
  2425. IsmReleaseMemory (expandedPath);
  2426. }
  2427. }
  2428. VOID
  2429. WINAPI
  2430. ScriptOpmTerminate (
  2431. VOID
  2432. )
  2433. {
  2434. //
  2435. // Temporary place to trigger setting refresh/upgrade
  2436. //
  2437. if (!IsmCheckCancel()) {
  2438. OEFixLastUser();
  2439. WABMerge();
  2440. OE4MergeStoreFolder();
  2441. OE5MergeStoreFolders();
  2442. OEWarning();
  2443. OutlookWarning();
  2444. }
  2445. TerminateRestoreCallback ();
  2446. TerminateSpecialRename();
  2447. TerminateSpecialConversion();
  2448. // LEAK: need to loop through table and FreeText the extra data
  2449. HtFree (g_RegCollisionDestTable);
  2450. g_RegCollisionDestTable = NULL;
  2451. HtFree (g_RegCollisionSrcTable);
  2452. g_RegCollisionSrcTable = NULL;
  2453. DestroyStringMapping (g_RegNodeFilterMap);
  2454. g_RegNodeFilterMap = NULL;
  2455. DestroyStringMapping (g_RegLeafFilterMap);
  2456. g_RegLeafFilterMap = NULL;
  2457. DestroyStringMapping (g_FileNodeFilterMap);
  2458. g_FileNodeFilterMap = NULL;
  2459. DestroyStringMapping (g_FileLeafFilterMap);
  2460. g_FileLeafFilterMap = NULL;
  2461. DestroyStringMapping (g_IniSectFilterMap);
  2462. g_IniSectFilterMap = NULL;
  2463. DestroyStringMapping (g_IniKeyFilterMap);
  2464. g_IniKeyFilterMap = NULL;
  2465. DestroyStringMapping (g_DestEnvMap);
  2466. g_DestEnvMap = NULL;
  2467. }