WindowsXP-SP1/enduser/netmeeting/nmrk/nmakwiz.cpp
2020-09-30 16:53:49 +02:00

1269 lines
40 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////////////////
// Look at the header file for usage information...
#include "precomp.h"
#include "resource.h"
#include <direct.h>
#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));
}