//*************************************************************************** //* 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 #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: : 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; intVerCheck), 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; (idwSize ) == 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; }