Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4151 lines
157 KiB

  1. //***************************************************************************
  2. //* Copyright (c) Microsoft Corporation 1995. All rights reserved. *
  3. //***************************************************************************
  4. //* *
  5. //* CABPACK.C - Wizard to build a Win32 Self-Extracting and self-installing *
  6. //* EXE from a Cabinet (CAB) file. *
  7. //* *
  8. //***************************************************************************
  9. //***************************************************************************
  10. //* INCLUDE FILES *
  11. //***************************************************************************
  12. #include "pch.h"
  13. #pragma hdrstop
  14. #include "cabpack.h"
  15. #include <memory.h>
  16. #include "sdsutils.h"
  17. #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
  18. #define MAX_TARGVER 0xFFFFFFFF
  19. #define FLAG_BLK "OK"
  20. #define FLAG_PMTYN "YesNo"
  21. #define FLAG_PMTOC "OkCancel"
  22. //***************************************************************************
  23. //* GLOBAL VARIABLES *
  24. //***************************************************************************
  25. //---------------------------------------------------------------------------
  26. // attention: 3\18\97: Update notes:
  27. // We are changing our batch directive file extension from
  28. // CDF to SED. But all the internal data structure name
  29. // remain unchanged. So if you see CDF, it means old CDF file
  30. // or new SED file data.
  31. //---------------------------------------------------------------------------
  32. HINSTANCE g_hInst = NULL; // Pointer to Instance
  33. WIZARDSTATE *g_pWizardState = NULL; // Pointer to global wizard state
  34. BOOL g_fQuitWizard = FALSE; // Global flag used to signal that we
  35. // want to terminate the wizard
  36. // ourselves
  37. HFONT g_hBigFont = NULL; // Bigger font used by dialogs.
  38. extern CDF g_CDF; // Contains stuff that we want to
  39. // store in the CABPack Directive
  40. // File
  41. BOOL g_fBuildNow;
  42. FARPROC g_lpfnOldMEditWndProc;
  43. CHAR g_szOverideCDF[MAX_PATH];
  44. CHAR g_szOverideSec[SMALL_BUF_LEN];
  45. WORD g_wQuietMode = 0;
  46. WORD g_wSilentMode = 0;
  47. WORD g_wRunDiamondMinimized = 0;
  48. HFONT g_hFont = NULL;
  49. extern char g_szInitialDir[];
  50. BOOL IsOSNT3X(VOID);
  51. // This table defines the dialog id's and functions for processing each page.
  52. // Pages need only provide functions when they want non-default behavior for
  53. // certain action (init,buttons,notifications,next/back/finish,cancel).
  54. PAGEINFO PageInfo[NUM_WIZARD_PAGES] = {
  55. { IDD_WELCOME, WelcomeInit, WelcomeCmd, NULL, WelcomeOK, NULL },
  56. { IDD_MODIFY, ModifyInit, NULL, NULL, ModifyOK, NULL },
  57. { IDD_PACKPURPOSE,PackPurposeInit,PackPurposeCmd,NULL, PackPurposeOK,NULL },
  58. { IDD_TITLE, TitleInit, NULL, NULL, TitleOK, NULL },
  59. { IDD_PROMPT, PromptInit, PromptCmd, NULL, PromptOK, NULL },
  60. { IDD_LICENSETXT, LicenseTxtInit, LicenseTxtCmd, NULL, LicenseTxtOK, NULL },
  61. { IDD_FILES, FilesInit, FilesCmd, FilesNotify, FilesOK, NULL },
  62. { IDD_COMMAND, CommandInit, NULL, NULL, CommandOK, NULL },
  63. { IDD_SHOWWINDOW, ShowWindowInit, NULL, NULL, ShowWindowOK, NULL },
  64. { IDD_FINISHMSG, FinishMsgInit, FinishMsgCmd, NULL, FinishMsgOK, NULL },
  65. { IDD_TARGET, TargetInit, TargetCmd, NULL, TargetOK, NULL },
  66. { IDD_TARGET_CAB, TargetCABInit, TargetCABCmd, NULL, TargetCABOK, NULL },
  67. { IDD_CABLABEL, CabLabelInit, CabLabelCmd, NULL, CabLabelOK, NULL },
  68. { IDD_REBOOT, RebootInit, RebootCmd, NULL, RebootOK, NULL },
  69. { IDD_SAVE, SaveInit, SaveCmd, NULL, SaveOK, NULL },
  70. { IDD_CREATE, CreateInit, NULL, NULL, CreateOK, NULL },
  71. };
  72. CDFSTRINGINFO CDFStrInfo[] = {
  73. { SEC_OPTIONS, KEY_INSTPROMPT, "", g_CDF.achPrompt, sizeof(g_CDF.achPrompt), g_szOverideSec, &g_CDF.fPrompt },
  74. { SEC_OPTIONS, KEY_DSPLICENSE, "", g_CDF.achLicense, sizeof(g_CDF.achLicense), g_szOverideSec, &g_CDF.fLicense },
  75. { SEC_OPTIONS, KEY_ENDMSG, "", g_CDF.achFinishMsg, sizeof(g_CDF.achFinishMsg), g_szOverideSec, &g_CDF.fFinishMsg },
  76. { SEC_OPTIONS, KEY_PACKNAME, "", g_CDF.achTarget, sizeof(g_CDF.achTarget), g_szOverideSec, NULL },
  77. { SEC_OPTIONS, KEY_FRIENDLYNAME, "", g_CDF.achTitle, sizeof(g_CDF.achTitle), g_szOverideSec, NULL },
  78. { SEC_OPTIONS, KEY_APPLAUNCH, "", g_CDF.achOrigiInstallCmd,sizeof(g_CDF.achInstallCmd),g_szOverideSec, NULL },
  79. { SEC_OPTIONS, KEY_POSTAPPLAUNCH, "", g_CDF.achOrigiPostInstCmd,sizeof(g_CDF.achPostInstCmd),g_szOverideSec, NULL },
  80. { SEC_OPTIONS, KEY_ADMQCMD, "", g_CDF.szOrigiAdmQCmd, sizeof(g_CDF.szOrigiAdmQCmd), g_szOverideSec, NULL },
  81. { SEC_OPTIONS, KEY_USERQCMD, "", g_CDF.szOrigiUsrQCmd, sizeof(g_CDF.szOrigiUsrQCmd), g_szOverideSec, NULL },
  82. } ;
  83. CDFOPTINFO CDFOptInfo[] = {
  84. { KEY_NOEXTRACTUI, EXTRACTOPT_UI_NO },
  85. { KEY_USELFN, EXTRACTOPT_LFN_YES },
  86. { KEY_PLATFORM_DIR, EXTRACTOPT_PLATFORM_DIR },
  87. { KEY_NESTCOMPRESSED, EXTRACTOPT_COMPRESSED },
  88. { KEY_UPDHELPDLLS, EXTRACTOPT_UPDHLPDLLS },
  89. { KEY_CHKADMRIGHT, EXTRACTOPT_CHKADMRIGHT },
  90. { KEY_PASSRETURN, EXTRACTOPT_PASSINSTRET },
  91. { KEY_PASSRETALWAYS,EXTRACTOPT_PASSINSTRETALWAYS },
  92. { KEY_CMDSDEPENDED, EXTRACTOPT_CMDSDEPENDED },
  93. };
  94. CHAR *AdvDlls[] = { ADVANCEDLL, ADVANCEDLL32, ADVANCEDLL16 };
  95. PSTR pResvSizes[] = { CAB_0K, CAB_2K, CAB_4K, CAB_6K };
  96. void SetControlFont();
  97. void TermApp();
  98. //***************************************************************************
  99. //* *
  100. //* NAME: WinMain *
  101. //* *
  102. //* SYNOPSIS: Main entry point for the program. *
  103. //* *
  104. //* REQUIRES: hInstance: Handle to the program instance *
  105. //* hPrevInstance: Handle to the previous instance (NULL) *
  106. //* lpszCmdLine: Command line arguments *
  107. //* nCmdShow: How to show the window *
  108. //* *
  109. //* RETURNS: int: Always 0 *
  110. //* *
  111. //***************************************************************************
  112. INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
  113. LPSTR lpszCmdLine, INT nCmdShow )
  114. {
  115. g_hInst = hInstance;
  116. g_fBuildNow = FALSE;
  117. g_szOverideCDF[0] = 0;
  118. g_szOverideSec[0] = 0;
  119. // init CDF filenaem
  120. g_CDF.achFilename[0] = '\0';
  121. g_CDF.achVerInfo[0] = '\0';
  122. g_CDF.lpszCookie = NULL;
  123. InitItemList(); // Initilize our file item list.
  124. // Get the command line args. If there is a "/N", then we want to
  125. // build NOW!
  126. if ( !ParseCmdLine( lpszCmdLine ) )
  127. {
  128. ErrorMsg( NULL, IDS_ERR_BADCMDLINE );
  129. return 1; //error return case
  130. }
  131. if ( g_fBuildNow && lstrlen( g_CDF.achFilename ) > 0 )
  132. {
  133. // batch mode did not update the CDF file, no need for writeCDF
  134. if ( ReadCDF( NULL ) && MakePackage( NULL ) )
  135. {
  136. return 0;
  137. }
  138. else
  139. {
  140. return 1;
  141. }
  142. }
  143. // Allocate global structures
  144. g_pWizardState = (PWIZARDSTATE) malloc( sizeof( WIZARDSTATE) );
  145. if ( ! g_pWizardState ) {
  146. ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
  147. } else {
  148. SetControlFont();
  149. RunCABPackWizard();
  150. if (g_hFont)
  151. DeleteObject(g_hFont);
  152. }
  153. // Clean up dialog title font
  154. DestroyBigFont();
  155. TermApp();
  156. // Free global structures
  157. if ( g_pWizardState ) {
  158. free( g_pWizardState );
  159. }
  160. return 0;
  161. }
  162. // Free up the allocated resource
  163. //
  164. void TermApp()
  165. {
  166. if ( g_CDF.lpszCookie )
  167. {
  168. LocalFree( g_CDF.lpszCookie );
  169. }
  170. if ( g_CDF.pVerInfo )
  171. LocalFree( g_CDF.pVerInfo );
  172. }
  173. //***************************************************************************
  174. //* *
  175. //* NAME: RunCABPackWizard *
  176. //* *
  177. //* SYNOPSIS: Creates property sheet pages, initializes wizard property *
  178. //* sheet and runs wizard. *
  179. //* *
  180. //* REQUIRES: Nothing *
  181. //* *
  182. //* RETURNS: BOOL: TRUE if user runs wizard to completion, FALSE *
  183. //* if user cancels or an error occurs. *
  184. //* *
  185. //* NOTES: Wizard pages all use one dialog proc (GenDlgProc). They may *
  186. //* specify their own handler procs to get called at init time *
  187. //* or in response to Next, Cancel or a dialog control, or use *
  188. //* the default behavior of GenDlgProc. *
  189. //* *
  190. //***************************************************************************
  191. BOOL RunCABPackWizard( VOID )
  192. {
  193. HPROPSHEETPAGE hWizPage[NUM_WIZARD_PAGES]; // array to hold handles to pages
  194. PROPSHEETPAGE psPage; // struct used to create prop sheet pages
  195. PROPSHEETHEADER psHeader; // struct used to run wizard property sheet
  196. UINT nPageIndex;
  197. UINT nFreeIndex;
  198. INT_PTR iRet;
  199. ASSERT( g_pWizardState );
  200. // initialize the app state structure
  201. InitWizardState( g_pWizardState );
  202. // zero out structures
  203. memset( &hWizPage, 0, sizeof(hWizPage) );
  204. memset( &psPage, 0, sizeof(psPage) );
  205. memset( &psHeader, 0, sizeof(psHeader) );
  206. // fill out common data property sheet page struct
  207. psPage.dwSize = sizeof(psPage);
  208. psPage.dwFlags = PSP_DEFAULT;
  209. psPage.hInstance = g_hInst;
  210. psPage.pfnDlgProc = GenDlgProc;
  211. // create a property sheet page for each page in the wizard
  212. for ( nPageIndex = 0; nPageIndex < NUM_WIZARD_PAGES; nPageIndex++ ) {
  213. psPage.pszTemplate = MAKEINTRESOURCE( PageInfo[nPageIndex].uDlgID );
  214. // set a pointer to the PAGEINFO struct as the private data for this
  215. // page
  216. psPage.lParam = (LPARAM) &PageInfo[nPageIndex];
  217. hWizPage[nPageIndex] = CreatePropertySheetPage( &psPage );
  218. if ( !hWizPage[nPageIndex] ) {
  219. // creating page failed, free any pages already created and bail
  220. ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
  221. for ( nFreeIndex = 0; nFreeIndex < nPageIndex; nFreeIndex++ ) {
  222. DestroyPropertySheetPage( hWizPage[nFreeIndex] );
  223. }
  224. return FALSE;
  225. }
  226. }
  227. // fill out property sheet header struct
  228. psHeader.dwSize = sizeof(psHeader);
  229. psHeader.dwFlags = PSH_WIZARD | PSH_USEICONID;
  230. psHeader.hwndParent = NULL;
  231. psHeader.hInstance = g_hInst;
  232. psHeader.nPages = NUM_WIZARD_PAGES;
  233. psHeader.phpage = hWizPage;
  234. psHeader.pszIcon = (LPSTR) IDI_ICON;
  235. // run the Wizard
  236. iRet = PropertySheet( &psHeader );
  237. if ( iRet < 0 ) {
  238. // property sheet failed, most likely due to lack of memory
  239. ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
  240. }
  241. // If the user Cancels out of the Wizard, there may be items
  242. // left in the file list. Clean them up.
  243. DeleteAllItems();
  244. return ( iRet > 0 );
  245. }
  246. //***************************************************************************
  247. //* *
  248. //* NAME: GenDlgProc *
  249. //* *
  250. //* SYNOPSIS: Generic dialog proc for all wizard pages. *
  251. //* *
  252. //* REQUIRES: hDlg: *
  253. //* uMsg: *
  254. //* wParam: *
  255. //* lParam: *
  256. //* *
  257. //* RETURNS: BOOL: *
  258. //* *
  259. //* *
  260. //* NOTES: This dialog proc provides the following default behavior: *
  261. //* init: back and next buttons enabled *
  262. //* next btn: switches to page following current page *
  263. //* back btn: switches to previous page *
  264. //* cancel btn: prompts user to confirm, and cancels wizard *
  265. //* dlg ctrl: does nothing (in response to WM_COMMANDs) *
  266. //* Wizard pages can specify their own handler functions (in *
  267. //* the PageInfo table) to override default behavior for any of *
  268. //* the above actions. *
  269. //* *
  270. //***************************************************************************
  271. INT_PTR CALLBACK GenDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  272. {
  273. switch ( uMsg ) {
  274. //*********************************************************************
  275. case WM_INITDIALOG:
  276. //*********************************************************************
  277. {
  278. LPPROPSHEETPAGE lpsp; // get propsheet page struct passed in
  279. PPAGEINFO pPageInfo; // fetch our private page info from
  280. // propsheet struct
  281. lpsp = (LPPROPSHEETPAGE) lParam;
  282. ASSERT( lpsp );
  283. pPageInfo = (PPAGEINFO) lpsp->lParam;
  284. ASSERT( pPageInfo );
  285. // store pointer to private page info in window data for later
  286. SetWindowLongPtr( hDlg, DWLP_USER, (LPARAM) pPageInfo );
  287. // set title text to large font
  288. InitBigFont( hDlg, IDC_BIGTEXT );
  289. // initialize 'back' and 'next' wizard buttons, if
  290. // page wants something different it can fix in init proc below
  291. PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT |
  292. PSWIZB_BACK );
  293. // call init proc for this page if one is specified
  294. if ( pPageInfo->InitProc ) {
  295. return pPageInfo->InitProc( hDlg, TRUE );
  296. }
  297. return TRUE;
  298. break;
  299. }
  300. //*********************************************************************
  301. case WM_NOTIFY:
  302. //*********************************************************************
  303. {
  304. // get pointer to private page data out of window data
  305. PPAGEINFO pPageInfo;
  306. BOOL fRet;
  307. BOOL fKeepHistory = TRUE;
  308. NMHDR *lpnm = (NMHDR *) lParam;
  309. UINT uNextPage = 0;
  310. pPageInfo = (PPAGEINFO) GetWindowLongPtr( hDlg, DWLP_USER );
  311. ASSERT( pPageInfo );
  312. switch ( lpnm->code ) {
  313. //***********************************************************
  314. case PSN_SETACTIVE:
  315. //***********************************************************
  316. // initialize 'back' and 'next' wizard buttons, if
  317. // page wants something different it can fix in init proc
  318. PropSheet_SetWizButtons( GetParent(hDlg), PSWIZB_NEXT |
  319. PSWIZB_BACK );
  320. // call init proc for this page if one is specified
  321. if ( pPageInfo->InitProc ) {
  322. return pPageInfo->InitProc(hDlg,FALSE);
  323. }
  324. return TRUE;
  325. break;
  326. //***********************************************************
  327. case PSN_WIZNEXT:
  328. case PSN_WIZBACK:
  329. case PSN_WIZFINISH:
  330. //***********************************************************
  331. // call OK proc for this page if one is specified
  332. if ( pPageInfo->OKProc )
  333. if ( ! pPageInfo->OKProc( hDlg, ( lpnm->code != PSN_WIZBACK ), &uNextPage, &fKeepHistory ) )
  334. {
  335. // stay on this page
  336. SetPropSheetResult( hDlg, -1 );
  337. return TRUE;
  338. }
  339. if ( lpnm->code != PSN_WIZBACK ) {
  340. // 'next' pressed
  341. ASSERT( g_pWizardState->uPagesCompleted <
  342. NUM_WIZARD_PAGES );
  343. // save the current page index in the page history,
  344. // unless this page told us not to when we called
  345. // its OK proc above
  346. if ( fKeepHistory ) {
  347. g_pWizardState->uPageHistory
  348. [g_pWizardState->uPagesCompleted]
  349. = g_pWizardState->uCurrentPage;
  350. g_pWizardState->uPagesCompleted++;
  351. }
  352. // if no next page specified or no OK proc,
  353. // advance page by one
  354. if ( !uNextPage ) {
  355. uNextPage = g_pWizardState->uCurrentPage + 1;
  356. }
  357. } else {
  358. // 'back' pressed
  359. ASSERT( g_pWizardState->uPagesCompleted > 0 );
  360. // get the last page from the history list
  361. g_pWizardState->uPagesCompleted--;
  362. uNextPage = g_pWizardState->
  363. uPageHistory[g_pWizardState->
  364. uPagesCompleted];
  365. }
  366. // if we need to exit the wizard now, send a 'cancel'
  367. // message to ourselves (to keep the prop. page mgr happy)
  368. if ( g_fQuitWizard ) {
  369. PropSheet_PressButton(GetParent(hDlg), PSBTN_CANCEL);
  370. SetPropSheetResult( hDlg, -1 );
  371. return TRUE;
  372. }
  373. // set next page, only if 'next' or 'back' button
  374. // was pressed
  375. if ( lpnm->code != PSN_WIZFINISH ) {
  376. // set the next current page index
  377. g_pWizardState->uCurrentPage = uNextPage;
  378. // tell the prop sheet mgr what the next page to
  379. // display is
  380. SetPropSheetResult( hDlg,
  381. GetDlgIDFromIndex( uNextPage ) );
  382. return TRUE;
  383. }
  384. break;
  385. //***********************************************************
  386. case PSN_QUERYCANCEL:
  387. //***********************************************************
  388. // if global flag to exit is set, then this cancel
  389. // is us pretending to push 'cancel' so prop page mgr
  390. // will kill the wizard. Let this through...
  391. if ( g_fQuitWizard ) {
  392. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, FALSE );
  393. return TRUE;
  394. }
  395. // if this page has a special cancel proc, call it
  396. if ( pPageInfo->CancelProc )
  397. fRet = pPageInfo->CancelProc( hDlg );
  398. else {
  399. // default behavior: pop up a message box confirming
  400. // the cancel
  401. fRet = ( MsgBox( hDlg, IDS_QUERYCANCEL,
  402. MB_ICONQUESTION, MB_YESNO |
  403. MB_DEFBUTTON2 ) == IDYES );
  404. }
  405. // return the value thru window data
  406. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, !fRet );
  407. return TRUE;
  408. break;
  409. //***********************************************************
  410. default:
  411. //***********************************************************
  412. if ( pPageInfo->NotifyProc ) {
  413. pPageInfo->NotifyProc( hDlg, wParam, lParam );
  414. }
  415. }
  416. break;
  417. }
  418. //*********************************************************************
  419. case WM_COMMAND:
  420. //*********************************************************************
  421. {
  422. // get pointer to private page data out of window data
  423. PPAGEINFO pPageInfo;
  424. UINT uNextPage = 0;
  425. BOOL fGotoPage = FALSE;
  426. BOOL fKeepHistory = TRUE;
  427. pPageInfo = (PPAGEINFO) GetWindowLongPtr( hDlg, DWLP_USER );
  428. ASSERT( pPageInfo );
  429. // if this page has a command handler proc, call it
  430. if ( pPageInfo->CmdProc ) {
  431. pPageInfo->CmdProc( hDlg, (UINT) LOWORD(wParam), &fGotoPage,
  432. &uNextPage, &fKeepHistory );
  433. if ( fGotoPage ) {
  434. ASSERT( g_pWizardState->uPagesCompleted
  435. < NUM_WIZARD_PAGES );
  436. ASSERT( g_pWizardState->uPagesCompleted > 0 );
  437. SetPropSheetResult( hDlg, uNextPage );
  438. g_pWizardState->uCurrentPage = uNextPage;
  439. if ( fKeepHistory ) {
  440. g_pWizardState->uPageHistory[g_pWizardState->
  441. uPagesCompleted] = g_pWizardState->uCurrentPage;
  442. g_pWizardState->uPagesCompleted++;
  443. }
  444. // set the next current page index
  445. g_pWizardState->uCurrentPage = uNextPage;
  446. // tell the prop sheet mgr what the next page to
  447. // display is
  448. SetPropSheetResult( hDlg,
  449. GetDlgIDFromIndex( uNextPage ) );
  450. return TRUE;
  451. }
  452. }
  453. }
  454. }
  455. return FALSE;
  456. }
  457. //***************************************************************************
  458. //* *
  459. //* NAME: InitWizardState *
  460. //* *
  461. //* SYNOPSIS: Initializes wizard state structure. *
  462. //* *
  463. //* REQUIRES: pWizardState: *
  464. //* *
  465. //* RETURNS: Nothing *
  466. //* *
  467. //***************************************************************************
  468. VOID InitWizardState( WIZARDSTATE *pWizardState )
  469. {
  470. ASSERT( pWizardState );
  471. // zero out structure
  472. memset( pWizardState, 0, sizeof(WIZARDSTATE) );
  473. // set starting page
  474. pWizardState->uCurrentPage = ORD_PAGE_WELCOME;
  475. }
  476. //***************************************************************************
  477. //* *
  478. //* NAME: MEditSubClassWnd *
  479. //* *
  480. //* SYNOPSIS: Subclasses a multiline edit control so that a edit message *
  481. //* to select the entire contents is ignored. *
  482. //* *
  483. //* REQUIRES: hWnd: Handle of the edit window *
  484. //* fnNewProc: New window handler proc *
  485. //* lpfnOldProc: (returns) Old window handler proc *
  486. //* *
  487. //* RETURNS: Nothing *
  488. //* *
  489. //* NOTE: A selected edit message is not generated when the user *
  490. //* selects text with the keyboard or mouse. *
  491. //* *
  492. //***************************************************************************
  493. VOID NEAR PASCAL MEditSubClassWnd( HWND hWnd, FARPROC fnNewProc )
  494. {
  495. g_lpfnOldMEditWndProc = (FARPROC) GetWindowLongPtr( hWnd, GWLP_WNDPROC );
  496. SetWindowLongPtr( hWnd, GWLP_WNDPROC, (LONG_PTR) MakeProcInstance( fnNewProc,
  497. (HINSTANCE) GetWindowWord( hWnd, GWW_HINSTANCE ) ) );
  498. }
  499. //***************************************************************************
  500. //* *
  501. //* NAME: MEditSubProc *
  502. //* *
  503. //* SYNOPSIS: New multiline edit window procedure to ignore selection of *
  504. //* all contents. *
  505. //* *
  506. //* REQUIRES: hWnd: *
  507. //* msg: *
  508. //* wParam: *
  509. //* lParam: *
  510. //* *
  511. //* RETURNS: LONG: *
  512. //* *
  513. //* NOTE: A selected edit message is not generated when the user *
  514. //* selects text with the keyboard or mouse. *
  515. //* *
  516. //***************************************************************************
  517. LRESULT CALLBACK MEditSubProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
  518. {
  519. if ( msg == EM_SETSEL ) {
  520. return 0;
  521. wParam = lParam;
  522. lParam = MAKELPARAM( LOWORD(lParam), LOWORD(lParam) );
  523. }
  524. return CallWindowProc( (WNDPROC) g_lpfnOldMEditWndProc, hWnd, msg,
  525. wParam, lParam );
  526. }
  527. //***************************************************************************
  528. //* *
  529. //* NAME: GetDlgIDFromIndex *
  530. //* *
  531. //* SYNOPSIS: For a given zero-based page index, returns the *
  532. //* corresponding dialog ID for the page. *
  533. //* *
  534. //* REQUIRES: uPageIndex: *
  535. //* *
  536. //* RETURNS: UINT: *
  537. //* *
  538. //***************************************************************************
  539. UINT GetDlgIDFromIndex( UINT uPageIndex )
  540. {
  541. ASSERT( uPageIndex < NUM_WIZARD_PAGES );
  542. return PageInfo[uPageIndex].uDlgID;
  543. }
  544. //***************************************************************************
  545. //* *
  546. //* NAME: EnableWizard *
  547. //* *
  548. //* SYNOPSIS: Enables or disables the wizard buttons and the wizard page *
  549. //* itself (so it can't receive focus). *
  550. //* *
  551. //* REQUIRES: hDlg: Dialog window *
  552. //* fEnable: TRUE to enable the wizard, FALSE to disable *
  553. //* *
  554. //* RETURNS: Nothing *
  555. //* *
  556. //***************************************************************************
  557. VOID EnableWizard( HWND hDlg, BOOL fEnable )
  558. {
  559. HWND hwndWiz = GetParent( hDlg );
  560. // disable/enable back, next, cancel
  561. EnableWindow( GetDlgItem( hwndWiz, IDD_BACK ), fEnable );
  562. EnableWindow( GetDlgItem( hwndWiz, IDD_NEXT ), fEnable );
  563. EnableWindow( GetDlgItem( hwndWiz, IDCANCEL ), fEnable );
  564. // disable/enable wizard page
  565. EnableWindow( hwndWiz, fEnable );
  566. UpdateWindow( hwndWiz );
  567. if ( fEnable ) {
  568. SetForegroundWindow( hDlg );
  569. }
  570. }
  571. //***************************************************************************
  572. //* *
  573. //* NAME: MsgWaitForMultipleObjectsLoop *
  574. //* *
  575. //* SYNOPSIS: *
  576. //* *
  577. //* REQUIRES: hEvent: *
  578. //* *
  579. //* RETURNS: DWORD: *
  580. //* *
  581. //***************************************************************************
  582. DWORD MsgWaitForMultipleObjectsLoop( HANDLE hEvent )
  583. {
  584. MSG msg;
  585. DWORD dwObject;
  586. while (1)
  587. {
  588. dwObject = MsgWaitForMultipleObjects( 1, &hEvent, FALSE,INFINITE,
  589. QS_ALLINPUT );
  590. // Are we done waiting?
  591. switch ( dwObject ) {
  592. case WAIT_OBJECT_0:
  593. case WAIT_FAILED:
  594. return dwObject;
  595. case WAIT_OBJECT_0 + 1:
  596. // got a message, dispatch it and wait again
  597. while (PeekMessage(&msg, NULL,0, 0, PM_REMOVE)) {
  598. DispatchMessage(&msg);
  599. }
  600. break;
  601. }
  602. }
  603. }
  604. //***************************************************************************
  605. //* *
  606. //* NAME: MsgBox2Param *
  607. //* *
  608. //* SYNOPSIS: Displays a message box with the specified string ID using *
  609. //* 2 string parameters. *
  610. //* *
  611. //* REQUIRES: hWnd: Parent window *
  612. //* nMsgID: String resource ID *
  613. //* szParam1: Parameter 1 (or NULL) *
  614. //* szParam2: Parameter 2 (or NULL) *
  615. //* uIcon: Icon to display (or 0) *
  616. //* uButtons: Buttons to display *
  617. //* *
  618. //* RETURNS: INT: ID of button pressed *
  619. //* *
  620. //* NOTES: Macros are provided for displaying 1 parameter or 0 *
  621. //* parameter message boxes. Also see ErrorMsg() macros. *
  622. //* *
  623. //***************************************************************************
  624. INT MsgBox2Param( HWND hWnd, UINT nMsgID, LPCSTR szParam1, LPCSTR szParam2,
  625. UINT uIcon, UINT uButtons )
  626. {
  627. CHAR achMsgBuf[STRING_BUF_LEN];
  628. CHAR achSmallBuf[SMALL_BUF_LEN];
  629. LPSTR szMessage;
  630. INT nReturn;
  631. if ( !(g_wQuietMode == 1) )
  632. {
  633. LoadSz( IDS_APPNAME, achSmallBuf, sizeof(achSmallBuf) );
  634. LoadSz( nMsgID, achMsgBuf, sizeof(achMsgBuf) );
  635. if ( szParam2 != NULL ) {
  636. szMessage = (LPSTR) LocalAlloc( LPTR, lstrlen( achMsgBuf )
  637. + lstrlen( szParam1 )
  638. + lstrlen( szParam2 ) + 100 );
  639. if ( ! szMessage ) {
  640. return -1;
  641. }
  642. wsprintf( szMessage, achMsgBuf, szParam1, szParam2 );
  643. } else if ( szParam1 != NULL ) {
  644. szMessage = (LPSTR) LocalAlloc( LPTR, lstrlen( achMsgBuf )
  645. + lstrlen( szParam1 ) + 100 );
  646. if ( ! szMessage ) {
  647. return -1;
  648. }
  649. wsprintf( szMessage, achMsgBuf, szParam1, szParam2 );
  650. } else {
  651. szMessage = (LPSTR) LocalAlloc( LPTR, lstrlen( achMsgBuf ) + 1 );
  652. if ( ! szMessage ) {
  653. return -1;
  654. }
  655. lstrcpy( szMessage, achMsgBuf );
  656. }
  657. MessageBeep( uIcon );
  658. nReturn = MessageBox( hWnd, szMessage, achSmallBuf, uIcon | uButtons |
  659. MB_APPLMODAL | MB_SETFOREGROUND |
  660. ((RunningOnWin95BiDiLoc() && IsBiDiLocalizedBinary(g_hInst,RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO))) ? (MB_RIGHT | MB_RTLREADING) : 0) );
  661. LocalFree( szMessage );
  662. return nReturn;
  663. } else {
  664. return MB_OK;
  665. }
  666. }
  667. //***************************************************************************
  668. //* *
  669. //* NAME: DisplayFieldErrorMsg *
  670. //* *
  671. //* SYNOPSIS: Pops up a warning message about a field, sets focus to the *
  672. //* field and selects any text in it. *
  673. //* *
  674. //* REQUIRES: hDlg: parent windows *
  675. //* uCtrlID: ID of control left blank *
  676. //* uStrID: ID of string resource with warning message *
  677. //* *
  678. //* RETURNS: Nothing *
  679. //* *
  680. //***************************************************************************
  681. VOID DisplayFieldErrorMsg( HWND hDlg, UINT uCtrlID, UINT uStrID )
  682. {
  683. ErrorMsg( hDlg, uStrID );
  684. SetFocus( GetDlgItem( hDlg, uCtrlID ) );
  685. SendDlgItemMessage( hDlg, uCtrlID, EM_SETSEL, 0, -1 );
  686. }
  687. //***************************************************************************
  688. //* *
  689. //* NAME: FileExists *
  690. //* *
  691. //* SYNOPSIS: Checks if a file exists. *
  692. //* *
  693. //* REQUIRES: pszFilename *
  694. //* *
  695. //* RETURNS: BOOL: TRUE if it exists, FALSE otherwise *
  696. //* *
  697. //***************************************************************************
  698. BOOL FileExists( LPCSTR pszFilename )
  699. {
  700. HANDLE hFile;
  701. ASSERT( pszFilename );
  702. hFile = CreateFile( pszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
  703. FILE_ATTRIBUTE_NORMAL, NULL );
  704. if ( hFile == INVALID_HANDLE_VALUE ) {
  705. return( FALSE );
  706. }
  707. CloseHandle( hFile );
  708. return( TRUE );
  709. }
  710. //***************************************************************************
  711. //* *
  712. //* NAME: InitBigFont *
  713. //* *
  714. //* SYNOPSIS: Sets the font of the specifed control to the large (title) *
  715. //* font. Creates the font if it doesn't already exist. *
  716. //* *
  717. //* REQUIRES: hwnd: *
  718. //* uCtrlID: *
  719. //* *
  720. //* RETURNS: Nothing *
  721. //* *
  722. //* NOTES: Make sure to call DestroyBigFont before the app exits to *
  723. //* dispose of the font. *
  724. //* *
  725. //* Borrowed from Win 95 setup code. *
  726. //* *
  727. //***************************************************************************
  728. VOID InitBigFont( HWND hwnd, UINT uCtrlID )
  729. {
  730. HFONT hFont;
  731. HWND hwndCtl;
  732. LOGFONT lFont;
  733. int nLogPixelsY;
  734. HDC hDC;
  735. // get the window for the specified control
  736. if ( ( hwndCtl = GetDlgItem( hwnd, uCtrlID ) ) == NULL ) {
  737. return;
  738. }
  739. // get the logical y pixels
  740. hDC = GetDC( NULL );
  741. ASSERT( hDC );
  742. if ( !hDC ) {
  743. return;
  744. }
  745. nLogPixelsY = GetDeviceCaps( hDC, LOGPIXELSY );
  746. ReleaseDC( NULL, hDC );
  747. if ( ! g_hBigFont ) {
  748. if ( ( hFont = (HFONT) (WORD) SendMessage( hwndCtl, WM_GETFONT, 0, 0L ) ) != NULL ) {
  749. if ( GetObject( hFont, sizeof(LOGFONT), (LPSTR) &lFont ) ) {
  750. lFont.lfWeight = FW_BOLD;
  751. LoadString( g_hInst, IDS_MSSERIF, lFont.lfFaceName, LF_FACESIZE - 1 );
  752. lFont.lfHeight = -1 * ( nLogPixelsY * LARGE_POINTSIZE / 72 );
  753. g_hBigFont = CreateFontIndirect( (LPLOGFONT) &lFont );
  754. }
  755. }
  756. }
  757. if ( g_hBigFont ) {
  758. SendMessage( hwndCtl, WM_SETFONT, (WPARAM) g_hBigFont, 0L );
  759. }
  760. else {
  761. // couldn't create font
  762. // DEBUGTRAP( "Couldn't create large font" );
  763. }
  764. }
  765. //***************************************************************************
  766. //* *
  767. //* NAME: DestroyBigFont *
  768. //* *
  769. //* SYNOPSIS: Destroys the large font used for dialog titles, if it has *
  770. //* been created. *
  771. //* *
  772. //* REQUIRES: Nothing *
  773. //* *
  774. //* RETURNS: Nothing *
  775. //* *
  776. //***************************************************************************
  777. VOID DestroyBigFont( VOID )
  778. {
  779. if ( g_hBigFont ) {
  780. DeleteObject( g_hBigFont );
  781. g_hBigFont = NULL;
  782. }
  783. }
  784. //***************************************************************************
  785. //* *
  786. //* NAME: EnableDlgItem *
  787. //* *
  788. //* SYNOPSIS: Makes it a little simpler to enable a dialog item. *
  789. //* *
  790. //* REQUIRES: hDlg: Dialog handle *
  791. //* uID: ID of control *
  792. //* fEnable: TRUE to enable, FALSE to disable *
  793. //* *
  794. //* RETURNS: BOOL: TRUE if successfull, FALSE otherwise *
  795. //* *
  796. //***************************************************************************
  797. BOOL EnableDlgItem( HWND hDlg, UINT uID, BOOL fEnable )
  798. {
  799. return EnableWindow( GetDlgItem( hDlg, uID ), fEnable );
  800. }
  801. //***************************************************************************
  802. //* *
  803. //* NAME: LoadSz *
  804. //* *
  805. //* SYNOPSIS: Loads specified string resource into buffer. *
  806. //* *
  807. //* REQUIRES: idString: *
  808. //* lpszBuf: *
  809. //* cbBuf: *
  810. //* *
  811. //* RETURNS: LPSTR: Pointer to the passed-in buffer. *
  812. //* *
  813. //* NOTES: If this function fails (most likely due to low memory), the *
  814. //* returned buffer will have a leading NULL so it is generally *
  815. //* safe to use this without checking for failure. *
  816. //* *
  817. //***************************************************************************
  818. LPSTR LoadSz( UINT idString, LPSTR lpszBuf, UINT cbBuf )
  819. {
  820. ASSERT( lpszBuf );
  821. // Clear the buffer and load the string
  822. if ( lpszBuf ) {
  823. *lpszBuf = '\0';
  824. LoadString( g_hInst, idString, lpszBuf, cbBuf );
  825. }
  826. return lpszBuf;
  827. }
  828. //***************************************************************************
  829. //* *
  830. //* NAME: IsDuplicate *
  831. //* *
  832. //* SYNOPSIS: Checks if a file being added to the list view is already *
  833. //* in the listview. *
  834. //* *
  835. //* REQUIRES: hDlg: dialog window *
  836. //* nDlgItem: ID of list view control *
  837. //* szFilename: Name of file to check for a dupe. *
  838. //* *
  839. //* RETURNS: BOOL: TRUE if it's a duplicate, FALSE otherwise *
  840. //* *
  841. //***************************************************************************
  842. BOOL WINAPI IsDuplicate( HWND hDlg, INT nDlgItem, LPSTR szFilename, BOOL chkIsListbox )
  843. {
  844. INT nItems;
  845. HWND hwndFiles;
  846. LV_ITEM lviCheck;
  847. PMYITEM pItem = NULL;
  848. INT nIndex;
  849. if ( chkIsListbox )
  850. {
  851. hwndFiles = GetDlgItem( hDlg, nDlgItem );
  852. nItems = ListView_GetItemCount( hwndFiles );
  853. for ( nIndex = 0; nIndex < nItems; nIndex += 1 ) {
  854. lviCheck.mask = LVIF_PARAM;
  855. lviCheck.iItem = nIndex;
  856. lviCheck.iSubItem = 0;
  857. lviCheck.lParam = (LPARAM) pItem;
  858. ListView_GetItem( hwndFiles, &lviCheck );
  859. if ( lstrcmpi( ((PMYITEM)(lviCheck.lParam))->aszCols[0],
  860. szFilename ) == 0 )
  861. {
  862. return TRUE;
  863. }
  864. }
  865. }
  866. else // check through the file item list
  867. {
  868. pItem = GetFirstItem();
  869. while ( ! LastItem( pItem ) )
  870. {
  871. if ( !lstrcmpi( szFilename, GetItemSz( pItem, 0 ) ) )
  872. {
  873. return TRUE;
  874. }
  875. pItem = GetNextItem( pItem );
  876. }
  877. }
  878. return FALSE;
  879. }
  880. //***************************************************************************
  881. //* *
  882. //* NAME: IsMyKeyExists *
  883. //* *
  884. //* SYNOPSIS: Checks if a specific key in the given section and given file*
  885. //* is defined. IF so, get the value. OW return -1 *
  886. //* *
  887. //* *
  888. //***************************************************************************
  889. LONG IsMyKeyExists( LPCSTR lpSec, LPCSTR lpKey, LPSTR lpBuf, UINT uSize, LPCSTR lpFile )
  890. {
  891. LONG lRet;
  892. lRet = (LONG)GetPrivateProfileString( lpSec, lpKey, SYS_DEFAULT, lpBuf, uSize, lpFile );
  893. if ( lpSec && lpKey && (lRet == (LONG)(uSize-1)) || !lpKey && (lRet == (LONG)(uSize-2)) )
  894. {
  895. // not enough buffer size to read the string
  896. lRet = -2;
  897. }
  898. else if ( !lstrcmp( lpBuf, SYS_DEFAULT ) )
  899. {
  900. // no key defined
  901. lRet = -1;
  902. }
  903. return lRet;
  904. }
  905. ULONG FileSize( LPSTR lpFile )
  906. {
  907. ULONG ulFileSize;
  908. WIN32_FIND_DATA FindFileData;
  909. HANDLE hFile;
  910. if ( *lpFile == 0 )
  911. return 0;
  912. hFile = FindFirstFile( lpFile, &FindFileData );
  913. ulFileSize = (FindFileData.nFileSizeHigh * MAXDWORD) + FindFileData.nFileSizeLow;
  914. FindClose( hFile );
  915. return ulFileSize;
  916. }
  917. void NotifyBadString( PCSTR pszBadname, UINT uMaxSize )
  918. {
  919. char szSize[20];
  920. _itoa(uMaxSize, szSize, 10);
  921. MsgBox2Param( NULL, IDS_ERR_BADSTRING, pszBadname, szSize, MB_ICONSTOP, MB_OK );
  922. }
  923. //***************************************************************************
  924. //
  925. // FormStrWithoutPlaceHolders( LPSTR szDst, LPCSTR szSrc, LPCSTR lpFile, UINT uSize );
  926. //
  927. // This function can be easily described by giving examples of what it
  928. // does:
  929. // Input: GenFormStrWithoutPlaceHolders(dest,"desc=%MS_XYZ%", hinf) ;
  930. // INF file has MS_VGA="Microsoft XYZ" in its [Strings] section!
  931. //
  932. // Output: "desc=Microsoft XYZ" in buffer dest when done.
  933. //
  934. //
  935. // ENTRY:
  936. // szDst - the destination where the string after the substitutions
  937. // for the place holders (the ones enclosed in "%' chars!)
  938. // is placed. This buffer should be big enough (LINE_LEN)
  939. // szSrc - the string with the place holders.
  940. // uSize - the size of the output buffer
  941. //
  942. // EXIT:
  943. //
  944. // NOTES:
  945. // To use a '%' as such in the string, one would use %% in szSrc! BUGBUG For
  946. // the sake of simplicity, we have placed a restriction that the place
  947. // holder name string cannot have a '%' as part of it! If this is a problem
  948. // for internationalization, we can revisit this and support it too! Also,
  949. // the way it is implemented, if there is only one % in the string, it is
  950. // also used as such! Another point to note is that if the key is not
  951. // found in the [Strings] section, we just use the %strkey% as such in the
  952. // destination. This should really help in debugging.
  953. //
  954. // BTW, CH_STRINGKEY, in the code below, is the symbolic name for '%'.
  955. //
  956. // Get/modified it from setupx: gen1.c
  957. //***************************************************************************
  958. LONG FormStrWithoutPlaceHolders( LPSTR szDst, LPCSTR szSrc, UINT uSize )
  959. {
  960. int uCnt ;
  961. LONG lRet;
  962. CHAR *pszTmp;
  963. LPSTR pszSaveDst;
  964. pszSaveDst = szDst;
  965. // Do until we reach the end of source (null char)
  966. while( (*szDst++ = *szSrc) )
  967. {
  968. // Increment source as we have only incremented destination above
  969. if(*szSrc++ == CH_STRINGKEY)
  970. {
  971. if (*szSrc == CH_STRINGKEY)
  972. {
  973. // One can use %% to get a single percentage char in message
  974. szSrc++ ;
  975. continue ;
  976. }
  977. // see if it is well formed -- there should be a '%' delimiter
  978. if ( (pszTmp = strchr( szSrc, CH_STRINGKEY)) != NULL )
  979. {
  980. szDst--; // get back to the '%' char to replace
  981. // yes, there is a STR_KEY to be looked for in [Strings] sect.
  982. *pszTmp = '\0' ; // replace '%' with a NULL char
  983. // szSrc points to the replaceable key now as we put the NULL char above.
  984. if ( (g_szOverideCDF[0] == 0) || (g_CDF.achStrings[0] == 0) ||
  985. (lRet = IsMyKeyExists( g_CDF.achStrings, szSrc, szDst, uSize, g_szOverideCDF )) == -1 )
  986. {
  987. lRet = IsMyKeyExists( SEC_STRINGS, szSrc, szDst, uSize, g_CDF.achFilename );
  988. }
  989. if ( lRet == -1 )
  990. {
  991. // key is missing in [Strings] section!
  992. if ( MsgBox1Param( NULL, IDS_WARN_MISSSTRING, (LPSTR)szSrc, MB_ICONQUESTION, MB_YESNO ) == IDNO )
  993. return lRet;
  994. *pszTmp = CH_STRINGKEY; // put back original character
  995. szSrc-- ; // get back to first '%' in Src
  996. uCnt = (INT)((pszTmp - szSrc) + 1); // include 2nd '%'
  997. // UGHHH... It copies 1 less byte from szSrc so that it can put
  998. // in a bad NULL character, that I don't care about!!!
  999. // Different from the normal API I am used to...
  1000. lstrcpyn( szDst, szSrc, uCnt + 1 ) ;
  1001. }
  1002. else if ( lRet == -2 )
  1003. {
  1004. NotifyBadString( szSrc, uSize );
  1005. return lRet;
  1006. }
  1007. else
  1008. {
  1009. // all was well, Dst filled right, but unfortunately count not passed
  1010. // back, like it used too... :-( quick fix is a lstrlen()...
  1011. uCnt = lstrlen( szDst ) ;
  1012. }
  1013. *pszTmp = CH_STRINGKEY ; // put back original character
  1014. szSrc = pszTmp + 1 ; // set Src after the second '%'
  1015. szDst += uCnt ; // set Dst also right.
  1016. }
  1017. // else it is ill-formed -- we use the '%' as such!
  1018. else
  1019. {
  1020. if ( MsgBox1Param( NULL, IDS_ERR_READ_CDF, (LPSTR)(szSrc - 1), MB_ICONQUESTION, MB_YESNO ) == IDNO )
  1021. return -1;
  1022. }
  1023. }
  1024. } /* while */
  1025. return lstrlen(pszSaveDst);
  1026. } /* GenFormStrWithoutPlaceHolders */
  1027. //***************************************************************************
  1028. //* *
  1029. //* NAME: MyGetPrivateProfileString *
  1030. //* *
  1031. //* SYNOPSIS: get key string vale from overide CDF if exists. Otherwise, *
  1032. //* get it from Main CDF. And expand to its real string value *
  1033. //* return -1 if key-string define error and user stops *
  1034. //* *
  1035. //***************************************************************************
  1036. LONG MyGetPrivateProfileString( LPCSTR lpSec, LPCSTR lpKey, LPCSTR lpDefault,
  1037. LPSTR lpBuf, UINT uSize, LPCSTR lpOverSec )
  1038. {
  1039. PSTR pszNewLine;
  1040. LONG lRet;
  1041. if ( g_szOverideCDF[0] == 0 || *lpOverSec == 0 ||
  1042. (lRet= IsMyKeyExists( lpOverSec, lpKey, lpBuf, uSize, g_szOverideCDF )) == -1 )
  1043. {
  1044. lRet = (LONG)GetPrivateProfileString( lpSec, lpKey, lpDefault, lpBuf, uSize, g_CDF.achFilename );
  1045. }
  1046. if ( lpKey == NULL )
  1047. {
  1048. return lRet;
  1049. }
  1050. pszNewLine = (LPSTR)LocalAlloc( LPTR, uSize );
  1051. if ( pszNewLine )
  1052. {
  1053. lRet = FormStrWithoutPlaceHolders( pszNewLine, lpBuf, uSize );
  1054. if ( lRet >= 0 )
  1055. lstrcpy( lpBuf, pszNewLine );
  1056. LocalFree( pszNewLine );
  1057. }
  1058. return lRet;
  1059. }
  1060. //***************************************************************************
  1061. //* *
  1062. //* NAME: MyGetPrivateProfileInt *
  1063. //* *
  1064. //* SYNOPSIS: get key INT vale from overide CDF if exists. Otherwise, *
  1065. //* get it from Main CDF. And expand to its real string value *
  1066. //* *
  1067. //***************************************************************************
  1068. UINT MyGetPrivateProfileInt( LPCSTR lpSec, LPCSTR lpKey, int idefault, LPCSTR lpOverSec )
  1069. {
  1070. UINT uRet = 999; // means not valid value
  1071. if ( g_szOverideCDF[0] && *lpOverSec )
  1072. uRet = GetPrivateProfileInt( lpOverSec, lpKey, 999, g_szOverideCDF );
  1073. if ( uRet == 999 )
  1074. uRet = GetPrivateProfileInt( lpSec, lpKey, idefault, g_CDF.achFilename );
  1075. return uRet;
  1076. }
  1077. //***************************************************************************
  1078. //* *
  1079. //* NAME: MyGetPrivateProfileSection *
  1080. //* *
  1081. //* SYNOPSIS: get section from overide CDF if exists. Otherwise, *
  1082. //* get it from Main CDF. *
  1083. //* *
  1084. //***************************************************************************
  1085. LONG MyGetPrivateProfileSection( LPCSTR lpSec, LPSTR lpBuf, int size, BOOL bSingleCol )
  1086. {
  1087. LONG lRet;
  1088. if ( g_szOverideCDF[0] == 0 || (lRet=RO_GetPrivateProfileSection( lpSec, lpBuf, size, g_szOverideCDF, bSingleCol )) == 0 )
  1089. {
  1090. lRet = RO_GetPrivateProfileSection( lpSec, lpBuf, size, g_CDF.achFilename, bSingleCol );
  1091. }
  1092. return lRet;
  1093. }
  1094. //***************************************************************************
  1095. //* *
  1096. //* NAME: MyWritePrivateProfileString *
  1097. //* *
  1098. //* SYNOPSIS: Write out all String value Key in its localizable format *
  1099. //* %...% If previouse keyname=%used-define% exists, reuse *
  1100. //* user-define as key in Strings section. Otherwise, use *
  1101. //* %keyname% and define keyname in Strings section *
  1102. //* *
  1103. //***************************************************************************
  1104. void MyWritePrivateProfileString( LPCSTR lpSec, LPCSTR lpKey, LPSTR lpBuf, UINT uSize, BOOL fQuotes )
  1105. {
  1106. CHAR szTmpBuf[MAX_PATH];
  1107. LPSTR pszTmpBuf2 = NULL;
  1108. BOOL fUseDefault;
  1109. pszTmpBuf2 = (LPSTR)LocalAlloc( LPTR, uSize+32 );
  1110. if ( !pszTmpBuf2 )
  1111. return;
  1112. // when we write the string value out, we write it in a localizable fashion
  1113. // if the item has %strKey% format, we re-use the %strKey% as its String refer key
  1114. // otherwise, we use %item-name% as the string refer key
  1115. GetPrivateProfileString( lpSec, lpKey, "", szTmpBuf, uSize, g_CDF.achFilename );
  1116. if ( (szTmpBuf[0] == CH_STRINGKEY) && (szTmpBuf[lstrlen(szTmpBuf)-1] == CH_STRINGKEY) )
  1117. {
  1118. szTmpBuf[lstrlen(szTmpBuf)-1] = '\0';
  1119. fUseDefault = FALSE;
  1120. }
  1121. else
  1122. {
  1123. lstrcpy( szTmpBuf, "%" );
  1124. lstrcat( szTmpBuf, lpKey );
  1125. lstrcat( szTmpBuf, "%" );
  1126. WritePrivateProfileString( lpSec, lpKey, szTmpBuf, g_CDF.achFilename );
  1127. fUseDefault = TRUE;
  1128. }
  1129. if ( fQuotes ) {
  1130. lstrcpy( pszTmpBuf2, "\"" );
  1131. lstrcat( pszTmpBuf2, lpBuf );
  1132. lstrcat( pszTmpBuf2, "\"" );
  1133. } else {
  1134. lstrcpy( pszTmpBuf2, lpBuf );
  1135. }
  1136. WritePrivateProfileString( SEC_STRINGS, fUseDefault?lpKey:(szTmpBuf+1), pszTmpBuf2, g_CDF.achFilename );
  1137. if ( pszTmpBuf2 )
  1138. LocalFree( pszTmpBuf2 );
  1139. return;
  1140. }
  1141. //***************************************************************************
  1142. //* *
  1143. //* NAME: CleanStringKey *
  1144. //* *
  1145. //* SYNOPSIS: Cleanup the leftover File%d stuff in Strings *
  1146. //* *
  1147. //***************************************************************************
  1148. void CleanStringKey( LPSTR lpstrKey )
  1149. {
  1150. LPSTR pszTmp;
  1151. if ( lpstrKey == NULL )
  1152. return;
  1153. while ( *lpstrKey )
  1154. {
  1155. if ( *lpstrKey++ == CH_STRINGKEY )
  1156. {
  1157. if (*lpstrKey == CH_STRINGKEY)
  1158. {
  1159. // One can use %% to get a single percentage char in message
  1160. lpstrKey++ ;
  1161. continue ;
  1162. }
  1163. // see if it is well formed -- there should be a '%' delimiter
  1164. if ( (pszTmp = strchr( lpstrKey, CH_STRINGKEY)) != NULL )
  1165. {
  1166. // yes, there is a STR_KEY to be looked for in [Strings] sect.
  1167. *pszTmp = '\0' ; // replace '%' with a NULL char
  1168. WritePrivateProfileString( SEC_STRINGS, lpstrKey, NULL, g_CDF.achFilename);
  1169. *pszTmp = CH_STRINGKEY;
  1170. lpstrKey = pszTmp+1;
  1171. }
  1172. else
  1173. break;
  1174. }
  1175. }
  1176. }
  1177. //***************************************************************************
  1178. //* *
  1179. //* NAME: CleanupSection *
  1180. //* *
  1181. //* SYNOPSIS: Cleanup the any given section with key=%xxxx% and its *
  1182. //* strings *
  1183. //* *
  1184. //***************************************************************************
  1185. BOOL CleanupSection( LPSTR lpSec, BOOL fSingleCol )
  1186. {
  1187. LPSTR lpBuf, lpSave;
  1188. CHAR szStrKey[SMALL_BUF_LEN];
  1189. int size;
  1190. size = FileSize( g_CDF.achFilename );
  1191. lpBuf = (LPSTR) LocalAlloc( LPTR, size );
  1192. if ( !lpBuf )
  1193. {
  1194. ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
  1195. return FALSE;
  1196. }
  1197. lpSave = lpBuf;
  1198. if ( fSingleCol )
  1199. RO_GetPrivateProfileSection( lpSec, lpBuf, size, g_CDF.achFilename, TRUE );
  1200. else
  1201. GetPrivateProfileString( lpSec, NULL, "", lpBuf, size, g_CDF.achFilename );
  1202. while ( *lpBuf )
  1203. {
  1204. if ( fSingleCol )
  1205. CleanStringKey( lpBuf );
  1206. else
  1207. {
  1208. GetPrivateProfileString( lpSec, lpBuf, "", szStrKey, sizeof(szStrKey), g_CDF.achFilename );
  1209. CleanStringKey( szStrKey );
  1210. }
  1211. lpBuf += lstrlen(lpBuf);
  1212. lpBuf++; //jump over the single '\0'
  1213. }
  1214. WritePrivateProfileString( lpSec, NULL, NULL, g_CDF.achFilename );
  1215. LocalFree( lpSave );
  1216. return TRUE;
  1217. }
  1218. //***************************************************************************
  1219. //* *
  1220. //* NAME: CleanSourceFiles *
  1221. //* *
  1222. //* SYNOPSIS: Cleanup the leftover SourceFile%d stuff *
  1223. //* *
  1224. //***************************************************************************
  1225. BOOL CleanSourceFiles( LPSTR lpSection )
  1226. {
  1227. LPSTR lpBuf, lpSave;
  1228. int size;
  1229. size = FileSize( g_CDF.achFilename );
  1230. lpBuf = (LPSTR) LocalAlloc( LPTR, size );
  1231. if ( !lpBuf )
  1232. {
  1233. ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
  1234. return FALSE;
  1235. }
  1236. lpSave = lpBuf;
  1237. GetPrivateProfileString( lpSection, NULL, "", lpBuf, size, g_CDF.achFilename );
  1238. while ( *lpBuf )
  1239. {
  1240. if ( !CleanupSection( lpBuf, TRUE ) )
  1241. {
  1242. LocalFree( lpSave );
  1243. return FALSE;
  1244. }
  1245. lpBuf += (lstrlen(lpBuf) + 1);
  1246. }
  1247. WritePrivateProfileString( lpSection, NULL, NULL, g_CDF.achFilename );
  1248. LocalFree( lpSave );
  1249. return TRUE;
  1250. }
  1251. //***************************************************************************
  1252. //* *
  1253. //* NAME: MergerSection *
  1254. //* *
  1255. //***************************************************************************
  1256. BOOL MergeSection( LPSTR lpSec, LPSTR lpOverideSec )
  1257. {
  1258. // always merge the lpOverideSec keys to lpSec
  1259. LPSTR lpBuf, lpSave;
  1260. CHAR szValue[MAX_PATH];
  1261. int size;
  1262. size = __max( FileSize( g_CDF.achFilename ), FileSize( g_szOverideCDF ) ) ;
  1263. lpBuf = (LPSTR) LocalAlloc( LPTR, size );
  1264. if ( !lpBuf )
  1265. {
  1266. ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
  1267. return FALSE;
  1268. }
  1269. lpSave = lpBuf;
  1270. GetPrivateProfileString( lpOverideSec, NULL, "", lpBuf, size, g_szOverideCDF );
  1271. while ( *lpBuf )
  1272. {
  1273. if ( MyGetPrivateProfileString( lpSec, lpBuf, "", szValue, sizeof(szValue), lpOverideSec ) == -1 )
  1274. {
  1275. LocalFree( lpSave );
  1276. return FALSE;
  1277. }
  1278. MyWritePrivateProfileString( lpSec, lpBuf, szValue, sizeof(szValue), FALSE );
  1279. lpBuf += (lstrlen(lpBuf) + 1);
  1280. }
  1281. LocalFree( lpSave );
  1282. return TRUE;
  1283. }
  1284. // If the next token in *pszData is delimited by the DeLim char, replace DeLim
  1285. // in *pszData by chEos, set *pszData to point to the char after the chEos and return
  1286. // ptr to the beginning of the token; otherwise, return NULL
  1287. //
  1288. LPSTR GetNextToken(LPSTR *pszData, char DeLim)
  1289. {
  1290. LPSTR szPos;
  1291. if (pszData == NULL || *pszData == NULL || **pszData == 0)
  1292. return NULL;
  1293. if ((szPos = strchr(*pszData, DeLim)) != NULL)
  1294. {
  1295. LPSTR szT = *pszData;
  1296. *pszData = CharNext(szPos);
  1297. *szPos = '\0';
  1298. szPos = szT;
  1299. }
  1300. else
  1301. {
  1302. szPos = *pszData;
  1303. *pszData = szPos + lstrlen(szPos);
  1304. }
  1305. return szPos;
  1306. }
  1307. void SetVerUnlimit( PVERRANGE pVer )
  1308. {
  1309. pVer->toVer.dwMV = MAX_TARGVER;
  1310. pVer->toVer.dwLV = MAX_TARGVER;
  1311. pVer->toVer.dwBd = MAX_TARGVER;
  1312. }
  1313. // given the str version range: ver1-ver2
  1314. void SetVerRange( PVERRANGE pVR, LPSTR pstrVer, BOOL bFile )
  1315. {
  1316. LPSTR pTmp, pArg, pSubArg;
  1317. DWORD dwVer[4];
  1318. int i, j;
  1319. BOOL bSingleVer;
  1320. pArg = pstrVer;
  1321. bSingleVer = strchr( pstrVer, '-' ) ? FALSE : TRUE;
  1322. for ( i=0; i<2; i++ )
  1323. {
  1324. pTmp = GetNextToken( &pArg, '-' );
  1325. if ( !pTmp )
  1326. {
  1327. if ( !bSingleVer )
  1328. {
  1329. // case1 -4.0.0 == 0.0.0-4.0.0
  1330. // case2 4.0.0- == 4.0.0-NoLimit
  1331. //
  1332. if ( i == 0 )
  1333. continue;
  1334. else
  1335. SetVerUnlimit( pVR );
  1336. }
  1337. break;
  1338. }
  1339. for ( j=0; j<4; j++ )
  1340. {
  1341. dwVer[j] = strtoul( pTmp, &pSubArg, 10 );
  1342. pTmp = CharNext(pSubArg);
  1343. }
  1344. if ( bFile )
  1345. {
  1346. DWORD dwMV, dwLV;
  1347. dwMV = MAKELONG( (WORD)dwVer[1], (WORD)dwVer[0] );
  1348. dwLV = MAKELONG( (WORD)dwVer[3], (WORD)dwVer[2] );
  1349. if ( i == 0 )
  1350. {
  1351. pVR->frVer.dwMV = dwMV;
  1352. pVR->frVer.dwLV = dwLV;
  1353. }
  1354. else
  1355. {
  1356. pVR->toVer.dwMV = dwMV;
  1357. pVR->toVer.dwLV = dwLV;
  1358. }
  1359. }
  1360. else
  1361. {
  1362. if ( i == 0 ) // start version (from version)
  1363. {
  1364. pVR->frVer.dwMV = dwVer[0];
  1365. pVR->frVer.dwLV = dwVer[1];
  1366. pVR->frVer.dwBd = dwVer[2];
  1367. }
  1368. else
  1369. {
  1370. pVR->toVer.dwMV = dwVer[0];
  1371. pVR->toVer.dwLV = dwVer[1];
  1372. pVR->toVer.dwBd = dwVer[2];
  1373. }
  1374. }
  1375. }
  1376. }
  1377. //***************************************************************************
  1378. //* *
  1379. //* NAME: GetTargetVerCheck *
  1380. //* *
  1381. //* SYNOPSIS: Get author specifined target versions *
  1382. //* *
  1383. //***************************************************************************
  1384. BOOL ParseTargetVerCheck( LPSTR szBuf, PVERCHECK pVerCheck, LPSTR szMsg, BOOL bFile)
  1385. {
  1386. int i, j;
  1387. LPSTR pArg, pSubArg, pTmp;
  1388. DWORD dwVer[4];
  1389. *szMsg = 0;
  1390. if ( szBuf[0] == 0 )
  1391. {
  1392. // this is the case that no versions are specified, meaning applying to all
  1393. SetVerUnlimit( &(pVerCheck->vr[0]) );
  1394. return TRUE;
  1395. }
  1396. // the loop for possible 3 fields: <ver range> : str : flags
  1397. //
  1398. pArg = szBuf;
  1399. for ( i=0; i<3; i++ )
  1400. {
  1401. pTmp = GetNextToken( &pArg, ':' );
  1402. if ( !pTmp )
  1403. break;
  1404. else if ( *pTmp == 0 )
  1405. {
  1406. if ( i == 0 )
  1407. {
  1408. // empty version range field no bother further!
  1409. SetVerUnlimit( &(pVerCheck->vr[0]) );
  1410. break;
  1411. }
  1412. continue;
  1413. }
  1414. if ( i == 0 )
  1415. {
  1416. LPSTR pRange;
  1417. // version range format: ver1-ver2 , ver1-ver2 :
  1418. //
  1419. for ( j = 0; j<2; j++)
  1420. {
  1421. pRange = GetNextToken( &pTmp, ',' );
  1422. if ( !pRange )
  1423. break;
  1424. else if ( *pRange == 0 )
  1425. continue;
  1426. else
  1427. SetVerRange( &(pVerCheck->vr[j]), pRange, bFile );
  1428. }
  1429. }
  1430. else if ( i == 1 )
  1431. {
  1432. // string field
  1433. lstrcpy( szMsg, pTmp );
  1434. }
  1435. else
  1436. {
  1437. // flag field
  1438. if ( !lstrcmpi(pTmp, FLAG_BLK) )
  1439. pVerCheck->dwFlag |= VERCHK_OK;
  1440. else if ( !lstrcmpi(pTmp, FLAG_PMTYN) )
  1441. pVerCheck->dwFlag |= VERCHK_YESNO;
  1442. else if ( !lstrcmpi(pTmp, FLAG_PMTOC) )
  1443. pVerCheck->dwFlag |= VERCHK_OKCANCEL;
  1444. else
  1445. {
  1446. ErrorMsg1Param( NULL, IDS_ERR_VCHKFLAG, pTmp );
  1447. return FALSE;
  1448. }
  1449. }
  1450. }
  1451. // Just in case, we broke out early or user's to-ver is empty fill with from-ver.
  1452. //
  1453. for ( j = 0; j<2; j++ )
  1454. {
  1455. if ( !pVerCheck->vr[j].toVer.dwMV && !pVerCheck->vr[j].toVer.dwLV && !pVerCheck->vr[j].toVer.dwBd )
  1456. {
  1457. pVerCheck->vr[j].toVer = pVerCheck->vr[j].frVer;
  1458. }
  1459. }
  1460. return TRUE;
  1461. }
  1462. //***************************************************************************
  1463. //* *
  1464. //* NAME: OutFileListSection *
  1465. //* *
  1466. //* SYNOPSIS: Write out the file list from the internal ItemList *
  1467. //* *
  1468. //***************************************************************************
  1469. BOOL OutFileListSection()
  1470. {
  1471. PMYITEM pItem;
  1472. LPSTR lpFileStr;
  1473. CHAR szCurrSection[MAX_SECLEN];
  1474. CHAR szCurrFile[MAX_SECLEN];
  1475. CHAR szCurrSecValue[MAX_PATH];
  1476. BOOL fAllDone;
  1477. int idxSec = 0, idxFile = 0;
  1478. LPSTR pFileList;
  1479. CHAR achFilename[MAX_PATH+10];
  1480. // this will allocate enough space to build file key list
  1481. #define FILEKEYSIZE 20
  1482. pFileList = (LPSTR) LocalAlloc( LPTR, g_CDF.cbFileListNum*FILEKEYSIZE );
  1483. if ( !pFileList )
  1484. {
  1485. ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
  1486. return FALSE;
  1487. }
  1488. do
  1489. {
  1490. fAllDone = TRUE;
  1491. pItem = g_CDF.pTop;
  1492. lpFileStr = pFileList;
  1493. szCurrSection[0] = 0;
  1494. *lpFileStr = '\0';
  1495. while ( pItem )
  1496. {
  1497. if ( !pItem->fWroteOut )
  1498. {
  1499. if ( fAllDone )
  1500. fAllDone = FALSE;
  1501. // if this section is not write out yet, write now
  1502. if ( pItem->aszCols[1] && (szCurrSection[0] == 0) )
  1503. {
  1504. lstrcpy( szCurrSection, KEY_FILELIST );
  1505. lstrcat( szCurrSection, _itoa(idxSec++, szCurrFile, 10 ) );
  1506. WritePrivateProfileString( g_CDF.achSourceFile, szCurrSection, pItem->aszCols[1], g_CDF.achFilename );
  1507. lstrcpy( szCurrSecValue, pItem->aszCols[1] );
  1508. }
  1509. if ( !lstrcmpi( szCurrSecValue, pItem->aszCols[1] ) )
  1510. {
  1511. pItem->fWroteOut = TRUE;
  1512. wsprintf( szCurrFile, KEY_FILEBASE, idxFile++ );
  1513. lstrcpy( achFilename, pItem->aszCols[0] );
  1514. MyWritePrivateProfileString( SEC_STRINGS, szCurrFile, achFilename, sizeof(achFilename), TRUE );
  1515. // build file list of this section
  1516. lstrcpy( lpFileStr, "%" );
  1517. lstrcat( lpFileStr, szCurrFile );
  1518. lstrcat( lpFileStr, "%=" );
  1519. lpFileStr += lstrlen(lpFileStr);
  1520. lpFileStr++; // jump over the '\0'
  1521. }
  1522. }
  1523. pItem = pItem->Next;
  1524. }
  1525. if ( !fAllDone )
  1526. {
  1527. *lpFileStr = '\0';
  1528. WritePrivateProfileSection( szCurrSection, pFileList, g_CDF.achFilename );
  1529. }
  1530. } while ( !fAllDone );
  1531. LocalFree( pFileList );
  1532. return TRUE;
  1533. }
  1534. // return the number of entries in the section
  1535. //
  1536. DWORD GetSecNumLines( LPCSTR pSec, LPCSTR pFile )
  1537. {
  1538. char szBuf[MAX_PATH];
  1539. DWORD dwNum = 0;
  1540. int i = 0;
  1541. GetPrivateProfileString( pSec, NULL, "", szBuf, sizeof(szBuf), pFile );
  1542. while ( szBuf[i] )
  1543. {
  1544. dwNum++;
  1545. i += lstrlen( &szBuf[i] );
  1546. i++; // jump over the fence
  1547. }
  1548. return dwNum;
  1549. }
  1550. // check if need to alloc and how much is needed
  1551. //
  1552. BOOL AllocTargetVerInfo( LPSTR pInfFile )
  1553. {
  1554. char achBuf[MAX_INFLINE];
  1555. DWORD dwNumFiles = 0;
  1556. BOOL bRet = TRUE;
  1557. DWORD dwSize;
  1558. if ( IsMyKeyExists( SEC_OPTIONS, KEY_SYSFILE, achBuf, sizeof(achBuf), pInfFile ) != -1 )
  1559. {
  1560. if (achBuf[0] == '@')
  1561. {
  1562. // process the file section
  1563. dwNumFiles = GetSecNumLines( &achBuf[1], pInfFile );
  1564. }
  1565. else
  1566. dwNumFiles = 1;
  1567. }
  1568. if ( dwNumFiles ||
  1569. (IsMyKeyExists( SEC_OPTIONS, KEY_NTVERCHECK, achBuf, sizeof(achBuf), pInfFile ) != -1) ||
  1570. (IsMyKeyExists( SEC_OPTIONS, KEY_WIN9XVERCHECK, achBuf, sizeof(achBuf), pInfFile ) != -1) )
  1571. {
  1572. // alloc structure: fixed potion, Message string pool and variable number of filever check struct
  1573. //
  1574. dwSize = sizeof(TARGETVERINFO) + (3*MAX_PATH) + (sizeof(VERCHECK) + MAX_PATH)*dwNumFiles;
  1575. if ( g_CDF.pVerInfo = (PTARGETVERINFO)LocalAlloc( LPTR, dwSize ) )
  1576. {
  1577. g_CDF.pVerInfo->dwNumFiles = dwNumFiles;
  1578. }
  1579. else
  1580. {
  1581. ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
  1582. bRet = FALSE;
  1583. }
  1584. }
  1585. return bRet;
  1586. }
  1587. void SetAuthorStr( LPCSTR szMsg, DWORD *pdwOffset )
  1588. {
  1589. int len = 0;
  1590. LPSTR pTmp;
  1591. BOOL bDup = FALSE;
  1592. if ( szMsg[0] )
  1593. {
  1594. pTmp = &(g_CDF.pVerInfo->szBuf[1]);
  1595. // there is an author defined message
  1596. while ( pTmp && *pTmp )
  1597. {
  1598. if ( !lstrcmpi( pTmp, szMsg ) )
  1599. {
  1600. bDup = TRUE;
  1601. break;
  1602. }
  1603. len = (lstrlen( pTmp )+1);
  1604. pTmp += len;
  1605. }
  1606. if ( pTmp )
  1607. {
  1608. // only store the offset to szBuf
  1609. *pdwOffset = (DWORD)(pTmp - g_CDF.pVerInfo->szBuf);
  1610. if ( !bDup )
  1611. {
  1612. // meaning there is no existing one!
  1613. //
  1614. lstrcpy( pTmp, szMsg );
  1615. // store the end of the last string data offset
  1616. g_CDF.pVerInfo->dwFileOffs = *pdwOffset + lstrlen(pTmp) + 1;
  1617. }
  1618. }
  1619. }
  1620. }
  1621. BOOL ParseTargetFiles( LPCSTR pBuf, PVERCHECK pVer )
  1622. {
  1623. LPSTR lpTmp1, lpTmp2;
  1624. BOOL bRet = FALSE;
  1625. char szPath[MAX_PATH];
  1626. lpTmp1 = strchr( pBuf, ':' );
  1627. if ( lpTmp1 )
  1628. {
  1629. char ch = (char)toupper(pBuf[1]);
  1630. lpTmp2 = CharNext( lpTmp1 );
  1631. *(lpTmp1) = '\0';
  1632. if ( (pBuf[0] == '#') && ( (ch == 'S') || (ch == 'W') || (ch == 'A') ) )
  1633. {
  1634. if ( ParseTargetVerCheck( lpTmp2, pVer, szPath, TRUE ) )
  1635. {
  1636. SetAuthorStr( szPath, &(pVer->dwstrOffs) );
  1637. SetAuthorStr( pBuf, &(pVer->dwNameOffs) );
  1638. bRet = TRUE;
  1639. }
  1640. }
  1641. }
  1642. return bRet;
  1643. }
  1644. //***************************************************************************
  1645. //* *
  1646. //* NAME: WriteCDF *
  1647. //* *
  1648. //* SYNOPSIS: Write a CABPack Directive File. Uses information from *
  1649. //* Global CDF structure (g_CDF). *
  1650. //* *
  1651. //* REQUIRES: hDlg: dialog window *
  1652. //* *
  1653. //* RETURNS: Nothing *
  1654. //* *
  1655. //***************************************************************************
  1656. BOOL WriteCDF( HWND hDlg )
  1657. {
  1658. CHAR achBuf[2 * MAX_PATH];
  1659. int i, arraySize;
  1660. // write class name.
  1661. WritePrivateProfileString( SEC_VERSION, KEY_CLASS, IEXPRESS_CLASS, g_CDF.achFilename );
  1662. // delete the old CDFVersion= line and add SEFVersion= line
  1663. WritePrivateProfileString( SEC_VERSION, KEY_VERSION, NULL, g_CDF.achFilename );
  1664. WritePrivateProfileString( SEC_VERSION, KEY_NEWVER, IEXPRESS_VER, g_CDF.achFilename );
  1665. // Write the config info, numeric value.
  1666. // if user has old ExtractOnly key, delete it first and re-create the new key PackagePurpose instead
  1667. WritePrivateProfileString( SEC_OPTIONS, KEY_EXTRACTONLY, NULL, g_CDF.achFilename );
  1668. switch ( g_CDF.uPackPurpose )
  1669. {
  1670. case IDC_CMD_RUNCMD:
  1671. default:
  1672. lstrcpy( achBuf, STR_INSTALLAPP );
  1673. break;
  1674. case IDC_CMD_EXTRACT:
  1675. lstrcpy( achBuf, STR_EXTRACTONLY );
  1676. break;
  1677. case IDC_CMD_CREATECAB:
  1678. lstrcpy( achBuf, STR_CREATECAB );
  1679. break;
  1680. }
  1681. WritePrivateProfileString( SEC_OPTIONS, KEY_PACKPURPOSE, achBuf, g_CDF.achFilename );
  1682. WritePrivateProfileString( SEC_OPTIONS, KEY_SHOWWIN, _itoa(g_CDF.uShowWindow, achBuf,10), g_CDF.achFilename );
  1683. WritePrivateProfileString( SEC_OPTIONS, KEY_NOEXTRACTUI, _itoa( (g_CDF.uExtractOpt&EXTRACTOPT_UI_NO)?1:0, achBuf, 10), g_CDF.achFilename );
  1684. WritePrivateProfileString( SEC_OPTIONS, KEY_USELFN, _itoa( (g_CDF.uExtractOpt&EXTRACTOPT_LFN_YES)?1:0, achBuf, 10), g_CDF.achFilename );
  1685. WritePrivateProfileString( SEC_OPTIONS, KEY_NESTCOMPRESSED, _itoa( (g_CDF.uExtractOpt&EXTRACTOPT_COMPRESSED)?1:0, achBuf, 10), g_CDF.achFilename );
  1686. WritePrivateProfileString( SEC_OPTIONS, KEY_CABFIXEDSIZE,
  1687. _itoa( (g_CDF.uExtractOpt & CAB_FIXEDSIZE)?1:0, achBuf, 10), g_CDF.achFilename );
  1688. if ( g_CDF.uExtractOpt & CAB_RESVSP2K )
  1689. i = 1;
  1690. else if ( g_CDF.uExtractOpt & CAB_RESVSP4K )
  1691. i = 2;
  1692. else if ( g_CDF.uExtractOpt & CAB_RESVSP6K )
  1693. i = 3;
  1694. else
  1695. i = 0;
  1696. lstrcpy( achBuf, pResvSizes[i] );
  1697. WritePrivateProfileString( SEC_OPTIONS, KEY_CABRESVCODESIGN, achBuf, g_CDF.achFilename );
  1698. // get reboot settings
  1699. achBuf[0] = 0;
  1700. if ( g_CDF.dwReboot & REBOOT_YES )
  1701. {
  1702. if ( g_CDF.dwReboot & REBOOT_ALWAYS )
  1703. lstrcpy( achBuf, "A" );
  1704. else
  1705. lstrcpy( achBuf, "I" );
  1706. if ( g_CDF.dwReboot & REBOOT_SILENT )
  1707. lstrcat( achBuf, "S" );
  1708. }
  1709. else
  1710. lstrcpy( achBuf, "N" );
  1711. WritePrivateProfileString( SEC_OPTIONS, KEY_REBOOTMODE, achBuf, g_CDF.achFilename );
  1712. arraySize = ARRAY_SIZE( CDFStrInfo );
  1713. // Start writting out the string value
  1714. for ( i = 0; i < arraySize; i++ )
  1715. {
  1716. if ( CDFStrInfo[i].lpFlag )
  1717. {
  1718. if ( *CDFStrInfo[i].lpFlag )
  1719. {
  1720. MyWritePrivateProfileString( CDFStrInfo[i].lpSec, CDFStrInfo[i].lpKey, CDFStrInfo[i].lpBuf, CDFStrInfo[i].uSize, FALSE );
  1721. }
  1722. else
  1723. MyWritePrivateProfileString( CDFStrInfo[i].lpSec, CDFStrInfo[i].lpKey, (LPSTR)CDFStrInfo[i].lpDef, CDFStrInfo[i].uSize, FALSE );
  1724. }
  1725. else
  1726. MyWritePrivateProfileString( CDFStrInfo[i].lpSec, CDFStrInfo[i].lpKey, CDFStrInfo[i].lpBuf, CDFStrInfo[i].uSize, FALSE );
  1727. }
  1728. if ( g_CDF.uExtractOpt & CAB_FIXEDSIZE )
  1729. {
  1730. MyWritePrivateProfileString( SEC_OPTIONS, KEY_LAYOUTINF, g_CDF.achINF, sizeof(g_CDF.achINF), FALSE );
  1731. MyWritePrivateProfileString( SEC_OPTIONS, KEY_CABLABEL, g_CDF.szCabLabel, sizeof(g_CDF.szCabLabel), FALSE );
  1732. }
  1733. // read in the exist one first
  1734. GetVersionInfoFromFile();
  1735. // cleanup VerInfo left over if needed
  1736. if ( GetPrivateProfileString( SEC_OPTIONS, KEY_VERSIONINFO, "", achBuf, sizeof(achBuf), g_CDF.achFilename ) )
  1737. {
  1738. if ( lstrcmpi( achBuf, g_CDF.achVerInfo) )
  1739. {
  1740. if ( !CleanupSection( achBuf, FALSE) )
  1741. {
  1742. return FALSE;
  1743. }
  1744. }
  1745. }
  1746. // write Version information overwite section
  1747. if ( g_CDF.achVerInfo[0] )
  1748. {
  1749. WritePrivateProfileString( SEC_OPTIONS, KEY_VERSIONINFO, g_CDF.achVerInfo, g_CDF.achFilename );
  1750. if ( !MergeSection( g_CDF.achVerInfo, g_CDF.achVerInfo ) )
  1751. return FALSE;
  1752. }
  1753. // if current SourceFiles has different name than the main CDF defined, clean the old one first
  1754. if ( GetPrivateProfileString( SEC_OPTIONS, KEY_FILELIST, "", achBuf, sizeof(achBuf), g_CDF.achFilename ) )
  1755. {
  1756. if ( !CleanSourceFiles( achBuf ) )
  1757. return FALSE;
  1758. }
  1759. WritePrivateProfileString( SEC_OPTIONS, KEY_FILELIST, g_CDF.achSourceFile, g_CDF.achFilename );
  1760. // write the file list section
  1761. return ( OutFileListSection() );
  1762. }
  1763. //***************************************************************************
  1764. //* *
  1765. //* NAME: ReadCDF *
  1766. //* *
  1767. //* SYNOPSIS: Read a CABPack Directive File into the Global CDF struct. *
  1768. //* *
  1769. //* REQUIRES: hDlg: dialog window *
  1770. //* *
  1771. //* RETURNS: Nothing *
  1772. //* *
  1773. //***************************************************************************
  1774. BOOL ReadCDF( HWND hDlg )
  1775. {
  1776. CHAR achBuf[2 * MAX_PATH];
  1777. LPSTR lpSave1=NULL, lpSave2=NULL;
  1778. LPSTR szFileList=NULL, szFileListKeys=NULL;
  1779. ULONG ulFileSize, uData;
  1780. PMYITEM pMyItem;
  1781. CHAR szPath[MAX_PATH];
  1782. int i, arraySize;
  1783. LONG lRet;
  1784. BOOL bRetVal = FALSE;
  1785. UINT uErrid = 0;
  1786. achBuf[0] = '\0';
  1787. szPath[0] = '\0';
  1788. if ( !FileExists(g_CDF.achFilename) )
  1789. {
  1790. uErrid = IDS_ERR_OPEN_CDF;
  1791. goto EXIT;
  1792. }
  1793. // Check to make sure it's a CDF file.
  1794. if ( MyGetPrivateProfileString( SEC_VERSION, KEY_CLASS, "", achBuf, sizeof(achBuf), g_szOverideSec ) < 0 )
  1795. goto EXIT;
  1796. if ( lstrcmpi( achBuf, "IEXPRESS" ) != 0 )
  1797. {
  1798. uErrid = IDS_ERR_CLASSNAME;
  1799. goto EXIT;
  1800. }
  1801. if ( !AllocTargetVerInfo( g_CDF.achFilename ) )
  1802. goto EXIT;
  1803. // get string section name from overideCDF if there
  1804. if ( g_szOverideCDF[0] && g_szOverideSec[0] )
  1805. {
  1806. if ( !AllocTargetVerInfo( g_szOverideCDF ) )
  1807. goto EXIT;
  1808. GetPrivateProfileString( g_szOverideSec, KEY_STRINGS, SEC_STRINGS, g_CDF.achStrings, sizeof(g_CDF.achStrings), g_szOverideCDF );
  1809. }
  1810. // Read the config info INT vaules.
  1811. // If old ExtractOnly key exists, read it for compatiable purpose.
  1812. // IExpress will never create both OLD and NEW keys.
  1813. // If Old ExtractOnly key is not set to 1 or does not exist, read the New key.
  1814. //
  1815. if ( MyGetPrivateProfileInt( SEC_OPTIONS, KEY_EXTRACTONLY, 0, g_szOverideSec ) )
  1816. {
  1817. g_CDF.uPackPurpose = IDC_CMD_EXTRACT;
  1818. }
  1819. else
  1820. {
  1821. // if the old key is not set, check the new key
  1822. //
  1823. MyGetPrivateProfileString( SEC_OPTIONS, KEY_PACKPURPOSE, STR_INSTALLAPP, achBuf, sizeof(achBuf), g_szOverideSec );
  1824. if ( !lstrcmpi( achBuf, STR_INSTALLAPP ) )
  1825. {
  1826. g_CDF.uPackPurpose = IDC_CMD_RUNCMD;
  1827. }
  1828. else if ( !lstrcmpi( achBuf, STR_EXTRACTONLY) )
  1829. {
  1830. g_CDF.uPackPurpose = IDC_CMD_EXTRACT;
  1831. }
  1832. else
  1833. g_CDF.uPackPurpose = IDC_CMD_CREATECAB;
  1834. }
  1835. g_CDF.uShowWindow = MyGetPrivateProfileInt( SEC_OPTIONS, KEY_SHOWWIN, 0, g_szOverideSec );
  1836. g_CDF.uExtractOpt = 0;
  1837. arraySize = ARRAY_SIZE( CDFOptInfo );
  1838. // Start writting out the string value
  1839. for ( i = 0; i < arraySize; i++ )
  1840. {
  1841. uData = MyGetPrivateProfileInt( SEC_OPTIONS, CDFOptInfo[i].lpKey, 0, g_szOverideSec );
  1842. if ( uData )
  1843. {
  1844. g_CDF.uExtractOpt |= CDFOptInfo[i].dwOpt;
  1845. }
  1846. }
  1847. // get OneInstance check info
  1848. MyGetPrivateProfileString( SEC_OPTIONS, KEY_INSTANCECHK, "", achBuf, sizeof(achBuf), g_szOverideSec );
  1849. switch ( toupper( achBuf[0]) )
  1850. {
  1851. case 'P':
  1852. g_CDF.uExtractOpt |= EXTRACTOPT_INSTCHKPROMPT;
  1853. break;
  1854. case 'B':
  1855. g_CDF.uExtractOpt |= EXTRACTOPT_INSTCHKBLOCK;
  1856. break;
  1857. default:
  1858. break;
  1859. }
  1860. if ( (g_CDF.uExtractOpt & EXTRACTOPT_INSTCHKPROMPT) ||
  1861. (g_CDF.uExtractOpt & EXTRACTOPT_INSTCHKBLOCK) )
  1862. {
  1863. if ( !(lpSave1 = strchr( achBuf, '"' )) )
  1864. {
  1865. uErrid = IDS_ERR_COOKIE;
  1866. goto EXIT;
  1867. }
  1868. lpSave2 = strchr( ++lpSave1, '"' );
  1869. if ( lpSave2 )
  1870. {
  1871. *lpSave2 = '\0';
  1872. g_CDF.lpszCookie = (LPSTR)LocalAlloc( LPTR, lstrlen(lpSave1)+1 );
  1873. if ( g_CDF.lpszCookie )
  1874. {
  1875. lstrcpy( g_CDF.lpszCookie, lpSave1 );
  1876. }
  1877. else
  1878. {
  1879. uErrid = IDS_ERR_NO_MEMORY;
  1880. goto EXIT;
  1881. }
  1882. }
  1883. else
  1884. {
  1885. uErrid = IDS_ERR_COOKIE;
  1886. goto EXIT;
  1887. }
  1888. }
  1889. uData = MyGetPrivateProfileInt( SEC_OPTIONS, KEY_CABFIXEDSIZE, 0, g_szOverideSec );
  1890. if ( uData )
  1891. {
  1892. g_CDF.uExtractOpt |= CAB_FIXEDSIZE;
  1893. }
  1894. MyGetPrivateProfileString( SEC_OPTIONS, KEY_LAYOUTINF, "", g_CDF.achINF, sizeof(g_CDF.achINF), g_szOverideSec );
  1895. MyGetPrivateProfileString( SEC_OPTIONS, KEY_CABLABEL, CAB_DEFSETUPMEDIA, g_CDF.szCabLabel, sizeof(g_CDF.szCabLabel), g_szOverideSec );
  1896. MyGetPrivateProfileString( SEC_OPTIONS, KEY_CABRESVCODESIGN, CAB_6K, achBuf, sizeof(achBuf), g_szOverideSec );
  1897. if ( !lstrcmpi(achBuf, pResvSizes[1]) )
  1898. g_CDF.uExtractOpt |= CAB_RESVSP2K;
  1899. else if ( !lstrcmpi(achBuf, pResvSizes[2]) )
  1900. g_CDF.uExtractOpt |= CAB_RESVSP4K;
  1901. else if ( !lstrcmpi(achBuf, pResvSizes[3]) )
  1902. g_CDF.uExtractOpt |= CAB_RESVSP6K;
  1903. MyGetPrivateProfileString( SEC_OPTIONS, KEY_COMPRESSTYPE, "", achBuf, sizeof(achBuf), g_szOverideSec );
  1904. if ( achBuf[0] == 0 )
  1905. {
  1906. // Get the compression type: For MS Internal, "QUANTUM=value" can be set.
  1907. g_CDF.uCompressionLevel = MyGetPrivateProfileInt( SEC_OPTIONS, KEY_QUANTUM, 999, g_szOverideSec );
  1908. if ( g_CDF.uCompressionLevel == 999 )
  1909. {
  1910. g_CDF.szCompressionType = achMSZIP;
  1911. g_CDF.uCompressionLevel = 7;
  1912. }
  1913. else
  1914. {
  1915. g_CDF.szCompressionType = achQUANTUM;
  1916. }
  1917. }
  1918. else
  1919. {
  1920. if ( !lstrcmpi( achBuf, achLZX ) )
  1921. {
  1922. g_CDF.szCompressionType = achLZX;
  1923. }
  1924. else if ( !lstrcmpi( achBuf, achQUANTUM ) )
  1925. {
  1926. g_CDF.szCompressionType = achQUANTUM;
  1927. }
  1928. else if ( !lstrcmpi( achBuf, achNONE ) )
  1929. {
  1930. g_CDF.szCompressionType = achNONE;
  1931. }
  1932. else
  1933. {
  1934. g_CDF.szCompressionType = achMSZIP;
  1935. }
  1936. g_CDF.uCompressionLevel = 7;
  1937. }
  1938. // get reboot info
  1939. g_CDF.dwReboot = 0;
  1940. i = 0;
  1941. MyGetPrivateProfileString( SEC_OPTIONS, KEY_REBOOTMODE, "I", achBuf, sizeof(achBuf), g_szOverideSec );
  1942. while ( achBuf[i] != 0 )
  1943. {
  1944. switch ( toupper(achBuf[i++]) )
  1945. {
  1946. case 'A':
  1947. g_CDF.dwReboot |= REBOOT_ALWAYS;
  1948. g_CDF.dwReboot |= REBOOT_YES;
  1949. break;
  1950. case 'S':
  1951. g_CDF.dwReboot |= REBOOT_SILENT;
  1952. break;
  1953. case 'N':
  1954. g_CDF.dwReboot &= ~(REBOOT_YES);
  1955. break;
  1956. case 'I':
  1957. g_CDF.dwReboot &= ~(REBOOT_ALWAYS);
  1958. g_CDF.dwReboot |= REBOOT_YES;
  1959. break;
  1960. default:
  1961. break;
  1962. }
  1963. }
  1964. // get package install space
  1965. g_CDF.cbPackInstSpace = MyGetPrivateProfileInt( SEC_OPTIONS, KEY_PACKINSTSPACE, 0, g_szOverideSec );
  1966. // use CDFStrInfo table to do read for a list of key strings
  1967. arraySize = ARRAY_SIZE( CDFStrInfo );
  1968. for ( i=0; i<arraySize; i++ )
  1969. {
  1970. if ( MyGetPrivateProfileString( CDFStrInfo[i].lpSec, CDFStrInfo[i].lpKey,
  1971. CDFStrInfo[i].lpDef, CDFStrInfo[i].lpBuf,
  1972. CDFStrInfo[i].uSize, CDFStrInfo[i].lpOverideSec ) < 0 )
  1973. goto EXIT;
  1974. if ( CDFStrInfo[i].lpFlag )
  1975. {
  1976. if ( CDFStrInfo[i].lpBuf[0] )
  1977. *(CDFStrInfo[i].lpFlag) = TRUE;
  1978. else
  1979. *(CDFStrInfo[i].lpFlag) = FALSE;
  1980. }
  1981. }
  1982. // generate cab name properly!
  1983. if ( (g_CDF.uPackPurpose == IDC_CMD_CREATECAB ) &&
  1984. !MakeCabName( hDlg, g_CDF.achTarget, g_CDF.achCABPath ) )
  1985. goto EXIT;
  1986. // Read the file list, adding it to our Item list as we go along.
  1987. if ( MyGetPrivateProfileString( SEC_OPTIONS, KEY_FILELIST, "", g_CDF.achSourceFile, sizeof(g_CDF.achSourceFile), g_szOverideSec ) <= 0 )
  1988. {
  1989. uErrid = IDS_ERR_NOSOURCEFILE;
  1990. goto EXIT;
  1991. }
  1992. ulFileSize = __max( FileSize( g_CDF.achFilename ), FileSize( g_szOverideCDF ) );
  1993. //BUGBUG: be smart about buf size to allocate
  1994. szFileList = (LPSTR) LocalAlloc( LPTR, ulFileSize );
  1995. szFileListKeys = (LPSTR) LocalAlloc( LPTR, ulFileSize );
  1996. if ( !szFileList || !szFileListKeys )
  1997. {
  1998. uErrid = IDS_ERR_NO_MEMORY;
  1999. goto EXIT;
  2000. }
  2001. lpSave1 = szFileList;
  2002. lpSave2 = szFileListKeys;
  2003. MyGetPrivateProfileString( g_CDF.achSourceFile, NULL, "", szFileListKeys, ulFileSize/2, g_CDF.achSourceFile );
  2004. while ( *szFileListKeys )
  2005. {
  2006. lstrcpy( achBuf, szFileListKeys );
  2007. szFileListKeys += lstrlen(szFileListKeys);
  2008. szFileListKeys++; // jump over the single '\0'
  2009. MyGetPrivateProfileString( g_CDF.achSourceFile, achBuf, "", szPath, sizeof(szPath), g_CDF.achSourceFile );
  2010. lRet = MyGetPrivateProfileSection( achBuf, szFileList, ulFileSize, TRUE );
  2011. if ( lRet == 0 )
  2012. {
  2013. // the current CDF format is not match with OS version
  2014. uErrid = IDS_ERR_CDFFORMAT;
  2015. LocalFree( lpSave1 );
  2016. LocalFree( lpSave2 );
  2017. goto EXIT;
  2018. }
  2019. else if ( lRet < 0 )
  2020. {
  2021. uErrid = IDS_ERR_INVALID_CDF;
  2022. LocalFree( lpSave1 );
  2023. LocalFree( lpSave2 );
  2024. goto EXIT;
  2025. }
  2026. // make sure there is a '\' at the end of path
  2027. AddPath( szPath, "" );
  2028. while ( *szFileList )
  2029. {
  2030. FormStrWithoutPlaceHolders( achBuf, szFileList, sizeof(achBuf) );
  2031. pMyItem = AddItem( achBuf, szPath );
  2032. szFileList += lstrlen( szFileList );
  2033. szFileList++; // jump over the single '\0'
  2034. }
  2035. szFileList = lpSave1;
  2036. }
  2037. LocalFree( lpSave1 );
  2038. LocalFree( lpSave2 );
  2039. // get the target version check info
  2040. //
  2041. if ( g_CDF.pVerInfo )
  2042. {
  2043. lRet = MyGetPrivateProfileString( SEC_OPTIONS, KEY_NTVERCHECK, "", achBuf, sizeof(achBuf), g_szOverideSec );
  2044. if ( (lRet<0) || !ParseTargetVerCheck( achBuf, &(g_CDF.pVerInfo->ntVerCheck), szPath, FALSE ) )
  2045. {
  2046. goto EXIT;
  2047. }
  2048. SetAuthorStr( szPath, &(g_CDF.pVerInfo->ntVerCheck.dwstrOffs) );
  2049. lRet = MyGetPrivateProfileString( SEC_OPTIONS, KEY_WIN9XVERCHECK, "", achBuf, sizeof(achBuf), g_szOverideSec );
  2050. if ( (lRet < 0) || !ParseTargetVerCheck( achBuf, &(g_CDF.pVerInfo->win9xVerCheck), szPath, FALSE ) )
  2051. {
  2052. goto EXIT;
  2053. }
  2054. SetAuthorStr( szPath, &(g_CDF.pVerInfo->win9xVerCheck.dwstrOffs) );
  2055. lRet = MyGetPrivateProfileString( SEC_OPTIONS, KEY_SYSFILE, "", achBuf, sizeof(achBuf), g_szOverideSec );
  2056. if ( lRet < 0 )
  2057. goto EXIT;
  2058. if ( achBuf[0] && g_CDF.pVerInfo->dwNumFiles )
  2059. {
  2060. PVERCHECK pVerChk = NULL;
  2061. pVerChk = (PVERCHECK) LocalAlloc( LPTR, g_CDF.pVerInfo->dwNumFiles * (sizeof(VERCHECK)) );
  2062. if ( !pVerChk )
  2063. {
  2064. uErrid = IDS_ERR_NO_MEMORY;
  2065. goto EXIT;
  2066. }
  2067. if ( achBuf[0] == '@' )
  2068. {
  2069. char szLine[MAX_PATH];
  2070. PVERCHECK pVerTmp;
  2071. i = 0;
  2072. pVerTmp = pVerChk;
  2073. MyGetPrivateProfileString( &achBuf[1], NULL, "", szPath, sizeof(szPath), g_szOverideSec );
  2074. while ( szPath[i] )
  2075. {
  2076. MyGetPrivateProfileString( &achBuf[1], &szPath[i], "", szLine, sizeof(szLine), g_szOverideSec );
  2077. if ( !ParseTargetFiles( szLine, pVerTmp ) )
  2078. {
  2079. LocalFree( pVerChk );
  2080. uErrid = IDS_ERR_VCHKFILE;
  2081. goto EXIT;
  2082. }
  2083. pVerTmp++;
  2084. i += lstrlen( &szPath[i] ) + 1;
  2085. }
  2086. }
  2087. else if ( !ParseTargetFiles( achBuf, pVerChk ) )
  2088. {
  2089. LocalFree( pVerChk );
  2090. uErrid = IDS_ERR_VCHKFILE;
  2091. goto EXIT;
  2092. }
  2093. // up to now all the strings have been processed. Put the File data into the struct
  2094. //
  2095. memcpy( (g_CDF.pVerInfo->szBuf + g_CDF.pVerInfo->dwFileOffs), pVerChk, g_CDF.pVerInfo->dwNumFiles * sizeof(VERCHECK) );
  2096. LocalFree( pVerChk );
  2097. }
  2098. g_CDF.pVerInfo->dwSize = sizeof(TARGETVERINFO) + g_CDF.pVerInfo->dwFileOffs + sizeof(VERCHECK)*g_CDF.pVerInfo->dwNumFiles;
  2099. }
  2100. // make sure the target file path exist
  2101. MakeDirectory( NULL, g_CDF.achTarget, FALSE );
  2102. // if it is LFN command from FileList, make it consistant with filename in the CAB
  2103. //
  2104. MyProcessLFNCmd( g_CDF.achOrigiInstallCmd, g_CDF.achInstallCmd );
  2105. MyProcessLFNCmd( g_CDF.achOrigiPostInstCmd, g_CDF.achPostInstCmd );
  2106. MyProcessLFNCmd( g_CDF.szOrigiAdmQCmd, g_CDF.szAdmQCmd );
  2107. MyProcessLFNCmd( g_CDF.szOrigiUsrQCmd, g_CDF.szUsrQCmd );
  2108. // after file-list has been read in
  2109. // set EXTRACTOPT_ADVDLL if needed, shorten the command name if needed
  2110. // if the .INF file is not from the file list, return FALSE
  2111. //
  2112. if ( (g_CDF.uPackPurpose == IDC_CMD_RUNCMD) &&
  2113. ( !CheckAdvBit( g_CDF.achOrigiInstallCmd ) ||
  2114. !CheckAdvBit( g_CDF.achOrigiPostInstCmd ) ||
  2115. !CheckAdvBit( g_CDF.szOrigiAdmQCmd ) ||
  2116. !CheckAdvBit( g_CDF.szOrigiUsrQCmd ) ) )
  2117. {
  2118. goto EXIT;
  2119. }
  2120. // successful path
  2121. bRetVal = TRUE;
  2122. EXIT:
  2123. if ( uErrid )
  2124. ErrorMsg( hDlg, uErrid );
  2125. return bRetVal;
  2126. }
  2127. #define MAXDISK_SIZE "1.44M"
  2128. #define CDROM_SIZE "CDROM"
  2129. // define
  2130. //***************************************************************************
  2131. //* *
  2132. //* NAME: WriteDDF *
  2133. //* *
  2134. //* SYNOPSIS: Writes out a Diamond Directive File. *
  2135. //* *
  2136. //* REQUIRES: hDlg: dialog window *
  2137. //* *
  2138. //* RETURNS: Nothing *
  2139. //* *
  2140. //***************************************************************************
  2141. BOOL WriteDDF( HWND hDlg )
  2142. {
  2143. HANDLE hFile;
  2144. DWORD dwAttr;
  2145. DWORD dwBytes;
  2146. PMYITEM pMyItem;
  2147. CHAR achHeader[256];
  2148. LPSTR szTempLine;
  2149. BOOL fReturn = TRUE;
  2150. CHAR achShortPath[MAX_PATH];
  2151. int i, arraySize;
  2152. LPSTR lpCurrLine;
  2153. LPSTR lpFName;
  2154. // These are the lines that will be written out.
  2155. CHAR achLine1[] = ".Set CabinetNameTemplate=%s\r\n";
  2156. CHAR achLine2[] = ".Set CompressionType=%s\r\n";
  2157. CHAR achLine3[] = ".Set CompressionLevel=%u\r\n";
  2158. CHAR achLine4[] = ".Set InfFileName=%s\r\n";
  2159. CHAR achLine5[] = ".Set RptFileName=%s\r\n";
  2160. CHAR achLine6[] = ".Set MaxDiskSize=%s\r\n";
  2161. CHAR achLine7[] = ".Set ReservePerCabinetSize=%s\r\n";
  2162. CHAR achLine8[] = ".Set InfCabinetLineFormat=""*cab#*=""%s"",""*cabfile*"",0""\r\n";
  2163. CHAR achLine9[] = ".Set Compress=%s\r\n";
  2164. CHAR achLine10[] = ".Set CompressionMemory=%d\r\n";
  2165. PSTR pszDDFLine[] = { // 11 lines no param needed
  2166. ".Set DiskDirectoryTemplate=\r\n",
  2167. ".Set Cabinet=ON\r\n",
  2168. ".Set MaxCabinetSize=999999999\r\n",
  2169. ".Set InfDiskHeader=\r\n",
  2170. ".Set InfDiskLineFormat=\r\n",
  2171. ".Set InfCabinetHeader=""[SourceDisksNames]""\r\n",
  2172. ".Set InfFileHeader=""""\r\n",
  2173. ".Set InfFileHeader1=""[SourceDisksFiles]""\r\n",
  2174. ".Set InfFileLineFormat=""*file*=*cab#*,,*size*,*csum*""\r\n",
  2175. NULL,
  2176. };
  2177. hFile = CreateFile( g_CDF.achDDF, GENERIC_WRITE, 0, NULL,
  2178. CREATE_ALWAYS,
  2179. FILE_ATTRIBUTE_NORMAL, NULL );
  2180. if ( hFile == INVALID_HANDLE_VALUE ) {
  2181. ErrorMsg( hDlg, IDS_ERR_OPEN_DDF );
  2182. return FALSE;
  2183. }
  2184. // allocate a working buffer once which is big enough for every line
  2185. //
  2186. szTempLine = (LPSTR) LocalAlloc( LPTR, MAX_STRING );
  2187. if ( ! szTempLine ) {
  2188. ErrorMsg( hDlg, IDS_ERR_NO_MEMORY );
  2189. CloseHandle( hFile );
  2190. return FALSE;
  2191. }
  2192. LoadSz( IDS_DDF_HEADER, achHeader, sizeof(achHeader) );
  2193. WriteFile( hFile, achHeader, lstrlen( achHeader ), &dwBytes, NULL );
  2194. wsprintf( szTempLine, achLine1, g_CDF.achCABPath );
  2195. WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
  2196. wsprintf( szTempLine, achLine2, g_CDF.szCompressionType );
  2197. WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
  2198. wsprintf( szTempLine, achLine3, g_CDF.uCompressionLevel );
  2199. WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
  2200. wsprintf( szTempLine, achLine4, g_CDF.achINF );
  2201. WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
  2202. wsprintf( szTempLine, achLine5, g_CDF.achRPT );
  2203. WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
  2204. if ( g_CDF.uExtractOpt & CAB_FIXEDSIZE )
  2205. lpCurrLine = MAXDISK_SIZE;
  2206. else
  2207. lpCurrLine = CDROM_SIZE;
  2208. wsprintf( szTempLine, achLine6, lpCurrLine );
  2209. WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
  2210. if ( g_CDF.uExtractOpt & CAB_RESVSP2K )
  2211. i = 1;
  2212. else if ( g_CDF.uExtractOpt & CAB_RESVSP4K )
  2213. i = 2;
  2214. else if ( g_CDF.uExtractOpt & CAB_RESVSP6K )
  2215. i = 3;
  2216. else
  2217. i = 0;
  2218. wsprintf( szTempLine, achLine7, pResvSizes[i] );
  2219. WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
  2220. wsprintf( szTempLine, achLine8, g_CDF.szCabLabel );
  2221. WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
  2222. MyGetPrivateProfileString( SEC_OPTIONS, KEY_COMPRESS, "on", achShortPath, sizeof(achShortPath), g_szOverideSec );
  2223. wsprintf( szTempLine, achLine9, achShortPath );
  2224. WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
  2225. i = MyGetPrivateProfileInt( SEC_OPTIONS, KEY_COMPRESSMEMORY, 21, g_szOverideSec );
  2226. if ( i <= 0 )
  2227. i = 21;
  2228. wsprintf( szTempLine, achLine10, i );
  2229. WriteFile( hFile, szTempLine, lstrlen( szTempLine ), &dwBytes, NULL );
  2230. i = 0;
  2231. while ( pszDDFLine[i] )
  2232. {
  2233. WriteFile( hFile, pszDDFLine[i], lstrlen( pszDDFLine[i] ), &dwBytes, NULL );
  2234. i++;
  2235. }
  2236. pMyItem = GetFirstItem();
  2237. while ( fReturn && ! LastItem( pMyItem ) ) {
  2238. lstrcpy( szTempLine, GetItemSz( pMyItem, 1 ) );
  2239. lstrcat( szTempLine, GetItemSz( pMyItem, 0 ) );
  2240. dwAttr = GetFileAttributes( szTempLine );
  2241. if ( ( dwAttr == -1 ) || ( dwAttr & FILE_ATTRIBUTE_DIRECTORY ) ) {
  2242. ErrorMsg1Param( hDlg, IDS_ERR_FILE_NOT_FOUND2, szTempLine );
  2243. LocalFree( szTempLine );
  2244. CloseHandle( hFile );
  2245. return FALSE;
  2246. }
  2247. if ( g_CDF.uExtractOpt & EXTRACTOPT_LFN_YES )
  2248. {
  2249. lstrcpy( achShortPath, "\"" );
  2250. lstrcat( achShortPath, szTempLine );
  2251. lstrcat( achShortPath, "\"" );
  2252. }
  2253. else
  2254. {
  2255. if ( ! GetShortPathName( szTempLine, achShortPath,
  2256. sizeof(achShortPath) ) )
  2257. {
  2258. ErrorMsg( hDlg, IDS_ERR_SHORT_PATH );
  2259. LocalFree( szTempLine );
  2260. CloseHandle( hFile );
  2261. return FALSE;
  2262. }
  2263. }
  2264. WriteFile( hFile, achShortPath, lstrlen(achShortPath), &dwBytes, NULL );
  2265. fReturn = WriteFile( hFile, "\r\n", lstrlen("\r\n"), &dwBytes, NULL );
  2266. pMyItem = GetNextItem( pMyItem );
  2267. }
  2268. if ( fReturn && g_CDF.uExtractOpt & EXTRACTOPT_ADVDLL )
  2269. {
  2270. SYSTEM_INFO SystemInfo;
  2271. int ix86Processor;
  2272. GetSystemInfo( &SystemInfo );
  2273. ix86Processor = MyGetPrivateProfileInt( SEC_OPTIONS, KEY_CROSSPROCESSOR, -1, g_szOverideSec );
  2274. if ( (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) &&
  2275. (ix86Processor != 0) ||
  2276. (SystemInfo.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL) &&
  2277. (ix86Processor == 1) )
  2278. {
  2279. arraySize = ARRAY_SIZE( AdvDlls );
  2280. }
  2281. else
  2282. {
  2283. arraySize = 1;
  2284. }
  2285. // add 3 advanced DLLS for handling OCX regiester or CustomDestination
  2286. for ( i = 0; (i<arraySize) && fReturn; i++ )
  2287. {
  2288. if ( !IsDuplicate( NULL, 0, AdvDlls[i], FALSE) )
  2289. {
  2290. if ( !GetFileFromModulePath( AdvDlls[i], achShortPath, sizeof(achShortPath) ) )
  2291. {
  2292. ErrorMsg1Param( hDlg, IDS_ERR_FILE_NOT_FOUND, achShortPath );
  2293. LocalFree( szTempLine );
  2294. CloseHandle( hFile );
  2295. return FALSE;
  2296. }
  2297. lstrcpy( szTempLine, "\"" );
  2298. lstrcat( szTempLine, achShortPath );
  2299. lstrcat( szTempLine, "\"" );
  2300. WriteFile( hFile, szTempLine, lstrlen(szTempLine), &dwBytes, NULL );
  2301. fReturn = WriteFile( hFile, "\r\n", strlen("\r\n"), &dwBytes, NULL );
  2302. }
  2303. }
  2304. }
  2305. LocalFree( szTempLine );
  2306. CloseHandle( hFile );
  2307. if ( fReturn == FALSE ) {
  2308. ErrorMsg( hDlg, IDS_ERR_WRITE_DDF );
  2309. return FALSE;
  2310. } else {
  2311. return TRUE;
  2312. }
  2313. }
  2314. //***************************************************************************
  2315. //* *
  2316. //* NAME: MasskePackage *
  2317. //* *
  2318. //* SYNOPSIS: Makes the full package (CAB and EXE). *
  2319. //* *
  2320. //* REQUIRES: hDlg: Handle to the dialog *
  2321. //* *
  2322. //* RETURNS: BOOL: *
  2323. //* *
  2324. //***************************************************************************
  2325. BOOL MakePackage( HWND hDlg )
  2326. {
  2327. CHAR achDrive[_MAX_DRIVE];
  2328. CHAR achDir[_MAX_DIR];
  2329. CHAR achStatus[MAX_STRING];
  2330. CHAR szExt[6];
  2331. BOOL fReturn = TRUE;
  2332. PSTR pTmp;
  2333. // Build the paths to the files, using the target path as a
  2334. // template. We create the DDF, CAB and INF file in the
  2335. // same directory as the target file.
  2336. _splitpath( g_CDF.achTarget, achDrive, achDir, g_CDF.achTargetBase, szExt);
  2337. lstrcpy( g_CDF.achTargetPath, achDrive );
  2338. lstrcat( g_CDF.achTargetPath, achDir );
  2339. lstrcpy( g_CDF.achDDF, g_CDF.achTargetPath );
  2340. wsprintf( achStatus, CABPACK_TMPFILE, g_CDF.achTargetBase, EXT_DDF );
  2341. AddPath( g_CDF.achDDF, achStatus );
  2342. if ( g_CDF.achINF[0] == 0 )
  2343. {
  2344. lstrcpy( g_CDF.achINF, g_CDF.achTargetPath );
  2345. wsprintf( achStatus, CABPACK_INFFILE, g_CDF.achTargetBase );
  2346. AddPath( g_CDF.achINF, achStatus );
  2347. }
  2348. lstrcpy( g_CDF.achRPT, g_CDF.achTargetPath );
  2349. wsprintf( achStatus, CABPACK_TMPFILE, g_CDF.achTargetBase, EXT_RPT );
  2350. AddPath( g_CDF.achRPT, achStatus );
  2351. if ( g_CDF.uPackPurpose != IDC_CMD_CREATECAB )
  2352. {
  2353. wsprintf( achStatus, CABPACK_TMPFILE, g_CDF.achTargetBase, EXT_CAB );
  2354. lstrcpy( g_CDF.achCABPath, g_CDF.achTargetPath );
  2355. AddPath( g_CDF.achCABPath, achStatus );
  2356. g_CDF.szCompressionType = achLZX;
  2357. g_CDF.uCompressionLevel = 7;
  2358. }
  2359. if ( g_CDF.fSave ) {
  2360. if ( ! WriteCDF( hDlg ) ) {
  2361. LoadSz( IDS_STATUS_ERROR_CDF, achStatus, sizeof(achStatus) );
  2362. Status( hDlg, IDC_MEDIT_STATUS, achStatus );
  2363. fReturn = FALSE;
  2364. goto done;
  2365. }
  2366. }
  2367. if ( ! MakeCAB( hDlg ) ) {
  2368. LoadSz( IDS_STATUS_ERROR_CAB, achStatus, sizeof(achStatus) );
  2369. Status( hDlg, IDC_MEDIT_STATUS, achStatus );
  2370. fReturn = FALSE;
  2371. goto done;
  2372. }
  2373. // if use choose to create CAB file only, MakeEXE() is not needed
  2374. //
  2375. if ( g_CDF.uPackPurpose != IDC_CMD_CREATECAB )
  2376. {
  2377. if ( ! MakeEXE( hDlg ) ) {
  2378. LoadSz( IDS_STATUS_ERROR_EXE, achStatus, sizeof(achStatus) );
  2379. Status( hDlg, IDC_MEDIT_STATUS, achStatus );
  2380. fReturn = FALSE;
  2381. goto done;
  2382. }
  2383. if ( MyGetPrivateProfileInt( SEC_OPTIONS, KEY_KEEPCABINET, 0, g_szOverideSec )
  2384. == 0 )
  2385. {
  2386. DeleteFile( g_CDF.achCABPath );
  2387. }
  2388. }
  2389. LoadSz( IDS_STATUS_DONE, achStatus, sizeof(achStatus) );
  2390. Status( hDlg, IDC_MEDIT_STATUS, achStatus );
  2391. done:
  2392. // if failure happen, clean the filewriteout flag to prepare for next CDF out
  2393. if ( !fReturn )
  2394. CleanFileListWriteFlag();
  2395. return fReturn;
  2396. }
  2397. //***************************************************************************
  2398. //* *
  2399. //* NAME: MakeCAB *
  2400. //* *
  2401. //* SYNOPSIS: Makes the cabinet file if it is out of date. *
  2402. //* *
  2403. //* REQUIRES: hDlg: Handle to the dialog *
  2404. //* *
  2405. //* RETURNS: BOOL: *
  2406. //* *
  2407. //***************************************************************************
  2408. BOOL MakeCAB( HWND hDlg )
  2409. {
  2410. CHAR achMessage[512]; // Used in FormatMessage()
  2411. DWORD dwError; // Used in GetLastError()
  2412. LPSTR szCommand;
  2413. HANDLE hFile;
  2414. LPSTR szTempFile;
  2415. ULONG ulFileSize;
  2416. LPSTR szFileContents;
  2417. DWORD dwBytes;
  2418. CHAR achDiamondExe[MAX_PATH];
  2419. CHAR achDiamondPath[MAX_PATH];
  2420. CHAR achStatus[MAX_STRING];
  2421. BOOL fFilesModified = FALSE;
  2422. DWORD dwExitCode;
  2423. STARTUPINFO sti;
  2424. PROCESS_INFORMATION pi; // Setup Process Launch
  2425. WIN32_FIND_DATA FindFileData;
  2426. DWORD dwCreationFlags;
  2427. //FindClose( hFile );
  2428. LoadSz( IDS_STATUS_MAKE_CAB, achStatus, sizeof(achStatus) );
  2429. Status( hDlg, IDC_MEDIT_STATUS, achStatus );
  2430. if ( ! WriteDDF( hDlg ) ) {
  2431. return FALSE;
  2432. }
  2433. // Make the CAB file
  2434. if ( lstrcmpi( g_CDF.szCompressionType, achQUANTUM ) == 0 ) {
  2435. lstrcpy( achDiamondExe, DIAMONDEXE );
  2436. } else {
  2437. lstrcpy( achDiamondExe, DIANTZEXE );
  2438. }
  2439. if ( !GetFileFromModulePath( achDiamondExe, achDiamondPath, sizeof(achDiamondPath) ) )
  2440. {
  2441. ErrorMsg1Param( hDlg, IDS_ERR_FILE_NOT_FOUND, achDiamondPath );
  2442. return FALSE;
  2443. }
  2444. // The +5 is to handle the " /f " in the wsprintf format string
  2445. // and for the terminating null char.
  2446. //
  2447. szCommand = (LPSTR) LocalAlloc( LPTR, lstrlen(achDiamondPath)
  2448. + lstrlen(g_CDF.achDDF)
  2449. + 10 );
  2450. if ( ! szCommand ) {
  2451. ErrorMsg( hDlg, IDS_ERR_NO_MEMORY );
  2452. return FALSE;
  2453. }
  2454. wsprintf( szCommand, "%s /f \"%s\"", achDiamondPath, g_CDF.achDDF );
  2455. memset( &sti, 0, sizeof(sti) );
  2456. sti.cb = sizeof(STARTUPINFO);
  2457. if (g_wRunDiamondMinimized) {
  2458. sti.dwFlags = STARTF_USESHOWWINDOW;
  2459. sti.wShowWindow = SW_MINIMIZE;
  2460. }
  2461. else if (g_wQuietMode || g_wSilentMode) {
  2462. sti.dwFlags = STARTF_USESHOWWINDOW;
  2463. sti.wShowWindow = SW_HIDE;
  2464. }
  2465. if (!g_wQuietMode)
  2466. dwCreationFlags = 0;
  2467. else
  2468. dwCreationFlags = CREATE_NO_WINDOW;
  2469. if ( CreateProcess( NULL, szCommand, NULL, NULL, FALSE,
  2470. dwCreationFlags, NULL, NULL, &sti, &pi ) )
  2471. {
  2472. CloseHandle( pi.hThread );
  2473. MsgWaitForMultipleObjectsLoop( pi.hProcess );
  2474. GetExitCodeProcess( pi.hProcess, &dwExitCode );
  2475. CloseHandle( pi.hProcess );
  2476. } else {
  2477. dwError = GetLastError();
  2478. FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0,
  2479. achMessage, sizeof(achMessage), NULL );
  2480. ErrorMsg2Param( hDlg, IDS_ERR_START_DIAMOND, szCommand,
  2481. achMessage );
  2482. }
  2483. LocalFree( szCommand );
  2484. Status( hDlg, IDC_MEDIT_STATUS, "---\r\n" );
  2485. hFile = FindFirstFile( g_CDF.achRPT, &FindFileData );
  2486. ulFileSize = (FindFileData.nFileSizeHigh * MAXDWORD)
  2487. + FindFileData.nFileSizeLow;
  2488. FindClose( hFile );
  2489. hFile = CreateFile( g_CDF.achRPT, GENERIC_READ, 0, NULL,
  2490. OPEN_EXISTING, 0, NULL );
  2491. if ( hFile == INVALID_HANDLE_VALUE ) {
  2492. ErrorMsg1Param( hDlg, IDS_ERR_OPEN_RPT, g_CDF.achRPT );
  2493. return FALSE;
  2494. }
  2495. szFileContents = (LPSTR) LocalAlloc( LPTR, ulFileSize + 1 );
  2496. if ( ! szFileContents ) {
  2497. ErrorMsg( hDlg, IDS_ERR_NO_MEMORY );
  2498. return FALSE;
  2499. }
  2500. if ( ! ReadFile( hFile, szFileContents, ulFileSize,
  2501. &dwBytes, NULL ) ) {
  2502. ErrorMsg1Param( hDlg, IDS_ERR_READ_RPT, g_CDF.achRPT );
  2503. return FALSE;
  2504. }
  2505. CloseHandle( hFile );
  2506. Status( hDlg, IDC_MEDIT_STATUS, szFileContents );
  2507. LocalFree( szFileContents );
  2508. Status( hDlg, IDC_MEDIT_STATUS, "---\r\n" );
  2509. if ( MyGetPrivateProfileInt( SEC_OPTIONS, KEY_KEEPCABINET, 0, g_szOverideSec )
  2510. == 0 )
  2511. {
  2512. DeleteFile( g_CDF.achDDF );
  2513. }
  2514. if ( !(g_CDF.uExtractOpt & CAB_FIXEDSIZE) )
  2515. DeleteFile( g_CDF.achINF );
  2516. DeleteFile( g_CDF.achRPT );
  2517. return TRUE;
  2518. }
  2519. //***************************************************************************
  2520. //* *
  2521. //* NAME: MakeEXE *
  2522. //* *
  2523. //* SYNOPSIS: Copies WEXTRACT.EXE to the target filename and adds *
  2524. //* resources to it. *
  2525. //* *
  2526. //* REQUIRES: hDlg: Handle to the dialog *
  2527. //* *
  2528. //* RETURNS: BOOL: *
  2529. //* *
  2530. //***************************************************************************
  2531. BOOL MakeEXE( HWND hDlg )
  2532. {
  2533. HANDLE hUpdate;
  2534. CHAR achMessage[512]; // Used in FormatMessage()
  2535. DWORD dwError; // Used in GetLastError()
  2536. PMYITEM pMyItem;
  2537. HANDLE hFile;
  2538. LPSTR szTempFile;
  2539. ULONG ulFileSize;
  2540. LPSTR szFileContents;
  2541. DWORD dwBytes;
  2542. CHAR achWExtractPath[MAX_PATH];
  2543. CHAR achStatus[MAX_STRING];
  2544. WIN32_FIND_DATA FindFileData;
  2545. DWORD dwFileSizes[MAX_NUMCLUSTERS+1]; // store the filesize in each cluster sizes.
  2546. // the last of dwFileSizes is used to store real
  2547. // total file sizes later used for calculate
  2548. // progress bar in wextract
  2549. DWORD clusterCurrSize;
  2550. int i;
  2551. UINT idErr = IDS_ERR_UPDATE_RESOURCE;
  2552. // get ExtractorStub based on CDF specification. Wextract.exe is default one.
  2553. //
  2554. LoadSz( IDS_STATUS_MAKE_EXE, achStatus, sizeof(achStatus) );
  2555. Status( hDlg, IDC_MEDIT_STATUS, achStatus );
  2556. if ( !MyGetPrivateProfileString( SEC_OPTIONS, KEY_STUBEXE, WEXTRACTEXE, achStatus, sizeof(achStatus), g_szOverideSec ) )
  2557. {
  2558. lstrcpy( achStatus, WEXTRACTEXE );
  2559. }
  2560. if ( !GetFileFromModulePath(achStatus, achWExtractPath, sizeof(achWExtractPath) ) )
  2561. {
  2562. ErrorMsg1Param( hDlg, IDS_ERR_FILE_NOT_FOUND, achWExtractPath );
  2563. return FALSE;
  2564. }
  2565. if ( ! CopyFile( achWExtractPath, g_CDF.achTarget, FALSE ) ) {
  2566. dwError = GetLastError();
  2567. FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0,
  2568. achMessage, sizeof(achMessage), NULL );
  2569. ErrorMsg2Param( hDlg, IDS_ERR_CREATE_TARGET, g_CDF.achTarget,
  2570. achMessage );
  2571. return FALSE;
  2572. }
  2573. // make sure the targe file is not read-only file
  2574. SetFileAttributes( g_CDF.achTarget, FILE_ATTRIBUTE_NORMAL );
  2575. // Initialize the EXE file for resource editing
  2576. hUpdate = LocalBeginUpdateResource( g_CDF.achTarget, FALSE );
  2577. if ( hUpdate == NULL ) {
  2578. ErrorMsg1Param( hDlg, IDS_ERR_INIT_RESOURCE, g_CDF.achTarget );
  2579. return FALSE;
  2580. }
  2581. //*******************************************************************
  2582. //* TITLE ***********************************************************
  2583. //*******************************************************************
  2584. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2585. achResTitle, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2586. g_CDF.achTitle, lstrlen( g_CDF.achTitle ) + 1 ) == FALSE )
  2587. {
  2588. goto ERR_OUT;
  2589. }
  2590. //*******************************************************************
  2591. //* PROMPT **********************************************************
  2592. //*******************************************************************
  2593. if ( g_CDF.fPrompt ) {
  2594. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2595. achResUPrompt, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2596. g_CDF.achPrompt, lstrlen( g_CDF.achPrompt ) + 1 ) == FALSE )
  2597. {
  2598. goto ERR_OUT;
  2599. }
  2600. } else {
  2601. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2602. achResUPrompt, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2603. achResNone, lstrlen( achResNone ) + 1 ) == FALSE )
  2604. {
  2605. goto ERR_OUT;
  2606. }
  2607. }
  2608. //*******************************************************************
  2609. //* LICENSE FILE ****************************************************
  2610. //*******************************************************************
  2611. if ( g_CDF.fLicense ) {
  2612. hFile = FindFirstFile( g_CDF.achLicense, &FindFileData );
  2613. ulFileSize = (FindFileData.nFileSizeHigh * MAXDWORD)
  2614. + FindFileData.nFileSizeLow;
  2615. FindClose( hFile );
  2616. hFile = CreateFile( g_CDF.achLicense, GENERIC_READ, 0, NULL,
  2617. OPEN_EXISTING, 0, NULL );
  2618. if ( hFile == INVALID_HANDLE_VALUE ) {
  2619. ErrorMsg1Param( hDlg, IDS_ERR_OPEN_LICENSE, g_CDF.achLicense );
  2620. DeleteFile(g_CDF.achTarget);
  2621. return FALSE;
  2622. }
  2623. szFileContents = (LPSTR) LocalAlloc( LPTR, ulFileSize + 1 );
  2624. if ( ! szFileContents ) {
  2625. ErrorMsg( hDlg, IDS_ERR_NO_MEMORY );
  2626. DeleteFile(g_CDF.achTarget);
  2627. return FALSE;
  2628. }
  2629. if ( ! ReadFile( hFile, szFileContents, ulFileSize,
  2630. &dwBytes, NULL ) ) {
  2631. ErrorMsg1Param( hDlg, IDS_ERR_READ_LICENSE, g_CDF.achLicense );
  2632. DeleteFile(g_CDF.achTarget);
  2633. return FALSE;
  2634. }
  2635. CloseHandle( hFile );
  2636. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2637. achResLicense, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2638. szFileContents, ulFileSize+1 ) == FALSE )
  2639. {
  2640. LocalFree( szFileContents );
  2641. goto ERR_OUT;
  2642. }
  2643. LocalFree( szFileContents );
  2644. } else {
  2645. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2646. achResLicense, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2647. achResNone, lstrlen( achResNone ) + 1 ) == FALSE )
  2648. {
  2649. goto ERR_OUT;
  2650. }
  2651. }
  2652. //*******************************************************************
  2653. //* COMMAND *********************************************************
  2654. //*******************************************************************
  2655. if ( g_CDF.uPackPurpose != IDC_CMD_EXTRACT )
  2656. {
  2657. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2658. achResRunProgram, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
  2659. g_CDF.achInstallCmd, lstrlen(g_CDF.achInstallCmd)+1 ) == FALSE )
  2660. {
  2661. goto ERR_OUT;
  2662. }
  2663. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2664. achResPostRunCmd, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
  2665. g_CDF.achPostInstCmd, lstrlen(g_CDF.achPostInstCmd)+1 ) == FALSE )
  2666. {
  2667. goto ERR_OUT;
  2668. }
  2669. //write quiet cmds resource
  2670. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2671. achResAdminQCmd, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
  2672. g_CDF.szAdmQCmd[0]?g_CDF.szAdmQCmd : achResNone,
  2673. g_CDF.szAdmQCmd[0]?(lstrlen(g_CDF.szAdmQCmd)+1) : (lstrlen(achResNone)+1) ) == FALSE )
  2674. {
  2675. goto ERR_OUT;
  2676. }
  2677. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2678. achResUserQCmd, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
  2679. g_CDF.szUsrQCmd[0]?g_CDF.szUsrQCmd : achResNone,
  2680. g_CDF.szUsrQCmd[0]?(lstrlen(g_CDF.szUsrQCmd)+1) : (lstrlen(achResNone)+1) ) == FALSE )
  2681. {
  2682. goto ERR_OUT;
  2683. }
  2684. }
  2685. else
  2686. {
  2687. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2688. achResRunProgram, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2689. achResNone, lstrlen( achResNone ) + 1 ) == FALSE )
  2690. {
  2691. goto ERR_OUT;
  2692. }
  2693. }
  2694. //*******************************************************************
  2695. //* SHOW WINDOW *****************************************************
  2696. //*******************************************************************
  2697. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2698. achResShowWindow, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2699. &g_CDF.uShowWindow, sizeof(g_CDF.uShowWindow) ) == FALSE )
  2700. {
  2701. goto ERR_OUT;
  2702. }
  2703. //*******************************************************************
  2704. //* FINISHMSG *******************************************************
  2705. //*******************************************************************
  2706. if ( g_CDF.fFinishMsg ) {
  2707. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2708. achResFinishMsg, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2709. g_CDF.achFinishMsg, lstrlen( g_CDF.achFinishMsg ) + 1 ) == FALSE )
  2710. {
  2711. goto ERR_OUT;
  2712. }
  2713. }
  2714. else
  2715. {
  2716. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2717. achResFinishMsg, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2718. achResNone, lstrlen( achResNone ) + 1 ) == FALSE )
  2719. {
  2720. goto ERR_OUT;
  2721. }
  2722. }
  2723. //*******************************************************************
  2724. //* CABINET *********************************************************
  2725. //*******************************************************************
  2726. hFile = FindFirstFile( g_CDF.achCABPath, &FindFileData );
  2727. ulFileSize = (FindFileData.nFileSizeHigh * MAXDWORD)
  2728. + FindFileData.nFileSizeLow;
  2729. FindClose( hFile );
  2730. hFile = CreateFile( g_CDF.achCABPath, GENERIC_READ, 0, NULL,
  2731. OPEN_EXISTING, 0, NULL );
  2732. if ( hFile == INVALID_HANDLE_VALUE ) {
  2733. ErrorMsg1Param( hDlg, IDS_ERR_OPEN_CAB, g_CDF.achCABPath );
  2734. DeleteFile(g_CDF.achTarget);
  2735. return FALSE;
  2736. }
  2737. szFileContents = (LPSTR) LocalAlloc( LPTR, ulFileSize + 1 );
  2738. if ( ! szFileContents ) {
  2739. idErr = IDS_ERR_NO_MEMORY;
  2740. goto ERR_OUT;
  2741. }
  2742. if ( ! ReadFile( hFile, szFileContents, ulFileSize, &dwBytes, NULL ) ) {
  2743. ErrorMsg1Param( hDlg, IDS_ERR_READ_CAB, g_CDF.achCABPath );
  2744. DeleteFile(g_CDF.achTarget);
  2745. return FALSE;
  2746. }
  2747. CloseHandle( hFile );
  2748. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2749. achResCabinet, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2750. szFileContents, ulFileSize ) == FALSE )
  2751. {
  2752. LocalFree( szFileContents );
  2753. goto ERR_OUT;
  2754. }
  2755. LocalFree( szFileContents );
  2756. //*******************************************************************
  2757. //* FILES ***********************************************************
  2758. //*******************************************************************
  2759. pMyItem = GetFirstItem();
  2760. RtlZeroMemory( dwFileSizes, sizeof(dwFileSizes));
  2761. while ( ! LastItem( pMyItem ) ) {
  2762. szTempFile = (LPSTR) LocalAlloc( LPTR,
  2763. lstrlen( GetItemSz( pMyItem, 0 ) )
  2764. + lstrlen( GetItemSz( pMyItem, 1 ) ) + 1 );
  2765. if ( ! szTempFile ) {
  2766. idErr = IDS_ERR_NO_MEMORY;
  2767. goto ERR_OUT;
  2768. }
  2769. lstrcpy( szTempFile, GetItemSz( pMyItem, 1 ) );
  2770. lstrcat( szTempFile, GetItemSz( pMyItem, 0 ) );
  2771. hFile = FindFirstFile( szTempFile, &FindFileData );
  2772. ulFileSize = (FindFileData.nFileSizeHigh * MAXDWORD)
  2773. + FindFileData.nFileSizeLow;
  2774. FindClose( hFile );
  2775. LocalFree( szTempFile );
  2776. // calculate the file size in different cluster sizes
  2777. clusterCurrSize = CLUSTER_BASESIZE;
  2778. for ( i = 0; i<MAX_NUMCLUSTERS; i++)
  2779. {
  2780. dwFileSizes[i] += ((ulFileSize/clusterCurrSize)*clusterCurrSize +
  2781. (ulFileSize%clusterCurrSize?clusterCurrSize : 0));
  2782. clusterCurrSize = (clusterCurrSize<<1);
  2783. }
  2784. // this size is not allocated size, just real accumulation
  2785. // of the files for later progress bar UI use
  2786. dwFileSizes[MAX_NUMCLUSTERS] += ulFileSize;
  2787. pMyItem = GetNextItem( pMyItem );
  2788. }
  2789. for ( i = 0; i<MAX_NUMCLUSTERS; i++)
  2790. {
  2791. dwFileSizes[i] = (dwFileSizes[i]+1023)/1024; //store in KB
  2792. }
  2793. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2794. achResSize, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2795. dwFileSizes, sizeof(dwFileSizes) ) == FALSE )
  2796. {
  2797. goto ERR_OUT;
  2798. }
  2799. //*******************************************************************
  2800. //* REBOOT *******************************************************
  2801. //*******************************************************************
  2802. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2803. achResReboot, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2804. &g_CDF.dwReboot, sizeof(g_CDF.dwReboot) ) == FALSE )
  2805. {
  2806. goto ERR_OUT;
  2807. }
  2808. //*******************************************************************
  2809. //* EXTRACTOPT ****************************************************
  2810. //*******************************************************************
  2811. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2812. achResExtractOpt, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2813. &g_CDF.uExtractOpt, sizeof(g_CDF.uExtractOpt) ) == FALSE )
  2814. {
  2815. goto ERR_OUT;
  2816. }
  2817. //*******************************************************************
  2818. //* COOKIE ****************************************************
  2819. //*******************************************************************
  2820. if ( g_CDF.lpszCookie && LocalUpdateResource( hUpdate, RT_RCDATA,
  2821. achResOneInstCheck, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2822. g_CDF.lpszCookie, lstrlen(g_CDF.lpszCookie)+1 ) == FALSE )
  2823. {
  2824. goto ERR_OUT;
  2825. }
  2826. //*******************************************************************
  2827. //* PACKINSTSPACE **************************************************
  2828. //*******************************************************************
  2829. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2830. achResPackInstSpace, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2831. &g_CDF.cbPackInstSpace, sizeof(g_CDF.cbPackInstSpace) ) == FALSE )
  2832. {
  2833. goto ERR_OUT;
  2834. }
  2835. // Update the version information. The function calls LocaleUpdateResource.
  2836. if (!DoVersionInfo(hDlg, achWExtractPath, hUpdate))
  2837. {
  2838. idErr = IDS_ERR_VERSION_INFO;
  2839. goto ERR_OUT;
  2840. }
  2841. //*******************************************************************
  2842. //* TARGETVERSION **************************************************
  2843. //*******************************************************************
  2844. if ( g_CDF.pVerInfo )
  2845. {
  2846. if ( LocalUpdateResource( hUpdate, RT_RCDATA,
  2847. achResVerCheck, MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  2848. g_CDF.pVerInfo, g_CDF.pVerInfo->dwSize ) == FALSE )
  2849. {
  2850. goto ERR_OUT;
  2851. }
  2852. }
  2853. //*******************************************************************
  2854. //* DONE ************************************************************
  2855. //*******************************************************************
  2856. // Write out modified EXE
  2857. if ( LocalEndUpdateResource( hUpdate, FALSE ) == FALSE )
  2858. {
  2859. idErr = IDS_ERR_CLOSE_RESOURCE;
  2860. goto ERR_OUT;
  2861. }
  2862. return TRUE;
  2863. ERR_OUT:
  2864. ErrorMsg( hDlg, idErr );
  2865. // error occurs, clean up the uncompleted target file
  2866. DeleteFile(g_CDF.achTarget);
  2867. return FALSE;
  2868. }
  2869. //***************************************************************************
  2870. //* *
  2871. //* NAME: MyOpen *
  2872. //* *
  2873. //* SYNOPSIS: Makes popping up a common file open dialog simpler. *
  2874. //* *
  2875. //* REQUIRES: Some of the members of the OPENFILENAME structure. See *
  2876. //* the docs on OPENFILENAME for more info. *
  2877. //* *
  2878. //* RETURNS: Nothing *
  2879. //* *
  2880. //***************************************************************************
  2881. BOOL MyOpen( HWND hWnd, UINT idFilter, LPSTR szFilename,
  2882. DWORD dwMaxFilename, DWORD dwFlags, INT *nFileOffset,
  2883. INT *nExtOffset, PSTR pszDefExt )
  2884. {
  2885. OPENFILENAME ofn;
  2886. BOOL fResult;
  2887. LPSTR szFilter;
  2888. szFilter = (LPSTR) LocalAlloc( LPTR, MAX_STRING );
  2889. if ( ! szFilter ) {
  2890. ErrorMsg( hWnd, IDS_ERR_NO_MEMORY );
  2891. return FALSE;
  2892. }
  2893. LoadSz( idFilter, szFilter, MAX_STRING );
  2894. ofn.lStructSize = sizeof(OPENFILENAME);
  2895. ofn.hwndOwner = hWnd;
  2896. ofn.hInstance = NULL;
  2897. ofn.lpstrFilter = szFilter;
  2898. ofn.lpstrCustomFilter = NULL;
  2899. ofn.nMaxCustFilter = 0;
  2900. ofn.nFilterIndex = 1;
  2901. ofn.lpstrFile = szFilename;
  2902. ofn.nMaxFile = dwMaxFilename;
  2903. ofn.lpstrFileTitle = NULL;
  2904. ofn.nMaxFileTitle = 0;
  2905. ofn.lpstrInitialDir = g_szInitialDir;
  2906. ofn.lpstrTitle = NULL;
  2907. ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY |
  2908. OFN_PATHMUSTEXIST | OFN_LONGNAMES |
  2909. OFN_NOCHANGEDIR | OFN_EXPLORER |
  2910. OFN_NODEREFERENCELINKS | dwFlags;
  2911. if ( IsOSNT3X() )
  2912. {
  2913. ofn.Flags &= ~OFN_ALLOWMULTISELECT;
  2914. }
  2915. ofn.lpstrDefExt = pszDefExt;
  2916. ofn.lCustData = 0;
  2917. ofn.lpfnHook = NULL;
  2918. ofn.lpTemplateName = NULL;
  2919. fResult = GetOpenFileName( &ofn );
  2920. if ( nFileOffset != NULL ) {
  2921. *nFileOffset = ofn.nFileOffset;
  2922. }
  2923. if ( nExtOffset != NULL ) {
  2924. *nExtOffset = ofn.nFileExtension;
  2925. }
  2926. LocalFree( szFilter );
  2927. return( fResult );
  2928. }
  2929. //***************************************************************************
  2930. //* *
  2931. //* NAME: MySave *
  2932. //* *
  2933. //* SYNOPSIS: Makes popping up a common file save dialog simpler. *
  2934. //* *
  2935. //* REQUIRES: Some of the members of the OPENFILENAME structure. See *
  2936. //* the docs on OPENFILENAME for more info. *
  2937. //* *
  2938. //* RETURNS: Nothing *
  2939. //* *
  2940. //***************************************************************************
  2941. BOOL MySave( HWND hWnd, UINT idFilter, LPSTR szFilename,
  2942. DWORD dwMaxFilename, DWORD dwFlags, INT *nFileOffset,
  2943. INT *nExtOffset, PSTR pszDefExt )
  2944. {
  2945. OPENFILENAME ofn;
  2946. BOOL fResult;
  2947. LPSTR szFilter;
  2948. szFilter = (LPSTR) LocalAlloc( LPTR, MAX_STRING );
  2949. if ( ! szFilter ) {
  2950. ErrorMsg( hWnd, IDS_ERR_NO_MEMORY );
  2951. return FALSE;
  2952. }
  2953. LoadSz( idFilter, szFilter, MAX_STRING );
  2954. ofn.lStructSize = sizeof(OPENFILENAME);
  2955. ofn.hwndOwner = hWnd;
  2956. ofn.hInstance = NULL;
  2957. ofn.lpstrFilter = szFilter;
  2958. ofn.lpstrCustomFilter = NULL;
  2959. ofn.nMaxCustFilter = 0;
  2960. ofn.nFilterIndex = 1;
  2961. ofn.lpstrFile = szFilename;
  2962. ofn.nMaxFile = dwMaxFilename;
  2963. ofn.lpstrFileTitle = NULL;
  2964. ofn.nMaxFileTitle = 0;
  2965. ofn.lpstrInitialDir = NULL;
  2966. ofn.lpstrTitle = NULL;
  2967. ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
  2968. OFN_LONGNAMES | OFN_NOCHANGEDIR | dwFlags;
  2969. ofn.lpstrDefExt = pszDefExt;
  2970. ofn.lCustData = 0;
  2971. ofn.lpfnHook = NULL;
  2972. ofn.lpTemplateName = NULL;
  2973. fResult = GetSaveFileName( &ofn );
  2974. if ( nFileOffset != NULL ) {
  2975. *nFileOffset = ofn.nFileOffset;
  2976. }
  2977. if ( nExtOffset != NULL ) {
  2978. *nExtOffset = ofn.nFileExtension;
  2979. }
  2980. LocalFree( szFilter );
  2981. return( fResult );
  2982. }
  2983. //***************************************************************************
  2984. //* *
  2985. //* NAME: Status *
  2986. //* *
  2987. //* SYNOPSIS: Adds a string to a status list box. *
  2988. //* *
  2989. //* REQUIRES: hDlg: Handle to the dialog *
  2990. //* uID: ID of the list box. *
  2991. //* szStatus: Status string to add. *
  2992. //* *
  2993. //* RETURNS: Nothing *
  2994. //* *
  2995. //***************************************************************************
  2996. VOID Status( HWND hDlg, UINT uID, LPSTR szStatus )
  2997. {
  2998. ULONG ulLength;
  2999. if ( hDlg != NULL ) {
  3000. ulLength = (ULONG)SendDlgItemMessage( hDlg, uID, WM_GETTEXTLENGTH, 0, 0 );
  3001. SendDlgItemMessage( hDlg, uID, EM_SETSEL, ulLength, ulLength );
  3002. SendDlgItemMessage( hDlg, uID, EM_REPLACESEL,
  3003. (WPARAM) FALSE, (LPARAM) szStatus );
  3004. SendDlgItemMessage( hDlg, uID, EM_SCROLLCARET, 0, 0 );
  3005. }
  3006. }
  3007. //***************************************************************************
  3008. //* *
  3009. //* NAME: CompareFunc *
  3010. //* *
  3011. //* SYNOPSIS: Compares two items and returns result. *
  3012. //* *
  3013. //* REQUIRES: lParam1: Pointer to the first item. *
  3014. //* uID: Pointer to the second item. *
  3015. //* lParamSort: Type of sorting to do. *
  3016. //* *
  3017. //* RETURNS: int: -1 if lParam1 goes before lParam2 *
  3018. //* 0 if lParam1 equals lParam2 *
  3019. //* +1 if lParam1 goes after lParam2 *
  3020. //* *
  3021. //* NOTES: For some weird reason, sorting the listview causes a *
  3022. //* really bad GPF (freezes the entire system). For now it's *
  3023. //* not worth the effort to fix it, so sorting is disabled. *
  3024. //* *
  3025. //***************************************************************************
  3026. /*
  3027. int CALLBACK CompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
  3028. {
  3029. PMYITEM pMyItem1 = (PMYITEM) lParam1;
  3030. PMYITEM pMyItem2 = (PMYITEM) lParam2;
  3031. int nReverse = 1;
  3032. UINT uString = 0;
  3033. lParamSort = _SORT_DESCENDING | _SORT_FILENAME;
  3034. if ( lParamSort & _SORT_ASCENDING ) {
  3035. nReverse = -1;
  3036. }
  3037. if ( lParamSort & _SORT_PATH ) {
  3038. uString = 1;
  3039. }
  3040. return ( nReverse * lstrcmp( GetItemSz( pMyItem1, uString ),
  3041. GetItemSz( pMyItem2, uString ) ) );
  3042. }
  3043. */
  3044. //***************************************************************************
  3045. //* *
  3046. //* NAME: InitItemList *
  3047. //* *
  3048. //* SYNOPSIS: Initializes the item list. *
  3049. //* *
  3050. //* REQUIRES: Nothing -- uses the global g_CDF.pTop *
  3051. //* *
  3052. //* RETURNS: Nothing *
  3053. //* *
  3054. //***************************************************************************
  3055. VOID InitItemList()
  3056. {
  3057. g_CDF.pTop = NULL;
  3058. g_CDF.cbFileListNum = 0;
  3059. }
  3060. //***************************************************************************
  3061. //* *
  3062. //* NAME: DeleteAllItems *
  3063. //* *
  3064. //* SYNOPSIS: Deletes all the items from our file list. *
  3065. //* *
  3066. //* REQUIRES: Nothing -- uses the global g_CDF.pTop *
  3067. //* *
  3068. //* RETURNS: Nothing *
  3069. //* *
  3070. //***************************************************************************
  3071. VOID DeleteAllItems()
  3072. {
  3073. PMYITEM pMyItem;
  3074. PMYITEM pTempItem;
  3075. pMyItem = GetFirstItem();
  3076. while( ! LastItem( pMyItem ) ) {
  3077. pTempItem = pMyItem;
  3078. pMyItem = GetNextItem( pMyItem );
  3079. FreeItem( &(pTempItem) );
  3080. }
  3081. InitItemList();
  3082. }
  3083. //***************************************************************************
  3084. //* *
  3085. //* NAME: GetFirstItem *
  3086. //* *
  3087. //* SYNOPSIS: Returns the first PMYITEM in the list *
  3088. //* *
  3089. //* REQUIRES: Nothing *
  3090. //* *
  3091. //* RETURNS: PMYITEM The first item *
  3092. //* *
  3093. //***************************************************************************
  3094. PMYITEM GetFirstItem( VOID )
  3095. {
  3096. return g_CDF.pTop;
  3097. }
  3098. //***************************************************************************
  3099. //* *
  3100. //* NAME: GetNextItem *
  3101. //* *
  3102. //* SYNOPSIS: Given the current item, returns the next item in the list. *
  3103. //* *
  3104. //* REQUIRES: pMyItem: The current item. *
  3105. //* *
  3106. //* RETURNS: PMYITEM The next item. *
  3107. //* *
  3108. //***************************************************************************
  3109. PMYITEM GetNextItem( PMYITEM pMyItem )
  3110. {
  3111. ASSERT( pMyItem != NULL );
  3112. return pMyItem->Next;
  3113. }
  3114. //***************************************************************************
  3115. //* *
  3116. //* NAME: FreeItem *
  3117. //* *
  3118. //* SYNOPSIS: Frees the memory associated with an item. *
  3119. //* *
  3120. //* REQUIRES: *pMyItem Pointer to a pointer to an item *
  3121. //* *
  3122. //* RETURNS: Nothing *
  3123. //* *
  3124. //***************************************************************************
  3125. VOID FreeItem( PMYITEM *pMyItem )
  3126. {
  3127. LocalFree( (*pMyItem)->aszCols[0] );
  3128. LocalFree( (*pMyItem)->aszCols[1] );
  3129. LocalFree( (*pMyItem) );
  3130. }
  3131. //***************************************************************************
  3132. //* *
  3133. //* NAME: GetItemSz *
  3134. //* *
  3135. //* SYNOPSIS: Returns a string associated with an item. You pick the *
  3136. //* string by passing the number of the string. *
  3137. //* *
  3138. //* REQUIRES: pMyItem: The item *
  3139. //* nItem: The string to return *
  3140. //* *
  3141. //* RETURNS: LPSTR: The string *
  3142. //* *
  3143. //***************************************************************************
  3144. LPSTR GetItemSz( PMYITEM pMyItem, UINT nItem )
  3145. {
  3146. ASSERT( pMyItem != NULL );
  3147. ASSERT( nItem <= 1 );
  3148. return pMyItem->aszCols[nItem];
  3149. }
  3150. //***************************************************************************
  3151. //* *
  3152. //* NAME: LastItem *
  3153. //* *
  3154. //* SYNOPSIS: Used to end a while loop when we've reached the end of list *
  3155. //* *
  3156. //* REQUIRES: pMyItem: the current item *
  3157. //* *
  3158. //* RETURNS: BOOL: TRUE if at end of list, FALSE otherwise *
  3159. //* *
  3160. //***************************************************************************
  3161. BOOL LastItem( PMYITEM pMyItem )
  3162. {
  3163. return( pMyItem == NULL );
  3164. }
  3165. //***************************************************************************
  3166. //* *
  3167. //* NAME: AddItem *
  3168. //* *
  3169. //* SYNOPSIS: Adds an item to the list. *
  3170. //* *
  3171. //* REQUIRES: szFilename, szPath - strings to add to structure. *
  3172. //* *
  3173. //* RETURNS: PMYITEM This function allocates memory which will *
  3174. //* be freed later by FreeItem() *
  3175. //* *
  3176. //***************************************************************************
  3177. PMYITEM AddItem( LPCSTR szFilename, LPCSTR szPath )
  3178. {
  3179. PMYITEM pMyItem;
  3180. PMYITEM pTail;
  3181. ASSERT( szFilename != NULL );
  3182. ASSERT( szPath != NULL );
  3183. pMyItem = (PMYITEM) LocalAlloc( GMEM_FIXED, sizeof(MYITEM) );
  3184. if ( ! pMyItem ) {
  3185. return NULL;
  3186. }
  3187. pMyItem->aszCols[0] = (LPSTR) LocalAlloc( LPTR, lstrlen( szFilename ) + 1 );
  3188. pMyItem->aszCols[1] = (LPSTR) LocalAlloc( LPTR, lstrlen( szPath ) + 1 );
  3189. if ( ! pMyItem->aszCols[0] || ! pMyItem->aszCols[1] ) {
  3190. FreeItem( &pMyItem );
  3191. return NULL;
  3192. }
  3193. lstrcpy( pMyItem->aszCols[0], szFilename );
  3194. lstrcpy( pMyItem->aszCols[1], szPath );
  3195. pMyItem->fWroteOut = FALSE;
  3196. pMyItem->Next = NULL;
  3197. if ( g_CDF.pTop == NULL )
  3198. {
  3199. g_CDF.pTop = pMyItem;
  3200. }
  3201. else
  3202. {
  3203. pTail = g_CDF.pTop;
  3204. while ( pTail->Next != NULL )
  3205. {
  3206. pTail = pTail->Next;
  3207. }
  3208. pTail->Next = pMyItem;
  3209. }
  3210. g_CDF.cbFileListNum++;
  3211. return pMyItem;
  3212. }
  3213. //***************************************************************************
  3214. //* *
  3215. //* NAME: RemoveItem *
  3216. //* *
  3217. //* SYNOPSIS: Removes an item from the list and frees the memory. *
  3218. //* *
  3219. //* REQUIRES: Nothing *
  3220. //* *
  3221. //* RETURNS: Nothing *
  3222. //* *
  3223. //***************************************************************************
  3224. VOID RemoveItem( PMYITEM pMyItem )
  3225. {
  3226. PMYITEM pCurItem;
  3227. PMYITEM pLastItem;
  3228. ASSERT( pMyItem != NULL );
  3229. pCurItem = GetFirstItem();
  3230. if ( pMyItem == pCurItem ) {
  3231. g_CDF.pTop = pCurItem->Next;
  3232. FreeItem( &pCurItem );
  3233. return;
  3234. }
  3235. pLastItem = pCurItem;
  3236. pCurItem = GetNextItem( pCurItem );
  3237. while ( ! LastItem( pCurItem ) ) {
  3238. if ( pCurItem == pMyItem ) {
  3239. pLastItem->Next = pCurItem->Next;
  3240. FreeItem( &pCurItem );
  3241. return;
  3242. }
  3243. pLastItem = pCurItem;
  3244. pCurItem = GetNextItem( pCurItem );
  3245. }
  3246. // We should never get here.
  3247. ASSERT( TRUE );
  3248. }
  3249. //***************************************************************************
  3250. //* *
  3251. //* ParseCmdLine() *
  3252. //* *
  3253. //* Purpose: Parses the command line looking for switches *
  3254. //* *
  3255. //* Parameters: LPSTR lpszCmdLineOrg - Original command line *
  3256. //* *
  3257. //* *
  3258. //* Return: (BOOL) TRUE if successful *
  3259. //* FALSE if an error occurs *
  3260. //* *
  3261. //***************************************************************************
  3262. BOOL ParseCmdLine( LPSTR lpszCmdLine )
  3263. {
  3264. LPSTR pSubArg, pArg, pTmp;
  3265. CHAR szTmpBuf[MAX_PATH];
  3266. if( (!lpszCmdLine) || (lpszCmdLine[0] == 0) )
  3267. return TRUE;
  3268. pArg = strtok( lpszCmdLine, " " );
  3269. while ( pArg )
  3270. {
  3271. if ( lstrcmpi( pArg, "/N" ) == 0 )
  3272. {
  3273. g_fBuildNow = TRUE;
  3274. }
  3275. else if( (*pArg != '/' ) )
  3276. {
  3277. lstrcpyn( g_CDF.achFilename, pArg, sizeof(g_CDF.achFilename) );
  3278. GetFullPathName( g_CDF.achFilename, sizeof(g_CDF.achFilename),
  3279. g_CDF.achFilename, &pTmp );
  3280. }
  3281. else if ( (*pArg == '/') && (toupper(*(pArg+1)) == 'O') && (*(pArg+2) == ':') )
  3282. {
  3283. lstrcpy( szTmpBuf, (pArg+3) );
  3284. if ( pSubArg = strchr( szTmpBuf, ',' ) )
  3285. {
  3286. *pSubArg = '\0';
  3287. lstrcpy( g_szOverideCDF, szTmpBuf );
  3288. GetFullPathName( g_szOverideCDF, sizeof(g_szOverideCDF),
  3289. g_szOverideCDF, &pTmp );
  3290. if ( *(pSubArg+1) )
  3291. lstrcpy( g_szOverideSec, (pSubArg+1) );
  3292. }
  3293. }
  3294. else if ( lstrcmpi( pArg, "/Q" ) == 0 )
  3295. {
  3296. g_wQuietMode = 1;
  3297. }
  3298. else if ( lstrcmpi( pArg, "/S" ) == 0 )
  3299. {
  3300. g_wSilentMode = 1;
  3301. }
  3302. else if ( lstrcmpi( pArg, "/M" ) == 0 )
  3303. {
  3304. g_wRunDiamondMinimized = 1;
  3305. }
  3306. else
  3307. {
  3308. return FALSE;
  3309. }
  3310. pArg = strtok( NULL, " " );
  3311. }
  3312. if ( (g_wQuietMode == 1) && (g_fBuildNow == FALSE) ) {
  3313. g_wQuietMode = 0;
  3314. }
  3315. return TRUE;
  3316. }
  3317. // RO_GetPrivateProfileSection
  3318. // ensure the file attribute is not read-only.
  3319. //
  3320. LONG RO_GetPrivateProfileSection( LPCSTR lpSec, LPSTR lpBuf, DWORD dwSize, LPCSTR lpFile, BOOL bSingleCol)
  3321. {
  3322. LONG lRealSize;
  3323. DWORD dwAttr;
  3324. int iCDFVer;
  3325. dwAttr = GetFileAttributes( lpFile );
  3326. if ( (dwAttr != -1) && (dwAttr & FILE_ATTRIBUTE_READONLY) )
  3327. {
  3328. if ( !SetFileAttributes( lpFile, FILE_ATTRIBUTE_NORMAL ) )
  3329. {
  3330. ErrorMsg1Param( NULL, IDS_ERR_CANT_SETA_FILE, lpFile );
  3331. }
  3332. }
  3333. if ( ( (iCDFVer = GetPrivateProfileInt( SEC_VERSION, KEY_VERSION, -1, lpFile )) == -1 ) &&
  3334. ( (iCDFVer = GetPrivateProfileInt( SEC_VERSION, KEY_NEWVER, -1, lpFile )) == -1 ) )
  3335. {
  3336. return (iCDFVer);
  3337. }
  3338. if ( !bSingleCol )
  3339. {
  3340. lRealSize = (LONG)GetPrivateProfileSection( lpSec, lpBuf, dwSize, lpFile );
  3341. }
  3342. else
  3343. {
  3344. if ( iCDFVer < 3 )
  3345. lRealSize = (LONG)GetPrivateProfileSection( lpSec, lpBuf, dwSize, lpFile );
  3346. else
  3347. lRealSize = (LONG)GetPrivateProfileString( lpSec, NULL, "", lpBuf, dwSize, lpFile );
  3348. }
  3349. if ( (dwAttr != -1) && (dwAttr & FILE_ATTRIBUTE_READONLY) )
  3350. {
  3351. SetFileAttributes( lpFile, dwAttr );
  3352. }
  3353. return lRealSize;
  3354. }
  3355. BOOL IsOSNT3X(VOID)
  3356. {
  3357. OSVERSIONINFO verinfo; // Version Check
  3358. // Operating System Version Check: For NT versions below 3.50 set flag to
  3359. // prevent use of common controls (progress bar and AVI) not available.
  3360. verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  3361. if ( GetVersionEx( &verinfo ) == FALSE )
  3362. {
  3363. // you definitly not windows 95 or NT 4.0
  3364. return TRUE;
  3365. }
  3366. if ( verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
  3367. {
  3368. if ( verinfo.dwMajorVersion <= 3 )
  3369. {
  3370. return TRUE;
  3371. }
  3372. }
  3373. return FALSE; // windows 95 or NT 4.0 above
  3374. }
  3375. void SetControlFont()
  3376. {
  3377. LOGFONT lFont;
  3378. if (GetSystemMetrics(SM_DBCSENABLED) &&
  3379. (GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof (lFont), &lFont) > 0))
  3380. {
  3381. g_hFont = CreateFontIndirect((LPLOGFONT)&lFont);
  3382. }
  3383. }
  3384. //==================================================================
  3385. BOOL GetThisModulePath( LPSTR lpPath, int size )
  3386. {
  3387. LPSTR lpTmp;
  3388. int len;
  3389. ASSERT(lpPath);
  3390. ASSERT(size);
  3391. *lpPath = 0;
  3392. if ( GetModuleFileName( g_hInst, lpPath, size ) )
  3393. {
  3394. // chop filename off
  3395. //
  3396. lpTmp = ANSIStrRChr( lpPath, '\\' );
  3397. if ( lpTmp )
  3398. {
  3399. *(CharNext(lpTmp)) = '\0';
  3400. }
  3401. }
  3402. return (*lpPath != '\0');
  3403. }
  3404. // BUGBUG: we don't need size param, since it is internal, we could assume
  3405. // MAX_PATH buffer
  3406. //
  3407. BOOL GetFileFromModulePath( LPCSTR pFile, LPSTR pPathBuf, int iBufSize )
  3408. {
  3409. BOOL bRet;
  3410. bRet = GetThisModulePath( pPathBuf, iBufSize );
  3411. AddPath( pPathBuf, pFile );
  3412. if ( bRet && GetFileAttributes( pPathBuf ) == -1 )
  3413. {
  3414. return FALSE;
  3415. }
  3416. return bRet;
  3417. }
  3418. //***************************************************************************
  3419. //* *
  3420. //* NAME: MakeDirectory *
  3421. //* *
  3422. //* SYNOPSIS: Make sure the directories along the given pathname exist. *
  3423. //* *
  3424. //* REQUIRES: pszFile: Name of the file being created. *
  3425. //* *
  3426. //* RETURNS: nothing *
  3427. //* *
  3428. //***************************************************************************
  3429. BOOL MakeDirectory( HWND hwnd, LPCSTR pszPath, BOOL bDoUI )
  3430. {
  3431. LPTSTR pchChopper;
  3432. int cExempt;
  3433. DWORD dwAttr;
  3434. BOOL bRet = FALSE;
  3435. if (pszPath[0] != '\0')
  3436. {
  3437. PSTR pszTmp = NULL;
  3438. char ch;
  3439. UINT umsg = 0;
  3440. UINT ubutton = MB_YESNO;
  3441. cExempt = 0;
  3442. pszTmp = ANSIStrRChr( pszPath, '\\' );
  3443. if ( pszTmp )
  3444. {
  3445. ch = *pszTmp;
  3446. *pszTmp = '\0';
  3447. }
  3448. dwAttr = GetFileAttributes( pszPath );
  3449. if ( bDoUI )
  3450. {
  3451. if ( dwAttr == 0xffffffff )
  3452. {
  3453. umsg = IDS_CREATEDIR;
  3454. ubutton = MB_YESNO;
  3455. }
  3456. else if ( !(dwAttr & FILE_ATTRIBUTE_DIRECTORY) )
  3457. {
  3458. umsg = IDS_INVALIDPATH;
  3459. ubutton = MB_OK;
  3460. }
  3461. if ( umsg && ( (MsgBox1Param( hwnd, umsg, (LPSTR)pszPath, MB_ICONQUESTION, ubutton ) == IDNO) ||
  3462. (ubutton == MB_OK) ) )
  3463. {
  3464. if ( pszTmp )
  3465. *pszTmp = ch;
  3466. return bRet;
  3467. }
  3468. }
  3469. if ( pszTmp )
  3470. *pszTmp = ch;
  3471. if ((pszPath[1] == ':') && (pszPath[2] == '\\'))
  3472. {
  3473. pchChopper = (LPTSTR) (pszPath + 3); /* skip past "C:\" */
  3474. }
  3475. else if ((pszPath[0] == '\\') && (pszPath[1] == '\\'))
  3476. {
  3477. pchChopper = (LPTSTR) (pszPath + 2); /* skip past "\\" */
  3478. cExempt = 2; /* machine & share names exempt */
  3479. }
  3480. else
  3481. {
  3482. pchChopper = (LPTSTR) (pszPath + 1); /* skip past potential "\" */
  3483. }
  3484. while (*pchChopper != '\0')
  3485. {
  3486. if ((*pchChopper == '\\') && (*(pchChopper - 1) != ':'))
  3487. {
  3488. if (cExempt != 0)
  3489. {
  3490. cExempt--;
  3491. }
  3492. else
  3493. {
  3494. *pchChopper = '\0';
  3495. CreateDirectory(pszPath,NULL);
  3496. *pchChopper = '\\';
  3497. }
  3498. }
  3499. pchChopper = CharNext(pchChopper);
  3500. }
  3501. bRet = TRUE;
  3502. }
  3503. return bRet;
  3504. }