rainmeter-studio/Installer/Install.cpp

148 lines
3.5 KiB
C++

/*
Copyright (C) 2013 Birunthan Mohanathas
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "Install.h"
#include "Resource.h"
extern "C" {
#include "lzma/Alloc.h"
#include "lzma/7zFile.h"
#include "lzma/7zVersion.h"
#include "lzma/LzmaDec.h"
#include "lzma/7zCrc.h"
#include "lzma/7z.h"
#include "lzma/7zMemInStream.h"
#include "lzma/7zAlloc.h"
} // extern "C"
void ExtractPayload(const void* payload, size_t payloadSize, const WCHAR* prefix)
{
CMemInStream memStream;
MemInStream_Init(&memStream, payload, payloadSize);
CrcGenerateTable();
ISzAlloc alloc = { SzAlloc, SzFree };
CSzArEx db;
SzArEx_Init(&db);
SRes res = SzArEx_Open(&db, &memStream.s, &alloc, &alloc);
if (res != SZ_OK)
{
SzArEx_Free(&db, &alloc);
return;
}
WCHAR buffer[MAX_PATH];
UInt32 blockIndex = 0xFFFFFFFF;
Byte* outBuffer = 0;
size_t outBufferSize = 0;
for (UInt32 i = 0; i < db.db.NumFiles; i++)
{
size_t offset = 0;
size_t outSizeProcessed = 0;
const CSzFileItem* f = db.db.Files + i;
SzArEx_GetFileNameUtf16(&db, i, (UInt16*)buffer);
WCHAR* destPath = buffer;
if (wcsncmp(destPath, prefix, 3) == 0 ||
wcsncmp(destPath, L"ALL", 3) == 0)
{
// Skip the prefix (X64/X32/ALL) and the path separater.
destPath += 4;
}
else
{
// This file isn't for this arch.
continue;
}
if (!f->IsDir)
{
res = SzArEx_Extract(
&db, &memStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset,
&outSizeProcessed, &alloc, &alloc);
if (res != SZ_OK)
{
break;
}
}
for (size_t j = 0; destPath[j] != L'\0'; ++j)
{
if (destPath[j] == L'/')
{
destPath[j] = L'\0';
CreateDirectory(destPath, NULL);
destPath[j] = CHAR_PATH_SEPARATOR;
}
}
if (f->IsDir)
{
CreateDirectory(destPath, NULL);
continue;
}
CSzFile outFile;
if (OutFile_OpenW(&outFile, destPath))
{
res = SZ_ERROR_FAIL;
break;
}
size_t processedSize = outSizeProcessed;
if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 ||
processedSize != outSizeProcessed)
{
res = SZ_ERROR_FAIL;
break;
}
if (File_Close(&outFile))
{
res = SZ_ERROR_FAIL;
break;
}
if (f->AttribDefined) SetFileAttributesW(destPath, f->Attrib);
}
IAlloc_Free(&alloc, outBuffer);
SzArEx_Free(&db, &alloc);
if (res == SZ_OK)
{
// Success.
}
}
void DoInstall(InstallOptions& options)
{
#ifdef INSTALLER_INCLUDE_PAYLOAD
const auto module = GetModuleHandle(nullptr);
HRSRC payload = FindResource(
module, MAKEINTRESOURCE(IDR_PAYLOAD), MAKEINTRESOURCE(PAYLOAD_RESOURCE_TYPEID));
const size_t payloadSize = SizeofResource(module, payload);
const void* payloadData = LockResource(LoadResource(module, payload));
SetCurrentDirectory(options.targetPath);
ExtractPayload(
payloadData, payloadSize, options.arch == InstallArch::X32 ? L"X32" : L"X64");
#endif
}