| Index: third_party/lzma_sdk/C/Util/SfxSetup/SfxSetup.c
|
| ===================================================================
|
| --- third_party/lzma_sdk/C/Util/SfxSetup/SfxSetup.c (revision 0)
|
| +++ third_party/lzma_sdk/C/Util/SfxSetup/SfxSetup.c (revision 0)
|
| @@ -0,0 +1,592 @@
|
| +/* SfxSetup.c - 7z SFX Setup
|
| +2010-11-11 : Igor Pavlov : Public domain */
|
| +
|
| +#ifndef UNICODE
|
| +#define UNICODE
|
| +#endif
|
| +
|
| +#ifndef _UNICODE
|
| +#define _UNICODE
|
| +#endif
|
| +
|
| +#ifdef _CONSOLE
|
| +#include <stdio.h>
|
| +#endif
|
| +
|
| +#include "../../7z.h"
|
| +#include "../../7zAlloc.h"
|
| +#include "../../7zCrc.h"
|
| +#include "../../7zFile.h"
|
| +#include "../../CpuArch.h"
|
| +
|
| +#define k_EXE_ExtIndex 1
|
| +
|
| +static const char *kExts[] =
|
| +{
|
| + "bat",
|
| + "exe",
|
| + "inf",
|
| + "msi",
|
| + #ifdef UNDER_CE
|
| + "cab",
|
| + #endif
|
| + "html",
|
| + "htm"
|
| +};
|
| +
|
| +static const char *kNames[] =
|
| +{
|
| + "setup",
|
| + "install",
|
| + "run",
|
| + "start"
|
| +};
|
| +
|
| +static unsigned FindExt(const wchar_t *s, unsigned *extLen)
|
| +{
|
| + unsigned len = (unsigned)wcslen(s);
|
| + unsigned i;
|
| + for (i = len; i > 0; i--)
|
| + {
|
| + if (s[i - 1] == '.')
|
| + {
|
| + *extLen = len - i;
|
| + return i - 1;
|
| + }
|
| + }
|
| + *extLen = 0;
|
| + return len;
|
| +}
|
| +
|
| +#define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c)))
|
| +
|
| +static unsigned FindItem(const char **items, unsigned num, const wchar_t *s, unsigned len)
|
| +{
|
| + unsigned i;
|
| + for (i = 0; i < num; i++)
|
| + {
|
| + const char *item = items[i];
|
| + unsigned itemLen = (unsigned)strlen(item);
|
| + unsigned j;
|
| + if (len != itemLen)
|
| + continue;
|
| + for (j = 0; j < len; j++)
|
| + {
|
| + unsigned c = item[j];
|
| + if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j])
|
| + break;
|
| + }
|
| + if (j == len)
|
| + return i;
|
| + }
|
| + return i;
|
| +}
|
| +
|
| +#ifdef _CONSOLE
|
| +static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
|
| +{
|
| + ctrlType = ctrlType;
|
| + return TRUE;
|
| +}
|
| +#endif
|
| +
|
| +static void PrintErrorMessage(const char *message)
|
| +{
|
| + #ifdef _CONSOLE
|
| + printf("\n7-Zip Error: %s\n", message);
|
| + #else
|
| + #ifdef UNDER_CE
|
| + WCHAR messageW[256 + 4];
|
| + unsigned i;
|
| + for (i = 0; i < 256 && message[i] != 0; i++)
|
| + messageW[i] = message[i];
|
| + messageW[i] = 0;
|
| + MessageBoxW(0, messageW, L"7-Zip Error", MB_ICONERROR);
|
| + #else
|
| + MessageBoxA(0, message, "7-Zip Error", MB_ICONERROR);
|
| + #endif
|
| + #endif
|
| +}
|
| +
|
| +static WRes MyCreateDir(const WCHAR *name)
|
| +{
|
| + return CreateDirectoryW(name, NULL) ? 0 : GetLastError();
|
| +}
|
| +
|
| +#ifdef UNDER_CE
|
| +#define kBufferSize (1 << 13)
|
| +#else
|
| +#define kBufferSize (1 << 15)
|
| +#endif
|
| +
|
| +#define kSignatureSearchLimit (1 << 22)
|
| +
|
| +static Bool FindSignature(CSzFile *stream, UInt64 *resPos)
|
| +{
|
| + Byte buf[kBufferSize];
|
| + size_t numPrevBytes = 0;
|
| + *resPos = 0;
|
| + for (;;)
|
| + {
|
| + size_t numTests, pos;
|
| + if (*resPos > kSignatureSearchLimit)
|
| + return False;
|
| +
|
| + do
|
| + {
|
| + size_t processed = kBufferSize - numPrevBytes;
|
| + if (File_Read(stream, buf + numPrevBytes, &processed) != 0)
|
| + return False;
|
| + if (processed == 0)
|
| + return False;
|
| + numPrevBytes += processed;
|
| + }
|
| + while (numPrevBytes <= k7zStartHeaderSize);
|
| +
|
| + numTests = numPrevBytes - k7zStartHeaderSize;
|
| + for (pos = 0; pos < numTests; pos++)
|
| + {
|
| + for (; buf[pos] != '7' && pos < numTests; pos++);
|
| + if (pos == numTests)
|
| + break;
|
| + if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0)
|
| + if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8))
|
| + {
|
| + *resPos += pos;
|
| + return True;
|
| + }
|
| + }
|
| + *resPos += numTests;
|
| + numPrevBytes -= numTests;
|
| + memmove(buf, buf + numTests, numPrevBytes);
|
| + }
|
| +}
|
| +
|
| +static Bool DoesFileOrDirExist(const WCHAR *path)
|
| +{
|
| + WIN32_FIND_DATAW fd;
|
| + HANDLE handle;
|
| + handle = FindFirstFileW(path, &fd);
|
| + if (handle == INVALID_HANDLE_VALUE)
|
| + return False;
|
| + FindClose(handle);
|
| + return True;
|
| +}
|
| +
|
| +static WRes RemoveDirWithSubItems(WCHAR *path)
|
| +{
|
| + WIN32_FIND_DATAW fd;
|
| + HANDLE handle;
|
| + WRes res = 0;
|
| + size_t len = wcslen(path);
|
| + wcscpy(path + len, L"*");
|
| + handle = FindFirstFileW(path, &fd);
|
| + path[len] = L'\0';
|
| + if (handle == INVALID_HANDLE_VALUE)
|
| + return GetLastError();
|
| + for (;;)
|
| + {
|
| + if (wcscmp(fd.cFileName, L".") != 0 &&
|
| + wcscmp(fd.cFileName, L"..") != 0)
|
| + {
|
| + wcscpy(path + len, fd.cFileName);
|
| + if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
| + {
|
| + wcscat(path, L"\\");
|
| + res = RemoveDirWithSubItems(path);
|
| + }
|
| + else
|
| + {
|
| + SetFileAttributesW(path, 0);
|
| + if (DeleteFileW(path) == 0)
|
| + res = GetLastError();
|
| + }
|
| + if (res != 0)
|
| + break;
|
| + }
|
| + if (!FindNextFileW(handle, &fd))
|
| + {
|
| + res = GetLastError();
|
| + if (res == ERROR_NO_MORE_FILES)
|
| + res = 0;
|
| + break;
|
| + }
|
| + }
|
| + path[len] = L'\0';
|
| + FindClose(handle);
|
| + if (res == 0)
|
| + {
|
| + if (!RemoveDirectoryW(path))
|
| + res = GetLastError();
|
| + }
|
| + return res;
|
| +}
|
| +
|
| +#ifdef _CONSOLE
|
| +int MY_CDECL main()
|
| +#else
|
| +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
| + #ifdef UNDER_CE
|
| + LPWSTR
|
| + #else
|
| + LPSTR
|
| + #endif
|
| + lpCmdLine, int nCmdShow)
|
| +#endif
|
| +{
|
| + CFileInStream archiveStream;
|
| + CLookToRead lookStream;
|
| + CSzArEx db;
|
| + SRes res = SZ_OK;
|
| + ISzAlloc allocImp;
|
| + ISzAlloc allocTempImp;
|
| + WCHAR sfxPath[MAX_PATH + 2];
|
| + WCHAR path[MAX_PATH * 3 + 2];
|
| + size_t pathLen;
|
| + DWORD winRes;
|
| + const wchar_t *cmdLineParams;
|
| + const char *errorMessage = NULL;
|
| + Bool useShellExecute = True;
|
| +
|
| + #ifdef _CONSOLE
|
| + SetConsoleCtrlHandler(HandlerRoutine, TRUE);
|
| + #else
|
| + hInstance = hInstance;
|
| + hPrevInstance = hPrevInstance;
|
| + lpCmdLine = lpCmdLine;
|
| + nCmdShow = nCmdShow;
|
| + #endif
|
| +
|
| + CrcGenerateTable();
|
| +
|
| + allocImp.Alloc = SzAlloc;
|
| + allocImp.Free = SzFree;
|
| +
|
| + allocTempImp.Alloc = SzAllocTemp;
|
| + allocTempImp.Free = SzFreeTemp;
|
| +
|
| + FileInStream_CreateVTable(&archiveStream);
|
| + LookToRead_CreateVTable(&lookStream, False);
|
| +
|
| + winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH);
|
| + if (winRes == 0 || winRes > MAX_PATH)
|
| + return 1;
|
| + {
|
| + cmdLineParams = GetCommandLineW();
|
| + #ifndef UNDER_CE
|
| + {
|
| + Bool quoteMode = False;
|
| + for (;; cmdLineParams++)
|
| + {
|
| + wchar_t c = *cmdLineParams;
|
| + if (c == L'\"')
|
| + quoteMode = !quoteMode;
|
| + else if (c == 0 || (c == L' ' && !quoteMode))
|
| + break;
|
| + }
|
| + }
|
| + #endif
|
| + }
|
| +
|
| + {
|
| + unsigned i;
|
| + DWORD d;
|
| + winRes = GetTempPathW(MAX_PATH, path);
|
| + if (winRes == 0 || winRes > MAX_PATH)
|
| + return 1;
|
| + pathLen = wcslen(path);
|
| + d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();
|
| + for (i = 0;; i++, d += GetTickCount())
|
| + {
|
| + if (i >= 100)
|
| + {
|
| + res = SZ_ERROR_FAIL;
|
| + break;
|
| + }
|
| + wcscpy(path + pathLen, L"7z");
|
| +
|
| + {
|
| + wchar_t *s = path + wcslen(path);
|
| + UInt32 value = d;
|
| + unsigned k;
|
| + for (k = 0; k < 8; k++)
|
| + {
|
| + unsigned t = value & 0xF;
|
| + value >>= 4;
|
| + s[7 - k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
|
| + }
|
| + s[k] = '\0';
|
| + }
|
| +
|
| + if (DoesFileOrDirExist(path))
|
| + continue;
|
| + if (CreateDirectoryW(path, NULL))
|
| + {
|
| + wcscat(path, L"\\");
|
| + pathLen = wcslen(path);
|
| + break;
|
| + }
|
| + if (GetLastError() != ERROR_ALREADY_EXISTS)
|
| + {
|
| + res = SZ_ERROR_FAIL;
|
| + break;
|
| + }
|
| + }
|
| + if (res != SZ_OK)
|
| + errorMessage = "Can't create temp folder";
|
| + }
|
| +
|
| + if (res != SZ_OK)
|
| + {
|
| + if (!errorMessage)
|
| + errorMessage = "Error";
|
| + PrintErrorMessage(errorMessage);
|
| + return 1;
|
| + }
|
| +
|
| + if (InFile_OpenW(&archiveStream.file, sfxPath) != 0)
|
| + {
|
| + errorMessage = "can not open input file";
|
| + res = SZ_ERROR_FAIL;
|
| + }
|
| + else
|
| + {
|
| + UInt64 pos = 0;
|
| + if (!FindSignature(&archiveStream.file, &pos))
|
| + res = SZ_ERROR_FAIL;
|
| + else if (File_Seek(&archiveStream.file, (Int64 *)&pos, SZ_SEEK_SET) != 0)
|
| + res = SZ_ERROR_FAIL;
|
| + if (res != 0)
|
| + errorMessage = "Can't find 7z archive";
|
| + }
|
| +
|
| + if (res == SZ_OK)
|
| + {
|
| + lookStream.realStream = &archiveStream.s;
|
| + LookToRead_Init(&lookStream);
|
| + }
|
| +
|
| + SzArEx_Init(&db);
|
| + if (res == SZ_OK)
|
| + {
|
| + res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
|
| + }
|
| + if (res == SZ_OK)
|
| + {
|
| + UInt32 executeFileIndex = (UInt32)(Int32)-1;
|
| + UInt32 minPrice = 1 << 30;
|
| + UInt32 i;
|
| + UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
|
| + Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
|
| + size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
|
| +
|
| + for (i = 0; i < db.db.NumFiles; i++)
|
| + {
|
| + size_t offset = 0;
|
| + size_t outSizeProcessed = 0;
|
| + const CSzFileItem *f = db.db.Files + i;
|
| + size_t len;
|
| + WCHAR *temp;
|
| + len = SzArEx_GetFileNameUtf16(&db, i, NULL);
|
| +
|
| + if (len >= MAX_PATH)
|
| + {
|
| + res = SZ_ERROR_FAIL;
|
| + break;
|
| + }
|
| +
|
| + temp = path + pathLen;
|
| +
|
| + SzArEx_GetFileNameUtf16(&db, i, temp);
|
| + {
|
| + res = SzArEx_Extract(&db, &lookStream.s, i,
|
| + &blockIndex, &outBuffer, &outBufferSize,
|
| + &offset, &outSizeProcessed,
|
| + &allocImp, &allocTempImp);
|
| + if (res != SZ_OK)
|
| + break;
|
| + }
|
| + {
|
| + CSzFile outFile;
|
| + size_t processedSize;
|
| + size_t j;
|
| + size_t nameStartPos = 0;
|
| + for (j = 0; temp[j] != 0; j++)
|
| + {
|
| + if (temp[j] == '/')
|
| + {
|
| + temp[j] = 0;
|
| + MyCreateDir(path);
|
| + temp[j] = CHAR_PATH_SEPARATOR;
|
| + nameStartPos = j + 1;
|
| + }
|
| + }
|
| +
|
| + if (f->IsDir)
|
| + {
|
| + MyCreateDir(path);
|
| + continue;
|
| + }
|
| + else
|
| + {
|
| + unsigned extLen;
|
| + const WCHAR *name = temp + nameStartPos;
|
| + unsigned len = (unsigned)wcslen(name);
|
| + unsigned nameLen = FindExt(temp + nameStartPos, &extLen);
|
| + unsigned extPrice = FindItem(kExts, sizeof(kExts) / sizeof(kExts[0]), name + len - extLen, extLen);
|
| + unsigned namePrice = FindItem(kNames, sizeof(kNames) / sizeof(kNames[0]), name, nameLen);
|
| +
|
| + unsigned price = namePrice + extPrice * 64 + (nameStartPos == 0 ? 0 : (1 << 12));
|
| + if (minPrice > price)
|
| + {
|
| + minPrice = price;
|
| + executeFileIndex = i;
|
| + useShellExecute = (extPrice != k_EXE_ExtIndex);
|
| + }
|
| +
|
| + if (DoesFileOrDirExist(path))
|
| + {
|
| + errorMessage = "Duplicate file";
|
| + res = SZ_ERROR_FAIL;
|
| + break;
|
| + }
|
| + if (OutFile_OpenW(&outFile, path))
|
| + {
|
| + errorMessage = "Can't open output file";
|
| + res = SZ_ERROR_FAIL;
|
| + break;
|
| + }
|
| + }
|
| + processedSize = outSizeProcessed;
|
| + if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)
|
| + {
|
| + errorMessage = "Can't write output file";
|
| + res = SZ_ERROR_FAIL;
|
| + }
|
| +
|
| + #ifdef USE_WINDOWS_FILE
|
| + if (f->MTimeDefined)
|
| + {
|
| + FILETIME mTime;
|
| + mTime.dwLowDateTime = f->MTime.Low;
|
| + mTime.dwHighDateTime = f->MTime.High;
|
| + SetFileTime(outFile.handle, NULL, NULL, &mTime);
|
| + }
|
| + #endif
|
| +
|
| + {
|
| + SRes res2 = File_Close(&outFile);
|
| + if (res != SZ_OK)
|
| + break;
|
| + if (res2 != SZ_OK)
|
| + {
|
| + res = res2;
|
| + break;
|
| + }
|
| + }
|
| + #ifdef USE_WINDOWS_FILE
|
| + if (f->AttribDefined)
|
| + SetFileAttributesW(path, f->Attrib);
|
| + #endif
|
| + }
|
| + }
|
| +
|
| + if (res == SZ_OK)
|
| + {
|
| + if (executeFileIndex == (UInt32)(Int32)-1)
|
| + {
|
| + errorMessage = "There is no file to execute";
|
| + res = SZ_ERROR_FAIL;
|
| + }
|
| + else
|
| + {
|
| + WCHAR *temp = path + pathLen;
|
| + UInt32 j;
|
| + SzArEx_GetFileNameUtf16(&db, executeFileIndex, temp);
|
| + for (j = 0; temp[j] != 0; j++)
|
| + if (temp[j] == '/')
|
| + temp[j] = CHAR_PATH_SEPARATOR;
|
| + }
|
| + }
|
| + IAlloc_Free(&allocImp, outBuffer);
|
| + }
|
| + SzArEx_Free(&db, &allocImp);
|
| +
|
| + File_Close(&archiveStream.file);
|
| +
|
| + if (res == SZ_OK)
|
| + {
|
| + HANDLE hProcess = 0;
|
| + if (useShellExecute)
|
| + {
|
| + SHELLEXECUTEINFO ei;
|
| + UINT32 executeRes;
|
| + BOOL success;
|
| +
|
| + memset(&ei, 0, sizeof(ei));
|
| + ei.cbSize = sizeof(ei);
|
| + ei.lpFile = path;
|
| + ei.fMask = SEE_MASK_NOCLOSEPROCESS
|
| + #ifndef UNDER_CE
|
| + | SEE_MASK_FLAG_DDEWAIT
|
| + #endif
|
| + /* | SEE_MASK_NO_CONSOLE */
|
| + ;
|
| + if (wcslen(cmdLineParams) != 0)
|
| + ei.lpParameters = cmdLineParams;
|
| + ei.nShow = SW_SHOWNORMAL; /* SW_HIDE; */
|
| + success = ShellExecuteEx(&ei);
|
| + executeRes = (UINT32)(UINT_PTR)ei.hInstApp;
|
| + if (!success || (executeRes <= 32 && executeRes != 0)) /* executeRes = 0 in Windows CE */
|
| + res = SZ_ERROR_FAIL;
|
| + else
|
| + hProcess = ei.hProcess;
|
| + }
|
| + else
|
| + {
|
| + STARTUPINFOW si;
|
| + PROCESS_INFORMATION pi;
|
| + WCHAR cmdLine[MAX_PATH * 3];
|
| +
|
| + wcscpy(cmdLine, path);
|
| + wcscat(cmdLine, cmdLineParams);
|
| + memset(&si, 0, sizeof(si));
|
| + si.cb = sizeof(si);
|
| + if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == 0)
|
| + res = SZ_ERROR_FAIL;
|
| + else
|
| + {
|
| + CloseHandle(pi.hThread);
|
| + hProcess = pi.hProcess;
|
| + }
|
| + }
|
| + if (hProcess != 0)
|
| + {
|
| + WaitForSingleObject(hProcess, INFINITE);
|
| + CloseHandle(hProcess);
|
| + }
|
| + }
|
| +
|
| + path[pathLen] = L'\0';
|
| + RemoveDirWithSubItems(path);
|
| +
|
| + if (res == SZ_OK)
|
| + return 0;
|
| +
|
| + {
|
| + if (res == SZ_ERROR_UNSUPPORTED)
|
| + errorMessage = "Decoder doesn't support this archive";
|
| + else if (res == SZ_ERROR_MEM)
|
| + errorMessage = "Can't allocate required memory";
|
| + else if (res == SZ_ERROR_CRC)
|
| + errorMessage = "CRC error";
|
| + else
|
| + {
|
| + if (!errorMessage)
|
| + errorMessage = "ERROR";
|
| + }
|
| + if (errorMessage)
|
| + PrintErrorMessage(errorMessage);
|
| + }
|
| + return 1;
|
| +}
|
|
|
| Property changes on: third_party\lzma_sdk\C\Util\SfxSetup\SfxSetup.c
|
| ___________________________________________________________________
|
| Added: svn:executable
|
| + *
|
|
|
|
|