//////////////////////////////////////////////////////////////////////////////////////////////////// // Look at the header file for usage information... #include "precomp.h" #include "resource.h" #include #include "PropPg.h" #include "PShtHdr.h" #include "NmAkWiz.h" #include "PolData.h" #include "NMAKReg.h" ///////////////// // Global ///////////////// CNmAkWiz * g_pWiz = NULL; HWND g_hwndActive = NULL; HINSTANCE g_hInstance = NULL; //////////////////////////////////////////////////////////////////////////////////////////////////// // Static Data //////////////////////////////////////////////////////////////////////////////////////////////////// /* static */ TCHAR CNmAkWiz::ms_InfFilePath[ MAX_PATH ] = TEXT("output"); /* static */ TCHAR CNmAkWiz::ms_InfFileName[ MAX_PATH ] = TEXT("msnetmtg.inf"); /* static */ TCHAR CNmAkWiz::ms_FileExtractPath[ MAX_PATH ] = TEXT("output"); /* static */ TCHAR CNmAkWiz::ms_ToolsFolder[ MAX_PATH ] = TEXT("tools"); /* static */ TCHAR CNmAkWiz::ms_NetmeetingOriginalDistributionFilePath[ MAX_PATH ] = TEXT(""); /* static */ TCHAR CNmAkWiz::ms_NetmeetingSourceDirectory[ MAX_PATH ] = TEXT("source"); /* static */ TCHAR CNmAkWiz::ms_NetmeetingOutputDirectory[ MAX_PATH ] = TEXT("output"); /* static */ TCHAR CNmAkWiz::ms_NetmeetingOriginalDistributionFileName[ MAX_PATH ] = TEXT("nm30.exe"); /* static */ TCHAR CNmAkWiz::ms_NMRK_TMP_FolderName[ MAX_PATH ] = TEXT("nmrktmp"); //////////////////////////////////////////////////////////////////////////////////////////////////// // Static Fns //////////////////////////////////////////////////////////////////////////////////////////////////// //-------------------------------------------------------------------------------------------------- // DoWizard is a static function of CNmAkWiz. This was done for two reasons: // 1.) There is always only a single CNmAkViz object // 2.) I wanted to make it clear that duriving something from CNmAkWiz is nonsense, so only access // to the CNmAkViz constructor and destructor is through this static helper function // // Do Wizard "blocks" while the modal NetMeeting AK Wizard does it's thing. HRESULT CNmAkWiz::DoWizard( HINSTANCE hInstance ) { g_hInstance = hInstance; if( NULL == GetInstallationPath() ) { // This means that NMRK is not properly installed NmrkMessageBox(MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_NMRK_MUST_BE_PROPERLY_INSTALLED), MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION), MB_OK | MB_ICONSTOP); NmrkMessageBox(MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_PLEASE_REINSTALL_NET_MEETING_RESOURCE_KIT), MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION), MB_OK | MB_ICONSTOP); return E_FAIL; } // Init common controls InitCommonControls(); g_pWiz = new CNmAkWiz(); if (!g_pWiz) return E_FAIL; HRESULT hr; // Initialize the Welcome property page g_pWiz->m_PropSheetHeader[ ID_WelcomeSheet ] = g_pWiz->m_WelcomeSheet.GetPropertySheet(); g_pWiz->m_PropSheetHeader[ ID_IntroSheet ] = g_pWiz->m_IntroSheet.GetPropertySheet(); g_pWiz->m_PropSheetHeader[ ID_SettingsSheet ] = g_pWiz->m_SettingsSheet.GetPropertySheet(); g_pWiz->m_PropSheetHeader[ ID_CallModeSheet ] = g_pWiz->m_CallModeSheet.GetPropertySheet(); g_pWiz->m_PropSheetHeader[ ID_ConfirmationSheet ] = g_pWiz->m_ConfirmationSheet.GetPropertySheet(); g_pWiz->m_PropSheetHeader[ ID_DistributionSheet ] = g_pWiz->m_DistributionSheet.GetPropertySheet(); g_pWiz->m_PropSheetHeader[ ID_FinishSheet ] = g_pWiz->m_FinishSheet.GetPropertySheet(); if (-1 == PropertySheet(g_pWiz->m_PropSheetHeader)) { hr = E_FAIL; } else { hr = S_OK; } delete g_pWiz; g_pWiz = NULL; return hr; } void CNmAkWiz::_CreateTextSpew( void ) { CFilePanePropWnd2 * pFilePane = m_ConfirmationSheet.GetFilePane(); if( pFilePane->OptionEnabled() ) { HANDLE hFile = pFilePane->CreateFile( GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL ); if( INVALID_HANDLE_VALUE == hFile ) { return; } else { HWND hList = m_ConfirmationSheet.GetListHwnd(); int iLines = ListBox_GetCount( hList ); DWORD dwWritten = 0; for( int i = 0; i < iLines; i++ ) { int iLen = ListBox_GetTextLen( hList, i ) + 1; LPTSTR szLine = new TCHAR[ iLen ]; ListBox_GetText( hList, i, szLine ); if( !WriteFile( hFile, (void *)szLine, iLen, &dwWritten, NULL ) || !WriteFile( hFile, (void *)TEXT("\r\n"), lstrlen( TEXT("\r\n") ), &dwWritten, NULL ) ) { delete [] szLine; return; } delete [] szLine; } CloseHandle( hFile ); } } } void CNmAkWiz::_CreateDistro( void ) { CFilePanePropWnd2 * pFilePane = m_DistributionSheet.GetDistroFilePane(); if( pFilePane->OptionEnabled() ) { if( ! _SetPathNames() ) { assert( 0 ); return; } // First Extract the nm21.exe file to the OUTPUT Directory if( !_ExtractOldNmCabFile() ) { assert( 0 ); return; } // Create the new MsNetMtg.inf file in the OUTPUT Directory if( !_CreateNewInfFile() ) { assert( 0 ); return; } if( !_CreateFileDistribution( pFilePane ) ) { return; } // Clean up after ourselves if( !_DeleteFiles() ) { assert( 0 ); return; } } } void CNmAkWiz::_CreateFinalAutoConf( void ) { CFilePanePropWnd2 * pFilePane = m_DistributionSheet.GetAutoFilePane(); // if( pFilePane->OptionEnabled() ) // { // // Try to drop most of the output in a temp file... // TCHAR szBuf[ 256 ]; ULONG cbWritten; HANDLE hAutoINF = pFilePane->CreateFile( GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL ); if( INVALID_HANDLE_VALUE == hAutoINF ) { ErrorMessage(); return; } lstrcpy( szBuf, TEXT("[version]\r\nsignature=\"$CHICAGO$\"\r\n\r\n\r\nAdvancedINF=2.5\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } // Write string [NetMtg.Install.NMRK]\n lstrcpy( szBuf, TEXT("[NetMtg.Install.NMRK]\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } lstrcpy( szBuf, TEXT("AddReg=NetMtg.Install.Reg.NMRK\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } lstrcpy( szBuf, TEXT("DelReg=NetMtg.Install.DeleteReg.NMRK\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } // Write string [NetMtg.Install.Reg.NMRK]\n lstrcpy( szBuf, TEXT("\r\n\r\n[NetMtg.Install.Reg.NMRK]\r\n\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } lstrcpy( szBuf, TEXT("HKCU,\"SOFTWARE\\Microsoft\\Conferencing\\AutoConf\",\"Use AutoConfig\",65537,0, 0, 0, 0\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } // Write the REG Keys //_StoreDialogData( hAutoINF ); // Write string [NetMtg.Install.DeleteReg.NMRK]\n lstrcpy( szBuf, TEXT("\r\n\r\n[NetMtg.Install.DeleteReg.NMRK]\r\n\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } // Write the REG Delete Keys //CPolicyData::FlushCachedInfData( hAutoINF ); // this is needed... lstrcpy( szBuf, TEXT("\r\n\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } CloseHandle( hAutoINF ); // } } void CNmAkWiz::_CreateAutoConf( void ) { CFilePanePropWnd2 * pFilePane = m_DistributionSheet.GetAutoFilePane(); if( pFilePane->OptionEnabled() ) { // // Try to drop most of the output in a temp file... // TCHAR szBuf[ 256 ]; ULONG cbWritten; HANDLE hAutoINF = pFilePane->CreateFile( GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL ); if( INVALID_HANDLE_VALUE == hAutoINF ) { ErrorMessage(); return; } lstrcpy( szBuf, TEXT("[version]\r\nsignature=\"$CHICAGO$\"\r\n\r\n\r\nAdvancedINF=2.5\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } // Write string [NetMtg.Install.NMRK]\n lstrcpy( szBuf, TEXT("[NetMtg.Install.NMRK]\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } lstrcpy( szBuf, TEXT("AddReg=NetMtg.Install.Reg.NMRK\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } lstrcpy( szBuf, TEXT("DelReg=NetMtg.Install.DeleteReg.NMRK\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } // Write string [NetMtg.Install.Reg.NMRK]\n lstrcpy( szBuf, TEXT("\r\n\r\n[NetMtg.Install.Reg.NMRK]\r\n\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } // Write the REG Keys _StoreDialogData( hAutoINF ); // Write string [NetMtg.Install.DeleteReg.NMRK]\n lstrcpy( szBuf, TEXT("\r\n\r\n[NetMtg.Install.DeleteReg.NMRK]\r\n\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } // Write the REG Delete Keys CPolicyData::FlushCachedInfData( hAutoINF ); // this is needed... lstrcpy( szBuf, TEXT("\r\n\r\n") ); if( 0 == WriteFile( hAutoINF, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { return; } CloseHandle( hAutoINF ); } } // // CreateSettingsFile() // // This saves the options (policies, servers, auto-conf location, distro loc) // to a .INI file // void CNmAkWiz::_CreateSettingsFile(void) { CFilePanePropWnd2 * pFilePane = m_FinishSheet.GetFilePane(); if (pFilePane->OptionEnabled()) { HKEY hKey; m_SettingsSheet.WriteSettings(); m_CallModeSheet.WriteSettings(); m_ConfirmationSheet.GetFilePane()->WriteSettings(); m_DistributionSheet.GetDistroFilePane()->WriteSettings(); m_DistributionSheet.GetAutoFilePane()->WriteSettings(); // Save last config path in registry. if (RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_NMRK, &hKey) == ERROR_SUCCESS) { TCHAR szFile[MAX_PATH]; pFilePane->GetPathAndFile(szFile); RegSetValueEx(hKey, REGVAL_LASTCONFIG, 0, REG_SZ, (LPBYTE)szFile, lstrlen(szFile)+1); RegCloseKey(hKey); } } } //------------------------------------------------------------------------------------------------- // This is called when the user hits the the FINISH button after entering data with the wizard... // We simply get the information from the various dialogs ( property sheets as they are ), and // set the appropriate data in the .INF file void CNmAkWiz::CallbackForWhenUserHitsFinishButton( void ) { if (m_DistributionSheet.TurnedOffAutoConf() ) { _CreateFinalAutoConf(); } else { _CreateAutoConf(); } _CreateTextSpew(); _CreateSettingsFile(); _CreateDistro(); } //////////////////////////////////////////////////////////////////////////////////////////////////// // Constructors, Destructors, and Initialization Fns //////////////////////////////////////////////////////////////////////////////////////////////////// //-------------------------------------------------------------------------------------------------- // CNmAkWiz::CNmAkWiz CNmAkWiz::CNmAkWiz(void) : m_WelcomeSheet(), m_IntroSheet(), m_SettingsSheet(), m_CallModeSheet(), m_ConfirmationSheet(), m_DistributionSheet(), m_FinishSheet(), m_PropSheetHeader( ID_NumSheets, PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_NOAPPLYNOW /* | PSH_HASHELP */ ) { } //-------------------------------------------------------------------------------------------------- // CNmAkWiz::~CNmAkWiz CNmAkWiz::~CNmAkWiz( void ) { } //-------------------------------------------------------------------------------------------------- // CNmAkWiz::_InitInfFile opens the reg file specified by ms_InfFilePath\ms_InfFileName. // If the file cannot be created there, the user is prompted for a good location for the file. BOOL CNmAkWiz::_InitInfFile( void ) { // First we have to open the .INF file TCHAR szFileName[ MAX_PATH ]; int Err; const TCHAR* szInstallationPath = GetInstallationPath(); if( NULL != szInstallationPath ) { lstrcpy( szFileName, szInstallationPath ); lstrcat( szFileName, TEXT("\\") ); lstrcat( szFileName, ms_InfFilePath ); lstrcat( szFileName, TEXT("\\") ); lstrcat( szFileName, ms_InfFileName ); } else { assert( 0 ); lstrcat( szFileName, ms_InfFileName ); } /**/m_hInfFile = CreateFile( szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, // This is going to overwrite existing files FILE_ATTRIBUTE_NORMAL, NULL ); if( INVALID_HANDLE_VALUE == m_hInfFile ) { switch( Err = GetLastError() ) { case ERROR_ACCESS_DENIED: assert( 0 ); return FALSE; case ERROR_PATH_NOT_FOUND: assert( 0 ); return FALSE; case ERROR_WRITE_PROTECT: assert( 0 ); return FALSE; default: ErrorMessage( "", Err ); assert( 0 ); return FALSE; } } DWORD cbWritten; TCHAR szPreamble [] = TEXT("[version]\nsignature=\"$CHICAGO$\"\nAdvancedINF=2.5\n\n[DefaultInstall]\nAddReg\t= AddRegSection\nDelReg\t= DelRegSection\n\n\n[AddRegSection]\n"); RETFAIL( WriteFile( m_hInfFile, szPreamble, lstrlen( szPreamble ), &cbWritten, NULL ) ); return TRUE; } //-------------------------------------------------------------------------------------------------- // CNmAkWiz::_StoreDialogData // The user specifies a bunch of data in the g_pWiz-> NetMeeting ( conf.exe ) reads customization // data stored from the registry. We have to store this customization data in a .INF file for // the setup program to use. This function will get the data from the wizard and save it to // a .INF file according to the key maps which map a Wizard property to a Infistry entry... BOOL CNmAkWiz::_StoreDialogData( HANDLE hFile ) { m_SettingsSheet.WriteToINF( hFile ); m_CallModeSheet.WriteToINF( hFile ); m_DistributionSheet.GetAutoFilePane()->WriteToINF( hFile, TRUE ); return TRUE; } //-------------------------------------------------------------------------------------------------- // CNmAkWiz::_CloseInfFile closes the registry file that we are using to store the data entered // by the user in the Wizard. BOOL CNmAkWiz::_CloseInfFile( void ) { TCHAR szDelRegSectionPrefix[] = "\n\n[DelRegSection]\n"; DWORD cbWritten; RETFAIL( WriteFile( m_hInfFile, szDelRegSectionPrefix, lstrlen( szDelRegSectionPrefix ), &cbWritten, NULL ) ); CPolicyData::FlushCachedInfData( m_hInfFile ); CloseHandle( m_hInfFile ); return TRUE; } //-------------------------------------------------------------------------------------------------- // CNmAkWiz::_CreateDistributableFile creates a custom NetMeeting distributable incorporating // the registry changes that are stored in ms_InfFilePath\ms_InfFileName // The szPathName is a path where we are going to create a file called: // CNmAkWiz::ms_NetmeetingCustomDistributionFileName; BOOL CNmAkWiz::_CreateDistributableFile( CFilePanePropWnd2 *pFilePane ) { // Get the location of the original distribution if( !_GetNetMeetingOriginalDistributionData() ) { return FALSE; } TCHAR szNMOriginalDistributableFile[ MAX_PATH ]; TCHAR szNMCustomDistributableFile[ MAX_PATH ]; TCHAR szUpdateCommandLine[ MAX_PATH ]; pFilePane->CreateOutputDir(); pFilePane->GetPathAndFile( szNMCustomDistributableFile ); const TCHAR* sz = GetInstallationPath(); if( NULL != sz ) { lstrcpy( szNMOriginalDistributableFile, sz ); lstrcat( szNMOriginalDistributableFile, TEXT("\\" ) ); lstrcat( szNMOriginalDistributableFile, ms_NetmeetingSourceDirectory ); lstrcat( szNMOriginalDistributableFile, TEXT("\\" ) ); lstrcat( szNMOriginalDistributableFile, ms_NetmeetingOriginalDistributionFileName ); } // Copy source distribution to custom exe SHFILEOPSTRUCT FileOp; ZeroMemory( &FileOp, sizeof( FileOp ) ); FileOp.hwnd = g_hwndActive; FileOp.wFunc = FO_COPY; FileOp.fFlags = FOF_SIMPLEPROGRESS | FOF_NOCONFIRMATION; // Must double-null terminate file names for the struct... szNMOriginalDistributableFile[ lstrlen( szNMOriginalDistributableFile ) + 1 ] = '\0'; szNMCustomDistributableFile[ lstrlen( szNMCustomDistributableFile ) + 1 ] = '\0'; FileOp.pFrom = szNMOriginalDistributableFile; FileOp.pTo = szNMCustomDistributableFile; TCHAR szProgressTitle[ 256 ]; LoadString( g_hInstance, IDS_CREATING_CUSTOM_DISTRIBUTION, szProgressTitle, CCHMAX( szProgressTitle ) ); FileOp.lpszProgressTitle = szProgressTitle; int iRet = SHFileOperation( &FileOp ); if( 0 != iRet ) { return FALSE; } // CreateProcess: updfile nm30.exe MsNetMtg.inf const TCHAR* szInstallationPath = GetInstallationPath(); wsprintf(szUpdateCommandLine, "\"%s\\%s\\updfile.exe\" \"%s\" \"%s\\%s\"", szInstallationPath, ms_ToolsFolder, szNMCustomDistributableFile, ms_FileExtractPath, ms_InfFileName); OutputDebugString(szUpdateCommandLine); OutputDebugString("\n\r"); PROCESS_INFORMATION ProcInfo; STARTUPINFO StartupInfo; ZeroMemory( &StartupInfo, sizeof( StartupInfo ) ); StartupInfo.cb = sizeof( StartupInfo ); BOOL bRet = CreateProcess( NULL, szUpdateCommandLine, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &StartupInfo, &ProcInfo ); if( 0 == bRet ) { DWORD dwErr; if( ERROR_FILE_NOT_FOUND == ( dwErr = GetLastError() ) ) { TCHAR szMsg[ 256 ]; LoadString( g_hInstance, IDS_COULD_NOT_FIND_THE_TOOL, szMsg, CCHMAX( szMsg ) ); lstrcat( szMsg, TEXT(" \"") ); lstrcat( szMsg, szInstallationPath ); lstrcat( szMsg, TEXT("\\") ); lstrcat( szMsg, ms_ToolsFolder ); lstrcat( szMsg, TEXT("\\") ); lstrcat( szMsg, TEXT("updfile.exe\"") ); NmrkMessageBox( szMsg, MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION), MB_OK | MB_ICONSTOP ); NmrkMessageBox(MAKEINTRESOURCE(IDS_REINSTALL_THE_NETMEETING_RESOURCE_KIT_AND_TRY_AGAIN), MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION), MB_OK | MB_ICONSTOP); } return FALSE; } SetLastError( 0 ); DWORD dwRet; MSG msg; while (TRUE) { dwRet = MsgWaitForMultipleObjects(1, &ProcInfo.hThread, FALSE, INFINITE, QS_ALLINPUT); // Process is done if (dwRet == WAIT_OBJECT_0) break; // Something went wrong if (dwRet != WAIT_OBJECT_0 + 1) { ErrorMessage(); assert(0); return FALSE; } // GUI stuff while (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); if (WaitForSingleObject(ProcInfo.hThread, 0) == WAIT_OBJECT_0) { // Process is done break; } } } DWORD dwExitCode; bRet = GetExitCodeProcess( ProcInfo.hProcess, &dwExitCode ); if (dwExitCode != 0) { NmrkMessageBox(MAKEINTRESOURCE(IDS_NOT_ENOUGH_SPACE_IN_FINAL), MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION), MB_OK | MB_ICONEXCLAMATION ); return FALSE; } TCHAR szMsg[ 256 ]; lstrcpy( szMsg, szNMCustomDistributableFile ); int len = lstrlen( szMsg ); LoadString( g_hInstance, IDS_SUCCESSFULLY_CREATED, szMsg + len, CCHMAX(szMsg) - len ); NmrkMessageBox(szMsg, NULL, MB_OK); return TRUE; } //-------------------------------------------------------------------------------------------------- // CNmAkWiz::_CreateFileDistribution // We are going to create a file called CNmAkWiz::ms_NetmeetingCustomDistributionFileName in the // location specified by the user in the m_DistributionSheet dialog BOOL CNmAkWiz::_CreateFileDistribution( CFilePanePropWnd2 *pFilePane ) { if ( !_CreateDistributableFile( pFilePane )) { NmrkMessageBox(MAKEINTRESOURCE(IDS_THERE_WAS_AN_UNEXPECTED_ERROR), MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION), MB_OK | MB_ICONSTOP); return FALSE; } return TRUE; } //-------------------------------------------------------------------------------------------------- // CNmAkWiz::_NetMeetingOriginalDistributionIsAtSpecifiedLocationsearches // BOOL CNmAkWiz::_NetMeetingOriginalDistributionIsAtSpecifiedLocation( void ) { TCHAR szFileName[ MAX_PATH ]; const TCHAR* sz = GetInstallationPath(); if( NULL != sz ) { lstrcpy( ms_NetmeetingOriginalDistributionFilePath, sz ); lstrcat( ms_NetmeetingOriginalDistributionFilePath, TEXT("\\") ); lstrcat( ms_NetmeetingOriginalDistributionFilePath, ms_NetmeetingSourceDirectory ); lstrcat( ms_NetmeetingOriginalDistributionFilePath, TEXT("\\") ); } if( MAX_PATH < ( lstrlen( ms_NetmeetingOriginalDistributionFilePath ) + lstrlen( ms_NetmeetingOriginalDistributionFileName ) + 1 ) ) { assert( 0 ); return FALSE; // This should not happen becaues the file should have been // Created in this same program } lstrcpy( szFileName, ms_NetmeetingOriginalDistributionFilePath ); lstrcat( szFileName, ms_NetmeetingOriginalDistributionFileName ); HANDLE hFile = CreateFile( szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( INVALID_HANDLE_VALUE != hFile ) { // The NetMeeting Distribution file was at the specified location... CloseHandle( hFile ); return TRUE; } return FALSE; } //-------------------------------------------------------------------------------------------------- // CNmAkWiz::_GetNetMeetingOriginalDistributionData searches for the NetMeeting original // distribution and if it can't find it, it will ask the user to help // return TRUE if the user selected one, and FALSE if the user wants to quit BOOL CNmAkWiz::_GetNetMeetingOriginalDistributionData( void ) { // We have to get the file path from the user OPENFILENAME OpenFileName; while( !_NetMeetingOriginalDistributionIsAtSpecifiedLocation() ) { NmrkMessageBox(MAKEINTRESOURCE(IDS_CANT_FIND_NETMEETING_ORIGINAL_DISTRIBUTION), MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION), MB_OK | MB_ICONEXCLAMATION); ZeroMemory( &OpenFileName, sizeof( OpenFileName ) ); OpenFileName.lStructSize = sizeof( OpenFileName ); OpenFileName.hwndOwner = g_hwndActive; OpenFileName.lpstrFile = ms_NetmeetingOriginalDistributionFileName; OpenFileName.nMaxFile = MAX_PATH; OpenFileName.Flags = OFN_PATHMUSTEXIST; if( GetOpenFileName( &OpenFileName ) ) { lstrcpy( ms_NetmeetingOriginalDistributionFilePath, "" ); } else { // This means that the user wants to cancel if( IDCANCEL == NmrkMessageBox( MAKEINTRESOURCE(IDS_CANT_FIND_NETMEETING_ORIGINAL_DISTRIBUTION_QUERY_ABORT), MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION), MB_OKCANCEL | MB_ICONEXCLAMATION ) ) { exit( 0 ); } } } return TRUE; } //-------------------------------------------------------------------------------------------------- // CNmAkWiz::_DeleteFiles deletes the Temp files that we have been using... BOOL CNmAkWiz::_DeleteFiles( void ) { TCHAR szProgressTitle[ 256 ]; LoadString( g_hInstance, IDS_DELETING_TEMPORARY_FILES_PROGRESS_TITLE, szProgressTitle, CCHMAX( szProgressTitle ) ); TCHAR szOutputDirectoryPath[ MAX_PATH ]; lstrcpy( szOutputDirectoryPath, ms_FileExtractPath ); lstrcat( szOutputDirectoryPath, TEXT("\\*.*") ); // Must double NULL terminate this! szOutputDirectoryPath[ lstrlen( szOutputDirectoryPath ) + 1 ] = '\0'; int iRet = rmdir( ms_FileExtractPath ); if( ( -1 == iRet ) && ( ENOENT != errno ) ) { SHFILEOPSTRUCT FileOp; ZeroMemory( &FileOp, sizeof( FileOp ) ); FileOp.hwnd = g_hwndActive; FileOp.wFunc = FO_DELETE; FileOp.fFlags = FOF_SIMPLEPROGRESS | FOF_NOCONFIRMATION; FileOp.pFrom = szOutputDirectoryPath; FileOp.lpszProgressTitle = szProgressTitle; iRet = SHFileOperation( &FileOp ); iRet = rmdir( ms_FileExtractPath ); } return TRUE; } BOOL CNmAkWiz::_SetPathNames( void ) { GetTempPath( MAX_PATH, ms_FileExtractPath ); lstrcat( ms_FileExtractPath, ms_NMRK_TMP_FolderName ); OutputDebugString( "ms_FileExtractPath = " ); OutputDebugString( ms_FileExtractPath ); OutputDebugString( "\r\n" ); return TRUE; } const TCHAR* GetInstallationPath( void ) { static TCHAR szPath[ MAX_PATH ]; HKEY hKey; long lRet = RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_NMRK, &hKey ); if( ERROR_SUCCESS != lRet ) { return NULL; } DWORD cb = MAX_PATH; DWORD dwType = REG_SZ; if( ERROR_SUCCESS != RegQueryValueEx( hKey, REGVAL_INSTALLATIONDIRECTORY, NULL, &dwType, reinterpret_cast< LPBYTE >( szPath ), &cb ) ) { ErrorMessage(); if( ERROR_SUCCESS != RegCloseKey( hKey ) ) { ErrorMessage(); } return NULL; } if( ERROR_SUCCESS != RegCloseKey( hKey ) ) { ErrorMessage(); } return szPath; } BOOL CNmAkWiz::_CreateNewInfFile( void ) { // Load MsNetMtg.inf into memory TCHAR szInfFilePath[ MAX_PATH ]; TCHAR szBuf[ MAX_PATH ]; TCHAR* pOriginalInfFileData; TCHAR* pOriginalInfFileDataCursor; TCHAR* pCursor; DWORD dwSize; DWORD cbWritten; lstrcpy( szInfFilePath, ms_FileExtractPath ); lstrcat( szInfFilePath, TEXT("\\") ); lstrcat( szInfFilePath, ms_InfFileName ); m_hInfFile = CreateFile( szInfFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( INVALID_HANDLE_VALUE == m_hInfFile ) { goto ExitError; } DWORD dwFileSizeHigh; dwSize = GetFileSize( m_hInfFile, &dwFileSizeHigh ); pOriginalInfFileData = new TCHAR[ dwSize ]; pOriginalInfFileDataCursor = pOriginalInfFileData; DWORD cbRead; if( 0 == ReadFile( m_hInfFile, pOriginalInfFileData, dwSize, &cbRead, NULL ) ) { goto ExitError; } if( cbRead != dwSize ) { goto ExitError; } // Close MsNetMtg.inf file CloseHandle( m_hInfFile ); // Open MsNetMtg.inf for writing ( overwrite existing ) m_hInfFile = CreateFile( szInfFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if( INVALID_HANDLE_VALUE == m_hInfFile ) { goto ExitError; } // Set cursor to [DefaultInstall] string pCursor = strstr( pOriginalInfFileDataCursor, TEXT("[DefaultInstall]") ); if( NULL == pCursor ) { goto ExitError; } // Set cursor to next "AddReg" pCursor = strstr( pCursor, TEXT("AddReg") ); if( NULL == pCursor ) { goto ExitError; } // Set cursor to the end of the line pCursor = strstr( pCursor, TEXT("\r") ); if( NULL == pCursor ) { goto ExitError; } // Write Original Data up to the cursor to INF if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) { goto ExitError; } pOriginalInfFileDataCursor = pCursor; if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) { goto ExitError; } // Write ",NetMtg.Install.Reg.NMRK" to INF lstrcpy( szBuf, ",NetMtg.Install.Reg.NMRK" ); if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { goto ExitError; } // Set cursor to next "DelReg" pCursor = strstr( pCursor, "DelReg" ); if( NULL == pCursor ) { goto ExitError; } // Set cursor to the end of the line pCursor = strstr( pCursor, "\r" ); if( NULL == pCursor ) { goto ExitError; } // Write Original Data up to the cursor to INF if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) { goto ExitError; } pOriginalInfFileDataCursor = pCursor; // Write ",NetMtg.Install.DeleteReg.NMRK" to INF lstrcpy( szBuf, ",NetMtg.Install.DeleteReg.NMRK" ); if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { goto ExitError; } // Set cursor to [DefaultInstall.NT] string pCursor = strstr( pOriginalInfFileDataCursor, "[DefaultInstall.NT]" ); if( NULL == pCursor ) { goto ExitError; } // Set cursor to next "AddReg" pCursor = strstr( pCursor, "AddReg" ); if( NULL == pCursor ) { goto ExitError; } // Set cursor to the end of the line pCursor = strstr( pCursor, "\r" ); if( NULL == pCursor ) { goto ExitError; } // Write Original Data up to the cursor to INF if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) { goto ExitError; } pOriginalInfFileDataCursor = pCursor; if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) { goto ExitError; } // Write ",NetMtg.Install.Reg.NMRK" to INF lstrcpy( szBuf, ",NetMtg.Install.Reg.NMRK" ); if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { goto ExitError; } // Set cursor to next "DelReg" pCursor = strstr( pCursor, "DelReg" ); if( NULL == pCursor ) { goto ExitError; } // Set cursor to the end of the line pCursor = strstr( pCursor, "\r" ); if( NULL == pCursor ) { goto ExitError; } // Write Original Data up to the cursor to INF if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) { goto ExitError; } pOriginalInfFileDataCursor = pCursor; // Write ",NetMtg.Install.DeleteReg.NMRK" to INF lstrcpy( szBuf, ",NetMtg.Install.DeleteReg.NMRK" ); if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { goto ExitError; } // // Now we have to yank the old Ils stuff... // // Set cursor to [NetMtg.Install.Reg.PerUser] string pCursor = strstr( pCursor, "[NetMtg.Install.Reg.PerUser]" ); if( NULL == pCursor ) { goto ExitError; } // Skip to the start of the next line pCursor = strstr( pCursor, "\n" ); // This is the last TCHARacter on the line pCursor++; // This will be the first TCHARacter on the line // Write Original Data up to the cursor to INF if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) { goto ExitError; } pOriginalInfFileDataCursor = pCursor; // skip white space while( isspace( *pCursor ) ) { pCursor++; } // While the cursor is not '[' while( *pCursor != '[' ) { // if current line starts with if( ( pCursor == strstr( pCursor, "HKCU,\"%KEY_CONFERENCING%\\UI\\Directory\",\"Name" ) ) || ( pCursor == strstr( pCursor, "HKCU,\"%KEY_CONFERENCING%\\UI\\Directory\",\"Count" ) ) ) { // Delete the line by incrementing the base cursor to the beginning of the next line pCursor = strstr( pCursor, "\n" ); pCursor++; } else { break; } } // Set pOriginalInfFileDataCursor to cursor ( thus skipping the old Ils stuff ) pOriginalInfFileDataCursor = pCursor; // Set Cursor to [Strings] string pCursor = strstr( pCursor, "[Strings]" ); if( NULL == pCursor ) { goto ExitError; } // Write original data to the cursor if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) { goto ExitError; } pOriginalInfFileDataCursor = pCursor; // Write string [NetMtg.Install.Reg.NMRK]\n lstrcpy( szBuf, "\r\n\r\n[NetMtg.Install.Reg.NMRK]\r\n\r\n" ); if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { goto ExitError; } // Write the REG Keys _StoreDialogData( m_hInfFile ); // Write string [NetMtg.Install.DeleteReg.NMRK]\n lstrcpy( szBuf, "\r\n\r\n[NetMtg.Install.DeleteReg.NMRK]\r\n\r\n" ); if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { goto ExitError; } // Write the REG Delete Keys CPolicyData::FlushCachedInfData( m_hInfFile ); // this is needed... lstrcpy( szBuf, "\r\n\r\n" ); if( 0 == WriteFile( m_hInfFile, szBuf, lstrlen( szBuf ), &cbWritten, NULL ) ) { goto ExitError; } // Write the rest of the Original File to the INF pCursor = pOriginalInfFileData + dwSize; if( 0 == WriteFile( m_hInfFile, pOriginalInfFileDataCursor, pCursor - pOriginalInfFileDataCursor, &cbWritten, NULL ) ) { goto ExitError; } CloseHandle( m_hInfFile ); m_hInfFile = INVALID_HANDLE_VALUE; delete [] pOriginalInfFileData; return TRUE; ExitError: assert( 0 ); if( INVALID_HANDLE_VALUE != INVALID_HANDLE_VALUE ) { CloseHandle( m_hInfFile ); } delete [] pOriginalInfFileData; return FALSE; } BOOL CNmAkWiz::_ExtractOldNmCabFile( void ) { TCHAR szCabPath[ MAX_PATH ]; TCHAR szOutputDirectoryPath[ MAX_PATH ]; TCHAR szCommandLine[ MAX_PATH ]; // Clean up in case we abnormally terminated before... _DeleteFiles(); // Create the temp folder mkdir( ms_FileExtractPath ); const TCHAR* szInstallationPath = GetInstallationPath(); if( NULL != szInstallationPath ) { lstrcpy( szCabPath, "\"" ); lstrcat( szCabPath, szInstallationPath ); lstrcat( szCabPath, "\\" ); lstrcat( szCabPath, ms_NetmeetingSourceDirectory ); lstrcat( szCabPath, "\\" ); lstrcat( szCabPath, ms_NetmeetingOriginalDistributionFileName ); lstrcat( szCabPath, "\" " ); } else { assert( 0 ); lstrcat( szCabPath, ms_InfFileName ); } lstrcpy( szOutputDirectoryPath, ms_FileExtractPath ); lstrcpy( szCommandLine, "/C /T:\"" ); lstrcat( szCommandLine, szOutputDirectoryPath ); lstrcat( szCommandLine, "\" /Q" ); PROCESS_INFORMATION ProcInfo; STARTUPINFO StartupInfo; ZeroMemory( &StartupInfo, sizeof( StartupInfo ) ); StartupInfo.cb = sizeof( StartupInfo ); lstrcat( szCabPath, szCommandLine ); OutputDebugString( szCabPath ); OutputDebugString( "\n" ); BOOL iRet = CreateProcess( NULL, szCabPath, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcInfo ); if( FALSE == iRet ) { ErrorMessage(); assert( 0 ); return FALSE; } SetLastError( 0 ); DWORD dwRet; MSG msg; while (TRUE) { dwRet = MsgWaitForMultipleObjects(1, &ProcInfo.hThread, FALSE, INFINITE, QS_ALLINPUT); // Process is done if (dwRet == WAIT_OBJECT_0) break; // Something went wrong if (dwRet != WAIT_OBJECT_0 + 1) { ErrorMessage(); assert(0); return FALSE; } // GUI stuff while (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); if (WaitForSingleObject(ProcInfo.hThread, 0) == WAIT_OBJECT_0) { // Process is done break; } } } DWORD dwExitCode; BOOL bRet = GetExitCodeProcess( ProcInfo.hProcess, &dwExitCode ); // dwExitCode 0 is success if (dwExitCode != 0) { NmrkMessageBox(MAKEINTRESOURCE(IDS_NOT_ENOUGH_SPACE_IN_TEMP_DIR), MAKEINTRESOURCE(IDS_NMAKWIZ_ERROR_CAPTION), MB_OK | MB_ICONEXCLAMATION ); return FALSE; } return TRUE; } // // NmrkMessageBox() // // Puts up a message box owned by the wizard // int NmrkMessageBox ( LPCSTR lpszText, LPCSTR lpszCaption, UINT uType, HWND hwndParent ) { MSGBOXPARAMS mbp; ZeroMemory(&mbp, sizeof(mbp)); mbp.cbSize = sizeof(mbp); mbp.hwndOwner = NULL == hwndParent ? g_hwndActive : hwndParent; mbp.hInstance = g_hInstance; mbp.lpszText = lpszText; if (!lpszCaption) mbp.lpszCaption = MAKEINTRESOURCE(IDS_MSG_CAPTION); else mbp.lpszCaption = lpszCaption; mbp.dwStyle = uType | MB_SETFOREGROUND; return(MessageBoxIndirect(&mbp)); }