mirror of
https://github.com/decompals/wibo.git
synced 2025-10-15 14:45:12 +00:00
Split advapi32 into separate files (part 2) & more impls for ee-gcc/cygwin
This commit is contained in:
parent
79e1dbf523
commit
3249ebf4bf
@ -33,8 +33,12 @@ FetchContent_MakeAvailable(mimalloc)
|
||||
include_directories(.)
|
||||
add_executable(wibo
|
||||
dll/advapi32.cpp
|
||||
dll/advapi32/winreg.cpp
|
||||
dll/advapi32/internal.cpp
|
||||
dll/advapi32/processthreadsapi.cpp
|
||||
dll/advapi32/securitybaseapi.cpp
|
||||
dll/advapi32/winbase.cpp
|
||||
dll/advapi32/wincrypt.cpp
|
||||
dll/advapi32/winreg.cpp
|
||||
dll/bcrypt.cpp
|
||||
dll/crt.cpp
|
||||
dll/kernel32.cpp
|
||||
|
8
common.h
8
common.h
@ -42,6 +42,7 @@ using HGLOBAL = HANDLE;
|
||||
using HLOCAL = HANDLE;
|
||||
using HRSRC = HANDLE;
|
||||
using LPHANDLE = HANDLE *;
|
||||
using PHANDLE = HANDLE *;
|
||||
using PVOID = void *;
|
||||
using LPVOID = void *;
|
||||
using LPCVOID = const void *;
|
||||
@ -56,6 +57,12 @@ using LONG = int32_t;
|
||||
using PLONG = LONG *;
|
||||
using ULONG = uint32_t;
|
||||
using PULONG = ULONG *;
|
||||
struct LUID {
|
||||
DWORD LowPart;
|
||||
LONG HighPart;
|
||||
};
|
||||
using PLUID = LUID *;
|
||||
using LPLUID = LUID *;
|
||||
using LARGE_INTEGER = int64_t;
|
||||
using PLARGE_INTEGER = LARGE_INTEGER *;
|
||||
using ULONG_PTR = uintptr_t;
|
||||
@ -84,6 +91,7 @@ using BOOLEAN = unsigned char;
|
||||
using UINT = unsigned int;
|
||||
using HKEY = void *;
|
||||
using PHKEY = HKEY *;
|
||||
using PSID = void *;
|
||||
using REGSAM = DWORD;
|
||||
using LSTATUS = LONG;
|
||||
using LCID = DWORD;
|
||||
|
614
dll/advapi32.cpp
614
dll/advapi32.cpp
@ -1,540 +1,106 @@
|
||||
#include "common.h"
|
||||
#include "advapi32/winreg.h"
|
||||
#include "advapi32/processthreadsapi.h"
|
||||
#include "advapi32/securitybaseapi.h"
|
||||
#include "advapi32/winbase.h"
|
||||
#include "advapi32/wincrypt.h"
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "strutil.h"
|
||||
#include "advapi32/winreg.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace {
|
||||
struct Luid;
|
||||
static std::mutex privilegeMapMutex;
|
||||
static std::unordered_map<std::string, Luid> privilegeLuidCache;
|
||||
|
||||
constexpr DWORD SECURITY_DESCRIPTOR_REVISION = 1;
|
||||
constexpr uint16_t SE_DACL_PRESENT = 0x0004;
|
||||
constexpr uint16_t SE_DACL_DEFAULTED = 0x0008;
|
||||
void *resolveByName(const char *name) {
|
||||
// processthreadsapi.h
|
||||
if (strcmp(name, "OpenProcessToken") == 0)
|
||||
return (void *)advapi32::OpenProcessToken;
|
||||
|
||||
struct SecurityDescriptor {
|
||||
uint8_t Revision = 0;
|
||||
uint8_t Sbz1 = 0;
|
||||
uint16_t Control = 0;
|
||||
void *Owner = nullptr;
|
||||
void *Group = nullptr;
|
||||
void *Sacl = nullptr;
|
||||
void *Dacl = nullptr;
|
||||
};
|
||||
// securitybaseapi.h
|
||||
if (strcmp(name, "InitializeAcl") == 0)
|
||||
return (void *)advapi32::InitializeAcl;
|
||||
if (strcmp(name, "AddAccessAllowedAce") == 0)
|
||||
return (void *)advapi32::AddAccessAllowedAce;
|
||||
if (strcmp(name, "FindFirstFreeAce") == 0)
|
||||
return (void *)advapi32::FindFirstFreeAce;
|
||||
if (strcmp(name, "GetSidIdentifierAuthority") == 0)
|
||||
return (void *)advapi32::GetSidIdentifierAuthority;
|
||||
if (strcmp(name, "GetSidSubAuthorityCount") == 0)
|
||||
return (void *)advapi32::GetSidSubAuthorityCount;
|
||||
if (strcmp(name, "GetSidSubAuthority") == 0)
|
||||
return (void *)advapi32::GetSidSubAuthority;
|
||||
if (strcmp(name, "ImpersonateLoggedOnUser") == 0)
|
||||
return (void *)advapi32::ImpersonateLoggedOnUser;
|
||||
if (strcmp(name, "DuplicateTokenEx") == 0)
|
||||
return (void *)advapi32::DuplicateTokenEx;
|
||||
if (strcmp(name, "CopySid") == 0)
|
||||
return (void *)advapi32::CopySid;
|
||||
if (strcmp(name, "GetSecurityDescriptorDacl") == 0)
|
||||
return (void *)advapi32::GetSecurityDescriptorDacl;
|
||||
if (strcmp(name, "SetKernelObjectSecurity") == 0)
|
||||
return (void *)advapi32::SetKernelObjectSecurity;
|
||||
if (strcmp(name, "InitializeSecurityDescriptor") == 0)
|
||||
return (void *)advapi32::InitializeSecurityDescriptor;
|
||||
if (strcmp(name, "SetSecurityDescriptorDacl") == 0)
|
||||
return (void *)advapi32::SetSecurityDescriptorDacl;
|
||||
if (strcmp(name, "GetTokenInformation") == 0)
|
||||
return (void *)advapi32::GetTokenInformation;
|
||||
if (strcmp(name, "AdjustTokenPrivileges") == 0)
|
||||
return (void *)advapi32::AdjustTokenPrivileges;
|
||||
if (strcmp(name, "SetTokenInformation") == 0)
|
||||
return (void *)advapi32::SetTokenInformation;
|
||||
|
||||
struct TokenObject {
|
||||
HANDLE processHandle = nullptr;
|
||||
DWORD desiredAccess = 0;
|
||||
};
|
||||
// winbase.h
|
||||
if (strcmp(name, "LookupAccountSidW") == 0)
|
||||
return (void *)advapi32::LookupAccountSidW;
|
||||
if (strcmp(name, "LookupPrivilegeValueA") == 0)
|
||||
return (void *)advapi32::LookupPrivilegeValueA;
|
||||
if (strcmp(name, "LookupPrivilegeValueW") == 0)
|
||||
return (void *)advapi32::LookupPrivilegeValueW;
|
||||
if (strcmp(name, "GetUserNameA") == 0)
|
||||
return (void *)advapi32::GetUserNameA;
|
||||
if (strcmp(name, "GetUserNameW") == 0)
|
||||
return (void *)advapi32::GetUserNameW;
|
||||
|
||||
struct SidIdentifierAuthority {
|
||||
uint8_t Value[6] = {0};
|
||||
};
|
||||
|
||||
struct Sid {
|
||||
uint8_t Revision = 1;
|
||||
uint8_t SubAuthorityCount = 0;
|
||||
SidIdentifierAuthority IdentifierAuthority = {};
|
||||
uint32_t SubAuthority[1] = {0};
|
||||
};
|
||||
|
||||
struct SidAndAttributes {
|
||||
Sid *SidPtr = nullptr;
|
||||
DWORD Attributes = 0;
|
||||
};
|
||||
|
||||
struct TokenUserData {
|
||||
SidAndAttributes User;
|
||||
};
|
||||
|
||||
enum SID_NAME_USE {
|
||||
SidTypeUser = 1,
|
||||
SidTypeGroup,
|
||||
SidTypeDomain,
|
||||
SidTypeAlias,
|
||||
SidTypeWellKnownGroup,
|
||||
SidTypeDeletedAccount,
|
||||
SidTypeInvalid,
|
||||
SidTypeUnknown,
|
||||
SidTypeComputer,
|
||||
SidTypeLabel
|
||||
};
|
||||
|
||||
bool isLocalSystemSid(const Sid *sid) {
|
||||
if (!sid) {
|
||||
return false;
|
||||
}
|
||||
static const uint8_t ntAuthority[6] = {0, 0, 0, 0, 0, 5};
|
||||
if (sid->Revision != 1 || sid->SubAuthorityCount != 1) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < 6; ++i) {
|
||||
if (sid->IdentifierAuthority.Value[i] != ntAuthority[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return sid->SubAuthority[0] == 18; // SECURITY_LOCAL_SYSTEM_RID
|
||||
}
|
||||
|
||||
struct Luid {
|
||||
uint32_t LowPart = 0;
|
||||
int32_t HighPart = 0;
|
||||
};
|
||||
|
||||
struct LuidAndAttributes {
|
||||
Luid value;
|
||||
DWORD Attributes = 0;
|
||||
};
|
||||
|
||||
struct TokenStatisticsData {
|
||||
Luid tokenId;
|
||||
Luid authenticationId;
|
||||
int64_t expirationTime = 0;
|
||||
uint32_t tokenType = 0;
|
||||
uint32_t impersonationLevel = 0;
|
||||
uint32_t dynamicCharged = 0;
|
||||
uint32_t dynamicAvailable = 0;
|
||||
uint32_t groupCount = 0;
|
||||
uint32_t privilegeCount = 0;
|
||||
Luid modifiedId;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace advapi32 {
|
||||
BOOL WIN_FUNC OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, HANDLE *TokenHandle) {
|
||||
DEBUG_LOG("OpenProcessToken(%p, %u, %p)\n", ProcessHandle, DesiredAccess, TokenHandle);
|
||||
if (!TokenHandle) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *token = new TokenObject;
|
||||
token->processHandle = ProcessHandle;
|
||||
token->desiredAccess = DesiredAccess;
|
||||
handles::Data data;
|
||||
data.type = handles::TYPE_TOKEN;
|
||||
data.ptr = token;
|
||||
data.size = 0;
|
||||
*TokenHandle = handles::allocDataHandle(data);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void releaseToken(void *tokenPtr) {
|
||||
delete reinterpret_cast<TokenObject *>(tokenPtr);
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetTokenInformation(HANDLE TokenHandle, unsigned int TokenInformationClass, void *TokenInformation, unsigned int TokenInformationLength, unsigned int *ReturnLength) {
|
||||
DEBUG_LOG("GetTokenInformation(%p, %u, %p, %u, %p)\n", TokenHandle, TokenInformationClass, TokenInformation,
|
||||
TokenInformationLength, ReturnLength);
|
||||
if (!ReturnLength) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
auto data = handles::dataFromHandle(TokenHandle, false);
|
||||
if (data.type != handles::TYPE_TOKEN) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
constexpr unsigned int TokenUserClass = 1; // TokenUser
|
||||
constexpr unsigned int TokenStatisticsClass = 10; // TokenStatistics
|
||||
constexpr unsigned int TokenElevationClass = 20; // TokenElevation
|
||||
constexpr unsigned int TokenPrimaryGroupClass = 5; // TokenPrimaryGroup
|
||||
if (TokenInformationClass == TokenUserClass) {
|
||||
constexpr size_t sidSize = sizeof(Sid);
|
||||
constexpr size_t tokenUserSize = sizeof(TokenUserData);
|
||||
const auto required = static_cast<unsigned int>(tokenUserSize + sidSize);
|
||||
*ReturnLength = required;
|
||||
if (!TokenInformation || TokenInformationLength < required) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *tokenUser = reinterpret_cast<TokenUserData *>(TokenInformation);
|
||||
auto *sid = reinterpret_cast<Sid *>(reinterpret_cast<uint8_t *>(TokenInformation) + tokenUserSize);
|
||||
SidIdentifierAuthority ntAuthority = {{0, 0, 0, 0, 0, 5}};
|
||||
sid->Revision = 1;
|
||||
sid->SubAuthorityCount = 1;
|
||||
sid->IdentifierAuthority = ntAuthority;
|
||||
sid->SubAuthority[0] = 18; // SECURITY_LOCAL_SYSTEM_RID
|
||||
tokenUser->User.SidPtr = sid;
|
||||
tokenUser->User.Attributes = 0;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
if (TokenInformationClass == TokenStatisticsClass) {
|
||||
const unsigned int required = sizeof(TokenStatisticsData);
|
||||
*ReturnLength = required;
|
||||
if (!TokenInformation || TokenInformationLength < required) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *stats = reinterpret_cast<TokenStatisticsData *>(TokenInformation);
|
||||
*stats = {};
|
||||
stats->tokenType = 1; // TokenPrimary
|
||||
stats->impersonationLevel = 0; // SecurityAnonymous
|
||||
stats->tokenId.LowPart = 1;
|
||||
stats->authenticationId.LowPart = 1;
|
||||
stats->modifiedId.LowPart = 1;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
if (TokenInformationClass == TokenElevationClass) {
|
||||
const unsigned int required = sizeof(DWORD);
|
||||
*ReturnLength = required;
|
||||
if (!TokenInformation || TokenInformationLength < required) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
*reinterpret_cast<DWORD *>(TokenInformation) = 0; // not elevated
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
if (TokenInformationClass == TokenPrimaryGroupClass) {
|
||||
struct TokenPrimaryGroupStub {
|
||||
Sid *PrimaryGroup;
|
||||
};
|
||||
constexpr size_t sidSize = sizeof(Sid);
|
||||
constexpr size_t headerSize = sizeof(TokenPrimaryGroupStub);
|
||||
const unsigned int required = static_cast<unsigned int>(headerSize + sidSize);
|
||||
*ReturnLength = required;
|
||||
if (!TokenInformation || TokenInformationLength < required) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *groupInfo = reinterpret_cast<TokenPrimaryGroupStub *>(TokenInformation);
|
||||
auto *sid = reinterpret_cast<Sid *>(reinterpret_cast<uint8_t *>(TokenInformation) + headerSize);
|
||||
sid->Revision = 1;
|
||||
sid->SubAuthorityCount = 1;
|
||||
sid->IdentifierAuthority = {{0, 0, 0, 0, 0, 5}};
|
||||
sid->SubAuthority[0] = 18; // SECURITY_LOCAL_SYSTEM_RID
|
||||
groupInfo->PrimaryGroup = sid;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
wibo::lastError = ERROR_NOT_SUPPORTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC LookupAccountSidW(const uint16_t *lpSystemName, const void *sidPointer, uint16_t *Name,
|
||||
unsigned long *cchName, uint16_t *ReferencedDomainName,
|
||||
unsigned long *cchReferencedDomainName, SID_NAME_USE *peUse) {
|
||||
std::string systemName = lpSystemName ? wideStringToString(lpSystemName) : std::string("(null)");
|
||||
DEBUG_LOG("LookupAccountSidW(%s, %p, %p, %p, %p, %p, %p)\n", systemName.c_str(), sidPointer, Name, cchName,
|
||||
ReferencedDomainName, cchReferencedDomainName, peUse);
|
||||
(void) lpSystemName; // Only local lookup supported
|
||||
if (!sidPointer || !cchName || !cchReferencedDomainName || !peUse) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *sid = reinterpret_cast<const Sid *>(sidPointer);
|
||||
if (!isLocalSystemSid(sid)) {
|
||||
wibo::lastError = ERROR_NONE_MAPPED;
|
||||
return FALSE;
|
||||
}
|
||||
static constexpr uint16_t accountName[] = {u'S', u'Y', u'S', u'T', u'E', u'M', u'\0'};
|
||||
static constexpr uint16_t domainName[] = {u'N', u'T', u' ', u'A', u'U', u'T', u'H', u'O', u'R', u'I', u'T', u'Y', u'\0'};
|
||||
unsigned long requiredAccount = wstrlen(accountName) + 1;
|
||||
unsigned long requiredDomain = wstrlen(domainName) + 1;
|
||||
if (!Name || *cchName < requiredAccount || !ReferencedDomainName || *cchReferencedDomainName < requiredDomain) {
|
||||
*cchName = requiredAccount;
|
||||
*cchReferencedDomainName = requiredDomain;
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
std::copy_n(accountName, requiredAccount, Name);
|
||||
std::copy_n(domainName, requiredDomain, ReferencedDomainName);
|
||||
*peUse = SidTypeWellKnownGroup;
|
||||
*cchName = requiredAccount - 1;
|
||||
*cchReferencedDomainName = requiredDomain - 1;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Luid generateDeterministicLuid(const std::string &normalizedName) {
|
||||
uint32_t hash = 2166136261u;
|
||||
for (unsigned char ch : normalizedName) {
|
||||
hash ^= ch;
|
||||
hash *= 16777619u;
|
||||
}
|
||||
if (hash == 0) {
|
||||
hash = 1;
|
||||
}
|
||||
Luid result{};
|
||||
result.LowPart = hash;
|
||||
result.HighPart = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string normalizePrivilegeName(const std::string &name) {
|
||||
std::string normalized;
|
||||
normalized.reserve(name.size());
|
||||
for (unsigned char ch : name) {
|
||||
if (ch == '\r' || ch == '\n' || ch == '\t') {
|
||||
continue;
|
||||
}
|
||||
normalized.push_back(static_cast<char>(std::tolower(ch)));
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
static Luid lookupOrGeneratePrivilegeLuid(const std::string &normalizedName) {
|
||||
std::lock_guard<std::mutex> lock(privilegeMapMutex);
|
||||
auto cached = privilegeLuidCache.find(normalizedName);
|
||||
if (cached != privilegeLuidCache.end()) {
|
||||
return cached->second;
|
||||
}
|
||||
static const std::unordered_map<std::string, uint32_t> predefined = {
|
||||
{"secreatepagefileprivilege", 0x00000002},
|
||||
{"seshutdownprivilege", 0x00000003},
|
||||
{"sebackupprivilege", 0x00000004},
|
||||
{"serestoreprivilege", 0x00000005},
|
||||
{"sechangenotifyprivilege", 0x00000006},
|
||||
{"seassignprimarytokenprivilege", 0x00000007},
|
||||
{"seincreasequotaprivilege", 0x00000008},
|
||||
{"seincreasebasepriorityprivilege", 0x00000009},
|
||||
{"seloaddriverprivilege", 0x0000000a},
|
||||
{"setakeownershipprivilege", 0x0000000b},
|
||||
{"sesystemtimeprivilege", 0x0000000c},
|
||||
{"sesystemenvironmentprivilege", 0x0000000d},
|
||||
{"setcbprivilege", 0x0000000e},
|
||||
{"sedebugprivilege", 0x0000000f},
|
||||
{"semanagevolumeprivilege", 0x00000010},
|
||||
{"seimpersonateprivilege", 0x00000011},
|
||||
{"secreateglobalprivilege", 0x00000012},
|
||||
{"sesecurityprivilege", 0x00000013},
|
||||
{"selockmemoryprivilege", 0x00000014},
|
||||
{"seundockprivilege", 0x00000015},
|
||||
{"seremoteshutdownprivilege", 0x00000016}
|
||||
};
|
||||
auto known = predefined.find(normalizedName);
|
||||
Luid luid{};
|
||||
if (known != predefined.end()) {
|
||||
luid.LowPart = known->second;
|
||||
luid.HighPart = 0;
|
||||
} else {
|
||||
luid = generateDeterministicLuid(normalizedName);
|
||||
}
|
||||
privilegeLuidCache.emplace(normalizedName, luid);
|
||||
return luid;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC LookupPrivilegeValueA(const char *lpSystemName, const char *lpName, Luid *lpLuid) {
|
||||
DEBUG_LOG("LookupPrivilegeValueA(%s, %s, %p)\n",
|
||||
lpSystemName ? lpSystemName : "<null>",
|
||||
lpName ? lpName : "<null>",
|
||||
lpLuid);
|
||||
if (!lpName || !lpLuid) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
if (lpSystemName && lpSystemName[0] != '\0') {
|
||||
DEBUG_LOG("-> remote system unsupported\n");
|
||||
wibo::lastError = ERROR_NOT_SUPPORTED;
|
||||
return FALSE;
|
||||
}
|
||||
std::string normalized = normalizePrivilegeName(lpName);
|
||||
if (normalized.empty()) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
Luid luid = lookupOrGeneratePrivilegeLuid(normalized);
|
||||
*lpLuid = luid;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC LookupPrivilegeValueW(const uint16_t *lpSystemName, const uint16_t *lpName, Luid *lpLuid) {
|
||||
DEBUG_LOG("LookupPrivilegeValueW(%ls, %ls, %p)\n",
|
||||
lpSystemName ? reinterpret_cast<const wchar_t *>(lpSystemName) : L"<null>",
|
||||
lpName ? reinterpret_cast<const wchar_t *>(lpName) : L"<null>",
|
||||
lpLuid);
|
||||
if (!lpName || !lpLuid) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
if (lpSystemName && lpSystemName[0] != 0) {
|
||||
std::string host = wideStringToString(lpSystemName);
|
||||
if (!host.empty()) {
|
||||
wibo::lastError = ERROR_NOT_SUPPORTED;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
std::string ansiName = wideStringToString(lpName);
|
||||
return LookupPrivilegeValueA(nullptr, ansiName.c_str(), lpLuid);
|
||||
}
|
||||
|
||||
struct TokenPrivilegesHeader {
|
||||
DWORD PrivilegeCount = 0;
|
||||
};
|
||||
|
||||
BOOL WIN_FUNC AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, void *NewState, DWORD BufferLength,
|
||||
void *PreviousState, PDWORD ReturnLength) {
|
||||
DEBUG_LOG("AdjustTokenPrivileges(%p, %d, %p, %u, %p, %p)\n", TokenHandle, DisableAllPrivileges,
|
||||
NewState, BufferLength, PreviousState, ReturnLength);
|
||||
(void) DisableAllPrivileges;
|
||||
(void) NewState;
|
||||
auto data = handles::dataFromHandle(TokenHandle, false);
|
||||
if (data.type != handles::TYPE_TOKEN) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
if (PreviousState) {
|
||||
if (BufferLength < sizeof(TokenPrivilegesHeader)) {
|
||||
if (ReturnLength) {
|
||||
*ReturnLength = sizeof(TokenPrivilegesHeader);
|
||||
}
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *header = reinterpret_cast<TokenPrivilegesHeader *>(PreviousState);
|
||||
header->PrivilegeCount = 0;
|
||||
if (ReturnLength) {
|
||||
*ReturnLength = sizeof(TokenPrivilegesHeader);
|
||||
}
|
||||
} else if (ReturnLength) {
|
||||
*ReturnLength = 0;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC InitializeSecurityDescriptor(void *pSecurityDescriptor, DWORD dwRevision) {
|
||||
DEBUG_LOG("InitializeSecurityDescriptor(%p, %u)\n", pSecurityDescriptor, dwRevision);
|
||||
if (!pSecurityDescriptor) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
if (dwRevision != SECURITY_DESCRIPTOR_REVISION) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *descriptor = static_cast<SecurityDescriptor *>(pSecurityDescriptor);
|
||||
descriptor->Revision = static_cast<uint8_t>(dwRevision);
|
||||
descriptor->Sbz1 = 0;
|
||||
descriptor->Control = 0;
|
||||
descriptor->Owner = nullptr;
|
||||
descriptor->Group = nullptr;
|
||||
descriptor->Sacl = nullptr;
|
||||
descriptor->Dacl = nullptr;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetSecurityDescriptorDacl(void *pSecurityDescriptor, BOOL bDaclPresent, void *pDacl, BOOL bDaclDefaulted) {
|
||||
DEBUG_LOG("SetSecurityDescriptorDacl(%p, %u, %p, %u)\n", pSecurityDescriptor, bDaclPresent, pDacl, bDaclDefaulted);
|
||||
if (!pSecurityDescriptor) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *descriptor = static_cast<SecurityDescriptor *>(pSecurityDescriptor);
|
||||
if (descriptor->Revision != SECURITY_DESCRIPTOR_REVISION) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
uint16_t control = static_cast<uint16_t>(descriptor->Control & ~(SE_DACL_PRESENT | SE_DACL_DEFAULTED));
|
||||
if (bDaclPresent) {
|
||||
control = static_cast<uint16_t>(control | SE_DACL_PRESENT);
|
||||
if (bDaclDefaulted) {
|
||||
control = static_cast<uint16_t>(control | SE_DACL_DEFAULTED);
|
||||
}
|
||||
descriptor->Dacl = pDacl;
|
||||
} else {
|
||||
descriptor->Dacl = nullptr;
|
||||
}
|
||||
descriptor->Control = control;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetUserNameA(char *lpBuffer, DWORD *pcbBuffer) {
|
||||
DEBUG_LOG("GetUserNameA(%p, %p)\n", lpBuffer, pcbBuffer);
|
||||
if (!pcbBuffer) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
const char *name = "SYSTEM";
|
||||
size_t needed = std::strlen(name) + 1;
|
||||
if (!lpBuffer || *pcbBuffer < needed) {
|
||||
*pcbBuffer = static_cast<DWORD>(needed);
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
std::memcpy(lpBuffer, name, needed);
|
||||
*pcbBuffer = static_cast<DWORD>(needed);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetUserNameW(uint16_t *lpBuffer, DWORD *pcbBuffer) {
|
||||
DEBUG_LOG("GetUserNameW(%p, %p)\n", lpBuffer, pcbBuffer);
|
||||
if (!pcbBuffer) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
const char16_t name[] = {u'S', u'Y', u'S', u'T', u'E', u'M', u'\0'};
|
||||
size_t needed = (std::size(name));
|
||||
if (!lpBuffer || *pcbBuffer < needed) {
|
||||
*pcbBuffer = static_cast<DWORD>(needed);
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
std::memcpy(lpBuffer, name, needed * sizeof(uint16_t));
|
||||
*pcbBuffer = static_cast<DWORD>(needed);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetTokenInformation(HANDLE TokenHandle, unsigned int TokenInformationClass, void *TokenInformation, DWORD TokenInformationLength) {
|
||||
DEBUG_LOG("STUB: SetTokenInformation(%p, %u, %p, %u)\n", TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength);
|
||||
(void) TokenInformationClass;
|
||||
(void) TokenInformation;
|
||||
(void) TokenInformationLength;
|
||||
auto data = handles::dataFromHandle(TokenHandle, false);
|
||||
if (data.type != handles::TYPE_TOKEN) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void *resolveByName(const char *name) {
|
||||
// winreg.h
|
||||
if (strcmp(name, "RegOpenKeyExA") == 0) return (void *) advapi32::RegOpenKeyExA;
|
||||
if (strcmp(name, "RegOpenKeyExW") == 0) return (void *) advapi32::RegOpenKeyExW;
|
||||
if (strcmp(name, "RegCloseKey") == 0) return (void *) advapi32::RegCloseKey;
|
||||
// wincrypt.h
|
||||
if (strcmp(name, "CryptReleaseContext") == 0) return (void*) advapi32::CryptReleaseContext;
|
||||
if (strcmp(name, "CryptAcquireContextW") == 0) return (void*) advapi32::CryptAcquireContextW;
|
||||
if (strcmp(name, "CryptGenRandom") == 0) return (void*) advapi32::CryptGenRandom;
|
||||
if (strcmp(name, "CryptCreateHash") == 0) return (void*) advapi32::CryptCreateHash;
|
||||
if (strcmp(name, "CryptHashData") == 0) return (void*) advapi32::CryptHashData;
|
||||
if (strcmp(name, "CryptGetHashParam") == 0) return (void*) advapi32::CryptGetHashParam;
|
||||
if (strcmp(name, "CryptDestroyHash") == 0) return (void*) advapi32::CryptDestroyHash;
|
||||
if (strcmp(name, "OpenProcessToken") == 0) return (void*) advapi32::OpenProcessToken;
|
||||
if (strcmp(name, "GetTokenInformation") == 0) return (void*) advapi32::GetTokenInformation;
|
||||
if (strcmp(name, "LookupAccountSidW") == 0) return (void*) advapi32::LookupAccountSidW;
|
||||
if (strcmp(name, "InitializeSecurityDescriptor") == 0) return (void*) advapi32::InitializeSecurityDescriptor;
|
||||
if (strcmp(name, "SetSecurityDescriptorDacl") == 0) return (void*) advapi32::SetSecurityDescriptorDacl;
|
||||
if (strcmp(name, "LookupPrivilegeValueA") == 0) return (void*) advapi32::LookupPrivilegeValueA;
|
||||
if (strcmp(name, "LookupPrivilegeValueW") == 0) return (void*) advapi32::LookupPrivilegeValueW;
|
||||
if (strcmp(name, "AdjustTokenPrivileges") == 0) return (void*) advapi32::AdjustTokenPrivileges;
|
||||
if (strcmp(name, "GetUserNameA") == 0) return (void*) advapi32::GetUserNameA;
|
||||
if (strcmp(name, "GetUserNameW") == 0) return (void*) advapi32::GetUserNameW;
|
||||
if (strcmp(name, "SetTokenInformation") == 0) return (void*) advapi32::SetTokenInformation;
|
||||
if (strcmp(name, "CryptReleaseContext") == 0)
|
||||
return (void *)advapi32::CryptReleaseContext;
|
||||
if (strcmp(name, "CryptAcquireContextW") == 0)
|
||||
return (void *)advapi32::CryptAcquireContextW;
|
||||
if (strcmp(name, "CryptGenRandom") == 0)
|
||||
return (void *)advapi32::CryptGenRandom;
|
||||
if (strcmp(name, "CryptCreateHash") == 0)
|
||||
return (void *)advapi32::CryptCreateHash;
|
||||
if (strcmp(name, "CryptHashData") == 0)
|
||||
return (void *)advapi32::CryptHashData;
|
||||
if (strcmp(name, "CryptGetHashParam") == 0)
|
||||
return (void *)advapi32::CryptGetHashParam;
|
||||
if (strcmp(name, "CryptDestroyHash") == 0)
|
||||
return (void *)advapi32::CryptDestroyHash;
|
||||
|
||||
// winreg.h
|
||||
if (strcmp(name, "RegCreateKeyExA") == 0)
|
||||
return (void *)advapi32::RegCreateKeyExA;
|
||||
if (strcmp(name, "RegCreateKeyExW") == 0)
|
||||
return (void *)advapi32::RegCreateKeyExW;
|
||||
if (strcmp(name, "RegOpenKeyExA") == 0)
|
||||
return (void *)advapi32::RegOpenKeyExA;
|
||||
if (strcmp(name, "RegOpenKeyExW") == 0)
|
||||
return (void *)advapi32::RegOpenKeyExW;
|
||||
if (strcmp(name, "RegQueryValueExA") == 0)
|
||||
return (void *)advapi32::RegQueryValueExA;
|
||||
if (strcmp(name, "RegQueryValueExW") == 0)
|
||||
return (void *)advapi32::RegQueryValueExW;
|
||||
if (strcmp(name, "RegEnumKeyExA") == 0)
|
||||
return (void *)advapi32::RegEnumKeyExA;
|
||||
if (strcmp(name, "RegEnumKeyExW") == 0)
|
||||
return (void *)advapi32::RegEnumKeyExW;
|
||||
if (strcmp(name, "RegCloseKey") == 0)
|
||||
return (void *)advapi32::RegCloseKey;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
wibo::Module lib_advapi32 = {
|
||||
(const char *[]){
|
||||
"advapi32",
|
||||
|
98
dll/advapi32/internal.cpp
Normal file
98
dll/advapi32/internal.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
#include "internal.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr DWORD SECURITY_LOCAL_SYSTEM_RID = 18;
|
||||
|
||||
constexpr BYTE kNtAuthority[6] = {0, 0, 0, 0, 0, 5};
|
||||
|
||||
std::mutex privilegeMapMutex;
|
||||
std::unordered_map<std::string, LUID> privilegeLuidCache;
|
||||
|
||||
LUID generateDeterministicLuid(const std::string &normalizedName) {
|
||||
uint32_t hash = 2166136261u;
|
||||
for (unsigned char ch : normalizedName) {
|
||||
hash ^= ch;
|
||||
hash *= 16777619u;
|
||||
}
|
||||
if (hash == 0) {
|
||||
hash = 1;
|
||||
}
|
||||
LUID luid{};
|
||||
luid.LowPart = hash;
|
||||
luid.HighPart = 0;
|
||||
return luid;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace advapi32 {
|
||||
|
||||
bool isLocalSystemSid(const Sid *sid) {
|
||||
if (!sid) {
|
||||
return false;
|
||||
}
|
||||
if (sid->Revision != 1 || sid->SubAuthorityCount != 1) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < std::size(kNtAuthority); ++i) {
|
||||
if (sid->IdentifierAuthority.Value[i] != kNtAuthority[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return sid->SubAuthority[0] == SECURITY_LOCAL_SYSTEM_RID;
|
||||
}
|
||||
|
||||
bool writeLocalSystemSid(Sid *sid) {
|
||||
if (!sid) {
|
||||
return false;
|
||||
}
|
||||
sid->Revision = 1;
|
||||
sid->SubAuthorityCount = 1;
|
||||
SidIdentifierAuthority authority{};
|
||||
for (size_t i = 0; i < std::size(kNtAuthority); ++i) {
|
||||
authority.Value[i] = kNtAuthority[i];
|
||||
}
|
||||
sid->IdentifierAuthority = authority;
|
||||
sid->SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string normalizePrivilegeName(const std::string &name) {
|
||||
std::string normalized;
|
||||
normalized.reserve(name.size());
|
||||
for (unsigned char ch : name) {
|
||||
normalized.push_back(static_cast<char>(std::tolower(ch)));
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
LUID lookupOrGeneratePrivilegeLuid(const std::string &normalizedName) {
|
||||
std::lock_guard<std::mutex> lock(privilegeMapMutex);
|
||||
static const std::unordered_map<std::string, uint32_t> predefined = {
|
||||
{"se_debug_name", 0x14},
|
||||
{"se_shutdown_name", 0x13},
|
||||
};
|
||||
auto it = privilegeLuidCache.find(normalizedName);
|
||||
if (it != privilegeLuidCache.end()) {
|
||||
return it->second;
|
||||
}
|
||||
LUID luid{};
|
||||
auto predefinedIt = predefined.find(normalizedName);
|
||||
if (predefinedIt != predefined.end()) {
|
||||
luid.LowPart = predefinedIt->second;
|
||||
luid.HighPart = 0;
|
||||
} else {
|
||||
luid = generateDeterministicLuid(normalizedName);
|
||||
}
|
||||
privilegeLuidCache[normalizedName] = luid;
|
||||
return luid;
|
||||
}
|
||||
|
||||
void releaseToken(void *tokenPtr) { delete reinterpret_cast<TokenObject *>(tokenPtr); }
|
||||
|
||||
} // namespace advapi32
|
30
dll/advapi32/internal.h
Normal file
30
dll/advapi32/internal.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "securitybaseapi.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace advapi32 {
|
||||
|
||||
struct TokenObject {
|
||||
HANDLE processHandle;
|
||||
DWORD desiredAccess;
|
||||
};
|
||||
|
||||
using SidIdentifierAuthority = SID_IDENTIFIER_AUTHORITY;
|
||||
|
||||
struct Sid {
|
||||
BYTE Revision;
|
||||
BYTE SubAuthorityCount;
|
||||
SidIdentifierAuthority IdentifierAuthority;
|
||||
DWORD SubAuthority[1];
|
||||
};
|
||||
|
||||
bool isLocalSystemSid(const Sid *sid);
|
||||
bool writeLocalSystemSid(Sid *sid);
|
||||
std::string normalizePrivilegeName(const std::string &name);
|
||||
LUID lookupOrGeneratePrivilegeLuid(const std::string &normalizedName);
|
||||
void releaseToken(void *tokenPtr);
|
||||
|
||||
} // namespace advapi32
|
27
dll/advapi32/processthreadsapi.cpp
Normal file
27
dll/advapi32/processthreadsapi.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "processthreadsapi.h"
|
||||
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
|
||||
namespace advapi32 {
|
||||
|
||||
BOOL WIN_FUNC OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle) {
|
||||
DEBUG_LOG("OpenProcessToken(%p, %u, %p)\n", ProcessHandle, DesiredAccess, TokenHandle);
|
||||
if (!TokenHandle) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *token = new TokenObject;
|
||||
token->processHandle = ProcessHandle;
|
||||
token->desiredAccess = DesiredAccess;
|
||||
handles::Data data;
|
||||
data.type = handles::TYPE_TOKEN;
|
||||
data.ptr = token;
|
||||
data.size = sizeof(TokenObject);
|
||||
*TokenHandle = handles::allocDataHandle(data);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // namespace advapi32
|
9
dll/advapi32/processthreadsapi.h
Normal file
9
dll/advapi32/processthreadsapi.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace advapi32 {
|
||||
|
||||
BOOL WIN_FUNC OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);
|
||||
|
||||
} // namespace advapi32
|
518
dll/advapi32/securitybaseapi.cpp
Normal file
518
dll/advapi32/securitybaseapi.cpp
Normal file
@ -0,0 +1,518 @@
|
||||
#include "securitybaseapi.h"
|
||||
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
namespace {
|
||||
|
||||
using advapi32::Sid;
|
||||
|
||||
constexpr size_t kAceAlignment = 4;
|
||||
constexpr DWORD ERROR_REVISION_MISMATCH = 1306;
|
||||
constexpr DWORD ERROR_INVALID_ACL = 1336;
|
||||
constexpr DWORD ERROR_INVALID_SID = 1337;
|
||||
constexpr DWORD ERROR_ALLOTTED_SPACE_EXCEEDED = 1344;
|
||||
constexpr DWORD ERROR_INVALID_SECURITY_DESCR = 1338;
|
||||
|
||||
size_t alignToDword(size_t value) { return (value + (kAceAlignment - 1)) & ~(kAceAlignment - 1); }
|
||||
|
||||
size_t sidLength(const Sid *sid) {
|
||||
if (!sid) {
|
||||
return 0;
|
||||
}
|
||||
if (sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) {
|
||||
return 0;
|
||||
}
|
||||
size_t base = sizeof(Sid) - sizeof(DWORD);
|
||||
size_t extra = static_cast<size_t>(sid->SubAuthorityCount) * sizeof(DWORD);
|
||||
return base + extra;
|
||||
}
|
||||
|
||||
bool computeAclUsedSize(const ACL *acl, size_t capacity, size_t &used) {
|
||||
if (!acl || capacity < sizeof(ACL)) {
|
||||
return false;
|
||||
}
|
||||
size_t offset = sizeof(ACL);
|
||||
const BYTE *base = reinterpret_cast<const BYTE *>(acl);
|
||||
for (WORD i = 0; i < acl->AceCount; ++i) {
|
||||
if (offset + sizeof(ACE_HEADER) > capacity) {
|
||||
return false;
|
||||
}
|
||||
const auto *header = reinterpret_cast<const ACE_HEADER *>(base + offset);
|
||||
if (header->AceSize < sizeof(ACE_HEADER)) {
|
||||
return false;
|
||||
}
|
||||
size_t aceSize = header->AceSize;
|
||||
if (offset + aceSize > capacity) {
|
||||
return false;
|
||||
}
|
||||
offset += aceSize;
|
||||
}
|
||||
used = offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct SidAndAttributes {
|
||||
Sid *SidPtr;
|
||||
DWORD Attributes;
|
||||
};
|
||||
|
||||
struct TokenUserData {
|
||||
SidAndAttributes User;
|
||||
};
|
||||
|
||||
struct TokenStatisticsData {
|
||||
LUID tokenId{};
|
||||
LUID authenticationId{};
|
||||
LARGE_INTEGER expirationTime{};
|
||||
DWORD tokenType = 0;
|
||||
DWORD impersonationLevel = 0;
|
||||
DWORD dynamicCharged = 0;
|
||||
DWORD dynamicAvailable = 0;
|
||||
DWORD groupCount = 0;
|
||||
DWORD privilegeCount = 0;
|
||||
LUID modifiedId{};
|
||||
};
|
||||
|
||||
struct TokenPrimaryGroupStub {
|
||||
Sid *PrimaryGroup;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace advapi32 {
|
||||
|
||||
BOOL WIN_FUNC InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision) {
|
||||
DEBUG_LOG("InitializeAcl(%p, %u, %u)\n", pAcl, nAclLength, dwAclRevision);
|
||||
if (!pAcl) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
if (nAclLength < sizeof(ACL) || nAclLength > std::numeric_limits<WORD>::max() || (nAclLength & 0x3) != 0) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
BYTE revision = static_cast<BYTE>(dwAclRevision);
|
||||
switch (revision) {
|
||||
case ACL_REVISION1:
|
||||
case ACL_REVISION2:
|
||||
case ACL_REVISION3:
|
||||
case ACL_REVISION4:
|
||||
break;
|
||||
default:
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
pAcl->AclRevision = revision;
|
||||
pAcl->Sbz1 = 0;
|
||||
pAcl->AclSize = static_cast<WORD>(sizeof(ACL));
|
||||
pAcl->AceCount = 0;
|
||||
pAcl->Sbz2 = static_cast<WORD>(nAclLength);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid) {
|
||||
DEBUG_LOG("AddAccessAllowedAce(%p, %u, 0x%x, %p)\n", pAcl, dwAceRevision, AccessMask, pSid);
|
||||
if (!pAcl || !pSid) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
BYTE revision = static_cast<BYTE>(dwAceRevision);
|
||||
switch (revision) {
|
||||
case ACL_REVISION1:
|
||||
case ACL_REVISION2:
|
||||
case ACL_REVISION3:
|
||||
case ACL_REVISION4:
|
||||
break;
|
||||
default:
|
||||
wibo::lastError = ERROR_REVISION_MISMATCH;
|
||||
return FALSE;
|
||||
}
|
||||
if (pAcl->AclRevision < revision) {
|
||||
wibo::lastError = ERROR_REVISION_MISMATCH;
|
||||
return FALSE;
|
||||
}
|
||||
if (pAcl->AceCount == std::numeric_limits<WORD>::max()) {
|
||||
wibo::lastError = ERROR_ALLOTTED_SPACE_EXCEEDED;
|
||||
return FALSE;
|
||||
}
|
||||
size_t capacity = pAcl->Sbz2 ? pAcl->Sbz2 : pAcl->AclSize;
|
||||
if (capacity < sizeof(ACL)) {
|
||||
wibo::lastError = ERROR_INVALID_ACL;
|
||||
return FALSE;
|
||||
}
|
||||
size_t used = 0;
|
||||
if (!computeAclUsedSize(pAcl, capacity, used)) {
|
||||
wibo::lastError = ERROR_INVALID_ACL;
|
||||
return FALSE;
|
||||
}
|
||||
if (used > pAcl->AclSize) {
|
||||
// Clamp to the computed size to avoid propagating inconsistent data.
|
||||
pAcl->AclSize = static_cast<WORD>(used);
|
||||
}
|
||||
const auto *sid = reinterpret_cast<const Sid *>(pSid);
|
||||
size_t sidLen = sidLength(sid);
|
||||
if (sidLen == 0 || sidLen > capacity) {
|
||||
wibo::lastError = ERROR_INVALID_SID;
|
||||
return FALSE;
|
||||
}
|
||||
size_t aceSize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidLen;
|
||||
aceSize = alignToDword(aceSize);
|
||||
if (aceSize > std::numeric_limits<WORD>::max()) {
|
||||
wibo::lastError = ERROR_INVALID_SID;
|
||||
return FALSE;
|
||||
}
|
||||
if (used + aceSize > capacity) {
|
||||
wibo::lastError = ERROR_ALLOTTED_SPACE_EXCEEDED;
|
||||
return FALSE;
|
||||
}
|
||||
auto *dest = reinterpret_cast<BYTE *>(pAcl) + used;
|
||||
std::memset(dest, 0, aceSize);
|
||||
auto *ace = reinterpret_cast<ACCESS_ALLOWED_ACE *>(dest);
|
||||
ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
|
||||
ace->Header.AceFlags = 0;
|
||||
ace->Header.AceSize = static_cast<WORD>(aceSize);
|
||||
ace->Mask = AccessMask;
|
||||
std::memcpy(&ace->SidStart, sid, sidLen);
|
||||
pAcl->AceCount = static_cast<WORD>(pAcl->AceCount + 1);
|
||||
pAcl->AclSize = static_cast<WORD>(used + aceSize);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC FindFirstFreeAce(PACL pAcl, LPVOID *pAce) {
|
||||
DEBUG_LOG("FindFirstFreeAce(%p, %p)\n", pAcl, pAce);
|
||||
if (!pAce) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
*pAce = nullptr;
|
||||
if (!pAcl) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
size_t capacity = pAcl->Sbz2 ? pAcl->Sbz2 : pAcl->AclSize;
|
||||
size_t used = 0;
|
||||
if (!computeAclUsedSize(pAcl, capacity, used)) {
|
||||
wibo::lastError = ERROR_INVALID_ACL;
|
||||
return FALSE;
|
||||
}
|
||||
*pAce = reinterpret_cast<BYTE *>(pAcl) + used;
|
||||
pAcl->AclSize = static_cast<WORD>(std::max<size_t>(pAcl->AclSize, used));
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL *pDacl,
|
||||
LPBOOL lpbDaclDefaulted) {
|
||||
DEBUG_LOG("GetSecurityDescriptorDacl(%p, %p, %p, %p)\n", pSecurityDescriptor, lpbDaclPresent, pDacl,
|
||||
lpbDaclDefaulted);
|
||||
if (!pSecurityDescriptor) {
|
||||
wibo::lastError = ERROR_INVALID_SECURITY_DESCR;
|
||||
return FALSE;
|
||||
}
|
||||
if (!lpbDaclPresent) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
if (pSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION) {
|
||||
wibo::lastError = ERROR_INVALID_SECURITY_DESCR;
|
||||
return FALSE;
|
||||
}
|
||||
BOOL hasDacl = (pSecurityDescriptor->Control & SE_DACL_PRESENT) ? TRUE : FALSE;
|
||||
*lpbDaclPresent = hasDacl;
|
||||
if (!hasDacl) {
|
||||
if (pDacl) {
|
||||
*pDacl = nullptr;
|
||||
}
|
||||
if (lpbDaclDefaulted) {
|
||||
*lpbDaclDefaulted = FALSE;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
if (pDacl) {
|
||||
*pDacl = pSecurityDescriptor->Dacl;
|
||||
}
|
||||
if (lpbDaclDefaulted) {
|
||||
*lpbDaclDefaulted = (pSecurityDescriptor->Control & SE_DACL_DEFAULTED) ? TRUE : FALSE;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PSID_IDENTIFIER_AUTHORITY WIN_FUNC GetSidIdentifierAuthority(PSID pSid) {
|
||||
DEBUG_LOG("GetSidIdentifierAuthority(%p)\n", pSid);
|
||||
if (!pSid) {
|
||||
wibo::lastError = ERROR_INVALID_SID;
|
||||
return nullptr;
|
||||
}
|
||||
auto *sid = reinterpret_cast<Sid *>(pSid);
|
||||
if (sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) {
|
||||
wibo::lastError = ERROR_INVALID_SID;
|
||||
return nullptr;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return reinterpret_cast<PSID_IDENTIFIER_AUTHORITY>(&sid->IdentifierAuthority);
|
||||
}
|
||||
|
||||
PUCHAR WIN_FUNC GetSidSubAuthorityCount(PSID pSid) {
|
||||
DEBUG_LOG("GetSidSubAuthorityCount(%p)\n", pSid);
|
||||
if (!pSid) {
|
||||
wibo::lastError = ERROR_INVALID_SID;
|
||||
return nullptr;
|
||||
}
|
||||
auto *sid = reinterpret_cast<Sid *>(pSid);
|
||||
if (sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) {
|
||||
wibo::lastError = ERROR_INVALID_SID;
|
||||
return nullptr;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return &sid->SubAuthorityCount;
|
||||
}
|
||||
|
||||
PDWORD WIN_FUNC GetSidSubAuthority(PSID pSid, DWORD nSubAuthority) {
|
||||
DEBUG_LOG("GetSidSubAuthority(%p, %u)\n", pSid, nSubAuthority);
|
||||
if (!pSid) {
|
||||
wibo::lastError = ERROR_INVALID_SID;
|
||||
return nullptr;
|
||||
}
|
||||
auto *sid = reinterpret_cast<Sid *>(pSid);
|
||||
if (sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES || nSubAuthority >= sid->SubAuthorityCount) {
|
||||
wibo::lastError = ERROR_INVALID_SID;
|
||||
return nullptr;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return &sid->SubAuthority[nSubAuthority];
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC ImpersonateLoggedOnUser(HANDLE hToken) {
|
||||
DEBUG_LOG("STUB: ImpersonateLoggedOnUser(%p)\n", hToken);
|
||||
(void)hToken;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC DuplicateTokenEx(HANDLE hExistingToken, DWORD dwDesiredAccess, void *lpTokenAttributes,
|
||||
DWORD ImpersonationLevel, DWORD TokenType, PHANDLE phNewToken) {
|
||||
DEBUG_LOG("DuplicateTokenEx(%p, 0x%x, %p, %u, %u, %p)\n", hExistingToken, dwDesiredAccess, lpTokenAttributes,
|
||||
ImpersonationLevel, TokenType, phNewToken);
|
||||
(void)lpTokenAttributes;
|
||||
(void)ImpersonationLevel;
|
||||
(void)TokenType;
|
||||
if (!phNewToken) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
handles::Data existingData = handles::dataFromHandle(hExistingToken, false);
|
||||
if (existingData.type != handles::TYPE_TOKEN || existingData.ptr == nullptr) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
auto *existingToken = static_cast<TokenObject *>(existingData.ptr);
|
||||
auto *newToken = new TokenObject(*existingToken);
|
||||
if (dwDesiredAccess != 0) {
|
||||
newToken->desiredAccess = dwDesiredAccess;
|
||||
}
|
||||
handles::Data newData;
|
||||
newData.type = handles::TYPE_TOKEN;
|
||||
newData.ptr = newToken;
|
||||
newData.size = sizeof(TokenObject);
|
||||
*phNewToken = handles::allocDataHandle(newData);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid) {
|
||||
DEBUG_LOG("CopySid(%u, %p, %p)\n", nDestinationSidLength, pDestinationSid, pSourceSid);
|
||||
if (!pDestinationSid || !pSourceSid) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *source = reinterpret_cast<Sid *>(pSourceSid);
|
||||
size_t required = sidLength(source);
|
||||
if (required == 0 || required > nDestinationSidLength) {
|
||||
wibo::lastError = ERROR_ALLOTTED_SPACE_EXCEEDED;
|
||||
return FALSE;
|
||||
}
|
||||
std::memcpy(pDestinationSid, pSourceSid, required);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION SecurityInformation,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor) {
|
||||
DEBUG_LOG("STUB: SetKernelObjectSecurity(%p, 0x%x, %p)\n", Handle, SecurityInformation, SecurityDescriptor);
|
||||
(void)SecurityInformation;
|
||||
if (!SecurityDescriptor) {
|
||||
wibo::lastError = ERROR_INVALID_SECURITY_DESCR;
|
||||
return FALSE;
|
||||
}
|
||||
auto data = handles::dataFromHandle(Handle, false);
|
||||
if (data.type == handles::TYPE_UNUSED) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision) {
|
||||
DEBUG_LOG("InitializeSecurityDescriptor(%p, %u)\n", pSecurityDescriptor, dwRevision);
|
||||
if (!pSecurityDescriptor || dwRevision != SECURITY_DESCRIPTOR_REVISION) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
pSecurityDescriptor->Revision = static_cast<BYTE>(dwRevision);
|
||||
pSecurityDescriptor->Sbz1 = 0;
|
||||
pSecurityDescriptor->Control = 0;
|
||||
pSecurityDescriptor->Owner = nullptr;
|
||||
pSecurityDescriptor->Group = nullptr;
|
||||
pSecurityDescriptor->Sacl = nullptr;
|
||||
pSecurityDescriptor->Dacl = nullptr;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl,
|
||||
BOOL bDaclDefaulted) {
|
||||
DEBUG_LOG("SetSecurityDescriptorDacl(%p, %u, %p, %u)\n", pSecurityDescriptor, bDaclPresent, pDacl, bDaclDefaulted);
|
||||
if (!pSecurityDescriptor || pSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
WORD control = static_cast<WORD>(pSecurityDescriptor->Control & ~(SE_DACL_PRESENT | SE_DACL_DEFAULTED));
|
||||
if (bDaclPresent) {
|
||||
control = static_cast<WORD>(control | SE_DACL_PRESENT);
|
||||
if (bDaclDefaulted) {
|
||||
control = static_cast<WORD>(control | SE_DACL_DEFAULTED);
|
||||
}
|
||||
pSecurityDescriptor->Dacl = pDacl;
|
||||
} else {
|
||||
pSecurityDescriptor->Dacl = nullptr;
|
||||
}
|
||||
pSecurityDescriptor->Control = control;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass,
|
||||
LPVOID TokenInformation, DWORD TokenInformationLength, LPDWORD ReturnLength) {
|
||||
DEBUG_LOG("GetTokenInformation(%p, %u, %p, %u, %p)\n", TokenHandle, TokenInformationClass, TokenInformation,
|
||||
TokenInformationLength, ReturnLength);
|
||||
if (!ReturnLength) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
auto data = handles::dataFromHandle(TokenHandle, false);
|
||||
if (data.type != handles::TYPE_TOKEN) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
*ReturnLength = 0;
|
||||
if (TokenInformationClass == TOKEN_INFORMATION_CLASS::TokenUser) {
|
||||
constexpr size_t sidSize = sizeof(Sid);
|
||||
constexpr size_t tokenUserSize = sizeof(TokenUserData);
|
||||
DWORD required = static_cast<DWORD>(tokenUserSize + sidSize);
|
||||
*ReturnLength = required;
|
||||
if (!TokenInformation || TokenInformationLength < required) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *tokenUser = reinterpret_cast<TokenUserData *>(TokenInformation);
|
||||
auto *sid = reinterpret_cast<Sid *>(reinterpret_cast<BYTE *>(TokenInformation) + tokenUserSize);
|
||||
if (!writeLocalSystemSid(sid)) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
tokenUser->User.SidPtr = sid;
|
||||
tokenUser->User.Attributes = 0;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
if (TokenInformationClass == TOKEN_INFORMATION_CLASS::TokenStatistics) {
|
||||
DWORD required = sizeof(TokenStatisticsData);
|
||||
*ReturnLength = required;
|
||||
if (!TokenInformation || TokenInformationLength < required) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *stats = reinterpret_cast<TokenStatisticsData *>(TokenInformation);
|
||||
*stats = TokenStatisticsData{};
|
||||
stats->tokenType = 1; // TokenPrimary
|
||||
stats->impersonationLevel = 0; // SecurityAnonymous
|
||||
stats->tokenId.LowPart = 1;
|
||||
stats->authenticationId.LowPart = 1;
|
||||
stats->modifiedId.LowPart = 1;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
if (TokenInformationClass == TOKEN_INFORMATION_CLASS::TokenElevation) {
|
||||
DWORD required = sizeof(DWORD);
|
||||
*ReturnLength = required;
|
||||
if (!TokenInformation || TokenInformationLength < required) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
*reinterpret_cast<DWORD *>(TokenInformation) = 0; // not elevated
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
if (TokenInformationClass == TOKEN_INFORMATION_CLASS::TokenPrimaryGroup) {
|
||||
DWORD required = static_cast<DWORD>(sizeof(TokenPrimaryGroupStub) + sizeof(Sid));
|
||||
*ReturnLength = required;
|
||||
if (!TokenInformation || TokenInformationLength < required) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *groupInfo = reinterpret_cast<TokenPrimaryGroupStub *>(TokenInformation);
|
||||
auto *sid = reinterpret_cast<Sid *>(reinterpret_cast<BYTE *>(TokenInformation) + sizeof(TokenPrimaryGroupStub));
|
||||
if (!writeLocalSystemSid(sid)) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
groupInfo->PrimaryGroup = sid;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
wibo::lastError = ERROR_NOT_SUPPORTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState,
|
||||
DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, LPDWORD ReturnLength) {
|
||||
DEBUG_LOG("AdjustTokenPrivileges(%p, %u, %p, %u, %p, %p)\n", TokenHandle, DisableAllPrivileges, NewState,
|
||||
BufferLength, PreviousState, ReturnLength);
|
||||
(void)TokenHandle;
|
||||
(void)DisableAllPrivileges;
|
||||
(void)NewState;
|
||||
(void)BufferLength;
|
||||
(void)PreviousState;
|
||||
(void)ReturnLength;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass,
|
||||
LPVOID TokenInformation, DWORD TokenInformationLength) {
|
||||
DEBUG_LOG("STUB: SetTokenInformation(%p, %u, %p, %u)\n", TokenHandle, TokenInformationClass, TokenInformation,
|
||||
TokenInformationLength);
|
||||
(void)TokenInformationClass;
|
||||
(void)TokenInformation;
|
||||
(void)TokenInformationLength;
|
||||
auto data = handles::dataFromHandle(TokenHandle, false);
|
||||
if (data.type != handles::TYPE_TOKEN) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // namespace advapi32
|
109
dll/advapi32/securitybaseapi.h
Normal file
109
dll/advapi32/securitybaseapi.h
Normal file
@ -0,0 +1,109 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
struct ACL {
|
||||
BYTE AclRevision;
|
||||
BYTE Sbz1;
|
||||
WORD AclSize;
|
||||
WORD AceCount;
|
||||
WORD Sbz2;
|
||||
};
|
||||
|
||||
struct ACE_HEADER {
|
||||
BYTE AceType;
|
||||
BYTE AceFlags;
|
||||
WORD AceSize;
|
||||
};
|
||||
|
||||
struct ACCESS_ALLOWED_ACE {
|
||||
ACE_HEADER Header;
|
||||
DWORD Mask;
|
||||
DWORD SidStart;
|
||||
};
|
||||
|
||||
struct SID_IDENTIFIER_AUTHORITY {
|
||||
BYTE Value[6];
|
||||
};
|
||||
|
||||
struct SECURITY_DESCRIPTOR {
|
||||
BYTE Revision;
|
||||
BYTE Sbz1;
|
||||
WORD Control;
|
||||
void *Owner;
|
||||
void *Group;
|
||||
ACL *Sacl;
|
||||
ACL *Dacl;
|
||||
};
|
||||
|
||||
using PSECURITY_DESCRIPTOR = SECURITY_DESCRIPTOR *;
|
||||
using PACL = ACL *;
|
||||
using PSID_IDENTIFIER_AUTHORITY = SID_IDENTIFIER_AUTHORITY *;
|
||||
using SECURITY_INFORMATION = DWORD;
|
||||
|
||||
constexpr DWORD SECURITY_DESCRIPTOR_REVISION = 1;
|
||||
constexpr WORD SE_DACL_PRESENT = 0x0004;
|
||||
constexpr WORD SE_DACL_DEFAULTED = 0x0008;
|
||||
|
||||
constexpr BYTE ACL_REVISION1 = 1;
|
||||
constexpr BYTE ACL_REVISION2 = 2;
|
||||
constexpr BYTE ACL_REVISION3 = 3;
|
||||
constexpr BYTE ACL_REVISION4 = 4;
|
||||
constexpr BYTE ACL_REVISION = ACL_REVISION2;
|
||||
constexpr BYTE ACL_REVISION_DS = ACL_REVISION4;
|
||||
constexpr BYTE ACCESS_ALLOWED_ACE_TYPE = 0x00;
|
||||
constexpr BYTE SID_MAX_SUB_AUTHORITIES = 15;
|
||||
|
||||
struct TOKEN_PRIVILEGES;
|
||||
using PTOKEN_PRIVILEGES = TOKEN_PRIVILEGES *;
|
||||
|
||||
enum TOKEN_INFORMATION_CLASS : DWORD {
|
||||
TokenUser = 1,
|
||||
TokenGroups,
|
||||
TokenPrivileges,
|
||||
TokenOwner,
|
||||
TokenPrimaryGroup,
|
||||
TokenDefaultDacl,
|
||||
TokenSource,
|
||||
TokenType,
|
||||
TokenImpersonationLevel,
|
||||
TokenStatistics,
|
||||
TokenRestrictedSids,
|
||||
TokenSessionId,
|
||||
TokenGroupsAndPrivileges,
|
||||
TokenSessionReference,
|
||||
TokenSandBoxInert,
|
||||
TokenAuditPolicy,
|
||||
TokenOrigin,
|
||||
TokenElevationType,
|
||||
TokenLinkedToken,
|
||||
TokenElevation = 20,
|
||||
};
|
||||
|
||||
namespace advapi32 {
|
||||
|
||||
BOOL WIN_FUNC InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision);
|
||||
BOOL WIN_FUNC AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid);
|
||||
BOOL WIN_FUNC FindFirstFreeAce(PACL pAcl, LPVOID *pAce);
|
||||
PSID_IDENTIFIER_AUTHORITY WIN_FUNC GetSidIdentifierAuthority(PSID pSid);
|
||||
PUCHAR WIN_FUNC GetSidSubAuthorityCount(PSID pSid);
|
||||
PDWORD WIN_FUNC GetSidSubAuthority(PSID pSid, DWORD nSubAuthority);
|
||||
BOOL WIN_FUNC ImpersonateLoggedOnUser(HANDLE hToken);
|
||||
BOOL WIN_FUNC DuplicateTokenEx(HANDLE hExistingToken, DWORD dwDesiredAccess, void *lpTokenAttributes,
|
||||
DWORD ImpersonationLevel, DWORD TokenType, PHANDLE phNewToken);
|
||||
BOOL WIN_FUNC CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid);
|
||||
BOOL WIN_FUNC GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL *pDacl,
|
||||
LPBOOL lpbDaclDefaulted);
|
||||
BOOL WIN_FUNC SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION SecurityInformation,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor);
|
||||
BOOL WIN_FUNC InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision);
|
||||
BOOL WIN_FUNC SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl,
|
||||
BOOL bDaclDefaulted);
|
||||
BOOL WIN_FUNC GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass,
|
||||
LPVOID TokenInformation, DWORD TokenInformationLength, LPDWORD ReturnLength);
|
||||
BOOL WIN_FUNC AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState,
|
||||
DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, LPDWORD ReturnLength);
|
||||
BOOL WIN_FUNC SetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass,
|
||||
LPVOID TokenInformation, DWORD TokenInformationLength);
|
||||
|
||||
} // namespace advapi32
|
117
dll/advapi32/winbase.cpp
Normal file
117
dll/advapi32/winbase.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
#include "winbase.h"
|
||||
|
||||
#include "errors.h"
|
||||
#include "internal.h"
|
||||
#include "strutil.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr WCHAR kAccountSystem[] = {u'S', u'Y', u'S', u'T', u'E', u'M', u'\0'};
|
||||
constexpr WCHAR kDomainNtAuthority[] = {u'N', u'T', u' ', u'A', u'U', u'T', u'H', u'O', u'R', u'I', u'T', u'Y', u'\0'};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace advapi32 {
|
||||
|
||||
BOOL WIN_FUNC LookupAccountSidW(LPCWSTR lpSystemName, PSID Sid, LPWSTR Name, LPDWORD cchName,
|
||||
LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, SID_NAME_USE *peUse) {
|
||||
std::string systemName = lpSystemName ? wideStringToString(lpSystemName) : std::string("(null)");
|
||||
DEBUG_LOG("LookupAccountSidW(%s, %p, %p, %p, %p, %p, %p)\n", systemName.c_str(), Sid, Name, cchName,
|
||||
ReferencedDomainName, cchReferencedDomainName, peUse);
|
||||
if (!Sid || !cchName || !cchReferencedDomainName || !peUse) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *sidStruct = reinterpret_cast<const ::advapi32::Sid *>(Sid);
|
||||
if (!isLocalSystemSid(sidStruct)) {
|
||||
wibo::lastError = ERROR_NONE_MAPPED;
|
||||
return FALSE;
|
||||
}
|
||||
DWORD requiredAccount = static_cast<DWORD>(wstrlen(kAccountSystem));
|
||||
DWORD requiredDomain = static_cast<DWORD>(wstrlen(kDomainNtAuthority));
|
||||
if (!Name || *cchName <= requiredAccount || !ReferencedDomainName || *cchReferencedDomainName <= requiredDomain) {
|
||||
*cchName = requiredAccount + 1;
|
||||
*cchReferencedDomainName = requiredDomain + 1;
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
std::copy_n(kAccountSystem, requiredAccount + 1, Name);
|
||||
std::copy_n(kDomainNtAuthority, requiredDomain + 1, ReferencedDomainName);
|
||||
*peUse = SidTypeWellKnownGroup;
|
||||
*cchName = requiredAccount;
|
||||
*cchReferencedDomainName = requiredDomain;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid) {
|
||||
DEBUG_LOG("LookupPrivilegeValueA(%s, %s, %p)\n", lpSystemName ? lpSystemName : "(null)", lpName ? lpName : "(null)",
|
||||
lpLuid);
|
||||
(void)lpSystemName; // only local lookup supported
|
||||
if (!lpName || !lpLuid) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
std::string normalized = normalizePrivilegeName(lpName);
|
||||
LUID luid = lookupOrGeneratePrivilegeLuid(normalized);
|
||||
*lpLuid = luid;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid) {
|
||||
DEBUG_LOG("LookupPrivilegeValueW(%p, %p, %p)\n", lpSystemName, lpName, lpLuid);
|
||||
(void)lpSystemName; // only local lookup supported
|
||||
if (!lpName || !lpLuid) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
std::string ansiName = wideStringToString(lpName);
|
||||
std::string normalized = normalizePrivilegeName(ansiName);
|
||||
LUID luid = lookupOrGeneratePrivilegeLuid(normalized);
|
||||
*lpLuid = luid;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer) {
|
||||
DEBUG_LOG("GetUserNameA(%p, %p)\n", lpBuffer, pcbBuffer);
|
||||
if (!pcbBuffer) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
const char *name = "SYSTEM";
|
||||
size_t needed = std::strlen(name) + 1;
|
||||
if (!lpBuffer || *pcbBuffer < needed) {
|
||||
*pcbBuffer = static_cast<DWORD>(needed);
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
std::memcpy(lpBuffer, name, needed);
|
||||
*pcbBuffer = static_cast<DWORD>(needed);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer) {
|
||||
DEBUG_LOG("GetUserNameW(%p, %p)\n", lpBuffer, pcbBuffer);
|
||||
if (!pcbBuffer) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
size_t needed = wstrlen(kAccountSystem) + 1;
|
||||
if (!lpBuffer || *pcbBuffer < needed) {
|
||||
*pcbBuffer = static_cast<DWORD>(needed);
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
std::memcpy(lpBuffer, kAccountSystem, needed * sizeof(WCHAR));
|
||||
*pcbBuffer = static_cast<DWORD>(needed);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // namespace advapi32
|
27
dll/advapi32/winbase.h
Normal file
27
dll/advapi32/winbase.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
enum SID_NAME_USE : DWORD {
|
||||
SidTypeUser = 1,
|
||||
SidTypeGroup,
|
||||
SidTypeDomain,
|
||||
SidTypeAlias,
|
||||
SidTypeWellKnownGroup,
|
||||
SidTypeDeletedAccount,
|
||||
SidTypeInvalid,
|
||||
SidTypeUnknown,
|
||||
SidTypeComputer,
|
||||
SidTypeLabel
|
||||
};
|
||||
|
||||
namespace advapi32 {
|
||||
|
||||
BOOL WIN_FUNC LookupAccountSidW(LPCWSTR lpSystemName, PSID Sid, LPWSTR Name, LPDWORD cchName,
|
||||
LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, SID_NAME_USE *peUse);
|
||||
BOOL WIN_FUNC LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid);
|
||||
BOOL WIN_FUNC LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid);
|
||||
BOOL WIN_FUNC GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer);
|
||||
BOOL WIN_FUNC GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer);
|
||||
|
||||
} // namespace advapi32
|
@ -33,11 +33,11 @@ constexpr PredefinedKeyInfo kPredefinedKeyInfos[] = {
|
||||
|
||||
constexpr size_t kPredefinedKeyCount = std::size(kPredefinedKeyInfos);
|
||||
|
||||
std::mutex registryMutex;
|
||||
bool predefinedHandlesInitialized = false;
|
||||
RegistryKeyHandleData predefinedHandles[kPredefinedKeyCount];
|
||||
bool registryInitialized = false;
|
||||
std::unordered_set<std::u16string> existingKeys;
|
||||
std::mutex g_registryMutex;
|
||||
bool g_predefinedHandlesInitialized = false;
|
||||
RegistryKeyHandleData g_predefinedHandles[kPredefinedKeyCount];
|
||||
bool g_registryInitialized = false;
|
||||
std::unordered_set<std::u16string> g_existingKeys;
|
||||
|
||||
std::u16string canonicalizeKeySegment(const std::u16string &input) {
|
||||
std::u16string result;
|
||||
@ -75,20 +75,20 @@ std::u16string canonicalizeKeySegment(LPCWSTR input) {
|
||||
}
|
||||
|
||||
void initializePredefinedHandlesLocked() {
|
||||
if (predefinedHandlesInitialized) {
|
||||
if (g_predefinedHandlesInitialized) {
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < kPredefinedKeyCount; ++i) {
|
||||
predefinedHandles[i].canonicalPath = canonicalizeKeySegment(std::u16string(kPredefinedKeyInfos[i].name));
|
||||
predefinedHandles[i].predefined = true;
|
||||
g_predefinedHandles[i].canonicalPath = canonicalizeKeySegment(std::u16string(kPredefinedKeyInfos[i].name));
|
||||
g_predefinedHandles[i].predefined = true;
|
||||
}
|
||||
predefinedHandlesInitialized = true;
|
||||
g_predefinedHandlesInitialized = true;
|
||||
}
|
||||
|
||||
RegistryKeyHandleData *predefinedHandleForValue(uintptr_t value) {
|
||||
for (size_t i = 0; i < kPredefinedKeyCount; ++i) {
|
||||
if (kPredefinedKeyInfos[i].value == value) {
|
||||
return &predefinedHandles[i];
|
||||
return &g_predefinedHandles[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
@ -121,20 +121,110 @@ bool isPredefinedKeyHandle(HKEY hKey) {
|
||||
}
|
||||
|
||||
void ensureRegistryInitializedLocked() {
|
||||
if (registryInitialized) {
|
||||
if (g_registryInitialized) {
|
||||
return;
|
||||
}
|
||||
initializePredefinedHandlesLocked();
|
||||
for (size_t i = 0; i < kPredefinedKeyCount; ++i) {
|
||||
existingKeys.insert(predefinedHandles[i].canonicalPath);
|
||||
for (auto &g_predefinedHandle : g_predefinedHandles) {
|
||||
g_existingKeys.insert(g_predefinedHandle.canonicalPath);
|
||||
}
|
||||
registryInitialized = true;
|
||||
g_registryInitialized = true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace advapi32 {
|
||||
|
||||
LSTATUS WIN_FUNC RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, DWORD dwOptions,
|
||||
REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult,
|
||||
LPDWORD lpdwDisposition) {
|
||||
std::string subKeyString = lpSubKey ? wideStringToString(lpSubKey) : std::string("(null)");
|
||||
std::string classString = lpClass ? wideStringToString(lpClass) : std::string("(null)");
|
||||
DEBUG_LOG("RegCreateKeyExW(%p, %s, %u, %s, 0x%x, 0x%x, %p, %p, %p)\n", hKey, subKeyString.c_str(), Reserved,
|
||||
classString.c_str(), dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
|
||||
(void)lpClass;
|
||||
(void)lpSecurityAttributes;
|
||||
if (!phkResult) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
*phkResult = nullptr;
|
||||
if (Reserved != 0) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
if (dwOptions != 0) {
|
||||
DEBUG_LOG("RegCreateKeyExW: unsupported options 0x%x\n", dwOptions);
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
REGSAM sanitizedAccess = samDesired & ~(KEY_WOW64_64KEY | KEY_WOW64_32KEY);
|
||||
if (sanitizedAccess != samDesired) {
|
||||
DEBUG_LOG("RegCreateKeyExW: ignoring WOW64 access mask 0x%x\n", samDesired ^ sanitizedAccess);
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(g_registryMutex);
|
||||
ensureRegistryInitializedLocked();
|
||||
RegistryKeyHandleData *baseHandle = handleDataFromHKeyLocked(hKey);
|
||||
if (!baseHandle) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return ERROR_INVALID_HANDLE;
|
||||
}
|
||||
std::u16string targetPath = baseHandle->canonicalPath;
|
||||
bool targetingBase = true;
|
||||
if (lpSubKey && lpSubKey[0] != 0) {
|
||||
std::u16string subComponent = canonicalizeKeySegment(lpSubKey);
|
||||
if (!subComponent.empty()) {
|
||||
targetingBase = false;
|
||||
if (!targetPath.empty()) {
|
||||
targetPath.push_back(u'\\');
|
||||
}
|
||||
targetPath.append(subComponent);
|
||||
}
|
||||
}
|
||||
if (targetPath.empty()) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return ERROR_INVALID_HANDLE;
|
||||
}
|
||||
bool existed = g_existingKeys.find(targetPath) != g_existingKeys.end();
|
||||
if (!existed) {
|
||||
g_existingKeys.insert(targetPath);
|
||||
}
|
||||
if (lpdwDisposition) {
|
||||
*lpdwDisposition = existed ? REG_OPENED_EXISTING_KEY : REG_CREATED_NEW_KEY;
|
||||
}
|
||||
if (targetingBase) {
|
||||
*phkResult = hKey;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
auto *handleData = new RegistryKeyHandleData;
|
||||
handleData->canonicalPath = targetPath;
|
||||
handleData->predefined = false;
|
||||
auto handle = handles::allocDataHandle({handles::TYPE_REGISTRY_KEY, handleData, sizeof(*handleData)});
|
||||
*phkResult = reinterpret_cast<HKEY>(handle);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
LSTATUS WIN_FUNC RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions,
|
||||
REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult,
|
||||
LPDWORD lpdwDisposition) {
|
||||
DEBUG_LOG("RegCreateKeyExA(%p, %s, %u, %s, 0x%x, 0x%x, %p, %p, %p)\n", hKey, lpSubKey ? lpSubKey : "(null)",
|
||||
Reserved, lpClass ? lpClass : "(null)", dwOptions, samDesired, lpSecurityAttributes, phkResult,
|
||||
lpdwDisposition);
|
||||
std::vector<uint16_t> subKeyWideStorage;
|
||||
if (lpSubKey) {
|
||||
subKeyWideStorage = stringToWideString(lpSubKey);
|
||||
}
|
||||
std::vector<uint16_t> classWideStorage;
|
||||
if (lpClass) {
|
||||
classWideStorage = stringToWideString(lpClass);
|
||||
}
|
||||
return RegCreateKeyExW(hKey, lpSubKey ? reinterpret_cast<LPCWSTR>(subKeyWideStorage.data()) : nullptr, Reserved,
|
||||
lpClass ? reinterpret_cast<LPWSTR>(classWideStorage.data()) : nullptr, dwOptions, samDesired,
|
||||
lpSecurityAttributes, phkResult, lpdwDisposition);
|
||||
}
|
||||
|
||||
LSTATUS WIN_FUNC RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) {
|
||||
std::string subKeyString = lpSubKey ? wideStringToString(lpSubKey) : std::string("(null)");
|
||||
DEBUG_LOG("RegOpenKeyExW(%p, %s, %u, 0x%x, %p)\n", hKey, subKeyString.c_str(), ulOptions, samDesired, phkResult);
|
||||
@ -155,7 +245,7 @@ LSTATUS WIN_FUNC RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REG
|
||||
DEBUG_LOG("RegOpenKeyExW: ignoring WOW64 access mask 0x%x\n", samDesired ^ sanitizedAccess);
|
||||
}
|
||||
(void)sanitizedAccess;
|
||||
std::lock_guard<std::mutex> lock(registryMutex);
|
||||
std::lock_guard<std::mutex> lock(g_registryMutex);
|
||||
ensureRegistryInitializedLocked();
|
||||
RegistryKeyHandleData *baseHandle = handleDataFromHKeyLocked(hKey);
|
||||
if (!baseHandle) {
|
||||
@ -176,7 +266,7 @@ LSTATUS WIN_FUNC RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REG
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (existingKeys.find(targetPath) == existingKeys.end()) {
|
||||
if (g_existingKeys.find(targetPath) == g_existingKeys.end()) {
|
||||
wibo::lastError = ERROR_FILE_NOT_FOUND;
|
||||
return ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
@ -208,6 +298,93 @@ LSTATUS WIN_FUNC RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGS
|
||||
return RegOpenKeyExW(hKey, widePtr, ulOptions, samDesired, phkResult);
|
||||
}
|
||||
|
||||
LSTATUS WIN_FUNC RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData,
|
||||
LPDWORD lpcbData) {
|
||||
std::string valueName = lpValueName ? wideStringToString(lpValueName) : std::string("(default)");
|
||||
DEBUG_LOG("RegQueryValueExW(%p, %s, %p, %p, %p, %p)\n", hKey, valueName.c_str(), lpReserved, lpType, lpData,
|
||||
lpcbData);
|
||||
if (lpReserved) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
if (lpcbData) {
|
||||
*lpcbData = 0;
|
||||
}
|
||||
if (lpType) {
|
||||
*lpType = 0;
|
||||
}
|
||||
(void)hKey;
|
||||
(void)lpData;
|
||||
wibo::lastError = ERROR_FILE_NOT_FOUND;
|
||||
return ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
LSTATUS WIN_FUNC RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData,
|
||||
LPDWORD lpcbData) {
|
||||
DEBUG_LOG("RegQueryValueExA(%p, %s, %p, %p, %p, %p)\n", hKey, lpValueName ? lpValueName : "(null)", lpReserved,
|
||||
lpType, lpData, lpcbData);
|
||||
std::vector<uint16_t> valueWideStorage;
|
||||
if (lpValueName) {
|
||||
valueWideStorage = stringToWideString(lpValueName);
|
||||
}
|
||||
return RegQueryValueExW(hKey, lpValueName ? reinterpret_cast<LPCWSTR>(valueWideStorage.data()) : nullptr,
|
||||
lpReserved, lpType, lpData, lpcbData);
|
||||
}
|
||||
|
||||
LSTATUS WIN_FUNC RegEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved,
|
||||
LPWSTR lpClass, LPDWORD lpcchClass, FILETIME *lpftLastWriteTime) {
|
||||
DEBUG_LOG("RegEnumKeyExW(%p, %u, %p, %p, %p, %p, %p, %p)\n", hKey, dwIndex, lpName, lpcchName, lpReserved, lpClass,
|
||||
lpcchClass, lpftLastWriteTime);
|
||||
(void)hKey;
|
||||
(void)dwIndex;
|
||||
if (lpReserved) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
if (lpcchName) {
|
||||
*lpcchName = 0;
|
||||
}
|
||||
if (lpName && lpcchName && *lpcchName > 0) {
|
||||
lpName[0] = 0;
|
||||
}
|
||||
if (lpClass && lpcchClass && *lpcchClass > 0) {
|
||||
lpClass[0] = 0;
|
||||
}
|
||||
if (lpcchClass) {
|
||||
*lpcchClass = 0;
|
||||
}
|
||||
(void)lpftLastWriteTime;
|
||||
wibo::lastError = ERROR_NO_MORE_ITEMS;
|
||||
return ERROR_NO_MORE_ITEMS;
|
||||
}
|
||||
|
||||
LSTATUS WIN_FUNC RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved,
|
||||
LPSTR lpClass, LPDWORD lpcchClass, FILETIME *lpftLastWriteTime) {
|
||||
DEBUG_LOG("RegEnumKeyExA(%p, %u, %p, %p, %p, %p, %p, %p)\n", hKey, dwIndex, lpName, lpcchName, lpReserved, lpClass,
|
||||
lpcchClass, lpftLastWriteTime);
|
||||
(void)hKey;
|
||||
(void)dwIndex;
|
||||
if (lpReserved) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
if (lpcchName) {
|
||||
*lpcchName = 0;
|
||||
}
|
||||
if (lpName && lpcchName && *lpcchName > 0) {
|
||||
lpName[0] = '\0';
|
||||
}
|
||||
if (lpClass && lpcchClass && *lpcchClass > 0) {
|
||||
lpClass[0] = '\0';
|
||||
}
|
||||
if (lpcchClass) {
|
||||
*lpcchClass = 0;
|
||||
}
|
||||
(void)lpftLastWriteTime;
|
||||
wibo::lastError = ERROR_NO_MORE_ITEMS;
|
||||
return ERROR_NO_MORE_ITEMS;
|
||||
}
|
||||
|
||||
LSTATUS WIN_FUNC RegCloseKey(HKEY hKey) {
|
||||
DEBUG_LOG("RegCloseKey(%p)\n", hKey);
|
||||
if (isPredefinedKeyHandle(hKey)) {
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
struct FILETIME;
|
||||
|
||||
#ifndef HKEY_CLASSES_ROOT
|
||||
#define HKEY_CLASSES_ROOT ((HKEY)(uintptr_t)0x80000000u)
|
||||
#endif
|
||||
@ -23,13 +25,30 @@
|
||||
|
||||
constexpr DWORD REG_OPTION_OPEN_LINK = 0x00000008;
|
||||
|
||||
constexpr DWORD REG_CREATED_NEW_KEY = 0x00000001;
|
||||
constexpr DWORD REG_OPENED_EXISTING_KEY = 0x00000002;
|
||||
|
||||
constexpr REGSAM KEY_WOW64_64KEY = 0x00000100;
|
||||
constexpr REGSAM KEY_WOW64_32KEY = 0x00000200;
|
||||
|
||||
namespace advapi32 {
|
||||
|
||||
LSTATUS WIN_FUNC RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions,
|
||||
REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult,
|
||||
LPDWORD lpdwDisposition);
|
||||
LSTATUS WIN_FUNC RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, DWORD dwOptions,
|
||||
REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult,
|
||||
LPDWORD lpdwDisposition);
|
||||
LSTATUS WIN_FUNC RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult);
|
||||
LSTATUS WIN_FUNC RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult);
|
||||
LSTATUS WIN_FUNC RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData,
|
||||
LPDWORD lpcbData);
|
||||
LSTATUS WIN_FUNC RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData,
|
||||
LPDWORD lpcbData);
|
||||
LSTATUS WIN_FUNC RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved,
|
||||
LPSTR lpClass, LPDWORD lpcchClass, FILETIME *lpftLastWriteTime);
|
||||
LSTATUS WIN_FUNC RegEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved,
|
||||
LPWSTR lpClass, LPDWORD lpcchClass, FILETIME *lpftLastWriteTime);
|
||||
LSTATUS WIN_FUNC RegCloseKey(HKEY hKey);
|
||||
|
||||
} // namespace advapi32
|
||||
|
@ -23,7 +23,9 @@
|
||||
#include "kernel32/winnt.h"
|
||||
#include "kernel32/wow64apiset.h"
|
||||
|
||||
static void *resolveByName(const char *name) {
|
||||
namespace {
|
||||
|
||||
void *resolveByName(const char *name) {
|
||||
// errhandlingapi.h
|
||||
if (strcmp(name, "GetLastError") == 0)
|
||||
return (void *)kernel32::GetLastError;
|
||||
@ -97,6 +99,8 @@ static void *resolveByName(const char *name) {
|
||||
return (void *)kernel32::SetThreadPriority;
|
||||
if (strcmp(name, "GetThreadPriority") == 0)
|
||||
return (void *)kernel32::GetThreadPriority;
|
||||
if (strcmp(name, "GetPriorityClass") == 0)
|
||||
return (void *)kernel32::GetPriorityClass;
|
||||
if (strcmp(name, "GetProcessAffinityMask") == 0)
|
||||
return (void *)kernel32::GetProcessAffinityMask;
|
||||
if (strcmp(name, "SetProcessAffinityMask") == 0)
|
||||
@ -293,6 +297,10 @@ static void *resolveByName(const char *name) {
|
||||
return (void *)kernel32::WriteConsoleW;
|
||||
if (strcmp(name, "GetConsoleOutputCP") == 0)
|
||||
return (void *)kernel32::GetConsoleOutputCP;
|
||||
if (strcmp(name, "GetConsoleTitleA") == 0)
|
||||
return (void *)kernel32::GetConsoleTitleA;
|
||||
if (strcmp(name, "GetConsoleTitleW") == 0)
|
||||
return (void *)kernel32::GetConsoleTitleW;
|
||||
if (strcmp(name, "PeekConsoleInputA") == 0)
|
||||
return (void *)kernel32::PeekConsoleInputA;
|
||||
if (strcmp(name, "ReadConsoleInputA") == 0)
|
||||
@ -323,6 +331,18 @@ static void *resolveByName(const char *name) {
|
||||
return (void *)kernel32::GetFileAttributesA;
|
||||
if (strcmp(name, "GetFileAttributesW") == 0)
|
||||
return (void *)kernel32::GetFileAttributesW;
|
||||
if (strcmp(name, "GetDriveTypeA") == 0)
|
||||
return (void *)kernel32::GetDriveTypeA;
|
||||
if (strcmp(name, "GetDriveTypeW") == 0)
|
||||
return (void *)kernel32::GetDriveTypeW;
|
||||
if (strcmp(name, "GetVolumeInformationA") == 0)
|
||||
return (void *)kernel32::GetVolumeInformationA;
|
||||
if (strcmp(name, "GetVolumeInformationW") == 0)
|
||||
return (void *)kernel32::GetVolumeInformationW;
|
||||
if (strcmp(name, "CompareFileTime") == 0)
|
||||
return (void *)kernel32::CompareFileTime;
|
||||
if (strcmp(name, "GetFileAttributesW") == 0)
|
||||
return (void *)kernel32::GetFileAttributesW;
|
||||
if (strcmp(name, "WriteFile") == 0)
|
||||
return (void *)kernel32::WriteFile;
|
||||
if (strcmp(name, "FlushFileBuffers") == 0)
|
||||
@ -339,6 +359,8 @@ static void *resolveByName(const char *name) {
|
||||
return (void *)kernel32::CreateFileMappingW;
|
||||
if (strcmp(name, "MapViewOfFile") == 0)
|
||||
return (void *)kernel32::MapViewOfFile;
|
||||
if (strcmp(name, "MapViewOfFileEx") == 0)
|
||||
return (void *)kernel32::MapViewOfFileEx;
|
||||
if (strcmp(name, "UnmapViewOfFile") == 0)
|
||||
return (void *)kernel32::UnmapViewOfFile;
|
||||
if (strcmp(name, "DeleteFileA") == 0)
|
||||
@ -541,6 +563,8 @@ static void *resolveByName(const char *name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
wibo::Module lib_kernel32 = {
|
||||
(const char *[]){
|
||||
"kernel32",
|
||||
|
@ -288,6 +288,100 @@ DWORD WIN_FUNC GetFileAttributesW(LPCWSTR lpFileName) {
|
||||
return GetFileAttributesA(str.c_str());
|
||||
}
|
||||
|
||||
UINT WIN_FUNC GetDriveTypeA(LPCSTR lpRootPathName) {
|
||||
DEBUG_LOG("STUB: GetDriveTypeA(%s)\n", lpRootPathName ? lpRootPathName : "(null)");
|
||||
(void)lpRootPathName;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return DRIVE_FIXED;
|
||||
}
|
||||
|
||||
UINT WIN_FUNC GetDriveTypeW(LPCWSTR lpRootPathName) {
|
||||
DEBUG_LOG("STUB: GetDriveTypeW(%p)\n", lpRootPathName);
|
||||
(void)lpRootPathName;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return DRIVE_FIXED;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetVolumeInformationA(LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize,
|
||||
LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength,
|
||||
LPDWORD lpFileSystemFlags, LPSTR lpFileSystemNameBuffer,
|
||||
DWORD nFileSystemNameSize) {
|
||||
DEBUG_LOG("STUB: GetVolumeInformationA(%s)\n", lpRootPathName ? lpRootPathName : "(null)");
|
||||
if (lpVolumeNameBuffer && nVolumeNameSize > 0) {
|
||||
lpVolumeNameBuffer[0] = '\0';
|
||||
}
|
||||
if (lpVolumeSerialNumber) {
|
||||
*lpVolumeSerialNumber = 0x12345678;
|
||||
}
|
||||
if (lpMaximumComponentLength) {
|
||||
*lpMaximumComponentLength = 255;
|
||||
}
|
||||
if (lpFileSystemFlags) {
|
||||
*lpFileSystemFlags = 0;
|
||||
}
|
||||
if (lpFileSystemNameBuffer) {
|
||||
if (nFileSystemNameSize > 0) {
|
||||
const char *fsName = "NTFS";
|
||||
size_t copyLen = std::min<size_t>(std::strlen(fsName), nFileSystemNameSize - 1);
|
||||
std::memcpy(lpFileSystemNameBuffer, fsName, copyLen);
|
||||
lpFileSystemNameBuffer[copyLen] = '\0';
|
||||
}
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetVolumeInformationW(LPCWSTR lpRootPathName, LPWSTR lpVolumeNameBuffer, DWORD nVolumeNameSize,
|
||||
LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength,
|
||||
LPDWORD lpFileSystemFlags, LPWSTR lpFileSystemNameBuffer,
|
||||
DWORD nFileSystemNameSize) {
|
||||
DEBUG_LOG("STUB: GetVolumeInformationW(%p)\n", lpRootPathName);
|
||||
if (lpVolumeNameBuffer && nVolumeNameSize > 0) {
|
||||
lpVolumeNameBuffer[0] = 0;
|
||||
}
|
||||
if (lpVolumeSerialNumber) {
|
||||
*lpVolumeSerialNumber = 0x12345678;
|
||||
}
|
||||
if (lpMaximumComponentLength) {
|
||||
*lpMaximumComponentLength = 255;
|
||||
}
|
||||
if (lpFileSystemFlags) {
|
||||
*lpFileSystemFlags = 0;
|
||||
}
|
||||
if (lpFileSystemNameBuffer) {
|
||||
if (nFileSystemNameSize > 0) {
|
||||
std::vector<uint16_t> fsWide = stringToWideString("NTFS");
|
||||
size_t copyLen = std::min<size_t>(fsWide.size() > 0 ? fsWide.size() - 1 : 0, nFileSystemNameSize - 1);
|
||||
for (size_t i = 0; i < copyLen; ++i) {
|
||||
lpFileSystemNameBuffer[i] = static_cast<uint16_t>(fsWide[i]);
|
||||
}
|
||||
lpFileSystemNameBuffer[copyLen] = 0;
|
||||
}
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LONG WIN_FUNC CompareFileTime(const FILETIME *lpFileTime1, const FILETIME *lpFileTime2) {
|
||||
DEBUG_LOG("CompareFileTime(%p, %p)\n", lpFileTime1, lpFileTime2);
|
||||
auto toInt64 = [](const FILETIME *ft) -> int64_t {
|
||||
if (!ft) {
|
||||
return 0;
|
||||
}
|
||||
uint64_t combined = (static_cast<uint64_t>(ft->dwHighDateTime) << 32) | ft->dwLowDateTime;
|
||||
return static_cast<int64_t>(combined);
|
||||
};
|
||||
int64_t value1 = toInt64(lpFileTime1);
|
||||
int64_t value2 = toInt64(lpFileTime2);
|
||||
if (value1 < value2) {
|
||||
return -1;
|
||||
}
|
||||
if (value1 > value2) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
DEBUG_LOG("WriteFile(%p, %u)\n", hFile, nNumberOfBytesToWrite);
|
||||
|
@ -47,6 +47,14 @@ constexpr DWORD FILE_ATTRIBUTE_OFFLINE = 0x00001000;
|
||||
constexpr DWORD FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000;
|
||||
constexpr DWORD FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
|
||||
|
||||
constexpr UINT DRIVE_UNKNOWN = 0;
|
||||
constexpr UINT DRIVE_NO_ROOT_DIR = 1;
|
||||
constexpr UINT DRIVE_REMOVABLE = 2;
|
||||
constexpr UINT DRIVE_FIXED = 3;
|
||||
constexpr UINT DRIVE_REMOTE = 4;
|
||||
constexpr UINT DRIVE_CDROM = 5;
|
||||
constexpr UINT DRIVE_RAMDISK = 6;
|
||||
|
||||
constexpr DWORD FILE_TYPE_UNKNOWN = 0x0000;
|
||||
constexpr DWORD FILE_TYPE_DISK = 0x0001;
|
||||
constexpr DWORD FILE_TYPE_CHAR = 0x0002;
|
||||
@ -72,6 +80,8 @@ BOOL WIN_FUNC FindNextFileW(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData)
|
||||
BOOL WIN_FUNC FindClose(HANDLE hFindFile);
|
||||
DWORD WIN_FUNC GetFileAttributesA(LPCSTR lpFileName);
|
||||
DWORD WIN_FUNC GetFileAttributesW(LPCWSTR lpFileName);
|
||||
UINT WIN_FUNC GetDriveTypeA(LPCSTR lpRootPathName);
|
||||
UINT WIN_FUNC GetDriveTypeW(LPCWSTR lpRootPathName);
|
||||
BOOL WIN_FUNC WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
BOOL WIN_FUNC ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||
@ -101,5 +111,13 @@ BOOL WIN_FUNC SetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, const FI
|
||||
const FILETIME *lpLastWriteTime);
|
||||
BOOL WIN_FUNC GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation);
|
||||
DWORD WIN_FUNC GetFileType(HANDLE hFile);
|
||||
LONG WIN_FUNC CompareFileTime(const FILETIME *lpFileTime1, const FILETIME *lpFileTime2);
|
||||
BOOL WIN_FUNC GetVolumeInformationA(LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize,
|
||||
LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength,
|
||||
LPDWORD lpFileSystemFlags, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize);
|
||||
BOOL WIN_FUNC GetVolumeInformationW(LPCWSTR lpRootPathName, LPWSTR lpVolumeNameBuffer, DWORD nVolumeNameSize,
|
||||
LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength,
|
||||
LPDWORD lpFileSystemFlags, LPWSTR lpFileSystemNameBuffer,
|
||||
DWORD nFileSystemNameSize);
|
||||
|
||||
} // namespace kernel32
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "handleapi.h"
|
||||
|
||||
#include "dll/advapi32/internal.h"
|
||||
#include "errors.h"
|
||||
#include "files.h"
|
||||
#include "handles.h"
|
||||
@ -9,10 +10,6 @@
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace advapi32 {
|
||||
void releaseToken(void *tokenPtr);
|
||||
}
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
BOOL WIN_FUNC DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle,
|
||||
@ -151,12 +148,7 @@ BOOL WIN_FUNC CloseHandle(HANDLE hObject) {
|
||||
success = false;
|
||||
}
|
||||
} else if (data.type == handles::TYPE_PROCESS) {
|
||||
auto *proc = reinterpret_cast<processes::Process *>(data.ptr);
|
||||
if (proc) {
|
||||
delete proc;
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
delete reinterpret_cast<processes::Process *>(data.ptr);
|
||||
} else if (data.type == handles::TYPE_TOKEN) {
|
||||
advapi32::releaseToken(data.ptr);
|
||||
} else if (data.type == handles::TYPE_MUTEX) {
|
||||
|
@ -303,17 +303,8 @@ HANDLE WIN_FUNC CreateFileMappingW(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMap
|
||||
lpName ? name.c_str() : nullptr);
|
||||
}
|
||||
|
||||
LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,
|
||||
DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap) {
|
||||
DEBUG_LOG("MapViewOfFile(%p, 0x%x, %u, %u, %zu)\n", hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,
|
||||
dwFileOffsetLow, dwNumberOfBytesToMap);
|
||||
|
||||
handles::Data data = handles::dataFromHandle(hFileMappingObject, false);
|
||||
if (data.type != handles::TYPE_MAPPED) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return nullptr;
|
||||
}
|
||||
auto *mapping = reinterpret_cast<MappingObject *>(data.ptr);
|
||||
static LPVOID mapViewOfFileInternal(MappingObject *mapping, DWORD dwDesiredAccess, uint64_t offset,
|
||||
SIZE_T dwNumberOfBytesToMap, LPVOID baseAddress) {
|
||||
if (!mapping) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return nullptr;
|
||||
@ -322,8 +313,6 @@ LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess,
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint64_t offset = (static_cast<uint64_t>(dwFileOffsetHigh) << 32) | dwFileOffsetLow;
|
||||
if (mapping->anonymous && offset != 0) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return nullptr;
|
||||
@ -331,11 +320,7 @@ LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess,
|
||||
size_t maxSize = mapping->maxSize;
|
||||
uint64_t length = static_cast<uint64_t>(dwNumberOfBytesToMap);
|
||||
if (length == 0) {
|
||||
if (maxSize == 0) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return nullptr;
|
||||
}
|
||||
if (offset > maxSize) {
|
||||
if (maxSize == 0 || offset > maxSize) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return nullptr;
|
||||
}
|
||||
@ -353,28 +338,27 @@ LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess,
|
||||
int prot = PROT_READ;
|
||||
bool wantWrite = (dwDesiredAccess & FILE_MAP_WRITE) != 0;
|
||||
bool wantExecute = (dwDesiredAccess & FILE_MAP_EXECUTE) != 0;
|
||||
bool wantCopy = (dwDesiredAccess & FILE_MAP_COPY) != 0;
|
||||
|
||||
if (mapping->protect == PAGE_READWRITE) {
|
||||
if (wantWrite) {
|
||||
if (wantWrite || wantCopy) {
|
||||
prot |= PROT_WRITE;
|
||||
}
|
||||
} else {
|
||||
if (wantWrite && (dwDesiredAccess & FILE_MAP_COPY) == 0) {
|
||||
if (wantWrite && !wantCopy) {
|
||||
wibo::lastError = ERROR_ACCESS_DENIED;
|
||||
return nullptr;
|
||||
}
|
||||
if (wantCopy) {
|
||||
prot |= PROT_WRITE;
|
||||
}
|
||||
}
|
||||
if (wantExecute) {
|
||||
prot |= PROT_EXEC;
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
if (mapping->anonymous) {
|
||||
flags |= MAP_ANONYMOUS;
|
||||
}
|
||||
flags |= (dwDesiredAccess & FILE_MAP_COPY) ? MAP_PRIVATE : MAP_SHARED;
|
||||
|
||||
size_t pageSize = static_cast<size_t>(sysconf(_SC_PAGESIZE));
|
||||
int flags = (mapping->anonymous ? MAP_ANONYMOUS : 0) | (wantCopy ? MAP_PRIVATE : MAP_SHARED);
|
||||
const size_t pageSize = static_cast<size_t>(sysconf(_SC_PAGESIZE));
|
||||
off_t alignedOffset = mapping->anonymous ? 0 : static_cast<off_t>(offset & ~static_cast<uint64_t>(pageSize - 1));
|
||||
size_t offsetDelta = static_cast<size_t>(offset - static_cast<uint64_t>(alignedOffset));
|
||||
uint64_t requestedLength = length + offsetDelta;
|
||||
@ -389,18 +373,84 @@ LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess,
|
||||
}
|
||||
|
||||
int mmapFd = mapping->anonymous ? -1 : mapping->fd;
|
||||
void *mapBase = mmap(nullptr, mapLength, prot, flags, mmapFd, alignedOffset);
|
||||
void *requestedBase = nullptr;
|
||||
int mapFlags = flags;
|
||||
if (baseAddress) {
|
||||
uintptr_t baseAddr = reinterpret_cast<uintptr_t>(baseAddress);
|
||||
if (baseAddr == 0 || (baseAddr % kVirtualAllocationGranularity) != 0) {
|
||||
wibo::lastError = ERROR_INVALID_ADDRESS;
|
||||
return nullptr;
|
||||
}
|
||||
if (offsetDelta > baseAddr) {
|
||||
wibo::lastError = ERROR_INVALID_ADDRESS;
|
||||
return nullptr;
|
||||
}
|
||||
uintptr_t mapBaseAddr = baseAddr - offsetDelta;
|
||||
if ((mapBaseAddr & (pageSize - 1)) != 0) {
|
||||
wibo::lastError = ERROR_INVALID_ADDRESS;
|
||||
return nullptr;
|
||||
}
|
||||
requestedBase = reinterpret_cast<void *>(mapBaseAddr);
|
||||
#ifdef MAP_FIXED_NOREPLACE
|
||||
mapFlags |= MAP_FIXED_NOREPLACE;
|
||||
#else
|
||||
mapFlags |= MAP_FIXED;
|
||||
#endif
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
void *mapBase = mmap(requestedBase, mapLength, prot, mapFlags, mmapFd, alignedOffset);
|
||||
if (mapBase == MAP_FAILED) {
|
||||
setLastErrorFromErrno();
|
||||
int err = errno;
|
||||
if (baseAddress && (err == ENOMEM || err == EEXIST || err == EINVAL || err == EPERM)) {
|
||||
wibo::lastError = ERROR_INVALID_ADDRESS;
|
||||
} else {
|
||||
wibo::lastError = wibo::winErrorFromErrno(err);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void *viewPtr = static_cast<uint8_t *>(mapBase) + offsetDelta;
|
||||
if (baseAddress && viewPtr != baseAddress) {
|
||||
munmap(mapBase, mapLength);
|
||||
wibo::lastError = ERROR_INVALID_ADDRESS;
|
||||
return nullptr;
|
||||
}
|
||||
g_viewInfo[viewPtr] = ViewInfo{mapBase, mapLength, mapping};
|
||||
mapping->refCount++;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return viewPtr;
|
||||
}
|
||||
|
||||
LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,
|
||||
DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap) {
|
||||
DEBUG_LOG("MapViewOfFile(%p, 0x%x, %u, %u, %zu)\n", hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,
|
||||
dwFileOffsetLow, dwNumberOfBytesToMap);
|
||||
|
||||
handles::Data data = handles::dataFromHandle(hFileMappingObject, false);
|
||||
if (data.type != handles::TYPE_MAPPED) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return nullptr;
|
||||
}
|
||||
auto *mapping = reinterpret_cast<MappingObject *>(data.ptr);
|
||||
uint64_t offset = (static_cast<uint64_t>(dwFileOffsetHigh) << 32) | dwFileOffsetLow;
|
||||
return mapViewOfFileInternal(mapping, dwDesiredAccess, offset, dwNumberOfBytesToMap, nullptr);
|
||||
}
|
||||
|
||||
LPVOID WIN_FUNC MapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,
|
||||
DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress) {
|
||||
DEBUG_LOG("MapViewOfFileEx(%p, 0x%x, %u, %u, %zu, %p)\n", hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,
|
||||
dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress);
|
||||
|
||||
handles::Data data = handles::dataFromHandle(hFileMappingObject, false);
|
||||
if (data.type != handles::TYPE_MAPPED) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return nullptr;
|
||||
}
|
||||
auto *mapping = reinterpret_cast<MappingObject *>(data.ptr);
|
||||
uint64_t offset = (static_cast<uint64_t>(dwFileOffsetHigh) << 32) | dwFileOffsetLow;
|
||||
return mapViewOfFileInternal(mapping, dwDesiredAccess, offset, dwNumberOfBytesToMap, lpBaseAddress);
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC UnmapViewOfFile(LPCVOID lpBaseAddress) {
|
||||
DEBUG_LOG("UnmapViewOfFile(%p)\n", lpBaseAddress);
|
||||
auto it = g_viewInfo.find(const_cast<void *>(lpBaseAddress));
|
||||
|
@ -53,6 +53,8 @@ HANDLE WIN_FUNC CreateFileMappingW(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMap
|
||||
DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCWSTR lpName);
|
||||
LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,
|
||||
DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap);
|
||||
LPVOID WIN_FUNC MapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,
|
||||
DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress);
|
||||
BOOL WIN_FUNC UnmapViewOfFile(LPCVOID lpBaseAddress);
|
||||
|
||||
LPVOID WIN_FUNC VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
|
||||
|
@ -625,6 +625,13 @@ int WIN_FUNC GetThreadPriority(HANDLE hThread) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC GetPriorityClass(HANDLE hProcess) {
|
||||
DEBUG_LOG("GetPriorityClass(%p)\n", hProcess);
|
||||
(void)hProcess;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return NORMAL_PRIORITY_CLASS;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetThreadTimes(HANDLE hThread, FILETIME *lpCreationTime, FILETIME *lpExitTime, FILETIME *lpKernelTime,
|
||||
FILETIME *lpUserTime) {
|
||||
DEBUG_LOG("GetThreadTimes(%p, %p, %p, %p, %p)\n", hThread, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
|
||||
|
@ -61,6 +61,7 @@ struct STARTUPINFOW {
|
||||
using LPSTARTUPINFOW = STARTUPINFOW *;
|
||||
|
||||
constexpr DWORD TLS_OUT_OF_INDEXES = 0xFFFFFFFFu;
|
||||
constexpr DWORD NORMAL_PRIORITY_CLASS = 0x00000020;
|
||||
|
||||
typedef DWORD(WIN_FUNC *LPTHREAD_START_ROUTINE)(LPVOID);
|
||||
|
||||
@ -91,6 +92,7 @@ void WIN_FUNC ExitThread(DWORD dwExitCode);
|
||||
BOOL WIN_FUNC GetExitCodeThread(HANDLE hThread, LPDWORD lpExitCode);
|
||||
BOOL WIN_FUNC SetThreadPriority(HANDLE hThread, int nPriority);
|
||||
int WIN_FUNC GetThreadPriority(HANDLE hThread);
|
||||
DWORD WIN_FUNC GetPriorityClass(HANDLE hProcess);
|
||||
BOOL WIN_FUNC GetThreadTimes(HANDLE hThread, FILETIME *lpCreationTime, FILETIME *lpExitTime, FILETIME *lpKernelTime,
|
||||
FILETIME *lpUserTime);
|
||||
BOOL WIN_FUNC CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
|
@ -83,6 +83,24 @@ BOOL WIN_FUNC WriteConsoleW(HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumb
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC GetConsoleTitleA(LPSTR lpConsoleTitle, DWORD nSize) {
|
||||
DEBUG_LOG("GetConsoleTitleA(%p, %u)\n", lpConsoleTitle, nSize);
|
||||
if (lpConsoleTitle && nSize > 0) {
|
||||
lpConsoleTitle[0] = '\0';
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC GetConsoleTitleW(LPWSTR lpConsoleTitle, DWORD nSize) {
|
||||
DEBUG_LOG("GetConsoleTitleW(%p, %u)\n", lpConsoleTitle, nSize);
|
||||
if (lpConsoleTitle && nSize > 0) {
|
||||
lpConsoleTitle[0] = 0;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC PeekConsoleInputA(HANDLE hConsoleInput, INPUT_RECORD *lpBuffer, DWORD nLength,
|
||||
LPDWORD lpNumberOfEventsRead) {
|
||||
DEBUG_LOG("STUB: PeekConsoleInputA(%p, %p, %u)\n", hConsoleInput, lpBuffer, nLength);
|
||||
|
@ -35,6 +35,8 @@ BOOL WIN_FUNC SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add);
|
||||
BOOL WIN_FUNC GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, CONSOLE_SCREEN_BUFFER_INFO *lpConsoleScreenBufferInfo);
|
||||
BOOL WIN_FUNC WriteConsoleW(HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumberOfCharsToWrite,
|
||||
LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved);
|
||||
DWORD WIN_FUNC GetConsoleTitleA(LPSTR lpConsoleTitle, DWORD nSize);
|
||||
DWORD WIN_FUNC GetConsoleTitleW(LPWSTR lpConsoleTitle, DWORD nSize);
|
||||
BOOL WIN_FUNC PeekConsoleInputA(HANDLE hConsoleInput, INPUT_RECORD *lpBuffer, DWORD nLength,
|
||||
LPDWORD lpNumberOfEventsRead);
|
||||
BOOL WIN_FUNC ReadConsoleInputA(HANDLE hConsoleInput, INPUT_RECORD *lpBuffer, DWORD nLength,
|
||||
|
Loading…
x
Reference in New Issue
Block a user