winmain.cpp
资源名称:unzip540.zip [点击查看]
上传用户:andy_li
上传日期:2007-01-06
资源大小:1019k
文件大小:131k
源码类别:
压缩解压
开发平台:
MultiPlatform
- //******************************************************************************
- //
- // 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.nn")
- 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(' ');
- // 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 "shellOpencommand" 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(' ');
- }
- } else {
- szPath = szIconFile;
- if (szEnd = _tcschr(szPath, TEXT(' '))) {
- *szEnd = TEXT(' ');
- }
- }
- // 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("&HelptF1"));
- }
- #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) *.zip SFX files (*.exe) *.exe All Files (*.*) *.* ");
- 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"nn")
- 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 = ' ';
- // 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".nn%snnTry 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 = ' ';
- while (*pszIn) {
- if (*pszIn == 'n') {
- if (cPrev == 'r') {
- cPrev = ' ';
- } else {
- *(pszOut++) = TEXT('r');
- *(pszOut++) = TEXT('n');
- cPrev = 'n';
- }
- } else if (*pszIn == 'r') {
- if (cPrev == 'n') {
- cPrev = ' ';
- } 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(' ');
- 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(' ');
- 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;
- }