From 8bd112f0e47c5d6eb35802fd310c38bff3fa8552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20Balatoni?= <40299962+dbalatoni13@users.noreply.github.com> Date: Wed, 18 Jun 2025 00:12:39 +0200 Subject: [PATCH] Add GetTempFileNameA (#84) --- common.h | 3 +++ dll/kernel32.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/common.h b/common.h index 64ad01c..0ac0157 100644 --- a/common.h +++ b/common.h @@ -55,6 +55,7 @@ typedef unsigned char BYTE; #define ERROR_HANDLE_EOF 38 #define ERROR_NOT_SUPPORTED 50 #define ERROR_INVALID_PARAMETER 87 +#define ERROR_BUFFER_OVERFLOW 111 #define ERROR_INSUFFICIENT_BUFFER 122 #define ERROR_NEGATIVE_SEEK 131 #define ERROR_ALREADY_EXISTS 183 @@ -72,6 +73,8 @@ typedef int NTSTATUS; typedef int HRESULT; #define S_OK ((HRESULT)0x00000000) +#define MAX_PATH (260) + namespace wibo { extern uint32_t lastError; extern char **argv; diff --git a/dll/kernel32.cpp b/dll/kernel32.cpp index fc3567a..6d575a6 100644 --- a/dll/kernel32.cpp +++ b/dll/kernel32.cpp @@ -3,6 +3,7 @@ #include "processes.h" #include "handles.h" #include +#include #include #include #include @@ -10,6 +11,7 @@ #include #include "strutil.h" #include +#include #include #include #include @@ -17,6 +19,7 @@ #include #include #include +#include typedef union _RTL_RUN_ONCE { PVOID Ptr; @@ -649,6 +652,46 @@ namespace kernel32 { } } + using random_shorts_engine = std::independent_bits_engine; + + unsigned int WIN_FUNC GetTempFileNameA(LPSTR lpPathName, LPSTR lpPrefixString, unsigned int uUnique, LPSTR lpTempFileName) { + DEBUG_LOG("GetTempFileNameA\n"); + if (lpPathName == 0) { + return 0; + } + if (strlen(lpPathName) > MAX_PATH - 14) { + wibo::lastError = ERROR_BUFFER_OVERFLOW; + return 0; + } + char uniqueStr[20]; + std::filesystem::path path; + + if (uUnique == 0) { + std::random_device rd; + random_shorts_engine rse(rd()); + while(true) { + uUnique = rse(); + if (uUnique == 0) { + continue; + } + snprintf(uniqueStr, sizeof(uniqueStr), "%.3s%X.TMP", lpPrefixString, uUnique); + path = files::pathFromWindows(lpPathName) / uniqueStr; + // Atomically create it if it doesn't exist + int fd = open(path.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0644); + if (fd >= 0) { + close(fd); + break; + } + } + } + else { + snprintf(uniqueStr, sizeof(uniqueStr), "%.3s%X.TMP", lpPrefixString, uUnique & 0xFFFF); + path = files::pathFromWindows(lpPathName) / uniqueStr; + } + strncpy(lpTempFileName, files::pathToWindows(path).c_str(), MAX_PATH); + return uUnique; + } + DWORD WIN_FUNC GetTempPathA(DWORD nBufferLength, LPSTR lpBuffer) { DEBUG_LOG("GetTempPathA\n"); @@ -2368,6 +2411,7 @@ static void *resolveByName(const char *name) { if (strcmp(name, "GetFileType") == 0) return (void *) kernel32::GetFileType; if (strcmp(name, "FileTimeToLocalFileTime") == 0) return (void *) kernel32::FileTimeToLocalFileTime; if (strcmp(name, "GetFileInformationByHandle") == 0) return (void *) kernel32::GetFileInformationByHandle; + if (strcmp(name, "GetTempFileNameA") == 0) return (void *) kernel32::GetTempFileNameA; if (strcmp(name, "GetTempPathA") == 0) return (void *) kernel32::GetTempPathA; // sysinfoapi.h