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.

778 lines
22 KiB

  1. /****************************************************************************
  2. Copyright (c) Microsoft Corporation 1997
  3. All rights reserved
  4. ***************************************************************************/
  5. #include "pch.h"
  6. #include <windowsx.h>
  7. #include <setupapi.h>
  8. #include <advpub.h>
  9. #include <regstr.h>
  10. #include <lm.h>
  11. #include "utils.h"
  12. DEFINE_MODULE("Main");
  13. // Globals
  14. HINSTANCE g_hinstance = NULL;
  15. #define SMALL_BUFFER_SIZE 256
  16. #define MAX_FILES_SIZE 512
  17. #define STRING_BUFFER_SIZE 65535
  18. static TCHAR g_szServerName[ SMALL_BUFFER_SIZE ] = { 0 };
  19. static TCHAR g_szRemoteBoot[ SMALL_BUFFER_SIZE ] = { 0 };
  20. static TCHAR g_szBootFilename[ SMALL_BUFFER_SIZE ] = { 0 };
  21. static TCHAR g_szBootIniOptions[ SMALL_BUFFER_SIZE ] = { 0 };
  22. static TCHAR g_szClientName[ SMALL_BUFFER_SIZE ] = { 0 };
  23. static TCHAR g_szMAC[ SMALL_BUFFER_SIZE ] = { 0 };
  24. static TCHAR g_szInstallation[ SMALL_BUFFER_SIZE ] = { 0 };
  25. static TCHAR g_szClientDomain[ SMALL_BUFFER_SIZE ] = { 0 };
  26. static TCHAR g_szAdminUser[ SMALL_BUFFER_SIZE ] = { 0 };
  27. static TCHAR g_szAdminPasswd[ SMALL_BUFFER_SIZE ] = { 0 };
  28. static TCHAR g_szWinntTemplate[ SMALL_BUFFER_SIZE ] = { 0 };
  29. // search and replace structure
  30. typedef struct {
  31. LPTSTR pszToken;
  32. LPTSTR pszString;
  33. } SAR, * LPSAR;
  34. //
  35. // Searches and replaces text.
  36. //
  37. // NOTE: There is no check for writing beyond the buffer even though
  38. // I passed the paramater.
  39. //
  40. void
  41. SearchAndReplace(
  42. LPSAR psarList,
  43. LPTSTR pszString,
  44. DWORD dwSize )
  45. {
  46. LPTSTR psz = pszString;
  47. if ( !psarList || !pszString )
  48. return;
  49. while ( *psz )
  50. {
  51. if ( *psz == TEXT('%') )
  52. {
  53. LPSAR psar = psarList;
  54. psz++; // move forward
  55. while( psar->pszToken )
  56. {
  57. int iCmp;
  58. DWORD dwString = lstrlen( psar->pszString );
  59. DWORD dwToken = lstrlen( psar->pszToken );
  60. LPTSTR pszTemp = psz + dwToken;
  61. TCHAR ch = *pszTemp;
  62. *pszTemp = 0;
  63. iCmp = lstrcmpi( psz, psar->pszToken );
  64. *pszTemp = ch;
  65. if ( !iCmp )
  66. { // match, so replace
  67. psz--; // move back
  68. if ( 2 + dwToken < dwString )
  69. {
  70. DWORD dwLen = lstrlen( &psz[ 2 + dwToken ] ) + 1;
  71. MoveMemory( &psz[ dwString ], &psz[ 2 + dwToken ], dwLen * sizeof(TCHAR));
  72. }
  73. CopyMemory( psz, psar->pszString, dwString * sizeof(TCHAR) );
  74. if ( 2 + dwToken > dwString )
  75. {
  76. lstrcpy( &psz[ dwString ], &psz[ 2 + dwToken ] );
  77. }
  78. psz++; // move forward
  79. break;
  80. }
  81. psar++;
  82. }
  83. }
  84. else
  85. {
  86. psz++;
  87. }
  88. }
  89. }
  90. //
  91. // Munge the registry
  92. //
  93. LONG
  94. MungeRegistry(
  95. LPCTSTR pszPath,
  96. LPCTSTR pszKey,
  97. LPTSTR pszResult,
  98. LPDWORD pdwSize )
  99. {
  100. HKEY hkeyComputer;
  101. LONG lResult;
  102. lResult = RegOpenKey( HKEY_LOCAL_MACHINE,
  103. pszPath,
  104. &hkeyComputer );
  105. if ( lResult != ERROR_SUCCESS )
  106. goto Finish;
  107. lResult = RegQueryValueEx( hkeyComputer,
  108. pszKey,
  109. NULL, // reserved
  110. NULL, // type
  111. (LPBYTE) pszResult,
  112. pdwSize );
  113. RegCloseKey( hkeyComputer );
  114. Finish:
  115. return lResult;
  116. }
  117. //
  118. // Munges the registry for the computer name
  119. //
  120. LONG
  121. RetrieveComputerName( void )
  122. {
  123. DWORD dwSize = sizeof( g_szServerName );
  124. return MungeRegistry( REGSTR_PATH_COMPUTRNAME,
  125. REGSTR_VAL_COMPUTERNAME,
  126. g_szServerName,
  127. &dwSize );
  128. }
  129. //
  130. // Populates the Installation ComboBox
  131. //
  132. HRESULT
  133. PopulateInstallationComboBox(
  134. HWND hDlg )
  135. {
  136. BOOL fKeepSearching = TRUE;
  137. HRESULT hr = S_OK;
  138. TCHAR szPath[ MAX_PATH ];
  139. DWORD dwLen;
  140. WIN32_FIND_DATA fd;
  141. HANDLE handle;
  142. HWND hwndCB = GetDlgItem( hDlg, IDC_CB_INSTALLATION );
  143. LPSHARE_INFO_2 psi = NULL;
  144. NetShareGetInfo( NULL, // this machine
  145. g_szRemoteBoot,
  146. 2, // share level 2
  147. (LPBYTE *) &psi );
  148. // create the directory
  149. lstrcpy( szPath, psi->shi2_path );
  150. dwLen = lstrlen( szPath );
  151. szPath[ dwLen++ ] = TEXT('\\');
  152. LoadString( g_hinstance, IDS_SETUP, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
  153. dwLen = lstrlen( szPath );
  154. lstrcpy( &szPath[ dwLen ], TEXT("\\*") );
  155. handle = FindFirstFile( szPath, &fd );
  156. if ( handle == INVALID_HANDLE_VALUE )
  157. goto Cleanup;
  158. while ( fKeepSearching)
  159. {
  160. if ( fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY &&
  161. lstrcmp( fd.cFileName, TEXT(".") ) && // ignore
  162. lstrcmp( fd.cFileName, TEXT("..") ) ) // ignore
  163. {
  164. ComboBox_AddString( hwndCB, fd.cFileName );
  165. }
  166. fKeepSearching = FindNextFile( handle, &fd );
  167. }
  168. ComboBox_SetCurSel( hwndCB, 0 );
  169. Cleanup:
  170. if ( handle != INVALID_HANDLE_VALUE)
  171. FindClose( handle );
  172. if ( psi )
  173. NetApiBufferFree( psi );
  174. return hr;
  175. }
  176. //
  177. // Populates the Configuration ComboBox
  178. //
  179. HRESULT
  180. PopulateConfigurationComboBox(
  181. HWND hDlg )
  182. {
  183. BOOL fKeepSearching = TRUE;
  184. HRESULT hr = S_OK;
  185. TCHAR szPath[ MAX_PATH ];
  186. DWORD dwLen;
  187. WIN32_FIND_DATA fd;
  188. HANDLE handle;
  189. HWND hwndCB = GetDlgItem( hDlg, IDC_CB_WINNTSIF );
  190. LPSHARE_INFO_2 psi = NULL;
  191. int iSel;
  192. ComboBox_ResetContent( hwndCB );
  193. NetShareGetInfo( NULL, // this machine
  194. g_szRemoteBoot,
  195. 2, // share level 2
  196. (LPBYTE *) &psi );
  197. // create the directory
  198. lstrcpy( szPath, psi->shi2_path );
  199. dwLen = lstrlen( szPath );
  200. szPath[ dwLen++ ] = TEXT('\\');
  201. LoadString( g_hinstance, IDS_TEMPLATES, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
  202. dwLen = lstrlen( szPath );
  203. szPath[ dwLen++ ] = TEXT('\\');
  204. LoadString( g_hinstance, IDS_INTELPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
  205. dwLen = lstrlen( szPath );
  206. szPath[ dwLen++ ] = TEXT('\\');
  207. LoadString( g_hinstance, IDS_WINNTTEMPLATEFILES, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
  208. handle = FindFirstFile( szPath, &fd );
  209. if ( handle == INVALID_HANDLE_VALUE )
  210. goto Cleanup;
  211. while ( fKeepSearching)
  212. {
  213. // whack it at the period
  214. LPTSTR psz = fd.cFileName;
  215. while ( *psz )
  216. {
  217. if ( *psz == TEXT('.') )
  218. {
  219. *psz = 0;
  220. break;
  221. }
  222. psz++;
  223. }
  224. ComboBox_AddString( hwndCB, fd.cFileName );
  225. fKeepSearching = FindNextFile( handle, &fd );
  226. }
  227. ComboBox_SetCurSel( hwndCB, 0 );
  228. Cleanup:
  229. if ( handle != INVALID_HANDLE_VALUE)
  230. FindClose( handle );
  231. if ( psi )
  232. NetApiBufferFree( psi );
  233. return hr;
  234. }
  235. //
  236. //
  237. //
  238. BOOL CALLBACK
  239. ClientDlgProc(
  240. HWND hDlg,
  241. UINT uMsg,
  242. WPARAM wParam,
  243. LPARAM lParam )
  244. {
  245. NMHDR FAR *lpnmhdr;
  246. DWORD dw;
  247. switch ( uMsg )
  248. {
  249. case WM_INITDIALOG:
  250. CenterDialog( hDlg );
  251. SetDlgItemText( hDlg, IDC_E_SERVER, g_szServerName );
  252. SetDlgItemText( hDlg, IDC_E_REMOTEBOOT, g_szRemoteBoot );
  253. SetDlgItemText( hDlg, IDC_E_BOOTFILENAME, g_szBootFilename );
  254. SetDlgItemText( hDlg, IDC_E_BOOTINIOPTIONS, g_szBootIniOptions);
  255. PopulateInstallationComboBox( hDlg );
  256. PopulateConfigurationComboBox( hDlg );
  257. Edit_LimitText( GetDlgItem( hDlg, IDC_E_MAC ), 12 );
  258. break;
  259. case WM_COMMAND:
  260. {
  261. switch ( LOWORD( wParam ) )
  262. {
  263. case IDOK:
  264. {
  265. DWORD dwLen;
  266. TCHAR sz[ SMALL_BUFFER_SIZE ];
  267. GetDlgItemText( hDlg, IDC_E_SERVER, g_szServerName, ARRAYSIZE( g_szServerName ));
  268. GetDlgItemText( hDlg, IDC_E_REMOTEBOOT, g_szRemoteBoot, ARRAYSIZE( g_szRemoteBoot ));
  269. GetDlgItemText( hDlg, IDC_E_BOOTFILENAME, g_szBootFilename, ARRAYSIZE( g_szBootFilename ));
  270. GetDlgItemText( hDlg, IDC_E_BOOTINIOPTIONS, g_szBootIniOptions, ARRAYSIZE( g_szBootIniOptions ));
  271. GetDlgItemText( hDlg, IDC_E_MAC, g_szMAC, ARRAYSIZE( g_szMAC ));
  272. GetDlgItemText( hDlg, IDC_E_MACHINENAME, g_szClientName, ARRAYSIZE( g_szClientName ));
  273. GetDlgItemText( hDlg, IDC_CB_INSTALLATION, g_szInstallation, ARRAYSIZE( g_szInstallation ));
  274. GetDlgItemText( hDlg, IDC_E_CLIENTDOMAIN, g_szClientDomain, ARRAYSIZE( g_szClientDomain ));
  275. GetDlgItemText( hDlg, IDC_E_ADMINUSER, g_szAdminUser, ARRAYSIZE( g_szAdminUser ));
  276. GetDlgItemText( hDlg, IDC_E_ADMINPASSWD, g_szAdminPasswd, ARRAYSIZE( g_szAdminPasswd ));
  277. GetDlgItemText( hDlg, IDC_CB_WINNTSIF, g_szWinntTemplate, ARRAYSIZE( g_szWinntTemplate ));
  278. // add that extension
  279. dw = LoadString( g_hinstance, IDS_WINNTTEMPLATEFILES, sz, ARRAYSIZE( sz ));
  280. Assert( dw );
  281. dwLen = lstrlen( g_szWinntTemplate );
  282. lstrcpy( &g_szWinntTemplate[ dwLen ], &sz[ 1 ] );
  283. EndDialog( hDlg, IDOK );
  284. }
  285. break;
  286. case IDCANCEL:
  287. EndDialog( hDlg, IDCANCEL );
  288. break;
  289. }
  290. }
  291. break;
  292. default:
  293. return FALSE;
  294. }
  295. return TRUE;
  296. }
  297. //
  298. // change semicolon delinated list to double-null list
  299. //
  300. void
  301. SemiColonToDoubleNullList( LPTSTR pszList )
  302. {
  303. while ( *pszList )
  304. {
  305. if ( *pszList == TEXT(';') )
  306. {
  307. *pszList = 0;
  308. }
  309. pszList++;
  310. }
  311. pszList++;
  312. *pszList = 0; // double the null.
  313. }
  314. //
  315. // Adds files to the Queue to be copied. It returns the number of files added
  316. // to the Queue.
  317. //
  318. DWORD
  319. CopyFilesAddToQueue(
  320. HSPFILEQ Queue, // setup Queue
  321. LPTSTR pszSource,
  322. LPTSTR pszDest,
  323. LPTSTR pszFiles, // Double-null terminated file list
  324. LPTSTR pszSubpath ) // optional sub-path
  325. {
  326. DWORD dwCount = 0;
  327. LPTSTR psz = pszFiles;
  328. while ( *pszFiles )
  329. {
  330. DWORD dwLen;
  331. // check for comma which indicates rename
  332. psz = pszFiles;
  333. while (*psz && *psz != TEXT(','))
  334. psz++;
  335. if ( *psz == TEXT(',') )
  336. {
  337. *psz= 0; // terminate
  338. psz++;
  339. }
  340. else
  341. { // sources name is dest name
  342. psz = pszFiles;
  343. }
  344. SetupQueueCopy(
  345. Queue,
  346. pszSource,
  347. NULL,
  348. pszFiles,
  349. NULL,
  350. NULL,
  351. pszDest,
  352. psz,
  353. SP_COPY_NEWER | SP_COPY_NOOVERWRITE | SP_COPY_WARNIFSKIP );
  354. // get next file
  355. pszFiles = psz + lstrlen( psz ) + 1;
  356. dwCount++;
  357. }
  358. return dwCount;
  359. }
  360. //
  361. //
  362. //
  363. HRESULT
  364. SetupClient( )
  365. {
  366. HRESULT hr = E_FAIL;
  367. TCHAR szImage[ MAX_PATH ];
  368. TCHAR szSetup[ MAX_PATH ];
  369. TCHAR szTemplates[ MAX_PATH ];
  370. TCHAR szBootIni[ MAX_PATH ];
  371. TCHAR szString[ MAX_PATH ];
  372. TCHAR szDosNetFilename[ MAX_PATH ];
  373. TCHAR szWinntSif[ MAX_PATH ];
  374. DWORD dwLen;
  375. DWORD dw;
  376. HSPFILEQ Queue;
  377. PVOID pContext;
  378. HANDLE hFile = INVALID_HANDLE_VALUE;
  379. HKEY hkeyBINL;
  380. HKEY hkeyMAC;
  381. LPTSTR pszFiles = (LPTSTR) TraceAlloc( GMEM_FIXED, MAX_FILES_SIZE );
  382. LPTSTR psz = NULL;
  383. LPSHARE_INFO_2 psi = NULL;
  384. LPVOID args[ 6 ];
  385. SAR sExpand[] = {
  386. { TEXT("BINLSERVER"), g_szServerName },
  387. { TEXT("INSTALLATION"), g_szInstallation },
  388. { TEXT("CLIENTNAME"), g_szClientName },
  389. { TEXT("REMOTEBOOT"), g_szRemoteBoot },
  390. { TEXT("CLIENTDOMAIN"), g_szClientDomain },
  391. { TEXT("ADMINUSER"), g_szAdminUser },
  392. { TEXT("ADMINPASSWD"), g_szAdminPasswd },
  393. { NULL, NULL } // end of list
  394. };
  395. char chString[ STRING_BUFFER_SIZE ];
  396. NetShareGetInfo( NULL, // this machine
  397. g_szRemoteBoot,
  398. 2, // share level 2
  399. (LPBYTE *) &psi );
  400. // create the directory
  401. lstrcpy( szImage, psi->shi2_path );
  402. dwLen = lstrlen( szImage );
  403. szImage[ dwLen++ ] = TEXT('\\');
  404. dw = LoadString( g_hinstance, IDS_IMAGES, &szImage[ dwLen ], ARRAYSIZE( szImage ) - dwLen );
  405. Assert( dw );
  406. dwLen = lstrlen( szImage );
  407. szImage[ dwLen++ ] = TEXT('\\');
  408. lstrcpy( &szImage[ dwLen ], g_szClientName );
  409. CreateDirectory( szImage, NULL );
  410. // setup path
  411. lstrcpy( szSetup, psi->shi2_path );
  412. dwLen = lstrlen( szSetup );
  413. szSetup[ dwLen++ ] = TEXT('\\');
  414. dw = LoadString( g_hinstance, IDS_SETUP, &szSetup[ dwLen ], ARRAYSIZE( szSetup ) - dwLen );
  415. Assert( dw );
  416. dwLen = lstrlen( szSetup );
  417. szSetup[ dwLen++ ] = TEXT('\\');
  418. lstrcpy( &szSetup[ dwLen ], g_szInstallation );
  419. dwLen = lstrlen( szSetup );
  420. szSetup[ dwLen++ ] = TEXT('\\');
  421. dw = LoadString( g_hinstance, IDS_INTELPATH, &szSetup[ dwLen ], ARRAYSIZE( szSetup ) - dwLen );
  422. Assert( dw );
  423. // Create DOSNET.INF filepath
  424. lstrcpy( szDosNetFilename, szSetup );
  425. dwLen = lstrlen( szDosNetFilename );
  426. szDosNetFilename[ dwLen ] = TEXT('\\');
  427. dwLen++;
  428. dw = LoadString( g_hinstance, IDS_DOSNETINFFILENAME,
  429. &szDosNetFilename[ dwLen ], ARRAYSIZE( szDosNetFilename ) - dwLen );
  430. Assert( dw );
  431. Queue = SetupOpenFileQueue( );
  432. // Retrieve the list of files from the INF and add to Queue
  433. GetPrivateProfileSection( TEXT("RootBootFiles"), pszFiles, MAX_FILES_SIZE,
  434. szDosNetFilename );
  435. CopyFilesAddToQueue( Queue, szSetup, szImage, pszFiles, NULL );
  436. // add additional files from resources
  437. dw = LoadString( g_hinstance, IDS_FILESTOBECOPIED, pszFiles, MAX_FILES_SIZE );
  438. Assert( dw );
  439. SemiColonToDoubleNullList( pszFiles );
  440. CopyFilesAddToQueue( Queue, szSetup, szImage, pszFiles, NULL );
  441. // copy winnt.sif template
  442. lstrcpy( szTemplates, psi->shi2_path );
  443. dwLen = lstrlen( szTemplates );
  444. szTemplates[ dwLen++ ] = TEXT('\\');
  445. dw = LoadString( g_hinstance, IDS_TEMPLATES, &szTemplates[ dwLen ], ARRAYSIZE( szTemplates ) - dwLen );
  446. Assert( dw );
  447. dwLen = lstrlen( szTemplates );
  448. szTemplates[ dwLen++ ] = TEXT('\\');
  449. dw = LoadString( g_hinstance, IDS_INTELPATH, &szTemplates[ dwLen ], ARRAYSIZE( szTemplates ) - dwLen );
  450. Assert( dw );
  451. lstrcpy( pszFiles, g_szWinntTemplate );
  452. dwLen = lstrlen( pszFiles );
  453. pszFiles[ dwLen++ ] = TEXT(',');
  454. dw = LoadString( g_hinstance, IDS_WINNTSIF, &pszFiles[ dwLen ], MAX_PATH );
  455. Assert( dw );
  456. SemiColonToDoubleNullList( pszFiles );
  457. CopyFilesAddToQueue( Queue, szTemplates, szImage, pszFiles, NULL );
  458. TraceFree( pszFiles );
  459. pContext = SetupInitDefaultQueueCallback( NULL );
  460. if (!SetupCommitFileQueue( NULL, Queue, SetupDefaultQueueCallback,
  461. pContext ) )
  462. goto Cleanup;
  463. dw = LoadString( g_hinstance, IDS_REG_BINL_PARAMETER, szString, ARRAYSIZE( szString ));
  464. Assert( dw );
  465. if ( ERROR_SUCCESS ==
  466. RegOpenKey( HKEY_LOCAL_MACHINE, szString, &hkeyBINL ) )
  467. {
  468. if ( ERROR_SUCCESS ==
  469. RegCreateKey( hkeyBINL, g_szMAC, &hkeyMAC ) )
  470. {
  471. dw = LoadString( g_hinstance, IDS_IMAGES, szString, ARRAYSIZE( dw ));
  472. Assert( dw );
  473. dwLen = lstrlen( szString );
  474. szString[ dwLen++ ] = TEXT('\\');
  475. lstrcpy( &szString[ dwLen ], g_szClientName );
  476. dwLen = lstrlen( szString );
  477. szString[ dwLen++ ] = TEXT('\\');
  478. lstrcpy( &szString[ dwLen ], g_szBootFilename );
  479. dwLen = ( lstrlen( szString ) + 1 ) * sizeof(TCHAR);
  480. RegSetValueEx( hkeyMAC, TEXT("BootFileName"), 0, REG_SZ, (LPBYTE) szString, dwLen );
  481. dwLen = ( lstrlen( g_szServerName ) + 1 ) * sizeof(TCHAR);
  482. RegSetValueEx( hkeyMAC, TEXT("HostName"), 0, REG_SZ, (LPBYTE) g_szServerName, dwLen );
  483. RegCloseKey( hkeyMAC );
  484. }
  485. RegCloseKey( hkeyBINL );
  486. }
  487. // create MAC Address file
  488. lstrcpy( szString, szImage );
  489. dwLen = lstrlen( szString );
  490. szString[ dwLen++ ] = TEXT('\\');
  491. lstrcpy( &szString[ dwLen ], g_szMAC );
  492. hFile = CreateFile( szString,
  493. GENERIC_WRITE,
  494. FILE_SHARE_READ,
  495. NULL, // security attribs
  496. CREATE_ALWAYS,
  497. FILE_ATTRIBUTE_NORMAL, // maybe FILE_ATTRIBUTE_HIDDEN
  498. NULL ); // template
  499. CloseHandle( hFile );
  500. lstrcpy( szBootIni, szImage );
  501. dwLen = lstrlen( szBootIni );
  502. szBootIni[ dwLen++ ] = TEXT('\\');
  503. dw = LoadString( g_hinstance, IDS_BOOTINI, &szBootIni[ dwLen ], ARRAYSIZE( szBootIni ) - dwLen );
  504. Assert( dw );
  505. hFile = CreateFile( szBootIni,
  506. GENERIC_WRITE,
  507. FILE_SHARE_READ,
  508. NULL, // security attribs
  509. CREATE_ALWAYS,
  510. FILE_ATTRIBUTE_NORMAL, // maybe FILE_ATTRIBUTE_HIDDEN
  511. NULL ); // template
  512. if ( hFile == INVALID_HANDLE_VALUE )
  513. goto Cleanup;
  514. dw = LoadString( g_hinstance, IDS_BOOTLOADER, szString, ARRAYSIZE( szString ));
  515. Assert( dw );
  516. args[0] = (LPVOID) &g_szServerName;
  517. args[1] = (LPVOID) &g_szRemoteBoot;
  518. args[2] = (LPVOID) &g_szClientName;
  519. args[3] = (LPVOID) &g_szInstallation;
  520. args[4] = (LPVOID) &g_szBootIniOptions;
  521. FormatMessage(
  522. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING |
  523. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  524. szString,
  525. NULL, // message id - n/a
  526. NULL, // language - use system
  527. (LPTSTR) &psz,
  528. 0, // minimum length
  529. (char **) &args );
  530. DebugMemoryAddAddress( psz );
  531. WideCharToMultiByte( CP_ACP, 0, psz, -1, chString, ARRAYSIZE( chString ), NULL, NULL );
  532. dwLen = lstrlenA( chString );
  533. WriteFile( hFile, chString, dwLen, &dw, NULL );
  534. CloseHandle( hFile );
  535. TraceFree( psz );
  536. // process WINNT.SIF
  537. lstrcpy( szWinntSif, szImage );
  538. dwLen = lstrlen( szWinntSif );
  539. szWinntSif[ dwLen++ ] = TEXT('\\');
  540. dw = LoadString( g_hinstance, IDS_WINNTSIF, &szWinntSif[ dwLen ], ARRAYSIZE( szWinntSif ) - dwLen );
  541. Assert( dw );
  542. hFile = CreateFile( szWinntSif,
  543. GENERIC_READ,
  544. FILE_SHARE_READ,
  545. NULL, // security attribs
  546. OPEN_EXISTING,
  547. FILE_ATTRIBUTE_NORMAL, // maybe FILE_ATTRIBUTE_HIDDEN
  548. NULL ); // template
  549. if ( hFile == INVALID_HANDLE_VALUE )
  550. goto Cleanup;
  551. ReadFile( hFile, chString, ARRAYSIZE( chString ), &dw, NULL );
  552. Assert( dw != ARRAYSIZE( chString ));
  553. CloseHandle( hFile );
  554. psz = (LPTSTR) TraceAlloc( GMEM_FIXED, ARRAYSIZE( chString ));
  555. MultiByteToWideChar( CP_ACP, 0, chString, -1, psz, ARRAYSIZE( chString ));
  556. SearchAndReplace( sExpand, psz, ARRAYSIZE( chString ));
  557. hFile = CreateFile( szWinntSif,
  558. GENERIC_WRITE,
  559. FILE_SHARE_READ,
  560. NULL, // security attribs
  561. CREATE_ALWAYS,
  562. FILE_ATTRIBUTE_NORMAL, // maybe FILE_ATTRIBUTE_HIDDEN
  563. NULL ); // template
  564. if ( hFile == INVALID_HANDLE_VALUE )
  565. goto Cleanup;
  566. WideCharToMultiByte( CP_ACP, 0, psz, -1, chString, ARRAYSIZE( chString ), NULL, NULL );
  567. dwLen = lstrlenA( chString );
  568. WriteFile( hFile, chString, dwLen, &dw, NULL );
  569. CloseHandle( hFile );
  570. TraceFree( psz );
  571. hr = S_OK;
  572. Cleanup:
  573. if ( Queue )
  574. SetupCloseFileQueue( Queue );
  575. if ( psi )
  576. NetApiBufferFree( psi );
  577. return hr;
  578. }
  579. //
  580. // WinMain()
  581. //
  582. int APIENTRY
  583. WinMain(
  584. HINSTANCE hInstance,
  585. HINSTANCE hPrevInstance,
  586. LPSTR lpCmdLine,
  587. int nCmdShow)
  588. {
  589. HANDLE hMutex;
  590. HRESULT hr = S_OK;
  591. DWORD dw;
  592. g_hinstance = hInstance;
  593. INITIALIZE_TRACE_MEMORY;
  594. // Initialize
  595. RetrieveComputerName( );
  596. dw = LoadString( g_hinstance, IDS_REMOTEBOOT, g_szRemoteBoot, ARRAYSIZE( g_szRemoteBoot ));
  597. Assert( dw );
  598. dw = LoadString( g_hinstance, IDS_BOOTFILENAME, g_szBootFilename, ARRAYSIZE( g_szBootFilename ));
  599. Assert( dw );
  600. dw = LoadString( g_hinstance, IDS_BOOTINIOPTIONS, g_szBootIniOptions, ARRAYSIZE( g_szBootIniOptions ));
  601. Assert( dw );
  602. if ( IDOK == DialogBox( g_hinstance, MAKEINTRESOURCE( IDD_CLIENT ), NULL, ClientDlgProc ) )
  603. {
  604. if ( lstrlen( g_szMAC ) != 12 )
  605. goto Cleanup;
  606. if ( !lstrlen( g_szClientName ) )
  607. goto Cleanup;
  608. hr = SetupClient( );
  609. }
  610. Cleanup:
  611. UNINITIALIZE_TRACE_MEMORY;
  612. RRETURN(hr);
  613. }
  614. // stolen from the CRT, used to shrink our code
  615. int _stdcall ModuleEntry(void)
  616. {
  617. int i;
  618. STARTUPINFOA si;
  619. LPSTR pszCmdLine = GetCommandLineA();
  620. if ( *pszCmdLine == '\"' )
  621. {
  622. /*
  623. * Scan, and skip over, subsequent characters until
  624. * another double-quote or a null is encountered.
  625. */
  626. while ( *++pszCmdLine && (*pszCmdLine != '\"') );
  627. /*
  628. * If we stopped on a double-quote (usual case), skip
  629. * over it.
  630. */
  631. if ( *pszCmdLine == '\"' )
  632. pszCmdLine++;
  633. }
  634. else
  635. {
  636. while (*pszCmdLine > ' ')
  637. pszCmdLine++;
  638. }
  639. /*
  640. * Skip past any white space preceeding the second token.
  641. */
  642. while (*pszCmdLine && (*pszCmdLine <= ' '))
  643. {
  644. pszCmdLine++;
  645. }
  646. si.dwFlags = 0;
  647. GetStartupInfoA(&si);
  648. i = WinMain(GetModuleHandle(NULL), NULL, pszCmdLine,
  649. si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT);
  650. ExitProcess(i);
  651. return i; // We never come here.
  652. }