/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. There is NO WARRANTY for this software. See license.txt for details. */ #include #include #include #include #include #include #include "embed.h" #ifdef __x86_64__ # define BINARY_LOADER(x) _binary_loader_##x #else # define BINARY_LOADER(x) binary_loader_##x #endif extern "C" const uint8_t BINARY_LOADER(start)[]; extern "C" const uint8_t BINARY_LOADER(end)[]; __declspec(noreturn) void printUsage(const wchar_t* executableName) { wprintf(L"Usage: %s destination.exe classes.jar package.Main\n", executableName); exit(0); } void writeDestinationFile(const wchar_t* filename) { if(FILE* file = _wfopen(filename, L"wb")) { size_t count = BINARY_LOADER(end) - BINARY_LOADER(start); if(count == fwrite(BINARY_LOADER(start), sizeof(BINARY_LOADER(start)[0]), count, file)) { fclose(file); return; } } fprintf(stderr, "Unable to write to destination file\n"); exit(EXIT_FAILURE); } void readFile(std::vector* jarFile, const wchar_t* fileName) { if(FILE* file = _wfopen(fileName, L"rb")) { fseek(file, 0, SEEK_END); jarFile->resize(ftell(file)); fseek(file, 0, SEEK_SET); fread(&jarFile->at(0), 1, jarFile->size(), file); fclose(file); } } bool mkStringSection(std::vector* stringSection, const std::vector& strings, int first, int last) { stringSection->clear(); for(int i = first; i <= last; ++i) { const std::wstring& s = strings.at(i); stringSection->push_back(s.size()); stringSection->insert(stringSection->end(), s.begin(), s.end()); } // pad to 16 entries for(int i = last - first; i < 15; ++i) stringSection->push_back(0); return stringSection->size() > 16; } void writeStringResources(HANDLE hDest, const std::vector& strings) { for(unsigned i = 0; i < strings.size(); i += 16) { std::vector stringSection; if(mkStringSection(&stringSection, strings, i, std::min(i + 15, strings.size() - 1))) UpdateResourceW(hDest, reinterpret_cast(RT_STRING), reinterpret_cast(MAKEINTRESOURCE((i >> 4) + 1)), LANG_NEUTRAL, &stringSection.at(0), sizeof(wchar_t) * stringSection.size()); } } int wmain(int argc, wchar_t* argv[]) { if(argc != 4) printUsage(argv[0]); const wchar_t* destinationName = argv[1]; const wchar_t* classesName = argv[2]; const wchar_t* mainClassName = argv[3]; writeDestinationFile(destinationName); if(HANDLE hDest = BeginUpdateResourceW(destinationName, TRUE)) { std::vector strings; strings.resize(RESID_MAIN_CLASS + 1); strings.at(RESID_MAIN_CLASS) = mainClassName; writeStringResources(hDest, strings); std::vector jarFile; readFile(&jarFile, classesName); UpdateResourceW(hDest, reinterpret_cast(RT_RCDATA), RESID_BOOT_JAR, LANG_NEUTRAL, &jarFile.at(0), jarFile.size()); EndUpdateResource(hDest, FALSE); } return 0; } #ifndef _MSC_VER extern "C" int _CRT_glob; extern "C" void __wgetmainargs(int*, wchar_t***, wchar_t***, int, int*); int main() { wchar_t **enpv, **argv; int argc, si = 0; __wgetmainargs(&argc, &argv, &enpv, _CRT_glob, &si); return wmain(argc, argv); } #endif