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.

792 lines
22 KiB

  1. /****************************************************************************
  2. Copyright (c) Microsoft Corporation 1997
  3. All rights reserved
  4. ***************************************************************************/
  5. #include "pch.h"
  6. #include <shlobj.h>
  7. #include <setupapi.h>
  8. #include <advpub.h>
  9. #include <lm.h>
  10. #include "dialogs.h"
  11. DEFINE_MODULE("Setup");
  12. #define SMALL_BUFFER_SIZE 256
  13. #define MAX_FILES_SIZE 640000
  14. static const TCHAR chSlash = TEXT('\\');
  15. //
  16. // Opens the layout.inf file for a particular platform.
  17. //
  18. HINF
  19. OpenLayoutInf( )
  20. {
  21. TCHAR szFilename[ MAX_PATH ];
  22. HANDLE hFile;
  23. UINT uErr;
  24. DWORD dwLen;
  25. DWORD dw;
  26. lstrcpy( szFilename, g_Options.szSourcePath );
  27. dwLen = lstrlen( szFilename );
  28. szFilename[ dwLen++ ] = chSlash;
  29. dw = LoadString( g_hinstance, IDS_NTSETUPINFFILENAME,
  30. &szFilename[ dwLen ], ARRAYSIZE( szFilename ) - dwLen );
  31. Assert( dw );
  32. hFile = SetupOpenInfFile( szFilename, NULL, INF_STYLE_WIN4, &uErr );
  33. return hFile;
  34. }
  35. //
  36. // Creates the RemoteBoot directory tree.
  37. //
  38. HRESULT
  39. CreateDirectories( HWND hDlg )
  40. {
  41. BOOL fReturn = FALSE;
  42. TCHAR szPath[ MAX_PATH ];
  43. TCHAR szCreating[ SMALL_BUFFER_SIZE ];
  44. HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
  45. DWORD dwLen;
  46. DWORD dw;
  47. SendMessage( hProg, PBM_SETRANGE, 0,
  48. MAKELPARAM(0, 4 + ( g_Options.fCreateDirectory ? 1 : 0 )) );
  49. SendMessage( hProg, PBM_SETSTEP, 1, 0 );
  50. dw = LoadString( g_hinstance, IDS_CREATINGDIRECTORIES, szCreating,
  51. ARRAYSIZE( szCreating ) );
  52. Assert( dw );
  53. SetWindowText( GetDlgItem( hDlg, IDC_S_OPERATION ), szCreating );
  54. if ( g_Options.fCreateDirectory )
  55. {
  56. fReturn = CreateDirectory( g_Options.szRemoteBootPath, NULL );
  57. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  58. if ( !fReturn )
  59. goto Finish;
  60. }
  61. lstrcpy( szPath, g_Options.szRemoteBootPath );
  62. dwLen = lstrlen( szPath );
  63. szPath[ dwLen ] = chSlash;
  64. dwLen++;
  65. dw = LoadString( g_hinstance, IDS_IMAGES, &szPath[ dwLen ],
  66. ARRAYSIZE( szPath ) - dwLen );
  67. Assert( dw );
  68. CreateDirectory( szPath, NULL );
  69. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  70. lstrcpy( g_Options.szImagesPath, szPath );
  71. dw = LoadString( g_hinstance, IDS_TEMPLATEPATH, &szPath[ dwLen ],
  72. ARRAYSIZE( szPath )- dwLen );
  73. Assert( dw );
  74. CreateDirectory( szPath, NULL );
  75. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  76. dw = LoadString( g_hinstance, IDS_SETUP, &szPath[ dwLen ],
  77. ARRAYSIZE( szPath ) - dwLen );
  78. Assert( dw );
  79. CreateDirectory( szPath, NULL );
  80. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  81. dwLen = lstrlen( szPath );
  82. szPath[ dwLen ] = chSlash;
  83. dwLen++;
  84. lstrcpy( &szPath[ dwLen ], g_Options.szName );
  85. CreateDirectory( szPath, NULL );
  86. SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
  87. /*
  88. // add '\i386'
  89. dwLen = lstrlen( szPath );
  90. szPath[ dwLen ] = chSlash;
  91. dwLen++;
  92. dw = LoadString( g_hinstance, IDS_INTELPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
  93. Assert( dw );
  94. */
  95. lstrcpy( g_Options.szSetupPath, szPath );
  96. fReturn = TRUE;
  97. Finish:
  98. g_Options.fError = !fReturn;
  99. return fReturn ? S_OK : E_FAIL;
  100. }
  101. //
  102. // Find the filename part from a complete path.
  103. //
  104. LPTSTR FilenameOnly( LPTSTR pszPath )
  105. {
  106. LPTSTR psz = pszPath;
  107. // find the end
  108. while ( *psz )
  109. psz++;
  110. // find the slash
  111. while ( psz > pszPath && *psz != chSlash )
  112. psz--;
  113. // move in front of the slash
  114. if ( psz != pszPath )
  115. psz++;
  116. return psz;
  117. }
  118. typedef struct {
  119. PVOID pContext; // "Context" for DefaultQueueCallback
  120. HWND hProg; // hwnd to the progress meter
  121. HWND hOperation; // hwnd to the "current operation"
  122. DWORD nCopied; // number of files copied
  123. DWORD nToBeCopied; // number of file to be copied
  124. DWORD dwCopyingLength; // length of the IDS_COPYING
  125. TCHAR szCopyingString[ SMALL_BUFFER_SIZE ]; // buffer to create "Copying file.ext..."
  126. } MYCONTEXT, *LPMYCONTEXT;
  127. //
  128. //
  129. //
  130. UINT CALLBACK
  131. CopyFilesCallback(
  132. IN PVOID Context,
  133. IN UINT Notification,
  134. IN UINT Param1,
  135. IN UINT Param2
  136. )
  137. {
  138. MSG Msg;
  139. LPMYCONTEXT pMyContext = (LPMYCONTEXT) Context;
  140. DWORD dw;
  141. // process some messages
  142. if ( PeekMessage( &Msg, NULL, 0, 0, PM_REMOVE ) )
  143. {
  144. TranslateMessage( &Msg );
  145. DispatchMessage( &Msg );
  146. }
  147. if ( g_Options.fAbort )
  148. {
  149. if ( !g_Options.fError )
  150. {
  151. TCHAR szAbort[ SMALL_BUFFER_SIZE ];
  152. // change filename text to aborting...
  153. dw = LoadString( g_hinstance, IDS_ABORTING, szAbort,
  154. ARRAYSIZE( szAbort ) );
  155. Assert( dw );
  156. SetWindowText( pMyContext->hOperation, szAbort );
  157. g_Options.fError = TRUE;
  158. }
  159. SetLastError(ERROR_CANCELLED);
  160. return FILEOP_ABORT;
  161. }
  162. switch ( Notification )
  163. {
  164. case SPFILENOTIFY_ENDCOPY:
  165. pMyContext->nCopied++;
  166. SendMessage( pMyContext->hProg, PBM_SETPOS,
  167. (1000 * pMyContext->nCopied) / pMyContext->nToBeCopied, 0 );
  168. break;
  169. case SPFILENOTIFY_STARTCOPY:
  170. {
  171. DWORD dwLen;
  172. LPTSTR * ppszCopyingFile = (LPTSTR *) Param1;
  173. lstrcpy( &pMyContext->szCopyingString[ pMyContext->dwCopyingLength ],
  174. FilenameOnly( *ppszCopyingFile ) );
  175. dwLen = lstrlen( pMyContext->szCopyingString );
  176. lstrcpy( &pMyContext->szCopyingString[ dwLen ], TEXT("...") );
  177. SetWindowText( pMyContext->hOperation, pMyContext->szCopyingString );
  178. }
  179. break;
  180. case SPFILENOTIFY_RENAMEERROR:
  181. case SPFILENOTIFY_DELETEERROR:
  182. case SPFILENOTIFY_COPYERROR:
  183. case SPFILENOTIFY_NEEDMEDIA:
  184. case SPFILENOTIFY_LANGMISMATCH:
  185. case SPFILENOTIFY_TARGETEXISTS:
  186. case SPFILENOTIFY_TARGETNEWER:
  187. return SetupDefaultQueueCallback( pMyContext->pContext, Notification,
  188. Param1, Param2 );
  189. }
  190. return FILEOP_DOIT;
  191. }
  192. //
  193. // Find a character in a NULL terminated string.
  194. //
  195. // Returns NULL is not found.
  196. //
  197. LPTSTR
  198. FindChar( LPTSTR pszSrc, TCHAR ch )
  199. {
  200. if ( pszSrc )
  201. {
  202. while ( *pszSrc )
  203. {
  204. if ( *pszSrc == ch )
  205. return pszSrc;
  206. pszSrc++;
  207. }
  208. }
  209. return NULL;
  210. }
  211. //
  212. // change layout format to double-null list
  213. //
  214. void
  215. LayoutToDoubleNullList( LPTSTR pszList )
  216. {
  217. /*
  218. Borrowed from LAYOUT.INF for reference
  219. ;
  220. ; filename_on_source = diskid,subdir,size,checksum,spare,spare
  221. ; extra fields are nt-specific
  222. ; bootmediaord: _1 (floppy #1)
  223. ; _2 (floppy #2)
  224. ; _3 (floppy #3)
  225. ; _x (textmode setup)
  226. ; nothing (gui mode setup)
  227. ; targetdirectory : 1 - 41 (see "WinntDirectories", above)
  228. ; upgradedisposition : 0 (always copy)
  229. ; 1 (copy if present)
  230. ; 2 (copy if not present)
  231. ; 3 (never copy)
  232. ; textmodedisposition:
  233. ; targetname
  234. ;
  235. */
  236. static const TCHAR chComma = TEXT(',');
  237. LPTSTR pszFile = pszList;
  238. LPTSTR pszCopyHere = pszList;
  239. while ( *pszFile )
  240. {
  241. MSG Msg;
  242. DWORD dwToNextFile = lstrlen( pszFile );
  243. LPTSTR pszNext;
  244. LPTSTR psz = FindChar( pszFile, TEXT('=') );
  245. Assert( psz );
  246. // process some messages
  247. if ( PeekMessage( &Msg, NULL, 0, 0, PM_REMOVE ) )
  248. {
  249. TranslateMessage( &Msg );
  250. DispatchMessage( &Msg );
  251. }
  252. *psz = 0;
  253. psz++;
  254. pszNext = FindChar( psz, chComma );
  255. *pszNext = 0;
  256. // must be "1"
  257. if ( !lstrcmp( psz, TEXT("1") ) )
  258. {
  259. // copy file name
  260. lstrcpy( pszCopyHere, pszFile );
  261. // advance copy pointer
  262. pszCopyHere += 1 + lstrlen( pszCopyHere );
  263. }
  264. else
  265. {
  266. AssertMsg( FALSE, "Now what?!" );
  267. }
  268. // advanced file pointer
  269. pszFile += dwToNextFile + 1;
  270. }
  271. *pszCopyHere = 0;
  272. }
  273. //
  274. // change semicolon delinated list to double-null list
  275. //
  276. void
  277. SemiColonToDoubleNullList( LPTSTR pszList )
  278. {
  279. while ( *pszList )
  280. {
  281. if ( *pszList == TEXT(';') )
  282. {
  283. *pszList = 0;
  284. }
  285. pszList++;
  286. }
  287. pszList++;
  288. *pszList = 0; // double the null.
  289. }
  290. //
  291. // Adds double-null terminated list of file name to the Queue. The filename
  292. // can have a comma in it indicating a rename operation:
  293. // optionalpath\newname.ext,optionalpath\sourcefil.ext
  294. //
  295. // Returns the number of files added to the Queue.
  296. //
  297. DWORD
  298. CopyFilesAddToQueue(
  299. HSPFILEQ Queue, // setup Queue
  300. LPTSTR pszSource, // source directory
  301. LPTSTR pszDest, // destination directory
  302. LPTSTR pszFiles, // Double-null terminated file list
  303. LPTSTR pszSubpath, // optional sub-path
  304. DWORD dwCopyStyle) // flags
  305. {
  306. DWORD dwCount = 0;
  307. LPTSTR psz = pszFiles;
  308. static const TCHAR chComma = TEXT(',');
  309. while ( *pszFiles )
  310. {
  311. DWORD dwLen;
  312. psz = pszFiles;
  313. // check for comma which indicates rename
  314. while (*psz && *psz != chComma)
  315. psz++;
  316. if ( *psz == chComma )
  317. {
  318. *psz= 0; // terminate
  319. psz++;
  320. }
  321. else
  322. { // sources name is dest name
  323. psz = pszFiles;
  324. }
  325. SetupQueueCopy(
  326. Queue,
  327. pszSource,
  328. pszSubpath,
  329. psz,
  330. NULL,
  331. NULL,
  332. pszDest,
  333. pszFiles,
  334. dwCopyStyle );
  335. // get next file
  336. pszFiles = psz + lstrlen( psz ) + 1;
  337. dwCount++;
  338. }
  339. return dwCount;
  340. }
  341. //
  342. // Copies the files into the setup directory.
  343. //
  344. HRESULT
  345. CopyFiles( HWND hDlg )
  346. {
  347. TCHAR szLayoutFilename[ MAX_PATH ];
  348. TCHAR szSystemPath[ MAX_PATH ];
  349. DWORD dwLen;
  350. LPTSTR psz;
  351. BOOL fReturn = FALSE;
  352. HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
  353. LPTSTR pszFiles = (LPTSTR) TraceAlloc( GMEM_FIXED, MAX_FILES_SIZE );
  354. DWORD dwCount = 0;
  355. DWORD dw;
  356. HSPFILEQ Queue;
  357. MYCONTEXT MyContext;
  358. if ( !pszFiles || g_Options.fAbort )
  359. goto Finish;
  360. // Setup and display next section of dialog
  361. SendMessage( hProg, PBM_SETRANGE, 0, MAKELPARAM(0, 1000 ));
  362. SendMessage( hProg, PBM_SETPOS, 0, 0 );
  363. dw = LoadString( g_hinstance, IDS_BUILDINGFILELIST, szLayoutFilename, ARRAYSIZE( szLayoutFilename ));
  364. Assert( dw );
  365. SetDlgItemText( hDlg, IDC_S_OPERATION, szLayoutFilename );
  366. // Create layout filepath
  367. lstrcpy( szLayoutFilename, g_Options.szSourcePath );
  368. dwLen = lstrlen( szLayoutFilename );
  369. szLayoutFilename[ dwLen ] = chSlash;
  370. dwLen++;
  371. dw = LoadString( g_hinstance, IDS_NTSETUPINFFILENAME,
  372. &szLayoutFilename[ dwLen ], ARRAYSIZE( szLayoutFilename )- dwLen );
  373. Assert( dw );
  374. Queue = SetupOpenFileQueue( );
  375. // add the files from the INF to the Queue
  376. GetPrivateProfileSection( TEXT("SourceDisksFiles"), pszFiles, MAX_FILES_SIZE,
  377. szLayoutFilename );
  378. LayoutToDoubleNullList( pszFiles );
  379. if ( g_Options.fIntel )
  380. {
  381. TCHAR szPath[ MAX_PATH ];
  382. DWORD dwLen;
  383. lstrcpy( szPath, g_Options.szSetupPath );
  384. dwLen = lstrlen( szPath );
  385. szPath[ dwLen++ ] = chSlash;
  386. dw = LoadString( g_hinstance, IDS_INTELPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
  387. Assert( dw );
  388. dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath,
  389. pszFiles, NULL, SP_COPY_NEWER | SP_COPY_WARNIFSKIP );
  390. // add the processor dependant files from the INF to the Queue
  391. GetPrivateProfileSection( TEXT("SourceDisksFiles.x86"), pszFiles, MAX_FILES_SIZE,
  392. szLayoutFilename );
  393. LayoutToDoubleNullList( pszFiles );
  394. dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath,
  395. pszFiles, NULL, SP_COPY_NEWER | SP_COPY_WARNIFSKIP );
  396. // additional files not listed
  397. dw = LoadString( g_hinstance, IDS_FILESTOBECOPIED, pszFiles, MAX_FILES_SIZE );
  398. SemiColonToDoubleNullList( pszFiles );
  399. dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath, pszFiles, NULL,
  400. SP_COPY_NEWER | SP_COPY_WARNIFSKIP );
  401. }
  402. if ( g_Options.fAlpha )
  403. {
  404. TCHAR szPath[ MAX_PATH ];
  405. DWORD dwLen;
  406. lstrcpy( szPath, g_Options.szSetupPath );
  407. dwLen = lstrlen( szPath );
  408. szPath[ dwLen++ ] = chSlash;
  409. dw = LoadString( g_hinstance, IDS_ALPHAPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
  410. Assert( dw );
  411. dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath,
  412. pszFiles, NULL, SP_COPY_NEWER | SP_COPY_WARNIFSKIP );
  413. // add the processor dependant files from the INF to the Queue
  414. GetPrivateProfileSection( TEXT("SourceDisksFiles.Alpha"), pszFiles, MAX_FILES_SIZE,
  415. szLayoutFilename );
  416. LayoutToDoubleNullList( pszFiles );
  417. dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath,
  418. pszFiles, NULL, SP_COPY_NEWER | SP_COPY_WARNIFSKIP );
  419. // additional files not listed
  420. dw = LoadString( g_hinstance, IDS_FILESTOBECOPIED, pszFiles, MAX_FILES_SIZE );
  421. Assert( dw );
  422. SemiColonToDoubleNullList( pszFiles );
  423. dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath, pszFiles, NULL,
  424. SP_COPY_NEWER | SP_COPY_WARNIFSKIP );
  425. }
  426. // add template files
  427. if ( g_Options.fIntel )
  428. {
  429. TCHAR szPath[ MAX_PATH ];
  430. DWORD dwLen;
  431. lstrcpy( szPath, g_Options.szRemoteBootPath );
  432. dwLen = lstrlen( szPath );
  433. szPath[ dwLen++ ] = chSlash;
  434. dw = LoadString( g_hinstance, IDS_TEMPLATEPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
  435. Assert( szPath );
  436. dwLen = lstrlen( szPath );
  437. szPath[ dwLen++ ] = chSlash;
  438. dw = LoadString( g_hinstance, IDS_INTELPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
  439. Assert( dw );
  440. dw = LoadString( g_hinstance, IDS_TEMPLATEFILES_INTEL, pszFiles, MAX_FILES_SIZE );
  441. Assert( dw );
  442. SemiColonToDoubleNullList( pszFiles );
  443. dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath,
  444. pszFiles, NULL, SP_COPY_NEWER | SP_COPY_NOOVERWRITE | SP_COPY_WARNIFSKIP );
  445. }
  446. if ( g_Options.fAlpha )
  447. {
  448. TCHAR szPath[ MAX_PATH ];
  449. DWORD dwLen;
  450. lstrcpy( szPath, g_Options.szRemoteBootPath );
  451. dwLen = lstrlen( szPath );
  452. szPath[ dwLen++ ] = chSlash;
  453. dw = LoadString( g_hinstance, IDS_TEMPLATEPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
  454. Assert( dw );
  455. dwLen = lstrlen( szPath );
  456. szPath[ dwLen++ ] = chSlash;
  457. dw = LoadString( g_hinstance, IDS_INTELPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
  458. Assert( dw );
  459. dw = LoadString( g_hinstance, IDS_TEMPLATEFILES_ALPHA, pszFiles, MAX_FILES_SIZE );
  460. Assert( dw );
  461. dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath,
  462. pszFiles, NULL, SP_COPY_NEWER | SP_COPY_NOOVERWRITE | SP_COPY_WARNIFSKIP );
  463. }
  464. /* BEGIN
  465. ADD/REMOVE PROGRAMS SHOULD DO THIS PART
  466. // add the services to the Queue
  467. GetSystemDirectory( szSystemPath, MAX_PATH );
  468. dw = LoadString( g_hinstance, IDS_SERVICESFILES, pszFiles, MAX_FILES_SIZE );
  469. Assert( dw );
  470. SemiColonToDoubleNullList( pszFiles );
  471. dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szSystemPath, pszFiles, NULL,
  472. SP_COPY_NEWER | SP_COPY_NOOVERWRITE | SP_COPY_WARNIFSKIP );
  473. END */
  474. // This information will be passed to CopyFileCallback() as
  475. // the Context.
  476. MyContext.nToBeCopied = dwCount;
  477. MyContext.nCopied = 0;
  478. MyContext.pContext = SetupInitDefaultQueueCallback( hDlg );
  479. MyContext.hProg = hProg;
  480. MyContext.hOperation = GetDlgItem( hDlg, IDC_S_OPERATION );
  481. MyContext.dwCopyingLength =
  482. LoadString( g_hinstance, IDS_COPYING, MyContext.szCopyingString,
  483. ARRAYSIZE( MyContext.szCopyingString ) );
  484. Assert( MyContext.dwCopyingLength );
  485. // Start copying
  486. fReturn = SetupCommitFileQueue( hDlg, Queue, (PSP_FILE_CALLBACK) CopyFilesCallback,
  487. (PVOID) &MyContext );
  488. Finish:
  489. SendMessage( hProg, PBM_SETPOS, 1000, 0 );
  490. if ( Queue )
  491. SetupCloseFileQueue( Queue );
  492. if ( pszFiles )
  493. TraceFree( pszFiles );
  494. g_Options.fError = !fReturn;
  495. return fReturn ? S_OK : E_FAIL;
  496. }
  497. //
  498. // Modifies registry entries from the SELFREG.INF resource
  499. //
  500. HRESULT
  501. ModifyRegistry( HWND hDlg )
  502. {
  503. HRESULT hr = E_FAIL;
  504. char szRemoteBootPath[ MAX_PATH ];
  505. TCHAR szText[ SMALL_BUFFER_SIZE ];
  506. STRENTRY seReg[] = {
  507. { "25", "%SystemRoot%" }, // NT-specific
  508. { "11", "%SystemRoot%\\system32" }, // NT-specific
  509. { "RemoteBoot", szRemoteBootPath },
  510. };
  511. STRTABLE stReg = { ARRAYSIZE(seReg), seReg };
  512. HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
  513. DWORD dw;
  514. SendMessage( hProg, PBM_SETRANGE, 0, MAKELPARAM(0, 1 ));
  515. SendMessage( hProg, PBM_SETPOS, 0, 0 );
  516. dw = LoadString( g_hinstance, IDS_UPDATING_REGISTRY, szText, ARRAYSIZE( szText ) );
  517. Assert( dw );
  518. SetWindowText( GetDlgItem( hDlg, IDC_S_OPERATION ), szText );
  519. // fill in substitution variables
  520. WideCharToMultiByte( CP_ACP, 0, g_Options.szRemoteBootPath, -1,
  521. szRemoteBootPath, ARRAYSIZE( szRemoteBootPath ), NULL, NULL );
  522. hr = THR( RegInstall( g_hinstance, "InstallRemoteBoot", &stReg) );
  523. SendMessage( hProg, PBM_SETPOS, 1 , 0 );
  524. return hr;
  525. }
  526. //
  527. // Creates the services needed for remote boot.
  528. //
  529. HRESULT
  530. StartRemoteBootServices( HWND hDlg )
  531. {
  532. TCHAR szTFTPD[ SMALL_BUFFER_SIZE ];
  533. TCHAR szBINL[ SMALL_BUFFER_SIZE ];
  534. TCHAR szTFTPDName[ SMALL_BUFFER_SIZE ];
  535. TCHAR szBINLName[ SMALL_BUFFER_SIZE ];
  536. TCHAR szText[ SMALL_BUFFER_SIZE ];
  537. SC_HANDLE schSystem;
  538. SC_HANDLE schTFTPD;
  539. SC_HANDLE schTCPService;
  540. DWORD dwErr = S_OK;
  541. HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
  542. DWORD dw;
  543. SendMessage( hProg, PBM_SETRANGE, 0, MAKELPARAM(0, 1 ));
  544. SendMessage( hProg, PBM_SETPOS, 0, 0 );
  545. dw = LoadString( g_hinstance, IDS_STARTING_SERVICES, szText, ARRAYSIZE( szText ) );
  546. Assert( dw );
  547. SetDlgItemText( hDlg, IDC_S_OPERATION, szText );
  548. dw = LoadString( g_hinstance, IDS_TFTPD, szTFTPD,
  549. ARRAYSIZE( szTFTPD ) );
  550. Assert( dw );
  551. dw = LoadString( g_hinstance, IDS_BINL, szBINL,
  552. ARRAYSIZE( szBINL ) );
  553. Assert( dw );
  554. dw = LoadString( g_hinstance, IDS_TFTPD_SERVICENAME, szTFTPDName,
  555. ARRAYSIZE( szTFTPDName ) );
  556. Assert( dw );
  557. dw = LoadString( g_hinstance, IDS_BINL_SERVICENAME, szBINLName,
  558. ARRAYSIZE( szBINLName ) );
  559. Assert( dw );
  560. schSystem = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
  561. Assert( schSystem );
  562. if ( !schSystem )
  563. goto Cleanup;
  564. schTFTPD = OpenService( schSystem, szTFTPD,
  565. STANDARD_RIGHTS_REQUIRED | SERVICE_START );
  566. schTCPService = OpenService( schSystem, szBINL,
  567. STANDARD_RIGHTS_REQUIRED | SERVICE_START );
  568. // start TFTPD
  569. if ( !StartService( schTFTPD, 0, NULL ) )
  570. {
  571. dwErr = GetLastError( );
  572. switch ( dwErr )
  573. {
  574. default:
  575. dw = LoadString( g_hinstance, IDS_ERROR_STARTING_SERVICE, szText,
  576. ARRAYSIZE( szText ) );
  577. Assert( dw );
  578. MessageBox( hDlg, szText, szTFTPDName, MB_OK );
  579. break;
  580. case ERROR_SERVICE_ALREADY_RUNNING:
  581. break;
  582. }
  583. }
  584. // start TCP services
  585. dw = LoadString( g_hinstance, IDS_STARTING_SERVICES, szText, ARRAYSIZE( szText ) );
  586. Assert( dw );
  587. SetDlgItemText( hDlg, IDC_S_OPERATION, szText );
  588. if ( !StartService( schTCPService, 0, NULL ) )
  589. {
  590. dwErr = GetLastError( );
  591. switch ( dwErr )
  592. {
  593. default:
  594. dw = LoadString( g_hinstance, IDS_ERROR_STARTING_SERVICE, szText,
  595. ARRAYSIZE( szText ) );
  596. Assert( dw );
  597. MessageBox( hDlg, szText, szBINLName, MB_OK );
  598. break;
  599. case ERROR_SERVICE_ALREADY_RUNNING:
  600. break;
  601. }
  602. }
  603. SendMessage( hProg, PBM_SETPOS, 1 , 0 );
  604. Cleanup:
  605. if ( schTCPService )
  606. CloseServiceHandle( schTCPService );
  607. if ( schTFTPD )
  608. CloseServiceHandle( schTFTPD );
  609. if ( schSystem )
  610. CloseServiceHandle( schSystem );
  611. return dwErr;
  612. }
  613. //
  614. // create RemoteBoot share
  615. //
  616. HRESULT
  617. CreateRemoteBootShare( HWND hDlg )
  618. {
  619. SHARE_INFO_502 si502;
  620. TCHAR szRemark[ SMALL_BUFFER_SIZE ];
  621. TCHAR szRemoteBoot[ SMALL_BUFFER_SIZE ];
  622. TCHAR szText[ SMALL_BUFFER_SIZE ];
  623. DWORD dwErr;
  624. HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
  625. DWORD dw;
  626. dw = LoadString( g_hinstance, IDS_CREATINGSHARES, szText, ARRAYSIZE( szText ) );
  627. Assert( dw );
  628. SetDlgItemText( hDlg, IDC_S_OPERATION, szText );
  629. dw = LoadString( g_hinstance, IDS_REMOTEBOOTSHAREREMARK, szRemark,
  630. ARRAYSIZE( szRemark ) );
  631. Assert( dw );
  632. dw = LoadString( g_hinstance, IDS_REMOTEBOOTSHARENAME, szRemoteBoot,
  633. ARRAYSIZE( szRemoteBoot ) );
  634. Assert( dw );
  635. si502.shi502_netname = szRemoteBoot;
  636. si502.shi502_type = STYPE_DISKTREE;
  637. si502.shi502_remark = szRemark;
  638. si502.shi502_permissions = ACCESS_ALL;
  639. si502.shi502_max_uses = -1; // unlimited
  640. si502.shi502_current_uses = 0;
  641. si502.shi502_path = g_Options.szRemoteBootPath;
  642. si502.shi502_passwd = NULL; // ignored
  643. si502.shi502_reserved = 0; // must be zero
  644. si502.shi502_security_descriptor = NULL;
  645. NetShareAdd( NULL, 502, (LPBYTE) &si502, &dwErr );
  646. switch ( dwErr )
  647. {
  648. // ignore these
  649. case NERR_Success:
  650. case NERR_DuplicateShare:
  651. break;
  652. default:
  653. MessageBoxFromStrings( hDlg, IDS_SHAREERRORCAPTION, IDS_SHAREERRORTEXT, MB_OK );
  654. }
  655. SendMessage( hProg, PBM_DELTAPOS, 1 , 0 );
  656. return dwErr;
  657. }