which included commits to RCS files with non-trunk default branches. git-svn-id: svn://10.65.10.50/trunk@5403 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			3780 lines
		
	
	
		
			131 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			3780 lines
		
	
	
		
			131 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
//******************************************************************************
 | 
						|
//
 | 
						|
// File:        WINMAIN.CPP
 | 
						|
//
 | 
						|
// Description: This module contains all the Windows specific code for Pocket
 | 
						|
//              UnZip.  It contains the entire user interface.  This code knows
 | 
						|
//              almost nothing about the Info-ZIP code.  All Info-ZIP related
 | 
						|
//              functions are wrapped by helper functions in INTRFACE.CPP.  The
 | 
						|
//              code in this module only calls those wrapper functions and
 | 
						|
//              INTRFACE.CPP handles all the details and callbacks of the 
 | 
						|
//              Info-ZIP code.
 | 
						|
//
 | 
						|
// Copyright:   All the source files for Pocket UnZip, except for components
 | 
						|
//              written by the Info-ZIP group, are copyrighted 1997 by Steve P.
 | 
						|
//              Miller.  The product "Pocket UnZip" itself is property of the
 | 
						|
//              author and cannot be altered in any way without written consent
 | 
						|
//              from Steve P. Miller.
 | 
						|
//
 | 
						|
// Disclaimer:  All project files are provided "as is" with no guarantee of
 | 
						|
//              their correctness.  The authors are not liable for any outcome
 | 
						|
//              that is the result of using this source.  The source for Pocket
 | 
						|
//              UnZip has been placed in the public domain to help provide an
 | 
						|
//              understanding of its implementation.  You are hereby granted
 | 
						|
//              full permission to use this source in any way you wish, except
 | 
						|
//              to alter Pocket UnZip itself.  For comments, suggestions, and
 | 
						|
//              bug reports, please write to stevemil@pobox.com.
 | 
						|
//
 | 
						|
// Functions:   WinMain
 | 
						|
//              InitializeApplication
 | 
						|
//              ShutdownApplication
 | 
						|
//              RegisterUnzip
 | 
						|
//              BuildImageList
 | 
						|
//              WndProc
 | 
						|
//              OnCreate
 | 
						|
//              OnFileOpen
 | 
						|
//              OnActionView
 | 
						|
//              OnActionSelectAll
 | 
						|
//              OnViewExpandedView
 | 
						|
//              OnHelp
 | 
						|
//              OnGetDispInfo
 | 
						|
//              OnDeleteItem
 | 
						|
//              OnItemChanged
 | 
						|
//              Sort
 | 
						|
//              CompareFunc
 | 
						|
//              SetCaptionText
 | 
						|
//              DrawBanner
 | 
						|
//              AddDeleteColumns
 | 
						|
//              ResizeColumns
 | 
						|
//              GetZipErrorString
 | 
						|
//              AddFileToListView
 | 
						|
//              EnableAllMenuItems
 | 
						|
//              CheckAllMenuItems
 | 
						|
//              CenterWindow
 | 
						|
//              AddTextToEdit
 | 
						|
//              FormatValue
 | 
						|
//              BuildAttributesString
 | 
						|
//              BuildTypeString
 | 
						|
//              GetFileFromPath
 | 
						|
//              ForwardSlashesToBackSlashesA
 | 
						|
//              ForwardSlashesToBackSlashesW
 | 
						|
//              DeleteDirectory(LPTSTR szPath);
 | 
						|
//              RegWriteKey
 | 
						|
//              RegReadKey
 | 
						|
//              WriteOptionString
 | 
						|
//              WriteOptionInt
 | 
						|
//              GetOptionString
 | 
						|
//              GetOptionInt
 | 
						|
//              DisableEditing
 | 
						|
//              EditSubclassProc
 | 
						|
//              GetMenuString
 | 
						|
//              InitializeMRU
 | 
						|
//              AddFileToMRU
 | 
						|
//              RemoveFileFromMRU
 | 
						|
//              ActivateMRU
 | 
						|
//              ReadZipFileList
 | 
						|
//              DlgProcProperties
 | 
						|
//              MergeValues
 | 
						|
//              CheckThreeStateBox
 | 
						|
//              ExtractOrTestFiles
 | 
						|
//              DlgProcExtractOrTest
 | 
						|
//              FolderBrowser
 | 
						|
//              DlgProcBrowser
 | 
						|
//              SubclassSaveAsDlg
 | 
						|
//              DlgProcExtractProgress
 | 
						|
//              DlgProcViewProgress
 | 
						|
//              UpdateProgress
 | 
						|
//              PromptToReplace
 | 
						|
//              DlgProcReplace
 | 
						|
//              DlgProcPassword
 | 
						|
//              DlgProcViewAssociation
 | 
						|
//              DlgProcComment
 | 
						|
//              DlgProcAbout
 | 
						|
//
 | 
						|
//
 | 
						|
// Date      Name          History
 | 
						|
// --------  ------------  -----------------------------------------------------
 | 
						|
// 02/01/97  Steve Miller  Created (Version 1.0 using Info-ZIP UnZip 5.30)
 | 
						|
//
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
extern "C" {
 | 
						|
#define __WINMAIN_CPP__
 | 
						|
#define UNZIP_INTERNAL
 | 
						|
 | 
						|
#include "unzip.h"
 | 
						|
 | 
						|
#include "version.h"   // Only needed by consts.h (VERSION_DATE & VersionDate)
 | 
						|
#include "consts.h"    // Only include once - defines constant string messages.
 | 
						|
 | 
						|
#include "crypt.h"     // Needed to pick up CRYPT define if set and return values.
 | 
						|
 | 
						|
#include <commctrl.h>  // Common controls - mainly ListView and ImageList
 | 
						|
#include <commdlg.h>   // Common dialogs - OpenFile dialog
 | 
						|
 | 
						|
#ifndef _WIN32_WCE
 | 
						|
#include <shlobj.h>    // On NT, we use the SHBrowseForFolder() stuff.
 | 
						|
#include <shellapi.h>  // CommandLineToArgvW() and ExtractIconEx()
 | 
						|
#endif
 | 
						|
 | 
						|
#include "intrface.h"  // Interface between Info-ZIP and us
 | 
						|
#include "winmain.h"   // Us
 | 
						|
}
 | 
						|
#include <tchar.h>     // Must be outside of extern "C" block
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** "Local" Global Variables
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
static LPCTSTR         g_szAppName     = TEXT("Pocket UnZip");
 | 
						|
static LPCTSTR         g_szClass       = TEXT("PocketUnZip");
 | 
						|
static LPCTSTR         g_szRegKey      = TEXT("Software\\Pocket UnZip");
 | 
						|
static LPCTSTR         g_szTempDir     = NULL;
 | 
						|
static HWND            g_hWndList      = NULL;
 | 
						|
static HWND            g_hWndCmdBar    = NULL;
 | 
						|
static int             g_cyCmdBar      = 0;
 | 
						|
static HFONT           g_hFontBanner   = NULL;
 | 
						|
static HICON           g_hIconMain     = NULL;
 | 
						|
static WNDPROC         g_wpSaveAsDlg   = NULL;
 | 
						|
static WNDPROC         g_wpEdit        = NULL;
 | 
						|
static int             g_sortColumn    = -1;
 | 
						|
static BOOL            g_fExpandedView = FALSE;
 | 
						|
static BOOL            g_fLoading      = FALSE;
 | 
						|
static BOOL            g_fSkipped      = FALSE;
 | 
						|
static BOOL            g_fViewing      = FALSE;
 | 
						|
static HWND            g_hWndWaitFor   = NULL;
 | 
						|
static FILE_TYPE_NODE *g_pftHead       = NULL;
 | 
						|
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
static LPCTSTR         g_szHelpFile    = TEXT("\\windows\\punzip.htp");
 | 
						|
#else
 | 
						|
static LPCTSTR         g_szHelpFile    = TEXT("punzip.html");
 | 
						|
#endif
 | 
						|
 | 
						|
static COLUMN g_columns[] = {
 | 
						|
   { TEXT("Name"),       LVCFMT_LEFT  },
 | 
						|
   { TEXT("Size"),       LVCFMT_RIGHT },
 | 
						|
   { TEXT("Type"),       LVCFMT_LEFT  },
 | 
						|
   { TEXT("Modified"),   LVCFMT_LEFT  },
 | 
						|
   { TEXT("Attributes"), LVCFMT_LEFT  },
 | 
						|
   { TEXT("Compressed"), LVCFMT_RIGHT },
 | 
						|
   { TEXT("Ratio"),      LVCFMT_RIGHT },
 | 
						|
   { TEXT("Method"),     LVCFMT_LEFT  },
 | 
						|
   { TEXT("CRC"),        LVCFMT_LEFT  },
 | 
						|
   { TEXT("Comment"),    LVCFMT_LEFT  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Local Function Prototypes
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
// Startup and Shutdown Functions
 | 
						|
void InitializeApplication(LPCTSTR szZipFile);
 | 
						|
void ShutdownApplication();
 | 
						|
void RegisterUnzip();
 | 
						|
void BuildImageList();
 | 
						|
 | 
						|
// Our Main Window's Message Handler
 | 
						|
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 | 
						|
 | 
						|
// Event Handlers for our Main Window
 | 
						|
int OnCreate();
 | 
						|
void OnFileOpen();
 | 
						|
void OnActionView();
 | 
						|
void OnActionSelectAll();
 | 
						|
void OnViewExpandedView();
 | 
						|
void OnHelp();
 | 
						|
 | 
						|
// Event Handlers for our List View
 | 
						|
void OnGetDispInfo(LV_DISPINFO *plvdi);
 | 
						|
void OnDeleteItem(NM_LISTVIEW *pnmlv);
 | 
						|
void OnItemChanged(NM_LISTVIEW *pnmlv);
 | 
						|
 | 
						|
// List View Sort Functions
 | 
						|
void Sort(int sortColumn, BOOL fForce);
 | 
						|
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM sortColumn);
 | 
						|
 | 
						|
// Helper/Utility Functions
 | 
						|
void SetCaptionText(LPCTSTR szPrefix);
 | 
						|
void DrawBanner(HDC hdc);
 | 
						|
void AddDeleteColumns();
 | 
						|
void ResizeColumns();
 | 
						|
LPCTSTR GetZipErrorString(int error);
 | 
						|
void AddFileToListView(FILE_NODE *pFile);
 | 
						|
void EnableAllMenuItems(UINT uMenuItem, BOOL fEnabled);
 | 
						|
void CheckAllMenuItems(UINT uMenuItem, BOOL fChecked);
 | 
						|
void CenterWindow(HWND hWnd);
 | 
						|
void AddTextToEdit(LPCSTR szText);
 | 
						|
LPTSTR FormatValue(LPTSTR szValue, DWORD dwValue);
 | 
						|
LPTSTR BuildAttributesString(LPTSTR szBuffer, DWORD dwAttributes);
 | 
						|
LPCSTR BuildTypeString(FILE_NODE *pFile, LPSTR szType);
 | 
						|
LPCSTR GetFileFromPath(LPCSTR szPath);
 | 
						|
void ForwardSlashesToBackSlashesA(LPSTR szBuffer);
 | 
						|
void ForwardSlashesToBackSlashesW(LPWSTR szBuffer);
 | 
						|
void DeleteDirectory(LPTSTR szPath);
 | 
						|
 | 
						|
// Registry Functions
 | 
						|
void RegWriteKey(HKEY hKeyRoot, LPCTSTR szSubKey, LPCTSTR szValue);
 | 
						|
BOOL RegReadKey(HKEY hKeyRoot, LPCTSTR szSubKey, LPTSTR szValue, DWORD cBytes);
 | 
						|
void WriteOptionString(LPCTSTR szOption, LPCTSTR szValue);
 | 
						|
void WriteOptionInt(LPCTSTR szOption, DWORD dwValue);
 | 
						|
LPTSTR GetOptionString(LPCTSTR szOption, LPCTSTR szDefault, LPTSTR szValue, DWORD nSize);
 | 
						|
DWORD GetOptionInt(LPCTSTR szOption, DWORD dwDefault);
 | 
						|
 | 
						|
// EDIT Control Subclass Functions
 | 
						|
void DisableEditing(HWND hWndEdit);
 | 
						|
LRESULT CALLBACK EditSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 | 
						|
 | 
						|
// MRU Functions
 | 
						|
void InitializeMRU();
 | 
						|
void AddFileToMRU(LPCSTR szFile);
 | 
						|
void RemoveFileFromMRU(LPCTSTR szFile);
 | 
						|
void ActivateMRU(UINT uIDItem);
 | 
						|
 | 
						|
// Open Zip File Functions
 | 
						|
void ReadZipFileList(LPCWSTR wszPath);
 | 
						|
 | 
						|
// Zip File Properties Dialog Functions
 | 
						|
BOOL CALLBACK DlgProcProperties(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 | 
						|
void MergeValues(int *p1, int p2);
 | 
						|
void CheckThreeStateBox(HWND hDlg, int nIDButton, int state);
 | 
						|
 | 
						|
// Extract/Test Dialog Functions
 | 
						|
void ExtractOrTestFiles(BOOL fExtract);
 | 
						|
BOOL CALLBACK DlgProcExtractOrTest(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 | 
						|
 | 
						|
// Folder Browsing Dialog Functions
 | 
						|
BOOL FolderBrowser(LPTSTR szPath, DWORD dwLength);
 | 
						|
BOOL CALLBACK DlgProcBrowser(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 | 
						|
void SubclassSaveAsDlg();
 | 
						|
 | 
						|
// Extraction/Test/View Progress Dialog Functions
 | 
						|
BOOL CALLBACK DlgProcExtractProgress(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 | 
						|
BOOL CALLBACK DlgProcViewProgress(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 | 
						|
void UpdateProgress(EXTRACT_INFO *pei, BOOL fFull);
 | 
						|
 | 
						|
// Replace File Dialog Functions
 | 
						|
int PromptToReplace(LPCSTR szPath);
 | 
						|
BOOL CALLBACK DlgProcReplace(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 | 
						|
 | 
						|
// Password Dialog Functions
 | 
						|
BOOL CALLBACK DlgProcPassword(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 | 
						|
 | 
						|
// View Association Dialog Functions
 | 
						|
BOOL CALLBACK DlgProcViewAssociation(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 | 
						|
 | 
						|
// Comment Dialog Functions
 | 
						|
BOOL CALLBACK DlgProcComment(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 | 
						|
 | 
						|
// About Dialog Functions
 | 
						|
BOOL CALLBACK DlgProcAbout(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** WinMain - Our one and only entry point
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
// Entrypoint is a tiny bit different on Windows CE - UNICODE command line.
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
extern "C" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
 | 
						|
                              LPTSTR lpCmdLine, int nCmdShow)
 | 
						|
#else
 | 
						|
extern "C" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 | 
						|
                              LPSTR lpCmdLine, int nCmdShow)
 | 
						|
#endif
 | 
						|
{
 | 
						|
   // Wrap the whole ball of wax in a big exception handler.
 | 
						|
   __try {
 | 
						|
 | 
						|
      // Store global instance handle.
 | 
						|
      g_hInst = hInstance;
 | 
						|
 | 
						|
      // Create our banner font.  We need to do this before creating our window.
 | 
						|
      // This font handle will be deleted in ShutdownApplication().
 | 
						|
      LOGFONT lf;
 | 
						|
      ZeroMemory(&lf, sizeof(lf));
 | 
						|
      lf.lfHeight = 16;
 | 
						|
      lf.lfWeight = FW_BOLD;
 | 
						|
      lf.lfCharSet = ANSI_CHARSET;
 | 
						|
      lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
 | 
						|
      lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
 | 
						|
      lf.lfQuality = DEFAULT_QUALITY;
 | 
						|
      lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
 | 
						|
      _tcscpy(lf.lfFaceName, TEXT("MS Sans Serif"));
 | 
						|
      g_hFontBanner = CreateFontIndirect(&lf);
 | 
						|
 | 
						|
      // Define the window class for our application's main window.
 | 
						|
      WNDCLASS wc;
 | 
						|
      ZeroMemory(&wc, sizeof(wc));
 | 
						|
      wc.lpszClassName = g_szClass;
 | 
						|
      wc.hInstance     = hInstance;
 | 
						|
      wc.lpfnWndProc   = WndProc;
 | 
						|
      wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
 | 
						|
 | 
						|
      TCHAR *szZipPath = NULL;
 | 
						|
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
 | 
						|
      // Get our main window's small icon.  On Windows CE, we need to send ourself
 | 
						|
      // a WM_SETICON in order for our task bar to update itself.
 | 
						|
      g_hIconMain = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_UNZIP), 
 | 
						|
                                     IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
 | 
						|
      wc.hIcon = g_hIconMain;
 | 
						|
 | 
						|
      // On Windows CE, we only need the WS_VISIBLE flag.
 | 
						|
      DWORD dwStyle = WS_VISIBLE;
 | 
						|
 | 
						|
      // Get and store command line file (if any).
 | 
						|
      if (lpCmdLine && *lpCmdLine) {
 | 
						|
         szZipPath = lpCmdLine;
 | 
						|
      }
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
      // On NT we add a cursor, icon, and nenu to our application's window class.
 | 
						|
      wc.hCursor      = LoadCursor(NULL, IDC_ARROW);
 | 
						|
      wc.hIcon        = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_UNZIP));
 | 
						|
      wc.lpszMenuName = MAKEINTRESOURCE(IDR_UNZIP);
 | 
						|
 | 
						|
      // On Windows NT, we use the standard overlapped window style.
 | 
						|
      DWORD dwStyle = WS_OVERLAPPEDWINDOW;
 | 
						|
 | 
						|
      TCHAR szBuffer[_MAX_PATH];
 | 
						|
 | 
						|
      // Get and store command line file (if any).
 | 
						|
      if (lpCmdLine && *lpCmdLine) {
 | 
						|
         mbstowcs(szBuffer, lpCmdLine, countof(szBuffer));
 | 
						|
         szZipPath = szBuffer;
 | 
						|
      }
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
      // Register our window class with the OS.
 | 
						|
      if (!RegisterClass(&wc)) {
 | 
						|
         DebugOut(TEXT("RegisterClass() failed [%u]"), GetLastError());
 | 
						|
      }
 | 
						|
 | 
						|
      // Create our main window using our registered window class.
 | 
						|
      g_hWndMain = CreateWindow(wc.lpszClassName, g_szAppName, dwStyle,
 | 
						|
                                CW_USEDEFAULT, CW_USEDEFAULT, 
 | 
						|
                                CW_USEDEFAULT, CW_USEDEFAULT,
 | 
						|
                                NULL, NULL, hInstance, NULL);
 | 
						|
 | 
						|
      // Quit now if we failed to create our main window.
 | 
						|
      if (!g_hWndMain) {
 | 
						|
         DebugOut(TEXT("CreateWindow() failed [%u]"), GetLastError());
 | 
						|
         ShutdownApplication();
 | 
						|
         return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      // Make sure our window is visible.  Really only needed for NT.
 | 
						|
      ShowWindow(g_hWndMain, nCmdShow);
 | 
						|
 | 
						|
      // Load our keyboard accelerator shortcuts.
 | 
						|
      MSG    msg;
 | 
						|
      HACCEL hAccel = LoadAccelerators(g_hInst, MAKEINTRESOURCE(IDR_UNZIP));
 | 
						|
      DWORD  dwPaintFlags = 0;
 | 
						|
 | 
						|
      // The message pump.  Loop until we get a WM_QUIT message.
 | 
						|
      while (GetMessage(&msg, NULL, 0, 0)) {
 | 
						|
      
 | 
						|
         // Check to see if this is an accelerator and handle it if neccessary.
 | 
						|
         if (!TranslateAccelerator(g_hWndMain, hAccel, &msg)) {
 | 
						|
 | 
						|
            // If a normal message, then dispatch it to the correct window.
 | 
						|
            TranslateMessage(&msg);
 | 
						|
            DispatchMessage(&msg); 
 | 
						|
 | 
						|
            // Wait until our application is up an visible before trying to
 | 
						|
            // initialize some of our structures and load any command line file.
 | 
						|
            if ((msg.message == WM_PAINT) && (dwPaintFlags != 0x11)) {
 | 
						|
               if (msg.hwnd == g_hWndWaitFor) {
 | 
						|
                  dwPaintFlags |= 0x01;
 | 
						|
               } else if (msg.hwnd == g_hWndList) {
 | 
						|
                  dwPaintFlags |= 0x10;
 | 
						|
               }
 | 
						|
               if (dwPaintFlags == 0x11) {
 | 
						|
                  InitializeApplication((szZipPath && *szZipPath) ? 
 | 
						|
                                        szZipPath : NULL);
 | 
						|
               }
 | 
						|
            }
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
      // Clean up code.
 | 
						|
      ShutdownApplication();
 | 
						|
 | 
						|
      // Nice clean finish - were out of here.
 | 
						|
      return msg.wParam;
 | 
						|
 | 
						|
 | 
						|
   } __except(EXCEPTION_EXECUTE_HANDLER) {
 | 
						|
 | 
						|
      // Something very bad happened.  Try our best to appear somewhat graceful.
 | 
						|
      MessageBox(NULL, 
 | 
						|
         TEXT("An internal error occurred.  Possible causes are that you are ")
 | 
						|
         TEXT("out of memory, a ZIP file (if one is loaded) contains an ")
 | 
						|
         TEXT("unexpected error, or there is a bug in our program (that's why ")
 | 
						|
         TEXT("it's free).  Pocket UnZip cannot continue.  It will exit now, ")
 | 
						|
         TEXT("but you may restart it and try again.\n\n")
 | 
						|
         TEXT("If the problem persists, please write to stevemil@pobox.com with ")
 | 
						|
         TEXT("any information that might help track down the problem."),
 | 
						|
         g_szAppName, MB_ICONERROR | MB_OK);
 | 
						|
   }
 | 
						|
 | 
						|
   return 1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Startup and Shutdown Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
void InitializeApplication(LPCTSTR szZipFile) {
 | 
						|
 | 
						|
   // This function is called after our class is registered and all our windows
 | 
						|
   // are created and visible to the user.
 | 
						|
 | 
						|
   // Show hour glass cursor.
 | 
						|
   HCURSOR hCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
 | 
						|
 | 
						|
   // Register UnZip in the registry to handle ".ZIP" files.
 | 
						|
   RegisterUnzip();
 | 
						|
 | 
						|
   // Enumerate the system file assoications and build an image list.
 | 
						|
   BuildImageList();
 | 
						|
 | 
						|
   // Load our initial MRU into our menu.
 | 
						|
   InitializeMRU();
 | 
						|
 | 
						|
   // Restore/remove our cursor.
 | 
						|
   SetCursor(hCur);
 | 
						|
 | 
						|
   // Clear our initialization window handle.
 | 
						|
   g_hWndWaitFor = NULL;
 | 
						|
 | 
						|
   // Load our command line file if one was specified. Otherwise, just update
 | 
						|
   // our banner to show that no file is loaded.
 | 
						|
   if (szZipFile) {
 | 
						|
      ReadZipFileList(szZipFile);
 | 
						|
   } else {
 | 
						|
      DrawBanner(NULL);
 | 
						|
   }
 | 
						|
 | 
						|
   // Enable some controls.
 | 
						|
   EnableAllMenuItems(IDM_FILE_OPEN,          TRUE);
 | 
						|
   EnableAllMenuItems(IDM_FILE_CLOSE,         TRUE);
 | 
						|
   EnableAllMenuItems(IDM_VIEW_EXPANDED_VIEW, TRUE);
 | 
						|
   EnableAllMenuItems(IDM_HELP_ABOUT,         TRUE);
 | 
						|
 | 
						|
   // Set our temporary directory.
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
   g_szTempDir = TEXT("\\Temporary Pocket UnZip Files");
 | 
						|
#else 
 | 
						|
   g_szTempDir = TEXT("C:\\Temporary Pocket UnZip Files");
 | 
						|
 | 
						|
   // Set the drive to be the same drive as the OS installation is on.
 | 
						|
   TCHAR szPath[_MAX_PATH];
 | 
						|
   if (GetWindowsDirectory(szPath, countof(szPath))) {
 | 
						|
      *((LPTSTR)g_szTempDir) = *szPath;
 | 
						|
   }
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void ShutdownApplication() {
 | 
						|
   
 | 
						|
   // Free our banner font.
 | 
						|
   if (g_hFontBanner) {
 | 
						|
      DeleteObject(g_hFontBanner);
 | 
						|
      g_hFontBanner = NULL;
 | 
						|
   }
 | 
						|
 | 
						|
   // Delete our FILE_TYPE_NODE linked list.
 | 
						|
   for (FILE_TYPE_NODE *pft = g_pftHead; pft; ) {
 | 
						|
      FILE_TYPE_NODE *pftNext = pft->pNext;
 | 
						|
      delete[] (BYTE*)pft;
 | 
						|
      pft = pftNext;
 | 
						|
   }
 | 
						|
   g_pftHead = NULL;
 | 
						|
 | 
						|
   // If there are no other instances of our application open, then delete our
 | 
						|
   // temporary directory and all the files in it.  Any files opened for viewing
 | 
						|
   // should be locked and will fail to delete.  This is to be expected.
 | 
						|
   if (g_szTempDir && (FindWindow(g_szClass, NULL) == NULL)) {
 | 
						|
      TCHAR szPath[_MAX_PATH];
 | 
						|
      _tcscpy(szPath, g_szTempDir);
 | 
						|
      DeleteDirectory(szPath);
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void RegisterUnzip() {
 | 
						|
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
 | 
						|
   // WARNING!  Since Windows CE does not support any way to get your binary's
 | 
						|
   // name at runtime, we have to hard-code in "punzip.exe".  If our binary is
 | 
						|
   // not named this or is in a non-path directory, then we will fail to
 | 
						|
   // register ourself with the system as the default application to handle
 | 
						|
   // ".zip" files.
 | 
						|
   TCHAR szPath[32] = TEXT("punzip.exe");
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
   // Get our module's path and file name.  We use the short path name for the
 | 
						|
   // registry because it is guarenteed to contain no spaces.
 | 
						|
   TCHAR szLongPath[_MAX_PATH];
 | 
						|
   TCHAR szPath[_MAX_PATH];
 | 
						|
   GetModuleFileName(NULL, szLongPath, countof(szLongPath));
 | 
						|
   GetShortPathName(szLongPath, szPath, countof(szPath));
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
   // Store a pointer to the end of our path for easy appending.
 | 
						|
   LPTSTR szEnd = szPath + _tcslen(szPath);
 | 
						|
 | 
						|
   // Associate "ZIP" file extensions to our application
 | 
						|
   RegWriteKey(HKEY_CLASSES_ROOT, TEXT(".zip"), TEXT("zipfile"));
 | 
						|
   RegWriteKey(HKEY_CLASSES_ROOT, TEXT("zipfile"), TEXT("ZIP File"));
 | 
						|
   RegWriteKey(HKEY_CLASSES_ROOT, TEXT("zipfile\\shell"), NULL);
 | 
						|
   RegWriteKey(HKEY_CLASSES_ROOT, TEXT("zipfile\\shell\\Open"), NULL);
 | 
						|
   _tcscpy(szEnd, TEXT(" %1"));
 | 
						|
   RegWriteKey(HKEY_CLASSES_ROOT, TEXT("zipfile\\shell\\Open\\command"), szPath);
 | 
						|
 | 
						|
   // Register our program icon for all ZIP files.
 | 
						|
   _stprintf(szEnd, TEXT(",-%u"), IDI_ZIPFILE);
 | 
						|
   RegWriteKey(HKEY_CLASSES_ROOT, TEXT("zipfile\\DefaultIcon"), szPath);
 | 
						|
 | 
						|
   // Create our application option location.
 | 
						|
   RegWriteKey(HKEY_CURRENT_USER, TEXT("Software"), NULL);
 | 
						|
   RegWriteKey(HKEY_CURRENT_USER, g_szRegKey, NULL);
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void BuildImageList() {
 | 
						|
 | 
						|
   // Create our global image list.
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
 
 | 
						|
   // On Windows CE, we can't spare a color for the mask, so we have to create
 | 
						|
   // the mask in a separate monochrome bitmap.
 | 
						|
 | 
						|
   HIMAGELIST hil = ImageList_Create(16, 16, ILC_COLOR | ILC_MASK, 8, 8);
 | 
						|
 | 
						|
   // Load our default bitmaps into the image list.
 | 
						|
   HBITMAP hBmpImageList = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_IMAGELIST));
 | 
						|
   HBITMAP hBmpMask = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_IMAGELIST_MASK));
 | 
						|
   ImageList_Add(hil, hBmpImageList, hBmpMask);
 | 
						|
   DeleteObject(hBmpImageList);
 | 
						|
   DeleteObject(hBmpMask);
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
   // On Windows NT, we use magenta as a transparency mask color.
 | 
						|
   HIMAGELIST hil = ImageList_LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_IMAGELIST),
 | 
						|
                                         16, 8, RGB(255, 0, 255));
 | 
						|
#endif
 | 
						|
 | 
						|
   // Set up for our registry file type enumeration.
 | 
						|
   FILE_TYPE_NODE *pftLast = NULL;
 | 
						|
   TCHAR szExtension[128], szKey[128], szDescription[_MAX_PATH], szIconFile[_MAX_PATH + 16];
 | 
						|
   DWORD dwIndex = 0, dwCount = countof(szExtension);
 | 
						|
 | 
						|
   // Enumerate all the keys immediately under HKEY_CLASSES_ROOT.
 | 
						|
   while (ERROR_SUCCESS == RegEnumKeyEx(HKEY_CLASSES_ROOT, dwIndex++, szExtension, 
 | 
						|
                                        &dwCount, NULL, NULL, NULL, NULL))
 | 
						|
   {
 | 
						|
      dwCount = countof(szExtension);
 | 
						|
 | 
						|
      // Check to see if we read an extension key (starts with a period)
 | 
						|
      if (*szExtension != TEXT('.')) {
 | 
						|
         continue;
 | 
						|
      }
 | 
						|
 | 
						|
      // Read the actual key name for this extension.
 | 
						|
      if (!RegReadKey(HKEY_CLASSES_ROOT, szExtension, szKey, sizeof(szKey))) {
 | 
						|
         continue;
 | 
						|
      }
 | 
						|
 | 
						|
      // Read the Description for this extension.
 | 
						|
      RegReadKey(HKEY_CLASSES_ROOT, szKey, szDescription, sizeof(szDescription));
 | 
						|
 | 
						|
      HICON hIcon = NULL;
 | 
						|
      LPTSTR szEnd = szKey + _tcslen(szKey);
 | 
						|
 | 
						|
      // Attempt to get an icon for this extension from the "DefaultIcon" key.
 | 
						|
      _tcscpy(szEnd, TEXT("\\DefaultIcon"));
 | 
						|
      if (RegReadKey(HKEY_CLASSES_ROOT, szKey, szIconFile, sizeof(szIconFile))) {
 | 
						|
 | 
						|
         // Look for the comma between the file name and the image.
 | 
						|
         LPTSTR szImageId = _tcschr(szIconFile, TEXT(','));
 | 
						|
         if (szImageId) {
 | 
						|
 | 
						|
            // NULL terminate the file name portion of szIconFile.
 | 
						|
            *(szImageId++) = TEXT('\0');
 | 
						|
 | 
						|
            // Get the image ID value from szIconFile.
 | 
						|
            int imageId = _ttoi(szImageId);
 | 
						|
 | 
						|
            // Extract the icon from the module specified in szIconFile.
 | 
						|
            ExtractIconEx(szIconFile, imageId, NULL, &hIcon, 1);
 | 
						|
            if (hIcon == NULL) {
 | 
						|
               ExtractIconEx(szIconFile, imageId, &hIcon, NULL, 1);
 | 
						|
            }
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
      // If we failed to get the icon using the "DefaultIcon" key, then try
 | 
						|
      // using the "shell\Open\command" key.
 | 
						|
      if (hIcon == NULL) {
 | 
						|
 | 
						|
         _tcscpy(szEnd, TEXT("\\shell\\Open\\command"));
 | 
						|
         if (RegReadKey(HKEY_CLASSES_ROOT, szKey, szIconFile, sizeof(szIconFile))) {
 | 
						|
 | 
						|
            // Get a pointer to just the binary - strip quotes and spaces.
 | 
						|
            LPTSTR szPath;
 | 
						|
            if (*szIconFile == TEXT('\"')) {
 | 
						|
               szPath = szIconFile + 1;
 | 
						|
               if (szEnd = _tcschr(szPath, TEXT('\"'))) {
 | 
						|
                  *szEnd = TEXT('\0');
 | 
						|
               }
 | 
						|
            } else {
 | 
						|
               szPath = szIconFile;
 | 
						|
               if (szEnd = _tcschr(szPath, TEXT(' '))) {
 | 
						|
                  *szEnd = TEXT('\0');
 | 
						|
               }
 | 
						|
            }
 | 
						|
 | 
						|
            // Extract the icon from the module specified in szIconFile.
 | 
						|
            ExtractIconEx(szPath, 0, NULL, &hIcon, 1);
 | 
						|
            if (hIcon == NULL) {
 | 
						|
               ExtractIconEx(szPath, 0, &hIcon, NULL, 1);
 | 
						|
            }
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
      // If we found an icon, add it to our image list.
 | 
						|
      int image = -1;
 | 
						|
      if (hIcon) {
 | 
						|
         image = ImageList_AddIcon(hil, hIcon);
 | 
						|
      }
 | 
						|
 | 
						|
      // If no icon could be found, then check to see if this is an executable.
 | 
						|
      if ((image == -1) && (
 | 
						|
#ifndef _WIN32_WCE // Windows CE only recognizes EXE's as executable.
 | 
						|
         !_tcsicmp(szExtension + 1, TEXT("bat")) ||
 | 
						|
         !_tcsicmp(szExtension + 1, TEXT("cmd")) ||
 | 
						|
         !_tcsicmp(szExtension + 1, TEXT("com")) ||
 | 
						|
#endif
 | 
						|
         !_tcsicmp(szExtension + 1, TEXT("exe"))))
 | 
						|
      {
 | 
						|
         image = IMAGE_APPLICATION;
 | 
						|
      }
 | 
						|
 | 
						|
      // If we don't have a description or a icon, then bail on this extension.
 | 
						|
      if (!*szDescription && (image < 0)) {
 | 
						|
         continue;
 | 
						|
      }
 | 
						|
         
 | 
						|
      // Create our FILE_TYPE_NODE.
 | 
						|
      int length = _tcslen(szExtension) - 1 + _tcslen(szDescription);
 | 
						|
      FILE_TYPE_NODE *pft = (FILE_TYPE_NODE*) new BYTE[
 | 
						|
         sizeof(FILE_TYPE_NODE) + (sizeof(TCHAR) * length)];
 | 
						|
 | 
						|
      // Bail out if we could not create our node.
 | 
						|
      if (!pft) {
 | 
						|
         DebugOut(TEXT("Not enough memory to create a FILE_TYPE_NODE."));
 | 
						|
         continue;
 | 
						|
      }
 | 
						|
 | 
						|
      // Fill in the node.
 | 
						|
      pft->pNext = NULL;
 | 
						|
      pft->image = (image >= 0) ? image : IMAGE_GENERIC;
 | 
						|
      wcstombs(pft->szExtAndDesc, szExtension + 1, length + 3);
 | 
						|
      wcstombs(pft->szExtAndDesc + strlen(pft->szExtAndDesc) + 1, 
 | 
						|
               szDescription, length + 3);
 | 
						|
 | 
						|
      // Add the node to our list.
 | 
						|
      if (pftLast) {
 | 
						|
         pftLast->pNext = pft;
 | 
						|
      } else {
 | 
						|
         g_pftHead = pft;
 | 
						|
      }
 | 
						|
      pftLast = pft;
 | 
						|
   }
 | 
						|
 | 
						|
   // Assign this image list to our tree control.
 | 
						|
   ListView_SetImageList(g_hWndList, hil, LVSIL_SMALL);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Our Main Window's Message Handler
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 | 
						|
 | 
						|
   switch(uMsg) {
 | 
						|
      case WM_CREATE:
 | 
						|
         g_hWndMain = hWnd;
 | 
						|
         return OnCreate();
 | 
						|
 | 
						|
      case WM_ERASEBKGND:
 | 
						|
         DrawBanner((HDC)wParam);
 | 
						|
         return 0;
 | 
						|
 | 
						|
      case WM_SIZE:
 | 
						|
         // Resize our list view control to match our client area.
 | 
						|
         MoveWindow(g_hWndList, 0, g_cyCmdBar + 22, LOWORD(lParam), 
 | 
						|
                    HIWORD(lParam) - (g_cyCmdBar + 22), TRUE);
 | 
						|
 | 
						|
#ifndef _WIN32_WCE
 | 
						|
         // On NT we have to resize our toolbar as well.
 | 
						|
         MoveWindow(g_hWndCmdBar, 0, 0, LOWORD(lParam), g_cyCmdBar, TRUE);
 | 
						|
#endif
 | 
						|
         return 0;
 | 
						|
      
 | 
						|
      case WM_SETFOCUS:
 | 
						|
         // Always direct focus to our list control.
 | 
						|
         SetFocus(g_hWndList);
 | 
						|
         return 0;
 | 
						|
 | 
						|
      case WM_DESTROY:
 | 
						|
         PostQuitMessage(0);
 | 
						|
         return 0;
 | 
						|
      
 | 
						|
      case WM_HELP:
 | 
						|
         OnHelp();
 | 
						|
         return 0;
 | 
						|
 | 
						|
      case WM_PRIVATE:
 | 
						|
         switch (wParam) {
 | 
						|
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
            case MSG_SUBCLASS_DIALOG:
 | 
						|
               SubclassSaveAsDlg();
 | 
						|
               return 0;
 | 
						|
#endif
 | 
						|
            case MSG_ADD_TEXT_TO_EDIT:
 | 
						|
               AddTextToEdit((LPCSTR)lParam);
 | 
						|
               return 0;
 | 
						|
            
 | 
						|
            case MSG_PROMPT_TO_REPLACE:
 | 
						|
               return PromptToReplace((LPCSTR)lParam);
 | 
						|
 | 
						|
#if CRYPT
 | 
						|
            case MSG_PROMPT_FOR_PASSWORD:
 | 
						|
               return DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_PASSWORD),
 | 
						|
                                     g_hDlgProgress, (DLGPROC)DlgProcPassword,
 | 
						|
                                     lParam);
 | 
						|
#endif
 | 
						|
 | 
						|
            case MSG_UPDATE_PROGRESS_PARTIAL:
 | 
						|
               UpdateProgress((EXTRACT_INFO*)lParam, FALSE);
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case MSG_UPDATE_PROGRESS_COMPLETE:
 | 
						|
               UpdateProgress((EXTRACT_INFO*)lParam, TRUE);
 | 
						|
               return 0;
 | 
						|
         }
 | 
						|
         return 0;
 | 
						|
 | 
						|
      case WM_NOTIFY:
 | 
						|
         switch (((LPNMHDR)lParam)->code) {
 | 
						|
 | 
						|
            case LVN_GETDISPINFO:
 | 
						|
               OnGetDispInfo((LV_DISPINFO*)lParam);
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case LVN_DELETEITEM:
 | 
						|
               OnDeleteItem((NM_LISTVIEW*)lParam);
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case LVN_COLUMNCLICK:
 | 
						|
               Sort(((NM_LISTVIEW*)lParam)->iSubItem, FALSE);
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case LVN_ITEMCHANGED:
 | 
						|
               OnItemChanged((NM_LISTVIEW*)lParam);
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case NM_DBLCLK:
 | 
						|
            case NM_RETURN:
 | 
						|
               OnActionView();
 | 
						|
               return 0;
 | 
						|
         }
 | 
						|
 | 
						|
         return 0;
 | 
						|
 | 
						|
      case WM_COMMAND:
 | 
						|
         switch (LOWORD(wParam)) {
 | 
						|
 | 
						|
            case IDM_FILE_OPEN:
 | 
						|
               OnFileOpen();
 | 
						|
               return 0;
 | 
						|
            
 | 
						|
            case IDM_FILE_PROPERTIES:
 | 
						|
               DialogBox(g_hInst, MAKEINTRESOURCE(IDD_PROPERTIES), hWnd, (DLGPROC)DlgProcProperties);
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case IDM_FILE_CLOSE:
 | 
						|
               SendMessage(hWnd, WM_CLOSE, 0, 0);
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case IDM_ACTION_EXTRACT_ALL:
 | 
						|
               OnActionSelectAll();
 | 
						|
               // Fall through to IDM_ACTION_EXTRACT
 | 
						|
 | 
						|
            case IDM_ACTION_EXTRACT:
 | 
						|
               ExtractOrTestFiles(TRUE);
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case IDM_ACTION_TEST_ALL:
 | 
						|
               OnActionSelectAll();
 | 
						|
               // Fall through to IDM_ACTION_TEST
 | 
						|
 | 
						|
            case IDM_ACTION_TEST:
 | 
						|
               ExtractOrTestFiles(FALSE);
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case IDM_ACTION_VIEW:
 | 
						|
               OnActionView();
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case IDM_ACTION_SELECT_ALL:
 | 
						|
               OnActionSelectAll();
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case IDM_VIEW_EXPANDED_VIEW:
 | 
						|
               OnViewExpandedView();
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case IDM_VIEW_COMMENT:
 | 
						|
               DialogBox(g_hInst, MAKEINTRESOURCE(IDD_COMMENT), hWnd, (DLGPROC)DlgProcComment);
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case IDM_HELP_ABOUT:
 | 
						|
               DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)DlgProcAbout);
 | 
						|
               return 0;
 | 
						|
 | 
						|
            case IDHELP:
 | 
						|
               return SendMessage(hWnd, WM_HELP, 0, 0);
 | 
						|
 | 
						|
            default:
 | 
						|
               // Check to see if a MRU file was selected.
 | 
						|
               if ((LOWORD(wParam) >= MRU_START_ID) && 
 | 
						|
                   (LOWORD(wParam) < (MRU_START_ID + MRU_MAX_FILE)))
 | 
						|
               {
 | 
						|
                  ActivateMRU(LOWORD(wParam));
 | 
						|
               }
 | 
						|
         }
 | 
						|
    }
 | 
						|
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
 | 
						|
}          
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Event Handlers for our Main Window
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
int OnCreate() {
 | 
						|
 | 
						|
   // Our toolbar buttons.
 | 
						|
   static TBBUTTON tbButton[] = {
 | 
						|
      { 0, 0,                      0, TBSTYLE_SEP,    0, 0, 0, -1 },
 | 
						|
      { 0, IDM_FILE_OPEN,          0, TBSTYLE_BUTTON, 0, 0, 0, -1 },
 | 
						|
      { 0, 0,                      0, TBSTYLE_SEP,    0, 0, 0, -1 },
 | 
						|
      { 1, IDM_FILE_PROPERTIES,    0, TBSTYLE_BUTTON, 0, 0, 0, -1 },
 | 
						|
      { 0, 0,                      0, TBSTYLE_SEP,    0, 0, 0, -1 },
 | 
						|
      { 2, IDM_ACTION_EXTRACT,     0, TBSTYLE_BUTTON, 0, 0, 0, -1 },
 | 
						|
      { 3, IDM_ACTION_EXTRACT_ALL, 0, TBSTYLE_BUTTON, 0, 0, 0, -1 },
 | 
						|
      { 0, 0,                      0, TBSTYLE_SEP,    0, 0, 0, -1 },
 | 
						|
      { 4, IDM_ACTION_TEST,        0, TBSTYLE_BUTTON, 0, 0, 0, -1 },
 | 
						|
      { 5, IDM_ACTION_TEST_ALL,    0, TBSTYLE_BUTTON, 0, 0, 0, -1 },
 | 
						|
      { 0, 0,                      0, TBSTYLE_SEP,    0, 0, 0, -1 },
 | 
						|
      { 6, IDM_ACTION_VIEW,        0, TBSTYLE_BUTTON, 0, 0, 0, -1 },
 | 
						|
      { 0, 0,                      0, TBSTYLE_SEP,    0, 0, 0, -1 },
 | 
						|
      { 7, IDM_VIEW_EXPANDED_VIEW, 0, TBSTYLE_BUTTON, 0, 0, 0, -1 },
 | 
						|
      { 8, IDM_VIEW_COMMENT,       0, TBSTYLE_BUTTON, 0, 0, 0, -1 }
 | 
						|
   };
 | 
						|
 | 
						|
   // Our toolbar buttons' tool tip text.
 | 
						|
   static LPTSTR szToolTips[] = {
 | 
						|
       TEXT(""),  // Menu
 | 
						|
       TEXT("Open (Ctrl+O)"),
 | 
						|
       TEXT("Properties (Alt+Enter)"),
 | 
						|
       TEXT("Extract Selected Files"),
 | 
						|
       TEXT("Extract All Files"),
 | 
						|
       TEXT("Test Selected Files"),
 | 
						|
       TEXT("Test All Files"),
 | 
						|
       TEXT("View Selected File"),
 | 
						|
       TEXT("Expanded View"),
 | 
						|
       TEXT("View Zip File Comment")
 | 
						|
   };
 | 
						|
 | 
						|
   // Initialize the common controls.
 | 
						|
   InitCommonControls();
 | 
						|
 | 
						|
   // Check to see if we have a help file.
 | 
						|
   BOOL fHelp = (GetFileAttributes(g_szHelpFile) != 0xFFFFFFFF);
 | 
						|
 | 
						|
   // Set our window's icon so it can update the task bar.
 | 
						|
   if (g_hIconMain) {
 | 
						|
      SendMessage(g_hWndMain, WM_SETICON, FALSE, (LPARAM)g_hIconMain);
 | 
						|
   }
 | 
						|
 | 
						|
   // Create the tree control.  Our main window will resize it to fit.
 | 
						|
   g_hWndList = CreateWindow(WC_LISTVIEW, TEXT(""),
 | 
						|
                             WS_VSCROLL | WS_CHILD | WS_VISIBLE | 
 | 
						|
                             LVS_REPORT | LVS_SHOWSELALWAYS,
 | 
						|
                             0, 0, 0, 0, g_hWndMain, NULL, g_hInst, NULL);
 | 
						|
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
 | 
						|
   // Create a command bar and add the toolbar bitmaps to it.
 | 
						|
   g_hWndCmdBar = CommandBar_Create(g_hInst, g_hWndMain, 1);
 | 
						|
   CommandBar_AddBitmap(g_hWndCmdBar, g_hInst, IDB_TOOLBAR, 9, 16, 16);
 | 
						|
   CommandBar_InsertMenubar(g_hWndCmdBar, g_hInst, IDR_UNZIP, 0);
 | 
						|
   CommandBar_AddButtons(g_hWndCmdBar, countof(tbButton), tbButton);
 | 
						|
   CommandBar_AddAdornments(g_hWndCmdBar, fHelp ? CMDBAR_HELP : 0, 0);
 | 
						|
 | 
						|
   // Add tool tips to the tool bar.
 | 
						|
   CommandBar_AddToolTips(g_hWndCmdBar, countof(szToolTips), szToolTips);
 | 
						|
 | 
						|
   // Store the height of the command bar for later calculations.
 | 
						|
   g_cyCmdBar = CommandBar_Height(g_hWndCmdBar);
 | 
						|
 | 
						|
   // We set our wait window handle to our menu window within our command bar.
 | 
						|
   // This is the last window that will be painted during startup of our app.
 | 
						|
   g_hWndWaitFor = GetWindow(g_hWndCmdBar, GW_CHILD);
 | 
						|
 | 
						|
   // Add the help item to our help menu if we have a help file.
 | 
						|
   if (fHelp) {
 | 
						|
      HMENU hMenu = GetSubMenu(CommandBar_GetMenu(g_hWndCmdBar, 0), 3);
 | 
						|
      InsertMenu(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
 | 
						|
      InsertMenu(hMenu, 0, MF_BYPOSITION | MF_ENABLED, IDHELP, TEXT("&Help"));
 | 
						|
   }
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
   // Create a tool bar and add the toolbar bitmaps to it.
 | 
						|
   g_hWndCmdBar = CreateToolbarEx(g_hWndMain, WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS,
 | 
						|
                                  1, 9, g_hInst, IDB_TOOLBAR, tbButton, 
 | 
						|
                                  countof(tbButton), 16, 16, 16, 16, 
 | 
						|
                                  sizeof(TBBUTTON));
 | 
						|
 | 
						|
   // Get our tool tip control.
 | 
						|
   HWND hWndTT = (HWND)SendMessage(g_hWndCmdBar, TB_GETTOOLTIPS, 0, 0);
 | 
						|
 | 
						|
   // Set our tool tip strings.
 | 
						|
   TOOLINFO ti;
 | 
						|
   ti.cbSize = sizeof(ti);
 | 
						|
   int tip = 0, button; 
 | 
						|
   while (SendMessage(hWndTT, TTM_ENUMTOOLS, tip++, (LPARAM)&ti)) {
 | 
						|
      for (button = 0; button < countof(tbButton); button++) {
 | 
						|
         if (tbButton[button].idCommand == (int)ti.uId) {
 | 
						|
            ti.lpszText = szToolTips[tbButton[button].iBitmap + 1];
 | 
						|
            SendMessage(hWndTT, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);
 | 
						|
            break;
 | 
						|
         }
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   // Store the height of the tool bar for later calculations.
 | 
						|
   RECT rc;
 | 
						|
   GetWindowRect(g_hWndCmdBar, &rc);
 | 
						|
   g_cyCmdBar = rc.bottom - rc.top;
 | 
						|
 | 
						|
   // We set our wait window handle to our toolbar.
 | 
						|
   // This is the last window that will be painted during the startup of our app.
 | 
						|
   g_hWndWaitFor = g_hWndCmdBar;
 | 
						|
 | 
						|
   // Add the help item to our help menu if we have a help file.
 | 
						|
   if (fHelp) {
 | 
						|
      HMENU hMenu = GetSubMenu(GetMenu(g_hWndMain), 3);
 | 
						|
      InsertMenu(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
 | 
						|
      InsertMenu(hMenu, 0, MF_BYPOSITION | MF_ENABLED, IDHELP, TEXT("&Help\tF1"));
 | 
						|
   }
 | 
						|
 | 
						|
#endif // _WIN32_WCE
 | 
						|
 | 
						|
   // Enable Full Row Select - This feature is supported on Windows CE and was
 | 
						|
   // introduced to Win95/NT with IE 3.0.  If the user does not have a 
 | 
						|
   // COMCTL32.DLL that supports this feature, then they will just see the 
 | 
						|
   // old standard First Column Select.
 | 
						|
   SendMessage(g_hWndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT |
 | 
						|
               SendMessage(g_hWndList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0));
 | 
						|
  
 | 
						|
   // Get our expanded view option from the registry.
 | 
						|
   g_fExpandedView = GetOptionInt(TEXT("ExpandedView"), FALSE);
 | 
						|
 | 
						|
   // Show or remove menu check for expanded view option.
 | 
						|
   CheckAllMenuItems(IDM_VIEW_EXPANDED_VIEW, g_fExpandedView);
 | 
						|
 | 
						|
   // Create our columns.
 | 
						|
   AddDeleteColumns();
 | 
						|
 | 
						|
   // Set our current sort column to our name column
 | 
						|
   Sort(0, TRUE);
 | 
						|
 | 
						|
   return 0;
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void OnFileOpen() {
 | 
						|
 | 
						|
   TCHAR szPath[_MAX_PATH] = TEXT("");
 | 
						|
 | 
						|
   OPENFILENAME ofn;
 | 
						|
   ZeroMemory(&ofn, sizeof(ofn));
 | 
						|
 | 
						|
   ofn.lStructSize  = sizeof(ofn);
 | 
						|
   ofn.hwndOwner    = g_hWndMain;
 | 
						|
   ofn.hInstance    = g_hInst;
 | 
						|
   ofn.lpstrFilter  = TEXT("ZIP files (*.zip)\0*.zip\0SFX files (*.exe)\0*.exe\0All Files (*.*)\0*.*\0");
 | 
						|
   ofn.nFilterIndex = 1;
 | 
						|
   ofn.lpstrFile    = szPath;
 | 
						|
   ofn.nMaxFile     = countof(szPath);
 | 
						|
   ofn.Flags        = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
 | 
						|
   ofn.lpstrDefExt  = TEXT("zip");
 | 
						|
 | 
						|
   if (GetOpenFileName(&ofn)) {
 | 
						|
      ReadZipFileList(szPath);
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void OnActionView() {
 | 
						|
 | 
						|
   // We only allow a view if one item is selected.
 | 
						|
   int count = ListView_GetSelectedCount(g_hWndList);
 | 
						|
   if (count != 1) {
 | 
						|
      return;
 | 
						|
   }
 | 
						|
 | 
						|
   // Query the selected item for its FILE_NODE.
 | 
						|
   LV_ITEM lvi;
 | 
						|
   ZeroMemory(&lvi, sizeof(lvi));
 | 
						|
   lvi.mask = LVIF_IMAGE | LVIF_PARAM;
 | 
						|
   lvi.iItem = ListView_GetNextItem(g_hWndList, -1, LVNI_SELECTED);
 | 
						|
   ListView_GetItem(g_hWndList, &lvi);
 | 
						|
   FILE_NODE *pfn = (FILE_NODE*)lvi.lParam;
 | 
						|
 | 
						|
   // Bail out if the selected item is a folder or volume label.
 | 
						|
   if (pfn->dwAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_VOLUME)) {
 | 
						|
      MessageBox(g_hWndMain, TEXT("You cannot view folders or volume labels."), 
 | 
						|
                 g_szAppName, MB_ICONINFORMATION | MB_OK);
 | 
						|
      return;
 | 
						|
   }
 | 
						|
 | 
						|
   // Make sure our temporary directory exists.
 | 
						|
   CreateDirectory(g_szTempDir, NULL);
 | 
						|
 | 
						|
   TCHAR szPath[_MAX_PATH + 256];
 | 
						|
 | 
						|
   // Set our extraction directory to our temporary directory.
 | 
						|
   if (!SetExtractToDirectory((LPTSTR)g_szTempDir)) {
 | 
						|
      
 | 
						|
      // Create error message.  Use szPath buffer because it is handy.
 | 
						|
      _stprintf(szPath,
 | 
						|
         TEXT("Could not create \"%s\"\n\n")
 | 
						|
         TEXT("Most likely cause is that your drive is full."),
 | 
						|
         g_szTempDir);
 | 
						|
 | 
						|
      // Display error message.
 | 
						|
      MessageBox(g_hWndMain, szPath, g_szAppName, MB_ICONERROR | MB_OK);
 | 
						|
 | 
						|
      return;
 | 
						|
   }
 | 
						|
 | 
						|
   // Create our single item file array.
 | 
						|
   CHAR *argv[2] = { pfn->szPathAndMethod, NULL };
 | 
						|
 | 
						|
   // Create a buffer to store the mapped name of the file.  If the has to be
 | 
						|
   // renamed to be compatible with our file system, then we need to know that
 | 
						|
   // new name in order to open it correctly.
 | 
						|
   CHAR szMappedPath[_MAX_PATH];
 | 
						|
   *szMappedPath = '\0';
 | 
						|
 | 
						|
   // Configure our extract structure.
 | 
						|
   EXTRACT_INFO ei;
 | 
						|
   ZeroMemory(&ei, sizeof(ei));
 | 
						|
   ei.fExtract      = TRUE;
 | 
						|
   ei.dwFileCount   = 1;
 | 
						|
   ei.dwByteCount   = pfn->dwSize;
 | 
						|
   ei.szFileList    = argv;
 | 
						|
   ei.fRestorePaths = FALSE;
 | 
						|
   ei.overwriteMode = OM_PROMPT;
 | 
						|
   ei.szMappedPath  = szMappedPath;
 | 
						|
 | 
						|
   // Clear our skipped flag and set our viewing flag.
 | 
						|
   g_fSkipped = FALSE;
 | 
						|
   g_fViewing = TRUE;
 | 
						|
 | 
						|
   // Display our progress dialog and do the extraction.
 | 
						|
   DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_VIEW_PROGRESS), g_hWndMain, 
 | 
						|
                  (DLGPROC)DlgProcViewProgress, (LPARAM)&ei);
 | 
						|
 | 
						|
   // Clear our viewing flag.
 | 
						|
   g_fViewing = FALSE;
 | 
						|
 | 
						|
   // Check to see if the user skipped the file by aborting the decryption or
 | 
						|
   // overwrite prompts.  The only other case that causes us to skip a file
 | 
						|
   // is when the user enters the incorrect password too many times.  In this
 | 
						|
   // case, IZ_BADPWD will be returned.
 | 
						|
   if (g_fSkipped) {
 | 
						|
      return;
 | 
						|
   }
 | 
						|
   if (ei.result == IZ_BADPWD) {
 | 
						|
      MessageBox(g_hWndMain, TEXT("Password was incorrect.  The file has been skipped."),
 | 
						|
                 g_szAppName, MB_ICONWARNING | MB_OK);
 | 
						|
      return;
 | 
						|
   }
 | 
						|
 | 
						|
   // Check to see if the extraction failed.
 | 
						|
   if (ei.result != PK_OK) {
 | 
						|
 | 
						|
      if (ei.result == PK_ABORTED) {
 | 
						|
         _tcscpy(szPath, GetZipErrorString(ei.result));
 | 
						|
 | 
						|
      } else {
 | 
						|
         // Create error message.  Use szPath buffer because it is handy.
 | 
						|
         _stprintf(szPath,
 | 
						|
            TEXT("Could not extract \"%S\".\n\n%s\n\nTry using the Test or ")
 | 
						|
            TEXT("Extract action on the file for more details."),
 | 
						|
            *szMappedPath ? szMappedPath : pfn->szPathAndMethod,
 | 
						|
            GetZipErrorString(ei.result));
 | 
						|
      }
 | 
						|
 | 
						|
      // Display error message.
 | 
						|
      MessageBox(g_hWndMain, szPath, g_szAppName, MB_ICONERROR | MB_OK);
 | 
						|
 | 
						|
      // If we managed to create a bad file, then delete it.
 | 
						|
      if (*szMappedPath) {
 | 
						|
         mbstowcs(szPath, szMappedPath, countof(szPath));
 | 
						|
         SetFileAttributes(szPath, FILE_ATTRIBUTE_NORMAL);
 | 
						|
         if (!DeleteFile(szPath)) {
 | 
						|
            SetFileAttributes(szPath, FILE_ATTRIBUTE_READONLY);
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
      return;
 | 
						|
   }
 | 
						|
 | 
						|
   // Convert the file name to UNICODE.
 | 
						|
   mbstowcs(szPath, szMappedPath, countof(szPath));
 | 
						|
 | 
						|
   // Prepare to launch the file.
 | 
						|
   SHELLEXECUTEINFO sei;
 | 
						|
   ZeroMemory(&sei, sizeof(sei));
 | 
						|
   sei.cbSize      = sizeof(sei);
 | 
						|
   sei.hwnd        = g_hWndMain;
 | 
						|
   sei.lpDirectory = g_szTempDir;
 | 
						|
   sei.nShow       = SW_SHOWNORMAL;
 | 
						|
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
 | 
						|
   TCHAR szApp[_MAX_PATH];
 | 
						|
 | 
						|
   // On Windows CE, there is no default file association dialog that appears
 | 
						|
   // when ShellExecuteEx() is given an unknown file type.  We check to see if
 | 
						|
   // file is unknown, and display our own file association prompt.
 | 
						|
 | 
						|
   // Check our file image to see if this file has no associated viewer.
 | 
						|
   if (lvi.iImage == IMAGE_GENERIC) {
 | 
						|
 | 
						|
      // Display our file association prompt dialog.
 | 
						|
      if (IDOK != DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_VIEW_ASSOCIATION),
 | 
						|
                                 g_hWndMain, (DLGPROC)DlgProcViewAssociation,
 | 
						|
                                 (LPARAM)szApp))
 | 
						|
      {
 | 
						|
         // If the user aborted the association prompt, then delete file and exit.
 | 
						|
         SetFileAttributes(szPath, FILE_ATTRIBUTE_NORMAL);
 | 
						|
         if (!DeleteFile(szPath)) {
 | 
						|
            SetFileAttributes(szPath, FILE_ATTRIBUTE_READONLY);
 | 
						|
         }
 | 
						|
         return;
 | 
						|
      }
 | 
						|
      // Set the file to be the viewer app and the parameters to be the file.
 | 
						|
      // Note: Some applications require that arguments with spaces be quoted,
 | 
						|
      // while other applications choked when quotes we part of the filename.
 | 
						|
      // In the end, it seems safer to leave the quotes off.
 | 
						|
      sei.lpFile = szApp;
 | 
						|
      sei.lpParameters = szPath;
 | 
						|
   } else {
 | 
						|
      sei.lpFile = szPath;
 | 
						|
   }
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
   // On NT, ShellExecuteEx() will prompt user for association if needed.
 | 
						|
   sei.lpFile = szPath;
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
   // Launch the file.  All errors will be displayed by ShellExecuteEx().
 | 
						|
   ShellExecuteEx(&sei);
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void OnActionSelectAll() {
 | 
						|
   for (int i = ListView_GetItemCount(g_hWndList) - 1; i >= 0; i--) {
 | 
						|
      ListView_SetItemState(g_hWndList, i, LVIS_SELECTED, LVIS_SELECTED);
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void OnViewExpandedView() {
 | 
						|
 | 
						|
   // Toggle our expanded view option.
 | 
						|
   g_fExpandedView = !g_fExpandedView;
 | 
						|
 | 
						|
   // Show or remove menu check and toolbar button press.
 | 
						|
   CheckAllMenuItems(IDM_VIEW_EXPANDED_VIEW, g_fExpandedView);
 | 
						|
 | 
						|
   // Display the new columns.
 | 
						|
   AddDeleteColumns();
 | 
						|
 | 
						|
   // Re-sort if we just did away with out sort column.
 | 
						|
   if (!g_fExpandedView && (g_sortColumn > 3)) {
 | 
						|
      Sort(0, TRUE);
 | 
						|
   }
 | 
						|
 | 
						|
   // Write our expanded view option to the registry.
 | 
						|
   WriteOptionInt(TEXT("ExpandedView"), g_fExpandedView);
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void OnHelp() {
 | 
						|
 | 
						|
   // Prepare to launch the help file.
 | 
						|
   SHELLEXECUTEINFO sei;
 | 
						|
   ZeroMemory(&sei, sizeof(sei));
 | 
						|
   sei.cbSize      = sizeof(sei);
 | 
						|
   sei.hwnd        = g_hWndMain;
 | 
						|
   sei.lpFile      = g_szHelpFile;
 | 
						|
 | 
						|
   // Launch the file.
 | 
						|
   ShellExecuteEx(&sei);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Event Handlers for our List View
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
void OnGetDispInfo(LV_DISPINFO *plvdi) {
 | 
						|
 | 
						|
   // Make sure we have the minimum amount of data to process this event.
 | 
						|
   if ((plvdi->item.iItem < 0) || !plvdi->item.lParam || !plvdi->item.pszText) {
 | 
						|
      return;
 | 
						|
   }
 | 
						|
 | 
						|
   // Get a pointer to the file node for this item.
 | 
						|
   FILE_NODE *pFile = (FILE_NODE*)plvdi->item.lParam;
 | 
						|
 | 
						|
   CHAR szBuffer[_MAX_PATH * 2];
 | 
						|
 | 
						|
   switch (plvdi->item.iSubItem) {
 | 
						|
 | 
						|
      case 0: // Name
 | 
						|
 | 
						|
         // Copy the string to a new string while removing all non-printables.
 | 
						|
         fnfilter(pFile->szPathAndMethod, (uch*)szBuffer);
 | 
						|
 | 
						|
         // Change all forward slashes to back slashes in the buffer
 | 
						|
         ForwardSlashesToBackSlashesA(szBuffer);
 | 
						|
 | 
						|
         // Convert the string to UNICODE and store it in our list control.
 | 
						|
         mbstowcs(plvdi->item.pszText, szBuffer, plvdi->item.cchTextMax);
 | 
						|
 | 
						|
         return;
 | 
						|
 | 
						|
      case 1: // Size
 | 
						|
         FormatValue(plvdi->item.pszText, pFile->dwSize);
 | 
						|
         return;
 | 
						|
 | 
						|
      case 2: // Type
 | 
						|
         mbstowcs(plvdi->item.pszText, BuildTypeString(pFile, szBuffer), 
 | 
						|
                  plvdi->item.cchTextMax);
 | 
						|
         return;
 | 
						|
 | 
						|
      case 3: // Modified
 | 
						|
         int hour; hour = (pFile->dwModified >> 6) & 0x001F;
 | 
						|
         _stprintf(plvdi->item.pszText, TEXT("%u/%u/%u %u:%02u %cM"),
 | 
						|
                   (pFile->dwModified  >> 16) & 0x000F,
 | 
						|
                   (pFile->dwModified  >> 11) & 0x001F,
 | 
						|
                   ((pFile->dwModified >> 20) & 0x0FFF) % 100,
 | 
						|
                   (hour % 12) ? (hour % 12) : 12,
 | 
						|
                   pFile->dwModified & 0x003F,
 | 
						|
                   hour >= 12 ? 'P' : 'A');
 | 
						|
         return;
 | 
						|
 | 
						|
      case 4: // Attributes
 | 
						|
         BuildAttributesString(plvdi->item.pszText, pFile->dwAttributes);
 | 
						|
         return;
 | 
						|
 | 
						|
      case 5: // Compressed
 | 
						|
         FormatValue(plvdi->item.pszText, pFile->dwCompressedSize);
 | 
						|
         return;
 | 
						|
 | 
						|
      case 6: // Ratio
 | 
						|
         int factor; factor = ratio(pFile->dwSize, pFile->dwCompressedSize);
 | 
						|
         _stprintf(plvdi->item.pszText, TEXT("%d.%d%%"), factor / 10, 
 | 
						|
                   ((factor < 0) ? -factor : factor) % 10);
 | 
						|
         return;
 | 
						|
 | 
						|
      case 7: // Method
 | 
						|
         mbstowcs(plvdi->item.pszText, pFile->szPathAndMethod + strlen(pFile->szPathAndMethod) + 1, 
 | 
						|
                  plvdi->item.cchTextMax);
 | 
						|
         return;
 | 
						|
 | 
						|
      case 8: // CRC
 | 
						|
         _stprintf(plvdi->item.pszText, L"%08X", pFile->dwCRC);
 | 
						|
         return;
 | 
						|
 | 
						|
      case 9: // Comment
 | 
						|
         mbstowcs(plvdi->item.pszText, pFile->szComment ? pFile->szComment : "",
 | 
						|
                  plvdi->item.cchTextMax);
 | 
						|
         return;
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void OnDeleteItem(NM_LISTVIEW *pnmlv) {
 | 
						|
   if (pnmlv->lParam) {
 | 
						|
 | 
						|
      // Free any comment string associated with this item.
 | 
						|
      if (((FILE_NODE*)pnmlv->lParam)->szComment) {
 | 
						|
         delete[] (CHAR*)((FILE_NODE*)pnmlv->lParam)->szComment;
 | 
						|
      }
 | 
						|
 | 
						|
      // Free the item itself.
 | 
						|
      delete[] (LPBYTE)pnmlv->lParam;
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void OnItemChanged(NM_LISTVIEW *pnmlv) {
 | 
						|
   int count = ListView_GetSelectedCount(pnmlv->hdr.hwndFrom);
 | 
						|
   EnableAllMenuItems(IDM_FILE_PROPERTIES, count > 0);
 | 
						|
   EnableAllMenuItems(IDM_ACTION_EXTRACT,  count > 0);
 | 
						|
   EnableAllMenuItems(IDM_ACTION_TEST,     count > 0);
 | 
						|
   EnableAllMenuItems(IDM_ACTION_VIEW,     count == 1);
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** List View Sort Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
void Sort(int sortColumn, BOOL fForce) {
 | 
						|
 | 
						|
   // Do not change the column header text if it is already correct.
 | 
						|
   if (sortColumn != g_sortColumn) {
 | 
						|
 | 
						|
      TCHAR szColumn[32];
 | 
						|
      LV_COLUMN lvc;
 | 
						|
      lvc.mask = LVCF_TEXT;
 | 
						|
      lvc.pszText = szColumn; 
 | 
						|
 | 
						|
      // Remove the '^' from the current sort column.
 | 
						|
      if (g_sortColumn != -1) {
 | 
						|
         _stprintf(szColumn, (g_columns[g_sortColumn].format == LVCFMT_LEFT) ? 
 | 
						|
                   TEXT("%s   ") : TEXT("   %s"), g_columns[g_sortColumn].szName);
 | 
						|
         ListView_SetColumn(g_hWndList, g_sortColumn, &lvc);
 | 
						|
      }
 | 
						|
 | 
						|
      // Set the new sort column.
 | 
						|
      g_sortColumn = sortColumn;
 | 
						|
 | 
						|
      // Add the '^' to the new sort column.
 | 
						|
      _stprintf(szColumn, (g_columns[g_sortColumn].format == LVCFMT_LEFT) ? 
 | 
						|
                TEXT("%s ^") : TEXT("^ %s"), g_columns[g_sortColumn].szName);
 | 
						|
      ListView_SetColumn(g_hWndList, g_sortColumn, &lvc);
 | 
						|
 | 
						|
      // Sort the list by the new column.
 | 
						|
      ListView_SortItems(g_hWndList, CompareFunc, g_sortColumn);
 | 
						|
 | 
						|
   } else if (fForce) {
 | 
						|
      // Force the list to sort by the same column.
 | 
						|
      ListView_SortItems(g_hWndList, CompareFunc, g_sortColumn);
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM sortColumn) {
 | 
						|
   FILE_NODE *pFile1 = (FILE_NODE*)lParam1, *pFile2 = (FILE_NODE*)lParam2;
 | 
						|
   TCHAR szBuffer1[8], szBuffer2[8];
 | 
						|
 | 
						|
   // Return Negative value if the first item should precede the second.
 | 
						|
   // Return Positive value if the first item should follow the second.
 | 
						|
   // Return Zero if the two items are equivalent.
 | 
						|
 | 
						|
   int result = 0;
 | 
						|
 | 
						|
   // Compute the relationship based on the current sort column
 | 
						|
   switch (sortColumn) {
 | 
						|
 | 
						|
      case 1: // Size - Smallest to Largest
 | 
						|
         if (pFile1->dwSize != pFile2->dwSize) {
 | 
						|
            result = ((pFile1->dwSize < pFile2->dwSize) ? -1 : 1);
 | 
						|
         }
 | 
						|
         break;
 | 
						|
 | 
						|
      case 2: { // Type - Volume Label's first, then directories, then files
 | 
						|
         int f1 = (pFile1->dwAttributes & FILE_ATTRIBUTE_VOLUME)    ? 1 : 
 | 
						|
                  (pFile1->dwAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 2 : 3;
 | 
						|
         int f2 = (pFile2->dwAttributes & FILE_ATTRIBUTE_VOLUME)    ? 1 : 
 | 
						|
                  (pFile2->dwAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 2 : 3;
 | 
						|
         if ((f1 == 3) && (f2 == 3)) {
 | 
						|
            CHAR szType1[128];
 | 
						|
            CHAR szType2[128];
 | 
						|
            result = _stricmp(BuildTypeString(pFile1, szType1),
 | 
						|
                              BuildTypeString(pFile2, szType2));
 | 
						|
         } else {
 | 
						|
            result = f1 - f2;
 | 
						|
         }
 | 
						|
         break;
 | 
						|
      }
 | 
						|
 | 
						|
      case 3: // Modified - Newest to Oldest
 | 
						|
         if (pFile1->dwModified != pFile2->dwModified) {
 | 
						|
            result = ((pFile1->dwModified > pFile2->dwModified) ? -1 : 1);
 | 
						|
         }
 | 
						|
         break;
 | 
						|
 | 
						|
      case 4: // Attributes - String Sort
 | 
						|
         result = _tcscmp(BuildAttributesString(szBuffer1, pFile1->dwAttributes),
 | 
						|
                          BuildAttributesString(szBuffer2, pFile2->dwAttributes));
 | 
						|
         break;
 | 
						|
 | 
						|
      case 5: // Compressed Size - Smallest to Largest
 | 
						|
         if (pFile1->dwCompressedSize != pFile2->dwCompressedSize) {
 | 
						|
            result = ((pFile1->dwCompressedSize < pFile2->dwCompressedSize) ? -1 : 1);
 | 
						|
         }
 | 
						|
         break;
 | 
						|
 | 
						|
      case 6: // Ratio - Smallest to Largest
 | 
						|
         int factor1, factor2;
 | 
						|
         factor1 = ratio(pFile1->dwSize, pFile1->dwCompressedSize);
 | 
						|
         factor2 = ratio(pFile2->dwSize, pFile2->dwCompressedSize);
 | 
						|
         result = factor1 - factor2;
 | 
						|
         break;
 | 
						|
 | 
						|
      case 7: // Method - String Sort
 | 
						|
         result = _stricmp(pFile1->szPathAndMethod + strlen(pFile1->szPathAndMethod) + 1,
 | 
						|
                           pFile2->szPathAndMethod + strlen(pFile2->szPathAndMethod) + 1);
 | 
						|
         break;
 | 
						|
 | 
						|
      case 8: // CRC - Smallest to Largest
 | 
						|
         if (pFile1->dwCRC != pFile2->dwCRC) {
 | 
						|
            result = ((pFile1->dwCRC < pFile2->dwCRC) ? -1 : 1);
 | 
						|
         }
 | 
						|
         break;
 | 
						|
 | 
						|
      case 9: // Comment - String Sort
 | 
						|
         result = _stricmp(pFile1->szComment ? pFile1->szComment : "",
 | 
						|
                           pFile2->szComment ? pFile2->szComment : "");
 | 
						|
         break;
 | 
						|
   }
 | 
						|
 | 
						|
   // If the sort resulted in a tie, we use the name to break the tie.
 | 
						|
   if (result == 0) {
 | 
						|
      result = _stricmp(pFile1->szPathAndMethod, pFile2->szPathAndMethod);
 | 
						|
   }
 | 
						|
 | 
						|
   return result;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Helper/Utility Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
void SetCaptionText(LPCTSTR szPrefix) {
 | 
						|
   TCHAR szCaption[_MAX_PATH + 32];
 | 
						|
   if (szPrefix && *g_szZipFile) {
 | 
						|
      _stprintf(szCaption, TEXT("%s - %S"), szPrefix, GetFileFromPath(g_szZipFile));
 | 
						|
   } else if (szPrefix) {
 | 
						|
      _stprintf(szCaption, TEXT("%s - Pocket UnZip"), szPrefix);
 | 
						|
   } else if (*g_szZipFile) {
 | 
						|
      _stprintf(szCaption, TEXT("%S"), GetFileFromPath(g_szZipFile));
 | 
						|
   } else {
 | 
						|
      _tcscpy(szCaption, TEXT("Pocket UnZip"));
 | 
						|
   }
 | 
						|
   SetWindowText(g_hWndMain, szCaption);
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void DrawBanner(HDC hdc) {
 | 
						|
 | 
						|
   // If we were not passed in a DC, then get one now.
 | 
						|
   BOOL fReleaseDC = FALSE;
 | 
						|
   if (!hdc) {
 | 
						|
      hdc = GetDC(g_hWndMain);
 | 
						|
      fReleaseDC = TRUE;
 | 
						|
   }
 | 
						|
 | 
						|
   // Compute the banner rectangle.
 | 
						|
   RECT rc;
 | 
						|
   GetClientRect(g_hWndMain, &rc);
 | 
						|
   rc.top += g_cyCmdBar;
 | 
						|
   rc.bottom = rc.top + 22;
 | 
						|
 | 
						|
   // Fill in the background with a light grey brush.
 | 
						|
   FillRect(hdc, &rc, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
 | 
						|
 | 
						|
   // Draw a highlight line across the top of our banner.
 | 
						|
   POINT pt[2] = { { rc.left, rc.top + 1 }, { rc.right, rc.top + 1 } };
 | 
						|
 | 
						|
   SelectObject(hdc, GetStockObject(WHITE_PEN));
 | 
						|
   Polyline(hdc, pt, 2);
 | 
						|
 | 
						|
   // Get the ZIP file image.  We do this only once and cache the result.
 | 
						|
   // Note that you do not need to free icons as they are a resource.
 | 
						|
   static HICON hIcon = NULL;
 | 
						|
   if (!hIcon) {
 | 
						|
      hIcon = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_ZIPFILE), 
 | 
						|
                               IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
 | 
						|
   }
 | 
						|
   
 | 
						|
   // Draw the ZIP file image.
 | 
						|
   DrawIconEx(hdc, rc.left + 6, rc.top + 3, hIcon, 16, 16, 0, NULL, DI_NORMAL);
 | 
						|
 | 
						|
   // Set our font and colors.
 | 
						|
   HFONT hFontStock = (HFONT)SelectObject(hdc, g_hFontBanner);
 | 
						|
   SetTextColor(hdc, RGB(0, 0, 0));
 | 
						|
   SetBkMode(hdc, TRANSPARENT);
 | 
						|
 | 
						|
   rc.left   += 26;      
 | 
						|
   rc.right  -= 48;
 | 
						|
   rc.bottom -=  2;
 | 
						|
 | 
						|
   // Decide what text to display.
 | 
						|
   TCHAR szPath[_MAX_PATH + 16];
 | 
						|
   if (g_hWndWaitFor) {
 | 
						|
      _tcscpy(szPath, TEXT("Initializing..."));
 | 
						|
   } else if (*g_szZipFile) {
 | 
						|
      if (g_fLoading) {
 | 
						|
         _stprintf(szPath, TEXT("Loading %S"), g_szZipFile);
 | 
						|
      } else {
 | 
						|
         mbstowcs(szPath, g_szZipFile, countof(szPath));
 | 
						|
      }
 | 
						|
   } else {
 | 
						|
      _tcscpy(szPath, TEXT("No File Loaded"));
 | 
						|
   }
 | 
						|
 | 
						|
   // Draw the banner text.
 | 
						|
   DrawText(hdc, szPath, _tcslen(szPath), &rc,
 | 
						|
            DT_NOPREFIX | DT_SINGLELINE | DT_LEFT | DT_VCENTER);
 | 
						|
 | 
						|
   // Remove all non stock objects from the DC
 | 
						|
   SelectObject(hdc, hFontStock);
 | 
						|
 | 
						|
   // Free our DC if we created it.
 | 
						|
   if (fReleaseDC) {
 | 
						|
      ReleaseDC(g_hWndMain, hdc);
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void AddDeleteColumns() {
 | 
						|
 | 
						|
   static int curColumns = 0;
 | 
						|
   int column, newColumns = (g_fExpandedView ? countof(g_columns) : 4);
 | 
						|
 | 
						|
   // Are we adding columns?
 | 
						|
   if (newColumns > curColumns) {
 | 
						|
 | 
						|
      // Set up column structure.
 | 
						|
      TCHAR szColumn[32];
 | 
						|
      LV_COLUMN lvc;
 | 
						|
      lvc.mask = LVCF_TEXT | LVCF_FMT;
 | 
						|
      lvc.pszText = szColumn;
 | 
						|
 | 
						|
      // Loop through each column we need to add.
 | 
						|
      for (column = curColumns; column < newColumns; column++) {
 | 
						|
 | 
						|
         // Build the real column string.
 | 
						|
         _stprintf(szColumn, (g_columns[column].format == LVCFMT_LEFT) ? 
 | 
						|
                   TEXT("%s   ") : TEXT("   %s"), g_columns[column].szName);
 | 
						|
 | 
						|
         // Insert the column with the correct format.
 | 
						|
         lvc.fmt = g_columns[column].format;
 | 
						|
         ListView_InsertColumn(g_hWndList, column, &lvc);
 | 
						|
      }
 | 
						|
 | 
						|
   // Otherwise, we are removing columns.
 | 
						|
   } else {
 | 
						|
 | 
						|
      // Loop through each column we need to delete and delete them.
 | 
						|
      for (column = curColumns - 1; column >= newColumns; column--) {
 | 
						|
         ListView_DeleteColumn(g_hWndList, column);
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   // Store our new column count statically to help us with the next call to 
 | 
						|
   // AddDeleteColumns().
 | 
						|
   curColumns = newColumns;
 | 
						|
 | 
						|
   // Re-calcualte our column widths.
 | 
						|
   ResizeColumns();
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void ResizeColumns() {
 | 
						|
 | 
						|
   // Hide the window since we are going to be doing some column shifting.
 | 
						|
   ShowWindow(g_hWndList, SW_HIDE);
 | 
						|
 | 
						|
   // Resize all the columns to best fit both the column data and the header.
 | 
						|
   for (int column = 0; column < countof(g_columns); column++) {
 | 
						|
      ListView_SetColumnWidth(g_hWndList, column, LVSCW_AUTOSIZE_USEHEADER);
 | 
						|
   }
 | 
						|
 | 
						|
   // Show the window again.
 | 
						|
   ShowWindow(g_hWndList, SW_SHOW);
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
LPCTSTR GetZipErrorString(int error) {
 | 
						|
 | 
						|
   switch (error) {
 | 
						|
 | 
						|
      case PK_OK: // no error
 | 
						|
         return TEXT("Operation completed successfully.");
 | 
						|
 | 
						|
      case PK_WARN: // warning error
 | 
						|
         return TEXT("There were warnings during the operation.");
 | 
						|
 | 
						|
      case PK_ERR:    // error in zipfile
 | 
						|
      case PK_BADERR: // severe error in zipfile
 | 
						|
         return TEXT("The operation could not be successfully completed.  ")
 | 
						|
                TEXT("Possible causes are that the ZIP file contains errors, ")
 | 
						|
                TEXT("or that an error occurred while trying to create a ")
 | 
						|
                TEXT("directory or file.");
 | 
						|
 | 
						|
      case PK_MEM:  // insufficient memory
 | 
						|
      case PK_MEM2: // insufficient memory
 | 
						|
      case PK_MEM3: // insufficient memory
 | 
						|
      case PK_MEM4: // insufficient memory
 | 
						|
      case PK_MEM5: // insufficient memory
 | 
						|
         return TEXT("There is not enough memory to perform the operation.  ")
 | 
						|
                TEXT("Try closing other running applications or adjust your ")
 | 
						|
                TEXT("memory configuration.");
 | 
						|
 | 
						|
      case PK_NOZIP: // zipfile not found or corrupt.
 | 
						|
         return TEXT("The ZIP file either contains errors or could not be found.");
 | 
						|
 | 
						|
      case PK_PARAM: // bad or illegal parameters specified
 | 
						|
         break; // Not used in the Windows CE port.
 | 
						|
 | 
						|
      case PK_FIND: // no files found in ZIP file
 | 
						|
         return TEXT("The ZIP file contains errors that prevented the ")
 | 
						|
                TEXT("operation from completing successfully.  A possible ")
 | 
						|
                TEXT("cause is that one or more of the files listed as being ")
 | 
						|
                TEXT("in the ZIP file could not actually be found within the ")
 | 
						|
                TEXT("ZIP file itself.");
 | 
						|
 | 
						|
      case PK_DISK: // disk full or file locked
 | 
						|
         return TEXT("An error occurred while attempting to save a file.  ")
 | 
						|
                TEXT("Possible causes are that your file storage is full or ")
 | 
						|
                TEXT("read only, or that a file with the same name already ")
 | 
						|
                TEXT("exists and is locked by another application.");
 | 
						|
 | 
						|
      case PK_EOF: // unexpected end of file
 | 
						|
         return TEXT("The ZIP file contains errors that prevented the ")
 | 
						|
                TEXT("operation from completing successfully.  A possible ")
 | 
						|
                TEXT("cause is that your ZIP file is incomplete and might be ")
 | 
						|
                TEXT("truncated.");
 | 
						|
 | 
						|
      case IZ_UNSUP:  // no files found: all unsup. compr/encrypt.
 | 
						|
         return TEXT("None of the files could be processed because they were ")
 | 
						|
                TEXT("all compressed using an unsupported compression or ")
 | 
						|
                TEXT("encryption algorithm.");
 | 
						|
         
 | 
						|
      case IZ_BADPWD: // no files found: all had bad password.
 | 
						|
         return TEXT("None of the files could be processed because all the ")
 | 
						|
                TEXT("password(s) specified were incorrect.");
 | 
						|
 | 
						|
      case PK_EXCEPTION: // exception occurred
 | 
						|
         return TEXT("An internal error occurred.  Possible causes are that ")
 | 
						|
                TEXT("you are out of memory, you are out of file storage ")
 | 
						|
                TEXT("space, the ZIP file contains unexpected errors, or there ")
 | 
						|
                TEXT("is a bug in our program (that's why it's free).");
 | 
						|
 | 
						|
      case PK_ABORTED: // user aborted
 | 
						|
         return TEXT("The operation was aborted.");
 | 
						|
   }
 | 
						|
 | 
						|
   return TEXT("An unknown error occurred while processing the ZIP file.");
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void AddFileToListView(FILE_NODE *pFile) {
 | 
						|
 | 
						|
   // Set up our List View Item structure.
 | 
						|
   LV_ITEM lvi;
 | 
						|
   ZeroMemory(&lvi, sizeof(lvi));
 | 
						|
   lvi.mask    = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
 | 
						|
   lvi.pszText = LPSTR_TEXTCALLBACK;
 | 
						|
   lvi.lParam  = (LPARAM)pFile;
 | 
						|
   lvi.iImage  = IMAGE_GENERIC;
 | 
						|
 | 
						|
   // Special case Volume Labels.
 | 
						|
   if (pFile->dwAttributes & FILE_ATTRIBUTE_VOLUME) {
 | 
						|
      pFile->szType = "Volume Label";
 | 
						|
      lvi.iImage = IMAGE_VOLUME;
 | 
						|
 | 
						|
   // Special case folders.
 | 
						|
   } else if (pFile->dwAttributes & FILE_ATTRIBUTE_DIRECTORY) {
 | 
						|
      pFile->szType = "Folder";
 | 
						|
      lvi.iImage = IMAGE_FOLDER;
 | 
						|
 | 
						|
   // Do a lookup on the file extension.
 | 
						|
   } else {
 | 
						|
 | 
						|
      // Locate the file portion of our path.
 | 
						|
      LPCSTR pszFile = GetFileFromPath(pFile->szPathAndMethod);
 | 
						|
 | 
						|
      // Find the extension portion of our file.
 | 
						|
      LPCSTR pszExt = strrchr(pszFile, '.');
 | 
						|
 | 
						|
      // Search our known extension list for this extension.
 | 
						|
      if (pszExt && *(pszExt + 1)) {
 | 
						|
 | 
						|
         // Loop through our linked list
 | 
						|
         for (FILE_TYPE_NODE *pft = g_pftHead; pft; pft = pft->pNext) {
 | 
						|
 | 
						|
            // Check for a match.
 | 
						|
            if (!_stricmp(pszExt + 1, pft->szExtAndDesc)) {
 | 
						|
 | 
						|
               // We found a match, store the image and type string and exit loop.
 | 
						|
               lvi.iImage = pft->image;
 | 
						|
               pFile->szType = pft->szExtAndDesc + strlen(pft->szExtAndDesc) + 1;
 | 
						|
               if (!*pFile->szType) {
 | 
						|
                  pFile->szType = NULL;
 | 
						|
               }
 | 
						|
               break;
 | 
						|
            }
 | 
						|
         }
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   // Add the item to our list.
 | 
						|
   ListView_InsertItem(g_hWndList, &lvi);
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void EnableAllMenuItems(UINT uMenuItem, BOOL fEnabled) {
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
   HMENU hMenu = CommandBar_GetMenu(g_hWndCmdBar, 0);
 | 
						|
#else
 | 
						|
   HMENU hMenu = GetMenu(g_hWndMain);
 | 
						|
#endif
 | 
						|
   EnableMenuItem(hMenu, uMenuItem, fEnabled ? MF_ENABLED : MF_GRAYED);
 | 
						|
   SendMessage(g_hWndCmdBar, TB_ENABLEBUTTON, uMenuItem, MAKELONG(fEnabled, 0));
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void CheckAllMenuItems(UINT uMenuItem, BOOL fChecked) {
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
   HMENU hMenu = CommandBar_GetMenu(g_hWndCmdBar, 0);
 | 
						|
#else
 | 
						|
   HMENU hMenu = GetMenu(g_hWndMain);
 | 
						|
#endif
 | 
						|
   CheckMenuItem(hMenu, uMenuItem, fChecked ? MF_CHECKED : MF_UNCHECKED);
 | 
						|
   SendMessage(g_hWndCmdBar, TB_PRESSBUTTON, uMenuItem, MAKELONG(fChecked, 0));
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void CenterWindow(HWND hWnd) {
 | 
						|
 | 
						|
   RECT rc, rcParent;
 | 
						|
 | 
						|
   // Get our window rectangle.
 | 
						|
   GetWindowRect(hWnd, &rc);
 | 
						|
 | 
						|
   // Get our parent's window rectangle.
 | 
						|
   GetWindowRect(GetParent(hWnd), &rcParent);
 | 
						|
 | 
						|
   // Center our window over our parent's window.
 | 
						|
   SetWindowPos(hWnd, NULL, 
 | 
						|
      rcParent.left + ((rcParent.right  - rcParent.left) - (rc.right  - rc.left)) / 2,
 | 
						|
      rcParent.top  + ((rcParent.bottom - rcParent.top ) - (rc.bottom - rc.top )) / 2,
 | 
						|
      0, 0, SWP_NOZORDER | SWP_NOSIZE);
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void AddTextToEdit(LPCSTR szText) {
 | 
						|
 | 
						|
   if (!g_hWndEdit) {
 | 
						|
      return;
 | 
						|
   }
 | 
						|
 | 
						|
   // Add the characters one by one to our edit box while performing the 
 | 
						|
   // the following newline conversions:
 | 
						|
   //    Single CR -> CR/LF
 | 
						|
   //    Single LF -> CR/LF
 | 
						|
   //    CR and LF -> CR/LF
 | 
						|
   //    LF and CR -> CR/LF
 | 
						|
   //    0 - 31    -> ^char
 | 
						|
 | 
						|
   TCHAR szOut[256], *pszOut = szOut;
 | 
						|
   CHAR *pszIn = (LPSTR)szText, cPrev = '\0';
 | 
						|
 | 
						|
   while (*pszIn) {
 | 
						|
 | 
						|
      if (*pszIn == '\n') {
 | 
						|
         if (cPrev == '\r') {
 | 
						|
            cPrev = '\0';
 | 
						|
         } else {
 | 
						|
            *(pszOut++) = TEXT('\r');
 | 
						|
            *(pszOut++) = TEXT('\n');
 | 
						|
            cPrev = '\n';
 | 
						|
         }
 | 
						|
 | 
						|
      } else if (*pszIn == '\r') {
 | 
						|
         if (cPrev == '\n') {
 | 
						|
            cPrev = '\0';
 | 
						|
         } else {
 | 
						|
            *(pszOut++) = TEXT('\r');
 | 
						|
            *(pszOut++) = TEXT('\n');
 | 
						|
            cPrev = '\r';
 | 
						|
         }
 | 
						|
 | 
						|
      } else if ((*pszIn < 32) && (*pszIn != '\t')) {
 | 
						|
         *(pszOut++) = (TCHAR)'^';
 | 
						|
         *(pszOut++) = (TCHAR)(64 + *pszIn);
 | 
						|
         cPrev = *pszIn;
 | 
						|
 | 
						|
      } else {
 | 
						|
         *(pszOut++) = (TCHAR)*pszIn;
 | 
						|
         cPrev = *pszIn;
 | 
						|
      }
 | 
						|
      pszIn++;
 | 
						|
 | 
						|
      // If our out buffer is full, then dump it to the edit box.
 | 
						|
      if ((pszOut - szOut) > 253) {
 | 
						|
         *pszOut = TEXT('\0');
 | 
						|
         SendMessage(g_hWndEdit, EM_SETSEL, 65536, 65536);
 | 
						|
         SendMessage(g_hWndEdit, EM_REPLACESEL, FALSE, (LPARAM)szOut);
 | 
						|
         pszOut = szOut;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   // One final flush of any partially full out buffer.
 | 
						|
   if (pszOut > szOut) {
 | 
						|
      *pszOut = TEXT('\0');
 | 
						|
      SendMessage(g_hWndEdit, EM_SETSEL, 65536, 65536);
 | 
						|
      SendMessage(g_hWndEdit, EM_REPLACESEL, FALSE, (LPARAM)szOut);
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
LPTSTR FormatValue(LPTSTR szValue, DWORD dwValue) {
 | 
						|
   DWORD dw = 0, dwGroup[4] = { 0, 0, 0, 0 };
 | 
						|
   while (dwValue) {
 | 
						|
      dwGroup[dw++] = dwValue % 1000;
 | 
						|
      dwValue /= 1000;
 | 
						|
   }
 | 
						|
   switch (dw) {
 | 
						|
      case 2:  _stprintf(szValue, TEXT("%u,%03u"), dwGroup[1], dwGroup[0]); break;
 | 
						|
      case 3:  _stprintf(szValue, TEXT("%u,%03u,%03u"), dwGroup[2], dwGroup[1], dwGroup[0]); break;
 | 
						|
      case 4:  _stprintf(szValue, TEXT("%u,%03u,%03u,%03u"), dwGroup[3], dwGroup[2], dwGroup[1], dwGroup[0]); break;
 | 
						|
      default: _stprintf(szValue, TEXT("%u"), dwGroup[0]);
 | 
						|
   }
 | 
						|
   return szValue;
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
LPTSTR BuildAttributesString(LPTSTR szBuffer, DWORD dwAttributes) {
 | 
						|
   // Build the attribute string according to the flags specified for this file.
 | 
						|
   _stprintf(szBuffer, TEXT("%s%s%s%s%s%s%s%s"),
 | 
						|
             (dwAttributes & FILE_ATTRIBUTE_VOLUME)    ? TEXT("V") : TEXT(""),
 | 
						|
             (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) ? TEXT("D") : TEXT(""),
 | 
						|
             (dwAttributes & FILE_ATTRIBUTE_READONLY)  ? TEXT("R") : TEXT(""),
 | 
						|
             (dwAttributes & FILE_ATTRIBUTE_ARCHIVE)   ? TEXT("A") : TEXT(""),
 | 
						|
             (dwAttributes & FILE_ATTRIBUTE_HIDDEN)    ? TEXT("H") : TEXT(""),
 | 
						|
             (dwAttributes & FILE_ATTRIBUTE_SYSTEM)    ? TEXT("S") : TEXT(""),
 | 
						|
             (dwAttributes & FILE_ATTRIBUTE_ENCRYPTED) ? TEXT("E") : TEXT(""),
 | 
						|
             (dwAttributes & FILE_ATTRIBUTE_COMMENT)   ? TEXT("C") : TEXT(""));
 | 
						|
   return szBuffer;
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
LPCSTR BuildTypeString(FILE_NODE *pFile, LPSTR szType) {
 | 
						|
 | 
						|
   // First check to see if we have a known description.
 | 
						|
   if (pFile->szType) {
 | 
						|
      return pFile->szType;
 | 
						|
   }
 | 
						|
 | 
						|
   // Locate the file portion of our path.
 | 
						|
   LPCSTR pszFile = GetFileFromPath(pFile->szPathAndMethod);
 | 
						|
 | 
						|
   // Get the extension portion of the file.
 | 
						|
   LPCSTR pszExt = strrchr(pszFile, '.');
 | 
						|
 | 
						|
   // If we have an extension create a type name for this file.
 | 
						|
   if (pszExt && *(pszExt + 1)) {
 | 
						|
      strcpy(szType, pszExt + 1);
 | 
						|
      _strupr(szType);
 | 
						|
      strcat(szType, " File");
 | 
						|
      return szType;
 | 
						|
   }
 | 
						|
   
 | 
						|
   // If no extension, then use the default "File".
 | 
						|
   return "File";
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
LPCSTR GetFileFromPath(LPCSTR szPath) {
 | 
						|
   LPCSTR p1 = strrchr(szPath, '/'), p2 = strrchr(szPath, '\\');
 | 
						|
   if (p1 && (p1 > p2)) {
 | 
						|
      return p1 + 1;
 | 
						|
   } else if (p2) {
 | 
						|
      return p2 + 1;
 | 
						|
   }
 | 
						|
   return szPath;
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void ForwardSlashesToBackSlashesA(LPSTR szBuffer) {
 | 
						|
   while (*szBuffer) {
 | 
						|
      if (*szBuffer == '/') {
 | 
						|
         *szBuffer = '\\';
 | 
						|
      }
 | 
						|
      szBuffer++;
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void ForwardSlashesToBackSlashesW(LPWSTR szBuffer) {
 | 
						|
   while (*szBuffer) {
 | 
						|
      if (*szBuffer == L'/') {
 | 
						|
         *szBuffer = L'\\';
 | 
						|
      }
 | 
						|
      szBuffer++;
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void DeleteDirectory(LPTSTR szPath) {
 | 
						|
 | 
						|
   // Make note to where the end of our path is.
 | 
						|
   LPTSTR szEnd = szPath + _tcslen(szPath);
 | 
						|
 | 
						|
   // Add our search spec to the path.
 | 
						|
   _tcscpy(szEnd, TEXT("\\*.*"));
 | 
						|
 | 
						|
   // Start a directory search.
 | 
						|
   WIN32_FIND_DATA w32fd;
 | 
						|
   HANDLE hFind = FindFirstFile(szPath, &w32fd);
 | 
						|
 | 
						|
   // Loop through all entries in this directory.
 | 
						|
   if (hFind != INVALID_HANDLE_VALUE) {
 | 
						|
 | 
						|
      do {
 | 
						|
         // Append the file/directory name to the path.
 | 
						|
         _tcscpy(szEnd + 1, w32fd.cFileName);
 | 
						|
 | 
						|
         // Check to see if this entry is a subdirectory.
 | 
						|
         if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
 | 
						|
 | 
						|
            // Ignore current directory (.) and previous directory (..)
 | 
						|
            if (_tcscmp(w32fd.cFileName, TEXT("."))   && 
 | 
						|
                _tcscmp(w32fd.cFileName, TEXT("..")))
 | 
						|
            {
 | 
						|
               // Recurse into DeleteDirectory() to delete subdirectory.
 | 
						|
               DeleteDirectory(szPath);
 | 
						|
            }
 | 
						|
 | 
						|
         // Otherwise, it must be a file.
 | 
						|
         } else {
 | 
						|
 | 
						|
            // If the file is marked as read-only, then change to read/write.
 | 
						|
            if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
 | 
						|
               SetFileAttributes(szPath, FILE_ATTRIBUTE_NORMAL);
 | 
						|
            }
 | 
						|
 | 
						|
            // Attempt to delete the file.  If we fail and the file used to be
 | 
						|
            // read-only, then set the read-only bit back on it.
 | 
						|
            if (!DeleteFile(szPath) && 
 | 
						|
                (w32fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
 | 
						|
            {
 | 
						|
               SetFileAttributes(szPath, FILE_ATTRIBUTE_READONLY);
 | 
						|
            }
 | 
						|
         }
 | 
						|
 | 
						|
      // Get the next directory entry.
 | 
						|
      } while (FindNextFile(hFind, &w32fd));
 | 
						|
 | 
						|
      // Close the directory search.
 | 
						|
      FindClose(hFind);
 | 
						|
   }
 | 
						|
 | 
						|
   // Remove the directory.
 | 
						|
   *szEnd = TEXT('\0');
 | 
						|
   RemoveDirectory(szPath);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Registry Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
void RegWriteKey(HKEY hKeyRoot, LPCTSTR szSubKey, LPCTSTR szValue) {
 | 
						|
   HKEY  hKey = NULL;
 | 
						|
   DWORD dwDisposition;
 | 
						|
 | 
						|
   if (RegCreateKeyEx(hKeyRoot, szSubKey, 0, NULL, 0, KEY_SET_VALUE, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) {
 | 
						|
      if (szValue) {
 | 
						|
         RegSetValueEx(hKey, NULL, 0, REG_SZ, (LPBYTE)szValue, 
 | 
						|
                       sizeof(TCHAR) * (_tcslen(szValue) + 1));
 | 
						|
      }
 | 
						|
      RegCloseKey(hKey);
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
BOOL RegReadKey(HKEY hKeyRoot, LPCTSTR szSubKey, LPTSTR szValue, DWORD cBytes) {
 | 
						|
   *szValue = TEXT('\0');
 | 
						|
   HKEY hKey = NULL;
 | 
						|
   LRESULT lResult = -1;
 | 
						|
 | 
						|
   if (RegOpenKeyEx(hKeyRoot, szSubKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
 | 
						|
      lResult = RegQueryValueEx(hKey, NULL, NULL, NULL, (LPBYTE)szValue, &cBytes);
 | 
						|
      RegCloseKey(hKey);
 | 
						|
   }
 | 
						|
   return ((lResult == ERROR_SUCCESS) && *szValue);
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void WriteOptionString(LPCTSTR szOption, LPCTSTR szValue) {
 | 
						|
   HKEY hKey = NULL;
 | 
						|
 | 
						|
   if (RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegKey, 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {
 | 
						|
      RegSetValueEx(hKey, szOption, 0, REG_SZ, (LPBYTE)szValue, 
 | 
						|
                    sizeof(TCHAR) * (_tcslen(szValue) + 1));
 | 
						|
      RegCloseKey(hKey);
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void WriteOptionInt(LPCTSTR szOption, DWORD dwValue) {
 | 
						|
   HKEY hKey = NULL;
 | 
						|
 | 
						|
   if (RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegKey, 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {
 | 
						|
      RegSetValueEx(hKey, szOption, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
 | 
						|
      RegCloseKey(hKey);
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
LPTSTR GetOptionString(LPCTSTR szOption, LPCTSTR szDefault, LPTSTR szValue, DWORD nSize) {
 | 
						|
   HKEY hKey = NULL;
 | 
						|
   LONG lResult = -1;
 | 
						|
 | 
						|
   if (RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
 | 
						|
      lResult = RegQueryValueEx(hKey, szOption, NULL, NULL, (LPBYTE)szValue, &nSize);
 | 
						|
      RegCloseKey(hKey);
 | 
						|
   }
 | 
						|
   if (lResult != ERROR_SUCCESS) {
 | 
						|
      _tcscpy(szValue, szDefault);
 | 
						|
   }
 | 
						|
   return szValue;
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
DWORD GetOptionInt(LPCTSTR szOption, DWORD dwDefault) {
 | 
						|
   HKEY  hKey = NULL;
 | 
						|
   LONG  lResult = -1;
 | 
						|
   DWORD dwValue;
 | 
						|
   DWORD nSize = sizeof(dwValue);
 | 
						|
 | 
						|
   if (RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
 | 
						|
      lResult = RegQueryValueEx(hKey, szOption, NULL, NULL, (LPBYTE)&dwValue, &nSize);
 | 
						|
      RegCloseKey(hKey);
 | 
						|
   }
 | 
						|
   return (lResult == ERROR_SUCCESS) ? dwValue : dwDefault;
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** EDIT Control Subclass Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
void DisableEditing(HWND hWndEdit) {
 | 
						|
   
 | 
						|
   // Make sure the control does not have ES_READONLY or ES_WANTRETURN styles.
 | 
						|
   DWORD dwStyle = (DWORD)GetWindowLong(hWndEdit, GWL_STYLE);
 | 
						|
   if (dwStyle & (ES_READONLY | ES_WANTRETURN)) {
 | 
						|
      SetWindowLong(hWndEdit, GWL_STYLE, dwStyle & ~(ES_READONLY | ES_WANTRETURN));
 | 
						|
   }
 | 
						|
 | 
						|
   // Subclass the control so we can intercept certain keys.
 | 
						|
   g_wpEdit = (WNDPROC)GetWindowLong(hWndEdit, GWL_WNDPROC);
 | 
						|
   SetWindowLong(hWndEdit, GWL_WNDPROC, (LONG)EditSubclassProc);
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
LRESULT CALLBACK EditSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 | 
						|
 | 
						|
   BOOL fCtrl, fShift;
 | 
						|
 | 
						|
   switch (uMsg) {
 | 
						|
      // For cut, paste, delete, and undo, the control post itself a message.
 | 
						|
      // we throw away that message.  This works as a fail-safe in case we miss
 | 
						|
      // some keystroke that causes one of these operations.  This also disables
 | 
						|
      // the context menu on NT from causing one of these actions to occur.
 | 
						|
      case WM_CUT:
 | 
						|
      case WM_PASTE:
 | 
						|
      case WM_CLEAR:
 | 
						|
      case WM_UNDO:
 | 
						|
         MessageBeep(0);
 | 
						|
         return 0;
 | 
						|
 | 
						|
      // WM_CHAR is used for normal characters. A-Z, numbers, symbols, enter,
 | 
						|
      // backspace, esc, and tab. In does not include del or movement keys.
 | 
						|
      case WM_CHAR:
 | 
						|
         fCtrl  = (GetKeyState(VK_CONTROL) & 0x8000) ? TRUE : FALSE;
 | 
						|
 | 
						|
         // We only allow CTRL-C (copy), plain ESC, plain TAB, plain ENTER.
 | 
						|
         if (( fCtrl && (wParam == 3))         ||
 | 
						|
             (!fCtrl && (wParam == VK_ESCAPE)) ||
 | 
						|
             (!fCtrl && (wParam == VK_RETURN)) ||
 | 
						|
             (!fCtrl && (wParam == VK_TAB)))
 | 
						|
         {
 | 
						|
            break;
 | 
						|
         }
 | 
						|
         MessageBeep(0);
 | 
						|
         return 0;
 | 
						|
 | 
						|
      // WM_KEYDOWN handles del, insert, arrows, pg up/down, home/end.
 | 
						|
      case WM_KEYDOWN:
 | 
						|
         fCtrl  = (GetKeyState(VK_CONTROL) & 0x8000) ? TRUE : FALSE;
 | 
						|
         fShift = (GetKeyState(VK_SHIFT)   & 0x8000) ? TRUE : FALSE;
 | 
						|
 | 
						|
         // Skip all forms of DELETE, SHIFT-INSERT (paste), 
 | 
						|
         // CTRL-RETURN (hard-return), and CTRL-TAB (hard-tab).
 | 
						|
         if ((          (wParam == VK_DELETE)) || 
 | 
						|
             (fShift && (wParam == VK_INSERT)) ||
 | 
						|
             (fCtrl  && (wParam == VK_RETURN)) ||
 | 
						|
             (fCtrl  && (wParam == VK_TAB)))
 | 
						|
         {
 | 
						|
            MessageBeep(0);
 | 
						|
            return 0;
 | 
						|
         }
 | 
						|
         break;
 | 
						|
   }
 | 
						|
   return CallWindowProc(g_wpEdit, hWnd, uMsg, wParam, lParam);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** MRU Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
int GetMenuString(HMENU hMenu, UINT uIDItem, LPTSTR lpString, int nMaxCount, 
 | 
						|
                  UINT uFlag) {
 | 
						|
   MENUITEMINFO mii;
 | 
						|
   ZeroMemory(&mii, sizeof(mii));
 | 
						|
   mii.cbSize = sizeof(mii);
 | 
						|
   mii.fMask = MIIM_TYPE;
 | 
						|
   mii.dwTypeData = lpString;
 | 
						|
   mii.cch = nMaxCount;
 | 
						|
   return (GetMenuItemInfo(hMenu, uIDItem, uFlag == MF_BYPOSITION, &mii) ?
 | 
						|
           mii.cch : 0);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void InitializeMRU() {
 | 
						|
   
 | 
						|
   TCHAR szMRU[MRU_MAX_FILE][_MAX_PATH + 4], szOption[8];
 | 
						|
   int   i, j;
 | 
						|
 | 
						|
   // Get our menu handle.
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
   HMENU hMenu = GetSubMenu(CommandBar_GetMenu(g_hWndCmdBar, 0), 0);
 | 
						|
#else
 | 
						|
   HMENU hMenu = GetSubMenu(GetMenu(g_hWndMain), 0);
 | 
						|
#endif
 | 
						|
 | 
						|
   // Read all our current MRUs from the registry.
 | 
						|
   for (i = 0, j = 0; i < MRU_MAX_FILE; i++) {
 | 
						|
 | 
						|
      // Build option name for current MRU and read from registry.
 | 
						|
      _stprintf(szOption, TEXT("MRU%d"), i+1);
 | 
						|
      GetOptionString(szOption, TEXT(""), &szMRU[i][3], sizeof(TCHAR) * _MAX_PATH);
 | 
						|
 | 
						|
      // If this MRU exists, then add it.
 | 
						|
      if (szMRU[i][3]) {
 | 
						|
 | 
						|
         // Build the accelerator prefix for this menu item.
 | 
						|
         szMRU[i][0] = TEXT('&');
 | 
						|
         szMRU[i][1] = TEXT('1') + j;
 | 
						|
         szMRU[i][2] = TEXT(' ');
 | 
						|
 | 
						|
         // Add the item to our menu.
 | 
						|
         InsertMenu(hMenu, 4 + j, MF_BYPOSITION | MF_STRING, MRU_START_ID + j,
 | 
						|
                    szMRU[i]);
 | 
						|
 | 
						|
         // Increment our actual MRU count.
 | 
						|
         j++;
 | 
						|
      }
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void AddFileToMRU(LPCSTR szFile) {
 | 
						|
   
 | 
						|
   TCHAR szMRU[MRU_MAX_FILE + 1][_MAX_PATH + 4], szOption[8];
 | 
						|
   int   i, j;
 | 
						|
 | 
						|
   // Store the new file in our first MRU index.
 | 
						|
   mbstowcs(&szMRU[0][3], szFile, _MAX_PATH);
 | 
						|
 | 
						|
   //---------------------------------------------------------------------------
 | 
						|
   // We first read the current MRU list from the registry, merge in our new
 | 
						|
   // file at the top, and then write back to the registry.  The registry merge
 | 
						|
   // is done to allow multiple instances of Pocket UnZip to maintain a global
 | 
						|
   // MRU list independent to this current instance's MRU list.
 | 
						|
   //---------------------------------------------------------------------------
 | 
						|
 | 
						|
   // Read all our current MRUs from the registry.
 | 
						|
   for (i = 1; i <= MRU_MAX_FILE; i++) {
 | 
						|
 | 
						|
      // Build option name for current MRU and read from registry.
 | 
						|
      _stprintf(szOption, TEXT("MRU%d"), i);
 | 
						|
      GetOptionString(szOption, TEXT(""), &szMRU[i][3], sizeof(TCHAR) * _MAX_PATH);
 | 
						|
   }
 | 
						|
 | 
						|
   // Write our new merged MRU list back to the registry.
 | 
						|
   for (i = 0, j = 0; (i <= MRU_MAX_FILE) && (j < MRU_MAX_FILE); i++) {
 | 
						|
 | 
						|
      // If this MRU exists and is different then our new file, then add it.
 | 
						|
      if ((i == 0) || (szMRU[i][3] && _tcsicmp(&szMRU[0][3], &szMRU[i][3]))) {
 | 
						|
 | 
						|
         // Build option name for current MRU and write to registry.
 | 
						|
         _stprintf(szOption, TEXT("MRU%d"), ++j);
 | 
						|
         WriteOptionString(szOption, &szMRU[i][3]);
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   //---------------------------------------------------------------------------
 | 
						|
   // The next thing we need to do is read our local MRU from our File menu,
 | 
						|
   // merge in our new file, and store the new list back to our File menu.
 | 
						|
   //---------------------------------------------------------------------------
 | 
						|
 | 
						|
   // Get our menu handle.
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
   HMENU hMenu = GetSubMenu(CommandBar_GetMenu(g_hWndCmdBar, 0), 0);
 | 
						|
#else
 | 
						|
   HMENU hMenu = GetSubMenu(GetMenu(g_hWndMain), 0);
 | 
						|
#endif
 | 
						|
 | 
						|
   // Read all our current MRUs from our File Menu.
 | 
						|
   for (i = 1; i <= MRU_MAX_FILE; i++) {
 | 
						|
 | 
						|
      // Query our file Menu for a MRU file.
 | 
						|
      if (GetMenuString(hMenu, MRU_START_ID + i - 1, szMRU[i], 
 | 
						|
                        countof(szMRU[0]), MF_BYCOMMAND))
 | 
						|
      {
 | 
						|
         // Delete this item from the menu for now.
 | 
						|
         DeleteMenu(hMenu, MRU_START_ID + i - 1, MF_BYCOMMAND);
 | 
						|
      } else {
 | 
						|
         szMRU[i][3] = TEXT('\0');
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   // Write our new merged MRU list back to the File menu.
 | 
						|
   for (i = 0, j = 0; (i <= MRU_MAX_FILE) && (j < MRU_MAX_FILE); i++) {
 | 
						|
 | 
						|
      // If this MRU exists and is different then our new file, then add it.
 | 
						|
      if ((i == 0) || (szMRU[i][3] && _tcsicmp(&szMRU[0][3], &szMRU[i][3]))) {
 | 
						|
 | 
						|
         // Build the accelerator prefix for this menu item.
 | 
						|
         szMRU[i][0] = TEXT('&');
 | 
						|
         szMRU[i][1] = TEXT('1') + j;
 | 
						|
         szMRU[i][2] = TEXT(' ');
 | 
						|
 | 
						|
         // Add the item to our menu.
 | 
						|
         InsertMenu(hMenu, 4 + j, MF_BYPOSITION | MF_STRING, MRU_START_ID + j,
 | 
						|
                    szMRU[i]);
 | 
						|
 | 
						|
         // Increment our actual MRU count.
 | 
						|
         j++;
 | 
						|
      }
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void RemoveFileFromMRU(LPCTSTR szFile) {
 | 
						|
 | 
						|
   TCHAR szMRU[MRU_MAX_FILE][_MAX_PATH + 4], szOption[8];
 | 
						|
   int   i, j;
 | 
						|
   BOOL  fFound;
 | 
						|
 | 
						|
   //---------------------------------------------------------------------------
 | 
						|
   // We first look for this file in our global MRU stored in the registry.  We
 | 
						|
   // read the current MRU list from the registry, and then write it back while
 | 
						|
   // removing all occurrances of the file specified.
 | 
						|
   //---------------------------------------------------------------------------
 | 
						|
 | 
						|
   // Read all our current MRUs from the registry.
 | 
						|
   for (i = 0, fFound = FALSE; i < MRU_MAX_FILE; i++) {
 | 
						|
 | 
						|
      // Build option name for current MRU and read from registry.
 | 
						|
      _stprintf(szOption, TEXT("MRU%d"), i+1);
 | 
						|
      GetOptionString(szOption, TEXT(""), &szMRU[i][3], sizeof(TCHAR) * _MAX_PATH);
 | 
						|
 | 
						|
      // Check for a match.
 | 
						|
      if (!_tcsicmp(szFile, &szMRU[i][3])) {
 | 
						|
         szMRU[i][3] = TEXT('\0');
 | 
						|
         fFound = TRUE;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   // Only write the MRU back to the registry if we found a file to remove.
 | 
						|
   if (fFound) {
 | 
						|
 | 
						|
      // Write the updated MRU list back to the registry.
 | 
						|
      for (i = 0, j = 0; i < MRU_MAX_FILE; i++) {
 | 
						|
 | 
						|
         // If this MRU still exists, then add it.
 | 
						|
         if (szMRU[i][3]) {
 | 
						|
 | 
						|
            // Build option name for current MRU and write to registry.
 | 
						|
            _stprintf(szOption, TEXT("MRU%d"), ++j);
 | 
						|
            WriteOptionString(szOption, &szMRU[i][3]);
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
      // If our list got smaller, clear the unused items in the registry.
 | 
						|
      while (j++ < MRU_MAX_FILE) {
 | 
						|
         _stprintf(szOption, TEXT("MRU%d"), j);
 | 
						|
         WriteOptionString(szOption, TEXT(""));
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   //---------------------------------------------------------------------------
 | 
						|
   // We next thing we do is look for this file in our local MRU stored in our
 | 
						|
   // File menu.  We read the current MRU list from the menu, and then write it
 | 
						|
   // back while removing all occurrances of the file specified.
 | 
						|
   //---------------------------------------------------------------------------
 | 
						|
 | 
						|
   // Get our menu handle.
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
   HMENU hMenu = GetSubMenu(CommandBar_GetMenu(g_hWndCmdBar, 0), 0);
 | 
						|
#else
 | 
						|
   HMENU hMenu = GetSubMenu(GetMenu(g_hWndMain), 0);
 | 
						|
#endif
 | 
						|
 | 
						|
   // Read all our current MRUs from our File Menu.
 | 
						|
   for (i = 0, fFound = FALSE; i < MRU_MAX_FILE; i++) {
 | 
						|
 | 
						|
      // Query our file Menu for a MRU file.
 | 
						|
      if (!GetMenuString(hMenu, MRU_START_ID + i, szMRU[i], countof(szMRU[0]),
 | 
						|
          MF_BYCOMMAND))
 | 
						|
      {
 | 
						|
         szMRU[i][3] = TEXT('\0');
 | 
						|
      }
 | 
						|
 | 
						|
      // Check for a match.
 | 
						|
      if (!_tcsicmp(szFile, &szMRU[i][3])) {
 | 
						|
         szMRU[i][3] = TEXT('\0');
 | 
						|
         fFound = TRUE;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   // Only update menu if we found a file to remove.
 | 
						|
   if (fFound) {
 | 
						|
 | 
						|
      // Clear out our menu's MRU list.
 | 
						|
      for (i = MRU_START_ID; i < (MRU_START_ID + MRU_MAX_FILE); i++) {
 | 
						|
         DeleteMenu(hMenu, i, MF_BYCOMMAND);
 | 
						|
      }
 | 
						|
 | 
						|
      // Write the rest of our MRU list back to the menu.
 | 
						|
      for (i = 0, j = 0; i < MRU_MAX_FILE; i++) {
 | 
						|
 | 
						|
         // If this MRU still exists, then add it.
 | 
						|
         if (szMRU[i][3]) {
 | 
						|
 | 
						|
            // Build the accelerator prefix for this menu item.
 | 
						|
            szMRU[i][0] = TEXT('&');
 | 
						|
            szMRU[i][1] = TEXT('1') + j;
 | 
						|
            szMRU[i][2] = TEXT(' ');
 | 
						|
 | 
						|
            // Add the item to our menu.
 | 
						|
            InsertMenu(hMenu, 4 + j, MF_BYPOSITION | MF_STRING, MRU_START_ID + j,
 | 
						|
                       szMRU[i]);
 | 
						|
 | 
						|
            // Increment our actual MRU count.
 | 
						|
            j++;
 | 
						|
         }
 | 
						|
      }
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void ActivateMRU(UINT uIDItem) {
 | 
						|
   TCHAR szFile[_MAX_PATH + 4];
 | 
						|
 | 
						|
   // Get our menu handle.
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
   HMENU hMenu = GetSubMenu(CommandBar_GetMenu(g_hWndCmdBar, 0), 0);
 | 
						|
#else
 | 
						|
   HMENU hMenu = GetSubMenu(GetMenu(g_hWndMain), 0);
 | 
						|
#endif
 | 
						|
 | 
						|
   // Query our menu for the selected MRU.
 | 
						|
   if (GetMenuString(hMenu, uIDItem, szFile, countof(szFile), MF_BYCOMMAND)) {
 | 
						|
 | 
						|
      // Move past 3 character accelerator prefix and open the file.
 | 
						|
      ReadZipFileList(&szFile[3]);
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Open Zip File Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
void ReadZipFileList(LPCWSTR wszPath) {
 | 
						|
 | 
						|
   // Show wait cursor.
 | 
						|
   HCURSOR hCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
 | 
						|
 | 
						|
   wcstombs(g_szZipFile, wszPath, countof(g_szZipFile));
 | 
						|
 | 
						|
   // Update our banner to show that we are loading.
 | 
						|
   g_fLoading = TRUE;
 | 
						|
   DrawBanner(NULL);
 | 
						|
 | 
						|
   // Update our caption to show that we are loading.
 | 
						|
   SetCaptionText(TEXT("Loading"));
 | 
						|
 | 
						|
   // Clear our list view.
 | 
						|
   ListView_DeleteAllItems(g_hWndList);
 | 
						|
 | 
						|
   // Ghost all our Unzip related menu items.
 | 
						|
   EnableAllMenuItems(IDM_FILE_PROPERTIES,    FALSE);
 | 
						|
   EnableAllMenuItems(IDM_ACTION_EXTRACT,     FALSE);
 | 
						|
   EnableAllMenuItems(IDM_ACTION_EXTRACT_ALL, FALSE);
 | 
						|
   EnableAllMenuItems(IDM_ACTION_TEST,        FALSE);
 | 
						|
   EnableAllMenuItems(IDM_ACTION_TEST_ALL,    FALSE);
 | 
						|
   EnableAllMenuItems(IDM_ACTION_VIEW,        FALSE);
 | 
						|
   EnableAllMenuItems(IDM_ACTION_SELECT_ALL,  FALSE);
 | 
						|
   EnableAllMenuItems(IDM_VIEW_COMMENT,       FALSE);
 | 
						|
 | 
						|
   // Let Info-ZIP and our callbacks do the work.
 | 
						|
   SendMessage(g_hWndList, WM_SETREDRAW, FALSE, 0);
 | 
						|
   int result = DoListFiles(g_szZipFile);
 | 
						|
   SendMessage(g_hWndList, WM_SETREDRAW, TRUE, 0);
 | 
						|
 | 
						|
   // Restore/remove cursor.
 | 
						|
   SetCursor(hCur);
 | 
						|
 | 
						|
   // Update our column widths
 | 
						|
   ResizeColumns();
 | 
						|
 | 
						|
   if ((result == PK_OK) || (result == PK_WARN)) {
 | 
						|
 | 
						|
      // Sort the items by name.
 | 
						|
      Sort(0, TRUE);
 | 
						|
 | 
						|
      // Update this file to our MRU list and menu.
 | 
						|
      AddFileToMRU(g_szZipFile);
 | 
						|
 | 
						|
      // Enabled the comment button if the zip file has a comment.
 | 
						|
      if (lpUserFunctions->cchComment) {
 | 
						|
         EnableAllMenuItems(IDM_VIEW_COMMENT, TRUE);
 | 
						|
      }
 | 
						|
 | 
						|
      // Update other items that are related to having a Zip file loaded.
 | 
						|
      EnableAllMenuItems(IDM_ACTION_EXTRACT_ALL, TRUE);
 | 
						|
      EnableAllMenuItems(IDM_ACTION_TEST_ALL,    TRUE);
 | 
						|
      EnableAllMenuItems(IDM_ACTION_SELECT_ALL,  TRUE);
 | 
						|
 | 
						|
   } else {
 | 
						|
 | 
						|
      // Make sure we didn't partially load and added a few files.
 | 
						|
      ListView_DeleteAllItems(g_hWndList);
 | 
						|
 | 
						|
      // If the file itself is bad or missing, then remove it from our MRU.
 | 
						|
      if ((result == PK_ERR) || (result == PK_BADERR) || (result == PK_NOZIP) ||
 | 
						|
          (result == PK_FIND) || (result == PK_EOF))
 | 
						|
      {
 | 
						|
         RemoveFileFromMRU(wszPath);
 | 
						|
      }
 | 
						|
 | 
						|
      // Display an error.
 | 
						|
      TCHAR szError[_MAX_PATH + 128];
 | 
						|
      _stprintf(szError, TEXT("Failure loading \"%s\".\n\n"), wszPath);
 | 
						|
      _tcscat(szError, GetZipErrorString(result));
 | 
						|
      MessageBox(g_hWndMain, szError, g_szAppName, MB_OK | MB_ICONERROR);
 | 
						|
 | 
						|
      // Clear our file status.
 | 
						|
      *g_szZipFile = '\0';
 | 
						|
   }
 | 
						|
 | 
						|
   // Update our caption to show that we are done loading.
 | 
						|
   SetCaptionText(NULL);
 | 
						|
 | 
						|
   // Update our banner to show that we are done loading.
 | 
						|
   g_fLoading = FALSE;
 | 
						|
   DrawBanner(NULL);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Zip File Properties Dialog Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
BOOL CALLBACK DlgProcProperties(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 | 
						|
 | 
						|
   switch (uMsg) {
 | 
						|
 | 
						|
      case WM_INITDIALOG: {
 | 
						|
 | 
						|
         // Add "General" and "Comments" tabs to tab control.  We are using a
 | 
						|
         // poor man's version of a property sheet.  We display our 2 pages
 | 
						|
         // by showing and hiding controls as necessary.  For our purposes,
 | 
						|
         // this is much easier than dealing with separate property pages.
 | 
						|
 | 
						|
         TC_ITEM tci;
 | 
						|
         tci.mask = TCIF_TEXT;
 | 
						|
         tci.pszText = TEXT("General");
 | 
						|
         TabCtrl_InsertItem(GetDlgItem(hDlg, IDC_TAB), 0, &tci);
 | 
						|
         tci.pszText = TEXT("Comment");
 | 
						|
         TabCtrl_InsertItem(GetDlgItem(hDlg, IDC_TAB), 1, &tci);
 | 
						|
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
         // Add "Ok" button to caption bar.
 | 
						|
         SetWindowLong(hDlg, GWL_EXSTYLE, WS_EX_CAPTIONOKBTN | 
 | 
						|
                       GetWindowLong(hDlg, GWL_EXSTYLE));
 | 
						|
#endif
 | 
						|
         // Center us over our parent.
 | 
						|
         CenterWindow(hDlg);
 | 
						|
 | 
						|
         int    directory = -1, readOnly = -1, archive = -1, hidden = -1;
 | 
						|
         int    system = -1, encrypted = -1;
 | 
						|
         int    year = -1, month = -1, day = -1, hour = -1, minute = -1, pm = -1;
 | 
						|
         DWORD  dwSize = 0, dwCompressedSize = 0;
 | 
						|
         LPCSTR szPath = NULL, szMethod = NULL, szComment = NULL;
 | 
						|
         DWORD  dwCRC = 0, dwCount = 0, dwCommentCount = 0;
 | 
						|
         TCHAR  szBuffer[MAX_PATH];
 | 
						|
 | 
						|
         // Loop through all selected items.
 | 
						|
         LV_ITEM lvi;
 | 
						|
         ZeroMemory(&lvi, sizeof(lvi));
 | 
						|
         lvi.mask = LVIF_PARAM;
 | 
						|
         lvi.iItem = -1;
 | 
						|
         while ((lvi.iItem = ListView_GetNextItem(g_hWndList, lvi.iItem, LVNI_SELECTED)) != -1) {
 | 
						|
 | 
						|
            // Get the FILE_NODE for the selected item.
 | 
						|
            ListView_GetItem(g_hWndList, &lvi);
 | 
						|
            FILE_NODE *pFile = (FILE_NODE*)lvi.lParam;
 | 
						|
 | 
						|
            // Merge this file's attributes into our accumulative attributes.
 | 
						|
            MergeValues(&directory, (pFile->dwAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
 | 
						|
            MergeValues(&readOnly,  (pFile->dwAttributes & FILE_ATTRIBUTE_READONLY)  != 0);
 | 
						|
            MergeValues(&archive,   (pFile->dwAttributes & FILE_ATTRIBUTE_ARCHIVE)   != 0);
 | 
						|
            MergeValues(&hidden,    (pFile->dwAttributes & FILE_ATTRIBUTE_HIDDEN)    != 0);
 | 
						|
            MergeValues(&system,    (pFile->dwAttributes & FILE_ATTRIBUTE_SYSTEM)    != 0);
 | 
						|
            MergeValues(&encrypted, (pFile->dwAttributes & FILE_ATTRIBUTE_ENCRYPTED) != 0);
 | 
						|
 | 
						|
            // Merge this file's date/time into our accumulative date/time.
 | 
						|
            int curHour = (pFile->dwModified >> 6) & 0x001F;
 | 
						|
            MergeValues(&year,   (pFile->dwModified >> 20) & 0x0FFF);
 | 
						|
            MergeValues(&month,  (pFile->dwModified >> 16) & 0x000F);
 | 
						|
            MergeValues(&day,    (pFile->dwModified >> 11) & 0x001F);
 | 
						|
            MergeValues(&hour,   (curHour % 12) ? (curHour % 12) : 12);
 | 
						|
            MergeValues(&minute, pFile->dwModified & 0x003F);
 | 
						|
            MergeValues(&pm,     curHour >= 12);
 | 
						|
 | 
						|
            // Store this file's name.
 | 
						|
            szPath = pFile->szPathAndMethod;
 | 
						|
 | 
						|
            // Store this file's CRC.
 | 
						|
            dwCRC = pFile->dwCRC;
 | 
						|
 | 
						|
            // Add the size and compressed size to our accumulative sizes.
 | 
						|
            dwSize += pFile->dwSize;
 | 
						|
            dwCompressedSize += pFile->dwCompressedSize;
 | 
						|
 | 
						|
            // Merge in our compression method.
 | 
						|
            LPCSTR szCurMethod = pFile->szPathAndMethod + strlen(pFile->szPathAndMethod) + 1;
 | 
						|
            if ((szMethod == NULL) || !strcmp(szMethod, szCurMethod)) {
 | 
						|
               szMethod = szCurMethod;
 | 
						|
            } else {
 | 
						|
               szMethod = "Multiple Methods";
 | 
						|
            }
 | 
						|
 | 
						|
            // Increment our file count.
 | 
						|
            dwCount++;
 | 
						|
 | 
						|
            // Increment our comment count if this file has a comment.
 | 
						|
            if (pFile->szComment) {
 | 
						|
               szComment = pFile->szComment;
 | 
						|
               dwCommentCount++;
 | 
						|
            }
 | 
						|
         };
 | 
						|
 | 
						|
         if (dwCount > 1) {
 | 
						|
 | 
						|
            // If multiple items selected, then display a selected count string
 | 
						|
            // in place of the file name.
 | 
						|
            _stprintf(szBuffer, TEXT("%u items selected."), dwCount);
 | 
						|
            SetDlgItemText(hDlg, IDC_FILE, szBuffer);
 | 
						|
 | 
						|
            // Display "Multiple" for CRC if multiple items selected.
 | 
						|
            SetDlgItemText(hDlg, IDC_CRC, TEXT("Multiple CRCs"));
 | 
						|
 | 
						|
         } else {
 | 
						|
 | 
						|
            // Set the file name text for the single item selected.
 | 
						|
            mbstowcs(szBuffer, szPath, countof(szBuffer));
 | 
						|
            ForwardSlashesToBackSlashesW(szBuffer);
 | 
						|
            SetDlgItemText(hDlg, IDC_FILE, szBuffer);
 | 
						|
 | 
						|
            // Set the CRC text for the single item selected.
 | 
						|
            _stprintf(szBuffer, TEXT("0x%08X"), dwCRC);
 | 
						|
            SetDlgItemText(hDlg, IDC_CRC, szBuffer);
 | 
						|
         }
 | 
						|
 | 
						|
         // Set the Size tally text.
 | 
						|
         FormatValue(szBuffer, dwSize);
 | 
						|
         _tcscat(szBuffer, (dwCount > 1) ? TEXT(" bytes total") : TEXT(" bytes"));
 | 
						|
         SetDlgItemText(hDlg, IDC_FILE_SIZE, szBuffer);
 | 
						|
 | 
						|
         // Set the Compressed Size tally text.
 | 
						|
         FormatValue(szBuffer, dwCompressedSize);
 | 
						|
         _tcscat(szBuffer, (dwCount > 1) ? TEXT(" bytes total") : TEXT(" bytes"));
 | 
						|
         SetDlgItemText(hDlg, IDC_COMPRESSED_SIZE, szBuffer);
 | 
						|
 | 
						|
         // Set the Compression Factor text.
 | 
						|
         int factor = ratio(dwSize, dwCompressedSize);
 | 
						|
         _stprintf(szBuffer, TEXT("%d.%d%%"), factor / 10, 
 | 
						|
                   ((factor < 0) ? -factor : factor) % 10);
 | 
						|
         SetDlgItemText(hDlg, IDC_COMPRESSON_FACTOR, szBuffer);
 | 
						|
 | 
						|
         // Set the Compression Method text.
 | 
						|
         mbstowcs(szBuffer, szMethod, countof(szBuffer));
 | 
						|
         SetDlgItemText(hDlg, IDC_COMPRESSION_METHOD, szBuffer);
 | 
						|
 | 
						|
         // Set the Attribute check boxes.
 | 
						|
         CheckThreeStateBox(hDlg, IDC_DIRECTORY, directory);
 | 
						|
         CheckThreeStateBox(hDlg, IDC_READONLY,  readOnly);
 | 
						|
         CheckThreeStateBox(hDlg, IDC_ARCHIVE,   archive);
 | 
						|
         CheckThreeStateBox(hDlg, IDC_HIDDEN,    hidden);
 | 
						|
         CheckThreeStateBox(hDlg, IDC_SYSTEM,    system);
 | 
						|
         CheckThreeStateBox(hDlg, IDC_ENCRYPTED, encrypted);
 | 
						|
 | 
						|
         // Build and set the Modified Date text.  The MS compiler does not
 | 
						|
         // consider "??/" to be a valid string.  "??/" is a trigraph that is
 | 
						|
         // turned into "\" by the preprocessor and causes grief for the compiler.
 | 
						|
         LPTSTR psz = szBuffer;
 | 
						|
         psz += ((month  < 0) ? _stprintf(psz, TEXT("?\?/")) : 
 | 
						|
                                _stprintf(psz, TEXT("%u/"), month));
 | 
						|
         psz += ((day    < 0) ? _stprintf(psz, TEXT("?\?/")) :
 | 
						|
                                _stprintf(psz, TEXT("%u/"), day));
 | 
						|
         psz += ((year   < 0) ? _stprintf(psz, TEXT("?\? ")) : 
 | 
						|
                                _stprintf(psz, TEXT("%u "), year % 100));
 | 
						|
         psz += ((hour   < 0) ? _stprintf(psz, TEXT("?\?:")) : 
 | 
						|
                                _stprintf(psz, TEXT("%u:"), hour));
 | 
						|
         psz += ((minute < 0) ? _stprintf(psz, TEXT("?\? ")) : 
 | 
						|
                                _stprintf(psz, TEXT("%02u "), minute));
 | 
						|
         psz += ((pm     < 0) ? _stprintf(psz, TEXT("?M")) : 
 | 
						|
                                _stprintf(psz, TEXT("%cM"), pm ? TEXT('P') : TEXT('A')));
 | 
						|
         SetDlgItemText(hDlg, IDC_MODIFIED, szBuffer);
 | 
						|
 | 
						|
         // Store a global handle to our edit control.
 | 
						|
         g_hWndEdit = GetDlgItem(hDlg, IDC_COMMENT);
 | 
						|
 | 
						|
         // Disable our edit box from being edited.
 | 
						|
         DisableEditing(g_hWndEdit);
 | 
						|
 | 
						|
         // Stuff the appropriate message into the Comment edit control.
 | 
						|
         if (dwCommentCount == 0) {
 | 
						|
            if (dwCount == 1) {
 | 
						|
               AddTextToEdit("This file does not have a comment.");
 | 
						|
            } else {
 | 
						|
               AddTextToEdit("None of the selected files have a comment.");
 | 
						|
            }
 | 
						|
         } else if (dwCount == 1) {
 | 
						|
            AddTextToEdit(szComment);
 | 
						|
         } else {
 | 
						|
            CHAR szTemp[64];
 | 
						|
            _stprintf(szBuffer, TEXT("%u of the selected files %s a comment."), 
 | 
						|
                      dwCommentCount, (dwCommentCount == 1)? TEXT("has") : TEXT("have"));
 | 
						|
            wcstombs(szTemp, szBuffer, countof(szTemp));
 | 
						|
            AddTextToEdit(szTemp);
 | 
						|
         }
 | 
						|
         g_hWndEdit = NULL;
 | 
						|
 | 
						|
 | 
						|
         // Whooh, done with WM_INITDIALOG
 | 
						|
         return TRUE;
 | 
						|
      }
 | 
						|
 | 
						|
      case WM_NOTIFY:
 | 
						|
         // Check to see if tab control was changed to new tab.
 | 
						|
         if (((NMHDR*)lParam)->code == TCN_SELCHANGE) {
 | 
						|
            HWND hWndTab     = ((NMHDR*)lParam)->hwndFrom;
 | 
						|
            HWND hWndComment = GetDlgItem(hDlg, IDC_COMMENT);
 | 
						|
            HWND hWnd        = GetWindow(hDlg, GW_CHILD);
 | 
						|
 | 
						|
            // If General tab selected, hide comment edit box and show all other controls.
 | 
						|
            if (TabCtrl_GetCurSel(hWndTab) == 0) {
 | 
						|
               while (hWnd) {
 | 
						|
                  ShowWindow(hWnd, ((hWnd == hWndTab) || (hWnd != hWndComment)) ?
 | 
						|
                             SW_SHOW : SW_HIDE);
 | 
						|
                  hWnd = GetWindow(hWnd, GW_HWNDNEXT);
 | 
						|
               }
 | 
						|
 | 
						|
            // If Comment tab selected, hide all controls except comment edit box.
 | 
						|
            } else {
 | 
						|
               while (hWnd) {
 | 
						|
                  ShowWindow(hWnd, ((hWnd == hWndTab) || (hWnd == hWndComment)) ?
 | 
						|
                             SW_SHOW : SW_HIDE);
 | 
						|
                  hWnd = GetWindow(hWnd, GW_HWNDNEXT);
 | 
						|
               }
 | 
						|
            }
 | 
						|
         }
 | 
						|
         return FALSE;
 | 
						|
 | 
						|
      case WM_COMMAND:
 | 
						|
         // Exit the dialog on OK (Enter) or CANCEL (Esc).
 | 
						|
         if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL)) {
 | 
						|
            EndDialog(hDlg, LOWORD(wParam));
 | 
						|
         }
 | 
						|
         return FALSE;
 | 
						|
   }
 | 
						|
   return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void MergeValues(int *p1, int p2) {
 | 
						|
   if ((*p1 == -1) || (*p1 == p2)) {
 | 
						|
      *p1 = p2;
 | 
						|
   } else {
 | 
						|
      *p1 = -2;
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void CheckThreeStateBox(HWND hDlg, int nIDButton, int state) {
 | 
						|
   CheckDlgButton(hDlg, nIDButton, (state == 0) ? BST_UNCHECKED : 
 | 
						|
                                   (state == 1) ? BST_CHECKED : 
 | 
						|
                                                  BST_INDETERMINATE);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Extract/Test Dialog Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
void ExtractOrTestFiles(BOOL fExtract) {
 | 
						|
 | 
						|
   EXTRACT_INFO ei;
 | 
						|
   ZeroMemory(&ei, sizeof(ei));
 | 
						|
 | 
						|
   // Set our Extract or Test flag.
 | 
						|
   ei.fExtract = fExtract;
 | 
						|
 | 
						|
   // Get the number of selected items and make sure we have at least one item.
 | 
						|
   if ((ei.dwFileCount = ListView_GetSelectedCount(g_hWndList)) <= 0) {
 | 
						|
      return;
 | 
						|
   }
 | 
						|
 | 
						|
   // If we are not extracting/testing all, then create and buffer large enough to
 | 
						|
   // hold the file list for all the selected files.
 | 
						|
   if ((int)ei.dwFileCount != ListView_GetItemCount(g_hWndList)) {
 | 
						|
      ei.szFileList = new LPSTR[ei.dwFileCount + 1];
 | 
						|
      if (!ei.szFileList) {
 | 
						|
         MessageBox(g_hWndMain, GetZipErrorString(PK_MEM), g_szAppName, 
 | 
						|
                    MB_ICONERROR | MB_OK);
 | 
						|
         return;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   ei.dwFileCount = 0;
 | 
						|
   ei.dwByteCount = 0;
 | 
						|
 | 
						|
   LV_ITEM lvi;
 | 
						|
   ZeroMemory(&lvi, sizeof(lvi));
 | 
						|
   lvi.mask = LVIF_PARAM;
 | 
						|
   lvi.iItem = -1;
 | 
						|
 | 
						|
   // Walk through all the selected files to build our counts and set our file
 | 
						|
   // list pointers into our FILE_NODE paths for each selected item.
 | 
						|
   while ((lvi.iItem = ListView_GetNextItem(g_hWndList, lvi.iItem, LVNI_SELECTED)) >= 0) {
 | 
						|
      ListView_GetItem(g_hWndList, &lvi);
 | 
						|
      if (ei.szFileList) {
 | 
						|
         ei.szFileList[ei.dwFileCount] = ((FILE_NODE*)lvi.lParam)->szPathAndMethod;
 | 
						|
      }
 | 
						|
      ei.dwFileCount++;
 | 
						|
      ei.dwByteCount += ((FILE_NODE*)lvi.lParam)->dwSize;
 | 
						|
   }
 | 
						|
   if (ei.szFileList) {
 | 
						|
      ei.szFileList[ei.dwFileCount] = NULL;
 | 
						|
   }
 | 
						|
 | 
						|
   // If we are extracting, display the extract dialog to query for parameters.
 | 
						|
   if (!fExtract || (DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_EXTRACT), g_hWndMain, 
 | 
						|
                                    (DLGPROC)DlgProcExtractOrTest, (LPARAM)&ei) == IDOK))
 | 
						|
   {
 | 
						|
      // Display our progress dialog and do the extraction/test.
 | 
						|
      DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_EXTRACT_PROGRESS), g_hWndMain, 
 | 
						|
                     (DLGPROC)DlgProcExtractProgress, (LPARAM)&ei);
 | 
						|
   }
 | 
						|
 | 
						|
   // Free our file list buffer if we created one.
 | 
						|
   if (ei.szFileList) {
 | 
						|
      delete[] ei.szFileList;
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
BOOL CALLBACK DlgProcExtractOrTest(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 | 
						|
 | 
						|
   static EXTRACT_INFO *pei;
 | 
						|
   TCHAR  szPath[_MAX_PATH];
 | 
						|
 | 
						|
   switch (uMsg) {
 | 
						|
 | 
						|
      case WM_INITDIALOG:
 | 
						|
         
 | 
						|
         // Store our extract information structure.
 | 
						|
         pei = (EXTRACT_INFO*)lParam;
 | 
						|
 | 
						|
         // Load our settings.
 | 
						|
         pei->fRestorePaths = GetOptionInt(TEXT("RestorePaths"), TRUE);
 | 
						|
         pei->overwriteMode = (OVERWRITE_MODE)GetOptionInt(TEXT("OverwriteMode"), OM_PROMPT);
 | 
						|
 | 
						|
         // Load and set our path string.
 | 
						|
         GetOptionString(TEXT("ExtractToDirectory"), TEXT("\\"), szPath, sizeof(szPath));
 | 
						|
         SetDlgItemText(hDlg, IDC_EXTRACT_TO, szPath);
 | 
						|
 | 
						|
         // Set the state of all the controls.
 | 
						|
         SetDlgItemText(hDlg, IDC_FILE_COUNT, FormatValue(szPath, pei->dwFileCount));
 | 
						|
         SetDlgItemText(hDlg, IDC_BYTE_COUNT, FormatValue(szPath, pei->dwByteCount));
 | 
						|
         CheckDlgButton(hDlg, IDC_RESTORE_PATHS, pei->fRestorePaths);
 | 
						|
         CheckDlgButton(hDlg, IDC_OVERWRITE_PROMPT, pei->overwriteMode == OM_PROMPT);
 | 
						|
         CheckDlgButton(hDlg, IDC_OVERWRITE_NEWER,  pei->overwriteMode == OM_NEWER);
 | 
						|
         CheckDlgButton(hDlg, IDC_OVERWRITE_ALWAYS, pei->overwriteMode == OM_ALWAYS);
 | 
						|
         CheckDlgButton(hDlg, IDC_OVERWRITE_NEVER,  pei->overwriteMode == OM_NEVER);
 | 
						|
 | 
						|
         // Limit our edit control to max path.
 | 
						|
         SendDlgItemMessage(hDlg, IDC_EXTRACT_TO, EM_LIMITTEXT, sizeof(szPath) - 1, 0);
 | 
						|
 | 
						|
         // Center our dialog.
 | 
						|
         CenterWindow(hDlg);
 | 
						|
         return TRUE;
 | 
						|
 | 
						|
      case WM_COMMAND:
 | 
						|
         switch (LOWORD(wParam)) {
 | 
						|
 | 
						|
            case IDOK:
 | 
						|
 | 
						|
               // Force us to read and validate the extract to directory.
 | 
						|
               SendMessage(hDlg, WM_COMMAND, MAKELONG(IDC_EXTRACT_TO, EN_KILLFOCUS), 0);
 | 
						|
 | 
						|
               // Get our current path string.
 | 
						|
               GetDlgItemText(hDlg, IDC_EXTRACT_TO, szPath, countof(szPath));
 | 
						|
 | 
						|
               // Verify our "extract to" path is valid.
 | 
						|
               if (!SetExtractToDirectory(szPath)) {
 | 
						|
                  MessageBox(hDlg, TEXT("The directory you entered is invalid or does not exist."), 
 | 
						|
                             g_szAppName, MB_ICONERROR | MB_OK);
 | 
						|
                  SetFocus(GetDlgItem(hDlg, IDC_EXTRACT_TO));
 | 
						|
                  return FALSE;
 | 
						|
               }
 | 
						|
 | 
						|
               // Query other control values.
 | 
						|
               pei->fRestorePaths = IsDlgButtonChecked(hDlg, IDC_RESTORE_PATHS);
 | 
						|
               pei->overwriteMode = 
 | 
						|
                  IsDlgButtonChecked(hDlg, IDC_OVERWRITE_NEWER)  ? OM_NEWER  :
 | 
						|
                  IsDlgButtonChecked(hDlg, IDC_OVERWRITE_ALWAYS) ? OM_ALWAYS :
 | 
						|
                  IsDlgButtonChecked(hDlg, IDC_OVERWRITE_NEVER)  ? OM_NEVER  : OM_PROMPT;
 | 
						|
 | 
						|
               // Write our settings.
 | 
						|
               WriteOptionInt(TEXT("RestorePaths"), pei->fRestorePaths);
 | 
						|
               WriteOptionInt(TEXT("OverwriteMode"), pei->overwriteMode);
 | 
						|
               WriteOptionString(TEXT("ExtractToDirectory"), szPath);
 | 
						|
 | 
						|
               // Fall through to IDCANCEL
 | 
						|
               
 | 
						|
            case IDCANCEL:
 | 
						|
               EndDialog(hDlg, LOWORD(wParam));
 | 
						|
               return FALSE;
 | 
						|
 | 
						|
            case IDC_EXTRACT_TO:
 | 
						|
 
 | 
						|
               // Make sure the path ends in a wack (\).
 | 
						|
               if (HIWORD(wParam) == EN_KILLFOCUS) {
 | 
						|
                  GetDlgItemText(hDlg, IDC_EXTRACT_TO, szPath, countof(szPath));
 | 
						|
                  int length = _tcslen(szPath);
 | 
						|
                  if ((length == 0) || szPath[length - 1] != TEXT('\\')) {
 | 
						|
                     szPath[length    ] = TEXT('\\');
 | 
						|
                     szPath[length + 1] = TEXT('\0');
 | 
						|
                     SetDlgItemText(hDlg, IDC_EXTRACT_TO, szPath);
 | 
						|
                  }
 | 
						|
               }
 | 
						|
               return FALSE;
 | 
						|
            
 | 
						|
            case IDC_BROWSE:
 | 
						|
               GetDlgItemText(hDlg, IDC_EXTRACT_TO, szPath, countof(szPath));
 | 
						|
               if (FolderBrowser(szPath, countof(szPath))) {
 | 
						|
                  SetDlgItemText(hDlg, IDC_EXTRACT_TO, szPath);
 | 
						|
               }
 | 
						|
               return FALSE;
 | 
						|
         }
 | 
						|
         return FALSE;
 | 
						|
   }
 | 
						|
   return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Folder Browsing Dialog Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
BOOL FolderBrowser(LPTSTR szPath, DWORD dwLength) {
 | 
						|
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
 | 
						|
   // On Windows CE, we use a common save-as dialog to query the diretory.  We
 | 
						|
   // display the dialog in this function, and then we sublass it.  Our subclass
 | 
						|
   // functions tweaks the dialog a bit and and returns the path.
 | 
						|
 | 
						|
   ForwardSlashesToBackSlashesW(szPath);
 | 
						|
 | 
						|
   TCHAR szInitialDir[_MAX_PATH];
 | 
						|
   _tcscpy(szInitialDir, szPath);
 | 
						|
 | 
						|
   // Remove trailing wacks from path - The common dialog doesn't like them.
 | 
						|
   int length = _tcslen(szInitialDir);
 | 
						|
   while ((length > 0) && (szInitialDir[length - 1] == TEXT('\\'))) {
 | 
						|
      szInitialDir[--length] = TEXT('\0');
 | 
						|
   }
 | 
						|
 | 
						|
   // Set up the parameters for our save-as dialog.
 | 
						|
   OPENFILENAME ofn;
 | 
						|
   ZeroMemory(&ofn, sizeof(ofn));
 | 
						|
   ofn.lStructSize     = sizeof(ofn);
 | 
						|
   ofn.hwndOwner       = g_hWndMain;
 | 
						|
   ofn.hInstance       = g_hInst;
 | 
						|
   ofn.lpstrFilter     = TEXT(" \0!\0");
 | 
						|
   ofn.nFilterIndex    = 1;
 | 
						|
   ofn.lpstrFile       = szPath;
 | 
						|
   ofn.nMaxFile        = dwLength;
 | 
						|
   ofn.lpstrInitialDir = *szInitialDir ? szInitialDir : NULL;
 | 
						|
   ofn.lpstrTitle      = TEXT("Extract To");
 | 
						|
   ofn.Flags           = OFN_HIDEREADONLY | OFN_NOVALIDATE | OFN_NOTESTFILECREATE;
 | 
						|
 | 
						|
   // Post a message to our main window telling it that we are about to create
 | 
						|
   // a save as dialog.  Our main window will receive this message after the
 | 
						|
   // save as dialog is created.  This gives us a change to subclass the save as
 | 
						|
   // dialog.
 | 
						|
   PostMessage(g_hWndMain, WM_PRIVATE, MSG_SUBCLASS_DIALOG, 0);
 | 
						|
 | 
						|
   // Create and display the common save-as dialog.
 | 
						|
   if (GetSaveFileName(&ofn)) {
 | 
						|
 | 
						|
      // If success, then remove are special "!" filename from the end.
 | 
						|
      szPath[_tcslen(szPath) - 1] = TEXT('\0');
 | 
						|
      return TRUE;
 | 
						|
   }
 | 
						|
   return FALSE;
 | 
						|
 | 
						|
#else // !_WIN32_WCE
 | 
						|
 | 
						|
   // On Windows NT, the shell provides us with a nice folder browser dialog.
 | 
						|
   // We don't need to jump through any hoops to make it work like on Windows CE.
 | 
						|
   // The only problem is that on VC 4.0, the libraries don't export the UNICODE
 | 
						|
   // shell APIs because only Win95 had a shell library at the time.  The
 | 
						|
   // following code requires headers and libs from VC 4.2 or later.
 | 
						|
 | 
						|
   // Set up our BROWSEINFO structure.
 | 
						|
   BROWSEINFO bi;
 | 
						|
   ZeroMemory(&bi, sizeof(bi));
 | 
						|
   bi.hwndOwner = g_hWndMain;
 | 
						|
   bi.pszDisplayName = szPath;
 | 
						|
   bi.lpszTitle = TEXT("Extract To");
 | 
						|
   bi.ulFlags = BIF_RETURNONLYFSDIRS;
 | 
						|
 
 | 
						|
   // Prompt user for path.
 | 
						|
   LPITEMIDLIST piidl = SHBrowseForFolder(&bi);
 | 
						|
   if (!piidl) {
 | 
						|
      return FALSE;
 | 
						|
   }
 | 
						|
 | 
						|
   // Build path string.
 | 
						|
   SHGetPathFromIDList(piidl, szPath);
 | 
						|
 
 | 
						|
   // Free the PIDL returned by SHBrowseForFolder. 
 | 
						|
   LPMALLOC pMalloc = NULL;
 | 
						|
   SHGetMalloc(&pMalloc);
 | 
						|
   pMalloc->Free(piidl); 
 | 
						|
 
 | 
						|
   // Add trailing wack if one is not present.
 | 
						|
   int length = _tcslen(szPath);
 | 
						|
   if ((length > 0) && (szPath[length - 1] != TEXT('\\'))) {
 | 
						|
      szPath[length++] = TEXT('\\');
 | 
						|
      szPath[length]   = TEXT('\0');
 | 
						|
   }
 | 
						|
 | 
						|
   return TRUE;
 | 
						|
 | 
						|
#endif // _WIN32_WCE
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
BOOL CALLBACK DlgProcBrowser(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 | 
						|
 | 
						|
   // This is our subclass of Windows CE's common save-as dialog.  We intercept
 | 
						|
   // the messages we care about and forward everything else to the original
 | 
						|
   // window procedure for the dialog.
 | 
						|
 | 
						|
   if (uMsg == WM_PRIVATE) { // wParam always equals MSG_INIT_DIALOG
 | 
						|
 | 
						|
      RECT rc1, rc2;
 | 
						|
 | 
						|
      // Get the window rectangle for the name edit control.
 | 
						|
      HWND hWnd = GetDlgItem(hDlg, IDC_SAVE_NAME_EDIT);
 | 
						|
      GetWindowRect(hWnd, &rc1);
 | 
						|
      POINT pt1 = { rc1.left, rc1.top };
 | 
						|
      ScreenToClient(hDlg, &pt1);
 | 
						|
 | 
						|
      // Hide all the windows we don't want.
 | 
						|
      ShowWindow(hWnd, SW_HIDE);
 | 
						|
      ShowWindow(GetDlgItem(hDlg, IDC_SAVE_NAME_PROMPT), SW_HIDE);
 | 
						|
      ShowWindow(GetDlgItem(hDlg, IDC_SAVE_TYPE_PROMPT), SW_HIDE);
 | 
						|
      ShowWindow(GetDlgItem(hDlg, IDC_SAVE_TYPE_LIST), SW_HIDE);
 | 
						|
 | 
						|
      // Get the window rectangle for the file list.
 | 
						|
      hWnd = GetDlgItem(hDlg, IDC_SAVE_FILE_LIST);
 | 
						|
      GetWindowRect(hWnd, &rc2);
 | 
						|
      POINT pt2 = { rc2.left, rc2.top };
 | 
						|
      ScreenToClient(hDlg, &pt2);
 | 
						|
 | 
						|
      // Resize the file list to fill the dialog.
 | 
						|
      MoveWindow(hWnd, pt2.x, pt2.y, rc2.right - rc2.left, rc1.bottom - rc2.top, TRUE);
 | 
						|
 | 
						|
   } else if ((uMsg == WM_COMMAND) && (LOWORD(wParam) == IDOK)) {
 | 
						|
 | 
						|
      // Get our file list window.
 | 
						|
      HWND hWnd = GetDlgItem(hDlg, IDC_SAVE_FILE_LIST);
 | 
						|
 | 
						|
      // Check to see if a directory is selected.
 | 
						|
      if (ListView_GetNextItem(hWnd, -1, LVNI_SELECTED) >= 0) {
 | 
						|
 | 
						|
         // If a directory is highlighted, then we post ourself a "Ok".  The "Ok"
 | 
						|
         // we are processing now will cause us to change into the highlighted
 | 
						|
         // directory, and our posted "Ok" will close the dialog in that directory.
 | 
						|
         PostMessage(hDlg, uMsg, wParam, lParam);
 | 
						|
 | 
						|
      } else {
 | 
						|
         // If no directory is selected, then enter the imaginary filename "!"
 | 
						|
         // into the name edit control and let the "Ok" end this dialog. The 
 | 
						|
         // result will be the correct path with a "\!" at the end.
 | 
						|
         SetDlgItemText(hDlg, IDC_SAVE_NAME_EDIT, TEXT("!"));
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   // Pass all messages to the base control's window proc.
 | 
						|
   return CallWindowProc(g_wpSaveAsDlg, hDlg, uMsg, wParam, lParam);
 | 
						|
}
 | 
						|
#endif // _WIN32_WCE
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
void SubclassSaveAsDlg() {
 | 
						|
 | 
						|
   // Get our cuurent thread ID so we can compare it to other thread IDs.
 | 
						|
   DWORD dwThreadId = GetCurrentThreadId();
 | 
						|
 | 
						|
   // Get the the top window in the z-order that is a child of the desktop.
 | 
						|
   // Dialogs are always children of the desktop on CE.  This first window
 | 
						|
   // should be the dialog we are looking for, but we will walk the window list
 | 
						|
   // just in case.
 | 
						|
   HWND hWnd = GetWindow(g_hWndMain, GW_HWNDFIRST);
 | 
						|
 | 
						|
   // Walk the window list.
 | 
						|
   while (hWnd) {
 | 
						|
   
 | 
						|
      // Check to see if this window was created by us and has controls from a
 | 
						|
      // common "save as" dialog.
 | 
						|
      if ((GetWindowThreadProcessId(hWnd, NULL) == dwThreadId) &&
 | 
						|
           GetDlgItem(hWnd, IDC_SAVE_FILE_LIST) &&
 | 
						|
           GetDlgItem(hWnd, IDC_SAVE_NAME_EDIT))
 | 
						|
      {
 | 
						|
         // We found our dialog.  Subclass it.
 | 
						|
         g_wpSaveAsDlg = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
 | 
						|
         SetWindowLong(hWnd, GWL_WNDPROC, (LONG)DlgProcBrowser);
 | 
						|
 | 
						|
         // Send our new dialog a message so it can do its initialization.
 | 
						|
         SendMessage(hWnd, WM_PRIVATE, MSG_INIT_DIALOG, 0);
 | 
						|
      }
 | 
						|
 | 
						|
      // Get the next window in our window list.
 | 
						|
      hWnd = GetWindow(hWnd, GW_HWNDNEXT);
 | 
						|
   }
 | 
						|
}
 | 
						|
#endif // _WIN32_WCE
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Extraction/Test/View Progress Dialog Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
BOOL CALLBACK DlgProcExtractProgress(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 | 
						|
 | 
						|
   static EXTRACT_INFO *pei;
 | 
						|
   static BOOL fComplete;
 | 
						|
   static HWND hWndButton;
 | 
						|
   TCHAR szBuffer[32];
 | 
						|
 | 
						|
   switch (uMsg) {
 | 
						|
 | 
						|
      case WM_INITDIALOG:
 | 
						|
         
 | 
						|
         // Globally store our handle so our worker thread can post to us.
 | 
						|
         g_hDlgProgress = hDlg;
 | 
						|
 | 
						|
         // Get a pointer to our extract information structure.
 | 
						|
         pei = (EXTRACT_INFO*)lParam;
 | 
						|
 | 
						|
         // Clear our complete flag.  It will be set to TRUE when done.
 | 
						|
         fComplete = FALSE;
 | 
						|
 | 
						|
         // Get and store our edit control.
 | 
						|
         g_hWndEdit = GetDlgItem(hDlg, IDC_LOG);
 | 
						|
 | 
						|
         // Disable our edit box from being edited.
 | 
						|
         DisableEditing(g_hWndEdit);
 | 
						|
 | 
						|
         // Store a static handle for our Abort/Close button.
 | 
						|
         hWndButton = GetDlgItem(hDlg, IDCANCEL);
 | 
						|
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
 | 
						|
         // Set our No-Drag style
 | 
						|
         SetWindowLong(hDlg, GWL_EXSTYLE, WS_EX_NODRAG |GetWindowLong(hDlg, GWL_EXSTYLE));
 | 
						|
 | 
						|
         RECT rc1, rc2, rcEdit;
 | 
						|
 | 
						|
         // Get our current client size.
 | 
						|
         GetClientRect(hDlg, &rc1);
 | 
						|
 | 
						|
         // Get the window rectangle for the edit control in client coordinates.
 | 
						|
         GetWindowRect(g_hWndEdit, &rcEdit);
 | 
						|
         ScreenToClient(hDlg, ((POINT*)&rcEdit));
 | 
						|
         ScreenToClient(hDlg, ((POINT*)&rcEdit) + 1);
 | 
						|
 | 
						|
         // Resize our dialog to be full screen (same size as parent).
 | 
						|
         GetWindowRect(g_hWndMain, &rc2);
 | 
						|
         MoveWindow(hDlg, rc2.left, rc2.top, rc2.right - rc2.left, 
 | 
						|
                    rc2.bottom - rc2.top + 1, FALSE);
 | 
						|
 | 
						|
         // Get our new client size.
 | 
						|
         GetClientRect(hDlg, &rc2);
 | 
						|
 | 
						|
         // Resize our edit box to fill the client.
 | 
						|
         MoveWindow(g_hWndEdit, rcEdit.left, rcEdit.top, 
 | 
						|
                    (rcEdit.right  - rcEdit.left) + (rc2.right  - rc1.right),
 | 
						|
                    (rcEdit.bottom - rcEdit.top)  + (rc2.bottom - rc1.bottom),
 | 
						|
                    FALSE);
 | 
						|
 | 
						|
#else
 | 
						|
         // On NT, we just center our dialog over our parent.
 | 
						|
         CenterWindow(hDlg);
 | 
						|
#endif
 | 
						|
 | 
						|
         // Store some globals until the extract/test finishes.
 | 
						|
         pei->hWndEditFile       = GetDlgItem(hDlg, IDC_FILE);
 | 
						|
         pei->hWndProgFile       = GetDlgItem(hDlg, IDC_FILE_PROGRESS);
 | 
						|
         pei->hWndProgTotal      = GetDlgItem(hDlg, IDC_TOTAL_PROGRESS);
 | 
						|
         pei->hWndPercentage     = GetDlgItem(hDlg, IDC_PERCENTAGE);
 | 
						|
         pei->hWndFilesProcessed = GetDlgItem(hDlg, IDC_FILES_PROCESSED);
 | 
						|
         pei->hWndBytesProcessed = GetDlgItem(hDlg, IDC_BYTES_PROCESSED);
 | 
						|
 | 
						|
         if (pei->fExtract) {
 | 
						|
            // Set our main window's caption.
 | 
						|
            SetCaptionText(TEXT("Extracting"));
 | 
						|
 | 
						|
         } else {
 | 
						|
            // Set our main window's caption.
 | 
						|
            SetCaptionText(TEXT("Testing"));
 | 
						|
 | 
						|
            // Hide the current file progress for test since it never moves.
 | 
						|
            ShowWindow(pei->hWndProgFile, SW_HIDE);
 | 
						|
         }
 | 
						|
 | 
						|
         // Set the ranges on our progress bars.
 | 
						|
         SendMessage(pei->hWndProgFile,  PBM_SETRANGE, 0, 
 | 
						|
                     MAKELPARAM(0, PROGRESS_MAX));
 | 
						|
         SendMessage(pei->hWndProgTotal, PBM_SETRANGE, 0, 
 | 
						|
                     MAKELPARAM(0, PROGRESS_MAX));
 | 
						|
 | 
						|
         // Set our file and byte totals.
 | 
						|
         SetDlgItemText(hDlg, IDC_FILES_TOTAL, 
 | 
						|
                        FormatValue(szBuffer, pei->dwFileCount));
 | 
						|
         SetDlgItemText(hDlg, IDC_BYTES_TOTAL, 
 | 
						|
                        FormatValue(szBuffer, pei->dwByteCount));
 | 
						|
 | 
						|
         // Luanch our Extract/Test thread and wait for WM_PRIVATE
 | 
						|
         DoExtractOrTestFiles(g_szZipFile, pei);
 | 
						|
 | 
						|
         return TRUE;
 | 
						|
 | 
						|
 | 
						|
      case WM_PRIVATE: // Sent with wParam equal to MSG_OPERATION_COMPLETE when
 | 
						|
                       // test/extract is complete.
 | 
						|
 | 
						|
         // Check to see if the operation was a success
 | 
						|
         if ((pei->result == PK_OK) || (pei->result == PK_WARN)) {
 | 
						|
 | 
						|
            // Set all our fields to their "100%" settings.
 | 
						|
            SendMessage(pei->hWndProgFile,  PBM_SETPOS, PROGRESS_MAX, 0);
 | 
						|
            SendMessage(pei->hWndProgTotal, PBM_SETPOS, PROGRESS_MAX, 0);
 | 
						|
            SetWindowText(pei->hWndPercentage, TEXT("100%"));
 | 
						|
            SetDlgItemText(hDlg, IDC_FILES_PROCESSED, 
 | 
						|
                           FormatValue(szBuffer, pei->dwFileCount));
 | 
						|
            SetDlgItemText(hDlg, IDC_BYTES_PROCESSED, 
 | 
						|
                           FormatValue(szBuffer, pei->dwByteCount));
 | 
						|
         }
 | 
						|
 | 
						|
         // Update our status text.
 | 
						|
         SetWindowText(pei->hWndEditFile, 
 | 
						|
            (pei->result == PK_OK)      ? TEXT("Completed.  There were no warnings or errors.") :
 | 
						|
            (pei->result == PK_WARN)    ? TEXT("Completed.  There was one or more warnings.") :
 | 
						|
            (pei->result == PK_ABORTED) ? TEXT("Aborted.  There may be warnings or errors.") :
 | 
						|
                                          TEXT("Completed.  There was one or more errors."));
 | 
						|
 | 
						|
         // Clear our global edit handle.
 | 
						|
         g_hWndEdit = NULL;
 | 
						|
 | 
						|
         // Update our caption to show that we are done extracting/testing.
 | 
						|
         SetCaptionText(NULL);
 | 
						|
 | 
						|
         // Change our abort button to now read "Close".
 | 
						|
         SetWindowText(hWndButton, TEXT("&Close"));
 | 
						|
         EnableWindow(hWndButton, TRUE);
 | 
						|
 | 
						|
         // Display an error dialog if an error occurred.
 | 
						|
         if ((pei->result != PK_OK) && (pei->result != PK_WARN)) {
 | 
						|
            MessageBox(hDlg, GetZipErrorString(pei->result),
 | 
						|
                       g_szAppName, MB_ICONERROR | MB_OK);
 | 
						|
         }
 | 
						|
 | 
						|
         // We are done.  Allow the user to close the dialog.
 | 
						|
         fComplete = TRUE;
 | 
						|
         return FALSE;
 | 
						|
 | 
						|
      case WM_COMMAND:
 | 
						|
         switch (LOWORD(wParam)) {
 | 
						|
            case IDCANCEL:
 | 
						|
               // If abort is pressed, then set a flag that our worker thread
 | 
						|
               // periodically checks to decide if it needs to bail out.
 | 
						|
               if (!fComplete && !pei->fAbort) {
 | 
						|
                  pei->fAbort = TRUE;
 | 
						|
                  SetWindowText(hWndButton, TEXT("Aborting..."));
 | 
						|
                  EnableWindow(hWndButton, FALSE);
 | 
						|
                  return FALSE;
 | 
						|
               }
 | 
						|
               // fall through to IDOK
 | 
						|
 | 
						|
            case IDOK:
 | 
						|
               // Don't allow dialog to close until extract/test is complete.
 | 
						|
               if (fComplete) {
 | 
						|
                  g_hDlgProgress = NULL;
 | 
						|
                  EndDialog(hDlg, LOWORD(wParam));
 | 
						|
               }
 | 
						|
               return FALSE;
 | 
						|
         }
 | 
						|
         return FALSE;
 | 
						|
   }
 | 
						|
   return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
BOOL CALLBACK DlgProcViewProgress(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 | 
						|
 | 
						|
   static EXTRACT_INFO *pei;
 | 
						|
 | 
						|
   switch (uMsg) {
 | 
						|
 | 
						|
      case WM_INITDIALOG:
 | 
						|
         
 | 
						|
         // Globally store our handle so our worker thread can post to us.
 | 
						|
         g_hDlgProgress = hDlg;
 | 
						|
 | 
						|
         // Get a pointer to our extract information structure.
 | 
						|
         pei = (EXTRACT_INFO*)lParam;
 | 
						|
 | 
						|
         // Center our dialog over our parent.
 | 
						|
         CenterWindow(hDlg);
 | 
						|
 | 
						|
         // Store some globals until the extract finishes.
 | 
						|
         pei->hWndProgFile = GetDlgItem(hDlg, IDC_FILE_PROGRESS);
 | 
						|
 | 
						|
         // Set the ranges on our progress bar.
 | 
						|
         SendDlgItemMessage(hDlg, IDC_FILE_PROGRESS, PBM_SETRANGE, 0, 
 | 
						|
                            MAKELPARAM(0, PROGRESS_MAX));
 | 
						|
 | 
						|
         // Luanch our Extract thread and wait for WM_PRIVATE message.
 | 
						|
         DoExtractOrTestFiles(g_szZipFile, pei);
 | 
						|
 | 
						|
         return TRUE;
 | 
						|
 | 
						|
      case WM_PRIVATE: // Sent with wParam equal to MSG_OPERATION_COMPLETE when
 | 
						|
                       // test/extract is complete.
 | 
						|
 | 
						|
         // We are done.  Close our dialog.  Any errors will be reported by
 | 
						|
         // OnActionView().
 | 
						|
         g_hDlgProgress = NULL;
 | 
						|
         EndDialog(hDlg, LOWORD(wParam));
 | 
						|
         return FALSE;
 | 
						|
 | 
						|
      case WM_COMMAND:
 | 
						|
         // If abort is pressed, then set a flag that our worker thread
 | 
						|
         // periodically checks to decide if it needs to bail out.
 | 
						|
         if ((LOWORD(wParam) == IDCANCEL) && !pei->fAbort) {
 | 
						|
            pei->fAbort = TRUE;
 | 
						|
            SetWindowText(GetDlgItem(hDlg, IDCANCEL), TEXT("Aborting..."));
 | 
						|
            EnableWindow(GetDlgItem(hDlg, IDCANCEL), FALSE);
 | 
						|
            return FALSE;
 | 
						|
         }
 | 
						|
   }
 | 
						|
 | 
						|
   return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
void UpdateProgress(EXTRACT_INFO *pei, BOOL fFull) {
 | 
						|
 | 
						|
   DWORD dwFile, dwTotal, dwPercentage;
 | 
						|
   TCHAR szBuffer[_MAX_PATH + 32];
 | 
						|
 | 
						|
   // Compute our file progress bar position.
 | 
						|
   if (pei->dwBytesTotalThisFile) {
 | 
						|
      dwFile = (DWORD)(((DWORDLONG)PROGRESS_MAX * 
 | 
						|
                        (DWORDLONG)pei->dwBytesWrittenThisFile) / 
 | 
						|
                        (DWORDLONG)pei->dwBytesTotalThisFile);
 | 
						|
   } else {
 | 
						|
      dwFile = PROGRESS_MAX;
 | 
						|
   }
 | 
						|
 | 
						|
   // Set our file progress indicators.
 | 
						|
   SendMessage(pei->hWndProgFile,  PBM_SETPOS, dwFile,  0);
 | 
						|
 | 
						|
   // If we are only updating our View Progress dialog, then we are done.
 | 
						|
   if (!pei->hWndProgTotal) {
 | 
						|
      return;
 | 
						|
   }
 | 
						|
 | 
						|
   // Compute our total progress bar position.
 | 
						|
   dwTotal = (DWORD)(((DWORDLONG)PROGRESS_MAX * 
 | 
						|
                      (DWORDLONG)(pei->dwBytesWrittenPreviousFiles + 
 | 
						|
                                  pei->dwBytesWrittenThisFile + 
 | 
						|
                                  pei->dwFile)) / 
 | 
						|
                      (DWORDLONG)(pei->dwByteCount + 
 | 
						|
                                  pei->dwFileCount));
 | 
						|
   dwPercentage = dwTotal / (PROGRESS_MAX / 100);
 | 
						|
 | 
						|
   // Set our total progress indicators.
 | 
						|
   SendMessage(pei->hWndProgTotal, PBM_SETPOS, dwTotal, 0);
 | 
						|
 | 
						|
   // Set our total percentage text.
 | 
						|
   _stprintf(szBuffer, TEXT("%u%%"), dwPercentage);
 | 
						|
   SetWindowText(pei->hWndPercentage, szBuffer);
 | 
						|
 | 
						|
   // Set our current file and byte process counts.
 | 
						|
   FormatValue(szBuffer, pei->dwFile - 1);
 | 
						|
   SetWindowText(pei->hWndFilesProcessed, szBuffer);
 | 
						|
   FormatValue(szBuffer, pei->dwBytesWrittenPreviousFiles + 
 | 
						|
               pei->dwBytesWrittenThisFile);
 | 
						|
   SetWindowText(pei->hWndBytesProcessed, szBuffer);
 | 
						|
 | 
						|
 | 
						|
   if (fFull) {
 | 
						|
 | 
						|
      // Build our message string.
 | 
						|
      _stprintf(szBuffer, TEXT("%Sing: %S"), pei->fExtract ? 
 | 
						|
                "Extract" : "Test", pei->szFile);
 | 
						|
 | 
						|
      // Change all forward slashes to back slashes in the buffer.
 | 
						|
      ForwardSlashesToBackSlashesW(szBuffer);
 | 
						|
 | 
						|
      // Update the file name in our dialog.
 | 
						|
      SetWindowText(pei->hWndEditFile, szBuffer);
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Replace File Dialog Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
int PromptToReplace(LPCSTR szPath) {
 | 
						|
 | 
						|
   // Check to see if we are extracting for view only.
 | 
						|
   if (g_fViewing) {
 | 
						|
 | 
						|
      // Build prompt.
 | 
						|
      TCHAR szMessage[_MAX_PATH + 128];
 | 
						|
      _stprintf(szMessage, 
 | 
						|
         TEXT("A file named \"%S\" has already been extracted for viewing.  ")
 | 
						|
         TEXT("That file might be opened and locked for viewing by another application.\n\n")
 | 
						|
         TEXT("Would you like to attempt to overwirite it with the new file?"),
 | 
						|
         GetFileFromPath(szPath));
 | 
						|
      
 | 
						|
      // Display prompt.
 | 
						|
      if (IDYES == MessageBox(g_hDlgProgress, szMessage, g_szAppName, 
 | 
						|
                              MB_ICONWARNING | MB_YESNO))
 | 
						|
      {
 | 
						|
         // Tell Info-ZIP to continue with extraction.
 | 
						|
         return IDM_REPLACE_YES;
 | 
						|
      }
 | 
						|
 | 
						|
      // Remember that the file was skipped and tell Info-ZIP to abort extraction.
 | 
						|
      g_fSkipped = TRUE;
 | 
						|
      return IDM_REPLACE_NO;
 | 
						|
   }
 | 
						|
   
 | 
						|
   // Otherwise, do the normal replace prompt dialog.
 | 
						|
   return DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_REPLACE), g_hWndMain, 
 | 
						|
                         (DLGPROC)DlgProcReplace, (LPARAM)szPath);
 | 
						|
}
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
BOOL CALLBACK DlgProcReplace(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 | 
						|
   TCHAR szMessage[_MAX_PATH + 32];
 | 
						|
 | 
						|
   switch (uMsg) {
 | 
						|
 | 
						|
      case WM_INITDIALOG:
 | 
						|
 | 
						|
         // Play the question tone to alert the user.
 | 
						|
         MessageBeep(MB_ICONQUESTION);
 | 
						|
         
 | 
						|
         // Display a message with the file name.
 | 
						|
         _stprintf(szMessage, TEXT("\"%S\" already exists."), (LPCSTR)lParam);
 | 
						|
 | 
						|
         // Change all forward slashes to back slashes in the buffer.
 | 
						|
         ForwardSlashesToBackSlashesW(szMessage);
 | 
						|
 | 
						|
         // Display the file string.
 | 
						|
         SetDlgItemText(hDlg, IDC_FILE, szMessage);
 | 
						|
 | 
						|
         // Center our dialog over our parent.
 | 
						|
         CenterWindow(hDlg);
 | 
						|
         return TRUE;
 | 
						|
 | 
						|
      case WM_COMMAND:
 | 
						|
         switch (LOWORD(wParam)) {
 | 
						|
 | 
						|
            case IDCANCEL:
 | 
						|
            case IDOK:
 | 
						|
               EndDialog(hDlg, IDM_REPLACE_NO);
 | 
						|
               break;
 | 
						|
 | 
						|
            case IDM_REPLACE_ALL:
 | 
						|
            case IDM_REPLACE_NONE:
 | 
						|
            case IDM_REPLACE_YES:
 | 
						|
            case IDM_REPLACE_NO:
 | 
						|
               EndDialog(hDlg, wParam);
 | 
						|
               break;
 | 
						|
         }
 | 
						|
         return FALSE;
 | 
						|
   }
 | 
						|
   return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Password Dialog Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
#if CRYPT
 | 
						|
 | 
						|
BOOL CALLBACK DlgProcPassword(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 | 
						|
   
 | 
						|
   // Return Values:
 | 
						|
   //    IZ_PW_ENTERED    got some PWD string, use/try it
 | 
						|
   //    IZ_PW_CANCEL     no password available (for this entry)
 | 
						|
   //    IZ_PW_CANCELALL  no password, skip any further PWD request
 | 
						|
   //    IZ_PW_ERROR      failure (no mem, no tty, ...)
 | 
						|
 | 
						|
   static DECRYPT_INFO *pdi;
 | 
						|
   TCHAR szMessage[_MAX_PATH + 32];
 | 
						|
 | 
						|
   switch (uMsg) {
 | 
						|
 | 
						|
      case WM_INITDIALOG:
 | 
						|
 | 
						|
         // Play the question tone to alert the user.
 | 
						|
         MessageBeep(MB_ICONQUESTION);
 | 
						|
         
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
         // Add "Ok" button to caption bar.
 | 
						|
         SetWindowLong(hDlg, GWL_EXSTYLE, WS_EX_CAPTIONOKBTN | 
 | 
						|
                       GetWindowLong(hDlg, GWL_EXSTYLE));
 | 
						|
#endif
 | 
						|
 | 
						|
         // Store our decrypt information structure.
 | 
						|
         pdi = (DECRYPT_INFO*)lParam;
 | 
						|
 | 
						|
         // Display a message with the file name.
 | 
						|
         _stprintf(szMessage, TEXT("\"%S\" is encrypted."), pdi->szFile);
 | 
						|
 | 
						|
         // Change all forward slashes to back slashes in the buffer.
 | 
						|
         ForwardSlashesToBackSlashesW(szMessage);
 | 
						|
 | 
						|
         // Display the message with the file name.
 | 
						|
         SetDlgItemText(hDlg, IDC_FILE, szMessage);
 | 
						|
 | 
						|
         // Display the appropriate prompt.
 | 
						|
         if (pdi->retry) {
 | 
						|
            _stprintf(szMessage, TEXT("Password was incorrect. Please re-enter (%d/%d)."),
 | 
						|
                     MAX_PASSWORD_RETRIES - pdi->retry + 2, MAX_PASSWORD_RETRIES + 1);
 | 
						|
            SetDlgItemText(hDlg, IDC_PROMPT, szMessage);
 | 
						|
         } else {
 | 
						|
            SetDlgItemText(hDlg, IDC_PROMPT, TEXT("Please enter the password."));
 | 
						|
         }
 | 
						|
 | 
						|
         // Limit the password to the size of the password buffer we have been given.
 | 
						|
         SendDlgItemMessage(hDlg, IDC_PASSWORD, EM_LIMITTEXT, pdi->nSize - 1, 0);
 | 
						|
 | 
						|
         // Center our dialog over our parent.
 | 
						|
         CenterWindow(hDlg);
 | 
						|
         return TRUE;
 | 
						|
 | 
						|
      case WM_COMMAND:
 | 
						|
         switch (LOWORD(wParam)) {
 | 
						|
 | 
						|
            case IDOK:
 | 
						|
 | 
						|
               // Store the password in our return password buffer.
 | 
						|
               GetDlgItemText(hDlg, IDC_PASSWORD, szMessage, countof(szMessage));
 | 
						|
               wcstombs(pdi->szPassword, szMessage, pdi->nSize);
 | 
						|
               EndDialog(hDlg, IZ_PW_ENTERED);
 | 
						|
               return FALSE;
 | 
						|
 | 
						|
            case IDCANCEL:
 | 
						|
               g_fSkipped = TRUE;
 | 
						|
               EndDialog(hDlg, IZ_PW_CANCEL);
 | 
						|
               return FALSE;
 | 
						|
 | 
						|
            case IDC_SKIP_ALL:
 | 
						|
               g_fSkipped = TRUE;
 | 
						|
               EndDialog(hDlg, IZ_PW_CANCELALL);
 | 
						|
               return FALSE;
 | 
						|
         }
 | 
						|
         return FALSE;
 | 
						|
   }
 | 
						|
   return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
#endif // CRYPT
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** View Association Dialog Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
BOOL CALLBACK DlgProcViewAssociation(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 | 
						|
 | 
						|
   static LPTSTR szApp;
 | 
						|
 | 
						|
   switch (uMsg) {
 | 
						|
 | 
						|
      case WM_INITDIALOG:
 | 
						|
         // Store the path buffer for our application.
 | 
						|
         szApp = (LPTSTR)lParam;
 | 
						|
 | 
						|
         // Read our default viewer from the registry.
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
         GetOptionString(TEXT("FileViewer"), TEXT("\\Windows\\PWord.exe"), 
 | 
						|
                         szApp, sizeof(TCHAR) * _MAX_PATH);
 | 
						|
#else
 | 
						|
         GetOptionString(TEXT("FileViewer"), TEXT("notepad.exe"), 
 | 
						|
                         szApp, sizeof(TCHAR) * _MAX_PATH);
 | 
						|
#endif
 | 
						|
 | 
						|
         // Limit our edit control to our buffer size.
 | 
						|
         SendDlgItemMessage(hDlg, IDC_PATH, EM_LIMITTEXT, _MAX_PATH - 1, 0);
 | 
						|
 | 
						|
         // Set our path string in our dialog.
 | 
						|
         SetDlgItemText(hDlg, IDC_PATH, szApp);
 | 
						|
 | 
						|
         // Center our dialog over our parent.
 | 
						|
         CenterWindow(hDlg);
 | 
						|
         return TRUE;
 | 
						|
 | 
						|
      case WM_COMMAND:
 | 
						|
         switch (LOWORD(wParam)) {
 | 
						|
 | 
						|
            case IDOK:
 | 
						|
               // Get the text currently in the path edit box and store it.
 | 
						|
               GetDlgItemText(hDlg, IDC_PATH, szApp, _MAX_PATH);
 | 
						|
               WriteOptionString(TEXT("FileViewer"), szApp);
 | 
						|
               // Fall through
 | 
						|
 | 
						|
            case IDCANCEL:
 | 
						|
               EndDialog(hDlg, LOWORD(wParam));
 | 
						|
               break;
 | 
						|
 | 
						|
            case IDC_BROWSE:
 | 
						|
               // Get the text currently in the path edit box.
 | 
						|
               GetDlgItemText(hDlg, IDC_PATH, szApp, _MAX_PATH);
 | 
						|
 | 
						|
               // Get the direcory from the path text.
 | 
						|
               ForwardSlashesToBackSlashesW(szApp);
 | 
						|
               TCHAR szInitialDir[_MAX_PATH], *szFile;
 | 
						|
               _tcscpy(szInitialDir, szApp);
 | 
						|
               if (szFile = _tcsrchr(szInitialDir, TEXT('\\'))) {
 | 
						|
                  *szFile = TEXT('\0');
 | 
						|
               }
 | 
						|
 | 
						|
               // Prepare to display browse dialog.
 | 
						|
               OPENFILENAME ofn;
 | 
						|
               ZeroMemory(&ofn, sizeof(ofn));
 | 
						|
               ofn.lStructSize     = sizeof(ofn);
 | 
						|
               ofn.hwndOwner       = hDlg;
 | 
						|
               ofn.hInstance       = g_hInst;
 | 
						|
               ofn.lpstrFilter     = TEXT("Programs (*.exe)\0*.exe\0All Files (*.*)\0*.*\0");
 | 
						|
               ofn.nFilterIndex    = 1;
 | 
						|
               ofn.lpstrFile       = szApp;
 | 
						|
               ofn.nMaxFile        = _MAX_PATH;
 | 
						|
               ofn.lpstrInitialDir = szInitialDir;
 | 
						|
               ofn.lpstrTitle      = TEXT("Open With...");
 | 
						|
               ofn.Flags           = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
 | 
						|
               ofn.lpstrDefExt     = TEXT("exe");
 | 
						|
 | 
						|
               // Display the browse dialog and update our path edit box if neccessary.
 | 
						|
               if (GetOpenFileName(&ofn)) {
 | 
						|
                  SetDlgItemText(hDlg, IDC_PATH, szApp);
 | 
						|
               }
 | 
						|
               break;
 | 
						|
         }
 | 
						|
         return FALSE;
 | 
						|
   }
 | 
						|
   return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** Comment Dialog Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
BOOL CALLBACK DlgProcComment(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 | 
						|
   RECT    rc;
 | 
						|
   HCURSOR hCur;
 | 
						|
   int     result;
 | 
						|
 | 
						|
   switch (uMsg) {
 | 
						|
 | 
						|
      case WM_INITDIALOG:
 | 
						|
         // Get the handle to our edit box and store it globally.
 | 
						|
         g_hWndEdit = GetDlgItem(hDlg, IDC_COMMENT);
 | 
						|
 | 
						|
         // Disable our edit box from being edited.
 | 
						|
         DisableEditing(g_hWndEdit);
 | 
						|
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
         // Add "Ok" button to caption bar and make window No-Drag.
 | 
						|
         SetWindowLong(hDlg, GWL_EXSTYLE, WS_EX_CAPTIONOKBTN | WS_EX_NODRAG |
 | 
						|
                       GetWindowLong(hDlg, GWL_EXSTYLE));
 | 
						|
 | 
						|
         // On CE, we resize our dialog to be full screen (same size as parent).
 | 
						|
         GetWindowRect(g_hWndMain, &rc);
 | 
						|
         MoveWindow(hDlg, rc.left, rc.top, rc.right - rc.left, 
 | 
						|
                    rc.bottom - rc.top + 1, FALSE);
 | 
						|
#else
 | 
						|
         // On NT we just center the dialog.
 | 
						|
         CenterWindow(hDlg);
 | 
						|
#endif
 | 
						|
 | 
						|
         // Set our edit control to be the full size of our dialog.
 | 
						|
         GetClientRect(hDlg, &rc);
 | 
						|
         MoveWindow(g_hWndEdit, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE);
 | 
						|
 | 
						|
         // Show hour glass cursor while processing comment.
 | 
						|
         hCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
 | 
						|
 | 
						|
         // Let Info-ZIP and our callbacks do the work.
 | 
						|
         result = DoGetComment(g_szZipFile);
 | 
						|
 | 
						|
         // Restore/remove our cursor.
 | 
						|
         SetCursor(hCur);
 | 
						|
 | 
						|
         // Display an error dialog if an error occurred.
 | 
						|
         if ((result != PK_OK) && (result != PK_WARN)) {
 | 
						|
            MessageBox(g_hWndMain, GetZipErrorString(result), g_szAppName,
 | 
						|
                       MB_ICONERROR | MB_OK);
 | 
						|
         }
 | 
						|
 | 
						|
         // Clear our global edit box handle as we are done with it.
 | 
						|
         g_hWndEdit = NULL;
 | 
						|
 | 
						|
         // Return FALSE to prevent edit box from gaining focus and showing highlight.
 | 
						|
         return FALSE;
 | 
						|
 | 
						|
      case WM_COMMAND:
 | 
						|
         if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL)) {
 | 
						|
            EndDialog(hDlg, LOWORD(wParam));
 | 
						|
         }
 | 
						|
         return FALSE;
 | 
						|
   }
 | 
						|
   return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//******************************************************************************
 | 
						|
//***** About Dialog Functions
 | 
						|
//******************************************************************************
 | 
						|
 | 
						|
BOOL CALLBACK DlgProcAbout(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 | 
						|
 | 
						|
   switch (uMsg) {
 | 
						|
 | 
						|
      case WM_INITDIALOG:
 | 
						|
 | 
						|
#ifdef _WIN32_WCE
 | 
						|
         // Add "Ok" button to caption bar.
 | 
						|
         SetWindowLong(hDlg, GWL_EXSTYLE, WS_EX_CAPTIONOKBTN | 
 | 
						|
                       GetWindowLong(hDlg, GWL_EXSTYLE));
 | 
						|
#endif
 | 
						|
 | 
						|
         // Fill in a few static members.
 | 
						|
         TCHAR szBuffer[80];
 | 
						|
         SetDlgItemText(hDlg, IDC_PRODUCT, TEXT(VER_PRODUCT_STR));
 | 
						|
         _stprintf(szBuffer, TEXT("Freeware Version %S"), VER_FULLVERSION_STR);
 | 
						|
         SetDlgItemText(hDlg, IDC_VERSION, szBuffer);
 | 
						|
         _stprintf(szBuffer, TEXT("Developed by %S"), VER_DEVELOPER_STR);
 | 
						|
         SetDlgItemText(hDlg, IDC_DEVELOPER, szBuffer);
 | 
						|
         SetDlgItemText(hDlg, IDC_COPYRIGHT, TEXT(VER_COPYRIGHT_STR));
 | 
						|
         SetDlgItemText(hDlg, IDC_COMMENT, TEXT(VER_COMMENT_STR));
 | 
						|
 | 
						|
         // Center the dialog over our parent.
 | 
						|
         CenterWindow(hDlg);
 | 
						|
         return TRUE;
 | 
						|
 | 
						|
      case WM_COMMAND:
 | 
						|
         if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL)) {
 | 
						|
            EndDialog(hDlg, 0);
 | 
						|
         }
 | 
						|
         return FALSE;
 | 
						|
   }
 | 
						|
   return FALSE;
 | 
						|
}
 |