Skip to content

Commit 24d30c5

Browse files
committed
Progress on launcher
1 parent 43f8357 commit 24d30c5

19 files changed

+970
-176
lines changed

GWToolbox/Download.cpp

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
#ifndef WIN32_LEAN_AND_MEAN
2+
# define WIN32_LEAN_AND_MEAN
3+
#endif
4+
#ifdef NOMINMAX
5+
# define NOMINMAX
6+
#endif
7+
#include <Windows.h>
8+
#include <WinInet.h>
9+
#include <urlmon.h>
10+
11+
#include <stdio.h>
12+
#include <vector>
13+
14+
#include <json.hpp>
15+
using Json = nlohmann::json;
16+
17+
#include "Download.h"
18+
#include "Path.h"
19+
20+
bool Download(std::string& content, const wchar_t *url)
21+
{
22+
DeleteUrlCacheEntryW(url);
23+
24+
IStream* stream;
25+
HRESULT result = URLOpenBlockingStreamW(NULL, url, &stream, 0, NULL);
26+
27+
if (FAILED(result)) {
28+
fprintf(stderr, "URLOpenBlockingStreamW failed (HRESULT: 0x%X)\n", result);
29+
return false;
30+
}
31+
32+
STATSTG stats;
33+
result = stream->Stat(&stats, STATFLAG_NONAME);
34+
if (FAILED(result)) {
35+
fprintf(stderr, "IStream::Stat failed (HRESULT: 0x%X)\n", result);
36+
stream->Release();
37+
return false;
38+
}
39+
40+
if (stats.cbSize.HighPart != 0) {
41+
fprintf(stderr, "This file is way to big to download, it's over 4GB\n");
42+
stream->Release();
43+
return false;
44+
}
45+
46+
content.resize(stats.cbSize.LowPart);
47+
result = stream->Read(&content[0], stats.cbSize.LowPart, NULL);
48+
stream->Release();
49+
50+
if (FAILED(result)) {
51+
fprintf(stderr, "IStream::Read failed (HRESULT: 0x%X, Url: '%ls')\n", result, url);
52+
return false;
53+
}
54+
55+
return true;
56+
}
57+
58+
bool Download(const wchar_t *path_to_file, const wchar_t *url)
59+
{
60+
DeleteUrlCacheEntryW(url);
61+
62+
HRESULT result = URLDownloadToFileW(
63+
NULL,
64+
url,
65+
path_to_file,
66+
0,
67+
NULL);
68+
69+
if (FAILED(result)) {
70+
fprintf(stderr, "URLDownloadToFileW failed: hresult:0x%X\n", result);
71+
return false;
72+
}
73+
74+
return true;
75+
}
76+
77+
struct Asset
78+
{
79+
std::string name;
80+
size_t size;
81+
std::string browser_download_url;
82+
};
83+
84+
struct Release
85+
{
86+
std::string tag_name;
87+
std::string body;
88+
std::vector<Asset> assets;
89+
};
90+
91+
static bool ParseRelease(std::string& json_text, Release *release)
92+
{
93+
Json json;
94+
try {
95+
json = Json::parse(json_text.c_str());
96+
} catch(...) {
97+
fprintf(stderr, "Json::parse failed\n");
98+
return false;
99+
}
100+
101+
auto it_tag_name = json.find("tag_name");
102+
if (it_tag_name == json.end() || !it_tag_name->is_string()) {
103+
fprintf(stderr, "Key 'tag_name' not found or not a string in '%s'\n", json_text.c_str());
104+
return false;
105+
}
106+
107+
auto it_body = json.find("body");
108+
if (it_body == json.end() || !it_body->is_string()) {
109+
fprintf(stderr, "Key 'body' not found or not a string in '%s'\n", json_text.c_str());
110+
return false;
111+
}
112+
113+
auto it_assets = json.find("assets");
114+
if (it_assets == json.end() || !it_assets->is_array()) {
115+
fprintf(stderr, "Key 'assets' not found or not an array in '%s'\n", json_text.c_str());
116+
return false;
117+
}
118+
119+
release->tag_name = *it_tag_name;
120+
release->body = *it_body;
121+
122+
for (size_t i = 0; i < it_assets->size(); i++) {
123+
Json& entry = it_assets->at(i);
124+
125+
auto it_name = entry.find("name");
126+
if (it_name == entry.end() || !it_name->is_string()) {
127+
fprintf(stderr, "Key 'name' not found or not a string in (assert:%zu) '%s'\n",
128+
i, json_text.c_str());
129+
return false;
130+
}
131+
132+
auto it_size = entry.find("size");
133+
if (it_size == entry.end() || !it_size->is_number()) {
134+
fprintf(stderr, "Key 'size' not found or not a number in (assert:%zu) '%s'\n",
135+
i, json_text.c_str());
136+
return false;
137+
}
138+
139+
auto it_browser_download_url = entry.find("browser_download_url");
140+
if (it_browser_download_url == entry.end() || !it_browser_download_url->is_string()) {
141+
fprintf(stderr, "Key 'browser_download_url' not found or not a string in (assert:%zu) '%s'\n",
142+
i, json_text.c_str());
143+
return false;
144+
}
145+
146+
Asset asset;
147+
asset.name = *it_name;
148+
asset.size = *it_size;
149+
asset.browser_download_url = *it_browser_download_url;
150+
151+
release->assets.emplace_back(std::move(asset));
152+
}
153+
154+
return true;
155+
}
156+
157+
bool DownloadFiles()
158+
{
159+
std::string content;
160+
if (!Download(content, L"https://api.github.com/repos/HasKha/GWToolboxpp/releases/latest")) {
161+
fprintf(stderr, "Couldn't download the latest release of GWToolboxpp\n");
162+
return false;
163+
}
164+
165+
Release release;
166+
if (!ParseRelease(content, &release)) {
167+
fprintf(stderr, "ParseRelease failed\n");
168+
return false;
169+
}
170+
171+
wchar_t dll_path[MAX_PATH];
172+
PathGetAppDataPath(dll_path, MAX_PATH, L"GWToolboxpp\\GWToolboxdll.dll");
173+
174+
char buffer[64];
175+
snprintf(buffer, 64, "Downloading version '%s'", release.tag_name.c_str());
176+
MessageBoxA(0, buffer, "Downloading...", 0);
177+
for (size_t i = 0; i < release.assets.size(); i++) {
178+
Asset *asset = &release.assets[i];
179+
if (asset->name == "GWToolbox.dll") {
180+
fprintf(stderr, "browser_download_url: '%s'\n", asset->browser_download_url.c_str());
181+
const char *purl = asset->browser_download_url.c_str();
182+
// @Cleanup: Utf8 -> Unicode (WCHAR)
183+
std::wstring url(purl, purl + asset->browser_download_url.size());
184+
if (!Download(dll_path, url.c_str())) {
185+
fprintf(stderr, "Download failed: path_to_file = '%ls', url = '%ls'\n",
186+
dll_path, url.c_str());
187+
return false;
188+
}
189+
}
190+
}
191+
192+
return true;
193+
}

GWToolbox/Download.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#pragma once
2+
3+
#include <string>
4+
5+
bool Download(std::string& content, const wchar_t *url);
6+
bool Download(const wchar_t *path_to_file, const wchar_t *url);
7+
8+
bool DownloadFiles();

GWToolbox/GWTBLauncher.vcxproj

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,11 @@
5252
<Optimization>Disabled</Optimization>
5353
<SDLCheck>true</SDLCheck>
5454
<ConformanceMode>true</ConformanceMode>
55+
<AdditionalIncludeDirectories>$(SolutionDir)Dependencies\</AdditionalIncludeDirectories>
5556
</ClCompile>
5657
<Link>
5758
<SubSystem>Console</SubSystem>
59+
<AdditionalDependencies>Wininet.lib;Urlmon.lib;Shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
5860
</Link>
5961
</ItemDefinitionGroup>
6062
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -65,25 +67,40 @@
6567
<IntrinsicFunctions>true</IntrinsicFunctions>
6668
<SDLCheck>true</SDLCheck>
6769
<ConformanceMode>true</ConformanceMode>
70+
<AdditionalIncludeDirectories>$(SolutionDir)Dependencies\</AdditionalIncludeDirectories>
6871
</ClCompile>
6972
<Link>
7073
<SubSystem>Console</SubSystem>
7174
<EnableCOMDATFolding>true</EnableCOMDATFolding>
7275
<OptimizeReferences>true</OptimizeReferences>
76+
<AdditionalDependencies>Wininet.lib;Urlmon.lib;Shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
7377
</Link>
7478
</ItemDefinitionGroup>
7579
<ItemGroup>
7680
<ClCompile Include="Download.cpp" />
7781
<ClCompile Include="Inject.cpp" />
82+
<ClCompile Include="Install.cpp" />
7883
<ClCompile Include="main.cpp" />
7984
<ClCompile Include="Options.cpp" />
85+
<ClCompile Include="Path.cpp" />
8086
<ClCompile Include="Process.cpp" />
87+
<ClCompile Include="Str.cpp" />
8188
</ItemGroup>
8289
<ItemGroup>
8390
<ClInclude Include="Download.h" />
8491
<ClInclude Include="Inject.h" />
92+
<ClInclude Include="Install.h" />
8593
<ClInclude Include="Options.h" />
94+
<ClInclude Include="Path.h" />
8695
<ClInclude Include="Process.h" />
96+
<ClInclude Include="resource.h" />
97+
<ClInclude Include="Str.h" />
98+
</ItemGroup>
99+
<ItemGroup>
100+
<ResourceCompile Include="GWToolbox.rc" />
101+
</ItemGroup>
102+
<ItemGroup>
103+
<Image Include="..\resources\gwtoolbox.ico" />
87104
</ItemGroup>
88105
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
89106
<ImportGroup Label="ExtensionTargets">

GWToolbox/GWTBLauncher.vcxproj.filters

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,35 @@
66
<ClCompile Include="Download.cpp" />
77
<ClCompile Include="Inject.cpp" />
88
<ClCompile Include="Options.cpp" />
9+
<ClCompile Include="Install.cpp" />
10+
<ClCompile Include="Path.cpp" />
11+
<ClCompile Include="Str.cpp" />
912
</ItemGroup>
1013
<ItemGroup>
1114
<ClInclude Include="Process.h" />
1215
<ClInclude Include="Download.h" />
1316
<ClInclude Include="Inject.h" />
1417
<ClInclude Include="Options.h" />
18+
<ClInclude Include="Install.h" />
19+
<ClInclude Include="Path.h" />
20+
<ClInclude Include="Str.h" />
21+
<ClInclude Include="resource.h">
22+
<Filter>Ressources</Filter>
23+
</ClInclude>
24+
</ItemGroup>
25+
<ItemGroup>
26+
<Filter Include="Ressources">
27+
<UniqueIdentifier>{2b6e2568-3dec-4b30-8084-0a7a363e003e}</UniqueIdentifier>
28+
</Filter>
29+
</ItemGroup>
30+
<ItemGroup>
31+
<ResourceCompile Include="GWToolbox.rc">
32+
<Filter>Ressources</Filter>
33+
</ResourceCompile>
34+
</ItemGroup>
35+
<ItemGroup>
36+
<Image Include="..\resources\gwtoolbox.ico">
37+
<Filter>Ressources</Filter>
38+
</Image>
1539
</ItemGroup>
1640
</Project>

GWToolbox/GWToolbox.rc

3.23 KB
Binary file not shown.

0 commit comments

Comments
 (0)