Leaked source code of windows server 2003
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.

1268 lines
40 KiB

  1. ////////////////////////////////////////////////////////////////////////////////////////////////////
  2. // Look at the header file for usage information...
  3. #include "precomp.h"
  4. #include "resource.h"
  5. #include <direct.h>
  6. #include "PropPg.h"
  7. #include "PShtHdr.h"
  8. #include "NmAkWiz.h"
  9. #include "PolData.h"
  10. #include "NMAKReg.h"
  11. /////////////////
  12. // Global
  13. /////////////////
  14. CNmAkWiz * g_pWiz = NULL;
  15. HWND g_hwndActive = NULL;
  16. HINSTANCE g_hInstance = NULL;
  17. ////////////////////////////////////////////////////////////////////////////////////////////////////
  18. // Static Data
  19. ////////////////////////////////////////////////////////////////////////////////////////////////////
  20. /* static */ TCHAR CNmAkWiz::ms_InfFilePath[ MAX_PATH ] = TEXT("output");
  21. /* static */ TCHAR CNmAkWiz::ms_InfFileName[ MAX_PATH ] = TEXT("msnetmtg.inf");
  22. /* static */ TCHAR CNmAkWiz::ms_FileExtractPath[ MAX_PATH ] = TEXT("output");
  23. /* static */ TCHAR CNmAkWiz::ms_ToolsFolder[ MAX_PATH ] = TEXT("tools");
  24. /* static */ TCHAR CNmAkWiz::ms_NetmeetingOriginalDistributionFilePath[ MAX_PATH ] = TEXT("");
  25. /* static */ TCHAR CNmAkWiz::ms_NetmeetingSourceDirectory[ MAX_PATH ] = TEXT("source");
  26. /* static */ TCHAR CNmAkWiz::ms_NetmeetingOutputDirectory[ MAX_PATH ] = TEXT("output");
  27. /* static */ TCHAR CNmAkWiz::ms_NetmeetingOriginalDistributionFileName[ MAX_PATH ] = TEXT("nm30.exe");
  28. /* static */ TCHAR CNmAkWiz::ms_NMRK_TMP_FolderName[ MAX_PATH ] = TEXT("nmrktmp");
  29. ////////////////////////////////////////////////////////////////////////////////////////////////////
  30. // Static Fns
  31. ////////////////////////////////////////////////////////////////////////////////////////////////////
  32. //--------------------------------------------------------------------------------------------------
  33. // DoWizard is a static function of CNmAkWiz. This was done for two reasons:
  34. // 1.) There is always only a single CNmAkViz object
  35. // 2.) I wanted to make it clear that duriving something from CNmAkWiz is nonsense, so only access
  36. // to the CNmAkViz constructor and destructor is through this static helper function
  37. //
  38. // Do Wizard "blocks" while the modal NetMeeting AK Wizard does it's thing.
  39. HRESULT CNmAkWiz::DoWizard( HINSTANCE hInstance )
  40. {
  41. g_hInstance = hInstance;
  42. if( NULL == GetInstallationPath() )
  43. {
  44. // This means that NMRK is not properly installed
  45. NmrkMessageBox(MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_NMRK_MUST_BE_PROPERLY_INSTALLED),
  46. MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION), MB_OK | MB_ICONSTOP);
  47. NmrkMessageBox(MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_PLEASE_REINSTALL_NET_MEETING_RESOURCE_KIT),
  48. MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION), MB_OK | MB_ICONSTOP);
  49. return E_FAIL;
  50. }
  51. // Init common controls
  52. InitCommonControls();
  53. g_pWiz = new CNmAkWiz();
  54. if (!g_pWiz)
  55. return E_FAIL;
  56. HRESULT hr;
  57. // Initialize the Welcome property page
  58. g_pWiz->m_PropSheetHeader[ ID_WelcomeSheet ] = g_pWiz->m_WelcomeSheet.GetPropertySheet();
  59. g_pWiz->m_PropSheetHeader[ ID_IntroSheet ] = g_pWiz->m_IntroSheet.GetPropertySheet();
  60. g_pWiz->m_PropSheetHeader[ ID_SettingsSheet ] = g_pWiz->m_SettingsSheet.GetPropertySheet();
  61. g_pWiz->m_PropSheetHeader[ ID_CallModeSheet ] = g_pWiz->m_CallModeSheet.GetPropertySheet();
  62. g_pWiz->m_PropSheetHeader[ ID_ConfirmationSheet ] = g_pWiz->m_ConfirmationSheet.GetPropertySheet();
  63. g_pWiz->m_PropSheetHeader[ ID_DistributionSheet ] = g_pWiz->m_DistributionSheet.GetPropertySheet();
  64. g_pWiz->m_PropSheetHeader[ ID_FinishSheet ] = g_pWiz->m_FinishSheet.GetPropertySheet();
  65. if (-1 == PropertySheet(g_pWiz->m_PropSheetHeader))
  66. {
  67. hr = E_FAIL;
  68. }
  69. else
  70. {
  71. hr = S_OK;
  72. }
  73. delete g_pWiz;
  74. g_pWiz = NULL;
  75. return hr;
  76. }
  77. void CNmAkWiz::_CreateTextSpew( void )
  78. {
  79. CFilePanePropWnd2 * pFilePane = m_ConfirmationSheet.GetFilePane();
  80. if( pFilePane->OptionEnabled() )
  81. {
  82. HANDLE hFile = pFilePane->CreateFile(
  83. GENERIC_WRITE | GENERIC_READ,
  84. FILE_SHARE_READ,
  85. NULL,
  86. CREATE_ALWAYS,
  87. FILE_ATTRIBUTE_NORMAL );
  88. if( INVALID_HANDLE_VALUE == hFile )
  89. {
  90. return;
  91. }
  92. else
  93. {
  94. HWND hList = m_ConfirmationSheet.GetListHwnd();
  95. int iLines = ListBox_GetCount( hList );
  96. DWORD dwWritten = 0;
  97. for( int i = 0; i < iLines; i++ )
  98. {
  99. int iLen = ListBox_GetTextLen( hList, i ) + 1;
  100. LPTSTR szLine = new TCHAR[ iLen ];
  101. ListBox_GetText( hList, i, szLine );
  102. if( !WriteFile( hFile, (void *)szLine, iLen, &dwWritten, NULL ) ||
  103. !WriteFile( hFile, (void *)TEXT("\r\n"), lstrlen( TEXT("\r\n") ), &dwWritten, NULL ) )
  104. {
  105. delete [] szLine;
  106. return;
  107. }
  108. delete [] szLine;
  109. }
  110. CloseHandle( hFile );
  111. }
  112. }
  113. }
  114. void CNmAkWiz::_CreateDistro( void )
  115. {
  116. CFilePanePropWnd2 * pFilePane = m_DistributionSheet.GetDistroFilePane();
  117. if( pFilePane->OptionEnabled() )
  118. {
  119. if( ! _SetPathNames() ) { assert( 0 ); return; }
  120. // First Extract the nm21.exe file to the OUTPUT Directory
  121. if( !_ExtractOldNmCabFile() ) { assert( 0 ); return; }
  122. // Create the new MsNetMtg.inf file in the OUTPUT Directory
  123. if( !_CreateNewInfFile() ) { assert( 0 ); return; }
  124. if( !_CreateFileDistribution( pFilePane ) ) { return; }
  125. // Clean up after ourselves
  126. if( !_DeleteFiles() ) { assert( 0 ); return; }
  127. }
  128. }
  129. void CNmAkWiz::_CreateFinalAutoConf( void )
  130. {
  131. CFilePanePropWnd2 * pFilePane = m_DistributionSheet.GetAutoFilePane();
  132. // if( pFilePane->OptionEnabled() )
  133. // {
  134. //
  135. // Try to drop most of the output in a temp file...
  136. //
  137. TCHAR szBuf[ 256 ];
  138. ULONG cbWritten;
  139. HANDLE hAutoINF = pFilePane->CreateFile( GENERIC_WRITE | GENERIC_READ,
  140. FILE_SHARE_READ,
  141. NULL,
  142. CREATE_ALWAYS,
  143. FILE_ATTRIBUTE_NORMAL
  144. );
  145. if( INVALID_HANDLE_VALUE == hAutoINF )
  146. {
  147. ErrorMessage();
  148. return;
  149. }
  150. lstrcpy( szBuf, TEXT("[version]\r\nsignature=\"$CHICAGO$\"\r\n\r\n\r\nAdvancedINF=2.5\r\n") );
  151. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  152. return;
  153. }
  154. // Write string [NetMtg.Install.NMRK]\n
  155. lstrcpy( szBuf, TEXT("[NetMtg.Install.NMRK]\r\n") );
  156. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  157. return;
  158. }
  159. lstrcpy( szBuf, TEXT("AddReg=NetMtg.Install.Reg.NMRK\r\n") );
  160. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  161. return;
  162. }
  163. lstrcpy( szBuf, TEXT("DelReg=NetMtg.Install.DeleteReg.NMRK\r\n") );
  164. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  165. return;
  166. }
  167. // Write string [NetMtg.Install.Reg.NMRK]\n
  168. lstrcpy( szBuf, TEXT("\r\n\r\n[NetMtg.Install.Reg.NMRK]\r\n\r\n") );
  169. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  170. return;
  171. }
  172. lstrcpy( szBuf, TEXT("HKCU,\"SOFTWARE\\Microsoft\\Conferencing\\AutoConf\",\"Use AutoConfig\",65537,0, 0, 0, 0\r\n") );
  173. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  174. return;
  175. }
  176. // Write the REG Keys
  177. //_StoreDialogData( hAutoINF );
  178. // Write string [NetMtg.Install.DeleteReg.NMRK]\n
  179. lstrcpy( szBuf, TEXT("\r\n\r\n[NetMtg.Install.DeleteReg.NMRK]\r\n\r\n") );
  180. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  181. return;
  182. }
  183. // Write the REG Delete Keys
  184. //CPolicyData::FlushCachedInfData( hAutoINF );
  185. // this is needed...
  186. lstrcpy( szBuf, TEXT("\r\n\r\n") );
  187. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  188. return;
  189. }
  190. CloseHandle( hAutoINF );
  191. // }
  192. }
  193. void CNmAkWiz::_CreateAutoConf( void )
  194. {
  195. CFilePanePropWnd2 * pFilePane = m_DistributionSheet.GetAutoFilePane();
  196. if( pFilePane->OptionEnabled() )
  197. {
  198. //
  199. // Try to drop most of the output in a temp file...
  200. //
  201. TCHAR szBuf[ 256 ];
  202. ULONG cbWritten;
  203. HANDLE hAutoINF = pFilePane->CreateFile( GENERIC_WRITE | GENERIC_READ,
  204. FILE_SHARE_READ,
  205. NULL,
  206. CREATE_ALWAYS,
  207. FILE_ATTRIBUTE_NORMAL
  208. );
  209. if( INVALID_HANDLE_VALUE == hAutoINF )
  210. {
  211. ErrorMessage();
  212. return;
  213. }
  214. lstrcpy( szBuf, TEXT("[version]\r\nsignature=\"$CHICAGO$\"\r\n\r\n\r\nAdvancedINF=2.5\r\n") );
  215. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  216. return;
  217. }
  218. // Write string [NetMtg.Install.NMRK]\n
  219. lstrcpy( szBuf, TEXT("[NetMtg.Install.NMRK]\r\n") );
  220. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  221. return;
  222. }
  223. lstrcpy( szBuf, TEXT("AddReg=NetMtg.Install.Reg.NMRK\r\n") );
  224. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  225. return;
  226. }
  227. lstrcpy( szBuf, TEXT("DelReg=NetMtg.Install.DeleteReg.NMRK\r\n") );
  228. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  229. return;
  230. }
  231. // Write string [NetMtg.Install.Reg.NMRK]\n
  232. lstrcpy( szBuf, TEXT("\r\n\r\n[NetMtg.Install.Reg.NMRK]\r\n\r\n") );
  233. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  234. return;
  235. }
  236. // Write the REG Keys
  237. _StoreDialogData( hAutoINF );
  238. // Write string [NetMtg.Install.DeleteReg.NMRK]\n
  239. lstrcpy( szBuf, TEXT("\r\n\r\n[NetMtg.Install.DeleteReg.NMRK]\r\n\r\n") );
  240. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  241. return;
  242. }
  243. // Write the REG Delete Keys
  244. CPolicyData::FlushCachedInfData( hAutoINF );
  245. // this is needed...
  246. lstrcpy( szBuf, TEXT("\r\n\r\n") );
  247. if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  248. return;
  249. }
  250. CloseHandle( hAutoINF );
  251. }
  252. }
  253. //
  254. // CreateSettingsFile()
  255. //
  256. // This saves the options (policies, servers, auto-conf location, distro loc)
  257. // to a .INI file
  258. //
  259. void CNmAkWiz::_CreateSettingsFile(void)
  260. {
  261. CFilePanePropWnd2 * pFilePane = m_FinishSheet.GetFilePane();
  262. if (pFilePane->OptionEnabled())
  263. {
  264. HKEY hKey;
  265. m_SettingsSheet.WriteSettings();
  266. m_CallModeSheet.WriteSettings();
  267. m_ConfirmationSheet.GetFilePane()->WriteSettings();
  268. m_DistributionSheet.GetDistroFilePane()->WriteSettings();
  269. m_DistributionSheet.GetAutoFilePane()->WriteSettings();
  270. // Save last config path in registry.
  271. if (RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_NMRK, &hKey) == ERROR_SUCCESS)
  272. {
  273. TCHAR szFile[MAX_PATH];
  274. pFilePane->GetPathAndFile(szFile);
  275. RegSetValueEx(hKey, REGVAL_LASTCONFIG, 0, REG_SZ, (LPBYTE)szFile,
  276. lstrlen(szFile)+1);
  277. RegCloseKey(hKey);
  278. }
  279. }
  280. }
  281. //-------------------------------------------------------------------------------------------------
  282. // This is called when the user hits the the FINISH button after entering data with the wizard...
  283. // We simply get the information from the various dialogs ( property sheets as they are ), and
  284. // set the appropriate data in the .INF file
  285. void CNmAkWiz::CallbackForWhenUserHitsFinishButton( void )
  286. {
  287. if (m_DistributionSheet.TurnedOffAutoConf() )
  288. {
  289. _CreateFinalAutoConf();
  290. }
  291. else
  292. {
  293. _CreateAutoConf();
  294. }
  295. _CreateTextSpew();
  296. _CreateSettingsFile();
  297. _CreateDistro();
  298. }
  299. ////////////////////////////////////////////////////////////////////////////////////////////////////
  300. // Constructors, Destructors, and Initialization Fns
  301. ////////////////////////////////////////////////////////////////////////////////////////////////////
  302. //--------------------------------------------------------------------------------------------------
  303. // CNmAkWiz::CNmAkWiz
  304. CNmAkWiz::CNmAkWiz(void)
  305. : m_WelcomeSheet(),
  306. m_IntroSheet(),
  307. m_SettingsSheet(),
  308. m_CallModeSheet(),
  309. m_ConfirmationSheet(),
  310. m_DistributionSheet(),
  311. m_FinishSheet(),
  312. m_PropSheetHeader( ID_NumSheets,
  313. PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_NOAPPLYNOW /* | PSH_HASHELP */
  314. )
  315. {
  316. }
  317. //--------------------------------------------------------------------------------------------------
  318. // CNmAkWiz::~CNmAkWiz
  319. CNmAkWiz::~CNmAkWiz( void )
  320. {
  321. }
  322. //--------------------------------------------------------------------------------------------------
  323. // CNmAkWiz::_InitInfFile opens the reg file specified by ms_InfFilePath\ms_InfFileName.
  324. // If the file cannot be created there, the user is prompted for a good location for the file.
  325. BOOL CNmAkWiz::_InitInfFile( void ) {
  326. // First we have to open the .INF file
  327. TCHAR szFileName[ MAX_PATH ];
  328. int Err;
  329. const TCHAR* szInstallationPath = GetInstallationPath();
  330. if( NULL != szInstallationPath ) {
  331. lstrcpy( szFileName, szInstallationPath );
  332. lstrcat( szFileName, TEXT("\\") );
  333. lstrcat( szFileName, ms_InfFilePath );
  334. lstrcat( szFileName, TEXT("\\") );
  335. lstrcat( szFileName, ms_InfFileName );
  336. }
  337. else {
  338. assert( 0 );
  339. lstrcat( szFileName, ms_InfFileName );
  340. }
  341. /**/m_hInfFile = CreateFile( szFileName,
  342. GENERIC_WRITE,
  343. 0,
  344. NULL,
  345. CREATE_ALWAYS, // This is going to overwrite existing files
  346. FILE_ATTRIBUTE_NORMAL,
  347. NULL
  348. );
  349. if( INVALID_HANDLE_VALUE == m_hInfFile ) {
  350. switch( Err = GetLastError() ) {
  351. case ERROR_ACCESS_DENIED:
  352. assert( 0 ); return FALSE;
  353. case ERROR_PATH_NOT_FOUND:
  354. assert( 0 ); return FALSE;
  355. case ERROR_WRITE_PROTECT:
  356. assert( 0 ); return FALSE;
  357. default:
  358. ErrorMessage( "", Err );
  359. assert( 0 );
  360. return FALSE;
  361. }
  362. }
  363. DWORD cbWritten;
  364. TCHAR szPreamble [] = TEXT("[version]\nsignature=\"$CHICAGO$\"\nAdvancedINF=2.5\n\n[DefaultInstall]\nAddReg\t= AddRegSection\nDelReg\t= DelRegSection\n\n\n[AddRegSection]\n");
  365. RETFAIL( WriteFile( m_hInfFile, szPreamble, lstrlen( szPreamble ), &cbWritten, NULL ) );
  366. return TRUE;
  367. }
  368. //--------------------------------------------------------------------------------------------------
  369. // CNmAkWiz::_StoreDialogData
  370. // The user specifies a bunch of data in the g_pWiz-> NetMeeting ( conf.exe ) reads customization
  371. // data stored from the registry. We have to store this customization data in a .INF file for
  372. // the setup program to use. This function will get the data from the wizard and save it to
  373. // a .INF file according to the key maps which map a Wizard property to a Infistry entry...
  374. BOOL CNmAkWiz::_StoreDialogData( HANDLE hFile ) {
  375. m_SettingsSheet.WriteToINF( hFile );
  376. m_CallModeSheet.WriteToINF( hFile );
  377. m_DistributionSheet.GetAutoFilePane()->WriteToINF( hFile, TRUE );
  378. return TRUE;
  379. }
  380. //--------------------------------------------------------------------------------------------------
  381. // CNmAkWiz::_CloseInfFile closes the registry file that we are using to store the data entered
  382. // by the user in the Wizard.
  383. BOOL CNmAkWiz::_CloseInfFile( void ) {
  384. TCHAR szDelRegSectionPrefix[] = "\n\n[DelRegSection]\n";
  385. DWORD cbWritten;
  386. RETFAIL( WriteFile( m_hInfFile, szDelRegSectionPrefix, lstrlen( szDelRegSectionPrefix ), &cbWritten, NULL ) );
  387. CPolicyData::FlushCachedInfData( m_hInfFile );
  388. CloseHandle( m_hInfFile );
  389. return TRUE;
  390. }
  391. //--------------------------------------------------------------------------------------------------
  392. // CNmAkWiz::_CreateDistributableFile creates a custom NetMeeting distributable incorporating
  393. // the registry changes that are stored in ms_InfFilePath\ms_InfFileName
  394. // The szPathName is a path where we are going to create a file called:
  395. // CNmAkWiz::ms_NetmeetingCustomDistributionFileName;
  396. BOOL CNmAkWiz::_CreateDistributableFile( CFilePanePropWnd2 *pFilePane ) {
  397. // Get the location of the original distribution
  398. if( !_GetNetMeetingOriginalDistributionData() ) { return FALSE; }
  399. TCHAR szNMOriginalDistributableFile[ MAX_PATH ];
  400. TCHAR szNMCustomDistributableFile[ MAX_PATH ];
  401. TCHAR szUpdateCommandLine[ MAX_PATH ];
  402. pFilePane->CreateOutputDir();
  403. pFilePane->GetPathAndFile( szNMCustomDistributableFile );
  404. const TCHAR* sz = GetInstallationPath();
  405. if( NULL != sz ) {
  406. lstrcpy( szNMOriginalDistributableFile, sz );
  407. lstrcat( szNMOriginalDistributableFile, TEXT("\\" ) );
  408. lstrcat( szNMOriginalDistributableFile, ms_NetmeetingSourceDirectory );
  409. lstrcat( szNMOriginalDistributableFile, TEXT("\\" ) );
  410. lstrcat( szNMOriginalDistributableFile, ms_NetmeetingOriginalDistributionFileName );
  411. }
  412. // Copy source distribution to custom exe
  413. SHFILEOPSTRUCT FileOp;
  414. ZeroMemory( &FileOp, sizeof( FileOp ) );
  415. FileOp.hwnd = g_hwndActive;
  416. FileOp.wFunc = FO_COPY;
  417. FileOp.fFlags = FOF_SIMPLEPROGRESS | FOF_NOCONFIRMATION;
  418. // Must double-null terminate file names for the struct...
  419. szNMOriginalDistributableFile[ lstrlen( szNMOriginalDistributableFile ) + 1 ] = '\0';
  420. szNMCustomDistributableFile[ lstrlen( szNMCustomDistributableFile ) + 1 ] = '\0';
  421. FileOp.pFrom = szNMOriginalDistributableFile;
  422. FileOp.pTo = szNMCustomDistributableFile;
  423. TCHAR szProgressTitle[ 256 ];
  424. LoadString( g_hInstance,
  425. IDS_CREATING_CUSTOM_DISTRIBUTION,
  426. szProgressTitle,
  427. CCHMAX( szProgressTitle )
  428. );
  429. FileOp.lpszProgressTitle = szProgressTitle;
  430. int iRet = SHFileOperation( &FileOp );
  431. if( 0 != iRet ) { return FALSE; }
  432. // CreateProcess: updfile nm30.exe MsNetMtg.inf
  433. const TCHAR* szInstallationPath = GetInstallationPath();
  434. wsprintf(szUpdateCommandLine, "\"%s\\%s\\updfile.exe\" \"%s\" \"%s\\%s\"",
  435. szInstallationPath, ms_ToolsFolder, szNMCustomDistributableFile,
  436. ms_FileExtractPath, ms_InfFileName);
  437. OutputDebugString(szUpdateCommandLine);
  438. OutputDebugString("\n\r");
  439. PROCESS_INFORMATION ProcInfo;
  440. STARTUPINFO StartupInfo;
  441. ZeroMemory( &StartupInfo, sizeof( StartupInfo ) );
  442. StartupInfo.cb = sizeof( StartupInfo );
  443. BOOL bRet = CreateProcess( NULL,
  444. szUpdateCommandLine,
  445. NULL,
  446. NULL,
  447. TRUE,
  448. DETACHED_PROCESS,
  449. NULL,
  450. NULL,
  451. &StartupInfo,
  452. &ProcInfo
  453. );
  454. if( 0 == bRet ) {
  455. DWORD dwErr;
  456. if( ERROR_FILE_NOT_FOUND == ( dwErr = GetLastError() ) ) {
  457. TCHAR szMsg[ 256 ];
  458. LoadString( g_hInstance,
  459. IDS_COULD_NOT_FIND_THE_TOOL,
  460. szMsg,
  461. CCHMAX( szMsg )
  462. );
  463. lstrcat( szMsg, TEXT(" \"") );
  464. lstrcat( szMsg, szInstallationPath );
  465. lstrcat( szMsg, TEXT("\\") );
  466. lstrcat( szMsg, ms_ToolsFolder );
  467. lstrcat( szMsg, TEXT("\\") );
  468. lstrcat( szMsg, TEXT("updfile.exe\"") );
  469. NmrkMessageBox(
  470. szMsg,
  471. MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION),
  472. MB_OK | MB_ICONSTOP
  473. );
  474. NmrkMessageBox(MAKEINTRESOURCE(IDS_REINSTALL_THE_NETMEETING_RESOURCE_KIT_AND_TRY_AGAIN),
  475. MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION),
  476. MB_OK | MB_ICONSTOP);
  477. }
  478. return FALSE;
  479. }
  480. SetLastError( 0 );
  481. DWORD dwRet;
  482. MSG msg;
  483. while (TRUE)
  484. {
  485. dwRet = MsgWaitForMultipleObjects(1, &ProcInfo.hThread, FALSE, INFINITE, QS_ALLINPUT);
  486. // Process is done
  487. if (dwRet == WAIT_OBJECT_0)
  488. break;
  489. // Something went wrong
  490. if (dwRet != WAIT_OBJECT_0 + 1)
  491. {
  492. ErrorMessage();
  493. assert(0);
  494. return FALSE;
  495. }
  496. // GUI stuff
  497. while (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
  498. {
  499. TranslateMessage(&msg);
  500. DispatchMessage(&msg);
  501. if (WaitForSingleObject(ProcInfo.hThread, 0) == WAIT_OBJECT_0)
  502. {
  503. // Process is done
  504. break;
  505. }
  506. }
  507. }
  508. DWORD dwExitCode;
  509. bRet = GetExitCodeProcess( ProcInfo.hProcess, &dwExitCode );
  510. if (dwExitCode != 0)
  511. {
  512. NmrkMessageBox(MAKEINTRESOURCE(IDS_NOT_ENOUGH_SPACE_IN_FINAL),
  513. MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION),
  514. MB_OK | MB_ICONEXCLAMATION
  515. );
  516. return FALSE;
  517. }
  518. TCHAR szMsg[ 256 ];
  519. lstrcpy( szMsg, szNMCustomDistributableFile );
  520. int len = lstrlen( szMsg );
  521. LoadString( g_hInstance,
  522. IDS_SUCCESSFULLY_CREATED,
  523. szMsg + len,
  524. CCHMAX(szMsg) - len
  525. );
  526. NmrkMessageBox(szMsg, NULL, MB_OK);
  527. return TRUE;
  528. }
  529. //--------------------------------------------------------------------------------------------------
  530. // CNmAkWiz::_CreateFileDistribution
  531. // We are going to create a file called CNmAkWiz::ms_NetmeetingCustomDistributionFileName in the
  532. // location specified by the user in the m_DistributionSheet dialog
  533. BOOL CNmAkWiz::_CreateFileDistribution( CFilePanePropWnd2 *pFilePane ) {
  534. if ( !_CreateDistributableFile( pFilePane ))
  535. {
  536. NmrkMessageBox(MAKEINTRESOURCE(IDS_THERE_WAS_AN_UNEXPECTED_ERROR),
  537. MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION),
  538. MB_OK | MB_ICONSTOP);
  539. return FALSE;
  540. }
  541. return TRUE;
  542. }
  543. //--------------------------------------------------------------------------------------------------
  544. // CNmAkWiz::_NetMeetingOriginalDistributionIsAtSpecifiedLocationsearches
  545. //
  546. BOOL CNmAkWiz::_NetMeetingOriginalDistributionIsAtSpecifiedLocation( void ) {
  547. TCHAR szFileName[ MAX_PATH ];
  548. const TCHAR* sz = GetInstallationPath();
  549. if( NULL != sz ) {
  550. lstrcpy( ms_NetmeetingOriginalDistributionFilePath, sz );
  551. lstrcat( ms_NetmeetingOriginalDistributionFilePath, TEXT("\\") );
  552. lstrcat( ms_NetmeetingOriginalDistributionFilePath, ms_NetmeetingSourceDirectory );
  553. lstrcat( ms_NetmeetingOriginalDistributionFilePath, TEXT("\\") );
  554. }
  555. if( MAX_PATH < ( lstrlen( ms_NetmeetingOriginalDistributionFilePath ) +
  556. lstrlen( ms_NetmeetingOriginalDistributionFileName ) + 1 )
  557. ) {
  558. assert( 0 );
  559. return FALSE; // This should not happen becaues the file should have been
  560. // Created in this same program
  561. }
  562. lstrcpy( szFileName, ms_NetmeetingOriginalDistributionFilePath );
  563. lstrcat( szFileName, ms_NetmeetingOriginalDistributionFileName );
  564. HANDLE hFile = CreateFile( szFileName,
  565. GENERIC_READ,
  566. FILE_SHARE_READ,
  567. NULL,
  568. OPEN_EXISTING,
  569. FILE_ATTRIBUTE_NORMAL,
  570. NULL
  571. );
  572. if( INVALID_HANDLE_VALUE != hFile ) {
  573. // The NetMeeting Distribution file was at the specified location...
  574. CloseHandle( hFile );
  575. return TRUE;
  576. }
  577. return FALSE;
  578. }
  579. //--------------------------------------------------------------------------------------------------
  580. // CNmAkWiz::_GetNetMeetingOriginalDistributionData searches for the NetMeeting original
  581. // distribution and if it can't find it, it will ask the user to help
  582. // return TRUE if the user selected one, and FALSE if the user wants to quit
  583. BOOL CNmAkWiz::_GetNetMeetingOriginalDistributionData( void )
  584. {
  585. // We have to get the file path from the user
  586. OPENFILENAME OpenFileName;
  587. while( !_NetMeetingOriginalDistributionIsAtSpecifiedLocation() )
  588. {
  589. NmrkMessageBox(MAKEINTRESOURCE(IDS_CANT_FIND_NETMEETING_ORIGINAL_DISTRIBUTION),
  590. MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION),
  591. MB_OK | MB_ICONEXCLAMATION);
  592. ZeroMemory( &OpenFileName, sizeof( OpenFileName ) );
  593. OpenFileName.lStructSize = sizeof( OpenFileName );
  594. OpenFileName.hwndOwner = g_hwndActive;
  595. OpenFileName.lpstrFile = ms_NetmeetingOriginalDistributionFileName;
  596. OpenFileName.nMaxFile = MAX_PATH;
  597. OpenFileName.Flags = OFN_PATHMUSTEXIST;
  598. if( GetOpenFileName( &OpenFileName ) ) {
  599. lstrcpy( ms_NetmeetingOriginalDistributionFilePath, "" );
  600. }
  601. else {
  602. // This means that the user wants to cancel
  603. if( IDCANCEL == NmrkMessageBox(
  604. MAKEINTRESOURCE(IDS_CANT_FIND_NETMEETING_ORIGINAL_DISTRIBUTION_QUERY_ABORT),
  605. MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION),
  606. MB_OKCANCEL | MB_ICONEXCLAMATION
  607. ) ) {
  608. exit( 0 );
  609. }
  610. }
  611. }
  612. return TRUE;
  613. }
  614. //--------------------------------------------------------------------------------------------------
  615. // CNmAkWiz::_DeleteFiles deletes the Temp files that we have been using...
  616. BOOL CNmAkWiz::_DeleteFiles( void ) {
  617. TCHAR szProgressTitle[ 256 ];
  618. LoadString( g_hInstance,
  619. IDS_DELETING_TEMPORARY_FILES_PROGRESS_TITLE,
  620. szProgressTitle,
  621. CCHMAX( szProgressTitle )
  622. );
  623. TCHAR szOutputDirectoryPath[ MAX_PATH ];
  624. lstrcpy( szOutputDirectoryPath, ms_FileExtractPath );
  625. lstrcat( szOutputDirectoryPath, TEXT("\\*.*") );
  626. // Must double NULL terminate this!
  627. szOutputDirectoryPath[ lstrlen( szOutputDirectoryPath ) + 1 ] = '\0';
  628. int iRet = rmdir( ms_FileExtractPath );
  629. if( ( -1 == iRet ) && ( ENOENT != errno ) ) {
  630. SHFILEOPSTRUCT FileOp;
  631. ZeroMemory( &FileOp, sizeof( FileOp ) );
  632. FileOp.hwnd = g_hwndActive;
  633. FileOp.wFunc = FO_DELETE;
  634. FileOp.fFlags = FOF_SIMPLEPROGRESS | FOF_NOCONFIRMATION;
  635. FileOp.pFrom = szOutputDirectoryPath;
  636. FileOp.lpszProgressTitle = szProgressTitle;
  637. iRet = SHFileOperation( &FileOp );
  638. iRet = rmdir( ms_FileExtractPath );
  639. }
  640. return TRUE;
  641. }
  642. BOOL CNmAkWiz::_SetPathNames( void ) {
  643. GetTempPath( MAX_PATH, ms_FileExtractPath );
  644. lstrcat( ms_FileExtractPath, ms_NMRK_TMP_FolderName );
  645. OutputDebugString( "ms_FileExtractPath = " );
  646. OutputDebugString( ms_FileExtractPath );
  647. OutputDebugString( "\r\n" );
  648. return TRUE;
  649. }
  650. const TCHAR* GetInstallationPath( void ) {
  651. static TCHAR szPath[ MAX_PATH ];
  652. HKEY hKey;
  653. long lRet = RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_NMRK, &hKey );
  654. if( ERROR_SUCCESS != lRet ) { return NULL; }
  655. DWORD cb = MAX_PATH;
  656. DWORD dwType = REG_SZ;
  657. if( ERROR_SUCCESS != RegQueryValueEx( hKey,
  658. REGVAL_INSTALLATIONDIRECTORY,
  659. NULL,
  660. &dwType,
  661. reinterpret_cast< LPBYTE >( szPath ),
  662. &cb ) ) {
  663. ErrorMessage();
  664. if( ERROR_SUCCESS != RegCloseKey( hKey ) ) {
  665. ErrorMessage();
  666. }
  667. return NULL;
  668. }
  669. if( ERROR_SUCCESS != RegCloseKey( hKey ) ) {
  670. ErrorMessage();
  671. }
  672. return szPath;
  673. }
  674. BOOL CNmAkWiz::_CreateNewInfFile( void ) {
  675. // Load MsNetMtg.inf into memory
  676. TCHAR szInfFilePath[ MAX_PATH ];
  677. TCHAR szBuf[ MAX_PATH ];
  678. TCHAR* pOriginalInfFileData;
  679. TCHAR* pOriginalInfFileDataCursor;
  680. TCHAR* pCursor;
  681. DWORD dwSize;
  682. DWORD cbWritten;
  683. lstrcpy( szInfFilePath, ms_FileExtractPath );
  684. lstrcat( szInfFilePath, TEXT("\\") );
  685. lstrcat( szInfFilePath, ms_InfFileName );
  686. m_hInfFile = CreateFile( szInfFilePath,
  687. GENERIC_READ,
  688. FILE_SHARE_READ,
  689. NULL,
  690. OPEN_EXISTING,
  691. FILE_ATTRIBUTE_NORMAL,
  692. NULL
  693. );
  694. if( INVALID_HANDLE_VALUE == m_hInfFile ) { goto ExitError; }
  695. DWORD dwFileSizeHigh;
  696. dwSize = GetFileSize( m_hInfFile, &dwFileSizeHigh );
  697. pOriginalInfFileData = new TCHAR[ dwSize ];
  698. pOriginalInfFileDataCursor = pOriginalInfFileData;
  699. DWORD cbRead;
  700. if( 0 == ReadFile( m_hInfFile, pOriginalInfFileData, dwSize, &cbRead, NULL ) ) {
  701. goto ExitError;
  702. }
  703. if( cbRead != dwSize ) { goto ExitError; }
  704. // Close MsNetMtg.inf file
  705. CloseHandle( m_hInfFile );
  706. // Open MsNetMtg.inf for writing ( overwrite existing )
  707. m_hInfFile = CreateFile( szInfFilePath,
  708. GENERIC_WRITE,
  709. 0,
  710. NULL,
  711. CREATE_ALWAYS,
  712. FILE_ATTRIBUTE_NORMAL,
  713. NULL
  714. );
  715. if( INVALID_HANDLE_VALUE == m_hInfFile ) { goto ExitError; }
  716. // Set cursor to [DefaultInstall] string
  717. pCursor = strstr( pOriginalInfFileDataCursor, TEXT("[DefaultInstall]") );
  718. if( NULL == pCursor ) { goto ExitError; }
  719. // Set cursor to next "AddReg"
  720. pCursor = strstr( pCursor, TEXT("AddReg") );
  721. if( NULL == pCursor ) { goto ExitError; }
  722. // Set cursor to the end of the line
  723. pCursor = strstr( pCursor, TEXT("\r") );
  724. if( NULL == pCursor ) { goto ExitError; }
  725. // Write Original Data up to the cursor to INF
  726. if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) {
  727. goto ExitError;
  728. }
  729. pOriginalInfFileDataCursor = pCursor;
  730. if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) {
  731. goto ExitError;
  732. }
  733. // Write ",NetMtg.Install.Reg.NMRK" to INF
  734. lstrcpy( szBuf, ",NetMtg.Install.Reg.NMRK" );
  735. if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  736. goto ExitError;
  737. }
  738. // Set cursor to next "DelReg"
  739. pCursor = strstr( pCursor, "DelReg" );
  740. if( NULL == pCursor ) { goto ExitError; }
  741. // Set cursor to the end of the line
  742. pCursor = strstr( pCursor, "\r" );
  743. if( NULL == pCursor ) { goto ExitError; }
  744. // Write Original Data up to the cursor to INF
  745. if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) {
  746. goto ExitError;
  747. }
  748. pOriginalInfFileDataCursor = pCursor;
  749. // Write ",NetMtg.Install.DeleteReg.NMRK" to INF
  750. lstrcpy( szBuf, ",NetMtg.Install.DeleteReg.NMRK" );
  751. if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  752. goto ExitError;
  753. }
  754. // Set cursor to [DefaultInstall.NT] string
  755. pCursor = strstr( pOriginalInfFileDataCursor, "[DefaultInstall.NT]" );
  756. if( NULL == pCursor ) { goto ExitError; }
  757. // Set cursor to next "AddReg"
  758. pCursor = strstr( pCursor, "AddReg" );
  759. if( NULL == pCursor ) { goto ExitError; }
  760. // Set cursor to the end of the line
  761. pCursor = strstr( pCursor, "\r" );
  762. if( NULL == pCursor ) { goto ExitError; }
  763. // Write Original Data up to the cursor to INF
  764. if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) {
  765. goto ExitError;
  766. }
  767. pOriginalInfFileDataCursor = pCursor;
  768. if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) {
  769. goto ExitError;
  770. }
  771. // Write ",NetMtg.Install.Reg.NMRK" to INF
  772. lstrcpy( szBuf, ",NetMtg.Install.Reg.NMRK" );
  773. if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  774. goto ExitError;
  775. }
  776. // Set cursor to next "DelReg"
  777. pCursor = strstr( pCursor, "DelReg" );
  778. if( NULL == pCursor ) { goto ExitError; }
  779. // Set cursor to the end of the line
  780. pCursor = strstr( pCursor, "\r" );
  781. if( NULL == pCursor ) { goto ExitError; }
  782. // Write Original Data up to the cursor to INF
  783. if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) {
  784. goto ExitError;
  785. }
  786. pOriginalInfFileDataCursor = pCursor;
  787. // Write ",NetMtg.Install.DeleteReg.NMRK" to INF
  788. lstrcpy( szBuf, ",NetMtg.Install.DeleteReg.NMRK" );
  789. if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  790. goto ExitError;
  791. }
  792. //
  793. // Now we have to yank the old Ils stuff...
  794. //
  795. // Set cursor to [NetMtg.Install.Reg.PerUser] string
  796. pCursor = strstr( pCursor, "[NetMtg.Install.Reg.PerUser]" );
  797. if( NULL == pCursor ) { goto ExitError; }
  798. // Skip to the start of the next line
  799. pCursor = strstr( pCursor, "\n" ); // This is the last TCHARacter on the line
  800. pCursor++; // This will be the first TCHARacter on the line
  801. // Write Original Data up to the cursor to INF
  802. if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) {
  803. goto ExitError;
  804. }
  805. pOriginalInfFileDataCursor = pCursor;
  806. // skip white space
  807. while( isspace( *pCursor ) ) { pCursor++; }
  808. // While the cursor is not '['
  809. while( *pCursor != '[' ) {
  810. // if current line starts with
  811. if( ( pCursor == strstr( pCursor, "HKCU,\"%KEY_CONFERENCING%\\UI\\Directory\",\"Name" ) ) ||
  812. ( pCursor == strstr( pCursor, "HKCU,\"%KEY_CONFERENCING%\\UI\\Directory\",\"Count" ) ) ) {
  813. // Delete the line by incrementing the base cursor to the beginning of the next line
  814. pCursor = strstr( pCursor, "\n" );
  815. pCursor++;
  816. }
  817. else {
  818. break;
  819. }
  820. }
  821. // Set pOriginalInfFileDataCursor to cursor ( thus skipping the old Ils stuff )
  822. pOriginalInfFileDataCursor = pCursor;
  823. // Set Cursor to [Strings] string
  824. pCursor = strstr( pCursor, "[Strings]" );
  825. if( NULL == pCursor ) { goto ExitError; }
  826. // Write original data to the cursor
  827. if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) {
  828. goto ExitError;
  829. }
  830. pOriginalInfFileDataCursor = pCursor;
  831. // Write string [NetMtg.Install.Reg.NMRK]\n
  832. lstrcpy( szBuf, "\r\n\r\n[NetMtg.Install.Reg.NMRK]\r\n\r\n" );
  833. if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  834. goto ExitError;
  835. }
  836. // Write the REG Keys
  837. _StoreDialogData( m_hInfFile );
  838. // Write string [NetMtg.Install.DeleteReg.NMRK]\n
  839. lstrcpy( szBuf, "\r\n\r\n[NetMtg.Install.DeleteReg.NMRK]\r\n\r\n" );
  840. if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  841. goto ExitError;
  842. }
  843. // Write the REG Delete Keys
  844. CPolicyData::FlushCachedInfData( m_hInfFile );
  845. // this is needed...
  846. lstrcpy( szBuf, "\r\n\r\n" );
  847. if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) {
  848. goto ExitError;
  849. }
  850. // Write the rest of the Original File to the INF
  851. pCursor = pOriginalInfFileData + dwSize;
  852. if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) {
  853. goto ExitError;
  854. }
  855. CloseHandle( m_hInfFile );
  856. m_hInfFile = INVALID_HANDLE_VALUE;
  857. delete [] pOriginalInfFileData;
  858. return TRUE;
  859. ExitError:
  860. assert( 0 );
  861. if( INVALID_HANDLE_VALUE != INVALID_HANDLE_VALUE ) {
  862. CloseHandle( m_hInfFile );
  863. }
  864. delete [] pOriginalInfFileData;
  865. return FALSE;
  866. }
  867. BOOL CNmAkWiz::_ExtractOldNmCabFile( void ) {
  868. TCHAR szCabPath[ MAX_PATH ];
  869. TCHAR szOutputDirectoryPath[ MAX_PATH ];
  870. TCHAR szCommandLine[ MAX_PATH ];
  871. // Clean up in case we abnormally terminated before...
  872. _DeleteFiles();
  873. // Create the temp folder
  874. mkdir( ms_FileExtractPath );
  875. const TCHAR* szInstallationPath = GetInstallationPath();
  876. if( NULL != szInstallationPath ) {
  877. lstrcpy( szCabPath, "\"" );
  878. lstrcat( szCabPath, szInstallationPath );
  879. lstrcat( szCabPath, "\\" );
  880. lstrcat( szCabPath, ms_NetmeetingSourceDirectory );
  881. lstrcat( szCabPath, "\\" );
  882. lstrcat( szCabPath, ms_NetmeetingOriginalDistributionFileName );
  883. lstrcat( szCabPath, "\" " );
  884. }
  885. else {
  886. assert( 0 );
  887. lstrcat( szCabPath, ms_InfFileName );
  888. }
  889. lstrcpy( szOutputDirectoryPath, ms_FileExtractPath );
  890. lstrcpy( szCommandLine, "/C /T:\"" );
  891. lstrcat( szCommandLine, szOutputDirectoryPath );
  892. lstrcat( szCommandLine, "\" /Q" );
  893. PROCESS_INFORMATION ProcInfo;
  894. STARTUPINFO StartupInfo;
  895. ZeroMemory( &StartupInfo, sizeof( StartupInfo ) );
  896. StartupInfo.cb = sizeof( StartupInfo );
  897. lstrcat( szCabPath, szCommandLine );
  898. OutputDebugString( szCabPath );
  899. OutputDebugString( "\n" );
  900. BOOL iRet = CreateProcess( NULL,
  901. szCabPath,
  902. NULL,
  903. NULL,
  904. FALSE,
  905. 0,
  906. NULL,
  907. NULL,
  908. &StartupInfo,
  909. &ProcInfo
  910. );
  911. if( FALSE == iRet ) {
  912. ErrorMessage();
  913. assert( 0 );
  914. return FALSE;
  915. }
  916. SetLastError( 0 );
  917. DWORD dwRet;
  918. MSG msg;
  919. while (TRUE)
  920. {
  921. dwRet = MsgWaitForMultipleObjects(1, &ProcInfo.hThread, FALSE, INFINITE, QS_ALLINPUT);
  922. // Process is done
  923. if (dwRet == WAIT_OBJECT_0)
  924. break;
  925. // Something went wrong
  926. if (dwRet != WAIT_OBJECT_0 + 1)
  927. {
  928. ErrorMessage();
  929. assert(0);
  930. return FALSE;
  931. }
  932. // GUI stuff
  933. while (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
  934. {
  935. TranslateMessage(&msg);
  936. DispatchMessage(&msg);
  937. if (WaitForSingleObject(ProcInfo.hThread, 0) == WAIT_OBJECT_0)
  938. {
  939. // Process is done
  940. break;
  941. }
  942. }
  943. }
  944. DWORD dwExitCode;
  945. BOOL bRet = GetExitCodeProcess( ProcInfo.hProcess, &dwExitCode );
  946. // dwExitCode 0 is success
  947. if (dwExitCode != 0)
  948. {
  949. NmrkMessageBox(MAKEINTRESOURCE(IDS_NOT_ENOUGH_SPACE_IN_TEMP_DIR),
  950. MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION),
  951. MB_OK | MB_ICONEXCLAMATION
  952. );
  953. return FALSE;
  954. }
  955. return TRUE;
  956. }
  957. //
  958. // NmrkMessageBox()
  959. //
  960. // Puts up a message box owned by the wizard
  961. //
  962. int NmrkMessageBox
  963. (
  964. LPCSTR lpszText,
  965. LPCSTR lpszCaption,
  966. UINT uType,
  967. HWND hwndParent
  968. )
  969. {
  970. MSGBOXPARAMS mbp;
  971. ZeroMemory(&mbp, sizeof(mbp));
  972. mbp.cbSize = sizeof(mbp);
  973. mbp.hwndOwner = NULL == hwndParent ? g_hwndActive : hwndParent;
  974. mbp.hInstance = g_hInstance;
  975. mbp.lpszText = lpszText;
  976. if (!lpszCaption)
  977. mbp.lpszCaption = MAKEINTRESOURCE(IDS_MSG_CAPTION);
  978. else
  979. mbp.lpszCaption = lpszCaption;
  980. mbp.dwStyle = uType | MB_SETFOREGROUND;
  981. return(MessageBoxIndirect(&mbp));
  982. }