Skip to content

Commit ebbab67

Browse files
author
Dan Dees
committed
winhttp test program - incomplete but runs
1 parent 27b5ae4 commit ebbab67

File tree

3 files changed

+136
-0
lines changed

3 files changed

+136
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ add_subdirectory(3rdparty)
1919
add_subdirectory(a)
2020
add_subdirectory(MemoryModule)
2121
add_subdirectory(test)
22+
add_subdirectory(winhttp)

winhttp/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
cmake_minimum_required(VERSION 3.27)
2+
project(winhttp-test LANGUAGES CXX)
3+
4+
set(exename "winhttp-test")
5+
add_executable(${exename})
6+
target_link_libraries(${exename} PRIVATE
7+
MemoryModulePP-shared
8+
shlwapi # PathFindOnPathW
9+
)
10+
11+
# use install directory under build to assemble tests
12+
set( INSTALL_DIR "${CMAKE_BINARY_DIR}/install")
13+
14+
# common sources and libs
15+
target_sources(${exename} PRIVATE winhttp.cpp)
16+
17+
# copy exes into install dir
18+
install(TARGETS ${exename} RUNTIME DESTINATION ${INSTALL_DIR})

winhttp/winhttp.cpp

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#include <expected>
2+
#include <filesystem>
3+
#include <system_error>
4+
#include <windows.h>
5+
#include <fstream>
6+
#include <print>
7+
#include <format>
8+
#include <array>
9+
#include <shlwapi.h>
10+
#include <iostream> // For std::wcout, std::wcerr
11+
12+
// Returns a pointer to the allocated memory containing the DLL data or an error code
13+
[[nodiscard]] std::expected<LPVOID, std::error_code>
14+
ReadDllToMemory(const std::filesystem::path& filePath) noexcept {
15+
std::expected<LPVOID, std::error_code> result
16+
= std::unexpected(
17+
std::make_error_code(
18+
std::errc::invalid_argument));
19+
20+
// Open the file in binary mode with RAII
21+
std::ifstream file(filePath, std::ios::binary | std::ios::ate);
22+
if (file.is_open()) {
23+
24+
// Get file size
25+
const std::streampos fileSize = file.tellg();
26+
27+
if (fileSize > 0) {
28+
29+
// Allocate executable memory
30+
const LPVOID memory = VirtualAlloc(
31+
nullptr,
32+
static_cast<size_t>(fileSize),
33+
MEM_COMMIT | MEM_RESERVE,
34+
PAGE_EXECUTE_READWRITE);
35+
36+
if (memory) {
37+
38+
// Reset to beginning of file
39+
file.seekg(0, std::ios::beg);
40+
41+
// Read file directly into allocated memory
42+
if (file.read(static_cast<char*>(memory), fileSize)) {
43+
result = memory;
44+
} else {
45+
result = std::unexpected(
46+
std::make_error_code(
47+
std::errc::io_error));
48+
}
49+
50+
} else {
51+
result = std::unexpected(std::make_error_code(std::errc::not_enough_memory));
52+
}
53+
}
54+
// No cleanup needed; file is closed by RAII
55+
} else {
56+
result = std::unexpected(
57+
std::make_error_code(
58+
std::errc::no_such_file_or_directory));
59+
}
60+
61+
return result;
62+
}
63+
64+
// Find DLL in system path, returning std::filesystem::path with single return
65+
[[nodiscard]] std::filesystem::path FindDllInPath(const std::wstring& dllName) noexcept
66+
{
67+
std::array<wchar_t, MAX_PATH> fullPath{};
68+
69+
return dllName.size() < fullPath.size()
70+
&& wcscpy_s(fullPath.data(), fullPath.size(), dllName.c_str()) == 0
71+
&& PathFindOnPathW(fullPath.data(), nullptr)
72+
? std::filesystem::path(fullPath.data())
73+
: std::filesystem::path{};
74+
}
75+
76+
int test( const std::filesystem::path& dllFullPath )
77+
{
78+
// Read DLL directly into executable memory
79+
const auto& result = ReadDllToMemory(dllFullPath);
80+
LPVOID memory = nullptr; // Track memory for cleanup
81+
if (!result) {
82+
const auto& errorMsg = std::system_category().message(result.error().value());
83+
const std::wstring wErrorMsg(errorMsg.begin(), errorMsg.end()); // Simple narrow-to-wide conversion
84+
std::wcout << std::format(L"Failed to load DLL: {}\n", wErrorMsg);
85+
return -1;
86+
}
87+
88+
memory = *result; // Store for cleanup
89+
std::wcout << std::format(L"Successfully loaded {} into memory at: {:#x}\n",
90+
dllFullPath.wstring(),
91+
reinterpret_cast<std::uintptr_t>(memory));
92+
93+
// Standardized cleanup
94+
VirtualFree(memory, 0, MEM_RELEASE);
95+
return 0;
96+
}
97+
98+
// Example usage
99+
int main( int argc, char* argv[]) {
100+
101+
std::wstring dll_name(L"winhttp.dll");
102+
103+
const std::filesystem::path dllPath{dll_name};
104+
105+
// Find DLL in system path
106+
const auto& dllFullPath = FindDllInPath(dll_name);
107+
if (dllFullPath.empty()) {
108+
std::wcout << std::format(L"DLL not found: {}\n", dll_name);
109+
return 1;
110+
}
111+
112+
std::wcout << std::format(L"Found {} for {}\n", dllFullPath.wstring(), dll_name);
113+
114+
test(dllFullPath);
115+
116+
return 0;
117+
}

0 commit comments

Comments
 (0)