Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

444 lines
11 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. copythrd.c
  5. Abstract:
  6. CopyThread routine copies files needed to support migration modules. This
  7. thread runs in the background while the user is reading the backup instructions,
  8. or while WINNT32 is doing some work. Any file copied is added to the
  9. CancelFileDelete category of memdb, so it will be cleaned up and the user's
  10. machine will look exactly like it did before WINNT32 ran.
  11. Author:
  12. Jim Schmidt (jimschm) 17-Mar-1997
  13. Revision History:
  14. jimschm 09-Apr-1998 Added DidCopyThreadFail
  15. jimschm 03-Dec-1997 Added g_CopyThreadHasStarted
  16. --*/
  17. #include "pch.h"
  18. #include "uip.h"
  19. //
  20. // Local prototypes
  21. //
  22. VOID CopyRuntimeDlls (VOID);
  23. //
  24. // Local variables
  25. //
  26. static HANDLE g_CopyThreadHandle;
  27. static BOOL g_CopyThreadHasStarted = FALSE;
  28. BOOL g_CopyThreadError;
  29. //
  30. // Implementation
  31. //
  32. BOOL
  33. DidCopyThreadFail (
  34. VOID
  35. )
  36. {
  37. return g_CopyThreadError;
  38. }
  39. DWORD
  40. pCopyThread (
  41. PVOID p
  42. )
  43. /*++
  44. Routine Description:
  45. pCopyThread is the routine that is called when the copy worker thread
  46. is created. Its job is to call all processing functions that need
  47. to complete before the user supplies migration DLLs.
  48. Currently the only processing necessary is to copy the runtime DLLs
  49. that migration DLLs may need.
  50. Arguments:
  51. p - Unused
  52. Return Value:
  53. Zero (don't care)
  54. --*/
  55. {
  56. CopyRuntimeDlls();
  57. return 0;
  58. }
  59. VOID
  60. StartCopyThread (
  61. VOID
  62. )
  63. /*++
  64. Routine Description:
  65. StartCopyThread creates a worker thread that copies the runtime DLLs
  66. specified in win95upg.inf. If the worker thread was already started,
  67. this routine does nothing.
  68. Arguments:
  69. none
  70. Return Value:
  71. none
  72. --*/
  73. {
  74. DWORD DontCare;
  75. if (!g_CopyThreadHasStarted) {
  76. //
  77. // Launch thread if it has not been launched previously
  78. //
  79. g_CopyThreadHandle = CreateThread (NULL, 0, pCopyThread, NULL, 0, &DontCare);
  80. g_CopyThreadHasStarted = TRUE;
  81. }
  82. }
  83. VOID
  84. EndCopyThread (
  85. VOID
  86. )
  87. /*++
  88. Routine Description:
  89. EndCopyThread waits for the worker thread to finish its copying before
  90. returning.
  91. Arguments:
  92. none
  93. Return Value:
  94. none
  95. --*/
  96. {
  97. if (!g_CopyThreadHandle) {
  98. return;
  99. }
  100. TurnOnWaitCursor();
  101. WaitForSingleObject (g_CopyThreadHandle, INFINITE);
  102. CloseHandle (g_CopyThreadHandle);
  103. g_CopyThreadHandle = NULL;
  104. TurnOffWaitCursor();
  105. }
  106. VOID
  107. CopyRuntimeDlls (
  108. VOID
  109. )
  110. /*++
  111. Routine Description:
  112. CopyRuntimeDlls enumerates the runtime DLL names in win95upg.inf and
  113. copies them to the appropriate destination on the local disk.
  114. This routine runs in a background worker thread and may not display
  115. UI. The failure case we care about is lack of disk space, and if we
  116. can't copy the runtimes, it is safe to assume we won't get much
  117. further. (Also, WINNT32 may have already verified there is a lot
  118. of space available.)
  119. Any file that is copied is also added to the CancelFileDelete
  120. category so it is cleaned up on cancel of Setup.
  121. The routines called by this proc must all be thread-safe!!
  122. Arguments:
  123. none
  124. Return Value:
  125. none
  126. --*/
  127. {
  128. INFSTRUCT is = INITINFSTRUCT_POOLHANDLE;
  129. PTSTR DirName;
  130. PCTSTR Winnt32FileName;
  131. TCHAR DataBuf[MEMDB_MAX];
  132. PTSTR FileName = NULL;
  133. PTSTR SourceName = NULL;
  134. PTSTR DestName = NULL;
  135. PTSTR Number = NULL;
  136. PCTSTR DestFileName;
  137. LONG DirArraySize;
  138. LONG l;
  139. TCHAR Key[MEMDB_MAX];
  140. DWORD rc;
  141. INT sysLocale;
  142. PTSTR localeStr = NULL;
  143. TCHAR InstallSectionName[128];
  144. if (g_Win95UpgInf == INVALID_HANDLE_VALUE) {
  145. LOG ((LOG_ERROR, "Win95upg.inf not open!"));
  146. return;
  147. }
  148. //
  149. // Build path list from [Win95.Directories]
  150. //
  151. // Get number of lines in this section
  152. DirArraySize = SetupGetLineCount (g_Win95UpgInf, S_WIN95_DIRECTORIES);
  153. if (DirArraySize == -1) {
  154. LOG ((LOG_ERROR, "%s does not exist in win95upg.inf", S_WIN95_DIRECTORIES));
  155. return;
  156. }
  157. // For each line, add number to temp memdb category (used for sorting)
  158. for (l = 0 ; l < DirArraySize ; l++) {
  159. if (!InfGetLineByIndex (g_Win95UpgInf, S_WIN95_DIRECTORIES, l, &is)) {
  160. LOG ((LOG_ERROR,"Failed to retrive line from win95upg.inf. (line %i)",l+1));
  161. } else {
  162. Number = InfGetStringField(&is,0);
  163. FileName = InfGetStringField(&is,1);
  164. if (Number && FileName) {
  165. //
  166. // Line is valid, expand dir name and add it to memdb
  167. //
  168. DirName = JoinPaths (g_WinDir, FileName);
  169. if (CharCount (DirName) > MEMDB_MAX / 2) {
  170. DEBUGMSG ((DBG_WHOOPS, "DirName is really long: %s", DirName));
  171. }
  172. else {
  173. wsprintf (
  174. Key,
  175. TEXT("%s\\%08u\\%s"),
  176. S_MEMDB_TEMP_RUNTIME_DLLS,
  177. _ttoi (Number),
  178. DirName
  179. );
  180. DEBUGMSG ((DBG_NAUSEA, "Adding %s to memdb", Key));
  181. MemDbSetValue (Key, 0);
  182. }
  183. FreePathString (DirName);
  184. }
  185. }
  186. }
  187. //
  188. // Enumerate [Win95.Install] section or [Win95.Install.ReportOnly] if in
  189. // report-only mode.
  190. //
  191. StringCopy (InstallSectionName, S_WIN95_INSTALL);
  192. if (REPORTONLY()) {
  193. StringCat (InstallSectionName, TEXT(".ReportOnly"));
  194. }
  195. if (InfFindFirstLine (g_Win95UpgInf, InstallSectionName, NULL, &is)) {
  196. do {
  197. FileName = InfGetStringField(&is,0);
  198. Number = InfGetStringField(&is,1);
  199. if (FileName && Number) {
  200. //
  201. // Look up Number in memdb and copy src to dest
  202. //
  203. wsprintf (Key, TEXT("%08u"), _ttoi (Number));
  204. if (MemDbGetEndpointValueEx (
  205. S_MEMDB_TEMP_RUNTIME_DLLS,
  206. Key,
  207. NULL,
  208. DataBuf
  209. )) {
  210. SourceName = JoinPaths (SOURCEDIRECTORY(0), FileName);
  211. if (_tcschr (FileName, TEXT('\\'))) {
  212. DestFileName = GetFileNameFromPath (FileName);
  213. } else {
  214. DestFileName = FileName;
  215. }
  216. DestName = JoinPaths (DataBuf, DestFileName);
  217. __try {
  218. //
  219. // Verify international field if it exists
  220. //
  221. localeStr = InfGetMultiSzField(&is,2);
  222. if (localeStr && *localeStr) {
  223. sysLocale = GetSystemDefaultLCID();
  224. while (*localeStr) {
  225. if (_ttoi(localeStr) == sysLocale) {
  226. break;
  227. }
  228. localeStr = GetEndOfString (localeStr) + 1;
  229. }
  230. if (!*localeStr) {
  231. DEBUGMSG ((
  232. DBG_NAUSEA,
  233. "CopyRuntimeDlls: Locale %s not supported",
  234. localeStr
  235. ));
  236. continue;
  237. }
  238. }
  239. // If user cancels, we just get out
  240. if (*g_CancelFlagPtr) {
  241. return;
  242. }
  243. if (0xffffffff == GetFileAttributes (DestName)) {
  244. rc = SetupDecompressOrCopyFile (SourceName, DestName, 0);
  245. if (rc == 2) {
  246. DEBUGMSG ((DBG_VERBOSE, "Can't copy %s to %s", SourceName, DestName));
  247. FreePathString (SourceName);
  248. Winnt32FileName = JoinPaths (TEXT("WINNT32"), FileName);
  249. MYASSERT (Winnt32FileName);
  250. SourceName = JoinPaths (SOURCEDIRECTORY(0), Winnt32FileName);
  251. MYASSERT (SourceName);
  252. FreePathString (Winnt32FileName);
  253. DEBUGMSG ((DBG_VERBOSE, "Trying to copy %s to %s", SourceName, DestName));
  254. rc = SetupDecompressOrCopyFile (SourceName, DestName, 0);
  255. }
  256. if (rc != ERROR_SUCCESS && rc != ERROR_SHARING_VIOLATION) {
  257. SetLastError (rc);
  258. if (rc != ERROR_FILE_EXISTS) {
  259. LOG ((
  260. LOG_ERROR,
  261. "Error while copying runtime dlls. Can't copy %s to %s",
  262. SourceName,
  263. DestName
  264. ));
  265. }
  266. g_CopyThreadError = TRUE;
  267. LOG ((LOG_ERROR, (PCSTR)MSG_FILE_COPY_ERROR_LOG, SourceName, DestName));
  268. }
  269. else {
  270. DEBUGMSG ((
  271. DBG_NAUSEA,
  272. "%s copied to %s",
  273. SourceName,
  274. DestName
  275. ));
  276. MemDbSetValueEx (
  277. MEMDB_CATEGORY_CANCELFILEDEL,
  278. NULL,
  279. NULL,
  280. DestName,
  281. 0,
  282. NULL
  283. );
  284. }
  285. }
  286. ELSE_DEBUGMSG ((
  287. DBG_VERBOSE,
  288. "GetFileAttributes failed for %s. Gle: %u (%xh)",
  289. DestName,
  290. GetLastError(),
  291. GetLastError()
  292. ));
  293. }
  294. __finally {
  295. FreePathString (SourceName);
  296. FreePathString (DestName);
  297. }
  298. }
  299. ELSE_DEBUGMSG ((
  300. DBG_ERROR,
  301. "CopyRuntimeDlls: Directory %s not indexed in memdb",
  302. Number
  303. ));
  304. }
  305. } while (InfFindNextLine (&is));
  306. }
  307. InfCleanUpInfStruct(&is);
  308. //
  309. // Blow away temp memdb category
  310. //
  311. MemDbDeleteTree (S_MEMDB_TEMP_RUNTIME_DLLS);
  312. }