Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -482,12 +482,17 @@ if (WIBO_ENABLE_FIXTURE_TESTS)
wibo_add_fixture_bin(NAME test_ws2 SOURCES test/test_ws2.c COMPILE_OPTIONS -lws2_32)
wibo_add_fixture_bin(NAME test_resources SOURCES test/test_resources.c ${WIBO_TEST_BIN_DIR}/test_resources_res.o COMPILE_OPTIONS -lversion)
wibo_add_fixture_bin(NAME test_threading SOURCES test/test_threading.c)
wibo_add_fixture_bin(NAME test_temppath SOURCES test/test_temppath.c)
wibo_add_fixture_bin(NAME test_gettempfilename SOURCES test/test_gettempfilename.c)
wibo_add_fixture_bin(NAME test_getprocaddress SOURCES test/test_getprocaddress.c)
wibo_add_fixture_bin(NAME test_getmodulehandleex SOURCES test/test_getmodulehandleex.c)
wibo_add_fixture_bin(NAME test_tls SOURCES test/test_tls.c)
wibo_add_fixture_bin(NAME test_tls_reloc SOURCES test/test_tls_reloc.c)
wibo_add_fixture_bin(NAME test_handleapi SOURCES test/test_handleapi.c)
wibo_add_fixture_bin(NAME test_findfile SOURCES test/test_findfile.c)
wibo_add_fixture_bin(NAME test_getfileattributesex SOURCES test/test_getfileattributesex.c)
wibo_add_fixture_bin(NAME test_locale SOURCES test/test_locale.c)
wibo_add_fixture_bin(NAME test_lstrcpyn SOURCES test/test_lstrcpyn.c)
wibo_add_fixture_bin(NAME test_critical_section SOURCES test/test_critical_section.c)
wibo_add_fixture_bin(NAME test_synchapi SOURCES test/test_synchapi.c)
wibo_add_fixture_bin(NAME test_processes SOURCES test/test_processes.c)
Expand All @@ -498,6 +503,7 @@ if (WIBO_ENABLE_FIXTURE_TESTS)
wibo_add_fixture_bin(NAME test_ntdll_time SOURCES test/test_ntdll_time.c)
wibo_add_fixture_bin(NAME test_virtualalloc SOURCES test/test_virtualalloc.c)
wibo_add_fixture_bin(NAME test_virtualquery SOURCES test/test_virtualquery.c)
wibo_add_fixture_bin(NAME test_createfilemapping SOURCES test/test_createfilemapping.c)
wibo_add_fixture_bin(NAME test_clsids SOURCES test/test_clsids.c COMPILE_OPTIONS -lole32)
wibo_add_fixture_bin(NAME test_rtl SOURCES test/test_rtl.c)
wibo_add_fixture_bin(NAME test_rtl_bitmap SOURCES test/test_rtl_bitmap.c)
Expand Down
61 changes: 46 additions & 15 deletions dll/kernel32/fileapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "context.h"
#include "errors.h"
#include "files.h"
#include "handleapi.h"
#include "handles.h"
#include "internal.h"
#include "namedpipeapi.h"
Expand Down Expand Up @@ -1755,33 +1756,60 @@ UINT WINAPI GetTempFileNameA(LPCSTR lpPathName, LPCSTR lpPrefixString, UINT uUni
setLastError(ERROR_BUFFER_OVERFLOW);
return 0;
}
char uniqueStr[20];
std::filesystem::path path;

auto makeTempFileName = [&](UINT unique) {
char filename[12];
snprintf(filename, sizeof(filename), "%.3s%04X.TMP", lpPrefixString, unique & 0xFFFF);

std::string path = lpPathName;
if (!path.empty() && path.back() != '\\' && path.back() != '/') {
path.push_back('\\');
}
path += filename;
return path;
};

if (uUnique == 0) {
std::random_device rd;
random_shorts_engine rse(rd());
while (true) {
uUnique = rse();
UINT startUnique = rse();
if (startUnique == 0) {
startUnique = 1;
}
bool created = false;
for (UINT attempt = 0; attempt < 0xFFFF; ++attempt) {
uUnique = (startUnique + attempt) & 0xFFFF;
if (uUnique == 0) {
continue;
}
snprintf(uniqueStr, sizeof(uniqueStr), "%.3s%X.TMP", lpPrefixString, uUnique);
path = files::pathFromWindows(lpPathName) / uniqueStr;
int fd = open(path.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0644);
if (fd >= 0) {
close(fd);
std::string path = makeTempFileName(uUnique);
HANDLE handle = CreateFileA(path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_NEW,
FILE_ATTRIBUTE_TEMPORARY, NO_HANDLE);
if (handle != INVALID_HANDLE_VALUE) {
CloseHandle(handle);
strncpy(lpTempFileName, path.c_str(), MAX_PATH);
lpTempFileName[MAX_PATH - 1] = '\0';
DEBUG_LOG(" -> %s\n", lpTempFileName);
created = true;
break;
}
DWORD error = getLastError();
if (error != ERROR_FILE_EXISTS && error != ERROR_ALREADY_EXISTS) {
DEBUG_LOG(" -> error %u\n", error);
return 0;
}
}
if (!created) {
setLastError(ERROR_FILE_EXISTS);
DEBUG_LOG(" -> ERROR_FILE_EXISTS\n");
return 0;
}
} else {
snprintf(uniqueStr, sizeof(uniqueStr), "%.3s%X.TMP", lpPrefixString, uUnique & 0xFFFF);
path = files::pathFromWindows(lpPathName) / uniqueStr;
std::string path = makeTempFileName(uUnique);
strncpy(lpTempFileName, path.c_str(), MAX_PATH);
lpTempFileName[MAX_PATH - 1] = '\0';
DEBUG_LOG(" -> %s\n", lpTempFileName);
}
std::string str = files::pathToWindows(path);
DEBUG_LOG(" -> %s\n", str.c_str());
strncpy(lpTempFileName, str.c_str(), MAX_PATH);
lpTempFileName[MAX_PATH - 1] = '\0';
return uUnique;
}

Expand All @@ -1803,6 +1831,9 @@ DWORD WINAPI GetTempPathA(DWORD nBufferLength, LPSTR lpBuffer) {
} else {
pathStr = "Z:\\tmp\\";
}
if (!pathStr.empty() && pathStr.back() != '\\') {
pathStr.push_back('\\');
}
size_t len = pathStr.length();
if (len + 1 > nBufferLength) {
setLastError(ERROR_INSUFFICIENT_BUFFER);
Expand Down
49 changes: 47 additions & 2 deletions dll/kernel32/libloaderapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,20 @@

#include <algorithm>
#include <cassert>
#include <climits>
#include <cstring>
#include <optional>
#include <string>

namespace {

constexpr DWORD GET_MODULE_HANDLE_EX_FLAG_PIN = 0x00000001;
constexpr DWORD GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 0x00000002;
constexpr DWORD GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 0x00000004;
constexpr DWORD GET_MODULE_HANDLE_EX_VALID_FLAGS = GET_MODULE_HANDLE_EX_FLAG_PIN |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS;

HRSRC findResourceInternal(HMODULE hModule, const wibo::ResourceIdentifier &type, const wibo::ResourceIdentifier &name,
std::optional<uint16_t> language) {
auto *exe = wibo::executableFromModule(hModule);
Expand Down Expand Up @@ -74,6 +82,43 @@ HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName) {
return GetModuleHandleA(nullptr);
}

BOOL WINAPI GetModuleHandleExW(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE *phModule) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("GetModuleHandleExW(%x, %p, %p)\n", dwFlags, lpModuleName, phModule);
if (!phModule) {
setLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
*phModule = NO_HANDLE;
if ((dwFlags & ~GET_MODULE_HANDLE_EX_VALID_FLAGS) != 0 ||
((dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) && (dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT))) {
setLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}

wibo::ModuleInfo *module = nullptr;
if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) {
module = wibo::moduleInfoFromAddress(const_cast<void *>(reinterpret_cast<const void *>(lpModuleName)));
} else if (lpModuleName) {
const auto lpModuleNameA = wideStringToString(lpModuleName);
module = wibo::findLoadedModule(lpModuleNameA.c_str());
} else {
module = wibo::findLoadedModule(nullptr);
}

if (!module) {
setLastError(ERROR_MOD_NOT_FOUND);
return FALSE;
}
if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) {
module->refCount = UINT_MAX;
} else if (!(dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) && module->refCount != UINT_MAX) {
module->refCount++;
}
*phModule = module->handle;
return TRUE;
}

DWORD WINAPI GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("GetModuleFileNameA(%p, %p, %u)\n", hModule, lpFilename, nSize);
Expand Down Expand Up @@ -283,10 +328,10 @@ FARPROC WINAPI GetProcAddress(HMODULE hModule, LPCSTR lpProcName) {
const auto proc = reinterpret_cast<uintptr_t>(lpProcName);
if (proc & ~0xFFFFu) {
DEBUG_LOG("GetProcAddress(%s, %s) ", info->normalizedName.c_str(), lpProcName);
result = wibo::resolveFuncByName(info, lpProcName);
result = wibo::findExportByName(info, lpProcName);
} else {
DEBUG_LOG("GetProcAddress(%s, %u) ", info->normalizedName.c_str(), proc);
result = wibo::resolveFuncByOrdinal(info, static_cast<uint16_t>(proc));
result = wibo::findExportByOrdinal(info, static_cast<uint16_t>(proc));
}
DEBUG_LOG("-> %p\n", result);
if (!result) {
Expand Down
1 change: 1 addition & 0 deletions dll/kernel32/libloaderapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace kernel32 {
BOOL WINAPI DisableThreadLibraryCalls(HMODULE hLibModule);
HMODULE WINAPI GetModuleHandleA(LPCSTR lpModuleName);
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName);
BOOL WINAPI GetModuleHandleExW(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE *phModule);
DWORD WINAPI GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
DWORD WINAPI GetModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize);
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR lpName, LPCSTR lpType);
Expand Down
Loading
Loading