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.

4531 lines
138 KiB

  1. /************************************************************************
  2. Copyright (c) Microsoft Corporation 1997
  3. All rights reserved
  4. ***************************************************************************/
  5. #include "pch.h"
  6. #include <aclapip.h>
  7. #include <winldap.h>
  8. #include "check.h"
  9. #include "dialogs.h"
  10. #include "setup.h"
  11. #include "check.h"
  12. DEFINE_MODULE( "Setup" );
  13. #ifdef SMALL_BUFFER_SIZE
  14. #undef SMALL_BUFFER_SIZE
  15. #endif
  16. #define SMALL_BUFFER_SIZE 512
  17. #define MAX_FILES_SIZE 1920000
  18. #define BIG_BUFFER 4096
  19. #define MACHINENAME_SIZE 32
  20. static const WCHAR chSlash = TEXT('\\');
  21. typedef LONGLONG INDEX;
  22. SCPDATA scpdata[] = {
  23. { L"netbootAllowNewClients", L"TRUE" },
  24. { L"netbootLimitClients", L"FALSE" },
  25. { L"netbootCurrentClientCount", L"0" },
  26. { L"netbootMaxClients", L"100" },
  27. { L"netbootAnswerRequests", L"TRUE" },
  28. { L"netbootAnswerOnlyValidClients", L"FALSE" },
  29. { L"netbootNewMachineNamingPolicy", L"%61Username%#" },
  30. { L"netbootNewMachineOU", NULL },
  31. { L"netbootServer", NULL }
  32. };
  33. #define MACHINEOU_INDEX 7
  34. #define NETBOOTSERVER_INDEX 8
  35. #define BINL_PARAMETERS_KEY L"System\\CurrentControlSet\\Services\\Binlsvc\\Parameters"
  36. PCWSTR
  37. SetupExtensionFromProcessorTag(
  38. PCWSTR ProcessorTag
  39. )
  40. {
  41. if (wcscmp(ProcessorTag,L"i386")==0) {
  42. return(L"x86");
  43. } else {
  44. return(ProcessorTag);
  45. }
  46. }
  47. //
  48. // KeepUIAlive( )
  49. //
  50. BOOL
  51. KeepUIAlive(
  52. HWND hDlg )
  53. {
  54. MSG Msg;
  55. //
  56. // process messages to keep UI alive
  57. //
  58. while ( PeekMessage( &Msg, NULL, 0, 0, PM_REMOVE ) )
  59. {
  60. TranslateMessage( &Msg );
  61. DispatchMessage( &Msg );
  62. if ( hDlg != NULL && Msg.message == WM_KEYUP && Msg.wParam == VK_ESCAPE ) {
  63. VerifyCancel( hDlg );
  64. }
  65. }
  66. return( g_Options.fError || g_Options.fAbort );
  67. }
  68. //
  69. // CreateSCP( )
  70. //
  71. HRESULT
  72. CreateSCP(
  73. HWND hDlg
  74. )
  75. /*++
  76. Routine Description:
  77. Creates SCP information so that BINL can create the SCP when it starts up.
  78. Arguments:
  79. hDlg - dialog window handle for putting up error messages.
  80. Return Value:
  81. HRESULT indicating outcome.
  82. --*/
  83. {
  84. TraceFunc( "CreateSCP( )\n" );
  85. HRESULT hr;
  86. ULONG ulSize;
  87. LPWSTR pszMachinePath = NULL;
  88. DWORD i,Err;
  89. HKEY hKey = 0;
  90. DWORD DontCare;
  91. Err = RegCreateKeyEx(
  92. HKEY_LOCAL_MACHINE,
  93. BINL_PARAMETERS_KEY,
  94. 0,
  95. NULL,
  96. REG_OPTION_NON_VOLATILE,
  97. KEY_SET_VALUE,
  98. NULL,
  99. &hKey,
  100. &DontCare);
  101. if (Err != ERROR_SUCCESS) {
  102. hr = HRESULT_FROM_WIN32( Err );
  103. goto e0;
  104. }
  105. if ( !GetComputerObjectName( NameFullyQualifiedDN, NULL, &ulSize )) {
  106. hr = HRESULT_FROM_WIN32( GetLastError() );
  107. goto e1;
  108. }
  109. pszMachinePath = (LPWSTR) TraceAlloc( LPTR, ulSize * sizeof(WCHAR) );
  110. if ( !pszMachinePath ) {
  111. hr = THR( E_OUTOFMEMORY );
  112. goto e1;
  113. }
  114. if ( !GetComputerObjectName( NameFullyQualifiedDN, pszMachinePath, &ulSize )) {
  115. hr = HRESULT_FROM_WIN32( GetLastError() );
  116. goto e2;
  117. }
  118. scpdata[MACHINEOU_INDEX].pszValue = pszMachinePath;
  119. scpdata[NETBOOTSERVER_INDEX].pszValue = pszMachinePath;
  120. //
  121. // Add default attribute values
  122. //
  123. for( i = 0; i < ARRAYSIZE(scpdata); i++ )
  124. {
  125. Err = RegSetValueEx(
  126. hKey,
  127. scpdata[i].pszAttribute,
  128. NULL,
  129. REG_SZ,
  130. (LPBYTE)scpdata[i].pszValue,
  131. (wcslen(scpdata[i].pszValue)+1)*sizeof(WCHAR) );
  132. if (Err != ERROR_SUCCESS) {
  133. hr = HRESULT_FROM_WIN32( Err );
  134. goto e3;
  135. }
  136. }
  137. hr = S_OK;
  138. Err = 0;
  139. RegSetValueEx(
  140. hKey,
  141. L"ScpCreated",
  142. NULL,
  143. REG_DWORD,
  144. (LPBYTE)&Err,
  145. sizeof(DWORD) );
  146. e3:
  147. if (FAILED(hr)) {
  148. for( i = 0; i < ARRAYSIZE(scpdata); i++ ) {
  149. RegDeleteValue(
  150. hKey,
  151. scpdata[i].pszAttribute );
  152. }
  153. }
  154. e2:
  155. TraceFree( pszMachinePath );
  156. e1:
  157. RegCloseKey(hKey);
  158. e0:
  159. if ( FAILED(hr)) {
  160. MessageBoxFromStrings( hDlg, IDS_SCPCREATIONFAIL_CAPTION, IDS_SCPCREATIONFAIL_TEXT, MB_OK );
  161. ErrorMsg( "Error 0x%08x occurred.\n", hr );
  162. }
  163. HRETURN(hr);
  164. }
  165. PWSTR
  166. GenerateCompressedName(
  167. IN PCWSTR Filename
  168. )
  169. /*++
  170. Routine Description:
  171. Given a filename, generate the compressed form of the name.
  172. The compressed form is generated as follows:
  173. Look backwards for a dot. If there is no dot, append "._" to the name.
  174. If there is a dot followed by 0, 1, or 2 charcaters, append "_".
  175. Otherwise there is a 3-character or greater extension and we replace
  176. the last character with "_".
  177. Arguments:
  178. Filename - supplies filename whose compressed form is desired.
  179. Return Value:
  180. Pointer to buffer containing nul-terminated compressed-form filename.
  181. The caller must free this buffer via TraceFree().
  182. --*/
  183. {
  184. PWSTR CompressedName,p,q;
  185. UINT u;
  186. //
  187. // The maximum length of the compressed filename is the length of the
  188. // original name plus 2 (for ._).
  189. //
  190. if(CompressedName = (PWSTR)TraceAlloc(LPTR, (wcslen(Filename)+3)*sizeof(WCHAR))) {
  191. wcscpy(CompressedName,Filename);
  192. p = wcsrchr(CompressedName,L'.');
  193. q = wcsrchr(CompressedName,L'\\');
  194. if(q < p) {
  195. //
  196. // If there are 0, 1, or 2 characters after the dot, just append
  197. // the underscore. p points to the dot so include that in the length.
  198. //
  199. u = wcslen(p);
  200. if(u < 4) {
  201. wcscat(CompressedName,L"_");
  202. } else {
  203. //
  204. // There are at least 3 characters in the extension.
  205. // Replace the final one with an underscore.
  206. //
  207. p[u-1] = L'_';
  208. }
  209. } else {
  210. //
  211. // No dot, just add ._.
  212. //
  213. wcscat(CompressedName,L"._");
  214. }
  215. }
  216. return(CompressedName);
  217. }
  218. BOOL
  219. IsFileOrCompressedVersionPresent(
  220. LPCWSTR FilePath,
  221. PWSTR *pCompressedName OPTIONAL
  222. )
  223. /*++
  224. Routine Description:
  225. Check if a file or a compressed version of it is present at the
  226. specified location.
  227. Arguments:
  228. FilePath - fully qualified path to the file to check for.
  229. pCompressedName - if the file is compressed, this can receive the compressed
  230. name
  231. Return Value:
  232. TRUE indicats the file or a compressed copy of it is present.
  233. --*/
  234. {
  235. BOOL FileIsPresent = FALSE, IsCompressed = FALSE;
  236. WCHAR ActualName[MAX_PATH];
  237. PWSTR p;
  238. wcscpy( ActualName, FilePath) ;
  239. if (0xFFFFFFFF != GetFileAttributes( ActualName )) {
  240. FileIsPresent = TRUE;
  241. } else {
  242. //
  243. // the file isn't present, so try generating the compressed name
  244. //
  245. p = GenerateCompressedName( ActualName );
  246. if (p) {
  247. wcscpy( ActualName, p );
  248. TraceFree( p );
  249. p = NULL;
  250. if (0xFFFFFFFF != GetFileAttributes( ActualName )) {
  251. IsCompressed = TRUE;
  252. FileIsPresent = TRUE;
  253. }
  254. }
  255. }
  256. if (FileIsPresent && IsCompressed && pCompressedName) {
  257. *pCompressedName = (PWSTR)TraceAlloc( LPTR, (wcslen(ActualName)+1) * sizeof(WCHAR));
  258. if (*pCompressedName) {
  259. wcscpy( *pCompressedName, ActualName) ;
  260. }
  261. }
  262. return( FileIsPresent == TRUE);
  263. }
  264. //
  265. // Builds the pathes used for installation
  266. //
  267. HRESULT
  268. BuildDirectories( void )
  269. {
  270. TraceFunc( "BuildDirectories( void )\n" );
  271. //
  272. // Create
  273. // "D:\IntelliMirror\Setup\English\Images\nt50.wks"
  274. //
  275. wcscpy( g_Options.szInstallationPath, g_Options.szIntelliMirrorPath );
  276. ConcatenatePaths( g_Options.szInstallationPath, L"\\Setup" );
  277. ConcatenatePaths( g_Options.szInstallationPath, g_Options.szLanguage );
  278. ConcatenatePaths( g_Options.szInstallationPath, REMOTE_INSTALL_IMAGE_DIR_W );
  279. ConcatenatePaths( g_Options.szInstallationPath, g_Options.szInstallationName );
  280. //ConcatenatePaths( g_Options.szInstallationPath, g_Options.ProcessorArchitectureString );
  281. Assert( wcslen(g_Options.szInstallationPath) < ARRAYSIZE(g_Options.szInstallationPath) );
  282. HRETURN(S_OK);
  283. }
  284. //
  285. // Creates the IntelliMirror directory tree.
  286. //
  287. HRESULT
  288. CreateDirectoryPath(
  289. HWND hDlg,
  290. LPWSTR DirectoryPath,
  291. PSECURITY_ATTRIBUTES SecurityAttributes,
  292. BOOL fAllowExisting
  293. )
  294. {
  295. PWCHAR p, pBackslash;
  296. BOOL f;
  297. DWORD attributes;
  298. //
  299. // Find the \ that indicates the root directory. There should be at least
  300. // one \, but if there isn't, we just fall through.
  301. //
  302. p = wcschr( DirectoryPath, L'\\' );
  303. if ( p != NULL ) {
  304. //
  305. // Find the \ that indicates the end of the first level directory. It's
  306. // probable that there won't be another \, in which case we just fall
  307. // through to creating the entire path.
  308. //
  309. p = wcschr( p + 1, L'\\' );
  310. while ( p != NULL ) {
  311. //
  312. // Skip multiple \ that appear together.
  313. //
  314. pBackslash = p;
  315. ++p;
  316. while (*p == L'\\') {
  317. ++p;
  318. }
  319. if (*p == 0) {
  320. //
  321. // These \ are all at the end of the string, so we can
  322. // proceed to the creation of the leaf directory.
  323. //
  324. break;
  325. }
  326. //
  327. // Terminate the directory path at the current level.
  328. //
  329. *pBackslash = 0;
  330. //
  331. // Create a directory at the current level.
  332. //
  333. attributes = GetFileAttributes( DirectoryPath );
  334. if ( 0xFFFFffff == attributes ) {
  335. f = CreateDirectory( DirectoryPath, NULL );
  336. if ( !f ) {
  337. if ( GetLastError() != ERROR_ALREADY_EXISTS ) {
  338. ErrorBox( hDlg, DirectoryPath );
  339. HRETURN(E_FAIL);
  340. }
  341. }
  342. } else if ( (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ) {
  343. MessageBoxFromError( hDlg, DirectoryPath, ERROR_DIRECTORY );
  344. HRETURN(E_FAIL);
  345. }
  346. //
  347. // Restore the \ and find the next one.
  348. //
  349. *pBackslash = L'\\';
  350. p = wcschr( p, L'\\' );
  351. }
  352. }
  353. //
  354. // Create the target directory.
  355. //
  356. f = CreateDirectory( DirectoryPath, SecurityAttributes );
  357. if ( !f && (!fAllowExisting || (GetLastError() != ERROR_ALREADY_EXISTS)) ) {
  358. ErrorBox( hDlg, DirectoryPath );
  359. HRETURN(E_FAIL);
  360. }
  361. HRETURN(NO_ERROR);
  362. }
  363. //
  364. // Creates the IntelliMirror directory tree.
  365. //
  366. HRESULT
  367. CreateDirectories( HWND hDlg )
  368. {
  369. HRESULT hr = S_OK;
  370. WCHAR szPath[ MAX_PATH ];
  371. WCHAR szCreating[ SMALL_BUFFER_SIZE ];
  372. HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
  373. DWORD dwLen;
  374. DWORD dw;
  375. BOOL f;
  376. LPARAM lRange;
  377. PACL pAcl = NULL;
  378. SECURITY_DESCRIPTOR SecDescriptor;
  379. PSECURITY_DESCRIPTOR pSecDescriptor = &SecDescriptor;
  380. PSID pWorldSid = NULL;
  381. PSID pAdminsSid = NULL;
  382. DWORD attributes;
  383. TraceFunc( "CreateDirectories( hDlg )\n" );
  384. lRange = MAKELPARAM( 0 , 0
  385. + ( g_Options.fIMirrorShareFound ? 0 : 1 )
  386. + ( g_Options.fDirectoryTreeExists ? 0 : 7 )
  387. + ( g_Options.fOSChooserInstalled ? 0 : 1 )
  388. + ( g_Options.fNewOSDirectoryExists ? 0 : 1 )
  389. + ( g_Options.fOSChooserScreensDirectory ? 0 : (g_Options.fLanguageSet ? 1 : 0 ) ) );
  390. SendMessage( hProg, PBM_SETRANGE, 0, lRange );
  391. SendMessage( hProg, PBM_SETSTEP, 1, 0 );
  392. dw = LoadString( g_hinstance, IDS_CREATINGDIRECTORIES, szCreating, ARRAYSIZE(szCreating));
  393. Assert( dw );
  394. SetWindowText( GetDlgItem( hDlg, IDC_S_OPERATION ), szCreating );
  395. if ( !g_Options.fDirectoryTreeExists ) {
  396. attributes = GetFileAttributes( g_Options.szIntelliMirrorPath );
  397. if ( 0xFFFFffff == attributes ) {
  398. EXPLICIT_ACCESS ExplicitEntries[2];
  399. SECURITY_ATTRIBUTES sa;
  400. SID_IDENTIFIER_AUTHORITY ntSidAuthority = SECURITY_NT_AUTHORITY;
  401. SID_IDENTIFIER_AUTHORITY worldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  402. //
  403. // build AccessEntry structure
  404. //
  405. ZeroMemory( ExplicitEntries, sizeof(ExplicitEntries) );
  406. f = AllocateAndInitializeSid(
  407. &ntSidAuthority,
  408. 2,
  409. SECURITY_BUILTIN_DOMAIN_RID,
  410. DOMAIN_ALIAS_RID_ADMINS,
  411. 0, 0, 0, 0, 0, 0,
  412. &pAdminsSid );
  413. if ( !f || (pAdminsSid == NULL) ) {
  414. dw = GetLastError();
  415. MessageBoxFromError( hDlg, NULL, dw );
  416. hr = HRESULT_FROM_WIN32(dw);
  417. goto Error;
  418. }
  419. BuildTrusteeWithSid( &ExplicitEntries[0].Trustee, pAdminsSid );
  420. ExplicitEntries[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  421. ExplicitEntries[0].grfAccessMode = SET_ACCESS;
  422. ExplicitEntries[0].grfAccessPermissions = FILE_ALL_ACCESS;
  423. f = AllocateAndInitializeSid(
  424. &worldSidAuthority,
  425. 1,
  426. SECURITY_WORLD_RID,
  427. 0, 0, 0, 0, 0, 0, 0,
  428. &pWorldSid );
  429. if ( !f || (pAdminsSid == NULL) ) {
  430. dw = GetLastError();
  431. MessageBoxFromError( hDlg, NULL, dw );
  432. hr = HRESULT_FROM_WIN32(dw);
  433. goto Error;
  434. }
  435. BuildTrusteeWithSid( &ExplicitEntries[1].Trustee, pWorldSid );
  436. ExplicitEntries[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  437. ExplicitEntries[1].grfAccessMode = SET_ACCESS;
  438. ExplicitEntries[1].grfAccessPermissions = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE;
  439. //
  440. // Set the Acl with the ExplicitEntry rights
  441. //
  442. dw = SetEntriesInAcl( 2,
  443. ExplicitEntries,
  444. NULL,
  445. &pAcl );
  446. if ( dw != ERROR_SUCCESS ) {
  447. MessageBoxFromError( hDlg, NULL, dw );
  448. hr = HRESULT_FROM_WIN32(dw);
  449. goto Error;
  450. }
  451. //
  452. // Create the Security Descriptor
  453. //
  454. InitializeSecurityDescriptor( pSecDescriptor, SECURITY_DESCRIPTOR_REVISION );
  455. if (!SetSecurityDescriptorDacl( pSecDescriptor, TRUE, pAcl, FALSE )) {
  456. dw = GetLastError();
  457. }
  458. if ( dw != ERROR_SUCCESS ) {
  459. MessageBoxFromError( hDlg, NULL, dw );
  460. hr = HRESULT_FROM_WIN32(dw);
  461. goto Error;
  462. }
  463. //
  464. // Create the Security Attributes structure
  465. //
  466. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  467. sa.lpSecurityDescriptor = pSecDescriptor;
  468. sa.bInheritHandle = TRUE;
  469. //
  470. // Create
  471. // "D:\IntelliMirror"
  472. //
  473. hr = CreateDirectoryPath( hDlg, g_Options.szIntelliMirrorPath, &sa, FALSE );
  474. if ( hr != NO_ERROR ) {
  475. goto Error;
  476. }
  477. } else if ( (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ) {
  478. MessageBoxFromError( hDlg, g_Options.szIntelliMirrorPath, ERROR_DIRECTORY );
  479. hr = E_FAIL;
  480. goto Error;
  481. }
  482. // Prevent the index server from indexing the IntelliMirror directory.
  483. attributes = GetFileAttributes( g_Options.szIntelliMirrorPath );
  484. attributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
  485. f = SetFileAttributes( g_Options.szIntelliMirrorPath, attributes );
  486. if ( !f ) {
  487. ErrorBox( hDlg, g_Options.szIntelliMirrorPath );
  488. hr = THR(S_FALSE);
  489. }
  490. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  491. #if 0
  492. //
  493. // Create
  494. // "D:\IntelliMirror\Clients"
  495. //
  496. wcscpy( szPath, g_Options.szIntelliMirrorPath );
  497. ConcatenatePaths( szPath, L"\\Clients" );
  498. Assert( wcslen(szPath) < ARRAYSIZE(szPath) );
  499. if ( 0xFFFFffff == GetFileAttributes( szPath ) ) {
  500. f = CreateDirectory( szPath, NULL );
  501. if ( !f ) {
  502. ErrorBox( hDlg, szPath );
  503. hr = THR(S_FALSE);
  504. }
  505. }
  506. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  507. #endif
  508. //
  509. // Create
  510. // "D:\IntelliMirror\Setup"
  511. //
  512. wcscpy( szPath, g_Options.szIntelliMirrorPath );
  513. ConcatenatePaths( szPath, L"\\Setup" );
  514. Assert( wcslen(szPath) < ARRAYSIZE(szPath) );
  515. if ( 0xFFFFffff == GetFileAttributes( szPath ) ) {
  516. f = CreateDirectory( szPath, NULL );
  517. if ( !f ) {
  518. ErrorBox( hDlg, szPath );
  519. hr = THR(S_FALSE);
  520. }
  521. }
  522. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  523. //
  524. // Create
  525. // "D:\IntelliMirror\Setup\English"
  526. //
  527. wcscpy( szPath, g_Options.szIntelliMirrorPath );
  528. ConcatenatePaths( szPath, L"\\Setup" );
  529. ConcatenatePaths( szPath, g_Options.szLanguage );
  530. Assert( wcslen(szPath) < ARRAYSIZE(szPath) );
  531. if ( 0xFFFFffff == GetFileAttributes( szPath ) ) {
  532. f = CreateDirectory( szPath, NULL );
  533. if ( !f ) {
  534. ErrorBox( hDlg, szPath );
  535. hr = THR(S_FALSE);
  536. }
  537. }
  538. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  539. #if 0
  540. //
  541. // Create
  542. // "D:\IntelliMirror\Setup\English\Tools"
  543. //
  544. wcscpy( szPath, g_Options.szIntelliMirrorPath );
  545. ConcatenatePaths( szPath, L"\\Setup" );
  546. ConcatenatePaths( szPath, g_Options.szLanguage );
  547. ConcatenatePaths( szPath, L"\\Tools" );
  548. Assert( wcslen(szPath) < ARRAYSIZE(szPath) );
  549. if ( 0xFFFFffff == GetFileAttributes( szPath ) ) {
  550. f = CreateDirectory( szPath, NULL );
  551. if ( !f ) {
  552. ErrorBox( hDlg, szPath );
  553. hr = THR(S_FALSE);
  554. }
  555. }
  556. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  557. #endif
  558. //
  559. // Create
  560. // "D:\IntelliMirror\Setup\English\Images"
  561. //
  562. wcscpy( szPath, g_Options.szIntelliMirrorPath );
  563. ConcatenatePaths( szPath, L"\\Setup" );
  564. ConcatenatePaths( szPath, g_Options.szLanguage );
  565. ConcatenatePaths( szPath, REMOTE_INSTALL_IMAGE_DIR_W );
  566. Assert( wcslen(szPath) < ARRAYSIZE(szPath) );
  567. if ( 0xFFFFffff == GetFileAttributes( szPath ) ) {
  568. f = CreateDirectory( szPath, NULL );
  569. if ( !f ) {
  570. ErrorBox( hDlg, szPath );
  571. hr = THR(S_FALSE);
  572. }
  573. }
  574. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  575. }
  576. if ( !g_Options.fNewOSDirectoryExists
  577. && g_Options.fNewOS ) {
  578. //
  579. // Create
  580. // "D:\IntelliMirror\Setup\English\Images\nt50.wks"
  581. /// by removing the "\i386" from the end.
  582. //
  583. DWORD dwLen = lstrlen( g_Options.szInstallationPath );
  584. #if 0
  585. LPWSTR psz = StrRChr( g_Options.szInstallationPath, &g_Options.szInstallationPath[dwLen], L'\\' );
  586. if (psz == NULL) {
  587. Assert( psz );
  588. SetLastError(ERROR_BAD_NETPATH);
  589. ErrorBox( hDlg, g_Options.szInstallationPath );
  590. hr = THR(S_FALSE);
  591. } else {
  592. *psz = L'\0'; // terminate
  593. if ( 0xFFFFffff == GetFileAttributes( g_Options.szInstallationPath ) ) {
  594. f = CreateDirectory( g_Options.szInstallationPath, NULL );
  595. if ( !f ) {
  596. ErrorBox( hDlg, g_Options.szInstallationPath );
  597. hr = THR(S_FALSE);
  598. }
  599. }
  600. *psz = L'\\'; // restore
  601. }
  602. #endif
  603. //
  604. // Create
  605. // "D:\IntelliMirror\Setup\English\Images\nt50.wks\i386"
  606. //
  607. if ( 0xFFFFffff == GetFileAttributes( g_Options.szInstallationPath ) ) {
  608. f = CreateDirectory( g_Options.szInstallationPath, NULL );
  609. if ( !f ) {
  610. ErrorBox( hDlg, g_Options.szInstallationPath );
  611. hr = THR(S_FALSE);
  612. }
  613. }
  614. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  615. }
  616. if ( !g_Options.fOSChooserDirectory ) {
  617. //
  618. // Create the OS Chooser tree
  619. // "D:\IntelliMirror\OSChooser"
  620. //
  621. wcscpy( g_Options.szOSChooserPath, g_Options.szIntelliMirrorPath );
  622. ConcatenatePaths( g_Options.szOSChooserPath, L"\\OSChooser" );
  623. Assert( wcslen(g_Options.szOSChooserPath) < ARRAYSIZE(g_Options.szOSChooserPath) );
  624. if ( 0xFFFFffff == GetFileAttributes( g_Options.szOSChooserPath ) ) {
  625. f = CreateDirectory( g_Options.szOSChooserPath, NULL );
  626. if ( !f ) {
  627. ErrorBox( hDlg, g_Options.szOSChooserPath );
  628. hr = THR(E_FAIL);
  629. goto Error;
  630. }
  631. }
  632. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  633. }
  634. if ( g_Options.hinf != INVALID_HANDLE_VALUE
  635. && !g_Options.fOSChooserDirectoryTreeExists ) {
  636. WCHAR szFile[ MAX_PATH ];
  637. BOOL fFound;
  638. INFCONTEXT context;
  639. fFound = SetupFindFirstLine( g_Options.hinf, L"OSChooser", NULL, &context );
  640. AssertMsg( fFound, "Could not find 'OSChooser' section in REMINST.INF.\n" );
  641. while ( fFound
  642. && SetupGetStringField( &context, 1, szFile, ARRAYSIZE(szFile), NULL ) )
  643. {
  644. WCHAR szPath[ MAX_PATH ];
  645. DWORD dwLen = lstrlen( szFile );
  646. LPWSTR psz = StrRChr( szFile, &szFile[ dwLen ], L'\\' );
  647. if ( psz ) {
  648. *psz = L'\0'; // terminate
  649. wsprintf( szPath,
  650. L"%s\\%s",
  651. g_Options.szOSChooserPath,
  652. szFile );
  653. Assert( wcslen(szPath) < ARRAYSIZE(szPath) );
  654. if ( 0xFFFFffff == GetFileAttributes( szPath ) ) {
  655. HRESULT hr2;
  656. hr2 = CreateDirectoryPath( hDlg, szPath, NULL, TRUE );
  657. if ( FAILED ( hr2 )) {
  658. hr = hr2;
  659. }
  660. }
  661. }
  662. fFound = SetupFindNextLine( &context, &context );
  663. }
  664. }
  665. if ( FAILED( hr )) goto Error;
  666. if ( !g_Options.fOSChooserScreensDirectory
  667. && g_Options.fLanguageSet ) {
  668. //
  669. // Create
  670. // "D:\IntelliMirror\OSChooser\English"
  671. //
  672. wcscpy( szPath, g_Options.szIntelliMirrorPath );
  673. ConcatenatePaths( szPath, L"\\OSChooser" );
  674. ConcatenatePaths( szPath, g_Options.szLanguage );
  675. Assert( wcslen(szPath) < ARRAYSIZE(szPath) );
  676. if ( 0xFFFFffff == GetFileAttributes( szPath ) ) {
  677. f = CreateDirectory( szPath, NULL );
  678. if ( !f ) {
  679. ErrorBox( hDlg, szPath );
  680. hr = THR(E_FAIL); // major error
  681. goto Error;
  682. }
  683. }
  684. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  685. }
  686. // do this last
  687. if ( !g_Options.fIMirrorShareFound ) {
  688. //
  689. // Add the share
  690. //
  691. hr = CreateRemoteBootShare( hDlg );
  692. SendMessage( hProg, PBM_SETPOS, 1 , 0 );
  693. }
  694. Error:
  695. if ( pWorldSid ) {
  696. FreeSid( pWorldSid );
  697. }
  698. if ( pAdminsSid ) {
  699. FreeSid( pAdminsSid );
  700. }
  701. if ( pAcl ) {
  702. TraceFree( pAcl );
  703. }
  704. HRETURN(hr);
  705. }
  706. //
  707. // Find the filename part from a complete path.
  708. //
  709. LPWSTR FilenameOnly( LPWSTR pszPath )
  710. {
  711. LPWSTR psz = pszPath;
  712. // find the end
  713. while ( *psz )
  714. psz++;
  715. // find the slash
  716. while ( psz > pszPath && *psz != chSlash )
  717. psz--;
  718. // move in front of the slash
  719. if ( psz != pszPath )
  720. psz++;
  721. return psz;
  722. }
  723. //
  724. // Private structure containing information that the CopyFilesCallback()
  725. // needs.
  726. //
  727. typedef struct {
  728. PVOID pContext; // "Context" for DefaultQueueCallback
  729. HWND hProg; // hwnd to the progress meter
  730. HWND hOperation; // hwnd to the "current operation"
  731. DWORD nCopied; // number of files copied
  732. DWORD nToBeCopied; // number of file to be copied
  733. DWORD dwCopyingLength; // length of the IDS_COPYING
  734. WCHAR szCopyingString[ SMALL_BUFFER_SIZE ]; // buffer to create "Copying file.ext..."
  735. BOOL fQuiet; // do things quietly
  736. HWND hDlg; // hwnd to the Tasks Dialog
  737. } MYCONTEXT, *LPMYCONTEXT;
  738. //
  739. // Callback that the SETUP APIs calls. It handles updating the
  740. // progress meters as well as UI updating. Any messages not
  741. // handled are passed to the default SETUP callback.
  742. //
  743. UINT CALLBACK
  744. CopyFilesCallback(
  745. IN PVOID Context,
  746. IN UINT Notification,
  747. IN UINT_PTR Param1,
  748. IN UINT_PTR Param2
  749. )
  750. {
  751. LPMYCONTEXT pMyContext = (LPMYCONTEXT) Context;
  752. KeepUIAlive( pMyContext->hDlg );
  753. if ( g_Options.fAbort )
  754. {
  755. if ( !g_Options.fError )
  756. {
  757. WCHAR szAbort[ SMALL_BUFFER_SIZE ];
  758. // change filename text to aborting...
  759. DWORD dw = LoadString( g_hinstance, IDS_ABORTING, szAbort, ARRAYSIZE(szAbort) );
  760. Assert( dw );
  761. SetWindowText( pMyContext->hOperation, szAbort );
  762. g_Options.fError = TRUE;
  763. }
  764. if ( g_Options.fError ) {
  765. SetLastError(ERROR_CANCELLED);
  766. return FILEOP_ABORT;
  767. }
  768. }
  769. switch ( Notification )
  770. {
  771. case SPFILENOTIFY_ENDCOPY:
  772. if ( !(pMyContext->fQuiet) ) {
  773. pMyContext->nCopied++;
  774. SendMessage( pMyContext->hProg, PBM_SETPOS,
  775. (5000 * pMyContext->nCopied) / pMyContext->nToBeCopied, 0 );
  776. }
  777. break;
  778. case SPFILENOTIFY_STARTCOPY:
  779. if ( !(pMyContext->fQuiet) ) {
  780. DWORD dwLen;
  781. LPWSTR * ppszCopyingFile = (LPWSTR *) Param1;
  782. lstrcpy( &pMyContext->szCopyingString[ pMyContext->dwCopyingLength ],
  783. FilenameOnly( *ppszCopyingFile ) );
  784. dwLen = lstrlen( pMyContext->szCopyingString );
  785. lstrcpy( &pMyContext->szCopyingString[ dwLen ], L"..." );
  786. SetWindowText( pMyContext->hOperation, pMyContext->szCopyingString );
  787. }
  788. break;
  789. case SPFILENOTIFY_LANGMISMATCH:
  790. case SPFILENOTIFY_TARGETEXISTS:
  791. case SPFILENOTIFY_TARGETNEWER:
  792. if ( !pMyContext->fQuiet )
  793. {
  794. UINT u = SetupDefaultQueueCallback( pMyContext->pContext, Notification, Param1, Param2 );
  795. return u;
  796. }
  797. break;
  798. case SPFILENOTIFY_RENAMEERROR:
  799. case SPFILENOTIFY_DELETEERROR:
  800. case SPFILENOTIFY_COPYERROR:
  801. {
  802. FILEPATHS *fp = (FILEPATHS *) Param1;
  803. Assert( fp->Win32Error != ERROR_FILE_NOT_FOUND ); // Malformed DRIVERS.CAB file
  804. if ( fp->Win32Error == ERROR_FILE_NOT_FOUND )
  805. return FILEOP_SKIP;
  806. }
  807. case SPFILENOTIFY_NEEDMEDIA:
  808. UINT u = SetupDefaultQueueCallback( pMyContext->pContext, Notification, Param1, Param2 );
  809. if ( u == FILEOP_ABORT )
  810. {
  811. g_Options.fAbort = g_Options.fError = TRUE;
  812. }
  813. return u;
  814. }
  815. return FILEOP_DOIT;
  816. }
  817. //
  818. // CopyInfSection( )
  819. //
  820. HRESULT
  821. CopyInfSection(
  822. HSPFILEQ Queue,
  823. HINF hinf,
  824. LPCWSTR pszSection,
  825. LPCWSTR pszSourcePath,
  826. LPCWSTR pszSubPath, OPTIONAL
  827. LPCWSTR pszDescName,
  828. LPCWSTR pszTagFile,
  829. LPCWSTR pszDestinationRoot,
  830. LPDWORD pdwCount )
  831. /*++
  832. Routine Description:
  833. queues up files from the specified section to be installed into the
  834. remote install directory.
  835. Arguments:
  836. Queue - queue handle to queue the copy operations to.
  837. hinf - handle to inf which specifies the list of files to be copied
  838. pszSection - section listing files to be copied
  839. pszSourcePath - specifies the base source path,where the files may
  840. be found on the *source* media
  841. pszSubPath - specifies the subdirectory, if any, where the files may
  842. be found on the *source* media
  843. pszDescName- user printable description of the media where this file is
  844. located. this may be used when the queue is committed.
  845. pszTagFile - specifies the tag file that is to uniquely describe the media
  846. where these files are located
  847. pszDestinationRoot - specifies the root location where files are to be
  848. copied to
  849. pdwCount - specifies the number of files that were queued from this
  850. section on return. if the function fails, this value is
  851. undefined.
  852. Return Value:
  853. An HRESULT indicating the outcome.
  854. --*/
  855. {
  856. HRESULT hr = S_OK;
  857. INFCONTEXT context;
  858. BOOL b;
  859. TraceFunc( "CopyInfSection( ... )\n" );
  860. //
  861. // make sure the section we're looking for exists.
  862. // We'll use this context to enumerate the files in the section
  863. //
  864. b = SetupFindFirstLine( hinf, pszSection, NULL, &context );
  865. AssertMsg( b, "Missing section?" );
  866. if ( !b ) {
  867. hr = S_FALSE;
  868. }
  869. while ( b )
  870. {
  871. LPWSTR pszDestRename = NULL;
  872. WCHAR szDestPath[ MAX_PATH ],szRename[100];;
  873. WCHAR szSrcName[ 64 ];
  874. DWORD dw;
  875. KeepUIAlive( NULL );
  876. wcscpy(szDestPath, pszSubPath );
  877. dw = SetupGetFieldCount( &context );
  878. if ( dw > 1 ) {
  879. //
  880. // first field is the destination name.
  881. // we overload this field to also contain a subdirectory where
  882. // the files should be placed as well
  883. //
  884. b = SetupGetStringField(
  885. &context,
  886. 1,
  887. szRename,
  888. ARRAYSIZE( szRename ),
  889. NULL );
  890. AssertMsg( b, "Missing field?" );
  891. if ( b ) {
  892. //
  893. // 2nd field is the actual source filename
  894. //
  895. b = SetupGetStringField(
  896. &context,
  897. 2,
  898. szSrcName,
  899. ARRAYSIZE(szSrcName),
  900. NULL );
  901. AssertMsg( b, "Missing field?" );
  902. pszDestRename = szRename;
  903. }
  904. } else {
  905. //
  906. // if there's only one field, this is the actual source name. the
  907. // destination name will be the same as the source name.
  908. //
  909. b = SetupGetStringField(
  910. &context,
  911. 1,
  912. szSrcName,
  913. ARRAYSIZE(szSrcName),
  914. NULL );
  915. AssertMsg( b, "Missing field?" );
  916. }
  917. if ( !b ) {
  918. hr = S_FALSE;
  919. goto SkipIt;
  920. }
  921. ConcatenatePaths(
  922. szDestPath,
  923. pszDestRename
  924. ? pszDestRename
  925. : szSrcName );
  926. //
  927. // all files are installed into the
  928. //
  929. b = SetupQueueCopy( Queue,
  930. pszSourcePath,
  931. pszSubPath,
  932. szSrcName,
  933. pszDescName,
  934. pszTagFile,
  935. pszDestinationRoot,
  936. szDestPath,
  937. SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER
  938. | SP_COPY_WARNIFSKIP | SP_COPY_SOURCE_ABSOLUTE );
  939. if ( !b ) {
  940. ErrorBox( NULL, szSrcName );
  941. hr = THR(S_FALSE);
  942. goto SkipIt;
  943. }
  944. // increment file count
  945. (*pdwCount)++;
  946. SkipIt:
  947. b = SetupFindNextLine( &context, &context );
  948. }
  949. HRETURN(hr);
  950. }
  951. typedef struct _EXPANDCABLISTPARAMS {
  952. HWND hDlg;
  953. HINF hinf;
  954. LPCWSTR pszSection;
  955. LPCWSTR pszSourcePath;
  956. LPCWSTR pszDestPath;
  957. LPCWSTR pszSubDir;
  958. } EXPANDCABLISTPARAMS, *PEXPANDCABLISTPARAMS;
  959. //
  960. // ExpandCabList( )
  961. //
  962. DWORD WINAPI
  963. ExpandCabList( LPVOID lpVoid )
  964. {
  965. PEXPANDCABLISTPARAMS pParams = (PEXPANDCABLISTPARAMS) lpVoid;
  966. HRESULT hr = S_OK;
  967. INFCONTEXT context;
  968. WCHAR TempDstPath[MAX_PATH];
  969. WCHAR TempSrcPath[MAX_PATH];
  970. BOOL b;
  971. TraceFunc( "ExpandCabList( ... )\n" );
  972. // First make sure the DestPath exists, since we may call this
  973. // before we commit the setup copy queue.
  974. Assert( pParams->pszSection );
  975. Assert( pParams->pszSourcePath );
  976. Assert( pParams->pszDestPath );
  977. Assert( pParams->pszSubDir );
  978. DebugMsg( "Expand section %s from %s to %s\n",
  979. pParams->pszSection,
  980. pParams->pszSourcePath,
  981. pParams->pszDestPath );
  982. wcscpy( TempDstPath, pParams->pszDestPath);
  983. ConcatenatePaths( TempDstPath, pParams->pszSubDir );
  984. hr = CreateDirectoryPath( pParams->hDlg, TempDstPath, NULL, TRUE );
  985. if ( hr ) {
  986. HRETURN(hr);
  987. }
  988. wcscpy( TempSrcPath, pParams->pszSourcePath );
  989. ConcatenatePaths( TempSrcPath, pParams->pszSubDir );
  990. b = SetupFindFirstLine( pParams->hinf, pParams->pszSection, NULL, &context );
  991. AssertMsg( b, "Missing section?" );
  992. if ( !b ) {
  993. hr = S_FALSE;
  994. }
  995. while ( b && !g_Options.fError && !g_Options.fAbort )
  996. {
  997. LPWSTR pszDest = NULL;
  998. WCHAR wszCabName[ MAX_PATH ];
  999. CHAR szCabPath[ MAX_PATH ];
  1000. CHAR szDestPath[ MAX_PATH ];
  1001. DWORD dwSourcePathLen;
  1002. b = SetupGetStringField( &context, 1, wszCabName, ARRAYSIZE(wszCabName), NULL );
  1003. AssertMsg( b, "Missing field?" );
  1004. if ( !b ) {
  1005. hr = S_FALSE;
  1006. goto SkipIt;
  1007. }
  1008. // szCabPath is pszSourcePath\wszCabName, in ANSI
  1009. dwSourcePathLen = wcslen(TempSrcPath);
  1010. wcstombs( szCabPath, TempSrcPath, dwSourcePathLen );
  1011. if (szCabPath[dwSourcePathLen-1] != '\\') {
  1012. szCabPath[dwSourcePathLen] = '\\';
  1013. ++dwSourcePathLen;
  1014. }
  1015. wcstombs( &szCabPath[dwSourcePathLen], wszCabName, wcslen(wszCabName)+1 );
  1016. wcstombs( szDestPath, TempDstPath, wcslen(TempDstPath)+1 );
  1017. hr = ExtractFiles( szCabPath, szDestPath, 0, NULL, NULL, 0 );
  1018. if ( hr ) {
  1019. ErrorBox( pParams->hDlg, wszCabName );
  1020. goto SkipIt;
  1021. }
  1022. SkipIt:
  1023. b = SetupFindNextLine( &context, &context );
  1024. }
  1025. HRETURN(hr);
  1026. }
  1027. //
  1028. // RecursiveCopySubDirectory
  1029. //
  1030. HRESULT
  1031. RecursiveCopySubDirectory(
  1032. HSPFILEQ Queue, // Setup queue
  1033. LPWSTR pszSrcDir, // points to a buffer MAX_PATH big and contains the source dir to recurse
  1034. LPWSTR pszDestDir, // points to a buffer MAX_PATH big and contains the destination dir to recurse
  1035. LPWSTR pszDiscName, // CD name, if any
  1036. LPWSTR pszTagFile, // tagfile to look for, if any
  1037. LPDWORD pdwCount ) // copy file counter
  1038. {
  1039. HRESULT hr = S_OK;
  1040. BOOL b;
  1041. TraceFunc( "RecursiveCopySubDirectory( ... )\n" );
  1042. WIN32_FIND_DATA fda;
  1043. HANDLE hfda = INVALID_HANDLE_VALUE;
  1044. LONG uOrginalSrcLength = wcslen( pszSrcDir );
  1045. LONG uOrginalDstLength = wcslen( pszDestDir );
  1046. ConcatenatePaths( pszSrcDir, L"*" );
  1047. hfda = FindFirstFile( pszSrcDir, &fda );
  1048. if ( hfda == INVALID_HANDLE_VALUE )
  1049. {
  1050. ErrorBox( NULL, pszSrcDir );
  1051. hr = E_FAIL;
  1052. goto Cleanup;
  1053. }
  1054. pszSrcDir[ uOrginalSrcLength ] = L'\0';
  1055. do
  1056. {
  1057. KeepUIAlive( NULL );
  1058. if (( fda.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  1059. && ( wcscmp( fda.cFileName, L"." ) )
  1060. && ( wcscmp( fda.cFileName, L".." ) )) // no dot dirs
  1061. {
  1062. if ( wcslen( fda.cFileName ) + uOrginalDstLength >= MAX_PATH
  1063. || wcslen( fda.cFileName ) + uOrginalSrcLength >= MAX_PATH )
  1064. {
  1065. SetLastError( ERROR_BUFFER_OVERFLOW );
  1066. ErrorBox( NULL, fda.cFileName );
  1067. hr = E_FAIL;
  1068. goto Cleanup;
  1069. }
  1070. ConcatenatePaths( pszSrcDir, fda.cFileName );
  1071. ConcatenatePaths( pszDestDir, fda.cFileName );
  1072. RecursiveCopySubDirectory( Queue,
  1073. pszSrcDir,
  1074. pszDestDir,
  1075. pszDiscName,
  1076. pszTagFile,
  1077. pdwCount );
  1078. pszSrcDir[ uOrginalSrcLength ] = L'\0';
  1079. pszDestDir[ uOrginalDstLength ] = L'\0';
  1080. goto SkipFile;
  1081. }
  1082. else if (fda.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  1083. goto SkipFile;
  1084. b = SetupQueueCopy( Queue,
  1085. pszSrcDir,
  1086. NULL,
  1087. fda.cFileName,
  1088. pszDiscName,
  1089. pszTagFile,
  1090. pszDestDir,
  1091. NULL,
  1092. SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER
  1093. | SP_COPY_WARNIFSKIP | SP_COPY_SOURCE_ABSOLUTE );
  1094. if ( !b ) {
  1095. ErrorBox( NULL, fda.cFileName );
  1096. hr = THR(S_FALSE);
  1097. goto SkipFile;
  1098. }
  1099. // increment file counter
  1100. (*pdwCount)++;
  1101. SkipFile:
  1102. ; // nop
  1103. } while ( FindNextFile( hfda, &fda ) );
  1104. Cleanup:
  1105. if ( hfda != INVALID_HANDLE_VALUE ) {
  1106. FindClose( hfda );
  1107. hfda = INVALID_HANDLE_VALUE;
  1108. }
  1109. HRETURN(hr);
  1110. }
  1111. //
  1112. // CopyOptionalDirs
  1113. //
  1114. HRESULT
  1115. CopyOptionalDirs(
  1116. HSPFILEQ Queue,
  1117. HINF hinf,
  1118. LPWSTR pszSection,
  1119. LPWSTR pszDiscName,
  1120. LPWSTR pszTagFile,
  1121. LPDWORD pdwCount )
  1122. {
  1123. HRESULT hr = S_OK;
  1124. INFCONTEXT context;
  1125. UINT uLineNum;
  1126. BOOL b;
  1127. TraceFunc( "CopyOptionalDirs( ... )\n" );
  1128. b = SetupFindFirstLine( hinf, pszSection, NULL, &context );
  1129. #if 0
  1130. // this will hit installing a 2195 build because [AdditionalClientDirs]
  1131. // is missing, so take it out for now
  1132. AssertMsg( b, "Missing section?" );
  1133. #endif
  1134. if ( !b ) {
  1135. hr = S_FALSE;
  1136. }
  1137. while ( b && hr == S_OK )
  1138. {
  1139. WCHAR szSrcPath[ 14 ]; // should be 8.3 directory name
  1140. WCHAR szSrcDir[ MAX_PATH ];
  1141. WCHAR szDestDir[ MAX_PATH ];
  1142. WIN32_FIND_DATA fda;
  1143. HANDLE hfda = INVALID_HANDLE_VALUE;
  1144. LONG uOrginalSrcLength;
  1145. LONG uOrginalDestLength;
  1146. b = SetupGetStringField( &context, 0, szSrcPath, ARRAYSIZE(szSrcPath), NULL );
  1147. AssertMsg( b, "Missing field?" );
  1148. if ( !b ) {
  1149. hr = S_FALSE;
  1150. goto Cleanup;
  1151. }
  1152. wcscpy( szSrcDir, g_Options.szSourcePath );
  1153. ConcatenatePaths( szSrcDir, g_Options.ProcessorArchitectureString );
  1154. ConcatenatePaths( szSrcDir, szSrcPath );
  1155. Assert( wcslen( szSrcDir ) < ARRAYSIZE(szSrcDir) );
  1156. wcscpy( szDestDir, g_Options.szInstallationPath );
  1157. ConcatenatePaths( szDestDir, g_Options.ProcessorArchitectureString );
  1158. ConcatenatePaths( szDestDir, szSrcPath );
  1159. Assert( wcslen( szDestDir ) < ARRAYSIZE(szDestDir) );
  1160. hr = RecursiveCopySubDirectory( Queue,
  1161. szSrcDir,
  1162. szDestDir,
  1163. pszDiscName,
  1164. pszTagFile,
  1165. pdwCount );
  1166. if (hr)
  1167. goto Cleanup;
  1168. b = SetupFindNextLine( &context, &context );
  1169. }
  1170. Cleanup:
  1171. HRETURN(hr);
  1172. }
  1173. //
  1174. // IsEntryInCab( )
  1175. BOOL
  1176. IsEntryInCab(
  1177. HINF hinf,
  1178. PCWSTR pszFileName
  1179. )
  1180. {
  1181. TraceFunc( "IsEntryInCab( ... )\n" );
  1182. INFCONTEXT Context;
  1183. INFCONTEXT SectionContext;
  1184. WCHAR szCabinetName[ MAX_PATH ];
  1185. UINT uField;
  1186. UINT uFieldCount;
  1187. DWORD dwLen = ARRAYSIZE( szCabinetName );
  1188. Assert( hinf != INVALID_HANDLE_VALUE );
  1189. Assert( pszFileName );
  1190. // Find the cab files listing section
  1191. if ( !SetupFindFirstLineW( hinf, L"Version", L"CabFiles", &SectionContext ) )
  1192. {
  1193. RETURN( FALSE );
  1194. }
  1195. do
  1196. {
  1197. uFieldCount = SetupGetFieldCount( &SectionContext );
  1198. for( uField = 1; uField <= uFieldCount; uField++ )
  1199. {
  1200. SetupGetStringField( &SectionContext, uField, szCabinetName, dwLen, NULL );
  1201. if( SetupFindFirstLineW( hinf, szCabinetName, pszFileName, &Context ) )
  1202. {
  1203. RETURN( TRUE ); // it's in a CAB
  1204. }
  1205. }
  1206. } while ( SetupFindNextMatchLine( &SectionContext, L"CabFiles", &SectionContext ) );
  1207. RETURN( FALSE );
  1208. }
  1209. typedef struct _LL_FILES_TO_EXTRACT LL_FILES_TO_EXTRACT;
  1210. typedef struct _LL_FILES_TO_EXTRACT {
  1211. LL_FILES_TO_EXTRACT * Next;
  1212. DWORD dwLen;
  1213. WCHAR szFilename[ MAX_PATH ];
  1214. WCHAR szSubDir[ MAX_PATH ];
  1215. } LL_FILES_TO_EXTRACT, * PLL_FILES_TO_EXTRACT;
  1216. PLL_FILES_TO_EXTRACT pExtractionList;
  1217. //
  1218. // AddEntryToExtractionQueue( )
  1219. //
  1220. HRESULT
  1221. AddEntryToExtractionQueue(
  1222. LPWSTR pszFileName )
  1223. {
  1224. TraceFunc( "AddEntryToExtractionQueue( ... )\n" );
  1225. HRESULT hr = S_OK;
  1226. PLL_FILES_TO_EXTRACT pNode = pExtractionList;
  1227. DWORD dwLen;
  1228. dwLen = wcslen( pszFileName );
  1229. while ( pNode )
  1230. {
  1231. if ( dwLen == pNode->dwLen
  1232. && _wcsicmp( pszFileName, pNode->szFilename ) == 0 )
  1233. {
  1234. hr = S_FALSE;
  1235. goto exit; // duplicate
  1236. }
  1237. pNode = pNode->Next;
  1238. }
  1239. pNode = (PLL_FILES_TO_EXTRACT) LocalAlloc( LMEM_FIXED, sizeof(LL_FILES_TO_EXTRACT) );
  1240. if ( pNode )
  1241. {
  1242. pNode->dwLen = dwLen;
  1243. pNode->Next = pExtractionList;
  1244. wcscpy( pNode->szFilename, pszFileName );
  1245. pExtractionList = pNode;
  1246. DebugMsg( "QUEUEING : %s to be extracted.\n", pszFileName );
  1247. }
  1248. else
  1249. {
  1250. hr = THR( E_OUTOFMEMORY );
  1251. }
  1252. exit:
  1253. HRETURN(hr);
  1254. }
  1255. BOOL
  1256. MySetupGetSourceInfo(
  1257. IN HINF hInf,
  1258. IN UINT SrcId,
  1259. IN UINT InfoDesired,
  1260. IN PCWSTR ProcessorArchitectureOverride, OPTIONAL
  1261. OUT PWSTR Buffer,
  1262. IN DWORD BufferSizeInBytes,
  1263. OUT LPDWORD RequiredSize OPTIONAL
  1264. )
  1265. /*++
  1266. Routine Description:
  1267. Wrapper for SetupGetSourceInfo because it doesn't handle platform path
  1268. override correctly.
  1269. --*/
  1270. {
  1271. WCHAR TempSectionName[MAX_PATH];
  1272. WCHAR SourceId[20];
  1273. INFCONTEXT Context;
  1274. BOOL RetVal = FALSE;
  1275. if (!ProcessorArchitectureOverride) {
  1276. return SetupGetSourceInfo(
  1277. hInf,
  1278. SrcId,
  1279. InfoDesired,
  1280. Buffer,
  1281. BufferSizeInBytes,
  1282. RequiredSize );
  1283. }
  1284. Assert( InfoDesired == SRCINFO_PATH );
  1285. wsprintf( TempSectionName, L"SourceDisksNames.%s", ProcessorArchitectureOverride );
  1286. wsprintf( SourceId, L"%d", SrcId );
  1287. if (!SetupFindFirstLine( hInf, TempSectionName,SourceId, &Context )) {
  1288. wcscpy( TempSectionName, L"SourceDisksNames" );
  1289. if (!SetupFindFirstLine( hInf, TempSectionName,SourceId, &Context )) {
  1290. goto exit;
  1291. }
  1292. }
  1293. RetVal = SetupGetStringField( &Context, 4, Buffer, BufferSizeInBytes/sizeof(TCHAR), NULL );
  1294. exit:
  1295. return(RetVal);
  1296. }
  1297. //
  1298. // CopyLayoutInfSection( )
  1299. //
  1300. HRESULT
  1301. CopyLayoutInfSection(
  1302. HSPFILEQ Queue,
  1303. HINF hinf,
  1304. HINF hinfDrivers,
  1305. LPCWSTR pszSection,
  1306. LPCWSTR pszDescName,
  1307. LPCWSTR pszTagFile,
  1308. LPCWSTR pszDestination,
  1309. LPDWORD pdwCount )
  1310. /*++
  1311. Routine Description:
  1312. Queues up files from the specified section in layout.inf to be installed
  1313. into the remote install image directory. This code is similar to what
  1314. textmode setup does, and it reads several of the extended layout flags
  1315. that textmode setup reads and setupapi doesn't have intrinsic knowledge
  1316. about.
  1317. Arguments:
  1318. Queue - queue handle to queue the copy operations to.
  1319. hinf - handle to layout.inf
  1320. hinfDrivers - handle to drvindex.inf, to be used to see if files are
  1321. located in the driver cabinet or not
  1322. pszSection - section listing files to be copied
  1323. pszDescName- user printable description of the media where this file is
  1324. located. this may be used when the queue is committed.
  1325. pszTagFile - specifies the tag file that is to uniquely describe the media
  1326. where these files are located
  1327. pszDestination - specifies the location where files are to be
  1328. copied to
  1329. pdwCount - specifies the number of files that were queued from this
  1330. section on return. if the function fails, this value is
  1331. undefined.
  1332. Return Value:
  1333. An HRESULT indicating the outcome.
  1334. --*/
  1335. {
  1336. HRESULT hr = S_OK;
  1337. INFCONTEXT context;
  1338. BOOL b;
  1339. TraceFunc( "CopyLayoutInfSection( ... )\n" );
  1340. b = SetupFindFirstLine( hinf, pszSection, NULL, &context );
  1341. AssertMsg( b, "Missing section?" );
  1342. if ( !b ) {
  1343. hr = S_FALSE;
  1344. }
  1345. while ( b )
  1346. {
  1347. BOOL fDecompress = FALSE;
  1348. WCHAR szTemp[ 5 ]; // "_x" is the biggest string right now
  1349. DWORD SrcId;
  1350. WCHAR szSrcName[ MAX_PATH ];
  1351. WCHAR szSubDir[20];
  1352. WCHAR szSubDirPlusFileName[MAX_PATH];
  1353. LPWSTR pszPeriod;
  1354. KeepUIAlive( NULL );
  1355. b = SetupGetStringField( &context, 0, szSrcName, ARRAYSIZE(szSrcName), NULL );
  1356. AssertMsg( b, "Missing field?" );
  1357. if ( !b ) {
  1358. hr = S_FALSE;
  1359. goto SkipIt;
  1360. }
  1361. //
  1362. // get the subdirectory that this file is located in, based on the
  1363. // sourcedisksnames data in field 1
  1364. //
  1365. b = SetupGetStringField( &context, 1, szTemp, ARRAYSIZE(szTemp), NULL );
  1366. AssertMsg( b, "Missing field?" );
  1367. if ( !b ) {
  1368. hr = S_FALSE;
  1369. goto SkipIt;
  1370. }
  1371. SrcId = _wtoi(szTemp);
  1372. b = MySetupGetSourceInfo(
  1373. hinf,
  1374. SrcId,
  1375. SRCINFO_PATH,
  1376. SetupExtensionFromProcessorTag(g_Options.ProcessorArchitectureString),
  1377. szSubDir,
  1378. sizeof(szSubDir),
  1379. NULL );
  1380. if (!b) {
  1381. hr = S_FALSE;
  1382. goto SkipIt;
  1383. }
  1384. // If there is an "_" in the 2nd character of "source" column of the
  1385. // layout.inf file, then this file should be decompressed because
  1386. // it is a file needed for booting.
  1387. szTemp[1] = 0;
  1388. b = SetupGetStringField( &context, 7, szTemp, ARRAYSIZE(szTemp), NULL );
  1389. AssertMsg( b, "Missing field?" );
  1390. if ( szTemp[1] == L'_' ) {
  1391. fDecompress = TRUE;
  1392. DebugMsg( "DECOMPRESS: %s is a boot driver.\n", szSrcName );
  1393. goto CopyIt;
  1394. }
  1395. // If the 7th field isn't NULL, then the file exists outside the
  1396. // CABs so just copy it.
  1397. if ( wcslen( szTemp ) > 0 ) {
  1398. DebugMsg( "BOOTFLOPPY: %s is external from CAB.\n", szSrcName );
  1399. goto CopyIt;
  1400. }
  1401. // If it is in the CAB and didn't meet any of the conditions above,
  1402. // don't copy the file. It'll be in the CAB when/if setup needs it.
  1403. if ( IsEntryInCab( hinfDrivers, szSrcName ) ) {
  1404. #if DBG
  1405. pszPeriod = wcschr(szSrcName, L'.');
  1406. if ((pszPeriod != NULL) && (_wcsicmp(pszPeriod, L".inf") == 0)) {
  1407. DebugMsg(
  1408. "WARNING: %s is an INF in a cab. This file will not be available for network inf processing .\n",
  1409. szSrcName );
  1410. }
  1411. #endif
  1412. DebugMsg( "SKIPPING : %s in a CAB.\n", szSrcName );
  1413. goto SkipIt;
  1414. }
  1415. // If the extension is ".inf", then decompress so binlsvc
  1416. // can do its network .inf processing.
  1417. pszPeriod = wcschr(szSrcName, L'.');
  1418. if ((pszPeriod != NULL) && (_wcsicmp(pszPeriod, L".inf") == 0)) {
  1419. fDecompress = TRUE;
  1420. DebugMsg( "DECOMPRESS: %s is an INF.\n", szSrcName );
  1421. }
  1422. CopyIt:
  1423. //
  1424. // we do this so that files end up in the proper subdirectory
  1425. //
  1426. wcscpy(szSubDirPlusFileName, szSubDir );
  1427. ConcatenatePaths( szSubDirPlusFileName, szSrcName );
  1428. b = SetupQueueCopy( Queue,
  1429. g_Options.szSourcePath,
  1430. szSubDir,
  1431. szSrcName,
  1432. pszDescName,
  1433. pszTagFile,
  1434. pszDestination,
  1435. szSubDirPlusFileName,
  1436. SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER | SP_COPY_WARNIFSKIP
  1437. | SP_COPY_SOURCE_ABSOLUTE | ( fDecompress ? 0 : SP_COPY_NODECOMP ) );
  1438. if ( !b ) {
  1439. ErrorBox( NULL, szSrcName );
  1440. hr = THR(S_FALSE);
  1441. goto SkipIt;
  1442. }
  1443. // increment file counter
  1444. (*pdwCount)++;
  1445. SkipIt:
  1446. b = SetupFindNextLine( &context, &context );
  1447. }
  1448. HRETURN(hr);
  1449. }
  1450. //
  1451. // EnumNetworkDriversCallback( )
  1452. //
  1453. ULONG
  1454. EnumNetworkDriversCallback(
  1455. LPVOID pContext,
  1456. LPWSTR pszInfName,
  1457. LPWSTR pszFileName )
  1458. {
  1459. TraceFunc( "EnumNetworkDriversCallback( ... )\n" );
  1460. MYCONTEXT * pMyContext = (MYCONTEXT *) pContext;
  1461. HRESULT hr;
  1462. Assert( pszFileName );
  1463. Assert( pszInfName );
  1464. //DebugMsg( "In %s: %s\n", pszInfName, pszFileName );
  1465. if ( KeepUIAlive( pMyContext->hDlg ) )
  1466. {
  1467. RETURN(ERROR_CANCELLED);
  1468. }
  1469. hr = AddEntryToExtractionQueue( pszFileName );
  1470. if ( hr == S_OK )
  1471. {
  1472. pMyContext->nToBeCopied++;
  1473. }
  1474. else if ( hr == S_FALSE )
  1475. { // duplicate found in queue... keep going
  1476. hr = S_OK;
  1477. }
  1478. HRETURN(hr);
  1479. }
  1480. //
  1481. // EnumCabinetCallback( )
  1482. //
  1483. UINT CALLBACK
  1484. EnumCabinetCallback(
  1485. IN PVOID Context,
  1486. IN UINT Notification,
  1487. IN UINT_PTR Param1,
  1488. IN UINT_PTR Param2
  1489. )
  1490. {
  1491. TraceFunc( "EnumCabinetCallback( ... )\n" );
  1492. UINT uResult = 0;
  1493. PLL_FILES_TO_EXTRACT pNode = pExtractionList;
  1494. PLL_FILES_TO_EXTRACT pLast;
  1495. DWORD dwLen;
  1496. PFILE_IN_CABINET_INFO pfici;
  1497. MYCONTEXT *pMyContext = (MYCONTEXT *) Context;
  1498. Assert( pMyContext );
  1499. KeepUIAlive( pMyContext->hDlg );
  1500. if ( g_Options.fAbort )
  1501. {
  1502. if ( !g_Options.fError )
  1503. {
  1504. WCHAR szAbort[ SMALL_BUFFER_SIZE ];
  1505. // change filename text to aborting...
  1506. DWORD dw = LoadString( g_hinstance, IDS_ABORTING, szAbort, ARRAYSIZE(szAbort) );
  1507. Assert( dw );
  1508. SetWindowText( pMyContext->hOperation, szAbort );
  1509. g_Options.fError = TRUE;
  1510. }
  1511. if ( g_Options.fError ) {
  1512. SetLastError(ERROR_CANCELLED);
  1513. uResult = FILEOP_ABORT;
  1514. goto exit;
  1515. }
  1516. }
  1517. if ( Notification == SPFILENOTIFY_FILEINCABINET )
  1518. {
  1519. pfici = (PFILE_IN_CABINET_INFO) Param1;
  1520. Assert( pfici );
  1521. Assert( pfici->NameInCabinet );
  1522. dwLen = wcslen( pfici->NameInCabinet );
  1523. while ( pNode )
  1524. {
  1525. if ( dwLen == pNode->dwLen
  1526. && _wcsicmp( pfici->NameInCabinet, pNode->szFilename ) == 0 )
  1527. { // match! remove it from the list and extract it.
  1528. if ( pNode == pExtractionList )
  1529. {
  1530. pExtractionList = pNode->Next;
  1531. }
  1532. else
  1533. {
  1534. pLast->Next = pNode->Next;
  1535. }
  1536. LocalFree( pNode );
  1537. // create target path
  1538. wcscpy( pfici->FullTargetName, g_Options.szInstallationPath );
  1539. ConcatenatePaths( pfici->FullTargetName, g_Options.ProcessorArchitectureString );
  1540. ConcatenatePaths( pfici->FullTargetName, pfici->NameInCabinet );
  1541. if ( !(pMyContext->fQuiet) ) {
  1542. wcscpy( &pMyContext->szCopyingString[ pMyContext->dwCopyingLength ],
  1543. pfici->NameInCabinet );
  1544. dwLen = wcslen( pMyContext->szCopyingString );
  1545. wcscpy( &pMyContext->szCopyingString[ dwLen ], L"..." );
  1546. SetWindowText( pMyContext->hOperation, pMyContext->szCopyingString );
  1547. }
  1548. DebugMsg( "EXTRACTING: %s from CAB.\n", pfici->NameInCabinet );
  1549. uResult = FILEOP_DOIT;
  1550. goto exit;
  1551. }
  1552. pLast = pNode;
  1553. pNode = pNode->Next;
  1554. }
  1555. uResult = FILEOP_SKIP;
  1556. }
  1557. else if ( Notification == SPFILENOTIFY_FILEEXTRACTED )
  1558. {
  1559. PFILEPATHS pfp = (PFILEPATHS) Param1;
  1560. Assert( pfp );
  1561. pMyContext->nCopied++;
  1562. SendMessage( pMyContext->hProg, PBM_SETPOS, (5000 * pMyContext->nCopied) / pMyContext->nToBeCopied, 0 );
  1563. uResult = pfp->Win32Error;
  1564. }
  1565. exit:
  1566. RETURN(uResult);
  1567. }
  1568. //
  1569. // AddInfSectionToExtractQueue( )
  1570. //
  1571. HRESULT
  1572. AddInfSectionToExtractQueue(
  1573. HINF hinf,
  1574. LPWSTR pszSection,
  1575. LPMYCONTEXT Context )
  1576. {
  1577. TraceFunc( "AddInfSectionToExtractQueue( ... )\n" );
  1578. HRESULT hr = S_OK;
  1579. BOOL b;
  1580. INFCONTEXT context;
  1581. b = SetupFindFirstLine( hinf, pszSection, NULL, &context );
  1582. if ( !b ) goto Cleanup; // nothing to do - don't complain!
  1583. while ( b )
  1584. {
  1585. WCHAR szFilename[ MAX_PATH ];
  1586. DWORD dwLen = ARRAYSIZE( szFilename );
  1587. b = SetupGetStringField( &context, 1, szFilename, dwLen, NULL );
  1588. if ( !b ) goto Error;
  1589. hr = AddEntryToExtractionQueue( szFilename );
  1590. if (FAILED( hr )) goto Cleanup;
  1591. if (hr == S_OK) {
  1592. Context->nToBeCopied += 1;
  1593. }
  1594. b = SetupFindNextLine( &context, &context );
  1595. }
  1596. Cleanup:
  1597. HRETURN(hr);
  1598. Error:
  1599. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  1600. goto Cleanup;
  1601. }
  1602. //
  1603. // Copies the files into the setup directory.
  1604. //
  1605. HRESULT
  1606. CopyClientFiles( HWND hDlg )
  1607. {
  1608. HRESULT hr = S_OK;
  1609. DWORD dwLen;
  1610. LPWSTR psz;
  1611. BOOL b;
  1612. HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
  1613. DWORD dwCount = 0;
  1614. DWORD dw;
  1615. WCHAR szText[ SMALL_BUFFER_SIZE ];
  1616. WCHAR szFilepath[ MAX_PATH ];
  1617. WCHAR szTempPath[ MAX_PATH ];
  1618. WCHAR szInsertMedia[ MAX_PATH ];
  1619. HINF hinfLayout = INVALID_HANDLE_VALUE;
  1620. HINF hinfReminst = INVALID_HANDLE_VALUE;
  1621. HINF hinfDrivers = INVALID_HANDLE_VALUE;
  1622. HINF hinfDosnet = INVALID_HANDLE_VALUE;
  1623. UINT uLineNum;
  1624. DWORD dwFlags = IDF_CHECKFIRST | IDF_NOSKIP;
  1625. WCHAR *p;
  1626. PLL_FILES_TO_EXTRACT pNode;
  1627. HMODULE hBinlsvc = NULL;
  1628. PNETINFENUMFILES pfnNetInfEnumFiles = NULL;
  1629. HANDLE hThread = NULL;
  1630. EXPANDCABLISTPARAMS ExpandParams;
  1631. INFCONTEXT context;
  1632. HSPFILEQ Queue = INVALID_HANDLE_VALUE;
  1633. MYCONTEXT MyContext;
  1634. TraceFunc( "CopyClientFiles( hDlg )\n" );
  1635. //
  1636. // Setup and display next section of dialog
  1637. //
  1638. SendMessage( hProg, PBM_SETRANGE, 0, MAKELPARAM(0, 5000 ));
  1639. SendMessage( hProg, PBM_SETPOS, 0, 0 );
  1640. dw = LoadString( g_hinstance, IDS_BUILDINGFILELIST, szText, ARRAYSIZE(szText));
  1641. Assert( dw );
  1642. SetDlgItemText( hDlg, IDC_S_OPERATION, szText );
  1643. // Initialize
  1644. ZeroMemory( &MyContext, sizeof(MyContext) );
  1645. pExtractionList = NULL;
  1646. ZeroMemory( &ExpandParams, sizeof(ExpandParams) );
  1647. hBinlsvc = LoadLibrary( L"BINLSVC.DLL" );
  1648. if ( hBinlsvc == NULL )
  1649. {
  1650. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  1651. ErrorBox( hDlg, L"BINLSVC.DLL" );
  1652. goto Cleanup;
  1653. }
  1654. pfnNetInfEnumFiles = (PNETINFENUMFILES) GetProcAddress( hBinlsvc, NETINFENUMFILESENTRYPOINT );
  1655. if ( pfnNetInfEnumFiles == NULL )
  1656. {
  1657. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  1658. ErrorBox( hDlg, L"BINLSVC.DLL" );
  1659. goto Cleanup;
  1660. }
  1661. // Make sure the workstation CD is the CD-ROM drive
  1662. dw = LoadString( g_hinstance, IDS_INSERT_MEDIA, szInsertMedia, ARRAYSIZE(szInsertMedia) );
  1663. Assert( dw );
  1664. AskForDisk:
  1665. wcscpy(szTempPath, g_Options.szSourcePath);
  1666. ConcatenatePaths( szTempPath, g_Options.ProcessorArchitectureString);
  1667. if ( DPROMPT_SUCCESS !=
  1668. SetupPromptForDisk( hDlg,
  1669. szInsertMedia,
  1670. g_Options.szWorkstationDiscName,
  1671. szTempPath,
  1672. L"layout.inf",
  1673. g_Options.szWorkstationTagFile,
  1674. dwFlags,
  1675. g_Options.szSourcePath,
  1676. MAX_PATH,
  1677. NULL ) )
  1678. {
  1679. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  1680. goto Cleanup;
  1681. }
  1682. //
  1683. // if they gave us a trailing architecture tag, then remove it
  1684. //
  1685. if (g_Options.szSourcePath[wcslen(g_Options.szSourcePath)-1] == L'\\') {
  1686. //
  1687. // lose the trailing backslash if present
  1688. //
  1689. g_Options.szSourcePath[wcslen(g_Options.szSourcePath)-1] = L'\0';
  1690. }
  1691. p = wcsrchr( g_Options.szSourcePath, L'\\');
  1692. if (p) {
  1693. p = StrStrI(p,g_Options.ProcessorArchitectureString);
  1694. if (p) {
  1695. *(p-1) = L'\0';
  1696. }
  1697. }
  1698. dw = CheckImageSource( hDlg );
  1699. if ( dw != ERROR_SUCCESS )
  1700. {
  1701. dwFlags = IDF_NOSKIP;
  1702. goto AskForDisk;
  1703. }
  1704. if ( g_Options.fAbort || g_Options.fError )
  1705. goto Cleanup;
  1706. wcscpy(szFilepath, g_Options.szSourcePath);
  1707. ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString);
  1708. ConcatenatePaths( szFilepath, L"layout.inf");
  1709. Assert( wcslen( szFilepath ) < ARRAYSIZE(szFilepath) );
  1710. hinfLayout = SetupOpenInfFile( szFilepath, NULL, INF_STYLE_WIN4, &uLineNum);
  1711. if ( hinfLayout == INVALID_HANDLE_VALUE ) {
  1712. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  1713. ErrorBox( hDlg, szFilepath );
  1714. goto Cleanup;
  1715. }
  1716. // Openning layout can take a long time. Update the UI and check to see
  1717. // if the user wants to abort.
  1718. if ( KeepUIAlive( hDlg ) )
  1719. {
  1720. hr = HRESULT_FROM_WIN32( ERROR_CANCELLED );
  1721. goto Cleanup;
  1722. }
  1723. wcscpy(szFilepath, g_Options.szSourcePath);
  1724. ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString);
  1725. ConcatenatePaths( szFilepath, L"drvindex.inf");
  1726. Assert( wcslen( szFilepath ) < ARRAYSIZE(szFilepath) );
  1727. hinfDrivers = SetupOpenInfFile( szFilepath, NULL, INF_STYLE_WIN4, &uLineNum);
  1728. if ( hinfDrivers == INVALID_HANDLE_VALUE ) {
  1729. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  1730. ErrorBox( hDlg, szFilepath );
  1731. goto Cleanup;
  1732. }
  1733. //
  1734. // Create the Queue
  1735. //
  1736. Queue = SetupOpenFileQueue( );
  1737. //
  1738. // Copy to REMINST.inf quietly
  1739. //
  1740. dw = GetEnvironmentVariable( L"TMP",
  1741. g_Options.szWorkstationRemBootInfPath,
  1742. ARRAYSIZE(g_Options.szWorkstationRemBootInfPath) );
  1743. Assert( dw );
  1744. ConcatenatePaths( g_Options.szWorkstationRemBootInfPath, L"\\REMINST.inf" );
  1745. Assert( wcslen(g_Options.szWorkstationRemBootInfPath) < ARRAYSIZE(g_Options.szWorkstationRemBootInfPath) );
  1746. wcscpy(szTempPath, g_Options.szSourcePath);
  1747. ConcatenatePaths( szTempPath, g_Options.ProcessorArchitectureString);
  1748. b = SetupInstallFile( hinfLayout,
  1749. NULL,
  1750. L"REMINST.inf",
  1751. szTempPath,
  1752. g_Options.szWorkstationRemBootInfPath,
  1753. SP_COPY_FORCE_NEWER,
  1754. NULL,
  1755. NULL );
  1756. if ( !b ) {
  1757. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  1758. WCHAR szCaption[SMALL_BUFFER_SIZE];
  1759. DWORD dw;
  1760. dw = LoadString( g_hinstance, IDS_COPYING_REMINST_TITLE, szCaption, SMALL_BUFFER_SIZE );
  1761. Assert( dw );
  1762. ErrorBox( hDlg, szCaption );
  1763. AssertMsg( b, "Failed to copy REMINST.INF to TEMP" );
  1764. goto Cleanup;
  1765. }
  1766. // The above call will initialize a lot of the SETUPAPI. This might take
  1767. // a long time as well. Refresh the UI and check for user abort.
  1768. if ( KeepUIAlive( hDlg ) )
  1769. {
  1770. hr = HRESULT_FROM_WIN32( ERROR_CANCELLED );
  1771. goto Cleanup;
  1772. }
  1773. // Now check the version of the workstation to make sure it's compatible
  1774. hr = CheckServerVersion( );
  1775. if ( FAILED(hr) )
  1776. goto Cleanup;
  1777. //
  1778. // Copy architecture-indepenedent files.
  1779. //
  1780. hr = CopyLayoutInfSection( Queue,
  1781. hinfLayout,
  1782. hinfDrivers,
  1783. L"SourceDisksFiles",
  1784. g_Options.szWorkstationDiscName,
  1785. g_Options.szWorkstationTagFile,
  1786. g_Options.szInstallationPath,
  1787. &dwCount );
  1788. if ( FAILED(hr) ) {
  1789. goto Cleanup;
  1790. }
  1791. //
  1792. // Copy architecture-depenedent files.
  1793. //
  1794. wsprintf(
  1795. szTempPath,
  1796. L"SourceDisksFiles.%s",
  1797. SetupExtensionFromProcessorTag(g_Options.ProcessorArchitectureString) );
  1798. hr = CopyLayoutInfSection( Queue,
  1799. hinfLayout,
  1800. hinfDrivers,
  1801. szTempPath,
  1802. g_Options.szWorkstationDiscName,
  1803. g_Options.szWorkstationTagFile,
  1804. g_Options.szInstallationPath,
  1805. &dwCount );
  1806. if ( FAILED(hr) ) {
  1807. goto Cleanup;
  1808. }
  1809. //
  1810. // build the path to dosnet.inf
  1811. //
  1812. wcscpy( szFilepath, g_Options.szSourcePath );
  1813. ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString );
  1814. ConcatenatePaths( szFilepath, L"dosnet.inf" );
  1815. Assert( wcslen( szFilepath ) < ARRAYSIZE(szFilepath));
  1816. hinfDosnet = SetupOpenInfFile( szFilepath, NULL, INF_STYLE_WIN4, &uLineNum);
  1817. if ( hinfDosnet == INVALID_HANDLE_VALUE ) {
  1818. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  1819. ErrorBox( NULL, szFilepath );
  1820. goto Cleanup;
  1821. }
  1822. hr = CopyOptionalDirs( Queue,
  1823. hinfDosnet,
  1824. L"OptionalSrcDirs",
  1825. g_Options.szWorkstationDiscName,
  1826. g_Options.szWorkstationTagFile,
  1827. &dwCount );
  1828. if ( FAILED(hr) )
  1829. goto Cleanup;
  1830. SetupCloseInfFile( hinfLayout );
  1831. hinfLayout = INVALID_HANDLE_VALUE;
  1832. SetupCloseInfFile( hinfDosnet );
  1833. hinfDosnet = INVALID_HANDLE_VALUE;
  1834. //
  1835. // Add additional files not specified in the LAYOUT.INF
  1836. //
  1837. hinfReminst = SetupOpenInfFile( g_Options.szWorkstationRemBootInfPath, NULL, INF_STYLE_WIN4, &uLineNum);
  1838. if ( hinfReminst == INVALID_HANDLE_VALUE ) {
  1839. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  1840. ErrorBox( hDlg, g_Options.szWorkstationRemBootInfPath );
  1841. goto Cleanup;
  1842. }
  1843. hr = CopyInfSection( Queue,
  1844. hinfReminst,
  1845. L"AdditionalClientFiles",
  1846. g_Options.szSourcePath,
  1847. g_Options.szWorkstationSubDir,
  1848. g_Options.szWorkstationDiscName,
  1849. g_Options.szWorkstationTagFile,
  1850. g_Options.szInstallationPath,
  1851. &dwCount );
  1852. if( FAILED(hr) )
  1853. goto Cleanup;
  1854. //
  1855. // Add additional directories not specified in LAYOUT.INF
  1856. //
  1857. hr = CopyOptionalDirs( Queue,
  1858. hinfReminst,
  1859. L"AdditionalClientDirs",
  1860. g_Options.szWorkstationDiscName,
  1861. g_Options.szWorkstationTagFile,
  1862. &dwCount );
  1863. if ( FAILED(hr) )
  1864. goto Cleanup;
  1865. //
  1866. // This information will be passed to CopyFileCallback() as
  1867. // the Context.
  1868. //
  1869. MyContext.nToBeCopied = dwCount;
  1870. MyContext.nCopied = 0;
  1871. MyContext.pContext = SetupInitDefaultQueueCallback( hDlg );
  1872. MyContext.hProg = hProg;
  1873. MyContext.hOperation = GetDlgItem( hDlg, IDC_S_OPERATION );
  1874. MyContext.hDlg = hDlg;
  1875. MyContext.fQuiet = FALSE;
  1876. MyContext.dwCopyingLength =
  1877. LoadString( g_hinstance, IDS_COPYING, MyContext.szCopyingString, ARRAYSIZE(MyContext.szCopyingString));
  1878. Assert(MyContext.dwCopyingLength);
  1879. //
  1880. // Start copying
  1881. //
  1882. Assert( dwCount );
  1883. if ( dwCount != 0 )
  1884. {
  1885. b = SetupCommitFileQueue( NULL,
  1886. Queue,
  1887. (PSP_FILE_CALLBACK) CopyFilesCallback,
  1888. (PVOID) &MyContext );
  1889. if ( !b ) {
  1890. DWORD dwErr = GetLastError( );
  1891. switch ( dwErr )
  1892. {
  1893. case ERROR_CANCELLED:
  1894. hr = THR( HRESULT_FROM_WIN32( ERROR_CANCELLED ) );
  1895. goto Cleanup;
  1896. default:
  1897. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  1898. MessageBoxFromError( hDlg, NULL, dwErr );
  1899. goto Cleanup;
  1900. }
  1901. }
  1902. }
  1903. SetupCloseFileQueue( Queue );
  1904. Queue = INVALID_HANDLE_VALUE;
  1905. //
  1906. // Ask BINL to go through the INFs to find the drivers
  1907. // that we need to extract from the CABs.
  1908. //
  1909. dw = LoadString( g_hinstance, IDS_BUILDINGFILELIST, szText, ARRAYSIZE(szText));
  1910. Assert( dw );
  1911. SetDlgItemText( hDlg, IDC_S_OPERATION, szText );
  1912. SendMessage( hProg, PBM_SETPOS, 0, 0 );
  1913. // Re-init these values
  1914. MyContext.nCopied = 0;
  1915. MyContext.nToBeCopied = 0;
  1916. // Pre-fill the link list of things to extract from the cab with
  1917. // things in the workstations REMINST.INF if needed. The section
  1918. // can be missing if there is nothing to pre-fill.
  1919. hr = AddInfSectionToExtractQueue( hinfReminst, L"ExtractFromCabs", &MyContext );
  1920. if (FAILED( hr ))
  1921. goto Cleanup;
  1922. //!!!!bugbug doesn't seem to be working right!!!!
  1923. // compile the list of files
  1924. wcscpy( szTempPath, g_Options.szInstallationPath );
  1925. ConcatenatePaths( szTempPath, g_Options.ProcessorArchitectureString );
  1926. dw = pfnNetInfEnumFiles( szTempPath,
  1927. g_Options.ProcessorArchitecture,
  1928. &MyContext,
  1929. EnumNetworkDriversCallback );
  1930. if ( dw != ERROR_SUCCESS )
  1931. {
  1932. hr = THR( HRESULT_FROM_WIN32( dw ) );
  1933. MessageBoxFromError( hDlg, NULL, dw );
  1934. goto Cleanup;
  1935. }
  1936. DebugMsg( "%d files need to be extracted from CABs.\n", MyContext.nToBeCopied );
  1937. // Go through the CABs extracting only the ones in the link list
  1938. if ( !SetupFindFirstLineW( hinfDrivers, L"Version", L"CabFiles", &context) )
  1939. {
  1940. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  1941. ErrorBox( hDlg, NULL );
  1942. goto Cleanup;
  1943. }
  1944. do
  1945. {
  1946. UINT uFieldCount = SetupGetFieldCount( &context );
  1947. DebugMsg( "uFieldCount = %u\n", uFieldCount );
  1948. for( UINT uField = 1; uField <= uFieldCount; uField++ )
  1949. {
  1950. WCHAR CabinetNameKey[64];
  1951. INFCONTEXT DrvContext;
  1952. WCHAR szCabinetName[ MAX_PATH ];
  1953. dwLen = ARRAYSIZE( szCabinetName );
  1954. if (!SetupGetStringField( &context, uField, CabinetNameKey, ARRAYSIZE( CabinetNameKey ), NULL ) ||
  1955. !SetupFindFirstLine( hinfDrivers, L"Cabs", CabinetNameKey, &DrvContext) ||
  1956. !SetupGetStringField( &DrvContext, 1, szCabinetName, dwLen, NULL )) {
  1957. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  1958. ErrorBox( hDlg, NULL );
  1959. goto Cleanup;
  1960. }
  1961. wcscpy( szFilepath, g_Options.szInstallationPath);
  1962. ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString );
  1963. ConcatenatePaths( szFilepath, szCabinetName );
  1964. DebugMsg( "Iterating: %s\n", szFilepath );
  1965. if ( szCabinetName[0] == L'\0' )
  1966. continue; // skip blanks
  1967. b = SetupIterateCabinet( szFilepath,
  1968. 0,
  1969. EnumCabinetCallback,
  1970. &MyContext );
  1971. if ( !b )
  1972. {
  1973. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  1974. ErrorBox( hDlg, szFilepath );
  1975. goto Cleanup;
  1976. }
  1977. }
  1978. } while ( SetupFindNextMatchLine( &context, L"CabFiles", &context ) );
  1979. //
  1980. // comment out this assert because it always fires -- some files we are
  1981. // queuing up (the ones in the ExtractFromCabs section) are not part of
  1982. // any cab, so they are handled in the following section.
  1983. //
  1984. #if 0
  1985. // This should be empty - if not tell someone on the CHKed version.
  1986. AssertMsg( pExtractionList == NULL, "Some network drivers are not in the CABs.\n\nIgnore this if you do not care." );
  1987. #endif
  1988. if ( pExtractionList != NULL )
  1989. {
  1990. WCHAR szDstPath[ MAX_PATH ];
  1991. // Ok. Someone decided that these files shouldn't be in the CAB. So
  1992. // let's try to get them from outside the CAB.
  1993. pNode = pExtractionList;
  1994. while ( pNode )
  1995. {
  1996. DWORD dwConditionalFlags = 0;
  1997. WCHAR cTmp;
  1998. PWSTR CompressedName = NULL;
  1999. //
  2000. // see if we copied the file to the installation image already
  2001. //
  2002. // if the file is already at the destination, we can skip copying
  2003. // this file or just decompress it (and delete the compressed
  2004. // source). In the case where the file is compressed, we may need
  2005. // to tweak the file attributes so that the source file can be
  2006. // successfully retreived.
  2007. //
  2008. wcscpy( szFilepath, g_Options.szInstallationPath );
  2009. ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString );
  2010. ConcatenatePaths( szFilepath, pNode->szFilename );
  2011. if ( !IsFileOrCompressedVersionPresent( szFilepath, &CompressedName )) {
  2012. //
  2013. // It's not already there, so check the source.
  2014. //
  2015. // Note that we don't care if the file is compressed or not, we
  2016. // just want the file to be there, because setupapi can do the
  2017. // rest without any help from us.
  2018. //
  2019. wcscpy( szFilepath, g_Options.szSourcePath );
  2020. ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString );
  2021. ConcatenatePaths( szFilepath, pNode->szFilename );
  2022. if ( !IsFileOrCompressedVersionPresent( szFilepath, &CompressedName )) {
  2023. //
  2024. // it's not there on the source - we must give up
  2025. //
  2026. hr = HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
  2027. MessageBoxFromError( hDlg, pNode->szFilename, ERROR_FILE_NOT_FOUND );
  2028. goto Cleanup;
  2029. }
  2030. } else {
  2031. if (CompressedName) {
  2032. //
  2033. // Make sure we can delete the compressed source file at
  2034. // the destination path since we're going to decompress
  2035. // this file
  2036. //
  2037. DWORD dwAttribs = dwAttribs = GetFileAttributes( CompressedName );
  2038. DebugMsg( "!!compressed name!!: %s\n", CompressedName );
  2039. if ( dwAttribs & FILE_ATTRIBUTE_READONLY )
  2040. {
  2041. dwAttribs &= ~FILE_ATTRIBUTE_READONLY;
  2042. SetFileAttributes( CompressedName, dwAttribs );
  2043. }
  2044. dwConditionalFlags = SP_COPY_DELETESOURCE;
  2045. TraceFree( CompressedName );
  2046. } else {
  2047. //
  2048. // the file is already expanded in the destination - NOP.
  2049. //
  2050. goto DeleteIt;
  2051. }
  2052. }
  2053. // Update UI
  2054. wcscpy( &MyContext.szCopyingString[ MyContext.dwCopyingLength ], pNode->szFilename );
  2055. wcscpy( &MyContext.szCopyingString[ wcslen( MyContext.szCopyingString ) ], L"..." );
  2056. SetWindowText( MyContext.hOperation, MyContext.szCopyingString );
  2057. DebugMsg( "!!COPYING!!: %s\n", szFilepath );
  2058. wcscpy( szDstPath, g_Options.szInstallationPath );
  2059. ConcatenatePaths( szDstPath, g_Options.ProcessorArchitectureString );
  2060. ConcatenatePaths( szDstPath, pNode->szFilename );
  2061. b= SetupInstallFile( NULL,
  2062. NULL,
  2063. szFilepath,
  2064. NULL,
  2065. szDstPath,
  2066. SP_COPY_SOURCE_ABSOLUTE | SP_COPY_NEWER_ONLY
  2067. | SP_COPY_FORCE_NEWER | dwConditionalFlags,
  2068. NULL,
  2069. NULL );
  2070. if ( !b )
  2071. {
  2072. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2073. ErrorBox( hDlg, szFilepath );
  2074. goto Cleanup;
  2075. }
  2076. if ( KeepUIAlive( hDlg ) )
  2077. {
  2078. hr = HRESULT_FROM_WIN32( ERROR_CANCELLED );
  2079. goto Cleanup;
  2080. }
  2081. DeleteIt:
  2082. // Update meter
  2083. MyContext.nCopied++;
  2084. SendMessage( MyContext.hProg, PBM_SETPOS, (5000 * MyContext.nCopied) / MyContext.nToBeCopied, 0 );
  2085. pExtractionList = pNode->Next;
  2086. LocalFree( pNode );
  2087. pNode = pExtractionList;
  2088. }
  2089. }
  2090. //
  2091. // Finally, blow out all the files in these cabs
  2092. //
  2093. dw = LoadString( g_hinstance, IDS_EXPANDING_CABS, szText, ARRAYSIZE(szText));
  2094. Assert( dw );
  2095. SetDlgItemText( hDlg, IDC_S_OPERATION, szText );
  2096. ExpandParams.hDlg = hDlg;
  2097. ExpandParams.hinf = hinfReminst;
  2098. ExpandParams.pszSection = L"CabsToExpand";
  2099. ExpandParams.pszSourcePath = g_Options.szSourcePath;
  2100. ExpandParams.pszDestPath = g_Options.szInstallationPath;
  2101. ExpandParams.pszSubDir = g_Options.ProcessorArchitectureString;
  2102. // Expand CABs in background to keep UI alive
  2103. hThread = CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE) ExpandCabList, (LPVOID) &ExpandParams, NULL, NULL );
  2104. while ( WAIT_TIMEOUT == WaitForSingleObject( hThread, 10 ) )
  2105. {
  2106. KeepUIAlive( hDlg );
  2107. }
  2108. GetExitCodeThread( hThread, (ULONG*)&hr );
  2109. DebugMsg( "Thread Exit Code was 0x%08x\n", hr );
  2110. if ( FAILED( hr ) )
  2111. goto Cleanup;
  2112. Cleanup:
  2113. if ( hThread != NULL )
  2114. CloseHandle( hThread );
  2115. if ( MyContext.pContext )
  2116. SetupTermDefaultQueueCallback( MyContext.pContext );
  2117. if ( Queue != INVALID_HANDLE_VALUE )
  2118. SetupCloseFileQueue( Queue );
  2119. if ( hinfLayout != INVALID_HANDLE_VALUE )
  2120. SetupCloseInfFile( hinfLayout );
  2121. if ( hinfReminst != INVALID_HANDLE_VALUE )
  2122. SetupCloseInfFile( hinfReminst );
  2123. if ( hinfDrivers != INVALID_HANDLE_VALUE )
  2124. SetupCloseInfFile( hinfDrivers );
  2125. if ( hinfDosnet != INVALID_HANDLE_VALUE )
  2126. SetupCloseInfFile( hinfDosnet );
  2127. if ( hBinlsvc != NULL )
  2128. FreeLibrary( hBinlsvc );
  2129. AssertMsg( pExtractionList == NULL, "The list still isn't empty.\n\nThe image will be missing some drivers.\n" );
  2130. while ( pExtractionList )
  2131. {
  2132. PLL_FILES_TO_EXTRACT pNode = pExtractionList;
  2133. pExtractionList = pExtractionList->Next;
  2134. LocalFree( pNode );
  2135. }
  2136. b = DeleteFile( g_Options.szWorkstationRemBootInfPath );
  2137. AssertMsg( b, "Failed to delete temp\\REMINST.INF\nThis was just a warning and can be ignored." );
  2138. g_Options.szWorkstationRemBootInfPath[0] = L'\0';
  2139. SendMessage( hProg, PBM_SETPOS, 5000, 0 );
  2140. SetDlgItemText( hDlg, IDC_S_OPERATION, L"" );
  2141. HRETURN(hr);
  2142. }
  2143. //
  2144. // Modifies registry from the registry section of the REMINST.INF
  2145. //
  2146. HRESULT
  2147. ModifyRegistry( HWND hDlg )
  2148. {
  2149. HRESULT hr = S_OK;
  2150. HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
  2151. WCHAR szText[ SMALL_BUFFER_SIZE ];
  2152. WCHAR szSection[ SMALL_BUFFER_SIZE ];
  2153. WCHAR szFiles[ MAX_PATH ];
  2154. WCHAR szPath[ MAX_PATH ];
  2155. BOOL b;
  2156. DWORD dw;
  2157. WCHAR szRegSrvDlls[ MAX_PATH ];
  2158. UINT spinstFlags = 0;
  2159. TraceFunc( "ModifyRegistry( hDlg )\n" );
  2160. Assert( g_Options.hinf != INVALID_HANDLE_VALUE );
  2161. if ( g_Options.hinf == INVALID_HANDLE_VALUE )
  2162. HRETURN( HRESULT_FROM_WIN32( ERROR_INVALID_HANDLE ) ); // need this handle!
  2163. //
  2164. // Update UI
  2165. //
  2166. SendMessage( hProg, PBM_SETRANGE, 0, MAKELPARAM( 0, 1 ) );
  2167. dw = LoadString( g_hinstance, IDS_UPDATING_REGISTRY, szText, ARRAYSIZE(szText));
  2168. Assert( dw );
  2169. SetDlgItemText( hDlg, IDC_S_OPERATION, szText );
  2170. dw = LoadString( g_hinstance, IDS_INF_SECTION, szSection, ARRAYSIZE(szSection));
  2171. Assert( dw );
  2172. //
  2173. // Process the INF's registry section
  2174. //
  2175. if ( !g_Options.fRegistryIntact ) {
  2176. spinstFlags |= SPINST_REGISTRY;
  2177. }
  2178. if ( !g_Options.fRegSrvDllsRegistered ) {
  2179. spinstFlags |= SPINST_REGSVR;
  2180. }
  2181. b = SetupInstallFromInfSection( hDlg, // hwndOwner
  2182. g_Options.hinf, // inf handle
  2183. szSection, // name of component
  2184. spinstFlags,
  2185. NULL, // relative key root
  2186. NULL, // source root path
  2187. 0, // copy flags
  2188. NULL, // callback routine
  2189. NULL, // callback routine context
  2190. NULL, // device info set
  2191. NULL); // device info struct
  2192. if ( !b ) {
  2193. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2194. ErrorBox( hDlg, szSection );
  2195. goto Error;
  2196. }
  2197. //
  2198. // Add the Reg Key for TFTPD
  2199. //
  2200. if ( !g_Options.fTFTPDDirectoryFound ) {
  2201. HKEY hkey;
  2202. dw = LoadString( g_hinstance, IDS_TFTPD_SERVICE_PARAMETERS, szPath, ARRAYSIZE(szPath));
  2203. Assert( dw );
  2204. if ( ERROR_SUCCESS == RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  2205. szPath,
  2206. 0, // options
  2207. NULL, // class
  2208. 0, // options
  2209. KEY_WRITE,
  2210. NULL, // security
  2211. &hkey,
  2212. &dw ) ) { // disposition
  2213. ULONG lLen;
  2214. DWORD dwType;
  2215. LONG lErr;
  2216. // paranoid
  2217. Assert( wcslen(g_Options.szIntelliMirrorPath) < ARRAYSIZE(g_Options.szIntelliMirrorPath));
  2218. lLen = lstrlen( g_Options.szIntelliMirrorPath ) * sizeof(WCHAR);
  2219. lErr = RegSetValueEx( hkey,
  2220. L"Directory",
  2221. 0, // reserved
  2222. REG_SZ,
  2223. (LPBYTE) g_Options.szIntelliMirrorPath,
  2224. lLen );
  2225. if ( lErr == ERROR_SUCCESS ) {
  2226. DebugMsg( "TFTPD's Directory RegKey set.\n" );
  2227. } else {
  2228. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2229. ErrorBox( hDlg, szPath );
  2230. DebugMsg( "HKLM\\%s could be not created.\n", szPath );
  2231. goto Error;
  2232. }
  2233. RegCloseKey( hkey );
  2234. } else {
  2235. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2236. ErrorBox( hDlg, szPath );
  2237. DebugMsg( "HKLM\\%s could be not created.\n", szPath );
  2238. goto Error;
  2239. }
  2240. }
  2241. Error:
  2242. SendMessage( hProg, PBM_SETPOS, 1 , 0 );
  2243. SetDlgItemText( hDlg, IDC_S_OPERATION, L"" );
  2244. HRETURN(hr);
  2245. }
  2246. //
  2247. // Stop a specific service
  2248. //
  2249. HRESULT
  2250. StopRBService(
  2251. HWND hDlg,
  2252. SC_HANDLE schSystem,
  2253. LPWSTR pszService
  2254. )
  2255. {
  2256. HRESULT hr = S_OK;
  2257. SC_HANDLE schService = NULL;
  2258. SERVICE_STATUS ssStatus;
  2259. BOOL b;
  2260. DWORD dwErr;
  2261. TraceFunc( "StopRBService( ... )\n" );
  2262. Assert( schSystem );
  2263. Assert( pszService );
  2264. schService = OpenService( schSystem,
  2265. pszService,
  2266. SERVICE_STOP | SERVICE_QUERY_STATUS );
  2267. if ( !schService ) {
  2268. goto Cleanup;
  2269. }
  2270. b = ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus );
  2271. #define SLEEP_TIME 2000
  2272. #define LOOP_COUNT 30
  2273. if ( !b && GetLastError() != ERROR_SERVICE_NOT_ACTIVE ) {
  2274. dwErr = GetLastError( );
  2275. } else {
  2276. DWORD loopCount = 0;
  2277. do {
  2278. b = QueryServiceStatus( schService, &ssStatus);
  2279. if ( !b ) {
  2280. goto Cleanup;
  2281. }
  2282. if (ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
  2283. if ( loopCount++ == LOOP_COUNT ) {
  2284. dwErr = ERROR_SERVICE_REQUEST_TIMEOUT;
  2285. break;
  2286. }
  2287. Sleep( SLEEP_TIME );
  2288. } else {
  2289. if ( ssStatus.dwCurrentState != SERVICE_STOPPED ) {
  2290. dwErr = ssStatus.dwWin32ExitCode;
  2291. if ( dwErr == ERROR_SERVICE_SPECIFIC_ERROR ) {
  2292. dwErr = ssStatus.dwServiceSpecificExitCode;
  2293. }
  2294. } else {
  2295. dwErr = NO_ERROR;
  2296. }
  2297. break;
  2298. }
  2299. } while ( TRUE );
  2300. }
  2301. Cleanup:
  2302. if ( schService )
  2303. CloseServiceHandle( schService );
  2304. HRETURN(hr);
  2305. }
  2306. //
  2307. // Start a specific service
  2308. //
  2309. HRESULT
  2310. StartRBService(
  2311. HWND hDlg,
  2312. SC_HANDLE schSystem,
  2313. LPWSTR pszService,
  2314. LPWSTR pszServiceName,
  2315. LPWSTR pszServiceDescription )
  2316. {
  2317. HRESULT hr = S_OK;
  2318. SC_HANDLE schService = NULL;
  2319. SERVICE_STATUS ssStatus;
  2320. BOOL b;
  2321. DWORD dwErr;
  2322. TraceFunc( "StartRBService( ... )\n" );
  2323. Assert( schSystem );
  2324. Assert( pszService );
  2325. Assert( pszServiceName );
  2326. schService = OpenService( schSystem,
  2327. pszService,
  2328. SERVICE_ALL_ACCESS );
  2329. if ( !schService ) {
  2330. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2331. ErrorBox( hDlg, pszServiceName );
  2332. goto Cleanup;
  2333. }
  2334. b = ChangeServiceConfig( schService,
  2335. SERVICE_NO_CHANGE,
  2336. SERVICE_AUTO_START,
  2337. SERVICE_NO_CHANGE,
  2338. NULL,
  2339. NULL,
  2340. NULL,
  2341. NULL,
  2342. NULL,
  2343. NULL,
  2344. NULL );
  2345. if ( !b ) {
  2346. ErrorBox( hDlg, pszServiceName );
  2347. hr = THR(S_FALSE);
  2348. }
  2349. // If the service is paused, continue it; else try to start it.
  2350. b = QueryServiceStatus( schService, &ssStatus);
  2351. if ( !b ) {
  2352. ErrorBox( hDlg, pszServiceName );
  2353. hr = THR(S_FALSE);
  2354. goto Cleanup;
  2355. }
  2356. if ( ssStatus.dwCurrentState == SERVICE_PAUSED ) {
  2357. b = ControlService( schService, SERVICE_CONTROL_CONTINUE, &ssStatus );
  2358. } else {
  2359. b = StartService( schService, 0, NULL );
  2360. }
  2361. #define SLEEP_TIME 2000
  2362. #define LOOP_COUNT 30
  2363. if ( !b ) {
  2364. dwErr = GetLastError( );
  2365. } else {
  2366. DWORD loopCount = 0;
  2367. do {
  2368. b = QueryServiceStatus( schService, &ssStatus);
  2369. if ( !b ) {
  2370. ErrorBox( hDlg, pszServiceName );
  2371. hr = THR(S_FALSE);
  2372. goto Cleanup;
  2373. }
  2374. if ( ssStatus.dwCurrentState != SERVICE_RUNNING ) {
  2375. if ( loopCount++ == LOOP_COUNT ) {
  2376. if ( (ssStatus.dwCurrentState == SERVICE_CONTINUE_PENDING) ||
  2377. (ssStatus.dwCurrentState == SERVICE_START_PENDING) ) {
  2378. dwErr = ERROR_SERVICE_REQUEST_TIMEOUT;
  2379. } else {
  2380. dwErr = ssStatus.dwWin32ExitCode;
  2381. if ( dwErr == ERROR_SERVICE_SPECIFIC_ERROR ) {
  2382. dwErr = ssStatus.dwServiceSpecificExitCode;
  2383. }
  2384. }
  2385. break;
  2386. }
  2387. Sleep( SLEEP_TIME );
  2388. } else {
  2389. dwErr = NO_ERROR;
  2390. break;
  2391. }
  2392. } while ( TRUE );
  2393. }
  2394. if ( dwErr != NO_ERROR ) {
  2395. switch ( dwErr )
  2396. {
  2397. default:
  2398. hr = THR( HRESULT_FROM_WIN32( dwErr ) );
  2399. MessageBoxFromError( hDlg, pszServiceName, dwErr );
  2400. break;
  2401. case ERROR_SERVICE_ALREADY_RUNNING:
  2402. {
  2403. // Attempt to HUP the service
  2404. SERVICE_STATUS ss;
  2405. ControlService( schService, SERVICE_CONTROL_INTERROGATE, &ss );
  2406. }
  2407. break;
  2408. }
  2409. }
  2410. else {
  2411. // There is a pathological case where the service is deleted and then risetup restarts it. When it does so, it doesn't set the description string.
  2412. // We check here if there is a description for the service and if not we give it one.
  2413. // We can't do this in CreateRemoteBootServices beacuse the services must be started.
  2414. SERVICE_DESCRIPTION description;
  2415. DWORD bytes_needed;
  2416. if( QueryServiceConfig2( schService, SERVICE_CONFIG_DESCRIPTION, ( LPBYTE )&description, sizeof( description ), &bytes_needed )) {
  2417. // Now, if there were a description the previous call would have failed with a ERROR_INSUFFICIENT_BUFFER error.
  2418. // We do a quick check to make sure that everything is valid.
  2419. Assert( description.lpDescription == NULL );
  2420. // Now we can change it.
  2421. description.lpDescription = pszServiceDescription;
  2422. ChangeServiceConfig2( schService, SERVICE_CONFIG_DESCRIPTION, &description );
  2423. // If that caused an error, we'll ignore it since the description is not essential to the operation of RIS.
  2424. }
  2425. // Whatever error the query threw we don't care as the description isn't sufficiently vital to RIS.
  2426. }
  2427. Cleanup:
  2428. if ( schService )
  2429. CloseServiceHandle( schService );
  2430. HRETURN(hr);
  2431. }
  2432. //
  2433. // Start the services needed for remote boot.
  2434. //
  2435. HRESULT
  2436. StartRemoteBootServices( HWND hDlg )
  2437. {
  2438. WCHAR szService[ SMALL_BUFFER_SIZE ];
  2439. WCHAR szServiceName[ SMALL_BUFFER_SIZE ];
  2440. WCHAR szServiceDescription[ 1024 ]; // Size is the maximum allowed by ChangeServiceConfig2
  2441. WCHAR szText[ SMALL_BUFFER_SIZE ];
  2442. SC_HANDLE schSystem;
  2443. HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
  2444. DWORD dw;
  2445. HRESULT hr;
  2446. HRESULT hrFatalError = S_OK;
  2447. HRESULT hrStartFailure = S_OK;
  2448. HWND hOper = GetDlgItem( hDlg, IDC_S_OPERATION );
  2449. TraceFunc( "StartRemoteBootServices( hDlg )\n" );
  2450. SendMessage( hProg, PBM_SETRANGE, 0, MAKELPARAM( 0, 2 ) );
  2451. SendMessage( hProg, PBM_SETPOS, 0, 0 );
  2452. dw = LoadString( g_hinstance, IDS_STARTING_SERVICES, szText, ARRAYSIZE(szText));
  2453. Assert( dw );
  2454. SetDlgItemText( hDlg, IDC_S_OPERATION, szText );
  2455. schSystem = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
  2456. Assert( schSystem );
  2457. if ( !schSystem ) {
  2458. hrFatalError = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2459. WCHAR szCaption[SMALL_BUFFER_SIZE];
  2460. DWORD dw;
  2461. dw = LoadString( g_hinstance, IDS_OPENING_SERVICE_MANAGER_TITLE, szCaption, SMALL_BUFFER_SIZE );
  2462. Assert( dw );
  2463. ErrorBox( hDlg, szCaption );
  2464. goto Cleanup;
  2465. }
  2466. //
  2467. // start TFTPD services
  2468. //
  2469. dw = LoadString( g_hinstance, IDS_TFTPD_SERVICENAME, szServiceName, ARRAYSIZE(szServiceName));
  2470. Assert( dw );
  2471. dw = LoadString( g_hinstance, IDS_TFTPD_DESCRIPTION, szServiceDescription, ARRAYSIZE(szServiceDescription));
  2472. Assert( dw );
  2473. SetWindowText( hOper, szServiceName );
  2474. hr = StartRBService( hDlg, schSystem, L"TFTPD", szServiceName, szServiceDescription );
  2475. if ( FAILED(hr) ) {
  2476. hrFatalError = hr;
  2477. goto Cleanup;
  2478. } else if ( hr != S_OK ) {
  2479. hrStartFailure = hr;
  2480. }
  2481. //
  2482. // start BINLSVC services
  2483. //
  2484. dw = LoadString( g_hinstance, IDS_BINL_SERVICENAME, szServiceName, ARRAYSIZE(szServiceName));
  2485. Assert( dw );
  2486. dw = LoadString( g_hinstance, IDS_BINL_DESCRIPTION, szServiceDescription, ARRAYSIZE(szServiceDescription));
  2487. Assert( dw );
  2488. SetWindowText( hOper, szServiceName );
  2489. if (!g_Options.fBINLSCPFound) {
  2490. StopRBService( hDlg, schSystem, L"BINLSVC" );
  2491. }
  2492. hr = StartRBService( hDlg, schSystem, L"BINLSVC", szServiceName, szServiceDescription );
  2493. if ( FAILED(hr) ) {
  2494. hrFatalError = hr;
  2495. goto Cleanup;
  2496. } else if ( hr != S_OK ) {
  2497. hrStartFailure = hr;
  2498. }
  2499. //
  2500. // start GROVELER services
  2501. //
  2502. dw = LoadString( g_hinstance, IDS_SISGROVELER_SERVICENAME, szServiceName, ARRAYSIZE(szServiceName));
  2503. Assert( dw );
  2504. dw = LoadString( g_hinstance, IDS_SISGROVELER_DESCRIPTION, szServiceDescription, ARRAYSIZE(szServiceDescription));
  2505. Assert( dw );
  2506. SetWindowText( hOper, szServiceName );
  2507. hr = StartRBService( hDlg, schSystem, L"GROVELER", szServiceName, szServiceDescription );
  2508. if ( FAILED(hr) ) {
  2509. hrFatalError = hr;
  2510. goto Cleanup;
  2511. } else if ( hr != S_OK ) {
  2512. hrStartFailure = hr;
  2513. }
  2514. Cleanup:
  2515. SetDlgItemText( hDlg, IDC_S_OPERATION, L"" );
  2516. if ( schSystem )
  2517. CloseServiceHandle( schSystem );
  2518. if ( hrFatalError != S_OK ) {
  2519. hr = hrFatalError;
  2520. } else if ( hrStartFailure != S_OK ) {
  2521. hr = hrStartFailure;
  2522. } else {
  2523. hr = S_OK;
  2524. }
  2525. RETURN(hr);
  2526. }
  2527. //
  2528. // create IntelliMirror share
  2529. //
  2530. HRESULT
  2531. CreateRemoteBootShare( HWND hDlg )
  2532. {
  2533. SHARE_INFO_502 si502;
  2534. SHARE_INFO_1005 si1005;
  2535. WCHAR szRemark[ SMALL_BUFFER_SIZE ];
  2536. WCHAR szRemoteBoot[ SMALL_BUFFER_SIZE ];
  2537. WCHAR szText[ SMALL_BUFFER_SIZE ];
  2538. WCHAR szPath[ 129 ];
  2539. DWORD dwErr;
  2540. HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
  2541. DWORD dw;
  2542. HRESULT hr;
  2543. TraceFunc( "CreateRemoteBootShare( hDlg )\n" );
  2544. dw = LoadString( g_hinstance, IDS_CREATINGSHARES, szText, ARRAYSIZE(szText));
  2545. Assert( dw );
  2546. SetDlgItemText( hDlg, IDC_S_OPERATION, szText );
  2547. dw = LoadString( g_hinstance, IDS_REMOTEBOOTSHAREREMARK, szRemark, ARRAYSIZE(szRemark));
  2548. Assert( dw );
  2549. dw = LoadString( g_hinstance, IDS_REMOTEBOOTSHARENAME, szRemoteBoot, ARRAYSIZE(szRemoteBoot));
  2550. Assert( dw );
  2551. wcscpy( szPath, g_Options.szIntelliMirrorPath );
  2552. if ( wcslen( szPath ) == 2 ) {
  2553. wcscat( szPath, L"\\" );
  2554. }
  2555. si502.shi502_netname = szRemoteBoot;
  2556. si502.shi502_type = STYPE_DISKTREE;
  2557. si502.shi502_remark = szRemark;
  2558. si502.shi502_permissions = ACCESS_ALL;
  2559. si502.shi502_max_uses = -1; // unlimited
  2560. si502.shi502_current_uses = 0;
  2561. si502.shi502_path = szPath;
  2562. si502.shi502_passwd = NULL; // ignored
  2563. si502.shi502_reserved = 0; // must be zero
  2564. si502.shi502_security_descriptor = NULL;
  2565. Assert( wcslen(g_Options.szIntelliMirrorPath) < ARRAYSIZE(g_Options.szIntelliMirrorPath) ); // paranoid
  2566. dwErr = NetShareAdd( NULL, 502, (LPBYTE) &si502, NULL );
  2567. switch ( dwErr )
  2568. {
  2569. // ignore these
  2570. case NERR_Success:
  2571. case NERR_DuplicateShare:
  2572. dwErr = ERROR_SUCCESS;
  2573. break;
  2574. default:
  2575. MessageBoxFromError( hDlg, g_Options.szIntelliMirrorPath, dwErr );
  2576. goto Error;
  2577. }
  2578. #ifdef REMOTE_BOOT
  2579. #error("Remote boot is dead!! Turn off the REMOTE_BOOT flag.")
  2580. si1005.shi1005_flags = CSC_CACHE_AUTO_REINT;
  2581. NetShareSetInfo( NULL, szRemoteBoot, 1005, (LPBYTE)&si1005, &dwErr );
  2582. switch ( dwErr )
  2583. {
  2584. // ignore these
  2585. case NERR_Success:
  2586. dwErr = ERROR_SUCCESS;
  2587. break;
  2588. default:
  2589. MessageBoxFromError( hDlg, g_Options.szIntelliMirrorPath, dwErr );
  2590. }
  2591. #endif // REMOTE_BOOT
  2592. Error:
  2593. hr = THR( HRESULT_FROM_WIN32(dwErr) );
  2594. HRETURN(hr);
  2595. }
  2596. typedef int (WINAPI * REGISTERDLL)( void );
  2597. //
  2598. // Register Dlls
  2599. //
  2600. // If hDlg is NULL, this will fail silently.
  2601. //
  2602. HRESULT
  2603. RegisterDll( HWND hDlg, LPWSTR pszDLLPath )
  2604. {
  2605. REGISTERDLL pfnRegisterDll = NULL;
  2606. HINSTANCE hLib;
  2607. HRESULT hr = S_OK;
  2608. TraceFunc( "RegisterDll( ... )\n" );
  2609. //
  2610. // We'll try to register it locally, but if fails MMC should
  2611. // grab it from the DS and register it on the machine.
  2612. //
  2613. hLib = LoadLibrary( pszDLLPath );
  2614. AssertMsg( hLib, "RegisterDll: Missing DLL?" );
  2615. if ( !hLib ) {
  2616. hr = S_FALSE;
  2617. goto Cleanup;
  2618. }
  2619. pfnRegisterDll = (REGISTERDLL) GetProcAddress( hLib, "DllRegisterServer" );
  2620. AssertMsg( pfnRegisterDll, "RegisterDll: Missing entry point?" );
  2621. if ( pfnRegisterDll != NULL )
  2622. {
  2623. hr = THR( pfnRegisterDll() );
  2624. if ( FAILED(hr) && hDlg ) {
  2625. MessageBoxFromStrings( hDlg,
  2626. IDS_REGISTER_IMADMIU_FAILED_CAPTION,
  2627. IDS_REGISTER_IMADMIU_FAILED_TEXT,
  2628. MB_OK );
  2629. }
  2630. }
  2631. FreeLibrary( hLib );
  2632. Cleanup:
  2633. HRETURN(hr);
  2634. }
  2635. //
  2636. // Creates the services needed for remote boot.
  2637. //
  2638. HRESULT
  2639. CreateRemoteBootServices( HWND hDlg )
  2640. {
  2641. HRESULT hr = S_OK;
  2642. WCHAR szServiceName[ SMALL_BUFFER_SIZE ]; // TFTPD service name
  2643. WCHAR szText[ SMALL_BUFFER_SIZE ]; // general use
  2644. WCHAR szGroup[ SMALL_BUFFER_SIZE ];
  2645. CHAR szIntelliMirrorDrive[ 3 ]; // eg. "D:" - ASCII not UNICODE
  2646. SC_HANDLE schSystem; // Handle to System Services
  2647. SC_HANDLE schService; // Temp handle to new service
  2648. DWORD dw; // general use
  2649. LPARAM lRange;
  2650. HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
  2651. HWND hOper = GetDlgItem( hDlg, IDC_S_OPERATION );
  2652. TraceFunc( "CreateRemoteBootServices( hDlg )\n" );
  2653. lRange = 0;
  2654. if ( !g_Options.fBINLServiceInstalled ) {
  2655. lRange++;
  2656. }
  2657. if ( !g_Options.fBINLSCPFound ) {
  2658. lRange++;
  2659. }
  2660. if ( !g_Options.fTFTPDServiceInstalled ) {
  2661. lRange++;
  2662. }
  2663. if ( !g_Options.fSISServiceInstalled ) {
  2664. lRange++;
  2665. }
  2666. lRange = MAKELPARAM( 0, lRange );
  2667. SendMessage( hProg, PBM_SETRANGE, 0, lRange );
  2668. SendMessage( hProg, PBM_SETPOS, 0, 0 );
  2669. //
  2670. // Display what we are doing in operations area
  2671. //
  2672. dw = LoadString( g_hinstance, IDS_STARTING_SERVICES, szText, ARRAYSIZE(szText));
  2673. Assert( dw );
  2674. SetWindowText( hOper, szText );
  2675. //
  2676. // Open System Services Manager
  2677. //
  2678. schSystem = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
  2679. Assert( schSystem );
  2680. if ( !schSystem ) {
  2681. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2682. WCHAR szCaption[SMALL_BUFFER_SIZE];
  2683. DWORD dw;
  2684. dw = LoadString( g_hinstance, IDS_OPENING_SERVICE_MANAGER_TITLE, szCaption, SMALL_BUFFER_SIZE );
  2685. Assert( dw );
  2686. ErrorBox( hDlg, szCaption );
  2687. goto Cleanup;
  2688. }
  2689. //
  2690. // Create TFTPD service
  2691. //
  2692. if ( !g_Options.fTFTPDServiceInstalled ) {
  2693. dw = LoadString( g_hinstance, IDS_TFTPD_SERVICENAME, szServiceName, ARRAYSIZE(szServiceName));
  2694. Assert( dw );
  2695. dw = LoadString( g_hinstance, IDS_TFTPD, szText, ARRAYSIZE(szText));
  2696. Assert( dw );
  2697. SetWindowText( hOper, szServiceName );
  2698. dw = LoadString( g_hinstance, IDS_TFTPD_PATH, szText, ARRAYSIZE(szText));
  2699. Assert( dw );
  2700. schService = CreateService(
  2701. schSystem,
  2702. L"TFTPD",
  2703. szServiceName,
  2704. STANDARD_RIGHTS_REQUIRED | SERVICE_START,
  2705. SERVICE_WIN32_OWN_PROCESS,
  2706. SERVICE_AUTO_START,
  2707. SERVICE_ERROR_NORMAL,
  2708. szText,
  2709. NULL,
  2710. NULL,
  2711. L"Tcpip\0",
  2712. NULL,
  2713. NULL );
  2714. if ( !schService ) {
  2715. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2716. ErrorBox( hDlg, szServiceName );
  2717. } else {
  2718. CloseServiceHandle( schService );
  2719. }
  2720. SendMessage( hProg, PBM_DELTAPOS, 1 , 0 );
  2721. }
  2722. //
  2723. // Create BINLSVC
  2724. //
  2725. if ( !g_Options.fBINLServiceInstalled ) {
  2726. dw = LoadString( g_hinstance, IDS_BINL_SERVICENAME, szServiceName, ARRAYSIZE(szServiceName));
  2727. Assert( dw );
  2728. SetWindowText( hOper, szServiceName );
  2729. dw = LoadString( g_hinstance, IDS_BINL_PATH, szText, ARRAYSIZE(szText));
  2730. Assert( dw );
  2731. schService = CreateService(
  2732. schSystem,
  2733. L"BINLSVC",
  2734. szServiceName,
  2735. STANDARD_RIGHTS_REQUIRED | SERVICE_START,
  2736. SERVICE_WIN32_SHARE_PROCESS,
  2737. SERVICE_AUTO_START,
  2738. SERVICE_ERROR_NORMAL,
  2739. szText,
  2740. NULL,
  2741. NULL,
  2742. L"Tcpip\0LanmanServer\0",
  2743. NULL,
  2744. NULL );
  2745. if ( !schService ) {
  2746. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2747. ErrorBox( hDlg, szServiceName );
  2748. } else {
  2749. CloseServiceHandle( schService );
  2750. }
  2751. SendMessage( hProg, PBM_DELTAPOS, 1 , 0 );
  2752. }
  2753. //
  2754. // Create SIS
  2755. //
  2756. if ( !g_Options.fSISServiceInstalled ) {
  2757. dw = LoadString( g_hinstance, IDS_SIS_SERVICENAME, szServiceName, ARRAYSIZE(szServiceName));
  2758. Assert( dw );
  2759. SetWindowText( hOper, szServiceName );
  2760. dw = LoadString( g_hinstance, IDS_SIS_PATH, szText, ARRAYSIZE(szText));
  2761. Assert( dw );
  2762. dw = LoadString( g_hinstance, IDS_SIS_GROUP, szGroup, ARRAYSIZE(szGroup));
  2763. Assert( dw );
  2764. schService = CreateService(
  2765. schSystem,
  2766. L"SIS",
  2767. szServiceName,
  2768. STANDARD_RIGHTS_REQUIRED | SERVICE_START,
  2769. SERVICE_FILE_SYSTEM_DRIVER,
  2770. SERVICE_BOOT_START,
  2771. SERVICE_ERROR_NORMAL,
  2772. szText,
  2773. szGroup,
  2774. NULL,
  2775. NULL,
  2776. NULL,
  2777. NULL );
  2778. if ( !schService ) {
  2779. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2780. ErrorBox( hDlg, szServiceName );
  2781. } else {
  2782. CloseServiceHandle( schService );
  2783. }
  2784. SendMessage( hProg, PBM_DELTAPOS, 1 , 0 );
  2785. }
  2786. //
  2787. // Create SIS Groveler
  2788. //
  2789. if ( !g_Options.fSISGrovelerServiceInstalled ) {
  2790. dw = LoadString( g_hinstance, IDS_SISGROVELER_SERVICENAME, szServiceName, ARRAYSIZE(szServiceName));
  2791. Assert( dw );
  2792. SetWindowText( hOper, szServiceName );
  2793. dw = LoadString( g_hinstance, IDS_SISGROVELER_PATH, szText, ARRAYSIZE(szText));
  2794. Assert( dw );
  2795. dw = LoadString( g_hinstance, IDS_SISGROVELER_GROUP, szGroup, ARRAYSIZE(szGroup));
  2796. Assert( dw );
  2797. schService = CreateService(
  2798. schSystem,
  2799. L"Groveler",
  2800. szServiceName,
  2801. STANDARD_RIGHTS_REQUIRED | SERVICE_START,
  2802. SERVICE_WIN32_OWN_PROCESS,
  2803. SERVICE_AUTO_START,
  2804. SERVICE_ERROR_NORMAL,
  2805. szText,
  2806. NULL,
  2807. NULL,
  2808. L"SIS\0",
  2809. NULL,
  2810. NULL );
  2811. if ( !schService ) {
  2812. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2813. ErrorBox( hDlg, szServiceName );
  2814. } else {
  2815. CloseServiceHandle( schService );
  2816. }
  2817. SendMessage( hProg, PBM_DELTAPOS, 1 , 0 );
  2818. }
  2819. //
  2820. // Create the BINL SCP
  2821. //
  2822. if ( !g_Options.fBINLSCPFound ) {
  2823. dw = LoadString( g_hinstance, IDS_BINL_SERVICECONTROLPOINT, szText, ARRAYSIZE(szText) );
  2824. Assert( dw );
  2825. SetWindowText( hOper, szText );
  2826. hr = CreateSCP( hDlg );
  2827. SendMessage( hProg, PBM_DELTAPOS, 1 , 0 );
  2828. }
  2829. Cleanup:
  2830. SetDlgItemText( hDlg, IDC_S_OPERATION, L"" );
  2831. HRETURN(hr);
  2832. }
  2833. //
  2834. // Reads the server's layout.inf file for disc name, tag file and
  2835. // optional sub-dir. All parameters are assumed to be MAX_PATH in
  2836. // size except the tag files which can only be 10.3 format.
  2837. //
  2838. HRESULT
  2839. RetrieveServerDiscInfo(
  2840. HWND hDlg,
  2841. LPWSTR pszDiscName,
  2842. LPWSTR pszTagFile,
  2843. LPWSTR pszSubDir )
  2844. {
  2845. TraceFunc("RetrieveServerDiscInfo()\n");
  2846. HRESULT hr = S_OK;
  2847. HINF hinf = INVALID_HANDLE_VALUE;
  2848. UINT uLineNum;
  2849. INFCONTEXT context;
  2850. WCHAR szSourcePath[ MAX_PATH ];
  2851. BOOL b;
  2852. if ( !GetEnvironmentVariable(L"windir", szSourcePath, ARRAYSIZE(szSourcePath)) )
  2853. {
  2854. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2855. ErrorBox( hDlg, szSourcePath );
  2856. goto Cleanup;
  2857. }
  2858. wcscat( szSourcePath, L"\\inf\\layout.inf" );
  2859. hinf = SetupOpenInfFile( szSourcePath, NULL, INF_STYLE_WIN4, &uLineNum);
  2860. if ( hinf == INVALID_HANDLE_VALUE ) {
  2861. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2862. ErrorBox( hDlg, szSourcePath );
  2863. goto Cleanup;
  2864. }
  2865. b = FALSE;
  2866. if ( g_Options.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL ) {
  2867. b = SetupFindFirstLine( hinf, L"SourceDisksNames.x86", L"1", &context );
  2868. } else if ( g_Options.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 ) {
  2869. b = SetupFindFirstLine( hinf, L"SourceDisksNames.ia64", L"1", &context );
  2870. }
  2871. if ( !b )
  2872. {
  2873. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2874. ErrorBox( hDlg, szSourcePath );
  2875. goto Cleanup;
  2876. }
  2877. if ( pszDiscName ) {
  2878. b = SetupGetStringField( &context, 1, pszDiscName, MAX_PATH, NULL );
  2879. if ( !b )
  2880. {
  2881. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2882. ErrorBox( hDlg, szSourcePath );
  2883. goto Cleanup;
  2884. }
  2885. }
  2886. if ( pszTagFile )
  2887. {
  2888. b = SetupGetStringField( &context, 2, pszTagFile, 14 /* 10.3 + NULL */, NULL );
  2889. if ( !b )
  2890. {
  2891. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2892. ErrorBox( hDlg, szSourcePath );
  2893. goto Cleanup;
  2894. }
  2895. }
  2896. if ( pszSubDir )
  2897. {
  2898. b = SetupGetStringField( &context, 4, pszSubDir, MAX_PATH, NULL );
  2899. if ( !b )
  2900. {
  2901. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2902. ErrorBox( hDlg, szSourcePath );
  2903. goto Cleanup;
  2904. }
  2905. }
  2906. Cleanup:
  2907. if ( hinf != INVALID_HANDLE_VALUE )
  2908. SetupCloseInfFile( hinf );
  2909. HRETURN(hr);
  2910. }
  2911. //
  2912. // Copies the files needed by the server from where the server
  2913. // was orginally installed from.
  2914. //
  2915. HRESULT
  2916. CopyServerFiles( HWND hDlg )
  2917. {
  2918. HRESULT hr = S_OK;
  2919. HSPFILEQ Queue = INVALID_HANDLE_VALUE;
  2920. WCHAR szSection[ SMALL_BUFFER_SIZE ];
  2921. HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
  2922. DWORD dwCount = 0;
  2923. DWORD dw;
  2924. BOOL b;
  2925. UINT iResult;
  2926. WCHAR szServerDiscName[ MAX_PATH ] = { L'\0' };
  2927. MYCONTEXT MyContext;
  2928. INFCONTEXT context;
  2929. UINT uLineNum;
  2930. ZeroMemory( &MyContext, sizeof(MyContext) );
  2931. TraceFunc( "CopyServerFiles( hDlg )\n" );
  2932. Assert( g_Options.hinf != INVALID_HANDLE_VALUE );
  2933. if ( g_Options.hinf == INVALID_HANDLE_VALUE ) {
  2934. hr = E_FAIL; // need this handle!
  2935. goto Cleanup;
  2936. }
  2937. //
  2938. // Setup and display next section of dialog
  2939. //
  2940. SendMessage( hProg, PBM_SETRANGE, 0, MAKELPARAM(0, 5000 ));
  2941. SendMessage( hProg, PBM_SETPOS, 0, 0 );
  2942. //
  2943. // Ask for CD if any of the Services files are missing.
  2944. // Or if the System32\RemBoot directory is missing and we
  2945. // need the OS Chooser files (not screens).
  2946. //
  2947. if ( !g_Options.fBINLFilesFound
  2948. || !g_Options.fTFTPDFilesFound
  2949. || !g_Options.fSISFilesFound
  2950. || !g_Options.fSISGrovelerFilesFound
  2951. || !g_Options.fRegSrvDllsFilesFound
  2952. || ( !g_Options.fRemBootDirectory && !g_Options.fOSChooserInstalled ) ) {
  2953. WCHAR szSourcePath[ MAX_PATH ];
  2954. WCHAR szServerTagFile[ 14 ] = { L'\0' };
  2955. WCHAR szInsertMedia[ 64 ];
  2956. WCHAR szServerSubDir[ MAX_PATH ] = { L'\0' };
  2957. DebugMsg( "Queue and copy reminst files\n" );
  2958. //
  2959. // Ask user to check the CDROM to make sure the right CD is in the drive.
  2960. // We skip this if it was installed from a share.
  2961. //
  2962. dw = LoadString( g_hinstance, IDS_INSERT_MEDIA, szInsertMedia, ARRAYSIZE(szInsertMedia) );
  2963. Assert( dw );
  2964. hr = RetrieveServerDiscInfo( hDlg, szServerDiscName, szServerTagFile, szServerSubDir );
  2965. // if it fails, try to proceed anyway to see if the user is smart enough
  2966. // to fix the problem.
  2967. iResult = SetupPromptForDisk( hDlg, // parent window of the dialog box
  2968. szInsertMedia, // optional, title of the dialog box
  2969. szServerDiscName, // optional, name of disk to insert
  2970. NULL, // optional, expected source path
  2971. szServerTagFile, // name of file needed
  2972. szServerTagFile, // optional, source media tag file
  2973. IDF_CHECKFIRST | IDF_NODETAILS | IDF_NOSKIP, // specifies dialog box behavior
  2974. szSourcePath, // receives the source location
  2975. MAX_PATH, // size of the supplied buffer
  2976. NULL ); // optional, buffer size needed
  2977. if ( iResult != DPROMPT_SUCCESS )
  2978. {
  2979. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  2980. goto Cleanup;
  2981. }
  2982. dw = LoadString( g_hinstance, IDS_INF_SECTION, szSection, ARRAYSIZE(szSection) );
  2983. Assert( dw );
  2984. //
  2985. // Create the Queue
  2986. //
  2987. Queue = SetupOpenFileQueue( );
  2988. //
  2989. // Add the files
  2990. //
  2991. b = SetupInstallFilesFromInfSection( g_Options.hinf,
  2992. NULL,
  2993. Queue,
  2994. szSection,
  2995. szSourcePath,
  2996. SP_COPY_WARNIFSKIP | SP_COPY_FORCE_NEWER
  2997. | SP_COPY_NEWER_ONLY ); // copy flags
  2998. Assert( b );
  2999. if ( !b ) {
  3000. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3001. ErrorBox( hDlg, szSection );
  3002. goto Cleanup;
  3003. }
  3004. //
  3005. // Add a section that is done during textmode setup
  3006. //
  3007. b = SetupQueueCopySection( Queue,
  3008. szSourcePath,
  3009. g_Options.hinf,
  3010. NULL,
  3011. L"REMINST.OtherSystemFiles",
  3012. SP_COPY_WARNIFSKIP | SP_COPY_FORCE_NEWER
  3013. | SP_COPY_NEWER_ONLY ); // copy flags
  3014. Assert( b );
  3015. if ( !b ) {
  3016. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3017. ErrorBox( hDlg, L"REMINST.OtherSystemFiles" );
  3018. goto Cleanup;
  3019. }
  3020. //
  3021. // This information will be passed to CopyFileCallback() as
  3022. // the Context.
  3023. //
  3024. MyContext.nToBeCopied = 12; // todo: generate this dynamically
  3025. MyContext.nCopied = 0;
  3026. MyContext.pContext = SetupInitDefaultQueueCallback( hDlg );
  3027. MyContext.hProg = hProg;
  3028. MyContext.hOperation = GetDlgItem( hDlg, IDC_S_OPERATION );
  3029. MyContext.hDlg = hDlg;
  3030. MyContext.dwCopyingLength =
  3031. LoadString( g_hinstance, IDS_COPYING, MyContext.szCopyingString, ARRAYSIZE(MyContext.szCopyingString));
  3032. b = SetupCommitFileQueue( NULL, Queue, (PSP_FILE_CALLBACK) CopyFilesCallback, (PVOID) &MyContext );
  3033. if ( !b ) {
  3034. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3035. ErrorBox( hDlg, NULL );
  3036. }
  3037. SetupTermDefaultQueueCallback( MyContext.pContext );
  3038. ZeroMemory( &MyContext, sizeof(MyContext) );
  3039. SetupCloseFileQueue( Queue );
  3040. Queue = INVALID_HANDLE_VALUE;
  3041. // recheck
  3042. HRESULT hr2 = CheckInstallation( );
  3043. if ( FAILED(hr2) ) {
  3044. hr = THR( hr2 );
  3045. goto Cleanup;
  3046. }
  3047. // because of the recheck, this flag should be set
  3048. Assert( g_Options.fRemBootDirectory );
  3049. g_Options.fRemBootDirectory = TRUE;
  3050. }
  3051. //
  3052. // Move OS Chooser files to the IntelliMirror\OSChooser tree.
  3053. //
  3054. if ( !g_Options.fOSChooserInstalled
  3055. && g_Options.fRemBootDirectory ) {
  3056. DebugMsg( "Queue and copy os chooser files\n" );
  3057. Assert( g_Options.fIMirrorDirectory );
  3058. Assert( g_Options.fOSChooserDirectory );
  3059. b = SetupFindFirstLine( g_Options.hinf, L"OSChooser", NULL, &context );
  3060. AssertMsg( b, "Missing section?" );
  3061. if ( !b ) {
  3062. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3063. }
  3064. if ( szServerDiscName[0] == L'\0' )
  3065. {
  3066. hr = RetrieveServerDiscInfo( hDlg, szServerDiscName, NULL, NULL );
  3067. // if it fails, try to proceed anyway to see if the user is smart enough
  3068. // to fix the problem.
  3069. }
  3070. dwCount = 0;
  3071. //
  3072. // Create the Queue
  3073. //
  3074. Queue = SetupOpenFileQueue( );
  3075. while ( b )
  3076. {
  3077. WCHAR szSrcFile[ MAX_PATH ];
  3078. WCHAR szDestFile[ MAX_PATH ];
  3079. DWORD dw;
  3080. LPWSTR pszDest = NULL;
  3081. dw = SetupGetFieldCount( &context );
  3082. if ( dw > 1 ) {
  3083. b = SetupGetStringField( &context, 1, szDestFile, ARRAYSIZE(szDestFile) , NULL );
  3084. AssertMsg( b, "Missing field?" );
  3085. if ( b ) {
  3086. b = SetupGetStringField( &context, 2, szSrcFile, ARRAYSIZE(szSrcFile), NULL );
  3087. AssertMsg( b, "Missing field?" );
  3088. pszDest = szDestFile;
  3089. }
  3090. } else {
  3091. b = SetupGetStringField( &context, 1, szSrcFile, ARRAYSIZE(szSrcFile), NULL );
  3092. AssertMsg( b, "Missing field?" );
  3093. }
  3094. if ( !b ) {
  3095. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3096. goto SkipIt;
  3097. }
  3098. b = SetupQueueCopy( Queue,
  3099. g_Options.szRemBootDirectory,
  3100. NULL,
  3101. szSrcFile,
  3102. szServerDiscName,
  3103. NULL,
  3104. g_Options.szOSChooserPath,
  3105. pszDest,
  3106. SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER
  3107. | SP_COPY_WARNIFSKIP | SP_COPY_SOURCEPATH_ABSOLUTE );
  3108. if ( !b ) {
  3109. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3110. ErrorBox( NULL, szSrcFile );
  3111. goto SkipIt;
  3112. }
  3113. // increment file count
  3114. dwCount++;
  3115. SkipIt:
  3116. b = SetupFindNextLine( &context, &context );
  3117. }
  3118. b = SetupFindFirstLine( g_Options.hinf, L"OSChooser.NoOverwrite", NULL, &context );
  3119. AssertMsg( b, "Missing section?" );
  3120. if ( !b ) {
  3121. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3122. }
  3123. while ( b )
  3124. {
  3125. WCHAR szSrcFile[ MAX_PATH ];
  3126. WCHAR szDestFile[ MAX_PATH ];
  3127. DWORD dw;
  3128. LPWSTR pszDest = NULL;
  3129. dw = SetupGetFieldCount( &context );
  3130. if ( dw > 1 ) {
  3131. b = SetupGetStringField( &context, 1, szDestFile, ARRAYSIZE(szDestFile) , NULL );
  3132. AssertMsg( b, "Missing field?" );
  3133. if ( b ) {
  3134. b = SetupGetStringField( &context, 2, szSrcFile, ARRAYSIZE(szSrcFile) , NULL );
  3135. AssertMsg( b, "Missing field?" );
  3136. pszDest = szDestFile;
  3137. }
  3138. } else {
  3139. b = SetupGetStringField( &context, 1, szSrcFile, ARRAYSIZE(szSrcFile) , NULL );
  3140. AssertMsg( b, "Missing field?" );
  3141. }
  3142. if ( !b ) {
  3143. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3144. goto SkipNonCritical;
  3145. }
  3146. b = SetupQueueCopy( Queue,
  3147. g_Options.szRemBootDirectory,
  3148. NULL,
  3149. szSrcFile,
  3150. szServerDiscName,
  3151. NULL,
  3152. g_Options.szOSChooserPath,
  3153. pszDest,
  3154. SP_COPY_NOOVERWRITE
  3155. | SP_COPY_WARNIFSKIP
  3156. | SP_COPY_SOURCEPATH_ABSOLUTE );
  3157. if ( !b ) {
  3158. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3159. ErrorBox( NULL, szSrcFile );
  3160. goto SkipNonCritical;
  3161. }
  3162. // increment file count
  3163. dwCount++;
  3164. SkipNonCritical:
  3165. b = SetupFindNextLine( &context, &context );
  3166. }
  3167. //
  3168. // This information will be passed to CopyFileCallback() as
  3169. // the Context.
  3170. //
  3171. MyContext.nToBeCopied = dwCount;
  3172. MyContext.nCopied = 0;
  3173. MyContext.pContext = SetupInitDefaultQueueCallback( hDlg );
  3174. MyContext.hProg = hProg;
  3175. MyContext.hDlg = hDlg;
  3176. MyContext.hOperation = GetDlgItem( hDlg, IDC_S_OPERATION );
  3177. MyContext.dwCopyingLength =
  3178. LoadString( g_hinstance, IDS_COPYING, MyContext.szCopyingString, ARRAYSIZE(MyContext.szCopyingString));
  3179. b = SetupCommitFileQueue( NULL, Queue, (PSP_FILE_CALLBACK) CopyFilesCallback, (PVOID) &MyContext );
  3180. if ( !b ) {
  3181. DWORD dwErr = GetLastError( );
  3182. hr = THR( HRESULT_FROM_WIN32( dwErr ) );
  3183. switch ( dwErr )
  3184. {
  3185. case ERROR_CANCELLED:
  3186. goto Cleanup;
  3187. break; // expected
  3188. default:
  3189. MessageBoxFromError( hDlg, NULL, dwErr );
  3190. goto Cleanup;
  3191. break;
  3192. }
  3193. }
  3194. }
  3195. Cleanup:
  3196. if ( MyContext.pContext )
  3197. SetupTermDefaultQueueCallback( MyContext.pContext );
  3198. if ( Queue != INVALID_HANDLE_VALUE )
  3199. SetupCloseFileQueue( Queue );
  3200. HRETURN(hr);
  3201. }
  3202. //
  3203. // CopyTemplateFiles( )
  3204. //
  3205. HRESULT
  3206. CopyTemplateFiles( HWND hDlg )
  3207. {
  3208. HRESULT hr = S_OK;
  3209. WCHAR sz[ SMALL_BUFFER_SIZE ];
  3210. WCHAR szSourcePath[ MAX_PATH ];
  3211. WCHAR szTemplatePath[ MAX_PATH ];
  3212. WCHAR szFileName[ MAX_PATH ];
  3213. BOOL fNotOverwrite;
  3214. BOOL b;
  3215. DWORD dw;
  3216. TraceFunc( "CopyTemplateFiles( ... )\n" );
  3217. dw = LoadString( g_hinstance, IDS_UPDATING_SIF_FILE, sz, ARRAYSIZE(sz) );
  3218. Assert( dw );
  3219. SetDlgItemText( hDlg, IDC_S_OPERATION, sz );
  3220. dw = LoadString( g_hinstance, IDS_DEFAULT_SIF, szFileName, ARRAYSIZE(szFileName) );
  3221. Assert( dw );
  3222. //
  3223. // Create the path "IntelliMirror\Setup\English\nt50.wks\i386\default.sif"
  3224. //
  3225. wcscpy( szSourcePath, g_Options.szInstallationPath );
  3226. ConcatenatePaths( szSourcePath, g_Options.ProcessorArchitectureString );
  3227. ConcatenatePaths( szSourcePath, szFileName );
  3228. Assert( wcslen( szSourcePath ) < ARRAYSIZE(szSourcePath) );
  3229. //
  3230. // Create the path "IntelliMirror\Setup\English\nt50.wks\i386\Templates"
  3231. //
  3232. wcscpy( szTemplatePath, g_Options.szInstallationPath );
  3233. ConcatenatePaths( szTemplatePath, g_Options.ProcessorArchitectureString );
  3234. ConcatenatePaths( szTemplatePath, L"Templates" );
  3235. Assert( wcslen( szTemplatePath ) < ARRAYSIZE(szTemplatePath) );
  3236. if ( 0xFFFFffff == GetFileAttributes( szTemplatePath ) ) {
  3237. b = CreateDirectory( szTemplatePath, NULL );
  3238. if ( !b ) {
  3239. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3240. ErrorBox( hDlg, szTemplatePath );
  3241. goto Error;
  3242. }
  3243. }
  3244. //
  3245. // Create the path "IntelliMirror\Setup\English\nt50.wks\i386\Templates\default.sif"
  3246. //
  3247. ConcatenatePaths( szTemplatePath, szFileName );
  3248. Assert( wcslen( szTemplatePath ) < ARRAYSIZE(szTemplatePath) );
  3249. DebugMsg( "Copying %s to %s...\n", szSourcePath, szTemplatePath );
  3250. fNotOverwrite = TRUE;
  3251. while ( hr == S_OK && !CopyFile( szSourcePath, szTemplatePath, fNotOverwrite) )
  3252. {
  3253. DWORD dwErr = GetLastError( );
  3254. switch (dwErr)
  3255. {
  3256. case ERROR_FILE_EXISTS:
  3257. {
  3258. dw = LoadString( g_hinstance, IDS_OVERWRITE_TEXT, sz, ARRAYSIZE(sz) );
  3259. Assert( dw );
  3260. if ( IDYES == MessageBox( hDlg, sz, szFileName, MB_YESNO ) )
  3261. {
  3262. fNotOverwrite = FALSE;
  3263. }
  3264. else
  3265. {
  3266. OPENFILENAME ofn;
  3267. dw = LoadString( g_hinstance, IDS_SAVE_SIF_TITLE, sz, ARRAYSIZE(sz) );
  3268. GetFileNameAgain:
  3269. memset( &ofn, 0, sizeof( ofn ) );
  3270. ofn.lStructSize = sizeof( ofn );
  3271. ofn.hwndOwner = hDlg;
  3272. ofn.hInstance = g_hinstance;
  3273. ofn.lpstrFilter = L"Unattended Setup Answer Files\0*.SIF\0\0";
  3274. ofn.lpstrFile = szTemplatePath;
  3275. ofn.nMaxFile = MAX_PATH;
  3276. ofn.lpstrInitialDir = szTemplatePath;
  3277. ofn.lpstrTitle = sz;
  3278. ofn.Flags = OFN_CREATEPROMPT |
  3279. OFN_NOCHANGEDIR |
  3280. OFN_NONETWORKBUTTON |
  3281. OFN_NOREADONLYRETURN |
  3282. OFN_OVERWRITEPROMPT |
  3283. OFN_PATHMUSTEXIST;
  3284. ofn.nFileOffset = lstrlen( szTemplatePath ) - lstrlen( szFileName );
  3285. ofn.nFileExtension = lstrlen( szTemplatePath ) - 3;
  3286. ofn.lpstrDefExt = L"SIF";
  3287. b = GetSaveFileName( &ofn );
  3288. if ( !b ) {
  3289. hr = S_FALSE;
  3290. }
  3291. // paranoid
  3292. Assert( wcslen(szTemplatePath) < ARRAYSIZE(szTemplatePath) );
  3293. Assert( wcslen(g_Options.szIntelliMirrorPath) < ARRAYSIZE(g_Options.szIntelliMirrorPath) );
  3294. if ( wcslen(szTemplatePath) - wcslen(g_Options.szIntelliMirrorPath) + 53 >= 128 )
  3295. {
  3296. MessageBoxFromStrings( hDlg, IDS_BOOTP_FILENAME_LENGTH_RESTRICTION_TITLE, IDS_BOOTP_FILENAME_LENGTH_RESTRICTION_TEXT, MB_OK );
  3297. goto GetFileNameAgain;
  3298. }
  3299. }
  3300. }
  3301. break;
  3302. default:
  3303. MessageBoxFromError( hDlg, szFileName, dwErr );
  3304. hr = S_FALSE;
  3305. }
  3306. }
  3307. if ( hr == S_OK )
  3308. {
  3309. //
  3310. // Need to add "Quotes" around the text
  3311. //
  3312. WCHAR szDescription[ REMOTE_INSTALL_MAX_DESCRIPTION_CHAR_COUNT + 2 ];
  3313. WCHAR szHelpText[ REMOTE_INSTALL_MAX_HELPTEXT_CHAR_COUNT + 2 ];
  3314. WCHAR szOSVersion[ 32 ];
  3315. wsprintf( szDescription, L"\"%s\"", g_Options.szDescription );
  3316. Assert( wcslen(szDescription) < ARRAYSIZE(szDescription) );
  3317. wsprintf( szHelpText, L"\"%s\"", g_Options.szHelpText );
  3318. Assert( wcslen(szHelpText) < ARRAYSIZE(szHelpText) );
  3319. wsprintf( szOSVersion, L"\"%s.%s (%d)\"", g_Options.szMajorVersion, g_Options.szMinorVersion, g_Options.dwBuildNumber );
  3320. Assert( wcslen(szOSVersion) < ARRAYSIZE(szOSVersion) );
  3321. WritePrivateProfileString( L"OSChooser",
  3322. L"Description",
  3323. szDescription,
  3324. szTemplatePath );
  3325. WritePrivateProfileString( L"OSChooser",
  3326. L"Help",
  3327. szHelpText,
  3328. szTemplatePath );
  3329. WritePrivateProfileString( L"OSChooser",
  3330. L"ImageType",
  3331. L"Flat",
  3332. szTemplatePath );
  3333. WritePrivateProfileString( L"OSChooser",
  3334. L"Version",
  3335. szOSVersion,
  3336. szTemplatePath );
  3337. }
  3338. Error:
  3339. HRETURN(hr);
  3340. }
  3341. //
  3342. // Create Common Store Volume
  3343. //
  3344. HRESULT
  3345. CreateSISVolume( HWND hDlg )
  3346. {
  3347. HRESULT hr = E_FAIL;
  3348. WCHAR sz[ SMALL_BUFFER_SIZE ];
  3349. DWORD dw;
  3350. BOOL b;
  3351. HANDLE hVolume;
  3352. WCHAR szVolumePath[ MAX_PATH ];
  3353. WCHAR szSISPath[ MAX_PATH ];
  3354. HANDLE hMaxIndex;
  3355. WCHAR szIndexFilePath[ MAX_PATH ];
  3356. PACL pAcl = NULL;
  3357. SECURITY_DESCRIPTOR SecDescriptor;
  3358. PSID pAdminsSid = NULL;
  3359. EXPLICIT_ACCESS ExplicitEntries;
  3360. SID_IDENTIFIER_AUTHORITY ntSidAuthority = SECURITY_NT_AUTHORITY;
  3361. TraceFunc( "CreateSISVolume( hDlg )\n" );
  3362. // We may have not known the IntelliMirror Drive/Directory
  3363. // until now and it was previously an SIS volume.
  3364. if ( g_Options.fSISVolumeCreated ) {
  3365. hr = S_OK;
  3366. goto Error;
  3367. }
  3368. dw = LoadString( g_hinstance, IDS_CREATING_SIS_VOLUME, sz, ARRAYSIZE(sz) );
  3369. Assert( dw );
  3370. SetDlgItemText( hDlg, IDC_S_OPERATION, sz );
  3371. b = GetVolumePathName( g_Options.szIntelliMirrorPath, szVolumePath, MAX_PATH );
  3372. Assert( b );
  3373. Assert( wcslen(szVolumePath) < ARRAYSIZE(szVolumePath) );
  3374. TraceMsg( TF_ALWAYS, "Creating %s...\n", szVolumePath );
  3375. wsprintf( szSISPath, L"%s\\SIS Common Store", szVolumePath );
  3376. //
  3377. // Create and zero SIS store
  3378. //
  3379. b = CreateDirectory( szSISPath, NULL );
  3380. if ( !b ) {
  3381. dw = GetLastError();
  3382. if (ERROR_ALREADY_EXISTS != dw) {
  3383. hr = THR( HRESULT_FROM_WIN32( dw ) );
  3384. ErrorBox( hDlg, szSISPath );
  3385. DebugMsg( "Cannot create Common Store directory." );
  3386. goto Error;
  3387. }
  3388. }
  3389. b = SetFileAttributes( szSISPath, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM );
  3390. if ( !b ) {
  3391. ErrorBox( hDlg, szSISPath );
  3392. DebugMsg( "Could not mark SIS Common Store directory as hidden and system. Error: %u\n", GetLastError() );
  3393. }
  3394. //
  3395. // Create the MaxIndex file.
  3396. //
  3397. wsprintf( szIndexFilePath, L"%s\\MaxIndex", szSISPath );
  3398. hMaxIndex = CreateFile( szIndexFilePath,
  3399. GENERIC_READ | GENERIC_WRITE,
  3400. 0,
  3401. NULL,
  3402. CREATE_NEW,
  3403. FILE_ATTRIBUTE_NORMAL,
  3404. NULL);
  3405. if ( hMaxIndex == INVALID_HANDLE_VALUE ) {
  3406. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3407. ErrorBox( hDlg, szIndexFilePath );
  3408. DebugMsg( "Can't create %s.\n", szIndexFilePath );
  3409. goto Error;
  3410. } else {
  3411. DWORD bytesWritten;
  3412. INDEX maxIndex = 1;
  3413. if ( !WriteFile( hMaxIndex, &maxIndex, sizeof maxIndex, &bytesWritten, NULL )
  3414. || ( bytesWritten < sizeof maxIndex ) ) {
  3415. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3416. ErrorBox( hDlg, szIndexFilePath );
  3417. DebugMsg( "Can't write MaxIndex. Error: %u\n", GetLastError() );
  3418. CloseHandle( hMaxIndex );
  3419. goto Error;
  3420. } else {
  3421. CloseHandle( hMaxIndex );
  3422. TraceMsg( TF_ALWAYS, "MaxIndex of %lu written\n", maxIndex );
  3423. hr = S_OK;
  3424. }
  3425. }
  3426. //
  3427. // Set security information on the common store directory
  3428. //
  3429. //
  3430. // build AccessEntry structure
  3431. //
  3432. ZeroMemory( &ExplicitEntries, sizeof(ExplicitEntries) );
  3433. b = AllocateAndInitializeSid(
  3434. &ntSidAuthority,
  3435. 1,
  3436. SECURITY_LOCAL_SYSTEM_RID,0,
  3437. /*2,
  3438. SECURITY_BUILTIN_DOMAIN_RID,
  3439. DOMAIN_ALIAS_RID_ADMINS,*/
  3440. 0, 0, 0, 0, 0, 0,
  3441. &pAdminsSid );
  3442. if ( !b || (pAdminsSid == NULL) ) {
  3443. dw = GetLastError();
  3444. hr = THR( HRESULT_FROM_WIN32( dw ) );
  3445. MessageBoxFromError( hDlg, NULL, dw );
  3446. goto Error;
  3447. }
  3448. BuildTrusteeWithSid( &ExplicitEntries.Trustee, pAdminsSid );
  3449. ExplicitEntries.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  3450. ExplicitEntries.grfAccessMode = SET_ACCESS;
  3451. ExplicitEntries.grfAccessPermissions = FILE_ALL_ACCESS;
  3452. //
  3453. // Set the Acl with the ExplicitEntry rights
  3454. //
  3455. dw = SetEntriesInAcl( 1,
  3456. &ExplicitEntries,
  3457. NULL,
  3458. &pAcl );
  3459. if ( dw != ERROR_SUCCESS ) {
  3460. hr = THR( HRESULT_FROM_WIN32(dw) );
  3461. MessageBoxFromError( hDlg, NULL, dw );
  3462. goto Error;
  3463. }
  3464. //
  3465. // Create the Security Descriptor
  3466. //
  3467. InitializeSecurityDescriptor( &SecDescriptor, SECURITY_DESCRIPTOR_REVISION );
  3468. if (!SetSecurityDescriptorDacl( &SecDescriptor, TRUE, pAcl, FALSE )) {
  3469. dw = GetLastError();
  3470. hr = THR( HRESULT_FROM_WIN32(dw) );
  3471. MessageBoxFromError( hDlg, NULL, dw );
  3472. goto Error;
  3473. }
  3474. //
  3475. // SET security on the Directory
  3476. //
  3477. dw = SetFileSecurity(szSISPath,
  3478. DACL_SECURITY_INFORMATION,
  3479. &SecDescriptor);
  3480. if ( !dw ) {
  3481. dw = GetLastError();
  3482. hr = THR( HRESULT_FROM_WIN32(dw) );
  3483. MessageBoxFromError( hDlg, szSISPath, dw );
  3484. goto Error;
  3485. }
  3486. Error:
  3487. if ( pAdminsSid ) {
  3488. FreeSid( pAdminsSid );
  3489. }
  3490. if ( pAcl ) {
  3491. TraceFree( pAcl );
  3492. }
  3493. HRETURN(hr);
  3494. }
  3495. //
  3496. // CopyScreenFiles( )
  3497. //
  3498. HRESULT
  3499. CopyScreenFiles( HWND hDlg )
  3500. {
  3501. HRESULT hr = S_OK;
  3502. WCHAR szText[ SMALL_BUFFER_SIZE ];
  3503. WCHAR szRembootPath[ MAX_PATH ];
  3504. WCHAR szScreenDirectory[ MAX_PATH ];
  3505. WCHAR szRemboot[ 14 ];
  3506. UINT uLineNum;
  3507. HINF hinf = INVALID_HANDLE_VALUE;
  3508. DWORD dwCount = 0;
  3509. DWORD dw;
  3510. BOOL b;
  3511. INFCONTEXT context;
  3512. HSPFILEQ Queue = INVALID_HANDLE_VALUE;
  3513. HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
  3514. BOOL fWarning = FALSE;
  3515. MYCONTEXT MyContext;
  3516. ZeroMemory( &MyContext, sizeof(MyContext) );
  3517. TraceFunc( "CopyScreenFiles( ... )\n" );
  3518. AssertMsg( !g_Options.fScreenLeaveAlone, "Should not have made it here with this flag set." );
  3519. SendMessage( hProg, PBM_SETRANGE, 0, MAKELPARAM(0, 5000 ));
  3520. SendMessage( hProg, PBM_SETPOS, 0, 0 );
  3521. dw = LoadString( g_hinstance, IDS_BUILDINGLIST, szText, ARRAYSIZE(szText));
  3522. Assert( dw );
  3523. SetDlgItemText( hDlg, IDC_S_OPERATION, szText );
  3524. dw = LoadString( g_hinstance, IDS_REMBOOTINF, szRemboot, ARRAYSIZE(szRemboot) );
  3525. Assert( dw );
  3526. Assert( g_Options.fLanguageSet );
  3527. wcscpy( szRembootPath, g_Options.szInstallationPath );
  3528. ConcatenatePaths( szRembootPath, g_Options.ProcessorArchitectureString);
  3529. ConcatenatePaths( szRembootPath, szRemboot );
  3530. Assert( wcslen( szRembootPath ) < ARRAYSIZE(szRembootPath) );
  3531. DebugMsg( "REMINST.INF: %s\n", szRembootPath );
  3532. wcscpy( szScreenDirectory, g_Options.szOSChooserPath );
  3533. ConcatenatePaths( szScreenDirectory, g_Options.szLanguage );
  3534. Assert( wcslen(szScreenDirectory) < ARRAYSIZE(szScreenDirectory) );
  3535. DebugMsg( "Destination: %s\n", szScreenDirectory );
  3536. hinf = SetupOpenInfFile( szRembootPath, NULL, INF_STYLE_WIN4, &uLineNum);
  3537. if ( hinf == INVALID_HANDLE_VALUE ) {
  3538. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3539. ErrorBox( hDlg, szRembootPath );
  3540. goto Cleanup;
  3541. }
  3542. Queue = SetupOpenFileQueue( );
  3543. b = SetupFindFirstLine( hinf, L"OSChooser Screens", NULL, &context );
  3544. if ( !b ) {
  3545. ErrorBox( hDlg, szRembootPath );
  3546. hr = THR(S_FALSE);
  3547. }
  3548. while ( b )
  3549. {
  3550. LPWSTR pszDest = NULL;
  3551. WCHAR szSrcPath[ MAX_PATH ];
  3552. WCHAR szDestPath[ MAX_PATH ];
  3553. DWORD dw;
  3554. dw = SetupGetFieldCount( &context );
  3555. if ( dw > 1 ) {
  3556. b = SetupGetStringField( &context, 1, szDestPath, ARRAYSIZE( szDestPath ), NULL );
  3557. AssertMsg( b, "REMINST: Missing field?" );
  3558. if ( b ) {
  3559. b = SetupGetStringField( &context, 2, szSrcPath, ARRAYSIZE(szSrcPath), NULL );
  3560. AssertMsg( b, "REMINST: Missing field?" );
  3561. pszDest = szDestPath;
  3562. }
  3563. } else {
  3564. b = SetupGetStringField( &context, 1, szSrcPath, ARRAYSIZE(szSrcPath), NULL );
  3565. AssertMsg( b, "REMINST: Missing field?" );
  3566. }
  3567. if ( !b ) {
  3568. hr = S_FALSE;
  3569. goto SkipIt;
  3570. }
  3571. if ( g_Options.fScreenSaveOld ) {
  3572. WCHAR szPath[ MAX_PATH ];
  3573. WCHAR szMovePath[ MAX_PATH ];
  3574. LPWSTR psz;
  3575. DWORD dwLen;
  3576. if ( pszDest ) {
  3577. wcscpy( szPath, szScreenDirectory );
  3578. ConcatenatePaths( szPath, pszDest );
  3579. } else {
  3580. wcscpy( szPath, szScreenDirectory );
  3581. ConcatenatePaths( szPath, szSrcPath );
  3582. }
  3583. // Rename to *.BAK
  3584. StrCpy( szMovePath, szPath );
  3585. dwLen = lstrlen( szMovePath );
  3586. Assert( StrCmpI( &szMovePath[ dwLen - 3 ], L"OSC" ) == 0 );
  3587. StrCpy( &szMovePath[ dwLen - 3 ], L"BAK");
  3588. DebugMsg( "Renaming %s to %s...\n", szPath, szMovePath );
  3589. b = DeleteFile( szMovePath );
  3590. b = MoveFile( szPath, szMovePath );
  3591. if ( !b ) {
  3592. DWORD dwErr = GetLastError( );
  3593. switch ( dwErr )
  3594. {
  3595. #if 0 // blast over files
  3596. case ERROR_FILE_EXISTS:
  3597. if ( !fWarning ) {
  3598. MessageBoxFromStrings( hDlg,
  3599. IDS_BACKUPSCREENFILEEXISTS_CAPTION,
  3600. IDS_BACKUPSCREENFILEEXISTS_TEXT,
  3601. MB_OK );
  3602. fWarning = TRUE;
  3603. }
  3604. #endif
  3605. case ERROR_FILE_NOT_FOUND:
  3606. break; // ignore this error
  3607. // It is possible that the user deleted the source files (old OSCs).
  3608. default:
  3609. MessageBoxFromError( hDlg, NULL, dwErr );
  3610. break;
  3611. }
  3612. }
  3613. }
  3614. b = SetupQueueCopy( Queue,
  3615. g_Options.szInstallationPath,
  3616. g_Options.ProcessorArchitectureString,
  3617. szSrcPath,
  3618. NULL,
  3619. NULL,
  3620. szScreenDirectory,
  3621. pszDest,
  3622. g_Options.fScreenOverwrite ?
  3623. SP_COPY_FORCE_NEWER | SP_COPY_WARNIFSKIP :
  3624. SP_COPY_NOOVERWRITE | SP_COPY_WARNIFSKIP );
  3625. if ( !b ) {
  3626. ErrorBox( hDlg, szSrcPath );
  3627. hr = THR(S_FALSE);
  3628. goto SkipIt;
  3629. }
  3630. dwCount++;
  3631. SkipIt:
  3632. b = SetupFindNextLine( &context, &context );
  3633. }
  3634. //
  3635. // This information will be passed to CopyFileCallback() as
  3636. // the Context.
  3637. //
  3638. MyContext.nToBeCopied = dwCount;
  3639. MyContext.nCopied = 0;
  3640. MyContext.pContext = SetupInitDefaultQueueCallback( hDlg );
  3641. MyContext.hProg = hProg;
  3642. MyContext.hOperation = GetDlgItem( hDlg, IDC_S_OPERATION );
  3643. MyContext.hDlg = hDlg;
  3644. MyContext.fQuiet = FALSE;
  3645. MyContext.dwCopyingLength =
  3646. LoadString( g_hinstance, IDS_COPYING, MyContext.szCopyingString, ARRAYSIZE(MyContext.szCopyingString));
  3647. Assert(MyContext.dwCopyingLength);
  3648. //
  3649. // Start copying
  3650. //
  3651. if ( dwCount != 0 )
  3652. {
  3653. b = SetupCommitFileQueue( NULL,
  3654. Queue,
  3655. (PSP_FILE_CALLBACK) CopyFilesCallback,
  3656. (PVOID) &MyContext );
  3657. if ( !b ) {
  3658. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3659. ErrorBox( hDlg, NULL );
  3660. goto Cleanup;
  3661. }
  3662. }
  3663. Cleanup:
  3664. SendMessage( hProg, PBM_SETPOS, 5000, 0 );
  3665. SetDlgItemText( hDlg, IDC_S_OPERATION, L"" );
  3666. if ( MyContext.pContext )
  3667. SetupTermDefaultQueueCallback( MyContext.pContext );
  3668. if ( Queue != INVALID_HANDLE_VALUE )
  3669. SetupCloseFileQueue( Queue );
  3670. if ( hinf != INVALID_HANDLE_VALUE )
  3671. SetupCloseInfFile( hinf );
  3672. HRETURN( hr );
  3673. }
  3674. //
  3675. // UpdateRemoteInstallTree( )
  3676. //
  3677. HRESULT
  3678. UpdateRemoteInstallTree( )
  3679. {
  3680. TraceFunc( "UpdateRemoteInstallTree( )\n" );
  3681. HRESULT hr = S_OK;
  3682. LRESULT lResult;
  3683. HKEY hkey;
  3684. DWORD dw;
  3685. BOOL b;
  3686. HINF hinf = INVALID_HANDLE_VALUE;
  3687. WCHAR szServerRemBootInfPath[ MAX_PATH ];
  3688. WCHAR szRemInstSetupPath[ MAX_PATH ];
  3689. WCHAR szRemoteInstallPath[ MAX_PATH ];
  3690. WCHAR szPath[ MAX_PATH ];
  3691. UINT uLineNum;
  3692. INFCONTEXT context;
  3693. //
  3694. // Try finding TFTPD's regkey to find the IntelliMirror Directory
  3695. //
  3696. dw = LoadString( g_hinstance, IDS_TFTPD_SERVICE_PARAMETERS, szPath, ARRAYSIZE( szPath ));
  3697. Assert( dw );
  3698. if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  3699. szPath,
  3700. 0, // options
  3701. KEY_QUERY_VALUE,
  3702. &hkey ) ) {
  3703. ULONG l;
  3704. DWORD dwType;
  3705. LONG lErr;
  3706. l = sizeof(szRemoteInstallPath);
  3707. lErr = RegQueryValueEx( hkey,
  3708. L"Directory",
  3709. 0, // reserved
  3710. &dwType,
  3711. (LPBYTE) szRemoteInstallPath,
  3712. &l );
  3713. if ( lErr == ERROR_SUCCESS ) {
  3714. DebugMsg( "Found TFTPD's Directory regkey: %s\n", szRemoteInstallPath );
  3715. // now add "OSChooser"
  3716. wcscat( szRemoteInstallPath, L"\\OSChooser" );
  3717. if ( 0xFFFFffff == GetFileAttributes( szRemoteInstallPath ) ) {
  3718. DebugMsg( "%s - directory doesn't exist.\n", szRemoteInstallPath );
  3719. hr = S_FALSE;
  3720. }
  3721. } else {
  3722. hr = S_FALSE;
  3723. }
  3724. RegCloseKey( hkey );
  3725. }
  3726. else
  3727. {
  3728. hr = S_FALSE;
  3729. }
  3730. if ( hr == S_OK )
  3731. {
  3732. // make x:\winnt
  3733. dw = ExpandEnvironmentStrings( TEXT("%SystemRoot%"), szServerRemBootInfPath, ARRAYSIZE( szServerRemBootInfPath ));
  3734. Assert( dw );
  3735. // make x:\winnt\system32
  3736. dw = lstrlen( szServerRemBootInfPath );
  3737. StrCpy( &szServerRemBootInfPath[dw], L"\\System32\\" );
  3738. StrCpy( szRemInstSetupPath, szServerRemBootInfPath );
  3739. // make x:\winnt\system32\reminst.inf
  3740. dw = lstrlen( szServerRemBootInfPath );
  3741. dw = LoadString( g_hinstance, IDS_REMBOOTINF, &szServerRemBootInfPath[dw], ARRAYSIZE( szServerRemBootInfPath ) - dw );
  3742. Assert( dw );
  3743. // make x:\winnt\system32\reminst
  3744. wcscat( szRemInstSetupPath, L"reminst" );
  3745. DebugMsg( "RemBoot.INF Path: %s\n", szServerRemBootInfPath );
  3746. DebugMsg( "RemInst Setup Path: %s\n", szRemInstSetupPath );
  3747. hinf = SetupOpenInfFile( szServerRemBootInfPath, NULL, INF_STYLE_WIN4, &uLineNum);
  3748. if ( hinf != INVALID_HANDLE_VALUE ) {
  3749. b = SetupFindFirstLine( hinf, L"OSChooser", NULL, &context );
  3750. AssertMsg( b, "Missing section?" );
  3751. if ( !b ) {
  3752. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3753. }
  3754. } else {
  3755. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3756. }
  3757. }
  3758. if ( hr == S_OK )
  3759. {
  3760. HSPFILEQ Queue;
  3761. //
  3762. // Create the Queue
  3763. //
  3764. Queue = SetupOpenFileQueue( );
  3765. b = TRUE;
  3766. while ( b )
  3767. {
  3768. WCHAR szSrcFile[ MAX_PATH ];
  3769. WCHAR szDestFile[ MAX_PATH ];
  3770. DWORD dw;
  3771. LPWSTR pszDest = NULL;
  3772. dw = SetupGetFieldCount( &context );
  3773. if ( dw > 1 ) {
  3774. b = SetupGetStringField( &context, 1, szDestFile, ARRAYSIZE(szDestFile), NULL );
  3775. AssertMsg( b, "Missing field?" );
  3776. if ( b ) {
  3777. b = SetupGetStringField( &context, 2, szSrcFile, ARRAYSIZE(szSrcFile), NULL );
  3778. AssertMsg( b, "Missing field?" );
  3779. pszDest = szDestFile;
  3780. }
  3781. } else {
  3782. b = SetupGetStringField( &context, 1, szSrcFile, ARRAYSIZE(szSrcFile), NULL );
  3783. AssertMsg( b, "Missing field?" );
  3784. }
  3785. if ( !b ) {
  3786. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3787. goto SkipIt;
  3788. }
  3789. b = SetupQueueCopy( Queue,
  3790. szRemInstSetupPath,
  3791. NULL,
  3792. szSrcFile,
  3793. NULL,
  3794. NULL,
  3795. szRemoteInstallPath,
  3796. pszDest,
  3797. SP_COPY_NEWER | SP_COPY_FORCE_NEWER
  3798. | SP_COPY_WARNIFSKIP | SP_COPY_SOURCEPATH_ABSOLUTE );
  3799. if ( !b ) {
  3800. THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3801. }
  3802. SkipIt:
  3803. b = SetupFindNextLine( &context, &context );
  3804. }
  3805. b = SetupCommitFileQueue( NULL,
  3806. Queue,
  3807. SetupDefaultQueueCallback,
  3808. SetupInitDefaultQueueCallback( NULL ) );
  3809. if ( !b ) {
  3810. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3811. }
  3812. SetupCloseFileQueue( Queue );
  3813. }
  3814. if ( hinf != INVALID_HANDLE_VALUE ) {
  3815. SetupCloseInfFile( hinf );
  3816. }
  3817. HRETURN( hr );
  3818. }