Windows2003-3790/inetcore/setup/iexpress/cabpack/cabpack.c
2020-09-30 16:53:55 +02:00

4152 lines
157 KiB
C

//***************************************************************************
//* Copyright (c) Microsoft Corporation 1995. All rights reserved. *
//***************************************************************************
//* *
//* CABPACK.C - Wizard to build a Win32 Self-Extracting and self-installing *
//* EXE from a Cabinet (CAB) file. *
//* *
//***************************************************************************
//***************************************************************************
//* INCLUDE FILES *
//***************************************************************************
#include "pch.h"
#pragma hdrstop
#include "cabpack.h"
#include <memory.h>
#include "sdsutils.h"
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
#define MAX_TARGVER 0xFFFFFFFF
#define FLAG_BLK "OK"
#define FLAG_PMTYN "YesNo"
#define FLAG_PMTOC "OkCancel"
//***************************************************************************
//* GLOBAL VARIABLES *
//***************************************************************************
//---------------------------------------------------------------------------
// attention: 3\18\97: Update notes:
// We are changing our batch directive file extension from
// CDF to SED. But all the internal data structure name
// remain unchanged. So if you see CDF, it means old CDF file
// or new SED file data.
//---------------------------------------------------------------------------
HINSTANCE g_hInst = NULL; // Pointer to Instance
WIZARDSTATE *g_pWizardState = NULL; // Pointer to global wizard state
BOOL g_fQuitWizard = FALSE; // Global flag used to signal that we
// want to terminate the wizard
// ourselves
HFONT g_hBigFont = NULL; // Bigger font used by dialogs.
extern CDF g_CDF; // Contains stuff that we want to
// store in the CABPack Directive
// File
BOOL g_fBuildNow;
FARPROC g_lpfnOldMEditWndProc;
CHAR g_szOverideCDF[MAX_PATH];
CHAR g_szOverideSec[SMALL_BUF_LEN];
WORD g_wQuietMode = 0;
WORD g_wSilentMode = 0;
WORD g_wRunDiamondMinimized = 0;
HFONT g_hFont = NULL;
extern char g_szInitialDir[];
BOOL IsOSNT3X(VOID);
// This table defines the dialog id's and functions for processing each page.
// Pages need only provide functions when they want non-default behavior for
// certain action (init,buttons,notifications,next/back/finish,cancel).
PAGEINFO PageInfo[NUM_WIZARD_PAGES] = {
{ IDD_WELCOME, WelcomeInit, WelcomeCmd, NULL, WelcomeOK, NULL },
{ IDD_MODIFY, ModifyInit, NULL, NULL, ModifyOK, NULL },
{ IDD_PACKPURPOSE,PackPurposeInit,PackPurposeCmd,NULL, PackPurposeOK,NULL },
{ IDD_TITLE, TitleInit, NULL, NULL, TitleOK, NULL },
{ IDD_PROMPT, PromptInit, PromptCmd, NULL, PromptOK, NULL },
{ IDD_LICENSETXT, LicenseTxtInit, LicenseTxtCmd, NULL, LicenseTxtOK, NULL },
{ IDD_FILES, FilesInit, FilesCmd, FilesNotify, FilesOK, NULL },
{ IDD_COMMAND, CommandInit, NULL, NULL, CommandOK, NULL },
{ IDD_SHOWWINDOW, ShowWindowInit, NULL, NULL, ShowWindowOK, NULL },
{ IDD_FINISHMSG, FinishMsgInit, FinishMsgCmd, NULL, FinishMsgOK, NULL },
{ IDD_TARGET, TargetInit, TargetCmd, NULL, TargetOK, NULL },
{ IDD_TARGET_CAB, TargetCABInit, TargetCABCmd, NULL, TargetCABOK, NULL },
{ IDD_CABLABEL, CabLabelInit, CabLabelCmd, NULL, CabLabelOK, NULL },
{ IDD_REBOOT, RebootInit, RebootCmd, NULL, RebootOK, NULL },
{ IDD_SAVE, SaveInit, SaveCmd, NULL, SaveOK, NULL },
{ IDD_CREATE, CreateInit, NULL, NULL, CreateOK, NULL },
};
CDFSTRINGINFO CDFStrInfo[] = {
{ SEC_OPTIONS, KEY_INSTPROMPT, "", g_CDF.achPrompt, sizeof(g_CDF.achPrompt), g_szOverideSec, &g_CDF.fPrompt },
{ SEC_OPTIONS, KEY_DSPLICENSE, "", g_CDF.achLicense, sizeof(g_CDF.achLicense), g_szOverideSec, &g_CDF.fLicense },
{ SEC_OPTIONS, KEY_ENDMSG, "", g_CDF.achFinishMsg, sizeof(g_CDF.achFinishMsg), g_szOverideSec, &g_CDF.fFinishMsg },
{ SEC_OPTIONS, KEY_PACKNAME, "", g_CDF.achTarget, sizeof(g_CDF.achTarget), g_szOverideSec, NULL },
{ SEC_OPTIONS, KEY_FRIENDLYNAME, "", g_CDF.achTitle, sizeof(g_CDF.achTitle), g_szOverideSec, NULL },
{ SEC_OPTIONS, KEY_APPLAUNCH, "", g_CDF.achOrigiInstallCmd,sizeof(g_CDF.achInstallCmd),g_szOverideSec, NULL },
{ SEC_OPTIONS, KEY_POSTAPPLAUNCH, "", g_CDF.achOrigiPostInstCmd,sizeof(g_CDF.achPostInstCmd),g_szOverideSec, NULL },
{ SEC_OPTIONS, KEY_ADMQCMD, "", g_CDF.szOrigiAdmQCmd, sizeof(g_CDF.szOrigiAdmQCmd), g_szOverideSec, NULL },
{ SEC_OPTIONS, KEY_USERQCMD, "", g_CDF.szOrigiUsrQCmd, sizeof(g_CDF.szOrigiUsrQCmd), g_szOverideSec, NULL },
} ;
CDFOPTINFO CDFOptInfo[] = {
{ KEY_NOEXTRACTUI, EXTRACTOPT_UI_NO },
{ KEY_USELFN, EXTRACTOPT_LFN_YES },
{ KEY_PLATFORM_DIR, EXTRACTOPT_PLATFORM_DIR },
{ KEY_NESTCOMPRESSED, EXTRACTOPT_COMPRESSED },
{ KEY_UPDHELPDLLS, EXTRACTOPT_UPDHLPDLLS },
{ KEY_CHKADMRIGHT, EXTRACTOPT_CHKADMRIGHT },
{ KEY_PASSRETURN, EXTRACTOPT_PASSINSTRET },
{ KEY_PASSRETALWAYS,EXTRACTOPT_PASSINSTRETALWAYS },
{ KEY_CMDSDEPENDED, EXTRACTOPT_CMDSDEPENDED },
};
CHAR *AdvDlls[] = { ADVANCEDLL, ADVANCEDLL32, ADVANCEDLL16 };
PSTR pResvSizes[] = { CAB_0K, CAB_2K, CAB_4K, CAB_6K };
void SetControlFont();
void TermApp();
//***************************************************************************
//* *
//* NAME: WinMain *
//* *
//* SYNOPSIS: Main entry point for the program. *
//* *
//* REQUIRES: hInstance: Handle to the program instance *
//* hPrevInstance: Handle to the previous instance (NULL) *
//* lpszCmdLine: Command line arguments *
//* nCmdShow: How to show the window *
//* *
//* RETURNS: int: Always 0 *
//* *
//***************************************************************************
INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, INT nCmdShow )
{
g_hInst = hInstance;
g_fBuildNow = FALSE;
g_szOverideCDF[0] = 0;
g_szOverideSec[0] = 0;
// init CDF filenaem
g_CDF.achFilename[0] = '\0';
g_CDF.achVerInfo[0] = '\0';
g_CDF.lpszCookie = NULL;
InitItemList(); // Initilize our file item list.
// Get the command line args. If there is a "/N", then we want to
// build NOW!
if ( !ParseCmdLine( lpszCmdLine ) )
{
ErrorMsg( NULL, IDS_ERR_BADCMDLINE );
return 1; //error return case
}
if ( g_fBuildNow && lstrlen( g_CDF.achFilename ) > 0 )
{
// batch mode did not update the CDF file, no need for writeCDF
if ( ReadCDF( NULL ) && MakePackage( NULL ) )
{
return 0;
}
else
{
return 1;
}
}
// Allocate global structures
g_pWizardState = (PWIZARDSTATE) malloc( sizeof( WIZARDSTATE) );
if ( ! g_pWizardState ) {
ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
} else {
SetControlFont();
RunCABPackWizard();
if (g_hFont)
DeleteObject(g_hFont);
}
// Clean up dialog title font
DestroyBigFont();
TermApp();
// Free global structures
if ( g_pWizardState ) {
free( g_pWizardState );
}
return 0;
}
// Free up the allocated resource
//
void TermApp()
{
if ( g_CDF.lpszCookie )
{
LocalFree( g_CDF.lpszCookie );
}
if ( g_CDF.pVerInfo )
LocalFree( g_CDF.pVerInfo );
}
//***************************************************************************
//* *
//* NAME: RunCABPackWizard *
//* *
//* SYNOPSIS: Creates property sheet pages, initializes wizard property *
//* sheet and runs wizard. *
//* *
//* REQUIRES: Nothing *
//* *
//* RETURNS: BOOL: TRUE if user runs wizard to completion, FALSE *
//* if user cancels or an error occurs. *
//* *
//* NOTES: Wizard pages all use one dialog proc (GenDlgProc). They may *
//* specify their own handler procs to get called at init time *
//* or in response to Next, Cancel or a dialog control, or use *
//* the default behavior of GenDlgProc. *
//* *
//***************************************************************************
BOOL RunCABPackWizard( VOID )
{
HPROPSHEETPAGE hWizPage[NUM_WIZARD_PAGES]; // array to hold handles to pages
PROPSHEETPAGE psPage; // struct used to create prop sheet pages
PROPSHEETHEADER psHeader; // struct used to run wizard property sheet
UINT nPageIndex;
UINT nFreeIndex;
INT_PTR iRet;
ASSERT( g_pWizardState );
// initialize the app state structure
InitWizardState( g_pWizardState );
// zero out structures
memset( &hWizPage, 0, sizeof(hWizPage) );
memset( &psPage, 0, sizeof(psPage) );
memset( &psHeader, 0, sizeof(psHeader) );
// fill out common data property sheet page struct
psPage.dwSize = sizeof(psPage);
psPage.dwFlags = PSP_DEFAULT;
psPage.hInstance = g_hInst;
psPage.pfnDlgProc = GenDlgProc;
// create a property sheet page for each page in the wizard
for ( nPageIndex = 0; nPageIndex < NUM_WIZARD_PAGES; nPageIndex++ ) {
psPage.pszTemplate = MAKEINTRESOURCE( PageInfo[nPageIndex].uDlgID );
// set a pointer to the PAGEINFO struct as the private data for this
// page
psPage.lParam = (LPARAM) &PageInfo[nPageIndex];
hWizPage[nPageIndex] = CreatePropertySheetPage( &psPage );
if ( !hWizPage[nPageIndex] ) {
// creating page failed, free any pages already created and bail
ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
for ( nFreeIndex = 0; nFreeIndex < nPageIndex; nFreeIndex++ ) {
DestroyPropertySheetPage( hWizPage[nFreeIndex] );
}
return FALSE;
}
}
// fill out property sheet header struct
psHeader.dwSize = sizeof(psHeader);
psHeader.dwFlags = PSH_WIZARD | PSH_USEICONID;
psHeader.hwndParent = NULL;
psHeader.hInstance = g_hInst;
psHeader.nPages = NUM_WIZARD_PAGES;
psHeader.phpage = hWizPage;
psHeader.pszIcon = (LPSTR) IDI_ICON;
// run the Wizard
iRet = PropertySheet( &psHeader );
if ( iRet < 0 ) {
// property sheet failed, most likely due to lack of memory
ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
}
// If the user Cancels out of the Wizard, there may be items
// left in the file list. Clean them up.
DeleteAllItems();
return ( iRet > 0 );
}
//***************************************************************************
//* *
//* NAME: GenDlgProc *
//* *
//* SYNOPSIS: Generic dialog proc for all wizard pages. *
//* *
//* REQUIRES: hDlg: *
//* uMsg: *
//* wParam: *
//* lParam: *
//* *
//* RETURNS: BOOL: *
//* *
//* *
//* NOTES: This dialog proc provides the following default behavior: *
//* init: back and next buttons enabled *
//* next btn: switches to page following current page *
//* back btn: switches to previous page *
//* cancel btn: prompts user to confirm, and cancels wizard *
//* dlg ctrl: does nothing (in response to WM_COMMANDs) *
//* Wizard pages can specify their own handler functions (in *
//* the PageInfo table) to override default behavior for any of *
//* the above actions. *
//* *
//***************************************************************************
INT_PTR CALLBACK GenDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch ( uMsg ) {
//*********************************************************************
case WM_INITDIALOG:
//*********************************************************************
{
LPPROPSHEETPAGE lpsp; // get propsheet page struct passed in
PPAGEINFO pPageInfo; // fetch our private page info from
// propsheet struct
lpsp = (LPPROPSHEETPAGE) lParam;
ASSERT( lpsp );
pPageInfo = (PPAGEINFO) lpsp->lParam;
ASSERT( pPageInfo );
// store pointer to private page info in window data for later
SetWindowLongPtr( hDlg, DWLP_USER, (LPARAM) pPageInfo );
// set title text to large font
InitBigFont( hDlg, IDC_BIGTEXT );
// initialize 'back' and 'next' wizard buttons, if
// page wants something different it can fix in init proc below
PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT |
PSWIZB_BACK );
// call init proc for this page if one is specified
if ( pPageInfo->InitProc ) {
return pPageInfo->InitProc( hDlg, TRUE );
}
return TRUE;
break;
}
//*********************************************************************
case WM_NOTIFY:
//*********************************************************************
{
// get pointer to private page data out of window data
PPAGEINFO pPageInfo;
BOOL fRet;
BOOL fKeepHistory = TRUE;
NMHDR *lpnm = (NMHDR *) lParam;
UINT uNextPage = 0;
pPageInfo = (PPAGEINFO) GetWindowLongPtr( hDlg, DWLP_USER );
ASSERT( pPageInfo );
switch ( lpnm->code ) {
//***********************************************************
case PSN_SETACTIVE:
//***********************************************************
// initialize 'back' and 'next' wizard buttons, if
// page wants something different it can fix in init proc
PropSheet_SetWizButtons( GetParent(hDlg), PSWIZB_NEXT |
PSWIZB_BACK );
// call init proc for this page if one is specified
if ( pPageInfo->InitProc ) {
return pPageInfo->InitProc(hDlg,FALSE);
}
return TRUE;
break;
//***********************************************************
case PSN_WIZNEXT:
case PSN_WIZBACK:
case PSN_WIZFINISH:
//***********************************************************
// call OK proc for this page if one is specified
if ( pPageInfo->OKProc )
if ( ! pPageInfo->OKProc( hDlg, ( lpnm->code != PSN_WIZBACK ), &uNextPage, &fKeepHistory ) )
{
// stay on this page
SetPropSheetResult( hDlg, -1 );
return TRUE;
}
if ( lpnm->code != PSN_WIZBACK ) {
// 'next' pressed
ASSERT( g_pWizardState->uPagesCompleted <
NUM_WIZARD_PAGES );
// save the current page index in the page history,
// unless this page told us not to when we called
// its OK proc above
if ( fKeepHistory ) {
g_pWizardState->uPageHistory
[g_pWizardState->uPagesCompleted]
= g_pWizardState->uCurrentPage;
g_pWizardState->uPagesCompleted++;
}
// if no next page specified or no OK proc,
// advance page by one
if ( !uNextPage ) {
uNextPage = g_pWizardState->uCurrentPage + 1;
}
} else {
// 'back' pressed
ASSERT( g_pWizardState->uPagesCompleted > 0 );
// get the last page from the history list
g_pWizardState->uPagesCompleted--;
uNextPage = g_pWizardState->
uPageHistory[g_pWizardState->
uPagesCompleted];
}
// if we need to exit the wizard now, send a 'cancel'
// message to ourselves (to keep the prop. page mgr happy)
if ( g_fQuitWizard ) {
PropSheet_PressButton(GetParent(hDlg), PSBTN_CANCEL);
SetPropSheetResult( hDlg, -1 );
return TRUE;
}
// set next page, only if 'next' or 'back' button
// was pressed
if ( lpnm->code != PSN_WIZFINISH ) {
// set the next current page index
g_pWizardState->uCurrentPage = uNextPage;
// tell the prop sheet mgr what the next page to
// display is
SetPropSheetResult( hDlg,
GetDlgIDFromIndex( uNextPage ) );
return TRUE;
}
break;
//***********************************************************
case PSN_QUERYCANCEL:
//***********************************************************
// if global flag to exit is set, then this cancel
// is us pretending to push 'cancel' so prop page mgr
// will kill the wizard. Let this through...
if ( g_fQuitWizard ) {
SetWindowLongPtr( hDlg, DWLP_MSGRESULT, FALSE );
return TRUE;
}
// if this page has a special cancel proc, call it
if ( pPageInfo->CancelProc )
fRet = pPageInfo->CancelProc( hDlg );
else {
// default behavior: pop up a message box confirming
// the cancel
fRet = ( MsgBox( hDlg, IDS_QUERYCANCEL,
MB_ICONQUESTION, MB_YESNO |
MB_DEFBUTTON2 ) == IDYES );
}
// return the value thru window data
SetWindowLongPtr( hDlg, DWLP_MSGRESULT, !fRet );
return TRUE;
break;
//***********************************************************
default:
//***********************************************************
if ( pPageInfo->NotifyProc ) {
pPageInfo->NotifyProc( hDlg, wParam, lParam );
}
}
break;
}
//*********************************************************************
case WM_COMMAND:
//*********************************************************************
{
// get pointer to private page data out of window data
PPAGEINFO pPageInfo;
UINT uNextPage = 0;
BOOL fGotoPage = FALSE;
BOOL fKeepHistory = TRUE;
pPageInfo = (PPAGEINFO) GetWindowLongPtr( hDlg, DWLP_USER );
ASSERT( pPageInfo );
// if this page has a command handler proc, call it
if ( pPageInfo->CmdProc ) {
pPageInfo->CmdProc( hDlg, (UINT) LOWORD(wParam), &fGotoPage,
&uNextPage, &fKeepHistory );
if ( fGotoPage ) {
ASSERT( g_pWizardState->uPagesCompleted
< NUM_WIZARD_PAGES );
ASSERT( g_pWizardState->uPagesCompleted > 0 );
SetPropSheetResult( hDlg, uNextPage );
g_pWizardState->uCurrentPage = uNextPage;
if ( fKeepHistory ) {
g_pWizardState->uPageHistory[g_pWizardState->
uPagesCompleted] = g_pWizardState->uCurrentPage;
g_pWizardState->uPagesCompleted++;
}
// set the next current page index
g_pWizardState->uCurrentPage = uNextPage;
// tell the prop sheet mgr what the next page to
// display is
SetPropSheetResult( hDlg,
GetDlgIDFromIndex( uNextPage ) );
return TRUE;
}
}
}
}
return FALSE;
}
//***************************************************************************
//* *
//* NAME: InitWizardState *
//* *
//* SYNOPSIS: Initializes wizard state structure. *
//* *
//* REQUIRES: pWizardState: *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
VOID InitWizardState( WIZARDSTATE *pWizardState )
{
ASSERT( pWizardState );
// zero out structure
memset( pWizardState, 0, sizeof(WIZARDSTATE) );
// set starting page
pWizardState->uCurrentPage = ORD_PAGE_WELCOME;
}
//***************************************************************************
//* *
//* NAME: MEditSubClassWnd *
//* *
//* SYNOPSIS: Subclasses a multiline edit control so that a edit message *
//* to select the entire contents is ignored. *
//* *
//* REQUIRES: hWnd: Handle of the edit window *
//* fnNewProc: New window handler proc *
//* lpfnOldProc: (returns) Old window handler proc *
//* *
//* RETURNS: Nothing *
//* *
//* NOTE: A selected edit message is not generated when the user *
//* selects text with the keyboard or mouse. *
//* *
//***************************************************************************
VOID NEAR PASCAL MEditSubClassWnd( HWND hWnd, FARPROC fnNewProc )
{
g_lpfnOldMEditWndProc = (FARPROC) GetWindowLongPtr( hWnd, GWLP_WNDPROC );
SetWindowLongPtr( hWnd, GWLP_WNDPROC, (LONG_PTR) MakeProcInstance( fnNewProc,
(HINSTANCE) GetWindowWord( hWnd, GWW_HINSTANCE ) ) );
}
//***************************************************************************
//* *
//* NAME: MEditSubProc *
//* *
//* SYNOPSIS: New multiline edit window procedure to ignore selection of *
//* all contents. *
//* *
//* REQUIRES: hWnd: *
//* msg: *
//* wParam: *
//* lParam: *
//* *
//* RETURNS: LONG: *
//* *
//* NOTE: A selected edit message is not generated when the user *
//* selects text with the keyboard or mouse. *
//* *
//***************************************************************************
LRESULT CALLBACK MEditSubProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
if ( msg == EM_SETSEL ) {
return 0;
wParam = lParam;
lParam = MAKELPARAM( LOWORD(lParam), LOWORD(lParam) );
}
return CallWindowProc( (WNDPROC) g_lpfnOldMEditWndProc, hWnd, msg,
wParam, lParam );
}
//***************************************************************************
//* *
//* NAME: GetDlgIDFromIndex *
//* *
//* SYNOPSIS: For a given zero-based page index, returns the *
//* corresponding dialog ID for the page. *
//* *
//* REQUIRES: uPageIndex: *
//* *
//* RETURNS: UINT: *
//* *
//***************************************************************************
UINT GetDlgIDFromIndex( UINT uPageIndex )
{
ASSERT( uPageIndex < NUM_WIZARD_PAGES );
return PageInfo[uPageIndex].uDlgID;
}
//***************************************************************************
//* *
//* NAME: EnableWizard *
//* *
//* SYNOPSIS: Enables or disables the wizard buttons and the wizard page *
//* itself (so it can't receive focus). *
//* *
//* REQUIRES: hDlg: Dialog window *
//* fEnable: TRUE to enable the wizard, FALSE to disable *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
VOID EnableWizard( HWND hDlg, BOOL fEnable )
{
HWND hwndWiz = GetParent( hDlg );
// disable/enable back, next, cancel
EnableWindow( GetDlgItem( hwndWiz, IDD_BACK ), fEnable );
EnableWindow( GetDlgItem( hwndWiz, IDD_NEXT ), fEnable );
EnableWindow( GetDlgItem( hwndWiz, IDCANCEL ), fEnable );
// disable/enable wizard page
EnableWindow( hwndWiz, fEnable );
UpdateWindow( hwndWiz );
if ( fEnable ) {
SetForegroundWindow( hDlg );
}
}
//***************************************************************************
//* *
//* NAME: MsgWaitForMultipleObjectsLoop *
//* *
//* SYNOPSIS: *
//* *
//* REQUIRES: hEvent: *
//* *
//* RETURNS: DWORD: *
//* *
//***************************************************************************
DWORD MsgWaitForMultipleObjectsLoop( HANDLE hEvent )
{
MSG msg;
DWORD dwObject;
while (1)
{
dwObject = MsgWaitForMultipleObjects( 1, &hEvent, FALSE,INFINITE,
QS_ALLINPUT );
// Are we done waiting?
switch ( dwObject ) {
case WAIT_OBJECT_0:
case WAIT_FAILED:
return dwObject;
case WAIT_OBJECT_0 + 1:
// got a message, dispatch it and wait again
while (PeekMessage(&msg, NULL,0, 0, PM_REMOVE)) {
DispatchMessage(&msg);
}
break;
}
}
}
//***************************************************************************
//* *
//* NAME: MsgBox2Param *
//* *
//* SYNOPSIS: Displays a message box with the specified string ID using *
//* 2 string parameters. *
//* *
//* REQUIRES: hWnd: Parent window *
//* nMsgID: String resource ID *
//* szParam1: Parameter 1 (or NULL) *
//* szParam2: Parameter 2 (or NULL) *
//* uIcon: Icon to display (or 0) *
//* uButtons: Buttons to display *
//* *
//* RETURNS: INT: ID of button pressed *
//* *
//* NOTES: Macros are provided for displaying 1 parameter or 0 *
//* parameter message boxes. Also see ErrorMsg() macros. *
//* *
//***************************************************************************
INT MsgBox2Param( HWND hWnd, UINT nMsgID, LPCSTR szParam1, LPCSTR szParam2,
UINT uIcon, UINT uButtons )
{
CHAR achMsgBuf[STRING_BUF_LEN];
CHAR achSmallBuf[SMALL_BUF_LEN];
LPSTR szMessage;
INT nReturn;
if ( !(g_wQuietMode == 1) )
{
LoadSz( IDS_APPNAME, achSmallBuf, sizeof(achSmallBuf) );
LoadSz( nMsgID, achMsgBuf, sizeof(achMsgBuf) );
if ( szParam2 != NULL ) {
szMessage = (LPSTR) LocalAlloc( LPTR, lstrlen( achMsgBuf )
+ lstrlen( szParam1 )
+ lstrlen( szParam2 ) + 100 );
if ( ! szMessage ) {
return -1;
}
wsprintf( szMessage, achMsgBuf, szParam1, szParam2 );
} else if ( szParam1 != NULL ) {
szMessage = (LPSTR) LocalAlloc( LPTR, lstrlen( achMsgBuf )
+ lstrlen( szParam1 ) + 100 );
if ( ! szMessage ) {
return -1;
}
wsprintf( szMessage, achMsgBuf, szParam1, szParam2 );
} else {
szMessage = (LPSTR) LocalAlloc( LPTR, lstrlen( achMsgBuf ) + 1 );
if ( ! szMessage ) {
return -1;
}
lstrcpy( szMessage, achMsgBuf );
}
MessageBeep( uIcon );
nReturn = MessageBox( hWnd, szMessage, achSmallBuf, uIcon | uButtons |
MB_APPLMODAL | MB_SETFOREGROUND |
((RunningOnWin95BiDiLoc() && IsBiDiLocalizedBinary(g_hInst,RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO))) ? (MB_RIGHT | MB_RTLREADING) : 0) );
LocalFree( szMessage );
return nReturn;
} else {
return MB_OK;
}
}
//***************************************************************************
//* *
//* NAME: DisplayFieldErrorMsg *
//* *
//* SYNOPSIS: Pops up a warning message about a field, sets focus to the *
//* field and selects any text in it. *
//* *
//* REQUIRES: hDlg: parent windows *
//* uCtrlID: ID of control left blank *
//* uStrID: ID of string resource with warning message *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
VOID DisplayFieldErrorMsg( HWND hDlg, UINT uCtrlID, UINT uStrID )
{
ErrorMsg( hDlg, uStrID );
SetFocus( GetDlgItem( hDlg, uCtrlID ) );
SendDlgItemMessage( hDlg, uCtrlID, EM_SETSEL, 0, -1 );
}
//***************************************************************************
//* *
//* NAME: FileExists *
//* *
//* SYNOPSIS: Checks if a file exists. *
//* *
//* REQUIRES: pszFilename *
//* *
//* RETURNS: BOOL: TRUE if it exists, FALSE otherwise *
//* *
//***************************************************************************
BOOL FileExists( LPCSTR pszFilename )
{
HANDLE hFile;
ASSERT( pszFilename );
hFile = CreateFile( pszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL );
if ( hFile == INVALID_HANDLE_VALUE ) {
return( FALSE );
}
CloseHandle( hFile );
return( TRUE );
}
//***************************************************************************
//* *
//* NAME: InitBigFont *
//* *
//* SYNOPSIS: Sets the font of the specifed control to the large (title) *
//* font. Creates the font if it doesn't already exist. *
//* *
//* REQUIRES: hwnd: *
//* uCtrlID: *
//* *
//* RETURNS: Nothing *
//* *
//* NOTES: Make sure to call DestroyBigFont before the app exits to *
//* dispose of the font. *
//* *
//* Borrowed from Win 95 setup code. *
//* *
//***************************************************************************
VOID InitBigFont( HWND hwnd, UINT uCtrlID )
{
HFONT hFont;
HWND hwndCtl;
LOGFONT lFont;
int nLogPixelsY;
HDC hDC;
// get the window for the specified control
if ( ( hwndCtl = GetDlgItem( hwnd, uCtrlID ) ) == NULL ) {
return;
}
// get the logical y pixels
hDC = GetDC( NULL );
ASSERT( hDC );
if ( !hDC ) {
return;
}
nLogPixelsY = GetDeviceCaps( hDC, LOGPIXELSY );
ReleaseDC( NULL, hDC );
if ( ! g_hBigFont ) {
if ( ( hFont = (HFONT) (WORD) SendMessage( hwndCtl, WM_GETFONT, 0, 0L ) ) != NULL ) {
if ( GetObject( hFont, sizeof(LOGFONT), (LPSTR) &lFont ) ) {
lFont.lfWeight = FW_BOLD;
LoadString( g_hInst, IDS_MSSERIF, lFont.lfFaceName, LF_FACESIZE - 1 );
lFont.lfHeight = -1 * ( nLogPixelsY * LARGE_POINTSIZE / 72 );
g_hBigFont = CreateFontIndirect( (LPLOGFONT) &lFont );
}
}
}
if ( g_hBigFont ) {
SendMessage( hwndCtl, WM_SETFONT, (WPARAM) g_hBigFont, 0L );
}
else {
// couldn't create font
// DEBUGTRAP( "Couldn't create large font" );
}
}
//***************************************************************************
//* *
//* NAME: DestroyBigFont *
//* *
//* SYNOPSIS: Destroys the large font used for dialog titles, if it has *
//* been created. *
//* *
//* REQUIRES: Nothing *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
VOID DestroyBigFont( VOID )
{
if ( g_hBigFont ) {
DeleteObject( g_hBigFont );
g_hBigFont = NULL;
}
}
//***************************************************************************
//* *
//* NAME: EnableDlgItem *
//* *
//* SYNOPSIS: Makes it a little simpler to enable a dialog item. *
//* *
//* REQUIRES: hDlg: Dialog handle *
//* uID: ID of control *
//* fEnable: TRUE to enable, FALSE to disable *
//* *
//* RETURNS: BOOL: TRUE if successfull, FALSE otherwise *
//* *
//***************************************************************************
BOOL EnableDlgItem( HWND hDlg, UINT uID, BOOL fEnable )
{
return EnableWindow( GetDlgItem( hDlg, uID ), fEnable );
}
//***************************************************************************
//* *
//* NAME: LoadSz *
//* *
//* SYNOPSIS: Loads specified string resource into buffer. *
//* *
//* REQUIRES: idString: *
//* lpszBuf: *
//* cbBuf: *
//* *
//* RETURNS: LPSTR: Pointer to the passed-in buffer. *
//* *
//* NOTES: If this function fails (most likely due to low memory), the *
//* returned buffer will have a leading NULL so it is generally *
//* safe to use this without checking for failure. *
//* *
//***************************************************************************
LPSTR LoadSz( UINT idString, LPSTR lpszBuf, UINT cbBuf )
{
ASSERT( lpszBuf );
// Clear the buffer and load the string
if ( lpszBuf ) {
*lpszBuf = '\0';
LoadString( g_hInst, idString, lpszBuf, cbBuf );
}
return lpszBuf;
}
//***************************************************************************
//* *
//* NAME: IsDuplicate *
//* *
//* SYNOPSIS: Checks if a file being added to the list view is already *
//* in the listview. *
//* *
//* REQUIRES: hDlg: dialog window *
//* nDlgItem: ID of list view control *
//* szFilename: Name of file to check for a dupe. *
//* *
//* RETURNS: BOOL: TRUE if it's a duplicate, FALSE otherwise *
//* *
//***************************************************************************
BOOL WINAPI IsDuplicate( HWND hDlg, INT nDlgItem, LPSTR szFilename, BOOL chkIsListbox )
{
INT nItems;
HWND hwndFiles;
LV_ITEM lviCheck;
PMYITEM pItem = NULL;
INT nIndex;
if ( chkIsListbox )
{
hwndFiles = GetDlgItem( hDlg, nDlgItem );
nItems = ListView_GetItemCount( hwndFiles );
for ( nIndex = 0; nIndex < nItems; nIndex += 1 ) {
lviCheck.mask = LVIF_PARAM;
lviCheck.iItem = nIndex;
lviCheck.iSubItem = 0;
lviCheck.lParam = (LPARAM) pItem;
ListView_GetItem( hwndFiles, &lviCheck );
if ( lstrcmpi( ((PMYITEM)(lviCheck.lParam))->aszCols[0],
szFilename ) == 0 )
{
return TRUE;
}
}
}
else // check through the file item list
{
pItem = GetFirstItem();
while ( ! LastItem( pItem ) )
{
if ( !lstrcmpi( szFilename, GetItemSz( pItem, 0 ) ) )
{
return TRUE;
}
pItem = GetNextItem( pItem );
}
}
return FALSE;
}
//***************************************************************************
//* *
//* NAME: IsMyKeyExists *
//* *
//* SYNOPSIS: Checks if a specific key in the given section and given file*
//* is defined. IF so, get the value. OW return -1 *
//* *
//* *
//***************************************************************************
LONG IsMyKeyExists( LPCSTR lpSec, LPCSTR lpKey, LPSTR lpBuf, UINT uSize, LPCSTR lpFile )
{
LONG lRet;
lRet = (LONG)GetPrivateProfileString( lpSec, lpKey, SYS_DEFAULT, lpBuf, uSize, lpFile );
if ( lpSec && lpKey && (lRet == (LONG)(uSize-1)) || !lpKey && (lRet == (LONG)(uSize-2)) )
{
// not enough buffer size to read the string
lRet = -2;
}
else if ( !lstrcmp( lpBuf, SYS_DEFAULT ) )
{
// no key defined
lRet = -1;
}
return lRet;
}
ULONG FileSize( LPSTR lpFile )
{
ULONG ulFileSize;
WIN32_FIND_DATA FindFileData;
HANDLE hFile;
if ( *lpFile == 0 )
return 0;
hFile = FindFirstFile( lpFile, &FindFileData );
ulFileSize = (FindFileData.nFileSizeHigh * MAXDWORD) + FindFileData.nFileSizeLow;
FindClose( hFile );
return ulFileSize;
}
void NotifyBadString( PCSTR pszBadname, UINT uMaxSize )
{
char szSize[20];
_itoa(uMaxSize, szSize, 10);
MsgBox2Param( NULL, IDS_ERR_BADSTRING, pszBadname, szSize, MB_ICONSTOP, MB_OK );
}
//***************************************************************************
//
// FormStrWithoutPlaceHolders( LPSTR szDst, LPCSTR szSrc, LPCSTR lpFile, UINT uSize );
//
// This function can be easily described by giving examples of what it
// does:
// Input: GenFormStrWithoutPlaceHolders(dest,"desc=%MS_XYZ%", hinf) ;
// INF file has MS_VGA="Microsoft XYZ" in its [Strings] section!
//
// Output: "desc=Microsoft XYZ" in buffer dest when done.
//
//
// ENTRY:
// szDst - the destination where the string after the substitutions
// for the place holders (the ones enclosed in "%' chars!)
// is placed. This buffer should be big enough (LINE_LEN)
// szSrc - the string with the place holders.
// uSize - the size of the output buffer
//
// EXIT:
//
// NOTES:
// To use a '%' as such in the string, one would use %% in szSrc! BUGBUG For
// the sake of simplicity, we have placed a restriction that the place
// holder name string cannot have a '%' as part of it! If this is a problem
// for internationalization, we can revisit this and support it too! Also,
// the way it is implemented, if there is only one % in the string, it is
// also used as such! Another point to note is that if the key is not
// found in the [Strings] section, we just use the %strkey% as such in the
// destination. This should really help in debugging.
//
// BTW, CH_STRINGKEY, in the code below, is the symbolic name for '%'.
//
// Get/modified it from setupx: gen1.c
//***************************************************************************
LONG FormStrWithoutPlaceHolders( LPSTR szDst, LPCSTR szSrc, UINT uSize )
{
int uCnt ;
LONG lRet;
CHAR *pszTmp;
LPSTR pszSaveDst;
pszSaveDst = szDst;
// Do until we reach the end of source (null char)
while( (*szDst++ = *szSrc) )
{
// Increment source as we have only incremented destination above
if(*szSrc++ == CH_STRINGKEY)
{
if (*szSrc == CH_STRINGKEY)
{
// One can use %% to get a single percentage char in message
szSrc++ ;
continue ;
}
// see if it is well formed -- there should be a '%' delimiter
if ( (pszTmp = strchr( szSrc, CH_STRINGKEY)) != NULL )
{
szDst--; // get back to the '%' char to replace
// yes, there is a STR_KEY to be looked for in [Strings] sect.
*pszTmp = '\0' ; // replace '%' with a NULL char
// szSrc points to the replaceable key now as we put the NULL char above.
if ( (g_szOverideCDF[0] == 0) || (g_CDF.achStrings[0] == 0) ||
(lRet = IsMyKeyExists( g_CDF.achStrings, szSrc, szDst, uSize, g_szOverideCDF )) == -1 )
{
lRet = IsMyKeyExists( SEC_STRINGS, szSrc, szDst, uSize, g_CDF.achFilename );
}
if ( lRet == -1 )
{
// key is missing in [Strings] section!
if ( MsgBox1Param( NULL, IDS_WARN_MISSSTRING, (LPSTR)szSrc, MB_ICONQUESTION, MB_YESNO ) == IDNO )
return lRet;
*pszTmp = CH_STRINGKEY; // put back original character
szSrc-- ; // get back to first '%' in Src
uCnt = (INT)((pszTmp - szSrc) + 1); // include 2nd '%'
// UGHHH... It copies 1 less byte from szSrc so that it can put
// in a bad NULL character, that I don't care about!!!
// Different from the normal API I am used to...
lstrcpyn( szDst, szSrc, uCnt + 1 ) ;
}
else if ( lRet == -2 )
{
NotifyBadString( szSrc, uSize );
return lRet;
}
else
{
// all was well, Dst filled right, but unfortunately count not passed
// back, like it used too... :-( quick fix is a lstrlen()...
uCnt = lstrlen( szDst ) ;
}
*pszTmp = CH_STRINGKEY ; // put back original character
szSrc = pszTmp + 1 ; // set Src after the second '%'
szDst += uCnt ; // set Dst also right.
}
// else it is ill-formed -- we use the '%' as such!
else
{
if ( MsgBox1Param( NULL, IDS_ERR_READ_CDF, (LPSTR)(szSrc - 1), MB_ICONQUESTION, MB_YESNO ) == IDNO )
return -1;
}
}
} /* while */
return lstrlen(pszSaveDst);
} /* GenFormStrWithoutPlaceHolders */
//***************************************************************************
//* *
//* NAME: MyGetPrivateProfileString *
//* *
//* SYNOPSIS: get key string vale from overide CDF if exists. Otherwise, *
//* get it from Main CDF. And expand to its real string value *
//* return -1 if key-string define error and user stops *
//* *
//***************************************************************************
LONG MyGetPrivateProfileString( LPCSTR lpSec, LPCSTR lpKey, LPCSTR lpDefault,
LPSTR lpBuf, UINT uSize, LPCSTR lpOverSec )
{
PSTR pszNewLine;
LONG lRet;
if ( g_szOverideCDF[0] == 0 || *lpOverSec == 0 ||
(lRet= IsMyKeyExists( lpOverSec, lpKey, lpBuf, uSize, g_szOverideCDF )) == -1 )
{
lRet = (LONG)GetPrivateProfileString( lpSec, lpKey, lpDefault, lpBuf, uSize, g_CDF.achFilename );
}
if ( lpKey == NULL )
{
return lRet;
}
pszNewLine = (LPSTR)LocalAlloc( LPTR, uSize );
if ( pszNewLine )
{
lRet = FormStrWithoutPlaceHolders( pszNewLine, lpBuf, uSize );
if ( lRet >= 0 )
lstrcpy( lpBuf, pszNewLine );
LocalFree( pszNewLine );
}
return lRet;
}
//***************************************************************************
//* *
//* NAME: MyGetPrivateProfileInt *
//* *
//* SYNOPSIS: get key INT vale from overide CDF if exists. Otherwise, *
//* get it from Main CDF. And expand to its real string value *
//* *
//***************************************************************************
UINT MyGetPrivateProfileInt( LPCSTR lpSec, LPCSTR lpKey, int idefault, LPCSTR lpOverSec )
{
UINT uRet = 999; // means not valid value
if ( g_szOverideCDF[0] && *lpOverSec )
uRet = GetPrivateProfileInt( lpOverSec, lpKey, 999, g_szOverideCDF );
if ( uRet == 999 )
uRet = GetPrivateProfileInt( lpSec, lpKey, idefault, g_CDF.achFilename );
return uRet;
}
//***************************************************************************
//* *
//* NAME: MyGetPrivateProfileSection *
//* *
//* SYNOPSIS: get section from overide CDF if exists. Otherwise, *
//* get it from Main CDF. *
//* *
//***************************************************************************
LONG MyGetPrivateProfileSection( LPCSTR lpSec, LPSTR lpBuf, int size, BOOL bSingleCol )
{
LONG lRet;
if ( g_szOverideCDF[0] == 0 || (lRet=RO_GetPrivateProfileSection( lpSec, lpBuf, size, g_szOverideCDF, bSingleCol )) == 0 )
{
lRet = RO_GetPrivateProfileSection( lpSec, lpBuf, size, g_CDF.achFilename, bSingleCol );
}
return lRet;
}
//***************************************************************************
//* *
//* NAME: MyWritePrivateProfileString *
//* *
//* SYNOPSIS: Write out all String value Key in its localizable format *
//* %...% If previouse keyname=%used-define% exists, reuse *
//* user-define as key in Strings section. Otherwise, use *
//* %keyname% and define keyname in Strings section *
//* *
//***************************************************************************
void MyWritePrivateProfileString( LPCSTR lpSec, LPCSTR lpKey, LPSTR lpBuf, UINT uSize, BOOL fQuotes )
{
CHAR szTmpBuf[MAX_PATH];
LPSTR pszTmpBuf2 = NULL;
BOOL fUseDefault;
pszTmpBuf2 = (LPSTR)LocalAlloc( LPTR, uSize+32 );
if ( !pszTmpBuf2 )
return;
// when we write the string value out, we write it in a localizable fashion
// if the item has %strKey% format, we re-use the %strKey% as its String refer key
// otherwise, we use %item-name% as the string refer key
GetPrivateProfileString( lpSec, lpKey, "", szTmpBuf, uSize, g_CDF.achFilename );
if ( (szTmpBuf[0] == CH_STRINGKEY) && (szTmpBuf[lstrlen(szTmpBuf)-1] == CH_STRINGKEY) )
{
szTmpBuf[lstrlen(szTmpBuf)-1] = '\0';
fUseDefault = FALSE;
}
else
{
lstrcpy( szTmpBuf, "%" );
lstrcat( szTmpBuf, lpKey );
lstrcat( szTmpBuf, "%" );
WritePrivateProfileString( lpSec, lpKey, szTmpBuf, g_CDF.achFilename );
fUseDefault = TRUE;
}
if ( fQuotes ) {
lstrcpy( pszTmpBuf2, "\"" );
lstrcat( pszTmpBuf2, lpBuf );
lstrcat( pszTmpBuf2, "\"" );
} else {
lstrcpy( pszTmpBuf2, lpBuf );
}
WritePrivateProfileString( SEC_STRINGS, fUseDefault?lpKey:(szTmpBuf+1), pszTmpBuf2, g_CDF.achFilename );
if ( pszTmpBuf2 )
LocalFree( pszTmpBuf2 );
return;
}
//***************************************************************************
//* *
//* NAME: CleanStringKey *
//* *
//* SYNOPSIS: Cleanup the leftover File%d stuff in Strings *
//* *
//***************************************************************************
void CleanStringKey( LPSTR lpstrKey )
{
LPSTR pszTmp;
if ( lpstrKey == NULL )
return;
while ( *lpstrKey )
{
if ( *lpstrKey++ == CH_STRINGKEY )
{
if (*lpstrKey == CH_STRINGKEY)
{
// One can use %% to get a single percentage char in message
lpstrKey++ ;
continue ;
}
// see if it is well formed -- there should be a '%' delimiter
if ( (pszTmp = strchr( lpstrKey, CH_STRINGKEY)) != NULL )
{
// yes, there is a STR_KEY to be looked for in [Strings] sect.
*pszTmp = '\0' ; // replace '%' with a NULL char
WritePrivateProfileString( SEC_STRINGS, lpstrKey, NULL, g_CDF.achFilename);
*pszTmp = CH_STRINGKEY;
lpstrKey = pszTmp+1;
}
else
break;
}
}
}
//***************************************************************************
//* *
//* NAME: CleanupSection *
//* *
//* SYNOPSIS: Cleanup the any given section with key=%xxxx% and its *
//* strings *
//* *
//***************************************************************************
BOOL CleanupSection( LPSTR lpSec, BOOL fSingleCol )
{
LPSTR lpBuf, lpSave;
CHAR szStrKey[SMALL_BUF_LEN];
int size;
size = FileSize( g_CDF.achFilename );
lpBuf = (LPSTR) LocalAlloc( LPTR, size );
if ( !lpBuf )
{
ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
return FALSE;
}
lpSave = lpBuf;
if ( fSingleCol )
RO_GetPrivateProfileSection( lpSec, lpBuf, size, g_CDF.achFilename, TRUE );
else
GetPrivateProfileString( lpSec, NULL, "", lpBuf, size, g_CDF.achFilename );
while ( *lpBuf )
{
if ( fSingleCol )
CleanStringKey( lpBuf );
else
{
GetPrivateProfileString( lpSec, lpBuf, "", szStrKey, sizeof(szStrKey), g_CDF.achFilename );
CleanStringKey( szStrKey );
}
lpBuf += lstrlen(lpBuf);
lpBuf++; //jump over the single '\0'
}
WritePrivateProfileString( lpSec, NULL, NULL, g_CDF.achFilename );
LocalFree( lpSave );
return TRUE;
}
//***************************************************************************
//* *
//* NAME: CleanSourceFiles *
//* *
//* SYNOPSIS: Cleanup the leftover SourceFile%d stuff *
//* *
//***************************************************************************
BOOL CleanSourceFiles( LPSTR lpSection )
{
LPSTR lpBuf, lpSave;
int size;
size = FileSize( g_CDF.achFilename );
lpBuf = (LPSTR) LocalAlloc( LPTR, size );
if ( !lpBuf )
{
ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
return FALSE;
}
lpSave = lpBuf;
GetPrivateProfileString( lpSection, NULL, "", lpBuf, size, g_CDF.achFilename );
while ( *lpBuf )
{
if ( !CleanupSection( lpBuf, TRUE ) )
{
LocalFree( lpSave );
return FALSE;
}
lpBuf += (lstrlen(lpBuf) + 1);
}
WritePrivateProfileString( lpSection, NULL, NULL, g_CDF.achFilename );
LocalFree( lpSave );
return TRUE;
}
//***************************************************************************
//* *
//* NAME: MergerSection *
//* *
//***************************************************************************
BOOL MergeSection( LPSTR lpSec, LPSTR lpOverideSec )
{
// always merge the lpOverideSec keys to lpSec
LPSTR lpBuf, lpSave;
CHAR szValue[MAX_PATH];
int size;
size = __max( FileSize( g_CDF.achFilename ), FileSize( g_szOverideCDF ) ) ;
lpBuf = (LPSTR) LocalAlloc( LPTR, size );
if ( !lpBuf )
{
ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
return FALSE;
}
lpSave = lpBuf;
GetPrivateProfileString( lpOverideSec, NULL, "", lpBuf, size, g_szOverideCDF );
while ( *lpBuf )
{
if ( MyGetPrivateProfileString( lpSec, lpBuf, "", szValue, sizeof(szValue), lpOverideSec ) == -1 )
{
LocalFree( lpSave );
return FALSE;
}
MyWritePrivateProfileString( lpSec, lpBuf, szValue, sizeof(szValue), FALSE );
lpBuf += (lstrlen(lpBuf) + 1);
}
LocalFree( lpSave );
return TRUE;
}
// If the next token in *pszData is delimited by the DeLim char, replace DeLim
// in *pszData by chEos, set *pszData to point to the char after the chEos and return
// ptr to the beginning of the token; otherwise, return NULL
//
LPSTR GetNextToken(LPSTR *pszData, char DeLim)
{
LPSTR szPos;
if (pszData == NULL || *pszData == NULL || **pszData == 0)
return NULL;
if ((szPos = strchr(*pszData, DeLim)) != NULL)
{
LPSTR szT = *pszData;
*pszData = CharNext(szPos);
*szPos = '\0';
szPos = szT;
}
else
{
szPos = *pszData;
*pszData = szPos + lstrlen(szPos);
}
return szPos;
}
void SetVerUnlimit( PVERRANGE pVer )
{
pVer->toVer.dwMV = MAX_TARGVER;
pVer->toVer.dwLV = MAX_TARGVER;
pVer->toVer.dwBd = MAX_TARGVER;
}
// given the str version range: ver1-ver2
void SetVerRange( PVERRANGE pVR, LPSTR pstrVer, BOOL bFile )
{
LPSTR pTmp, pArg, pSubArg;
DWORD dwVer[4];
int i, j;
BOOL bSingleVer;
pArg = pstrVer;
bSingleVer = strchr( pstrVer, '-' ) ? FALSE : TRUE;
for ( i=0; i<2; i++ )
{
pTmp = GetNextToken( &pArg, '-' );
if ( !pTmp )
{
if ( !bSingleVer )
{
// case1 -4.0.0 == 0.0.0-4.0.0
// case2 4.0.0- == 4.0.0-NoLimit
//
if ( i == 0 )
continue;
else
SetVerUnlimit( pVR );
}
break;
}
for ( j=0; j<4; j++ )
{
dwVer[j] = strtoul( pTmp, &pSubArg, 10 );
pTmp = CharNext(pSubArg);
}
if ( bFile )
{
DWORD dwMV, dwLV;
dwMV = MAKELONG( (WORD)dwVer[1], (WORD)dwVer[0] );
dwLV = MAKELONG( (WORD)dwVer[3], (WORD)dwVer[2] );
if ( i == 0 )
{
pVR->frVer.dwMV = dwMV;
pVR->frVer.dwLV = dwLV;
}
else
{
pVR->toVer.dwMV = dwMV;
pVR->toVer.dwLV = dwLV;
}
}
else
{
if ( i == 0 ) // start version (from version)
{
pVR->frVer.dwMV = dwVer[0];
pVR->frVer.dwLV = dwVer[1];
pVR->frVer.dwBd = dwVer[2];
}
else
{
pVR->toVer.dwMV = dwVer[0];
pVR->toVer.dwLV = dwVer[1];
pVR->toVer.dwBd = dwVer[2];
}
}
}
}
//***************************************************************************
//* *
//* NAME: GetTargetVerCheck *
//* *
//* SYNOPSIS: Get author specifined target versions *
//* *
//***************************************************************************
BOOL ParseTargetVerCheck( LPSTR szBuf, PVERCHECK pVerCheck, LPSTR szMsg, BOOL bFile)
{
int i, j;
LPSTR pArg, pSubArg, pTmp;
DWORD dwVer[4];
*szMsg = 0;
if ( szBuf[0] == 0 )
{
// this is the case that no versions are specified, meaning applying to all
SetVerUnlimit( &(pVerCheck->vr[0]) );
return TRUE;
}
// the loop for possible 3 fields: <ver range> : str : flags
//
pArg = szBuf;
for ( i=0; i<3; i++ )
{
pTmp = GetNextToken( &pArg, ':' );
if ( !pTmp )
break;
else if ( *pTmp == 0 )
{
if ( i == 0 )
{
// empty version range field no bother further!
SetVerUnlimit( &(pVerCheck->vr[0]) );
break;
}
continue;
}
if ( i == 0 )
{
LPSTR pRange;
// version range format: ver1-ver2 , ver1-ver2 :
//
for ( j = 0; j<2; j++)
{
pRange = GetNextToken( &pTmp, ',' );
if ( !pRange )
break;
else if ( *pRange == 0 )
continue;
else
SetVerRange( &(pVerCheck->vr[j]), pRange, bFile );
}
}
else if ( i == 1 )
{
// string field
lstrcpy( szMsg, pTmp );
}
else
{
// flag field
if ( !lstrcmpi(pTmp, FLAG_BLK) )
pVerCheck->dwFlag |= VERCHK_OK;
else if ( !lstrcmpi(pTmp, FLAG_PMTYN) )
pVerCheck->dwFlag |= VERCHK_YESNO;
else if ( !lstrcmpi(pTmp, FLAG_PMTOC) )
pVerCheck->dwFlag |= VERCHK_OKCANCEL;
else
{
ErrorMsg1Param( NULL, IDS_ERR_VCHKFLAG, pTmp );
return FALSE;
}
}
}
// Just in case, we broke out early or user's to-ver is empty fill with from-ver.
//
for ( j = 0; j<2; j++ )
{
if ( !pVerCheck->vr[j].toVer.dwMV && !pVerCheck->vr[j].toVer.dwLV && !pVerCheck->vr[j].toVer.dwBd )
{
pVerCheck->vr[j].toVer = pVerCheck->vr[j].frVer;
}
}
return TRUE;
}
//***************************************************************************
//* *
//* NAME: OutFileListSection *
//* *
//* SYNOPSIS: Write out the file list from the internal ItemList *
//* *
//***************************************************************************
BOOL OutFileListSection()
{
PMYITEM pItem;
LPSTR lpFileStr;
CHAR szCurrSection[MAX_SECLEN];
CHAR szCurrFile[MAX_SECLEN];
CHAR szCurrSecValue[MAX_PATH];
BOOL fAllDone;
int idxSec = 0, idxFile = 0;
LPSTR pFileList;
CHAR achFilename[MAX_PATH+10];
// this will allocate enough space to build file key list
#define FILEKEYSIZE 20
pFileList = (LPSTR) LocalAlloc( LPTR, g_CDF.cbFileListNum*FILEKEYSIZE );
if ( !pFileList )
{
ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
return FALSE;
}
do
{
fAllDone = TRUE;
pItem = g_CDF.pTop;
lpFileStr = pFileList;
szCurrSection[0] = 0;
*lpFileStr = '\0';
while ( pItem )
{
if ( !pItem->fWroteOut )
{
if ( fAllDone )
fAllDone = FALSE;
// if this section is not write out yet, write now
if ( pItem->aszCols[1] && (szCurrSection[0] == 0) )
{
lstrcpy( szCurrSection, KEY_FILELIST );
lstrcat( szCurrSection, _itoa(idxSec++, szCurrFile, 10 ) );
WritePrivateProfileString( g_CDF.achSourceFile, szCurrSection, pItem->aszCols[1], g_CDF.achFilename );
lstrcpy( szCurrSecValue, pItem->aszCols[1] );
}
if ( !lstrcmpi( szCurrSecValue, pItem->aszCols[1] ) )
{
pItem->fWroteOut = TRUE;
wsprintf( szCurrFile, KEY_FILEBASE, idxFile++ );
lstrcpy( achFilename, pItem->aszCols[0] );
MyWritePrivateProfileString( SEC_STRINGS, szCurrFile, achFilename, sizeof(achFilename), TRUE );
// build file list of this section
lstrcpy( lpFileStr, "%" );
lstrcat( lpFileStr, szCurrFile );
lstrcat( lpFileStr, "%=" );
lpFileStr += lstrlen(lpFileStr);
lpFileStr++; // jump over the '\0'
}
}
pItem = pItem->Next;
}
if ( !fAllDone )
{
*lpFileStr = '\0';
WritePrivateProfileSection( szCurrSection, pFileList, g_CDF.achFilename );
}
} while ( !fAllDone );
LocalFree( pFileList );
return TRUE;
}
// return the number of entries in the section
//
DWORD GetSecNumLines( LPCSTR pSec, LPCSTR pFile )
{
char szBuf[MAX_PATH];
DWORD dwNum = 0;
int i = 0;
GetPrivateProfileString( pSec, NULL, "", szBuf, sizeof(szBuf), pFile );
while ( szBuf[i] )
{
dwNum++;
i += lstrlen( &szBuf[i] );
i++; // jump over the fence
}
return dwNum;
}
// check if need to alloc and how much is needed
//
BOOL AllocTargetVerInfo( LPSTR pInfFile )
{
char achBuf[MAX_INFLINE];
DWORD dwNumFiles = 0;
BOOL bRet = TRUE;
DWORD dwSize;
if ( IsMyKeyExists( SEC_OPTIONS, KEY_SYSFILE, achBuf, sizeof(achBuf), pInfFile ) != -1 )
{
if (achBuf[0] == '@')
{
// process the file section
dwNumFiles = GetSecNumLines( &achBuf[1], pInfFile );
}
else
dwNumFiles = 1;
}
if ( dwNumFiles ||
(IsMyKeyExists( SEC_OPTIONS, KEY_NTVERCHECK, achBuf, sizeof(achBuf), pInfFile ) != -1) ||
(IsMyKeyExists( SEC_OPTIONS, KEY_WIN9XVERCHECK, achBuf, sizeof(achBuf), pInfFile ) != -1) )
{
// alloc structure: fixed potion, Message string pool and variable number of filever check struct
//
dwSize = sizeof(TARGETVERINFO) + (3*MAX_PATH) + (sizeof(VERCHECK) + MAX_PATH)*dwNumFiles;
if ( g_CDF.pVerInfo = (PTARGETVERINFO)LocalAlloc( LPTR, dwSize ) )
{
g_CDF.pVerInfo->dwNumFiles = dwNumFiles;
}
else
{
ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
bRet = FALSE;
}
}
return bRet;
}
void SetAuthorStr( LPCSTR szMsg, DWORD *pdwOffset )
{
int len = 0;
LPSTR pTmp;
BOOL bDup = FALSE;
if ( szMsg[0] )
{
pTmp = &(g_CDF.pVerInfo->szBuf[1]);
// there is an author defined message
while ( pTmp && *pTmp )
{
if ( !lstrcmpi( pTmp, szMsg ) )
{
bDup = TRUE;
break;
}
len = (lstrlen( pTmp )+1);
pTmp += len;
}
if ( pTmp )
{
// only store the offset to szBuf
*pdwOffset = (DWORD)(pTmp - g_CDF.pVerInfo->szBuf);
if ( !bDup )
{
// meaning there is no existing one!
//
lstrcpy( pTmp, szMsg );
// store the end of the last string data offset
g_CDF.pVerInfo->dwFileOffs = *pdwOffset + lstrlen(pTmp) + 1;
}
}
}
}
BOOL ParseTargetFiles( LPCSTR pBuf, PVERCHECK pVer )
{
LPSTR lpTmp1, lpTmp2;
BOOL bRet = FALSE;
char szPath[MAX_PATH];
lpTmp1 = strchr( pBuf, ':' );
if ( lpTmp1 )
{
char ch = (char)toupper(pBuf[1]);
lpTmp2 = CharNext( lpTmp1 );
*(lpTmp1) = '\0';
if ( (pBuf[0] == '#') && ( (ch == 'S') || (ch == 'W') || (ch == 'A') ) )
{
if ( ParseTargetVerCheck( lpTmp2, pVer, szPath, TRUE ) )
{
SetAuthorStr( szPath, &(pVer->dwstrOffs) );
SetAuthorStr( pBuf, &(pVer->dwNameOffs) );
bRet = TRUE;
}
}
}
return bRet;
}
//***************************************************************************
//* *
//* NAME: WriteCDF *
//* *
//* SYNOPSIS: Write a CABPack Directive File. Uses information from *
//* Global CDF structure (g_CDF). *
//* *
//* REQUIRES: hDlg: dialog window *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
BOOL WriteCDF( HWND hDlg )
{
CHAR achBuf[2 * MAX_PATH];
int i, arraySize;
// write class name.
WritePrivateProfileString( SEC_VERSION, KEY_CLASS, IEXPRESS_CLASS, g_CDF.achFilename );
// delete the old CDFVersion= line and add SEFVersion= line
WritePrivateProfileString( SEC_VERSION, KEY_VERSION, NULL, g_CDF.achFilename );
WritePrivateProfileString( SEC_VERSION, KEY_NEWVER, IEXPRESS_VER, g_CDF.achFilename );
// Write the config info, numeric value.
// if user has old ExtractOnly key, delete it first and re-create the new key PackagePurpose instead
WritePrivateProfileString( SEC_OPTIONS, KEY_EXTRACTONLY, NULL, g_CDF.achFilename );
switch ( g_CDF.uPackPurpose )
{
case IDC_CMD_RUNCMD:
default:
lstrcpy( achBuf, STR_INSTALLAPP );
break;
case IDC_CMD_EXTRACT:
lstrcpy( achBuf, STR_EXTRACTONLY );
break;
case IDC_CMD_CREATECAB:
lstrcpy( achBuf, STR_CREATECAB );
break;
}
WritePrivateProfileString( SEC_OPTIONS, KEY_PACKPURPOSE, achBuf, g_CDF.achFilename );
WritePrivateProfileString( SEC_OPTIONS, KEY_SHOWWIN, _itoa(g_CDF.uShowWindow, achBuf,10), g_CDF.achFilename );
WritePrivateProfileString( SEC_OPTIONS, KEY_NOEXTRACTUI, _itoa( (g_CDF.uExtractOpt&EXTRACTOPT_UI_NO)?1:0, achBuf, 10), g_CDF.achFilename );
WritePrivateProfileString( SEC_OPTIONS, KEY_USELFN, _itoa( (g_CDF.uExtractOpt&EXTRACTOPT_LFN_YES)?1:0, achBuf, 10), g_CDF.achFilename );
WritePrivateProfileString( SEC_OPTIONS, KEY_NESTCOMPRESSED, _itoa( (g_CDF.uExtractOpt&EXTRACTOPT_COMPRESSED)?1:0, achBuf, 10), g_CDF.achFilename );
WritePrivateProfileString( SEC_OPTIONS, KEY_CABFIXEDSIZE,
_itoa( (g_CDF.uExtractOpt & CAB_FIXEDSIZE)?1:0, achBuf, 10), g_CDF.achFilename );
if ( g_CDF.uExtractOpt & CAB_RESVSP2K )
i = 1;
else if ( g_CDF.uExtractOpt & CAB_RESVSP4K )
i = 2;
else if ( g_CDF.uExtractOpt & CAB_RESVSP6K )
i = 3;
else
i = 0;
lstrcpy( achBuf, pResvSizes[i] );
WritePrivateProfileString( SEC_OPTIONS, KEY_CABRESVCODESIGN, achBuf, g_CDF.achFilename );
// get reboot settings
achBuf[0] = 0;
if ( g_CDF.dwReboot & REBOOT_YES )
{
if ( g_CDF.dwReboot & REBOOT_ALWAYS )
lstrcpy( achBuf, "A" );
else
lstrcpy( achBuf, "I" );
if ( g_CDF.dwReboot & REBOOT_SILENT )
lstrcat( achBuf, "S" );
}
else
lstrcpy( achBuf, "N" );
WritePrivateProfileString( SEC_OPTIONS, KEY_REBOOTMODE, achBuf, g_CDF.achFilename );
arraySize = ARRAY_SIZE( CDFStrInfo );
// Start writting out the string value
for ( i = 0; i < arraySize; i++ )
{
if ( CDFStrInfo[i].lpFlag )
{
if ( *CDFStrInfo[i].lpFlag )
{
MyWritePrivateProfileString( CDFStrInfo[i].lpSec, CDFStrInfo[i].lpKey, CDFStrInfo[i].lpBuf, CDFStrInfo[i].uSize, FALSE );
}
else
MyWritePrivateProfileString( CDFStrInfo[i].lpSec, CDFStrInfo[i].lpKey, (LPSTR)CDFStrInfo[i].lpDef, CDFStrInfo[i].uSize, FALSE );
}
else
MyWritePrivateProfileString( CDFStrInfo[i].lpSec, CDFStrInfo[i].lpKey, CDFStrInfo[i].lpBuf, CDFStrInfo[i].uSize, FALSE );
}
if ( g_CDF.uExtractOpt & CAB_FIXEDSIZE )
{
MyWritePrivateProfileString( SEC_OPTIONS, KEY_LAYOUTINF, g_CDF.achINF, sizeof(g_CDF.achINF), FALSE );
MyWritePrivateProfileString( SEC_OPTIONS, KEY_CABLABEL, g_CDF.szCabLabel, sizeof(g_CDF.szCabLabel), FALSE );
}
// read in the exist one first
GetVersionInfoFromFile();
// cleanup VerInfo left over if needed
if ( GetPrivateProfileString( SEC_OPTIONS, KEY_VERSIONINFO, "", achBuf, sizeof(achBuf), g_CDF.achFilename ) )
{
if ( lstrcmpi( achBuf, g_CDF.achVerInfo) )
{
if ( !CleanupSection( achBuf, FALSE) )
{
return FALSE;
}
}
}
// write Version information overwite section
if ( g_CDF.achVerInfo[0] )
{
WritePrivateProfileString( SEC_OPTIONS, KEY_VERSIONINFO, g_CDF.achVerInfo, g_CDF.achFilename );
if ( !MergeSection( g_CDF.achVerInfo, g_CDF.achVerInfo ) )
return FALSE;
}
// if current SourceFiles has different name than the main CDF defined, clean the old one first
if ( GetPrivateProfileString( SEC_OPTIONS, KEY_FILELIST, "", achBuf, sizeof(achBuf), g_CDF.achFilename ) )
{
if ( !CleanSourceFiles( achBuf ) )
return FALSE;
}
WritePrivateProfileString( SEC_OPTIONS, KEY_FILELIST, g_CDF.achSourceFile, g_CDF.achFilename );
// write the file list section
return ( OutFileListSection() );
}
//***************************************************************************
//* *
//* NAME: ReadCDF *
//* *
//* SYNOPSIS: Read a CABPack Directive File into the Global CDF struct. *
//* *
//* REQUIRES: hDlg: dialog window *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
BOOL ReadCDF( HWND hDlg )
{
CHAR achBuf[2 * MAX_PATH];
LPSTR lpSave1=NULL, lpSave2=NULL;
LPSTR szFileList=NULL, szFileListKeys=NULL;
ULONG ulFileSize, uData;
PMYITEM pMyItem;
CHAR szPath[MAX_PATH];
int i, arraySize;
LONG lRet;
BOOL bRetVal = FALSE;
UINT uErrid = 0;
achBuf[0] = '\0';
szPath[0] = '\0';
if ( !FileExists(g_CDF.achFilename) )
{
uErrid = IDS_ERR_OPEN_CDF;
goto EXIT;
}
// Check to make sure it's a CDF file.
if ( MyGetPrivateProfileString( SEC_VERSION, KEY_CLASS, "", achBuf, sizeof(achBuf), g_szOverideSec ) < 0 )
goto EXIT;
if ( lstrcmpi( achBuf, "IEXPRESS" ) != 0 )
{
uErrid = IDS_ERR_CLASSNAME;
goto EXIT;
}
if ( !AllocTargetVerInfo( g_CDF.achFilename ) )
goto EXIT;
// get string section name from overideCDF if there
if ( g_szOverideCDF[0] && g_szOverideSec[0] )
{
if ( !AllocTargetVerInfo( g_szOverideCDF ) )
goto EXIT;
GetPrivateProfileString( g_szOverideSec, KEY_STRINGS, SEC_STRINGS, g_CDF.achStrings, sizeof(g_CDF.achStrings), g_szOverideCDF );
}
// Read the config info INT vaules.
// If old ExtractOnly key exists, read it for compatiable purpose.
// IExpress will never create both OLD and NEW keys.
// If Old ExtractOnly key is not set to 1 or does not exist, read the New key.
//
if ( MyGetPrivateProfileInt( SEC_OPTIONS, KEY_EXTRACTONLY, 0, g_szOverideSec ) )
{
g_CDF.uPackPurpose = IDC_CMD_EXTRACT;
}
else
{
// if the old key is not set, check the new key
//
MyGetPrivateProfileString( SEC_OPTIONS, KEY_PACKPURPOSE, STR_INSTALLAPP, achBuf, sizeof(achBuf), g_szOverideSec );
if ( !lstrcmpi( achBuf, STR_INSTALLAPP ) )
{
g_CDF.uPackPurpose = IDC_CMD_RUNCMD;
}
else if ( !lstrcmpi( achBuf, STR_EXTRACTONLY) )
{
g_CDF.uPackPurpose = IDC_CMD_EXTRACT;
}
else
g_CDF.uPackPurpose = IDC_CMD_CREATECAB;
}
g_CDF.uShowWindow = MyGetPrivateProfileInt( SEC_OPTIONS, KEY_SHOWWIN, 0, g_szOverideSec );
g_CDF.uExtractOpt = 0;
arraySize = ARRAY_SIZE( CDFOptInfo );
// Start writting out the string value
for ( i = 0; i < arraySize; i++ )
{
uData = MyGetPrivateProfileInt( SEC_OPTIONS, CDFOptInfo[i].lpKey, 0, g_szOverideSec );
if ( uData )
{
g_CDF.uExtractOpt |= CDFOptInfo[i].dwOpt;
}
}
// get OneInstance check info
MyGetPrivateProfileString( SEC_OPTIONS, KEY_INSTANCECHK, "", achBuf, sizeof(achBuf), g_szOverideSec );
switch ( toupper( achBuf[0]) )
{
case 'P':
g_CDF.uExtractOpt |= EXTRACTOPT_INSTCHKPROMPT;
break;
case 'B':
g_CDF.uExtractOpt |= EXTRACTOPT_INSTCHKBLOCK;
break;
default:
break;
}
if ( (g_CDF.uExtractOpt & EXTRACTOPT_INSTCHKPROMPT) ||
(g_CDF.uExtractOpt & EXTRACTOPT_INSTCHKBLOCK) )
{
if ( !(lpSave1 = strchr( achBuf, '"' )) )
{
uErrid = IDS_ERR_COOKIE;
goto EXIT;
}
lpSave2 = strchr( ++lpSave1, '"' );
if ( lpSave2 )
{
*lpSave2 = '\0';
g_CDF.lpszCookie = (LPSTR)LocalAlloc( LPTR, lstrlen(lpSave1)+1 );
if ( g_CDF.lpszCookie )
{
lstrcpy( g_CDF.lpszCookie, lpSave1 );
}
else
{
uErrid = IDS_ERR_NO_MEMORY;
goto EXIT;
}
}
else
{
uErrid = IDS_ERR_COOKIE;
goto EXIT;
}
}
uData = MyGetPrivateProfileInt( SEC_OPTIONS, KEY_CABFIXEDSIZE, 0, g_szOverideSec );
if ( uData )
{
g_CDF.uExtractOpt |= CAB_FIXEDSIZE;
}
MyGetPrivateProfileString( SEC_OPTIONS, KEY_LAYOUTINF, "", g_CDF.achINF, sizeof(g_CDF.achINF), g_szOverideSec );
MyGetPrivateProfileString( SEC_OPTIONS, KEY_CABLABEL, CAB_DEFSETUPMEDIA, g_CDF.szCabLabel, sizeof(g_CDF.szCabLabel), g_szOverideSec );
MyGetPrivateProfileString( SEC_OPTIONS, KEY_CABRESVCODESIGN, CAB_6K, achBuf, sizeof(achBuf), g_szOverideSec );
if ( !lstrcmpi(achBuf, pResvSizes[1]) )
g_CDF.uExtractOpt |= CAB_RESVSP2K;
else if ( !lstrcmpi(achBuf, pResvSizes[2]) )
g_CDF.uExtractOpt |= CAB_RESVSP4K;
else if ( !lstrcmpi(achBuf, pResvSizes[3]) )
g_CDF.uExtractOpt |= CAB_RESVSP6K;
MyGetPrivateProfileString( SEC_OPTIONS, KEY_COMPRESSTYPE, "", achBuf, sizeof(achBuf), g_szOverideSec );
if ( achBuf[0] == 0 )
{
// Get the compression type: For MS Internal, "QUANTUM=value" can be set.
g_CDF.uCompressionLevel = MyGetPrivateProfileInt( SEC_OPTIONS, KEY_QUANTUM, 999, g_szOverideSec );
if ( g_CDF.uCompressionLevel == 999 )
{
g_CDF.szCompressionType = achMSZIP;
g_CDF.uCompressionLevel = 7;
}
else
{
g_CDF.szCompressionType = achQUANTUM;
}
}
else
{
if ( !lstrcmpi( achBuf, achLZX ) )
{
g_CDF.szCompressionType = achLZX;
}
else if ( !lstrcmpi( achBuf, achQUANTUM ) )
{
g_CDF.szCompressionType = achQUANTUM;
}
else if ( !lstrcmpi( achBuf, achNONE ) )
{
g_CDF.szCompressionType = achNONE;
}
else
{
g_CDF.szCompressionType = achMSZIP;
}
g_CDF.uCompressionLevel = 7;
}
// get reboot info
g_CDF.dwReboot = 0;
i = 0;
MyGetPrivateProfileString( SEC_OPTIONS, KEY_REBOOTMODE, "I", achBuf, sizeof(achBuf), g_szOverideSec );
while ( achBuf[i] != 0 )
{
switch ( toupper(achBuf[i++]) )
{
case 'A':
g_CDF.dwReboot |= REBOOT_ALWAYS;
g_CDF.dwReboot |= REBOOT_YES;
break;
case 'S':
g_CDF.dwReboot |= REBOOT_SILENT;
break;
case 'N':
g_CDF.dwReboot &= ~(REBOOT_YES);
break;
case 'I':
g_CDF.dwReboot &= ~(REBOOT_ALWAYS);
g_CDF.dwReboot |= REBOOT_YES;
break;
default:
break;
}
}
// get package install space
g_CDF.cbPackInstSpace = MyGetPrivateProfileInt( SEC_OPTIONS, KEY_PACKINSTSPACE, 0, g_szOverideSec );
// use CDFStrInfo table to do read for a list of key strings
arraySize = ARRAY_SIZE( CDFStrInfo );
for ( i=0; i<arraySize; i++ )
{
if ( MyGetPrivateProfileString( CDFStrInfo[i].lpSec, CDFStrInfo[i].lpKey,
CDFStrInfo[i].lpDef, CDFStrInfo[i].lpBuf,
CDFStrInfo[i].uSize, CDFStrInfo[i].lpOverideSec ) < 0 )
goto EXIT;
if ( CDFStrInfo[i].lpFlag )
{
if ( CDFStrInfo[i].lpBuf[0] )
*(CDFStrInfo[i].lpFlag) = TRUE;
else
*(CDFStrInfo[i].lpFlag) = FALSE;
}
}
// generate cab name properly!
if ( (g_CDF.uPackPurpose == IDC_CMD_CREATECAB ) &&
!MakeCabName( hDlg, g_CDF.achTarget, g_CDF.achCABPath ) )
goto EXIT;
// Read the file list, adding it to our Item list as we go along.
if ( MyGetPrivateProfileString( SEC_OPTIONS, KEY_FILELIST, "", g_CDF.achSourceFile, sizeof(g_CDF.achSourceFile), g_szOverideSec ) <= 0 )
{
uErrid = IDS_ERR_NOSOURCEFILE;
goto EXIT;
}
ulFileSize = __max( FileSize( g_CDF.achFilename ), FileSize( g_szOverideCDF ) );
//BUGBUG: be smart about buf size to allocate
szFileList = (LPSTR) LocalAlloc( LPTR, ulFileSize );
szFileListKeys = (LPSTR) LocalAlloc( LPTR, ulFileSize );
if ( !szFileList || !szFileListKeys )
{
uErrid = IDS_ERR_NO_MEMORY;
goto EXIT;
}
lpSave1 = szFileList;
lpSave2 = szFileListKeys;
MyGetPrivateProfileString( g_CDF.achSourceFile, NULL, "", szFileListKeys, ulFileSize/2, g_CDF.achSourceFile );
while ( *szFileListKeys )
{
lstrcpy( achBuf, szFileListKeys );
szFileListKeys += lstrlen(szFileListKeys);
szFileListKeys++; // jump over the single '\0'
MyGetPrivateProfileString( g_CDF.achSourceFile, achBuf, "", szPath, sizeof(szPath), g_CDF.achSourceFile );
lRet = MyGetPrivateProfileSection( achBuf, szFileList, ulFileSize, TRUE );
if ( lRet == 0 )
{
// the current CDF format is not match with OS version
uErrid = IDS_ERR_CDFFORMAT;
LocalFree( lpSave1 );
LocalFree( lpSave2 );
goto EXIT;
}
else if ( lRet < 0 )
{
uErrid = IDS_ERR_INVALID_CDF;
LocalFree( lpSave1 );
LocalFree( lpSave2 );
goto EXIT;
}
// make sure there is a '\' at the end of path
AddPath( szPath, "" );
while ( *szFileList )
{
FormStrWithoutPlaceHolders( achBuf, szFileList, sizeof(achBuf) );
pMyItem = AddItem( achBuf, szPath );
szFileList += lstrlen( szFileList );
szFileList++; // jump over the single '\0'
}
szFileList = lpSave1;
}
LocalFree( lpSave1 );
LocalFree( lpSave2 );
// get the target version check info
//
if ( g_CDF.pVerInfo )
{
lRet = MyGetPrivateProfileString( SEC_OPTIONS, KEY_NTVERCHECK, "", achBuf, sizeof(achBuf), g_szOverideSec );
if ( (lRet<0) || !ParseTargetVerCheck( achBuf, &(g_CDF.pVerInfo->ntVerCheck), szPath, FALSE ) )
{
goto EXIT;
}
SetAuthorStr( szPath, &(g_CDF.pVerInfo->ntVerCheck.dwstrOffs) );
lRet = MyGetPrivateProfileString( SEC_OPTIONS, KEY_WIN9XVERCHECK, "", achBuf, sizeof(achBuf), g_szOverideSec );
if ( (lRet < 0) || !ParseTargetVerCheck( achBuf, &(g_CDF.pVerInfo->win9xVerCheck), szPath, FALSE ) )
{
goto EXIT;
}
SetAuthorStr( szPath, &(g_CDF.pVerInfo->win9xVerCheck.dwstrOffs) );
lRet = MyGetPrivateProfileString( SEC_OPTIONS, KEY_SYSFILE, "", achBuf, sizeof(achBuf), g_szOverideSec );
if ( lRet < 0 )
goto EXIT;
if ( achBuf[0] && g_CDF.pVerInfo->dwNumFiles )
{
PVERCHECK pVerChk = NULL;
pVerChk = (PVERCHECK) LocalAlloc( LPTR, g_CDF.pVerInfo->dwNumFiles * (sizeof(VERCHECK)) );
if ( !pVerChk )
{
uErrid = IDS_ERR_NO_MEMORY;
goto EXIT;
}
if ( achBuf[0] == '@' )
{
char szLine[MAX_PATH];
PVERCHECK pVerTmp;
i = 0;
pVerTmp = pVerChk;
MyGetPrivateProfileString( &achBuf[1], NULL, "", szPath, sizeof(szPath), g_szOverideSec );
while ( szPath[i] )
{
MyGetPrivateProfileString( &achBuf[1], &szPath[i], "", szLine, sizeof(szLine), g_szOverideSec );
if ( !ParseTargetFiles( szLine, pVerTmp ) )
{
LocalFree( pVerChk );
uErrid = IDS_ERR_VCHKFILE;
goto EXIT;
}
pVerTmp++;
i += lstrlen( &szPath[i] ) + 1;
}
}
else if ( !ParseTargetFiles( achBuf, pVerChk ) )
{
LocalFree( pVerChk );
uErrid = IDS_ERR_VCHKFILE;
goto EXIT;
}
// up to now all the strings have been processed. Put the File data into the struct
//
memcpy( (g_CDF.pVerInfo->szBuf + g_CDF.pVerInfo->dwFileOffs), pVerChk, g_CDF.pVerInfo->dwNumFiles * sizeof(VERCHECK) );
LocalFree( pVerChk );
}
g_CDF.pVerInfo->dwSize = sizeof(TARGETVERINFO) + g_CDF.pVerInfo->dwFileOffs + sizeof(VERCHECK)*g_CDF.pVerInfo->dwNumFiles;
}
// make sure the target file path exist
MakeDirectory( NULL, g_CDF.achTarget, FALSE );
// if it is LFN command from FileList, make it consistant with filename in the CAB
//
MyProcessLFNCmd( g_CDF.achOrigiInstallCmd, g_CDF.achInstallCmd );
MyProcessLFNCmd( g_CDF.achOrigiPostInstCmd, g_CDF.achPostInstCmd );
MyProcessLFNCmd( g_CDF.szOrigiAdmQCmd, g_CDF.szAdmQCmd );
MyProcessLFNCmd( g_CDF.szOrigiUsrQCmd, g_CDF.szUsrQCmd );
// after file-list has been read in
// set EXTRACTOPT_ADVDLL if needed, shorten the command name if needed
// if the .INF file is not from the file list, return FALSE
//
if ( (g_CDF.uPackPurpose == IDC_CMD_RUNCMD) &&
( !CheckAdvBit( g_CDF.achOrigiInstallCmd ) ||
!CheckAdvBit( g_CDF.achOrigiPostInstCmd ) ||
!CheckAdvBit( g_CDF.szOrigiAdmQCmd ) ||
!CheckAdvBit( g_CDF.szOrigiUsrQCmd ) ) )
{
goto EXIT;
}
// successful path
bRetVal = TRUE;
EXIT:
if ( uErrid )
ErrorMsg( hDlg, uErrid );
return bRetVal;
}
#define MAXDISK_SIZE "1.44M"
#define CDROM_SIZE "CDROM"
// define
//***************************************************************************
//* *
//* NAME: WriteDDF *
//* *
//* SYNOPSIS: Writes out a Diamond Directive File. *
//* *
//* REQUIRES: hDlg: dialog window *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
BOOL WriteDDF( HWND hDlg )
{
HANDLE hFile;
DWORD dwAttr;
DWORD dwBytes;
PMYITEM pMyItem;
CHAR achHeader[256];
LPSTR szTempLine;
BOOL fReturn = TRUE;
CHAR achShortPath[MAX_PATH];
int i, arraySize;
LPSTR lpCurrLine;
LPSTR lpFName;
// These are the lines that will be written out.
CHAR achLine1[] = ".Set CabinetNameTemplate=%s\r\n";
CHAR achLine2[] = ".Set CompressionType=%s\r\n";
CHAR achLine3[] = ".Set CompressionLevel=%u\r\n";
CHAR achLine4[] = ".Set InfFileName=%s\r\n";
CHAR achLine5[] = ".Set RptFileName=%s\r\n";
CHAR achLine6[] = ".Set MaxDiskSize=%s\r\n";
CHAR achLine7[] = ".Set ReservePerCabinetSize=%s\r\n";
CHAR achLine8[] = ".Set InfCabinetLineFormat=""*cab#*=""%s"",""*cabfile*"",0""\r\n";
CHAR achLine9[] = ".Set Compress=%s\r\n";
CHAR achLine10[] = ".Set CompressionMemory=%d\r\n";
PSTR pszDDFLine[] = { // 11 lines no param needed
".Set DiskDirectoryTemplate=\r\n",
".Set Cabinet=ON\r\n",
".Set MaxCabinetSize=999999999\r\n",
".Set InfDiskHeader=\r\n",
".Set InfDiskLineFormat=\r\n",
".Set InfCabinetHeader=""[SourceDisksNames]""\r\n",
".Set InfFileHeader=""""\r\n",
".Set InfFileHeader1=""[SourceDisksFiles]""\r\n",
".Set InfFileLineFormat=""*file*=*cab#*,,*size*,*csum*""\r\n",
NULL,
};
hFile = CreateFile( g_CDF.achDDF, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL );
if ( hFile == INVALID_HANDLE_VALUE ) {
ErrorMsg( hDlg, IDS_ERR_OPEN_DDF );
return FALSE;
}
// allocate a working buffer once which is big enough for every line
//
szTempLine = (LPSTR) LocalAlloc( LPTR, MAX_STRING );
if ( ! szTempLine ) {
ErrorMsg( hDlg, IDS_ERR_NO_MEMORY );
CloseHandle( hFile );
return FALSE;
}
LoadSz( IDS_DDF_HEADER, achHeader, sizeof(achHeader) );
WriteFile( hFile, achHeader, lstrlen( achHeader ), &dwBytes, NULL );
wsprintf( szTempLine, achLine1, g_CDF.achCABPath );
WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
wsprintf( szTempLine, achLine2, g_CDF.szCompressionType );
WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
wsprintf( szTempLine, achLine3, g_CDF.uCompressionLevel );
WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
wsprintf( szTempLine, achLine4, g_CDF.achINF );
WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
wsprintf( szTempLine, achLine5, g_CDF.achRPT );
WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
if ( g_CDF.uExtractOpt & CAB_FIXEDSIZE )
lpCurrLine = MAXDISK_SIZE;
else
lpCurrLine = CDROM_SIZE;
wsprintf( szTempLine, achLine6, lpCurrLine );
WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
if ( g_CDF.uExtractOpt & CAB_RESVSP2K )
i = 1;
else if ( g_CDF.uExtractOpt & CAB_RESVSP4K )
i = 2;
else if ( g_CDF.uExtractOpt & CAB_RESVSP6K )
i = 3;
else
i = 0;
wsprintf( szTempLine, achLine7, pResvSizes[i] );
WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
wsprintf( szTempLine, achLine8, g_CDF.szCabLabel );
WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
MyGetPrivateProfileString( SEC_OPTIONS, KEY_COMPRESS, "on", achShortPath, sizeof(achShortPath), g_szOverideSec );
wsprintf( szTempLine, achLine9, achShortPath );
WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
i = MyGetPrivateProfileInt( SEC_OPTIONS, KEY_COMPRESSMEMORY, 21, g_szOverideSec );
if ( i <= 0 )
i = 21;
wsprintf( szTempLine, achLine10, i );
WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
i = 0;
while ( pszDDFLine[i] )
{
WriteFile( hFile, pszDDFLine[i], lstrlen( pszDDFLine[i] ), &dwBytes, NULL );
i++;
}
pMyItem = GetFirstItem();
while ( fReturn && ! LastItem( pMyItem ) ) {
lstrcpy( szTempLine, GetItemSz( pMyItem, 1 ) );
lstrcat( szTempLine, GetItemSz( pMyItem, 0 ) );
dwAttr = GetFileAttributes( szTempLine );
if ( ( dwAttr == -1 ) || ( dwAttr & FILE_ATTRIBUTE_DIRECTORY ) ) {
ErrorMsg1Param( hDlg, IDS_ERR_FILE_NOT_FOUND2, szTempLine );
LocalFree( szTempLine );
CloseHandle( hFile );
return FALSE;
}
if ( g_CDF.uExtractOpt & EXTRACTOPT_LFN_YES )
{
lstrcpy( achShortPath, "\"" );
lstrcat( achShortPath, szTempLine );
lstrcat( achShortPath, "\"" );
}
else
{
if ( ! GetShortPathName( szTempLine, achShortPath,
sizeof(achShortPath) ) )
{
ErrorMsg( hDlg, IDS_ERR_SHORT_PATH );
LocalFree( szTempLine );
CloseHandle( hFile );
return FALSE;
}
}
WriteFile( hFile, achShortPath, lstrlen(achShortPath), &dwBytes, NULL );
fReturn = WriteFile( hFile, "\r\n", lstrlen("\r\n"), &dwBytes, NULL );
pMyItem = GetNextItem( pMyItem );
}
if ( fReturn && g_CDF.uExtractOpt & EXTRACTOPT_ADVDLL )
{
SYSTEM_INFO SystemInfo;
int ix86Processor;
GetSystemInfo( &SystemInfo );
ix86Processor = MyGetPrivateProfileInt( SEC_OPTIONS, KEY_CROSSPROCESSOR, -1, g_szOverideSec );
if ( (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) &&
(ix86Processor != 0) ||
(SystemInfo.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL) &&
(ix86Processor == 1) )
{
arraySize = ARRAY_SIZE( AdvDlls );
}
else
{
arraySize = 1;
}
// add 3 advanced DLLS for handling OCX regiester or CustomDestination
for ( i = 0; (i<arraySize) && fReturn; i++ )
{
if ( !IsDuplicate( NULL, 0, AdvDlls[i], FALSE) )
{
if ( !GetFileFromModulePath( AdvDlls[i], achShortPath, sizeof(achShortPath) ) )
{
ErrorMsg1Param( hDlg, IDS_ERR_FILE_NOT_FOUND, achShortPath );
LocalFree( szTempLine );
CloseHandle( hFile );
return FALSE;
}
lstrcpy( szTempLine, "\"" );
lstrcat( szTempLine, achShortPath );
lstrcat( szTempLine, "\"" );
WriteFile( hFile, szTempLine, lstrlen(szTempLine), &dwBytes, NULL );
fReturn = WriteFile( hFile, "\r\n", strlen("\r\n"), &dwBytes, NULL );
}
}
}
LocalFree( szTempLine );
CloseHandle( hFile );
if ( fReturn == FALSE ) {
ErrorMsg( hDlg, IDS_ERR_WRITE_DDF );
return FALSE;
} else {
return TRUE;
}
}
//***************************************************************************
//* *
//* NAME: MasskePackage *
//* *
//* SYNOPSIS: Makes the full package (CAB and EXE). *
//* *
//* REQUIRES: hDlg: Handle to the dialog *
//* *
//* RETURNS: BOOL: *
//* *
//***************************************************************************
BOOL MakePackage( HWND hDlg )
{
CHAR achDrive[_MAX_DRIVE];
CHAR achDir[_MAX_DIR];
CHAR achStatus[MAX_STRING];
CHAR szExt[6];
BOOL fReturn = TRUE;
PSTR pTmp;
// Build the paths to the files, using the target path as a
// template. We create the DDF, CAB and INF file in the
// same directory as the target file.
_splitpath( g_CDF.achTarget, achDrive, achDir, g_CDF.achTargetBase, szExt);
lstrcpy( g_CDF.achTargetPath, achDrive );
lstrcat( g_CDF.achTargetPath, achDir );
lstrcpy( g_CDF.achDDF, g_CDF.achTargetPath );
wsprintf( achStatus, CABPACK_TMPFILE, g_CDF.achTargetBase, EXT_DDF );
AddPath( g_CDF.achDDF, achStatus );
if ( g_CDF.achINF[0] == 0 )
{
lstrcpy( g_CDF.achINF, g_CDF.achTargetPath );
wsprintf( achStatus, CABPACK_INFFILE, g_CDF.achTargetBase );
AddPath( g_CDF.achINF, achStatus );
}
lstrcpy( g_CDF.achRPT, g_CDF.achTargetPath );
wsprintf( achStatus, CABPACK_TMPFILE, g_CDF.achTargetBase, EXT_RPT );
AddPath( g_CDF.achRPT, achStatus );
if ( g_CDF.uPackPurpose != IDC_CMD_CREATECAB )
{
wsprintf( achStatus, CABPACK_TMPFILE, g_CDF.achTargetBase, EXT_CAB );
lstrcpy( g_CDF.achCABPath, g_CDF.achTargetPath );
AddPath( g_CDF.achCABPath, achStatus );
g_CDF.szCompressionType = achLZX;
g_CDF.uCompressionLevel = 7;
}
if ( g_CDF.fSave ) {
if ( ! WriteCDF( hDlg ) ) {
LoadSz( IDS_STATUS_ERROR_CDF, achStatus, sizeof(achStatus) );
Status( hDlg, IDC_MEDIT_STATUS, achStatus );
fReturn = FALSE;
goto done;
}
}
if ( ! MakeCAB( hDlg ) ) {
LoadSz( IDS_STATUS_ERROR_CAB, achStatus, sizeof(achStatus) );
Status( hDlg, IDC_MEDIT_STATUS, achStatus );
fReturn = FALSE;
goto done;
}
// if use choose to create CAB file only, MakeEXE() is not needed
//
if ( g_CDF.uPackPurpose != IDC_CMD_CREATECAB )
{
if ( ! MakeEXE( hDlg ) ) {
LoadSz( IDS_STATUS_ERROR_EXE, achStatus, sizeof(achStatus) );
Status( hDlg, IDC_MEDIT_STATUS, achStatus );
fReturn = FALSE;
goto done;
}
if ( MyGetPrivateProfileInt( SEC_OPTIONS, KEY_KEEPCABINET, 0, g_szOverideSec )
== 0 )
{
DeleteFile( g_CDF.achCABPath );
}
}
LoadSz( IDS_STATUS_DONE, achStatus, sizeof(achStatus) );
Status( hDlg, IDC_MEDIT_STATUS, achStatus );
done:
// if failure happen, clean the filewriteout flag to prepare for next CDF out
if ( !fReturn )
CleanFileListWriteFlag();
return fReturn;
}
//***************************************************************************
//* *
//* NAME: MakeCAB *
//* *
//* SYNOPSIS: Makes the cabinet file if it is out of date. *
//* *
//* REQUIRES: hDlg: Handle to the dialog *
//* *
//* RETURNS: BOOL: *
//* *
//***************************************************************************
BOOL MakeCAB( HWND hDlg )
{
CHAR achMessage[512]; // Used in FormatMessage()
DWORD dwError; // Used in GetLastError()
LPSTR szCommand;
HANDLE hFile;
LPSTR szTempFile;
ULONG ulFileSize;
LPSTR szFileContents;
DWORD dwBytes;
CHAR achDiamondExe[MAX_PATH];
CHAR achDiamondPath[MAX_PATH];
CHAR achStatus[MAX_STRING];
BOOL fFilesModified = FALSE;
DWORD dwExitCode;
STARTUPINFO sti;
PROCESS_INFORMATION pi; // Setup Process Launch
WIN32_FIND_DATA FindFileData;
DWORD dwCreationFlags;
//FindClose( hFile );
LoadSz( IDS_STATUS_MAKE_CAB, achStatus, sizeof(achStatus) );
Status( hDlg, IDC_MEDIT_STATUS, achStatus );
if ( ! WriteDDF( hDlg ) ) {
return FALSE;
}
// Make the CAB file
if ( lstrcmpi( g_CDF.szCompressionType, achQUANTUM ) == 0 ) {
lstrcpy( achDiamondExe, DIAMONDEXE );
} else {
lstrcpy( achDiamondExe, DIANTZEXE );
}
if ( !GetFileFromModulePath( achDiamondExe, achDiamondPath, sizeof(achDiamondPath) ) )
{
ErrorMsg1Param( hDlg, IDS_ERR_FILE_NOT_FOUND, achDiamondPath );
return FALSE;
}
// The +5 is to handle the " /f " in the wsprintf format string
// and for the terminating null char.
//
szCommand = (LPSTR) LocalAlloc( LPTR, lstrlen(achDiamondPath)
+ lstrlen(g_CDF.achDDF)
+ 10 );
if ( ! szCommand ) {
ErrorMsg( hDlg, IDS_ERR_NO_MEMORY );
return FALSE;
}
wsprintf( szCommand, "%s /f \"%s\"", achDiamondPath, g_CDF.achDDF );
memset( &sti, 0, sizeof(sti) );
sti.cb = sizeof(STARTUPINFO);
if (g_wRunDiamondMinimized) {
sti.dwFlags = STARTF_USESHOWWINDOW;
sti.wShowWindow = SW_MINIMIZE;
}
else if (g_wQuietMode || g_wSilentMode) {
sti.dwFlags = STARTF_USESHOWWINDOW;
sti.wShowWindow = SW_HIDE;
}
if (!g_wQuietMode)
dwCreationFlags = 0;
else
dwCreationFlags = CREATE_NO_WINDOW;
if ( CreateProcess( NULL, szCommand, NULL, NULL, FALSE,
dwCreationFlags, NULL, NULL, &sti, &pi ) )
{
CloseHandle( pi.hThread );
MsgWaitForMultipleObjectsLoop( pi.hProcess );
GetExitCodeProcess( pi.hProcess, &dwExitCode );
CloseHandle( pi.hProcess );
} else {
dwError = GetLastError();
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0,
achMessage, sizeof(achMessage), NULL );
ErrorMsg2Param( hDlg, IDS_ERR_START_DIAMOND, szCommand,
achMessage );
}
LocalFree( szCommand );
Status( hDlg, IDC_MEDIT_STATUS, "---\r\n" );
hFile = FindFirstFile( g_CDF.achRPT, &FindFileData );
ulFileSize = (FindFileData.nFileSizeHigh * MAXDWORD)
+ FindFileData.nFileSizeLow;
FindClose( hFile );
hFile = CreateFile( g_CDF.achRPT, GENERIC_READ, 0, NULL,
OPEN_EXISTING, 0, NULL );
if ( hFile == INVALID_HANDLE_VALUE ) {
ErrorMsg1Param( hDlg, IDS_ERR_OPEN_RPT, g_CDF.achRPT );
return FALSE;
}
szFileContents = (LPSTR) LocalAlloc( LPTR, ulFileSize + 1 );
if ( ! szFileContents ) {
ErrorMsg( hDlg, IDS_ERR_NO_MEMORY );
return FALSE;
}
if ( ! ReadFile( hFile, szFileContents, ulFileSize,
&dwBytes, NULL ) ) {
ErrorMsg1Param( hDlg, IDS_ERR_READ_RPT, g_CDF.achRPT );
return FALSE;
}
CloseHandle( hFile );
Status( hDlg, IDC_MEDIT_STATUS, szFileContents );
LocalFree( szFileContents );
Status( hDlg, IDC_MEDIT_STATUS, "---\r\n" );
if ( MyGetPrivateProfileInt( SEC_OPTIONS, KEY_KEEPCABINET, 0, g_szOverideSec )
== 0 )
{
DeleteFile( g_CDF.achDDF );
}
if ( !(g_CDF.uExtractOpt & CAB_FIXEDSIZE) )
DeleteFile( g_CDF.achINF );
DeleteFile( g_CDF.achRPT );
return TRUE;
}
//***************************************************************************
//* *
//* NAME: MakeEXE *
//* *
//* SYNOPSIS: Copies WEXTRACT.EXE to the target filename and adds *
//* resources to it. *
//* *
//* REQUIRES: hDlg: Handle to the dialog *
//* *
//* RETURNS: BOOL: *
//* *
//***************************************************************************
BOOL MakeEXE( HWND hDlg )
{
HANDLE hUpdate;
CHAR achMessage[512]; // Used in FormatMessage()
DWORD dwError; // Used in GetLastError()
PMYITEM pMyItem;
HANDLE hFile;
LPSTR szTempFile;
ULONG ulFileSize;
LPSTR szFileContents;
DWORD dwBytes;
CHAR achWExtractPath[MAX_PATH];
CHAR achStatus[MAX_STRING];
WIN32_FIND_DATA FindFileData;
DWORD dwFileSizes[MAX_NUMCLUSTERS+1]; // store the filesize in each cluster sizes.
// the last of dwFileSizes is used to store real
// total file sizes later used for calculate
// progress bar in wextract
DWORD clusterCurrSize;
int i;
UINT idErr = IDS_ERR_UPDATE_RESOURCE;
// get ExtractorStub based on CDF specification. Wextract.exe is default one.
//
LoadSz( IDS_STATUS_MAKE_EXE, achStatus, sizeof(achStatus) );
Status( hDlg, IDC_MEDIT_STATUS, achStatus );
if ( !MyGetPrivateProfileString( SEC_OPTIONS, KEY_STUBEXE, WEXTRACTEXE, achStatus, sizeof(achStatus), g_szOverideSec ) )
{
lstrcpy( achStatus, WEXTRACTEXE );
}
if ( !GetFileFromModulePath(achStatus, achWExtractPath, sizeof(achWExtractPath) ) )
{
ErrorMsg1Param( hDlg, IDS_ERR_FILE_NOT_FOUND, achWExtractPath );
return FALSE;
}
if ( ! CopyFile( achWExtractPath, g_CDF.achTarget, FALSE ) ) {
dwError = GetLastError();
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0,
achMessage, sizeof(achMessage), NULL );
ErrorMsg2Param( hDlg, IDS_ERR_CREATE_TARGET, g_CDF.achTarget,
achMessage );
return FALSE;
}
// make sure the targe file is not read-only file
SetFileAttributes( g_CDF.achTarget, FILE_ATTRIBUTE_NORMAL );
// Initialize the EXE file for resource editing
hUpdate = LocalBeginUpdateResource( g_CDF.achTarget, FALSE );
if ( hUpdate == NULL ) {
ErrorMsg1Param( hDlg, IDS_ERR_INIT_RESOURCE, g_CDF.achTarget );
return FALSE;
}
//*******************************************************************
//* TITLE ***********************************************************
//*******************************************************************
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResTitle, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
g_CDF.achTitle, lstrlen( g_CDF.achTitle ) + 1 ) == FALSE )
{
goto ERR_OUT;
}
//*******************************************************************
//* PROMPT **********************************************************
//*******************************************************************
if ( g_CDF.fPrompt ) {
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResUPrompt, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
g_CDF.achPrompt, lstrlen( g_CDF.achPrompt ) + 1 ) == FALSE )
{
goto ERR_OUT;
}
} else {
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResUPrompt, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
achResNone, lstrlen( achResNone ) + 1 ) == FALSE )
{
goto ERR_OUT;
}
}
//*******************************************************************
//* LICENSE FILE ****************************************************
//*******************************************************************
if ( g_CDF.fLicense ) {
hFile = FindFirstFile( g_CDF.achLicense, &FindFileData );
ulFileSize = (FindFileData.nFileSizeHigh * MAXDWORD)
+ FindFileData.nFileSizeLow;
FindClose( hFile );
hFile = CreateFile( g_CDF.achLicense, GENERIC_READ, 0, NULL,
OPEN_EXISTING, 0, NULL );
if ( hFile == INVALID_HANDLE_VALUE ) {
ErrorMsg1Param( hDlg, IDS_ERR_OPEN_LICENSE, g_CDF.achLicense );
DeleteFile(g_CDF.achTarget);
return FALSE;
}
szFileContents = (LPSTR) LocalAlloc( LPTR, ulFileSize + 1 );
if ( ! szFileContents ) {
ErrorMsg( hDlg, IDS_ERR_NO_MEMORY );
DeleteFile(g_CDF.achTarget);
return FALSE;
}
if ( ! ReadFile( hFile, szFileContents, ulFileSize,
&dwBytes, NULL ) ) {
ErrorMsg1Param( hDlg, IDS_ERR_READ_LICENSE, g_CDF.achLicense );
DeleteFile(g_CDF.achTarget);
return FALSE;
}
CloseHandle( hFile );
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResLicense, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
szFileContents, ulFileSize+1 ) == FALSE )
{
LocalFree( szFileContents );
goto ERR_OUT;
}
LocalFree( szFileContents );
} else {
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResLicense, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
achResNone, lstrlen( achResNone ) + 1 ) == FALSE )
{
goto ERR_OUT;
}
}
//*******************************************************************
//* COMMAND *********************************************************
//*******************************************************************
if ( g_CDF.uPackPurpose != IDC_CMD_EXTRACT )
{
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResRunProgram, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
g_CDF.achInstallCmd, lstrlen(g_CDF.achInstallCmd)+1 ) == FALSE )
{
goto ERR_OUT;
}
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResPostRunCmd, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
g_CDF.achPostInstCmd, lstrlen(g_CDF.achPostInstCmd)+1 ) == FALSE )
{
goto ERR_OUT;
}
//write quiet cmds resource
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResAdminQCmd, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
g_CDF.szAdmQCmd[0]?g_CDF.szAdmQCmd : achResNone,
g_CDF.szAdmQCmd[0]?(lstrlen(g_CDF.szAdmQCmd)+1) : (lstrlen(achResNone)+1) ) == FALSE )
{
goto ERR_OUT;
}
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResUserQCmd, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
g_CDF.szUsrQCmd[0]?g_CDF.szUsrQCmd : achResNone,
g_CDF.szUsrQCmd[0]?(lstrlen(g_CDF.szUsrQCmd)+1) : (lstrlen(achResNone)+1) ) == FALSE )
{
goto ERR_OUT;
}
}
else
{
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResRunProgram, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
achResNone, lstrlen( achResNone ) + 1 ) == FALSE )
{
goto ERR_OUT;
}
}
//*******************************************************************
//* SHOW WINDOW *****************************************************
//*******************************************************************
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResShowWindow, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
&g_CDF.uShowWindow, sizeof(g_CDF.uShowWindow) ) == FALSE )
{
goto ERR_OUT;
}
//*******************************************************************
//* FINISHMSG *******************************************************
//*******************************************************************
if ( g_CDF.fFinishMsg ) {
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResFinishMsg, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
g_CDF.achFinishMsg, lstrlen( g_CDF.achFinishMsg ) + 1 ) == FALSE )
{
goto ERR_OUT;
}
}
else
{
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResFinishMsg, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
achResNone, lstrlen( achResNone ) + 1 ) == FALSE )
{
goto ERR_OUT;
}
}
//*******************************************************************
//* CABINET *********************************************************
//*******************************************************************
hFile = FindFirstFile( g_CDF.achCABPath, &FindFileData );
ulFileSize = (FindFileData.nFileSizeHigh * MAXDWORD)
+ FindFileData.nFileSizeLow;
FindClose( hFile );
hFile = CreateFile( g_CDF.achCABPath, GENERIC_READ, 0, NULL,
OPEN_EXISTING, 0, NULL );
if ( hFile == INVALID_HANDLE_VALUE ) {
ErrorMsg1Param( hDlg, IDS_ERR_OPEN_CAB, g_CDF.achCABPath );
DeleteFile(g_CDF.achTarget);
return FALSE;
}
szFileContents = (LPSTR) LocalAlloc( LPTR, ulFileSize + 1 );
if ( ! szFileContents ) {
idErr = IDS_ERR_NO_MEMORY;
goto ERR_OUT;
}
if ( ! ReadFile( hFile, szFileContents, ulFileSize, &dwBytes, NULL ) ) {
ErrorMsg1Param( hDlg, IDS_ERR_READ_CAB, g_CDF.achCABPath );
DeleteFile(g_CDF.achTarget);
return FALSE;
}
CloseHandle( hFile );
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResCabinet, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
szFileContents, ulFileSize ) == FALSE )
{
LocalFree( szFileContents );
goto ERR_OUT;
}
LocalFree( szFileContents );
//*******************************************************************
//* FILES ***********************************************************
//*******************************************************************
pMyItem = GetFirstItem();
RtlZeroMemory( dwFileSizes, sizeof(dwFileSizes));
while ( ! LastItem( pMyItem ) ) {
szTempFile = (LPSTR) LocalAlloc( LPTR,
lstrlen( GetItemSz( pMyItem, 0 ) )
+ lstrlen( GetItemSz( pMyItem, 1 ) ) + 1 );
if ( ! szTempFile ) {
idErr = IDS_ERR_NO_MEMORY;
goto ERR_OUT;
}
lstrcpy( szTempFile, GetItemSz( pMyItem, 1 ) );
lstrcat( szTempFile, GetItemSz( pMyItem, 0 ) );
hFile = FindFirstFile( szTempFile, &FindFileData );
ulFileSize = (FindFileData.nFileSizeHigh * MAXDWORD)
+ FindFileData.nFileSizeLow;
FindClose( hFile );
LocalFree( szTempFile );
// calculate the file size in different cluster sizes
clusterCurrSize = CLUSTER_BASESIZE;
for ( i = 0; i<MAX_NUMCLUSTERS; i++)
{
dwFileSizes[i] += ((ulFileSize/clusterCurrSize)*clusterCurrSize +
(ulFileSize%clusterCurrSize?clusterCurrSize : 0));
clusterCurrSize = (clusterCurrSize<<1);
}
// this size is not allocated size, just real accumulation
// of the files for later progress bar UI use
dwFileSizes[MAX_NUMCLUSTERS] += ulFileSize;
pMyItem = GetNextItem( pMyItem );
}
for ( i = 0; i<MAX_NUMCLUSTERS; i++)
{
dwFileSizes[i] = (dwFileSizes[i]+1023)/1024; //store in KB
}
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResSize, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
dwFileSizes, sizeof(dwFileSizes) ) == FALSE )
{
goto ERR_OUT;
}
//*******************************************************************
//* REBOOT *******************************************************
//*******************************************************************
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResReboot, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
&g_CDF.dwReboot, sizeof(g_CDF.dwReboot) ) == FALSE )
{
goto ERR_OUT;
}
//*******************************************************************
//* EXTRACTOPT ****************************************************
//*******************************************************************
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResExtractOpt, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
&g_CDF.uExtractOpt, sizeof(g_CDF.uExtractOpt) ) == FALSE )
{
goto ERR_OUT;
}
//*******************************************************************
//* COOKIE ****************************************************
//*******************************************************************
if ( g_CDF.lpszCookie && LocalUpdateResource( hUpdate, RT_RCDATA,
achResOneInstCheck, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
g_CDF.lpszCookie, lstrlen(g_CDF.lpszCookie)+1 ) == FALSE )
{
goto ERR_OUT;
}
//*******************************************************************
//* PACKINSTSPACE **************************************************
//*******************************************************************
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResPackInstSpace, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
&g_CDF.cbPackInstSpace, sizeof(g_CDF.cbPackInstSpace) ) == FALSE )
{
goto ERR_OUT;
}
// Update the version information. The function calls LocaleUpdateResource.
if (!DoVersionInfo(hDlg, achWExtractPath, hUpdate))
{
idErr = IDS_ERR_VERSION_INFO;
goto ERR_OUT;
}
//*******************************************************************
//* TARGETVERSION **************************************************
//*******************************************************************
if ( g_CDF.pVerInfo )
{
if ( LocalUpdateResource( hUpdate, RT_RCDATA,
achResVerCheck, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
g_CDF.pVerInfo, g_CDF.pVerInfo->dwSize ) == FALSE )
{
goto ERR_OUT;
}
}
//*******************************************************************
//* DONE ************************************************************
//*******************************************************************
// Write out modified EXE
if ( LocalEndUpdateResource( hUpdate, FALSE ) == FALSE )
{
idErr = IDS_ERR_CLOSE_RESOURCE;
goto ERR_OUT;
}
return TRUE;
ERR_OUT:
ErrorMsg( hDlg, idErr );
// error occurs, clean up the uncompleted target file
DeleteFile(g_CDF.achTarget);
return FALSE;
}
//***************************************************************************
//* *
//* NAME: MyOpen *
//* *
//* SYNOPSIS: Makes popping up a common file open dialog simpler. *
//* *
//* REQUIRES: Some of the members of the OPENFILENAME structure. See *
//* the docs on OPENFILENAME for more info. *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
BOOL MyOpen( HWND hWnd, UINT idFilter, LPSTR szFilename,
DWORD dwMaxFilename, DWORD dwFlags, INT *nFileOffset,
INT *nExtOffset, PSTR pszDefExt )
{
OPENFILENAME ofn;
BOOL fResult;
LPSTR szFilter;
szFilter = (LPSTR) LocalAlloc( LPTR, MAX_STRING );
if ( ! szFilter ) {
ErrorMsg( hWnd, IDS_ERR_NO_MEMORY );
return FALSE;
}
LoadSz( idFilter, szFilter, MAX_STRING );
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWnd;
ofn.hInstance = NULL;
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFilename;
ofn.nMaxFile = dwMaxFilename;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = g_szInitialDir;
ofn.lpstrTitle = NULL;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY |
OFN_PATHMUSTEXIST | OFN_LONGNAMES |
OFN_NOCHANGEDIR | OFN_EXPLORER |
OFN_NODEREFERENCELINKS | dwFlags;
if ( IsOSNT3X() )
{
ofn.Flags &= ~OFN_ALLOWMULTISELECT;
}
ofn.lpstrDefExt = pszDefExt;
ofn.lCustData = 0;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
fResult = GetOpenFileName( &ofn );
if ( nFileOffset != NULL ) {
*nFileOffset = ofn.nFileOffset;
}
if ( nExtOffset != NULL ) {
*nExtOffset = ofn.nFileExtension;
}
LocalFree( szFilter );
return( fResult );
}
//***************************************************************************
//* *
//* NAME: MySave *
//* *
//* SYNOPSIS: Makes popping up a common file save dialog simpler. *
//* *
//* REQUIRES: Some of the members of the OPENFILENAME structure. See *
//* the docs on OPENFILENAME for more info. *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
BOOL MySave( HWND hWnd, UINT idFilter, LPSTR szFilename,
DWORD dwMaxFilename, DWORD dwFlags, INT *nFileOffset,
INT *nExtOffset, PSTR pszDefExt )
{
OPENFILENAME ofn;
BOOL fResult;
LPSTR szFilter;
szFilter = (LPSTR) LocalAlloc( LPTR, MAX_STRING );
if ( ! szFilter ) {
ErrorMsg( hWnd, IDS_ERR_NO_MEMORY );
return FALSE;
}
LoadSz( idFilter, szFilter, MAX_STRING );
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWnd;
ofn.hInstance = NULL;
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFilename;
ofn.nMaxFile = dwMaxFilename;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
OFN_LONGNAMES | OFN_NOCHANGEDIR | dwFlags;
ofn.lpstrDefExt = pszDefExt;
ofn.lCustData = 0;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
fResult = GetSaveFileName( &ofn );
if ( nFileOffset != NULL ) {
*nFileOffset = ofn.nFileOffset;
}
if ( nExtOffset != NULL ) {
*nExtOffset = ofn.nFileExtension;
}
LocalFree( szFilter );
return( fResult );
}
//***************************************************************************
//* *
//* NAME: Status *
//* *
//* SYNOPSIS: Adds a string to a status list box. *
//* *
//* REQUIRES: hDlg: Handle to the dialog *
//* uID: ID of the list box. *
//* szStatus: Status string to add. *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
VOID Status( HWND hDlg, UINT uID, LPSTR szStatus )
{
ULONG ulLength;
if ( hDlg != NULL ) {
ulLength = (ULONG)SendDlgItemMessage( hDlg, uID, WM_GETTEXTLENGTH, 0, 0 );
SendDlgItemMessage( hDlg, uID, EM_SETSEL, ulLength, ulLength );
SendDlgItemMessage( hDlg, uID, EM_REPLACESEL,
(WPARAM) FALSE, (LPARAM) szStatus );
SendDlgItemMessage( hDlg, uID, EM_SCROLLCARET, 0, 0 );
}
}
//***************************************************************************
//* *
//* NAME: CompareFunc *
//* *
//* SYNOPSIS: Compares two items and returns result. *
//* *
//* REQUIRES: lParam1: Pointer to the first item. *
//* uID: Pointer to the second item. *
//* lParamSort: Type of sorting to do. *
//* *
//* RETURNS: int: -1 if lParam1 goes before lParam2 *
//* 0 if lParam1 equals lParam2 *
//* +1 if lParam1 goes after lParam2 *
//* *
//* NOTES: For some weird reason, sorting the listview causes a *
//* really bad GPF (freezes the entire system). For now it's *
//* not worth the effort to fix it, so sorting is disabled. *
//* *
//***************************************************************************
/*
int CALLBACK CompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
{
PMYITEM pMyItem1 = (PMYITEM) lParam1;
PMYITEM pMyItem2 = (PMYITEM) lParam2;
int nReverse = 1;
UINT uString = 0;
lParamSort = _SORT_DESCENDING | _SORT_FILENAME;
if ( lParamSort & _SORT_ASCENDING ) {
nReverse = -1;
}
if ( lParamSort & _SORT_PATH ) {
uString = 1;
}
return ( nReverse * lstrcmp( GetItemSz( pMyItem1, uString ),
GetItemSz( pMyItem2, uString ) ) );
}
*/
//***************************************************************************
//* *
//* NAME: InitItemList *
//* *
//* SYNOPSIS: Initializes the item list. *
//* *
//* REQUIRES: Nothing -- uses the global g_CDF.pTop *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
VOID InitItemList()
{
g_CDF.pTop = NULL;
g_CDF.cbFileListNum = 0;
}
//***************************************************************************
//* *
//* NAME: DeleteAllItems *
//* *
//* SYNOPSIS: Deletes all the items from our file list. *
//* *
//* REQUIRES: Nothing -- uses the global g_CDF.pTop *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
VOID DeleteAllItems()
{
PMYITEM pMyItem;
PMYITEM pTempItem;
pMyItem = GetFirstItem();
while( ! LastItem( pMyItem ) ) {
pTempItem = pMyItem;
pMyItem = GetNextItem( pMyItem );
FreeItem( &(pTempItem) );
}
InitItemList();
}
//***************************************************************************
//* *
//* NAME: GetFirstItem *
//* *
//* SYNOPSIS: Returns the first PMYITEM in the list *
//* *
//* REQUIRES: Nothing *
//* *
//* RETURNS: PMYITEM The first item *
//* *
//***************************************************************************
PMYITEM GetFirstItem( VOID )
{
return g_CDF.pTop;
}
//***************************************************************************
//* *
//* NAME: GetNextItem *
//* *
//* SYNOPSIS: Given the current item, returns the next item in the list. *
//* *
//* REQUIRES: pMyItem: The current item. *
//* *
//* RETURNS: PMYITEM The next item. *
//* *
//***************************************************************************
PMYITEM GetNextItem( PMYITEM pMyItem )
{
ASSERT( pMyItem != NULL );
return pMyItem->Next;
}
//***************************************************************************
//* *
//* NAME: FreeItem *
//* *
//* SYNOPSIS: Frees the memory associated with an item. *
//* *
//* REQUIRES: *pMyItem Pointer to a pointer to an item *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
VOID FreeItem( PMYITEM *pMyItem )
{
LocalFree( (*pMyItem)->aszCols[0] );
LocalFree( (*pMyItem)->aszCols[1] );
LocalFree( (*pMyItem) );
}
//***************************************************************************
//* *
//* NAME: GetItemSz *
//* *
//* SYNOPSIS: Returns a string associated with an item. You pick the *
//* string by passing the number of the string. *
//* *
//* REQUIRES: pMyItem: The item *
//* nItem: The string to return *
//* *
//* RETURNS: LPSTR: The string *
//* *
//***************************************************************************
LPSTR GetItemSz( PMYITEM pMyItem, UINT nItem )
{
ASSERT( pMyItem != NULL );
ASSERT( nItem <= 1 );
return pMyItem->aszCols[nItem];
}
//***************************************************************************
//* *
//* NAME: LastItem *
//* *
//* SYNOPSIS: Used to end a while loop when we've reached the end of list *
//* *
//* REQUIRES: pMyItem: the current item *
//* *
//* RETURNS: BOOL: TRUE if at end of list, FALSE otherwise *
//* *
//***************************************************************************
BOOL LastItem( PMYITEM pMyItem )
{
return( pMyItem == NULL );
}
//***************************************************************************
//* *
//* NAME: AddItem *
//* *
//* SYNOPSIS: Adds an item to the list. *
//* *
//* REQUIRES: szFilename, szPath - strings to add to structure. *
//* *
//* RETURNS: PMYITEM This function allocates memory which will *
//* be freed later by FreeItem() *
//* *
//***************************************************************************
PMYITEM AddItem( LPCSTR szFilename, LPCSTR szPath )
{
PMYITEM pMyItem;
PMYITEM pTail;
ASSERT( szFilename != NULL );
ASSERT( szPath != NULL );
pMyItem = (PMYITEM) LocalAlloc( GMEM_FIXED, sizeof(MYITEM) );
if ( ! pMyItem ) {
return NULL;
}
pMyItem->aszCols[0] = (LPSTR) LocalAlloc( LPTR, lstrlen( szFilename ) + 1 );
pMyItem->aszCols[1] = (LPSTR) LocalAlloc( LPTR, lstrlen( szPath ) + 1 );
if ( ! pMyItem->aszCols[0] || ! pMyItem->aszCols[1] ) {
FreeItem( &pMyItem );
return NULL;
}
lstrcpy( pMyItem->aszCols[0], szFilename );
lstrcpy( pMyItem->aszCols[1], szPath );
pMyItem->fWroteOut = FALSE;
pMyItem->Next = NULL;
if ( g_CDF.pTop == NULL )
{
g_CDF.pTop = pMyItem;
}
else
{
pTail = g_CDF.pTop;
while ( pTail->Next != NULL )
{
pTail = pTail->Next;
}
pTail->Next = pMyItem;
}
g_CDF.cbFileListNum++;
return pMyItem;
}
//***************************************************************************
//* *
//* NAME: RemoveItem *
//* *
//* SYNOPSIS: Removes an item from the list and frees the memory. *
//* *
//* REQUIRES: Nothing *
//* *
//* RETURNS: Nothing *
//* *
//***************************************************************************
VOID RemoveItem( PMYITEM pMyItem )
{
PMYITEM pCurItem;
PMYITEM pLastItem;
ASSERT( pMyItem != NULL );
pCurItem = GetFirstItem();
if ( pMyItem == pCurItem ) {
g_CDF.pTop = pCurItem->Next;
FreeItem( &pCurItem );
return;
}
pLastItem = pCurItem;
pCurItem = GetNextItem( pCurItem );
while ( ! LastItem( pCurItem ) ) {
if ( pCurItem == pMyItem ) {
pLastItem->Next = pCurItem->Next;
FreeItem( &pCurItem );
return;
}
pLastItem = pCurItem;
pCurItem = GetNextItem( pCurItem );
}
// We should never get here.
ASSERT( TRUE );
}
//***************************************************************************
//* *
//* ParseCmdLine() *
//* *
//* Purpose: Parses the command line looking for switches *
//* *
//* Parameters: LPSTR lpszCmdLineOrg - Original command line *
//* *
//* *
//* Return: (BOOL) TRUE if successful *
//* FALSE if an error occurs *
//* *
//***************************************************************************
BOOL ParseCmdLine( LPSTR lpszCmdLine )
{
LPSTR pSubArg, pArg, pTmp;
CHAR szTmpBuf[MAX_PATH];
if( (!lpszCmdLine) || (lpszCmdLine[0] == 0) )
return TRUE;
pArg = strtok( lpszCmdLine, " " );
while ( pArg )
{
if ( lstrcmpi( pArg, "/N" ) == 0 )
{
g_fBuildNow = TRUE;
}
else if( (*pArg != '/' ) )
{
lstrcpyn( g_CDF.achFilename, pArg, sizeof(g_CDF.achFilename) );
GetFullPathName( g_CDF.achFilename, sizeof(g_CDF.achFilename),
g_CDF.achFilename, &pTmp );
}
else if ( (*pArg == '/') && (toupper(*(pArg+1)) == 'O') && (*(pArg+2) == ':') )
{
lstrcpy( szTmpBuf, (pArg+3) );
if ( pSubArg = strchr( szTmpBuf, ',' ) )
{
*pSubArg = '\0';
lstrcpy( g_szOverideCDF, szTmpBuf );
GetFullPathName( g_szOverideCDF, sizeof(g_szOverideCDF),
g_szOverideCDF, &pTmp );
if ( *(pSubArg+1) )
lstrcpy( g_szOverideSec, (pSubArg+1) );
}
}
else if ( lstrcmpi( pArg, "/Q" ) == 0 )
{
g_wQuietMode = 1;
}
else if ( lstrcmpi( pArg, "/S" ) == 0 )
{
g_wSilentMode = 1;
}
else if ( lstrcmpi( pArg, "/M" ) == 0 )
{
g_wRunDiamondMinimized = 1;
}
else
{
return FALSE;
}
pArg = strtok( NULL, " " );
}
if ( (g_wQuietMode == 1) && (g_fBuildNow == FALSE) ) {
g_wQuietMode = 0;
}
return TRUE;
}
// RO_GetPrivateProfileSection
// ensure the file attribute is not read-only.
//
LONG RO_GetPrivateProfileSection( LPCSTR lpSec, LPSTR lpBuf, DWORD dwSize, LPCSTR lpFile, BOOL bSingleCol)
{
LONG lRealSize;
DWORD dwAttr;
int iCDFVer;
dwAttr = GetFileAttributes( lpFile );
if ( (dwAttr != -1) && (dwAttr & FILE_ATTRIBUTE_READONLY) )
{
if ( !SetFileAttributes( lpFile, FILE_ATTRIBUTE_NORMAL ) )
{
ErrorMsg1Param( NULL, IDS_ERR_CANT_SETA_FILE, lpFile );
}
}
if ( ( (iCDFVer = GetPrivateProfileInt( SEC_VERSION, KEY_VERSION, -1, lpFile )) == -1 ) &&
( (iCDFVer = GetPrivateProfileInt( SEC_VERSION, KEY_NEWVER, -1, lpFile )) == -1 ) )
{
return (iCDFVer);
}
if ( !bSingleCol )
{
lRealSize = (LONG)GetPrivateProfileSection( lpSec, lpBuf, dwSize, lpFile );
}
else
{
if ( iCDFVer < 3 )
lRealSize = (LONG)GetPrivateProfileSection( lpSec, lpBuf, dwSize, lpFile );
else
lRealSize = (LONG)GetPrivateProfileString( lpSec, NULL, "", lpBuf, dwSize, lpFile );
}
if ( (dwAttr != -1) && (dwAttr & FILE_ATTRIBUTE_READONLY) )
{
SetFileAttributes( lpFile, dwAttr );
}
return lRealSize;
}
BOOL IsOSNT3X(VOID)
{
OSVERSIONINFO verinfo; // Version Check
// Operating System Version Check: For NT versions below 3.50 set flag to
// prevent use of common controls (progress bar and AVI) not available.
verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if ( GetVersionEx( &verinfo ) == FALSE )
{
// you definitly not windows 95 or NT 4.0
return TRUE;
}
if ( verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
{
if ( verinfo.dwMajorVersion <= 3 )
{
return TRUE;
}
}
return FALSE; // windows 95 or NT 4.0 above
}
void SetControlFont()
{
LOGFONT lFont;
if (GetSystemMetrics(SM_DBCSENABLED) &&
(GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof (lFont), &lFont) > 0))
{
g_hFont = CreateFontIndirect((LPLOGFONT)&lFont);
}
}
//==================================================================
BOOL GetThisModulePath( LPSTR lpPath, int size )
{
LPSTR lpTmp;
int len;
ASSERT(lpPath);
ASSERT(size);
*lpPath = 0;
if ( GetModuleFileName( g_hInst, lpPath, size ) )
{
// chop filename off
//
lpTmp = ANSIStrRChr( lpPath, '\\' );
if ( lpTmp )
{
*(CharNext(lpTmp)) = '\0';
}
}
return (*lpPath != '\0');
}
// BUGBUG: we don't need size param, since it is internal, we could assume
// MAX_PATH buffer
//
BOOL GetFileFromModulePath( LPCSTR pFile, LPSTR pPathBuf, int iBufSize )
{
BOOL bRet;
bRet = GetThisModulePath( pPathBuf, iBufSize );
AddPath( pPathBuf, pFile );
if ( bRet && GetFileAttributes( pPathBuf ) == -1 )
{
return FALSE;
}
return bRet;
}
//***************************************************************************
//* *
//* NAME: MakeDirectory *
//* *
//* SYNOPSIS: Make sure the directories along the given pathname exist. *
//* *
//* REQUIRES: pszFile: Name of the file being created. *
//* *
//* RETURNS: nothing *
//* *
//***************************************************************************
BOOL MakeDirectory( HWND hwnd, LPCSTR pszPath, BOOL bDoUI )
{
LPTSTR pchChopper;
int cExempt;
DWORD dwAttr;
BOOL bRet = FALSE;
if (pszPath[0] != '\0')
{
PSTR pszTmp = NULL;
char ch;
UINT umsg = 0;
UINT ubutton = MB_YESNO;
cExempt = 0;
pszTmp = ANSIStrRChr( pszPath, '\\' );
if ( pszTmp )
{
ch = *pszTmp;
*pszTmp = '\0';
}
dwAttr = GetFileAttributes( pszPath );
if ( bDoUI )
{
if ( dwAttr == 0xffffffff )
{
umsg = IDS_CREATEDIR;
ubutton = MB_YESNO;
}
else if ( !(dwAttr & FILE_ATTRIBUTE_DIRECTORY) )
{
umsg = IDS_INVALIDPATH;
ubutton = MB_OK;
}
if ( umsg && ( (MsgBox1Param( hwnd, umsg, (LPSTR)pszPath, MB_ICONQUESTION, ubutton ) == IDNO) ||
(ubutton == MB_OK) ) )
{
if ( pszTmp )
*pszTmp = ch;
return bRet;
}
}
if ( pszTmp )
*pszTmp = ch;
if ((pszPath[1] == ':') && (pszPath[2] == '\\'))
{
pchChopper = (LPTSTR) (pszPath + 3); /* skip past "C:\" */
}
else if ((pszPath[0] == '\\') && (pszPath[1] == '\\'))
{
pchChopper = (LPTSTR) (pszPath + 2); /* skip past "\\" */
cExempt = 2; /* machine & share names exempt */
}
else
{
pchChopper = (LPTSTR) (pszPath + 1); /* skip past potential "\" */
}
while (*pchChopper != '\0')
{
if ((*pchChopper == '\\') && (*(pchChopper - 1) != ':'))
{
if (cExempt != 0)
{
cExempt--;
}
else
{
*pchChopper = '\0';
CreateDirectory(pszPath,NULL);
*pchChopper = '\\';
}
}
pchChopper = CharNext(pchChopper);
}
bRet = TRUE;
}
return bRet;
}