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.

575 lines
15 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. restore.c
  5. Abstract:
  6. Implements object restore callbacks
  7. Author:
  8. Calin Negreanu (calinn) 21-Nov-2000
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include "v1p.h"
  17. #define DBG_RESTORE "RestoreCallbacks"
  18. //
  19. // Strings
  20. //
  21. // None
  22. //
  23. // Constants
  24. //
  25. // None
  26. //
  27. // Macros
  28. //
  29. // None
  30. //
  31. // Types
  32. //
  33. typedef BOOL(WINAPI SCRIPTRESTOREFUNCTION)(
  34. IN MIG_OBJECTTYPEID ObjectTypeId,
  35. IN MIG_OBJECTID ObjectId,
  36. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  37. IN PCTSTR MultiSzData
  38. );
  39. typedef SCRIPTRESTOREFUNCTION *PSCRIPTRESTOREFUNCTION;
  40. //
  41. // This is the structure used for handling restore callback functions
  42. //
  43. typedef struct {
  44. PCTSTR InfFunctionName;
  45. PSCRIPTRESTOREFUNCTION RestoreCallback;
  46. } RESTORE_STRUCT, *PRESTORE_STRUCT;
  47. typedef struct _RESTOREDATA_STRUCT{
  48. POBSPARSEDPATTERN ParsedPattern;
  49. PCTSTR RestoreArgs;
  50. PRESTORE_STRUCT RestoreStruct;
  51. struct _RESTOREDATA_STRUCT *Next;
  52. } RESTOREDATA_STRUCT, *PRESTOREDATA_STRUCT;
  53. //
  54. // Globals
  55. //
  56. PRESTOREDATA_STRUCT g_RestoreData = NULL;
  57. PMHANDLE g_RestorePool;
  58. //
  59. // Macro expansion list
  60. //
  61. #define RESTORE_FUNCTIONS \
  62. DEFMAC(NEVER, pNever ) \
  63. DEFMAC(SAMEREGVALUE, pSameRegValue ) \
  64. DEFMAC(EXISTSINHKLM, pExistsInHKLM ) \
  65. //
  66. // Private function prototypes
  67. //
  68. MIG_RESTORECALLBACK pRestoreCallback;
  69. //
  70. // Macro expansion definition
  71. //
  72. //
  73. // Declare special conversion operation apply callback functions
  74. //
  75. #define DEFMAC(ifn,fn) SCRIPTRESTOREFUNCTION fn;
  76. RESTORE_FUNCTIONS
  77. #undef DEFMAC
  78. //
  79. // Declare a global array of conversion functions
  80. //
  81. #define DEFMAC(ifn,fn) {TEXT("\\")TEXT(#ifn),fn},
  82. static RESTORE_STRUCT g_RestoreFunctions[] = {
  83. RESTORE_FUNCTIONS
  84. {NULL, NULL}
  85. };
  86. #undef DEFMAC
  87. //
  88. // Code
  89. //
  90. PRESTORE_STRUCT
  91. pGetRestoreStruct (
  92. IN PCTSTR FunctionName
  93. )
  94. {
  95. PRESTORE_STRUCT p = g_RestoreFunctions;
  96. INT i = 0;
  97. while (p->InfFunctionName != NULL) {
  98. if (StringIMatch (p->InfFunctionName, FunctionName)) {
  99. return p;
  100. }
  101. p++;
  102. i++;
  103. }
  104. return NULL;
  105. }
  106. BOOL
  107. pParseRestoreInf (
  108. IN HINF InfHandle
  109. )
  110. {
  111. INFSTRUCT is = INITINFSTRUCT_PMHANDLE;
  112. PCTSTR pattern;
  113. PCTSTR fnName;
  114. PCTSTR fnArgs;
  115. ENCODEDSTRHANDLE srcHandle = NULL;
  116. BOOL result = FALSE;
  117. GROWBUFFER multiSz = INIT_GROWBUFFER;
  118. MULTISZ_ENUM e;
  119. UINT sizeNeeded;
  120. PRESTOREDATA_STRUCT restoreData;
  121. __try {
  122. if (!IsmGetEnvironmentMultiSz (
  123. PLATFORM_SOURCE,
  124. NULL,
  125. S_ENV_DEST_RESTORE,
  126. NULL,
  127. 0,
  128. &sizeNeeded
  129. )) {
  130. result = TRUE;
  131. __leave;
  132. }
  133. if (!GbGrow (&multiSz, sizeNeeded)) {
  134. __leave;
  135. }
  136. if (!IsmGetEnvironmentMultiSz (
  137. PLATFORM_SOURCE,
  138. NULL,
  139. S_ENV_DEST_RESTORE,
  140. (PTSTR) multiSz.Buf,
  141. multiSz.End,
  142. NULL
  143. )) {
  144. __leave;
  145. }
  146. if (EnumFirstMultiSz (&e, (PCTSTR) multiSz.Buf)) {
  147. do {
  148. if (InfFindFirstLine (InfHandle, e.CurrentString, NULL, &is)) {
  149. do {
  150. if (IsmCheckCancel()) {
  151. __leave;
  152. }
  153. pattern = InfGetStringField (&is, 0);
  154. if (!pattern) {
  155. LOG ((LOG_WARNING, (PCSTR) MSG_EMPTY_REG_SPEC));
  156. continue;
  157. }
  158. srcHandle = TurnRegStringIntoHandle (pattern, TRUE, NULL);
  159. if (!srcHandle) {
  160. LOG ((LOG_ERROR, (PCSTR) MSG_REG_SPEC_BAD, pattern));
  161. continue;
  162. }
  163. fnName = InfGetStringField (&is, 1);
  164. if (!fnName) {
  165. LOG ((LOG_ERROR, (PCSTR) MSG_REG_SPEC_BAD, pattern));
  166. IsmDestroyObjectHandle (srcHandle);
  167. srcHandle = NULL;
  168. continue;
  169. }
  170. fnArgs = InfGetMultiSzField (&is, 2);
  171. restoreData = PmGetMemory (g_RestorePool, sizeof (RESTOREDATA_STRUCT));
  172. ZeroMemory (restoreData, sizeof (RESTOREDATA_STRUCT));
  173. restoreData->ParsedPattern = ObsCreateParsedPatternEx (g_RestorePool, srcHandle, FALSE);
  174. if (fnArgs) {
  175. restoreData->RestoreArgs = PmDuplicateMultiSz (g_RestorePool, fnArgs);
  176. }
  177. if (fnName) {
  178. restoreData->RestoreStruct = pGetRestoreStruct (fnName);
  179. }
  180. restoreData->Next = g_RestoreData;
  181. g_RestoreData = restoreData;
  182. IsmDestroyObjectHandle (srcHandle);
  183. srcHandle = NULL;
  184. } while (InfFindNextLine (&is));
  185. }
  186. } while (EnumNextMultiSz (&e));
  187. }
  188. result = TRUE;
  189. }
  190. __finally {
  191. GbFree (&multiSz);
  192. InfCleanUpInfStruct (&is);
  193. }
  194. return result;
  195. }
  196. BOOL
  197. InitRestoreCallback (
  198. IN MIG_PLATFORMTYPEID Platform
  199. )
  200. {
  201. PTSTR multiSz = NULL;
  202. MULTISZ_ENUM e;
  203. UINT sizeNeeded;
  204. HINF infHandle = INVALID_HANDLE_VALUE;
  205. ENVENTRY_TYPE dataType;
  206. BOOL result = FALSE;
  207. g_RestorePool = PmCreateNamedPoolEx ("Restore Callback Data", 32768);
  208. PmDisableTracking (g_RestorePool);
  209. if (IsmGetEnvironmentValue (
  210. IsmGetRealPlatform (),
  211. NULL,
  212. S_GLOBAL_INF_HANDLE,
  213. (PBYTE)(&infHandle),
  214. sizeof (HINF),
  215. &sizeNeeded,
  216. &dataType
  217. ) &&
  218. (sizeNeeded == sizeof (HINF)) &&
  219. (dataType == ENVENTRY_BINARY)
  220. ) {
  221. if (pParseRestoreInf (infHandle)) {
  222. result = TRUE;
  223. }
  224. InfNameHandle (infHandle, NULL, FALSE);
  225. } else {
  226. if (!IsmGetEnvironmentValue (IsmGetRealPlatform (), NULL, S_INF_FILE_MULTISZ, NULL, 0, &sizeNeeded, NULL)) {
  227. return TRUE; // no INF files specified
  228. }
  229. __try {
  230. multiSz = AllocText (sizeNeeded);
  231. if (!multiSz) {
  232. __leave;
  233. }
  234. if (!IsmGetEnvironmentValue (IsmGetRealPlatform (), NULL, S_INF_FILE_MULTISZ, (PBYTE) multiSz, sizeNeeded, NULL, NULL)) {
  235. __leave;
  236. }
  237. if (EnumFirstMultiSz (&e, multiSz)) {
  238. do {
  239. infHandle = InfOpenInfFile (e.CurrentString);
  240. if (infHandle != INVALID_HANDLE_VALUE) {
  241. if (!pParseRestoreInf (infHandle)) {
  242. InfCloseInfFile (infHandle);
  243. infHandle = INVALID_HANDLE_VALUE;
  244. __leave;
  245. }
  246. } else {
  247. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_INF, e.CurrentString));
  248. }
  249. InfCloseInfFile (infHandle);
  250. infHandle = INVALID_HANDLE_VALUE;
  251. } while (EnumNextMultiSz (&e));
  252. }
  253. result = TRUE;
  254. }
  255. __finally {
  256. if (multiSz) {
  257. FreeText (multiSz);
  258. multiSz = NULL;
  259. }
  260. }
  261. }
  262. IsmRegisterRestoreCallback (pRestoreCallback);
  263. return result;
  264. }
  265. VOID
  266. TerminateRestoreCallback (
  267. VOID
  268. )
  269. {
  270. if (g_RestorePool) {
  271. PmEmptyPool (g_RestorePool);
  272. PmDestroyPool (g_RestorePool);
  273. g_RestorePool = NULL;
  274. }
  275. }
  276. BOOL
  277. pRestoreCallback (
  278. IN MIG_OBJECTTYPEID ObjectTypeId,
  279. IN MIG_OBJECTID ObjectId,
  280. IN MIG_OBJECTSTRINGHANDLE ObjectName
  281. )
  282. {
  283. BOOL result = TRUE;
  284. PRESTOREDATA_STRUCT p = g_RestoreData;
  285. if (ObjectTypeId & MIG_REGISTRY_TYPE) {
  286. while (p) {
  287. if (p->ParsedPattern) {
  288. if (IsmParsedPatternMatch ((MIG_PARSEDPATTERN)p->ParsedPattern, MIG_REGISTRY_TYPE, ObjectName)) {
  289. if (p->RestoreStruct) {
  290. if (p->RestoreStruct->RestoreCallback) {
  291. if (!p->RestoreStruct->RestoreCallback (
  292. ObjectTypeId,
  293. ObjectId,
  294. ObjectName,
  295. p->RestoreArgs
  296. )) {
  297. result = FALSE;
  298. break;
  299. }
  300. }
  301. }
  302. }
  303. }
  304. p = p->Next;
  305. }
  306. }
  307. return result;
  308. }
  309. BOOL
  310. pIsSameContent (
  311. IN PMIG_CONTENT ContentSrc,
  312. IN PMIG_CONTENT ContentDest
  313. )
  314. {
  315. INT value1 = 0;
  316. INT value2 = 0;
  317. if (ContentSrc->ContentInFile) {
  318. return FALSE;
  319. }
  320. if (ContentDest->ContentInFile) {
  321. return FALSE;
  322. }
  323. if (ContentSrc->Details.DetailsSize != ContentDest->Details.DetailsSize) {
  324. return FALSE;
  325. }
  326. if (!TestBuffer (
  327. ContentSrc->Details.DetailsData,
  328. ContentDest->Details.DetailsData,
  329. ContentSrc->Details.DetailsSize
  330. )) {
  331. return FALSE;
  332. }
  333. if ((ContentSrc->MemoryContent.ContentSize == 0) &&
  334. (ContentDest->MemoryContent.ContentSize == 0)
  335. ) {
  336. // no content, just return TRUE
  337. return TRUE;
  338. }
  339. if ((ContentSrc->MemoryContent.ContentSize == ContentDest->MemoryContent.ContentSize) &&
  340. TestBuffer (
  341. ContentSrc->MemoryContent.ContentBytes,
  342. ContentDest->MemoryContent.ContentBytes,
  343. ContentSrc->MemoryContent.ContentSize
  344. )) {
  345. // same exact content
  346. return TRUE;
  347. }
  348. // we have an extra case, if the source and dest are strings but they are actually numbers
  349. // we will get the numbers and compare them
  350. if ((ContentSrc->Details.DetailsSize == sizeof (DWORD)) &&
  351. (ContentSrc->Details.DetailsData) &&
  352. (ContentDest->Details.DetailsData) &&
  353. ((*(PDWORD)ContentSrc->Details.DetailsData == REG_SZ) ||
  354. (*(PDWORD)ContentSrc->Details.DetailsData == REG_EXPAND_SZ)
  355. ) &&
  356. ((*(PDWORD)ContentDest->Details.DetailsData == REG_SZ) ||
  357. (*(PDWORD)ContentDest->Details.DetailsData == REG_EXPAND_SZ)
  358. ) &&
  359. (ContentSrc->MemoryContent.ContentBytes) &&
  360. (ContentDest->MemoryContent.ContentBytes)
  361. ) {
  362. value1 = _ttoi ((PCTSTR)ContentSrc->MemoryContent.ContentBytes);
  363. value2 = _ttoi ((PCTSTR)ContentDest->MemoryContent.ContentBytes);
  364. if ((value1 != 0) &&
  365. (value2 != 0) &&
  366. (value1 == value2)
  367. ) {
  368. return TRUE;
  369. }
  370. }
  371. return FALSE;
  372. }
  373. BOOL
  374. pSameRegValue (
  375. IN MIG_OBJECTTYPEID ObjectTypeId,
  376. IN MIG_OBJECTID ObjectId,
  377. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  378. IN PCTSTR MultiSzData
  379. )
  380. {
  381. MIG_OBJECTSTRINGHANDLE objectName;
  382. BOOL hadLeaf = FALSE;
  383. BOOL existsSrc = FALSE;
  384. MIG_CONTENT contentSrc;
  385. BOOL existsDest = FALSE;
  386. MIG_CONTENT contentDest;
  387. BOOL result = TRUE;
  388. if (MultiSzData) {
  389. objectName = TurnRegStringIntoHandle (MultiSzData, FALSE, &hadLeaf);
  390. if (objectName) {
  391. existsSrc = IsmAcquireObjectEx (
  392. MIG_REGISTRY_TYPE | PLATFORM_SOURCE,
  393. objectName,
  394. &contentSrc,
  395. CONTENTTYPE_MEMORY,
  396. 0
  397. );
  398. existsDest = IsmAcquireObjectEx (
  399. MIG_REGISTRY_TYPE | PLATFORM_DESTINATION,
  400. objectName,
  401. &contentDest,
  402. CONTENTTYPE_MEMORY,
  403. 0
  404. );
  405. result = (existsSrc && existsDest) || (!existsSrc && !existsDest);
  406. if (hadLeaf && result && existsSrc && existsDest) {
  407. result = pIsSameContent (&contentSrc, &contentDest);
  408. }
  409. if (existsSrc) {
  410. IsmReleaseObject (&contentSrc);
  411. }
  412. if (existsDest) {
  413. IsmReleaseObject (&contentDest);
  414. }
  415. }
  416. }
  417. return result;
  418. }
  419. BOOL
  420. pNever (
  421. IN MIG_OBJECTTYPEID ObjectTypeId,
  422. IN MIG_OBJECTID ObjectId,
  423. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  424. IN PCTSTR MultiSzData
  425. )
  426. {
  427. return FALSE;
  428. }
  429. BOOL
  430. pExistsInHKLM (
  431. IN MIG_OBJECTTYPEID ObjectTypeId,
  432. IN MIG_OBJECTID ObjectId,
  433. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  434. IN PCTSTR MultiSzData
  435. )
  436. {
  437. MIG_OBJECTSTRINGHANDLE newObjectName;
  438. PCTSTR node, leaf, nodePtr, newNode;
  439. MIG_CONTENT content;
  440. BOOL result = TRUE;
  441. if (ObjectTypeId == (MIG_REGISTRY_TYPE | PLATFORM_SOURCE)) {
  442. if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) {
  443. if (node && StringIPrefix (node, TEXT("HKCU\\"))) {
  444. nodePtr = node + ARRAYSIZE (TEXT("HKCU"));
  445. newNode = JoinPathsInPoolEx ((
  446. NULL,
  447. TEXT("HKLM"),
  448. MultiSzData?MultiSzData:nodePtr,
  449. MultiSzData?nodePtr:NULL,
  450. NULL
  451. ));
  452. newObjectName = IsmCreateObjectHandle (newNode, leaf);
  453. if (newObjectName) {
  454. result = !IsmAcquireObjectEx (
  455. MIG_REGISTRY_TYPE | PLATFORM_DESTINATION,
  456. newObjectName,
  457. &content,
  458. CONTENTTYPE_MEMORY,
  459. 0
  460. );
  461. if (!result) {
  462. IsmReleaseObject (&content);
  463. }
  464. IsmDestroyObjectHandle (newObjectName);
  465. }
  466. FreePathString (newNode);
  467. }
  468. IsmDestroyObjectString (node);
  469. IsmDestroyObjectString (leaf);
  470. }
  471. }
  472. return result;
  473. }