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.

529 lines
12 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. fileq.c
  5. Abstract:
  6. This file implements the file copy code.
  7. Environment:
  8. WIN32 User Mode
  9. Author:
  10. Wesley Witt (wesw) 17-Feb-1996
  11. --*/
  12. #include "wizard.h"
  13. #pragma hdrstop
  14. BOOL RebootRequired;
  15. DWORD
  16. SetupQueueXXXSection(
  17. HSPFILEQ QueueHandle,
  18. LPTSTR SourceRootPath,
  19. HINF InfHandle,
  20. HINF ListInfHandle,
  21. LPTSTR Section,
  22. DWORD CopyStyle,
  23. DWORD Action
  24. )
  25. {
  26. if (Action == SETUP_ACTION_NONE) {
  27. return 0;
  28. }
  29. if (Action == SETUP_ACTION_COPY) {
  30. return SetupQueueCopySection(
  31. QueueHandle,
  32. SourceRootPath,
  33. InfHandle,
  34. ListInfHandle,
  35. Section,
  36. CopyStyle
  37. );
  38. }
  39. if (Action == SETUP_ACTION_DELETE) {
  40. return SetupQueueDeleteSection(
  41. QueueHandle,
  42. InfHandle,
  43. ListInfHandle,
  44. Section
  45. );
  46. }
  47. return 0;
  48. }
  49. BOOL
  50. SetDestinationDir(
  51. HINF SetupInf,
  52. PFILE_QUEUE_INFO FileQueueInfo,
  53. PPLATFORM_INFO PlatformInfo
  54. )
  55. {
  56. TCHAR Buffer[MAX_PATH*2];
  57. TCHAR DestDir[MAX_PATH*2];
  58. BOOL Rval;
  59. if (FileQueueInfo->InfDirId < DIRID_USER) {
  60. return TRUE;
  61. }
  62. DestDir[0] = 0;
  63. switch (FileQueueInfo->DestDirId) {
  64. case DIRID_SPOOLDRIVERS:
  65. _tcscat( DestDir, PlatformInfo->DriverDir );
  66. if (FileQueueInfo->DestDir) {
  67. RemoveLastNode( DestDir );
  68. }
  69. break;
  70. case DIRID_SYSTEM:
  71. ExpandEnvironmentStrings( TEXT("%systemroot%\\"), Buffer, sizeof(Buffer) );
  72. _tcscat( DestDir, Buffer );
  73. break;
  74. case DIRID_WINDOWS:
  75. ExpandEnvironmentStrings( TEXT("%windir%\\"), Buffer, sizeof(Buffer) );
  76. _tcscat( DestDir, Buffer );
  77. break;
  78. }
  79. if (FileQueueInfo->DestDir) {
  80. ExpandEnvironmentStrings( FileQueueInfo->DestDir, Buffer, sizeof(Buffer) );
  81. _tcscat( DestDir, Buffer );
  82. }
  83. if (FileQueueInfo->PlatformsFlag == PLATFORM_USE_MACHINE) {
  84. _tcscat( DestDir, TEXT("\\") );
  85. _tcscat( DestDir, PlatformInfo->OsPlatform );
  86. }
  87. DebugPrint(( TEXT("Setting destination dir: [%d] [%s]"), FileQueueInfo->InfDirId, DestDir ));
  88. MakeDirectory( DestDir );
  89. Rval = SetupSetDirectoryId(
  90. SetupInf,
  91. FileQueueInfo->InfDirId,
  92. DestDir
  93. );
  94. if (!Rval) {
  95. DebugPrint(( TEXT("SetupSetDirectoryId() failed, ec=%d"), GetLastError() ));
  96. return FALSE;
  97. }
  98. return TRUE;
  99. }
  100. BOOL
  101. ProcessFileQueueEntry(
  102. HINF SetupInf,
  103. HSPFILEQ FileQueue,
  104. LPTSTR SourceRoot,
  105. PFILE_QUEUE_INFO FileQueueInfo,
  106. PPLATFORM_INFO PlatformInfo,
  107. DWORD ActionId,
  108. BOOL OsPlatformDir
  109. )
  110. {
  111. TCHAR SourceDir[MAX_PATH*2];
  112. BOOL Rval;
  113. //
  114. // set the source directory
  115. //
  116. // work around Setupapi!SetupSetPlatformPathOverride bug
  117. if (PlatformInfo->ThisPlatform) {
  118. _tcscpy( SourceDir, SourceRoot );
  119. }
  120. else {
  121. if (! PlatformOverride(
  122. ThisPlatformName,
  123. PlatformInfo->OsPlatform,
  124. SourceRoot,
  125. SourceDir
  126. ) ) {
  127. DebugPrint(( TEXT("PlatformOverride() failed") ));
  128. return FALSE;
  129. }
  130. }
  131. #if 0
  132. _tcscpy( SourceDir, SourceRoot );
  133. if (!PlatformInfo->ThisPlatform) {
  134. SetupSetPlatformPathOverride( PlatformInfo->OsPlatform );
  135. }
  136. #endif
  137. //
  138. // set the destination directory
  139. //
  140. SetDestinationDir( SetupInf, FileQueueInfo, PlatformInfo );
  141. //
  142. // queue the operation
  143. //
  144. Rval = SetupQueueXXXSection(
  145. FileQueue,
  146. SourceDir,
  147. SetupInf,
  148. SetupInf,
  149. FileQueueInfo->SectionName,
  150. FileQueueInfo->CopyFlags,
  151. ActionId
  152. );
  153. if (!Rval) {
  154. return FALSE;
  155. }
  156. return TRUE;
  157. }
  158. UINT
  159. FileQueueCallbackRoutine(
  160. IN LPDWORD FileCounter,
  161. IN UINT Notification,
  162. IN UINT Param1,
  163. IN UINT Param2
  164. )
  165. {
  166. *FileCounter += 1;
  167. return NO_ERROR;
  168. }
  169. BOOL
  170. ProcessFileQueue(
  171. HINF SetupInf,
  172. HSPFILEQ *FileQueue,
  173. PVOID QueueContext,
  174. LPTSTR SourceRoot,
  175. PFILE_QUEUE_INFO FileQueueInfo,
  176. DWORD CountFileQueueInfo,
  177. PSP_FILE_CALLBACK MyQueueCallback,
  178. DWORD ActionId
  179. )
  180. {
  181. DWORD i;
  182. DWORD j;
  183. LPTSTR p;
  184. TCHAR Drive[_MAX_DRIVE];
  185. TCHAR Dir[_MAX_DIR];
  186. BOOL OsPlatformDir = FALSE;
  187. BOOL Rval;
  188. PFILE_QUEUE_CONTEXT FileQueueContext = (PFILE_QUEUE_CONTEXT) QueueContext;
  189. INT SetupReboot;
  190. DWORD FileCounter;
  191. //
  192. // check to see if the directory is a platform directory
  193. // if this is false then this is most likely an internal setup
  194. //
  195. _tsplitpath( SourceRoot, Drive, Dir, NULL, NULL );
  196. if (Dir[0] && Dir[1]) {
  197. p = Dir + _tcslen(Dir) - 1;
  198. *p = 0;
  199. p -= 1;
  200. while (*p != TEXT('\\')) {
  201. p -= 1;
  202. }
  203. p += 1;
  204. for (i=0; i<MAX_PLATFORMS; i++) {
  205. if (_tcsicmp(p, Platforms[i].OsPlatform) == 0) {
  206. OsPlatformDir = TRUE;
  207. }
  208. }
  209. p = Dir + _tcslen(Dir);
  210. *p = TEXT('\\');
  211. }
  212. //
  213. // process each entry in the file queue array
  214. //
  215. for (i=0; i<CountFileQueueInfo; i++) {
  216. switch (FileQueueInfo[i].PlatformsFlag) {
  217. case PLATFORM_NONE:
  218. for (j=0; j<CountPlatforms; j++) {
  219. if (Platforms[j].ThisPlatform) {
  220. break;
  221. }
  222. }
  223. ProcessFileQueueEntry(
  224. SetupInf,
  225. FileQueue[j],
  226. SourceRoot,
  227. &FileQueueInfo[i],
  228. &Platforms[j],
  229. ActionId,
  230. OsPlatformDir
  231. );
  232. break;
  233. case PLATFORM_USE_MACHINE:
  234. case PLATFORM_USE_PRINTER:
  235. for (j=0; j<CountPlatforms; j++) {
  236. if (Platforms[j].Selected) {
  237. ProcessFileQueueEntry(
  238. SetupInf,
  239. FileQueue[j],
  240. SourceRoot,
  241. &FileQueueInfo[i],
  242. &Platforms[j],
  243. ActionId,
  244. OsPlatformDir
  245. );
  246. }
  247. }
  248. break;
  249. default:
  250. Assert( FALSE && TEXT("Corrupt file queue array") );
  251. continue;
  252. }
  253. }
  254. //
  255. // now we scan the file queues to count the
  256. // number of files that got queued. this is
  257. // necessary because we have 1 file queue per
  258. // platform and setupapi only send notification
  259. // messages to the callback function at the
  260. // beginning of the commit process for each queue.
  261. // this means that we cannot get a total count
  262. // of the files in advance of the first file being
  263. // copied. the result being a hosed progress meter.
  264. //
  265. FileCounter = 0;
  266. for (i=0; i<CountPlatforms; i++) {
  267. if (Platforms[i].Selected) {
  268. SetupScanFileQueue(
  269. FileQueue[i],
  270. SPQ_SCAN_USE_CALLBACK,
  271. NULL,
  272. (PSP_FILE_CALLBACK) FileQueueCallbackRoutine,
  273. (PVOID) &FileCounter,
  274. &j
  275. );
  276. }
  277. }
  278. if (!Unattended) {
  279. SendMessage( FileQueueContext->hwnd, WM_MY_PROGRESS, 0xfe, (LPARAM) FileCounter );
  280. }
  281. //
  282. // copy the files
  283. //
  284. for (i=0; i<CountPlatforms; i++) {
  285. if (Platforms[i].Selected) {
  286. Rval = SetupCommitFileQueue(
  287. FileQueueContext->hwnd,
  288. FileQueue[i],
  289. MyQueueCallback,
  290. (PVOID) FileQueueContext
  291. );
  292. if (!Rval) {
  293. DebugPrint(( TEXT("SetupCommitFileQueue() failed, ec=%d"), GetLastError() ));
  294. return FALSE;
  295. }
  296. }
  297. }
  298. //
  299. // set to see if we need to reboot
  300. //
  301. if (!RebootRequired) {
  302. for (i=0; i<CountPlatforms; i++) {
  303. if (Platforms[i].Selected) {
  304. SetupReboot = SetupPromptReboot( FileQueue[i], NULL, TRUE );
  305. if (SetupReboot != -1) {
  306. RebootRequired = SetupReboot & SPFILEQ_FILE_IN_USE;
  307. if (RebootRequired) {
  308. break;
  309. }
  310. }
  311. }
  312. }
  313. }
  314. return TRUE;
  315. }
  316. BOOL
  317. CloseFileQueue(
  318. HSPFILEQ *FileQueue,
  319. PVOID QueueContext
  320. )
  321. {
  322. DWORD i;
  323. PFILE_QUEUE_CONTEXT FileQueueContext = (PFILE_QUEUE_CONTEXT) QueueContext;
  324. SetupTermDefaultQueueCallback( FileQueueContext->QueueContext );
  325. for (i=0; i<CountPlatforms; i++) {
  326. if (Platforms[i].Selected) {
  327. SetupCloseFileQueue( FileQueue[i] );
  328. }
  329. }
  330. return TRUE;
  331. }
  332. BOOL
  333. InitializeFileQueue(
  334. HWND hwnd,
  335. HINF *SetupInf,
  336. HSPFILEQ **FileQueue,
  337. PVOID *QueueContext,
  338. LPTSTR SourceRoot
  339. )
  340. {
  341. SYSTEM_INFO SystemInfo;
  342. DWORD i;
  343. BOOL Rval;
  344. DWORD Bytes;
  345. TCHAR Buffer[MAX_PATH*2];
  346. TCHAR Drive[_MAX_DRIVE];
  347. TCHAR Dir[_MAX_DIR];
  348. PFILE_QUEUE_CONTEXT FileQueueContext;
  349. GetSystemInfo( &SystemInfo );
  350. //
  351. // be sure that the spooler is running
  352. //
  353. StartSpoolerService();
  354. for (i=0; i<CountPlatforms; i++) {
  355. Rval = GetPrinterDriverDirectory(
  356. NULL,
  357. Platforms[i].PrintPlatform,
  358. 1,
  359. (LPBYTE) Buffer,
  360. sizeof(Buffer),
  361. &Bytes
  362. );
  363. if (!Rval) {
  364. DebugPrint(( TEXT("GetPrinterDriverDirectory() failed, ec=%d"), GetLastError() ));
  365. return FALSE;
  366. }
  367. Platforms[i].DriverDir = StringDup( Buffer );
  368. }
  369. if ( (SystemInfo.wProcessorArchitecture > 3) || (EnumPlatforms[SystemInfo.wProcessorArchitecture] == WRONG_PLATFORM ) ) {
  370. return FALSE;
  371. }
  372. Platforms[ EnumPlatforms[SystemInfo.wProcessorArchitecture] ].ThisPlatform = TRUE;
  373. if (SourceRoot[0] == 0) {
  374. //
  375. // get the directory that the setup program is running from
  376. //
  377. GetModuleFileName( FaxWizModuleHandle, Buffer, sizeof(Buffer) );
  378. _tsplitpath( Buffer, Drive, Dir, NULL, NULL );
  379. _stprintf( SourceRoot, TEXT("%s%s"), Drive, Dir );
  380. }
  381. //
  382. // open the setup inf file
  383. //
  384. _stprintf( Buffer, TEXT("%sfaxsetup.inf"), SourceRoot );
  385. *SetupInf = SetupOpenInfFile(
  386. Buffer,
  387. NULL,
  388. INF_STYLE_WIN4,
  389. NULL
  390. );
  391. if (*SetupInf == INVALID_HANDLE_VALUE) {
  392. DebugPrint(( TEXT("SetupOpenInfFile() failed, ec=%d"), GetLastError() ));
  393. return FALSE;
  394. }
  395. //
  396. // open the file queues
  397. //
  398. *FileQueue = (HSPFILEQ*) MemAlloc( sizeof(HSPFILEQ) * CountPlatforms );
  399. if (!*FileQueue) {
  400. DebugPrint(( TEXT("Could not allocate memory for file queues") ));
  401. return FALSE;
  402. }
  403. for (i=0; i<CountPlatforms; i++) {
  404. if (Platforms[i].Selected) {
  405. (*FileQueue)[i] = SetupOpenFileQueue();
  406. if ((*FileQueue)[i] == INVALID_HANDLE_VALUE) {
  407. DebugPrint(( TEXT("SetupOpenFileQueue() failed, ec=%d"), GetLastError() ));
  408. return FALSE;
  409. }
  410. }
  411. }
  412. FileQueueContext = (PFILE_QUEUE_CONTEXT) MemAlloc( sizeof(FILE_QUEUE_CONTEXT) );
  413. if (!FileQueueContext) {
  414. return FALSE;
  415. }
  416. FileQueueContext->hwnd = hwnd;
  417. FileQueueContext->QueueContext = SetupInitDefaultQueueCallbackEx(
  418. hwnd,
  419. hwnd,
  420. WM_MY_PROGRESS,
  421. 0,
  422. NULL
  423. );
  424. if (!FileQueueContext->QueueContext) {
  425. DebugPrint(( TEXT("SetupInitDefaultQueueCallbackEx() failed, ec=%d"), GetLastError() ));
  426. return FALSE;
  427. }
  428. *QueueContext = FileQueueContext;
  429. return TRUE;
  430. }