11// This file is part of BOINC.
22// https://boinc.berkeley.edu
3- // Copyright (C) 2024 University of California
3+ // Copyright (C) 2025 University of California
44//
55// BOINC is free software; you can redistribute it and/or modify it
66// under the terms of the GNU Lesser General Public License
1919
2020#include < string>
2121#include < filesystem>
22+ #include < iostream>
23+ #include < vector>
24+ #include < iomanip>
25+ #include < sstream>
26+
27+ #include < openssl/evp.h>
28+ #include < openssl/md5.h>
2229
2330#include " installer_setup.h"
2431#include " version.h"
@@ -60,27 +67,43 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
6067 return 0 ;
6168}
6269
63- bool ExtractResourceAndExecute (UINT ResourceID, std::string OutputFileName)
64- {
65- char buffer[MAX_PATH];
66- const auto result = GetWindowsDirectory (buffer, MAX_PATH);
67- if (result == 0 || result > MAX_PATH) {
68- MessageBox (NULL , " Failed to get the Windows directory!" , " Error" ,
69- MB_ICONERROR);
70- return false ;
70+ std::string computeMD5 (const void * buffer, size_t size) {
71+ unsigned char md5Digest[MD5_DIGEST_LENGTH];
72+ auto * mdContext = EVP_MD_CTX_new ();
73+
74+ if (mdContext == nullptr ) {
75+ return {};
7176 }
7277
73- const std::filesystem::path windowsDir (buffer);
74- const auto outputDir = windowsDir / " Downloaded Installations" / " BOINC" /
75- BOINC_VERSION_STRING;
76- if (!std::filesystem::exists (outputDir)) {
77- if (!std::filesystem::create_directories (outputDir)) {
78- MessageBox (NULL , " Failed to create output directory!" , " Error" ,
79- MB_ICONERROR);
80- return false ;
81- }
78+ if (EVP_DigestInit_ex (mdContext, EVP_md5 (), nullptr ) != 1 ) {
79+ EVP_MD_CTX_free (mdContext);
80+ return {};
81+ }
82+
83+ if (EVP_DigestUpdate (mdContext, buffer, size) != 1 ) {
84+ EVP_MD_CTX_free (mdContext);
85+ return {};
8286 }
8387
88+ if (EVP_DigestFinal_ex (mdContext, md5Digest, nullptr ) != 1 ) {
89+ EVP_MD_CTX_free (mdContext);
90+ return {};
91+ }
92+
93+ EVP_MD_CTX_free (mdContext);
94+
95+ std::ostringstream oss;
96+ for (auto i = 0u ; i < MD5_DIGEST_LENGTH; ++i) {
97+ oss << std::hex << std::setw (2 ) << std::setfill (' 0' ) <<
98+ static_cast <int >(md5Digest[i]);
99+ }
100+
101+ return oss.str ();
102+ }
103+
104+
105+ bool ExtractResourceAndExecute (UINT ResourceID, std::string OutputFileName)
106+ {
84107 try {
85108 auto hResource = FindResource (nullptr , MAKEINTRESOURCE (ResourceID),
86109 " BINARY" );
@@ -103,6 +126,25 @@ bool ExtractResourceAndExecute(UINT ResourceID, std::string OutputFileName)
103126 return false ;
104127 }
105128
129+ char buffer[MAX_PATH];
130+ const auto result = GetWindowsDirectory (buffer, MAX_PATH);
131+ if (result == 0 || result > MAX_PATH) {
132+ MessageBox (NULL , " Failed to get the Windows directory!" , " Error" ,
133+ MB_ICONERROR);
134+ return false ;
135+ }
136+
137+ const std::filesystem::path windowsDir (buffer);
138+ const auto outputDir = windowsDir / " Downloaded Installations" /
139+ " BOINC" / BOINC_VERSION_STRING / computeMD5 (lpFile, dwSize);
140+ if (!std::filesystem::exists (outputDir)) {
141+ if (!std::filesystem::create_directories (outputDir)) {
142+ MessageBox (NULL , " Failed to create output directory!" , " Error" ,
143+ MB_ICONERROR);
144+ return false ;
145+ }
146+ }
147+
106148 auto hFile = CreateFile ((outputDir / OutputFileName).string ().c_str (),
107149 GENERIC_READ | GENERIC_WRITE, 0 , nullptr , CREATE_ALWAYS,
108150 FILE_ATTRIBUTE_NORMAL, nullptr );
@@ -156,7 +198,8 @@ void ShowWindow(HINSTANCE hInstance, int nCmdShow) {
156198
157199 auto hwnd = CreateWindowEx (
158200 WS_EX_TOPMOST, CLASS_NAME, " Splash Screen" , WS_POPUP,
159- CW_USEDEFAULT, CW_USEDEFAULT, 800 , 600 , NULL , NULL , hInstance, NULL );
201+ CW_USEDEFAULT, CW_USEDEFAULT, 800 , 600 , NULL , NULL , hInstance,
202+ NULL );
160203
161204 if (!hwnd) {
162205 return ;
0 commit comments