Skip to content

Commit 04994a6

Browse files
committed
Implemented issue #6 - Implement Windows support using resource file and Windows API for getting resources
1 parent 051ed96 commit 04994a6

11 files changed

+286
-2
lines changed

CHANGES

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
Changes for 2.0:
1+
Changes for 2.1.0:
2+
3+
* New feature (issue #6): Implement Windows support using resource file and Windows API for getting resources.
4+
5+
Changes for 2.0.0:
26

37
* New feature (issue #2): Update command line parameters syntax with the --name=value syntax
48
* New feature: Command line --noheader to not display the application header in the console output.

msvc/bin2cpp.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
<ClCompile Include="..\src\main.cpp" />
9494
<ClCompile Include="..\src\SegmentGenerator.cpp" />
9595
<ClCompile Include="..\src\StringGenerator.cpp" />
96+
<ClCompile Include="..\src\Win32ResourceGenerator.cpp" />
9697
</ItemGroup>
9798
<ItemGroup>
9899
<ClInclude Include="..\src\ArrayGenerator.h" />
@@ -101,6 +102,7 @@
101102
<ClInclude Include="..\src\SegmentGenerator.h" />
102103
<ClInclude Include="..\src\StringGenerator.h" />
103104
<ClInclude Include="..\src\targetver.h" />
105+
<ClInclude Include="..\src\Win32ResourceGenerator.h" />
104106
</ItemGroup>
105107
<ItemGroup>
106108
<ProjectReference Include="common.vcxproj">

msvc/bin2cpp.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
<ClCompile Include="..\src\BaseGenerator.cpp">
3131
<Filter>Source Files</Filter>
3232
</ClCompile>
33+
<ClCompile Include="..\src\Win32ResourceGenerator.cpp">
34+
<Filter>Source Files</Filter>
35+
</ClCompile>
3336
</ItemGroup>
3437
<ItemGroup>
3538
<ClInclude Include="..\src\targetver.h">
@@ -50,5 +53,8 @@
5053
<ClInclude Include="..\src\BaseGenerator.h">
5154
<Filter>Header Files</Filter>
5255
</ClInclude>
56+
<ClInclude Include="..\src\Win32ResourceGenerator.h">
57+
<Filter>Header Files</Filter>
58+
</ClInclude>
5359
</ItemGroup>
5460
</Project>

msvc/bin2cpp_unittest.vcxproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
<ClCompile Include="generated_files\testGeneratorArray10000\_testGeneratorArray10000.cpp" />
116116
<ClCompile Include="generated_files\testGeneratorSegment10000\_testGeneratorSegment10000.cpp" />
117117
<ClCompile Include="generated_files\testGeneratorString10000\_testGeneratorString10000.cpp" />
118+
<ClCompile Include="generated_files\testGeneratorWin32\_testGeneratorWin32.cpp" />
118119
<ClCompile Include="generated_files\testHtml100000\_testHtml100000.cpp" />
119120
<ClCompile Include="generated_files\testIssue12Mini\_testIssue12Mini.cpp" />
120121
<ClCompile Include="generated_files\testIssue12\_testIssue12.cpp" />
@@ -160,6 +161,7 @@
160161
<ClInclude Include="generated_files\testGeneratorArray10000\_testGeneratorArray10000.h" />
161162
<ClInclude Include="generated_files\testGeneratorSegment10000\_testGeneratorSegment10000.h" />
162163
<ClInclude Include="generated_files\testGeneratorString10000\_testGeneratorString10000.h" />
164+
<ClInclude Include="generated_files\testGeneratorWin32\_testGeneratorWin32.h" />
163165
<ClInclude Include="generated_files\testHtml100000\_testHtml100000.h" />
164166
<ClInclude Include="generated_files\testIssue12Mini\_testIssue12Mini.h" />
165167
<ClInclude Include="generated_files\testIssue12\_testIssue12.h" />
@@ -190,6 +192,9 @@
190192
<Project>{f78fce3c-6b97-4bfb-9f8f-e46e36431cfd}</Project>
191193
</ProjectReference>
192194
</ItemGroup>
195+
<ItemGroup>
196+
<ResourceCompile Include="generated_files\testGeneratorWin32\_testGeneratorWin32.rc" />
197+
</ItemGroup>
193198
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
194199
<ImportGroup Label="ExtensionTargets">
195200
</ImportGroup>

msvc/bin2cpp_unittest.vcxproj.filters

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@
114114
<ClCompile Include="generated_files\testEncodingOct\_testEncodingOct.cpp">
115115
<Filter>Generated Files</Filter>
116116
</ClCompile>
117+
<ClCompile Include="generated_files\testGeneratorWin32\_testGeneratorWin32.cpp">
118+
<Filter>Generated Files</Filter>
119+
</ClCompile>
117120
</ItemGroup>
118121
<ItemGroup>
119122
<None Include="bin2cppTest.x86.debug.xml">
@@ -212,8 +215,16 @@
212215
<ClInclude Include="generated_files\testEncodingOct\_testEncodingOct.h">
213216
<Filter>Generated Files</Filter>
214217
</ClInclude>
218+
<ClInclude Include="generated_files\testGeneratorWin32\_testGeneratorWin32.h">
219+
<Filter>Generated Files</Filter>
220+
</ClInclude>
215221
</ItemGroup>
216222
<ItemGroup>
217223
<CustomBuild Include="generate_test_files.bat" />
218224
</ItemGroup>
225+
<ItemGroup>
226+
<ResourceCompile Include="generated_files\testGeneratorWin32\_testGeneratorWin32.rc">
227+
<Filter>Generated Files</Filter>
228+
</ResourceCompile>
229+
</ItemGroup>
219230
</Project>

msvc/generate_test_files.bat

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ mkdir %OUTDIR% 1>NUL 2>NUL
114114
testfilegenerator.exe --file=%OUTDIR%\%TEST_NAME%.bin --size=10000 --fill=sequential
115115
bin2cpp.exe --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=segment --override
116116

117+
set TEST_NAME=testGeneratorWin32
118+
set OUTDIR=.\generated_files\%TEST_NAME%
119+
mkdir %OUTDIR% 1>NUL 2>NUL
120+
testfilegenerator.exe --file=%OUTDIR%\%TEST_NAME%.bin --size=10000 --fill=sequential
121+
bin2cpp.exe --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=win32 --override
122+
117123
set TEST_NAME=testNamespace
118124
set OUTDIR=.\generated_files\%TEST_NAME%
119125
mkdir %OUTDIR% 1>NUL 2>NUL

src/Win32ResourceGenerator.cpp

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
#include "Win32ResourceGenerator.h"
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <string>
5+
#include <stdlib.h>
6+
7+
#include "common.h"
8+
#include "cppencoder.h"
9+
#include "stringfunc.h"
10+
#include "filesystemfunc.h"
11+
12+
using namespace stringfunc;
13+
using namespace filesystem;
14+
15+
namespace bin2cpp
16+
{
17+
Win32ResourceGenerator::Win32ResourceGenerator()
18+
{
19+
}
20+
21+
Win32ResourceGenerator::~Win32ResourceGenerator()
22+
{
23+
}
24+
25+
const char * Win32ResourceGenerator::getName() const
26+
{
27+
return "win32";
28+
}
29+
30+
bool Win32ResourceGenerator::createCppSourceFile(const char * iCppFilePath)
31+
{
32+
bool resourceFileSuccess = createResourceFile(iCppFilePath);
33+
if (!resourceFileSuccess)
34+
return false;
35+
36+
//check if input file exists
37+
FILE * input = fopen(mInputFile.c_str(), "rb");
38+
if (!input)
39+
return false;
40+
41+
//Uppercase function identifier
42+
std::string functionIdentifier = capitalizeFirstCharacter(mFunctionIdentifier);
43+
44+
//Build header and cpp file path
45+
std::string headerPath = getHeaderFilePath(iCppFilePath);
46+
std::string cppPath = iCppFilePath;
47+
std::string headerFilename = getFilename(headerPath.c_str());
48+
std::string cppFilename = getFilename(iCppFilePath);
49+
50+
//create cpp file
51+
FILE * cpp = fopen(cppPath.c_str(), "w");
52+
if (!cpp)
53+
{
54+
fclose(input);
55+
return false;
56+
}
57+
58+
//determine file properties
59+
//long fileSize = getFileSize(input);
60+
std::string filename = getFilename(mInputFile.c_str());
61+
62+
//Build class name
63+
std::string className;
64+
className.append(functionIdentifier.c_str());
65+
className.append("File");
66+
67+
//Build function
68+
std::string getterFunctionName = getGetterFunctionName();
69+
70+
//write cpp file heading
71+
fprintf(cpp, "%s", getHeaderTemplate().c_str());
72+
fprintf(cpp, "#include \"%s\"\n", headerFilename.c_str() );
73+
fprintf(cpp, "#include <stdio.h> //for FILE\n");
74+
fprintf(cpp, "#include <stdint.h>\n");
75+
fprintf(cpp, "\n");
76+
fprintf(cpp, "#ifndef WIN32_LEAN_AND_MEAN\n");
77+
fprintf(cpp, "#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers\n");
78+
fprintf(cpp, "#endif\n");
79+
fprintf(cpp, "#include <windows.h>\n");
80+
fprintf(cpp, "\n");
81+
fprintf(cpp, "#include <psapi.h> //for EnumProcessModules()\n");
82+
fprintf(cpp, "#pragma comment( lib, \"psapi.lib\" )\n");
83+
fprintf(cpp, "\n");
84+
85+
fprintf(cpp, "namespace %s\n", mNamespace.c_str());
86+
fprintf(cpp, "{\n");
87+
fprintf(cpp, " class %s : public virtual %s::%s\n", className.c_str(), mNamespace.c_str(), mBaseClass.c_str());
88+
fprintf(cpp, " {\n");
89+
fprintf(cpp, " public:\n");
90+
fprintf(cpp, " %s() :\n", className.c_str());
91+
fprintf(cpp, " hProcess(NULL),\n");
92+
fprintf(cpp, " hModule(NULL),\n");
93+
fprintf(cpp, " hResourceInfoBlock(NULL),\n");
94+
fprintf(cpp, " hResHandle(NULL),\n");
95+
fprintf(cpp, " mBufferSize(0),\n");
96+
fprintf(cpp, " mBuffer(NULL)\n");
97+
fprintf(cpp, " {\n");
98+
fprintf(cpp, " loadResource();\n");
99+
fprintf(cpp, " }\n");
100+
fprintf(cpp, " ~%s() { unloadResource(); }\n", className.c_str());
101+
fprintf(cpp, " virtual size_t getSize() const { return mBufferSize; }\n");
102+
fprintf(cpp, " virtual const char * getFilename() const { return \"%s\"; }\n", getFilename(mInputFile.c_str()).c_str());
103+
fprintf(cpp, " virtual const char * getBuffer() const { return mBuffer; }\n");
104+
fprintf(cpp, " void loadResource()\n");
105+
fprintf(cpp, " {\n");
106+
fprintf(cpp, " //Get a handle to this process\n");
107+
fprintf(cpp, " hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId() );\n");
108+
fprintf(cpp, " if (hProcess)\n");
109+
fprintf(cpp, " {\n");
110+
fprintf(cpp, " //Find the main HMODULE of the process\n");
111+
fprintf(cpp, " DWORD cbNeeded;\n");
112+
fprintf(cpp, " if ( EnumProcessModules( hProcess, &hModule, sizeof(hModule), &cbNeeded) )\n");
113+
fprintf(cpp, " {\n");
114+
fprintf(cpp, " //Retrieve the resource\n");
115+
fprintf(cpp, " hResourceInfoBlock = FindResource(hModule, \"%s\", \"CUSTOM\");\n", getRandomIdentifier(iCppFilePath).c_str());
116+
fprintf(cpp, " if (hResourceInfoBlock)\n");
117+
fprintf(cpp, " {\n");
118+
fprintf(cpp, " hResHandle = LoadResource(hModule, hResourceInfoBlock);\n");
119+
fprintf(cpp, " if (hResHandle)\n");
120+
fprintf(cpp, " {\n");
121+
fprintf(cpp, " mBuffer = (const char *)LockResource(hResHandle);\n");
122+
fprintf(cpp, " mBufferSize = SizeofResource(hModule, hResourceInfoBlock);\n");
123+
fprintf(cpp, " }\n");
124+
fprintf(cpp, " }\n");
125+
fprintf(cpp, " }\n");
126+
fprintf(cpp, " }\n");
127+
fprintf(cpp, " }\n");
128+
fprintf(cpp, " virtual void unloadResource()\n");
129+
fprintf(cpp, " {\n");
130+
fprintf(cpp, " if (hResHandle)\n");
131+
fprintf(cpp, " {\n");
132+
fprintf(cpp, " FreeResource(hResHandle);\n");
133+
fprintf(cpp, " hResHandle = NULL;\n");
134+
fprintf(cpp, " mBuffer = NULL;\n");
135+
fprintf(cpp, " mBufferSize = 0;\n");
136+
fprintf(cpp, " }\n");
137+
fprintf(cpp, " hResourceInfoBlock = NULL;\n");
138+
fprintf(cpp, " hModule = NULL;\n");
139+
fprintf(cpp, " if (hProcess)\n");
140+
fprintf(cpp, " {\n");
141+
fprintf(cpp, " CloseHandle(hProcess);\n");
142+
fprintf(cpp, " hProcess = NULL;\n");
143+
fprintf(cpp, " }\n");
144+
fprintf(cpp, " }\n");
145+
fprintf(cpp, "%s", getSaveMethodTemplate().c_str());
146+
fprintf(cpp, " private:\n");
147+
fprintf(cpp, " HANDLE hProcess;\n");
148+
fprintf(cpp, " HMODULE hModule;\n");
149+
fprintf(cpp, " HRSRC hResourceInfoBlock;\n");
150+
fprintf(cpp, " HGLOBAL hResHandle;\n");
151+
fprintf(cpp, " DWORD mBufferSize;\n");
152+
fprintf(cpp, " const char * mBuffer;\n");
153+
fprintf(cpp, " };\n");
154+
fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", mBaseClass.c_str(), getterFunctionName.c_str(), className.c_str());
155+
fprintf(cpp, "}; //%s\n", mNamespace.c_str());
156+
157+
fclose(input);
158+
fclose(cpp);
159+
160+
return true;
161+
}
162+
163+
std::string Win32ResourceGenerator::getResourceFilePath(const char * iCppFilePath)
164+
{
165+
//Build header file path
166+
std::string resourcePath = iCppFilePath;
167+
strReplace(resourcePath, ".cpp", ".rc");
168+
return resourcePath;
169+
}
170+
171+
bool Win32ResourceGenerator::createResourceFile(const char * iCppFilePath)
172+
{
173+
//Build resource file path
174+
std::string resourceFilePath = getResourceFilePath(iCppFilePath);
175+
176+
//create resource file
177+
FILE * res = fopen(resourceFilePath.c_str(), "w");
178+
if (!res)
179+
{
180+
return false;
181+
}
182+
183+
std::string filePath = mInputFile;
184+
strReplace(filePath, "\\", "\\\\");
185+
186+
//write res file heading
187+
fprintf(res, "%s", getHeaderTemplate().c_str());
188+
fprintf(res, "#include <windows.h>\n");
189+
fprintf(res, "%s CUSTOM \"%s\"\n", getRandomIdentifier(iCppFilePath).c_str(), filePath.c_str());
190+
191+
fclose(res);
192+
193+
return true;
194+
}
195+
196+
std::string Win32ResourceGenerator::getRandomIdentifier(const char * /*iCppFilePath*/)
197+
{
198+
return "html5skeletonAGE632H2D7";
199+
}
200+
201+
}; //bin2cpp

src/Win32ResourceGenerator.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include "BaseGenerator.h"
4+
5+
namespace bin2cpp
6+
{
7+
8+
///<summary>
9+
///This generator stores data in a single string of a maximum of 65535 bytes.
10+
///</summary>
11+
class Win32ResourceGenerator : public BaseGenerator
12+
{
13+
public:
14+
Win32ResourceGenerator();
15+
virtual ~Win32ResourceGenerator();
16+
virtual const char * getName() const;
17+
virtual bool createCppSourceFile(const char * iCppFilePath);
18+
protected:
19+
virtual std::string getResourceFilePath(const char * iCppFilePath);
20+
virtual bool createResourceFile(const char * iCppFilePath);
21+
virtual std::string getRandomIdentifier(const char * iCppFilePath);
22+
};
23+
24+
}; //bin2cpp

src/main.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "SegmentGenerator.h"
77
#include "StringGenerator.h"
88
#include "ArrayGenerator.h"
9+
#include "Win32ResourceGenerator.h"
910

1011
#include <stdlib.h>
1112
#include <stdio.h>
@@ -100,7 +101,7 @@ void printUsage()
100101
" --file=<path> Path of the input file used for embedding as a C++ source code.\n"
101102
" --output=<path> Output folder where to create generated code. ie: .\\generated_files\n"
102103
" --headerfile=<name> File name of the generated C++ Header file. ie: SplashScreen.h\n"
103-
" --generator=<name> Name of the generator to use. Possible values are 'segment', 'string' and 'array'. [default: segment].\n"
104+
" --generator=<name> Name of the generator to use. Possible values are 'segment', 'string', 'array' and 'win32'. [default: segment].\n"
104105
" --encoding=<name> Name of the binary to string literal encoding to use. Possible values are 'oct' and 'hex'. [default: oct].\n"
105106
" --identifier=<name> Identifier of the function name that is used to get an instance of the file. ie: SplashScreen\n"
106107
" --chunksize=<value> Size in bytes of each string segments (bytes per row). [default: 200].\n"
@@ -249,6 +250,7 @@ int main(int argc, char* argv[])
249250
bin2cpp::SegmentGenerator segmentGenerator;
250251
bin2cpp::StringGenerator stringGenerator;
251252
bin2cpp::ArrayGenerator arrayGenerator;
253+
bin2cpp::Win32ResourceGenerator win32Generator;
252254
bin2cpp::IGenerator * generator = NULL;
253255

254256
std::string generatorName;
@@ -266,6 +268,10 @@ int main(int argc, char* argv[])
266268
{
267269
generator = &arrayGenerator;
268270
}
271+
else if (generatorName == "win32")
272+
{
273+
generator = &win32Generator;
274+
}
269275

270276
//validate generator selection
271277
if (generator == NULL)

test/TestCLI.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,13 +321,16 @@ TEST_F(TestCLI, testGenerators)
321321
generators.push_back("segment");
322322
generators.push_back("string");
323323
generators.push_back("array");
324+
generators.push_back("win32");
324325

325326
//generate cpp output for each generators
326327
std::vector<std::string> files;
327328
for(size_t genIndex = 0; genIndex<generators.size(); genIndex++)
328329
{
329330
const char * generatorName = generators[genIndex].c_str();
330331

332+
printf("Testing '%s' generator...\n", generatorName);
333+
331334
std::string headerFileName = std::string("_") + hlp.getTestCaseName().c_str() + "." + generatorName + ".h";
332335
std::string headerFilePath = std::string("generated_files\\") + headerFileName;
333336
std::string cppFilePath = headerFilePath; stringfunc::strReplace(cppFilePath, ".h", ".cpp");

0 commit comments

Comments
 (0)