Click here to Skip to main content
15,887,083 members
Articles / Desktop Programming / MFC

Little Install Builder

Rate me:
Please Sign up or sign in to vote.
4.84/5 (23 votes)
30 Jul 20023 min read 100K   1.1K   47  
Building setup programs using Microsoft's setup scripts.
/****************************************************************/
/*																*/
/*  Setup.cpp													*/
/*																*/
/*  Implementation of the CSetupApp class.						*/
/*	This file is part of the Setup application.					*/
/*																*/
/*  Programmed by Pablo van der Meer							*/
/*  Copyright Pablo Software Solutions 2002						*/
/*	http://www.pablovandermeer.nl								*/
/*																*/
/*  Last updated: 22 July 2002									*/
/*																*/
/****************************************************************/

#include "stdafx.h"
#include "Setup.h"
#include "MainFrm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


BEGIN_MESSAGE_MAP(CSetupApp, CWinApp)
	//{{AFX_MSG_MAP(CSetupApp)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


CSetupApp::CSetupApp()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}

// The one and only CSetupApp object
CSetupApp theApp;


/********************************************************************/
/*																	*/
/* Function name : InitInstance										*/
/* Description   : CSetupApp initialization.						*/
/*																	*/
/********************************************************************/
BOOL CSetupApp::InitInstance()
{
	// Change the registry key under which our settings are stored.
	SetRegistryKey(_T("Pablo Software Solutions"));

	if (!ExtractSetupFiles())
	{
		AfxMessageBox("Failed to extract setup files!");
		return FALSE;
	}

	char szBuff[255];
	GetPrivateProfileString("Strings", "AppName", "Setup Application", szBuff, sizeof(szBuff), m_strLastExtractedFile);
	m_strApplicationName = szBuff;

	GetPrivateProfileString("Strings", "CopyrightMessage", "Copyright (c) 2002. All rights reserved. Pablo Software Solutions. http://www.pablovandermeer.nl", szBuff, sizeof(szBuff), m_strLastExtractedFile);
	m_strCopyright = szBuff;

	GetPrivateProfileString("Strings", "AppExe", "", szBuff, sizeof(szBuff), m_strLastExtractedFile);
	m_strApplicationExe = szBuff;
	m_strApplicationExe.TrimLeft();
	m_strApplicationExe.TrimRight();

	// To create the main window, this code creates a new frame window
	// object and then sets it as the application's main window object.
	CMainFrame* pFrame = new CMainFrame;
	m_pMainWnd = pFrame;

	// create and load the frame with its resources
	pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);

	// The one and only window has been initialized, so show and update it.
	pFrame->ShowWindow(SW_SHOWMAXIMIZED);
	pFrame->UpdateWindow();
	return TRUE;
}


/********************************************************************/
/*																	*/
/* Function name : ExitInstance										*/
/* Description   : CSetupApp cleanup.								*/
/*																	*/
/********************************************************************/
int CSetupApp::ExitInstance() 
{
	DeleteTemporaryFolder();

	CMainFrame* pFrame = (CMainFrame *)m_pMainWnd;
	if (pFrame)
		delete pFrame;

	return CWinApp::ExitInstance();
}


/********************************************************************/
/*																	*/
/* Function name : ExtractSetupFiles								*/
/* Description   : Extract files from setup package.				*/
/*																	*/
/********************************************************************/
BOOL CSetupApp::ExtractSetupFiles()
{
	// get temporary files directory
	char szTempPath[MAX_PATH];
	::GetTempPath(MAX_PATH, szTempPath);

	m_strExtractFolder = szTempPath;

	if (m_strExtractFolder.Right(1) != '\\')
		m_strExtractFolder += "\\";

	m_strExtractFolder += "~instdir\\";

	// create the extract directory
	CreateDirectories(m_strExtractFolder);

	// this is where the real extracting takes place...
	char szModuleName[MAX_PATH];
    char *ppMemoryBlock, *ppBlockEnd, *ptr;
    char *pStartPos = 0;
    
	// string to search for (unique GUID)
	CString strTag = "{58A60076-593E-414e-8152-BD3516480CAA}";
	// reverse it to prevent detecting it in this executable
	strTag.MakeReverse();

    int nLength = strTag.GetLength();

	// get our own name
    GetModuleFileName(NULL, szModuleName, sizeof(szModuleName));

    LoadFile(szModuleName, &ppMemoryBlock, &ppBlockEnd);

    if (!ppMemoryBlock) 
		return FALSE;

    ptr = ppMemoryBlock;
    
	int nCounter = 0;

	// search in memory block for string
    for ( ; ptr < ppBlockEnd; ptr++)
    {
        if (nCounter < nLength)
        {
			// compare part of string
            if (*ptr == strTag.GetAt(nCounter))
			{
                // this part is OK
				nCounter++;
			}
            else
			{
                // not good -> reset counter
				nCounter = 0;
			}
        }
        else
        {
			// found string !

			// rewind pointer (do not include marker tag)
			for (int i=0; i < nLength; i++)
				ptr--;

			ExtractFile(pStartPos, ptr, m_strExtractFolder);

			// skip marker
			for (int j=0; j < nLength; j++)
				ptr++;

            pStartPos = ptr;
            nCounter = 0;
        }
    }
	// last file is setup.inf !
    ExtractFile(pStartPos, ptr + 1, m_strExtractFolder);
    
	// release memory
	GlobalFree((HGLOBAL)ppMemoryBlock);

	return TRUE;
}


/********************************************************************/
/*																	*/
/* Function name : LoadFile											*/
/* Description   : Load whole file into memory.						*/
/*																	*/
/********************************************************************/
BOOL CSetupApp::LoadFile(LPCTSTR lpszFileName, char** ppMemoryBlock, char** ppBlockEnd)
{
    HANDLE hFile = CreateFile(lpszFileName, GENERIC_READ,
                   FILE_SHARE_READ, 0, OPEN_EXISTING,
                   FILE_ATTRIBUTE_NORMAL, 0 );
    
	*ppMemoryBlock = NULL;
    if (hFile == INVALID_HANDLE_VALUE)
        return FALSE;

	// get file size
    DWORD dwBytes = GetFileSize(hFile, 0);
    if (dwBytes == -1 )
        return FALSE;

	// allocate memory for file contents
    *ppMemoryBlock = (char*)GlobalAlloc(GMEM_ZEROINIT | GMEM_FIXED, dwBytes);
    *ppBlockEnd = *ppMemoryBlock + dwBytes;

    DWORD dwRead;
    if (ReadFile(hFile, *ppMemoryBlock, dwBytes, &dwRead, 0 ) == 0 || dwRead == 0)
        *ppMemoryBlock = NULL; 

    CloseHandle(hFile);
	return TRUE;
}


/********************************************************************/
/*																	*/
/* Function name : ExtractFile										*/
/* Description   : Extract one file from package -> write memory	*/
/*				   contents to file.								*/
/*																	*/
/********************************************************************/
BOOL CSetupApp::ExtractFile(LPTSTR lpszStart, LPTSTR lpszEnd, LPCTSTR lpszExtractFolder)
{
	if (lpszStart == NULL)
        return FALSE;

    if (lpszEnd - lpszStart == 0)
        return FALSE;

    FILETIME filetime[3];
	// get creation time, last access Time, lastwrite time
	memcpy(filetime, (LPCTSTR)lpszStart, sizeof(FILETIME) * 3);

	// move pointer to filename
	int nSize = sizeof(FILETIME) * 3;
	while (nSize--)
		*lpszStart++;
   
	int nLength = lstrlen(lpszStart);

	// save filename
	CString strFileName = lpszExtractFolder;
	strFileName += lpszStart;

	// move start position
    lpszStart = lpszStart + nLength + 1;
	
	// save file contents
    HANDLE hFile = CreateFile(strFileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 );
    if (hFile == INVALID_HANDLE_VALUE )
        return FALSE;
    
	DWORD dwWritten;
	WriteFile(hFile, (LPCVOID)lpszStart, lpszEnd - lpszStart, &dwWritten, 0);
	// restore original time stamp
	SetFileTime(hFile, &filetime[0], &filetime[1], &filetime[2]);
    CloseHandle(hFile);

	// remember last extracted filename
	m_strLastExtractedFile = strFileName;
	return TRUE;
}


/********************************************************************/
/*																	*/
/* Function name : DeleteTemporaryFolder							*/
/* Description   : Delete Temporary Folder and its contents.		*/
/*																	*/
/********************************************************************/
void CSetupApp::DeleteTemporaryFolder()
{
	// remove all files
	CFileFind finder;
	BOOL bContinue = finder.FindFile(m_strExtractFolder + "*.*");
	while (bContinue)
	{
		bContinue = finder.FindNextFile();
		if (finder.IsDots() || finder.IsDirectory())
			continue;

		DeleteFile(finder.GetFilePath());
	}
	finder.Close();

	// and finally remove the folder
	RemoveDirectory(m_strExtractFolder);
}


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Netherlands Netherlands
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions