www.pudn.com > WinMerge-2.6.12-src.zip > Installer.cpp
/* Installer.cpp: Merge7z plugin installer * Copyright (c) 2005 Jochen Tucht * * License: This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Remarks: Bundles plugins for all supported versions of 7-Zip in a single * installer. Also includes essential components from latest 7-Zip * stable release for optional standalone operation. * Files to be installed are embedded as resources (see Files.rc2). * The resulting exe must be run through UPX (upx.sourceforge.net) * to reduce size. Please mind 2. a) of the GNU General Public License, and log your changes below. DATE: BY: DESCRIPTION: ========== ================== ================================================ 2005/01/15 Jochen Tucht Created 2005/02/28 Jochen Tucht Initialize filename in Open dialog to "*.exe" 2005/04/26 Jochen Tucht No default assumption on program directory Double-click option for in-place extraction Fix empty path issue with GetFileTitle() Accept extraction folder on command line Batch options: /standalone, /select, /commit 2005/05/30 Jochen Tucht Standalone option now based on 7z420 2005/06/28 Jochen Tucht Standalone option now based on 7z423 2005/12/04 Jochen Tucht Standalone option now based on 7z431 2005/12/09 Jochen Tucht Standalone option now based on 7z432 2006/06/28 Jochen Neubeck Standalone option now based on 7z442 */ #include#pragma intrinsic(memset) // do not depend on CRT // Compute dwBuild from revision.txt static const DWORD dwBuild = ( sizeof"" # define VERSION(MAJOR,MINOR) # include "../Merge7z/revision.txt" # undef VERSION ); const SYSTEMTIME *st = NULL; // initialized from SYSTEMTIME RCDATA in Files.rc2 LPTSTR NTAPI ArgLower(LPTSTR lpCmdLine) { while (*lpCmdLine == VK_SPACE) ++lpCmdLine; return lpCmdLine; } LPTSTR NTAPI ArgUpper(LPTSTR lpCmdLine) { TCHAR cSpace = VK_SPACE; while (*lpCmdLine && *lpCmdLine != cSpace) { if (*lpCmdLine == '"') { cSpace ^= VK_SPACE; } ++lpCmdLine; } return lpCmdLine; } int NTAPI PathGetTailLength(LPCTSTR path) { //GetFileTitle() returns garbage when passed in empty path... return *path ? GetFileTitle(path, 0, 0) : 0; } void InstallFile(HWND hWnd, LPTSTR lpName, LPCTSTR lpType, LPTSTR path, int cchPath) { HMODULE hModule = GetModuleHandle(0); HRSRC hResource = FindResource(hModule, lpName, lpType); DWORD dwSize = SizeofResource(hModule, hResource); LPVOID pResource = LoadResource(hModule, hResource); LPTSTR name = path + cchPath; if (name != lpName) { lstrcpy(name, lpName); } int cchName = lstrlen(name); int i; for (i = 0 ; i < cchName ; ++i) { if (name[i] == '/') { name[i] = '\0'; CreateDirectory(path, 0); name[i] = '\\'; } } HANDLE hFile = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); if (hFile != INVALID_HANDLE_VALUE) { DWORD dwNumberOfBytesWritten; BOOL bSuccess = WriteFile(hFile, pResource, dwSize, &dwNumberOfBytesWritten, 0); FILETIME ft; if (SystemTimeToFileTime(st, &ft)) { SetFileTime(hFile, &ft, &ft, &ft); } CloseHandle(hFile); if (!bSuccess || dwNumberOfBytesWritten != dwSize) { hFile = INVALID_HANDLE_VALUE; } } if (hFile == INVALID_HANDLE_VALUE) { LONG error = GetLastError(); name[cchName++] = '\n'; FormatMessage ( FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT), name + cchName, MAX_PATH, NULL ); int response = MessageBox(hWnd, path, 0, MB_ICONSTOP|MB_OKCANCEL); if (response == IDCANCEL) { ExitProcess(1); } } } BOOL CALLBACK fnPopulateList(HMODULE hModule, LPCTSTR lpType, LPTSTR lpName, LONG lParam) { TCHAR acName[MAX_PATH]; if (ATOM aName = FindAtom(lpName)) { GetAtomName(aName, lpName = acName, sizeof acName); } SendDlgItemMessage((HWND)lParam, 100, LB_ADDSTRING, 0, (LPARAM)lpName); return TRUE; } BOOL CALLBACK fnInstallFiles(HMODULE hModule, LPCTSTR lpType, LPTSTR lpName, LONG lParam) { HWND hWnd = (HWND)lParam; TCHAR path[8 * MAX_PATH]; int cchPath = GetDlgItemText(hWnd, 203, path, 5 * MAX_PATH); int cchName = PathGetTailLength(path); if (cchName < cchPath) { cchPath -= cchName; } if (cchPath != 3 || path[1] != ':') { path[cchPath++] = '\\'; } TCHAR acName[MAX_PATH]; if (ATOM aName = FindAtom(lpName)) { GetAtomName(aName, lpName = acName, sizeof acName); } InstallFile(hWnd, lpName, lpType, path, cchPath); return TRUE; } BOOL CALLBACK DlgMain_InitDialog(HWND hWnd, LPARAM lParam) { TCHAR path[5 * MAX_PATH]; wsprintf(path + GetWindowText(hWnd, path, MAX_PATH), " (dllbuild %04lu, %04u-%02u-%02u)", dwBuild, (UINT)st->wYear, (UINT)st->wMonth, (UINT)st->wDay); SetWindowText(hWnd, path); EnumResourceNames(GetModuleHandle(0), "Merge7z", fnPopulateList, (LONG)hWnd); LONG lCount = SendDlgItemMessage(hWnd, 100, LB_GETCOUNT , 0, 0); SendDlgItemMessage(hWnd, 100, LB_SELITEMRANGEEX, 0, lCount - 1); CheckRadioButton(hWnd, 201, 202, 201); //GetModuleFileName(0, path, sizeof path); //SetDlgItemText(hWnd, 203, path); BOOL bCommit = FALSE; BOOL bSelect = FALSE; LPTSTR lpCmdLine = GetCommandLine(); LPTSTR lpArgLower = ArgLower(lpCmdLine); LPTSTR lpArgUpper = ArgUpper(lpArgLower); while (*(lpArgLower = ArgLower(lpArgUpper))) { TCHAR cAhead = *(lpArgUpper = ArgUpper(lpArgLower)); *lpArgUpper = '\0'; if (0 == lstrcmpi(lpArgLower, "/standalone")) { CheckRadioButton(hWnd, 201, 202, 202); SendMessage(hWnd, WM_COMMAND, 202, 0); CheckDlgButton(hWnd, 205, 1); SendMessage(hWnd, WM_COMMAND, 205, 0); } else if (0 == lstrcmpi(lpArgLower, "/select")) { int lower = -1; int upper = -1; *lpArgUpper = cAhead; if (*(lpArgLower = ArgLower(lpArgUpper))) { cAhead = *(lpArgUpper = ArgUpper(lpArgLower)); *lpArgUpper = '\0'; lower = SendDlgItemMessage(hWnd, 100, LB_FINDSTRING, -1, (LPARAM)lpArgLower); if (lower == -1) { MessageBox(hWnd, lpArgLower, "No match", MB_ICONSTOP); } } *lpArgUpper = cAhead; if (*(lpArgLower = ArgLower(lpArgUpper))) { cAhead = *(lpArgUpper = ArgUpper(lpArgLower)); *lpArgUpper = '\0'; int ahead = -1; while ((ahead = SendDlgItemMessage(hWnd, 100, LB_FINDSTRING, ahead, (LPARAM)lpArgLower)) > upper) { upper = ahead; } if (upper == -1) { MessageBox(hWnd, lpArgLower, "No match", MB_ICONSTOP); } } if (lower >= 0 && upper >= 0) { if (!bSelect) { SendDlgItemMessage(hWnd, 100, LB_SETSEL, 0, -1); bSelect = TRUE; } SendDlgItemMessage(hWnd, 100, LB_SELITEMRANGEEX, lower, upper); } } else if (0 == lstrcmpi(lpArgLower, "/commit")) { bCommit = TRUE; } /*//just for test else if (0 == lstrcmpi(lpArgLower, "\"ping pong\"")) { MessageBox(hWnd, "", lpArgLower, 0); }*/ else { DWORD dwAttributes = GetFileAttributes(lpArgLower); if (dwAttributes != 0xFFFFFFFF && dwAttributes & FILE_ATTRIBUTE_DIRECTORY) { lstrcpy(path, lpArgLower); if (PathGetTailLength(path) > 1) { lstrcat(path, "\\"); } lstrcat(path, "*.exe"); CheckRadioButton(hWnd, 201, 202, 202); SendMessage(hWnd, WM_COMMAND, 202, 0); SetDlgItemText(hWnd, 203, path); } else { MessageBox(hWnd, lpArgLower, "Not a directory", MB_ICONSTOP); } } *lpArgUpper = cAhead; } if (bCommit) { SendMessage(hWnd, WM_COMMAND, IDOK, 0); } return TRUE; } BOOL CALLBACK DlgMain_BrowseExe(HWND hWnd) { struct { OPENFILENAME ofn; TCHAR buffer[5 * MAX_PATH]; } path; ZeroMemory(&path, sizeof path); path.ofn.lStructSize = sizeof path.ofn; path.ofn.hwndOwner = hWnd; path.ofn.lpstrFile = path.buffer; path.ofn.nMaxFile = sizeof path.buffer; path.ofn.lpstrFilter = "*.exe\0*.exe\0"; path.ofn.lpstrTitle = "Browse for application ..."; path.ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_PATHMUSTEXIST; int cchPath = GetDlgItemText(hWnd, 203, path.buffer, sizeof path.buffer); int cchName = PathGetTailLength(path.buffer); if (cchName < cchPath) { lstrcpy(path.buffer + cchPath - cchName, "\\*.exe"); } if (GetOpenFileName(&path.ofn)) { SetDlgItemText(hWnd, 203, path.buffer); } return FALSE; } BOOL CALLBACK DlgMain_InstallFiles(HWND hWnd) { HCURSOR hCursor = SetCursor(LoadCursor(0, IDC_WAIT)); HINSTANCE hModule = GetModuleHandle(0); int count = SendDlgItemMessage(hWnd, 100, LB_GETCOUNT , 0, 0); int index = 0; TCHAR path[8 * MAX_PATH]; int cchPath; if (IsDlgButtonChecked(hWnd, 201)) { cchPath = GetSystemDirectory(path, 4 * MAX_PATH); } else { cchPath = GetDlgItemText(hWnd, 203, path, 5 * MAX_PATH); int cchName = PathGetTailLength(path); if (cchName < cchPath) { cchPath -= cchName; } } if (cchPath != 3 || path[1] != ':') { path[cchPath++] = '\\'; } LPTSTR name = path + cchPath; while (index < count) { if (SendDlgItemMessage(hWnd, 100, LB_GETSEL, index, 0)) { int cchName = SendDlgItemMessage(hWnd, 100, LB_GETTEXT, index, (LPARAM)name); InstallFile(hWnd, name, "Merge7z", path, cchPath); } ++index; } if (IsDlgButtonChecked(hWnd, 205)) { EnumResourceNames(GetModuleHandle(0), "7-ZIP", fnInstallFiles, (LONG)hWnd); } SetCursor(hCursor); return TRUE; } BOOL CALLBACK DlgMain_EnableStandalone(HWND hWnd) { if (IsDlgButtonChecked(hWnd, 205)) { int lower = SendDlgItemMessage(hWnd, 100, LB_FINDSTRINGEXACT, -1, (LPARAM)"Merge7z442.dll"); int upper = SendDlgItemMessage(hWnd, 100, LB_FINDSTRINGEXACT, -1, (LPARAM)"Merge7z442U.dll"); SendDlgItemMessage(hWnd, 100, LB_SELITEMRANGEEX, lower, upper); if (GetFocus() == GetDlgItem(hWnd, 205)) { SendDlgItemMessage(hWnd, 100, LB_SETTOPINDEX, lower, 0); } } return TRUE; } BOOL CALLBACK DlgMain(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { TCHAR path[8 * MAX_PATH]; switch (uMsg) { case WM_INITDIALOG: return DlgMain_InitDialog(hWnd, lParam); case WM_COMMAND: switch (wParam) { case 201: CheckDlgButton(hWnd, 205, 0); //fall through case 202: EnableWindow(GetDlgItem(hWnd, 203), wParam == 202); EnableWindow(GetDlgItem(hWnd, 204), wParam == 202); EnableWindow(GetDlgItem(hWnd, 205), wParam == 202); SetDlgItemText(hWnd, 203, ""); break; case MAKELONG(202, BN_DOUBLECLICKED): GetModuleFileName(0, path, sizeof path); SetDlgItemText(hWnd, 203, path); break; case MAKELONG(203, EN_CHANGE): EnableWindow(GetDlgItem(hWnd, IDOK), GetWindowTextLength((HWND)lParam) || IsDlgButtonChecked(hWnd, 201)); break; case 204: return DlgMain_BrowseExe(hWnd); case 205: if (IsDlgButtonChecked(hWnd, 205) && GetKeyState(VK_SHIFT) >= 0) SendDlgItemMessage(hWnd, 100, LB_SETSEL, 0, -1); //fall through case MAKELONG(100, LBN_SELCHANGE): return DlgMain_EnableStandalone(hWnd); case IDOK: if (DlgMain_InstallFiles(hWnd)) case IDCANCEL: EndDialog(hWnd, wParam); break; } return TRUE; } return FALSE; } void WinMainCRTStartup(void) { HINSTANCE hModule = GetModuleHandle(0); HRSRC hResource = FindResource(hModule, "SYSTEMTIME", RT_RCDATA); st = (SYSTEMTIME *)LoadResource(hModule, hResource); InitAtomTable(0x3001); # define IMPORT(name) AddAtom(#name); /##/ # include "files.rc2" DialogBoxParam(hModule, MAKEINTRESOURCE(100), 0, DlgMain, 0); ExitProcess(0); }