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.

532 lines
13 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. progress.c
  5. Abstract:
  6. This file implements routines that estimate the size of the progress
  7. bar.
  8. Author:
  9. Jim Schmidt (jimschm) 02-Jul-1998
  10. Revision History:
  11. jimschm 23-Sep-1998 MigrateShellFolders & split of usermig.c
  12. --*/
  13. /*++
  14. Macro Expansion List Description:
  15. The macro expansion lists FIRST_SYSTEM_ROUTINES, USER_ROUTINES and
  16. LAST_SYSTEM_ROUTINES list all the functions called to perform the migration
  17. of user and system settings. The functions are executed in the order they
  18. appear. Each function is responsible for estimating a tick count and ticking
  19. the progress bar.
  20. Line Syntax:
  21. SYSFUNCTION(Function, Flag) (for FIRST_SYSTEM_ROUTINES and LAST_SYSTEM_ROUTINES)
  22. or
  23. USERFUNCTION(Function, Flag) (for USER_ROUTINES)
  24. Arguments:
  25. Function - These functions must return DWORD and are called with a request as a parameter,
  26. request that can be either REQUEST_QUERYTICKS (the function should estimate the
  27. number of ticks it needs) or REQUEST_RUN (the function should do it's job).
  28. For user functions there are also three more parameters (UserName, UserAccount,
  29. and a handle to HKCU)
  30. Flag - Specifies NOFAIL if the function terminates migration when it fails, or
  31. CANFAIL if migration can proceed even if the function fails
  32. Variables Generated From List:
  33. g_MigrationFnList
  34. For accessing the arrays there are the following functions:
  35. PrepareMigrationProgressBar
  36. PerformMigration
  37. --*/
  38. #include "pch.h"
  39. #include "migmainp.h"
  40. #define NOFAIL FALSE
  41. #define CANFAIL TRUE
  42. #define FIRST_SYSTEM_ROUTINES \
  43. SYSFUNCTION(PrepareEnvironment, NOFAIL) \
  44. SYSFUNCTION(ResolveDomains, NOFAIL) \
  45. SYSFUNCTION(DeleteSysTapiSettings, NOFAIL) \
  46. SYSFUNCTION(ProcessLocalMachine_First, CANFAIL) \
  47. SYSFUNCTION(UninstallStartMenuCleanupPreparation, CANFAIL) \
  48. SYSFUNCTION(RemoveBootIniCancelOption, CANFAIL) \
  49. SYSFUNCTION(MigrateShellFolders, CANFAIL) \
  50. SYSFUNCTION(MigrateGhostSystemFiles, CANFAIL) \
  51. #define USER_ROUTINES \
  52. USERFUNCTION(RunPerUserUninstallUserProfileCleanupPreparation, CANFAIL) \
  53. USERFUNCTION(PrepareUserForMigration, NOFAIL) \
  54. USERFUNCTION(DeleteUserTapiSettings, NOFAIL) \
  55. USERFUNCTION(MigrateUserRegistry, CANFAIL) \
  56. USERFUNCTION(MigrateLogonPromptSettings, CANFAIL) \
  57. USERFUNCTION(MigrateUserSettings, CANFAIL) \
  58. USERFUNCTION(RunPerUserExternalProcesses, CANFAIL) \
  59. USERFUNCTION(SaveMigratedUserHive, CANFAIL) \
  60. #define LAST_SYSTEM_ROUTINES \
  61. SYSFUNCTION(DoCopyFile, CANFAIL) \
  62. SYSFUNCTION(ProcessLocalMachine_Last, CANFAIL) \
  63. SYSFUNCTION(ConvertHiveFiles, CANFAIL) \
  64. SYSFUNCTION(MigrateBriefcases, CANFAIL) \
  65. SYSFUNCTION(MigrateAtmFonts, CANFAIL) \
  66. SYSFUNCTION(AddOptionsDiskCleaner, CANFAIL) \
  67. SYSFUNCTION(DoFileEdit, CANFAIL) \
  68. SYSFUNCTION(RunSystemExternalProcesses, CANFAIL) \
  69. SYSFUNCTION(ProcessMigrationDLLs, CANFAIL) \
  70. SYSFUNCTION(DisableFiles, CANFAIL) \
  71. SYSFUNCTION(RunSystemUninstallUserProfileCleanupPreparation, CANFAIL) \
  72. SYSFUNCTION(WriteBackupInfo, CANFAIL) \
  73. //
  74. // Declare tables of processing structures
  75. //
  76. // Create a combined list
  77. #define MIGRATION_ROUTINES FIRST_SYSTEM_ROUTINES USER_ROUTINES LAST_SYSTEM_ROUTINES
  78. // Processing functions types
  79. typedef DWORD (MIGMAIN_SYS_PROTOTYPE) (DWORD Request);
  80. typedef MIGMAIN_SYS_PROTOTYPE * MIGMAIN_SYS_FN;
  81. typedef DWORD (MIGMAIN_USER_PROTOTYPE) (DWORD Request, PMIGRATE_USER_ENUM EnumPtr);
  82. typedef MIGMAIN_USER_PROTOTYPE * MIGMAIN_USER_FN;
  83. // Structure holding state for processing functions
  84. typedef struct {
  85. // One of the two will be NULL, the other will be a valid fn ptr:
  86. MIGMAIN_SYS_FN SysFnPtr;
  87. MIGMAIN_USER_FN UserFnPtr;
  88. BOOL CanFail;
  89. UINT Ticks;
  90. PCTSTR FnName;
  91. GROWBUFFER SliceIdArray;
  92. } PROCESSING_ROUTINE, *PPROCESSING_ROUTINE;
  93. #define PROCESSING_ROUTINE_TERMINATOR {NULL, NULL, FALSE, 0, NULL, GROWBUF_INIT}
  94. // Declaration of prototypes
  95. #define SYSFUNCTION(fn,flag) MIGMAIN_SYS_PROTOTYPE fn;
  96. #define USERFUNCTION(fn,flag) MIGMAIN_USER_PROTOTYPE fn;
  97. MIGRATION_ROUTINES
  98. #undef SYSFUNCTION
  99. #undef USERFUNCTION
  100. // Declaration of table
  101. #define SYSFUNCTION(fn,flag) {fn, NULL, flag, 0, L###fn, GROWBUF_INIT},
  102. #define USERFUNCTION(fn,flag) {NULL, fn, flag, 0, L###fn, GROWBUF_INIT},
  103. static PROCESSING_ROUTINE g_FirstSystemRoutines[] = {
  104. FIRST_SYSTEM_ROUTINES /* , */
  105. PROCESSING_ROUTINE_TERMINATOR
  106. };
  107. static PROCESSING_ROUTINE g_UserRoutines [] = {
  108. USER_ROUTINES /* , */
  109. PROCESSING_ROUTINE_TERMINATOR
  110. };
  111. static PROCESSING_ROUTINE g_LastSystemRoutines[] = {
  112. LAST_SYSTEM_ROUTINES /* , */
  113. PROCESSING_ROUTINE_TERMINATOR
  114. };
  115. #undef SYSFUNCTION
  116. #undef USERFUNCTION
  117. //
  118. // Prototypes
  119. //
  120. BOOL
  121. pProcessTable (
  122. IN DWORD Request,
  123. IN PPROCESSING_ROUTINE Table
  124. );
  125. //
  126. // Implementation
  127. //
  128. VOID
  129. pInitTable (
  130. PPROCESSING_ROUTINE p
  131. )
  132. {
  133. while (p->SysFnPtr || p->UserFnPtr) {
  134. p->SliceIdArray.GrowSize = sizeof (DWORD) * 8;
  135. p++;
  136. }
  137. }
  138. VOID
  139. InitProcessingTable (
  140. VOID
  141. )
  142. {
  143. pInitTable (g_FirstSystemRoutines);
  144. pInitTable (g_UserRoutines);
  145. pInitTable (g_LastSystemRoutines);
  146. }
  147. VOID
  148. pTerminateTable (
  149. PPROCESSING_ROUTINE p
  150. )
  151. {
  152. while (p->SysFnPtr || p->UserFnPtr) {
  153. FreeGrowBuffer (&p->SliceIdArray);
  154. p++;
  155. }
  156. }
  157. VOID
  158. TerminateProcessingTable (
  159. VOID
  160. )
  161. {
  162. pTerminateTable (g_FirstSystemRoutines);
  163. pTerminateTable (g_UserRoutines);
  164. pTerminateTable (g_LastSystemRoutines);
  165. }
  166. BOOL
  167. pCallAllRoutines (
  168. BOOL Run
  169. )
  170. {
  171. BOOL b;
  172. DWORD Request;
  173. Request = Run ? REQUEST_RUN : REQUEST_QUERYTICKS;
  174. b = pProcessTable (Request, g_FirstSystemRoutines);
  175. if (b && Run) {
  176. b = pProcessTable (REQUEST_BEGINUSERPROCESSING, g_UserRoutines);
  177. }
  178. if (b) {
  179. b = pProcessTable (Request, g_UserRoutines);
  180. }
  181. if (b && Run) {
  182. b = pProcessTable (REQUEST_ENDUSERPROCESSING, g_UserRoutines);
  183. }
  184. if (b) {
  185. b = pProcessTable (Request, g_LastSystemRoutines);
  186. }
  187. return b;
  188. }
  189. VOID
  190. PrepareMigrationProgressBar (
  191. VOID
  192. )
  193. {
  194. InitProcessingTable();
  195. pCallAllRoutines (FALSE);
  196. }
  197. BOOL
  198. CallAllMigrationFunctions (
  199. VOID
  200. )
  201. {
  202. return pCallAllRoutines (TRUE);
  203. }
  204. BOOL
  205. pProcessWorker (
  206. IN DWORD Request,
  207. IN PPROCESSING_ROUTINE fn,
  208. IN PMIGRATE_USER_ENUM EnumPtr OPTIONAL
  209. )
  210. {
  211. DWORD rc;
  212. PDWORD SliceId;
  213. DWORD Size;
  214. BOOL Result = TRUE;
  215. //
  216. // If running the function, start the progress bar slice
  217. //
  218. if (Request == REQUEST_RUN) {
  219. if (fn->Ticks == 0) {
  220. return TRUE;
  221. }
  222. Size = fn->SliceIdArray.End / sizeof (DWORD);
  223. if (fn->SliceIdArray.UserIndex >= Size) {
  224. DEBUGMSG ((DBG_WHOOPS, "pProcessWorker: QUERYTICKS vs. RUN mismatch"));
  225. return fn->CanFail;
  226. }
  227. SliceId = (PDWORD) fn->SliceIdArray.Buf + fn->SliceIdArray.UserIndex;
  228. fn->SliceIdArray.UserIndex += 1;
  229. BeginSliceProcessing (*SliceId);
  230. DEBUGLOGTIME (("Starting function: %ls", fn->FnName));
  231. }
  232. //
  233. // Now call the function
  234. //
  235. if (fn->SysFnPtr) {
  236. //
  237. // System processing
  238. //
  239. MYASSERT (!EnumPtr);
  240. rc = fn->SysFnPtr (Request);
  241. if (Request != REQUEST_QUERYTICKS && rc != ERROR_SUCCESS) {
  242. DEBUGMSG ((DBG_ERROR, "%s failed with rc=%u", fn->FnName, rc));
  243. Result = fn->CanFail;
  244. }
  245. } else {
  246. //
  247. // User processing
  248. //
  249. MYASSERT (fn->UserFnPtr);
  250. rc = fn->UserFnPtr (Request, EnumPtr);
  251. if (Request != REQUEST_QUERYTICKS && rc != ERROR_SUCCESS) {
  252. DEBUGMSG ((DBG_ERROR, "%s failed with rc=%u", fn->FnName, rc));
  253. Result = fn->CanFail;
  254. }
  255. }
  256. //
  257. // If running the function, end the progress bar slice
  258. //
  259. if (Request == REQUEST_RUN) {
  260. if (rc != ERROR_SUCCESS) {
  261. LOG ((LOG_ERROR, "Failure in %s, rc=%u", fn->FnName, rc));
  262. }
  263. EndSliceProcessing();
  264. DEBUGLOGTIME (("Function complete: %ls", fn->FnName));
  265. }
  266. if (Request != REQUEST_QUERYTICKS) {
  267. SetLastError (rc);
  268. }
  269. //
  270. // If querying the ticks, register them and add slice ID to grow buffer
  271. //
  272. else {
  273. fn->Ticks += rc;
  274. SliceId = (PDWORD) GrowBuffer (&fn->SliceIdArray, sizeof (DWORD));
  275. *SliceId = RegisterProgressBarSlice (rc);
  276. }
  277. return Result;
  278. }
  279. BOOL
  280. pProcessTable (
  281. IN DWORD Request,
  282. IN PPROCESSING_ROUTINE Table
  283. )
  284. /*++
  285. Routine Description:
  286. pProcessTable calls all routines in the specified table to perform
  287. the specified request.
  288. Arguments:
  289. Request - Specifies REQUEST_QUERYTICKS when a tick estimate is needed,
  290. or REQUEST_RUN when the function needs to perform its
  291. processing. For User routines, there are the additional two
  292. requests REQUEST_BEGINUSERPROCESSING and REQUEST_ENDUSERPROCESSING
  293. Functions can use these requests to init/free needed resources
  294. for user processing.
  295. Return Value:
  296. none
  297. --*/
  298. {
  299. MIGRATE_USER_ENUM e;
  300. PPROCESSING_ROUTINE OrgStart;
  301. DWORD Flags;
  302. g_DomainUserName = NULL;
  303. g_Win9xUserName = NULL;
  304. g_FixedUserName = NULL;
  305. MYASSERT (Table->SysFnPtr || Table->UserFnPtr);
  306. while (Table->SysFnPtr || Table->UserFnPtr) {
  307. if (Table->SysFnPtr ||
  308. Request == REQUEST_BEGINUSERPROCESSING ||
  309. Request == REQUEST_ENDUSERPROCESSING
  310. ) {
  311. //
  312. // Call system routine, or call per-user routine with begin or
  313. // end request
  314. //
  315. __try {
  316. if (!pProcessWorker (Request, Table, NULL)) {
  317. return FALSE;
  318. }
  319. } __except (1) {
  320. LOG ((LOG_WARNING, "Unhandled exception occurred during processing of function %s.", Table->FnName));
  321. SafeModeExceptionOccured ();
  322. if (!Table->CanFail) {
  323. return FALSE;
  324. }
  325. }
  326. //
  327. // Loop inc
  328. //
  329. Table++;
  330. } else {
  331. //
  332. // Enumerate each user, and run through all the per-user
  333. // routines in the group.
  334. //
  335. OrgStart = Table;
  336. if (Request == REQUEST_QUERYTICKS) {
  337. Flags = ENUM_NO_FLAGS;
  338. } else {
  339. Flags = ENUM_SET_WIN9X_HKR;
  340. }
  341. if (EnumFirstUserToMigrate (&e, Flags)) {
  342. do {
  343. if (!e.CreateOnly) {
  344. for (Table = OrgStart ; Table->UserFnPtr ; Table++) {
  345. __try {
  346. if (!pProcessWorker (Request, Table, &e)) {
  347. return FALSE;
  348. }
  349. } __except (1) {
  350. LOG ((LOG_WARNING, "Unhandled exception occurred during processing of function %s.", Table->FnName));
  351. SafeModeExceptionOccured ();
  352. if (!Table->CanFail) {
  353. return FALSE;
  354. }
  355. }
  356. }
  357. }
  358. } while (EnumNextUserToMigrate (&e));
  359. }
  360. ELSE_DEBUGMSG ((DBG_WARNING, "No active users to process!"));
  361. //
  362. // Loop inc
  363. //
  364. while (Table->UserFnPtr) {
  365. Table++;
  366. }
  367. }
  368. TickProgressBar ();
  369. }
  370. return TRUE;
  371. }