mirror of
https://github.com/decompals/wibo.git
synced 2025-10-16 15:15:10 +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(.)
|
include_directories(.)
|
||||||
add_executable(wibo
|
add_executable(wibo
|
||||||
dll/advapi32.cpp
|
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/wincrypt.cpp
|
||||||
|
dll/advapi32/winreg.cpp
|
||||||
dll/bcrypt.cpp
|
dll/bcrypt.cpp
|
||||||
dll/crt.cpp
|
dll/crt.cpp
|
||||||
dll/kernel32.cpp
|
dll/kernel32.cpp
|
||||||
|
8
common.h
8
common.h
@ -42,6 +42,7 @@ using HGLOBAL = HANDLE;
|
|||||||
using HLOCAL = HANDLE;
|
using HLOCAL = HANDLE;
|
||||||
using HRSRC = HANDLE;
|
using HRSRC = HANDLE;
|
||||||
using LPHANDLE = HANDLE *;
|
using LPHANDLE = HANDLE *;
|
||||||
|
using PHANDLE = HANDLE *;
|
||||||
using PVOID = void *;
|
using PVOID = void *;
|
||||||
using LPVOID = void *;
|
using LPVOID = void *;
|
||||||
using LPCVOID = const void *;
|
using LPCVOID = const void *;
|
||||||
@ -56,6 +57,12 @@ using LONG = int32_t;
|
|||||||
using PLONG = LONG *;
|
using PLONG = LONG *;
|
||||||
using ULONG = uint32_t;
|
using ULONG = uint32_t;
|
||||||
using PULONG = ULONG *;
|
using PULONG = ULONG *;
|
||||||
|
struct LUID {
|
||||||
|
DWORD LowPart;
|
||||||
|
LONG HighPart;
|
||||||
|
};
|
||||||
|
using PLUID = LUID *;
|
||||||
|
using LPLUID = LUID *;
|
||||||
using LARGE_INTEGER = int64_t;
|
using LARGE_INTEGER = int64_t;
|
||||||
using PLARGE_INTEGER = LARGE_INTEGER *;
|
using PLARGE_INTEGER = LARGE_INTEGER *;
|
||||||
using ULONG_PTR = uintptr_t;
|
using ULONG_PTR = uintptr_t;
|
||||||
@ -84,6 +91,7 @@ using BOOLEAN = unsigned char;
|
|||||||
using UINT = unsigned int;
|
using UINT = unsigned int;
|
||||||
using HKEY = void *;
|
using HKEY = void *;
|
||||||
using PHKEY = HKEY *;
|
using PHKEY = HKEY *;
|
||||||
|
using PSID = void *;
|
||||||
using REGSAM = DWORD;
|
using REGSAM = DWORD;
|
||||||
using LSTATUS = LONG;
|
using LSTATUS = LONG;
|
||||||
using LCID = DWORD;
|
using LCID = DWORD;
|
||||||
|
614
dll/advapi32.cpp
614
dll/advapi32.cpp
@ -1,540 +1,106 @@
|
|||||||
#include "common.h"
|
#include "advapi32/processthreadsapi.h"
|
||||||
#include "advapi32/winreg.h"
|
#include "advapi32/securitybaseapi.h"
|
||||||
|
#include "advapi32/winbase.h"
|
||||||
#include "advapi32/wincrypt.h"
|
#include "advapi32/wincrypt.h"
|
||||||
#include "errors.h"
|
#include "advapi32/winreg.h"
|
||||||
#include "handles.h"
|
#include "common.h"
|
||||||
#include "strutil.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cctype>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct Luid;
|
|
||||||
static std::mutex privilegeMapMutex;
|
|
||||||
static std::unordered_map<std::string, Luid> privilegeLuidCache;
|
|
||||||
|
|
||||||
constexpr DWORD SECURITY_DESCRIPTOR_REVISION = 1;
|
void *resolveByName(const char *name) {
|
||||||
constexpr uint16_t SE_DACL_PRESENT = 0x0004;
|
// processthreadsapi.h
|
||||||
constexpr uint16_t SE_DACL_DEFAULTED = 0x0008;
|
if (strcmp(name, "OpenProcessToken") == 0)
|
||||||
|
return (void *)advapi32::OpenProcessToken;
|
||||||
|
|
||||||
struct SecurityDescriptor {
|
// securitybaseapi.h
|
||||||
uint8_t Revision = 0;
|
if (strcmp(name, "InitializeAcl") == 0)
|
||||||
uint8_t Sbz1 = 0;
|
return (void *)advapi32::InitializeAcl;
|
||||||
uint16_t Control = 0;
|
if (strcmp(name, "AddAccessAllowedAce") == 0)
|
||||||
void *Owner = nullptr;
|
return (void *)advapi32::AddAccessAllowedAce;
|
||||||
void *Group = nullptr;
|
if (strcmp(name, "FindFirstFreeAce") == 0)
|
||||||
void *Sacl = nullptr;
|
return (void *)advapi32::FindFirstFreeAce;
|
||||||
void *Dacl = nullptr;
|
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 {
|
// winbase.h
|
||||||
HANDLE processHandle = nullptr;
|
if (strcmp(name, "LookupAccountSidW") == 0)
|
||||||
DWORD desiredAccess = 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
|
// wincrypt.h
|
||||||
if (strcmp(name, "CryptReleaseContext") == 0) return (void*) advapi32::CryptReleaseContext;
|
if (strcmp(name, "CryptReleaseContext") == 0)
|
||||||
if (strcmp(name, "CryptAcquireContextW") == 0) return (void*) advapi32::CryptAcquireContextW;
|
return (void *)advapi32::CryptReleaseContext;
|
||||||
if (strcmp(name, "CryptGenRandom") == 0) return (void*) advapi32::CryptGenRandom;
|
if (strcmp(name, "CryptAcquireContextW") == 0)
|
||||||
if (strcmp(name, "CryptCreateHash") == 0) return (void*) advapi32::CryptCreateHash;
|
return (void *)advapi32::CryptAcquireContextW;
|
||||||
if (strcmp(name, "CryptHashData") == 0) return (void*) advapi32::CryptHashData;
|
if (strcmp(name, "CryptGenRandom") == 0)
|
||||||
if (strcmp(name, "CryptGetHashParam") == 0) return (void*) advapi32::CryptGetHashParam;
|
return (void *)advapi32::CryptGenRandom;
|
||||||
if (strcmp(name, "CryptDestroyHash") == 0) return (void*) advapi32::CryptDestroyHash;
|
if (strcmp(name, "CryptCreateHash") == 0)
|
||||||
if (strcmp(name, "OpenProcessToken") == 0) return (void*) advapi32::OpenProcessToken;
|
return (void *)advapi32::CryptCreateHash;
|
||||||
if (strcmp(name, "GetTokenInformation") == 0) return (void*) advapi32::GetTokenInformation;
|
if (strcmp(name, "CryptHashData") == 0)
|
||||||
if (strcmp(name, "LookupAccountSidW") == 0) return (void*) advapi32::LookupAccountSidW;
|
return (void *)advapi32::CryptHashData;
|
||||||
if (strcmp(name, "InitializeSecurityDescriptor") == 0) return (void*) advapi32::InitializeSecurityDescriptor;
|
if (strcmp(name, "CryptGetHashParam") == 0)
|
||||||
if (strcmp(name, "SetSecurityDescriptorDacl") == 0) return (void*) advapi32::SetSecurityDescriptorDacl;
|
return (void *)advapi32::CryptGetHashParam;
|
||||||
if (strcmp(name, "LookupPrivilegeValueA") == 0) return (void*) advapi32::LookupPrivilegeValueA;
|
if (strcmp(name, "CryptDestroyHash") == 0)
|
||||||
if (strcmp(name, "LookupPrivilegeValueW") == 0) return (void*) advapi32::LookupPrivilegeValueW;
|
return (void *)advapi32::CryptDestroyHash;
|
||||||
if (strcmp(name, "AdjustTokenPrivileges") == 0) return (void*) advapi32::AdjustTokenPrivileges;
|
|
||||||
if (strcmp(name, "GetUserNameA") == 0) return (void*) advapi32::GetUserNameA;
|
// winreg.h
|
||||||
if (strcmp(name, "GetUserNameW") == 0) return (void*) advapi32::GetUserNameW;
|
if (strcmp(name, "RegCreateKeyExA") == 0)
|
||||||
if (strcmp(name, "SetTokenInformation") == 0) return (void*) advapi32::SetTokenInformation;
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
wibo::Module lib_advapi32 = {
|
wibo::Module lib_advapi32 = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"advapi32",
|
"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);
|
constexpr size_t kPredefinedKeyCount = std::size(kPredefinedKeyInfos);
|
||||||
|
|
||||||
std::mutex registryMutex;
|
std::mutex g_registryMutex;
|
||||||
bool predefinedHandlesInitialized = false;
|
bool g_predefinedHandlesInitialized = false;
|
||||||
RegistryKeyHandleData predefinedHandles[kPredefinedKeyCount];
|
RegistryKeyHandleData g_predefinedHandles[kPredefinedKeyCount];
|
||||||
bool registryInitialized = false;
|
bool g_registryInitialized = false;
|
||||||
std::unordered_set<std::u16string> existingKeys;
|
std::unordered_set<std::u16string> g_existingKeys;
|
||||||
|
|
||||||
std::u16string canonicalizeKeySegment(const std::u16string &input) {
|
std::u16string canonicalizeKeySegment(const std::u16string &input) {
|
||||||
std::u16string result;
|
std::u16string result;
|
||||||
@ -75,20 +75,20 @@ std::u16string canonicalizeKeySegment(LPCWSTR input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void initializePredefinedHandlesLocked() {
|
void initializePredefinedHandlesLocked() {
|
||||||
if (predefinedHandlesInitialized) {
|
if (g_predefinedHandlesInitialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < kPredefinedKeyCount; ++i) {
|
for (size_t i = 0; i < kPredefinedKeyCount; ++i) {
|
||||||
predefinedHandles[i].canonicalPath = canonicalizeKeySegment(std::u16string(kPredefinedKeyInfos[i].name));
|
g_predefinedHandles[i].canonicalPath = canonicalizeKeySegment(std::u16string(kPredefinedKeyInfos[i].name));
|
||||||
predefinedHandles[i].predefined = true;
|
g_predefinedHandles[i].predefined = true;
|
||||||
}
|
}
|
||||||
predefinedHandlesInitialized = true;
|
g_predefinedHandlesInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegistryKeyHandleData *predefinedHandleForValue(uintptr_t value) {
|
RegistryKeyHandleData *predefinedHandleForValue(uintptr_t value) {
|
||||||
for (size_t i = 0; i < kPredefinedKeyCount; ++i) {
|
for (size_t i = 0; i < kPredefinedKeyCount; ++i) {
|
||||||
if (kPredefinedKeyInfos[i].value == value) {
|
if (kPredefinedKeyInfos[i].value == value) {
|
||||||
return &predefinedHandles[i];
|
return &g_predefinedHandles[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -121,20 +121,110 @@ bool isPredefinedKeyHandle(HKEY hKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ensureRegistryInitializedLocked() {
|
void ensureRegistryInitializedLocked() {
|
||||||
if (registryInitialized) {
|
if (g_registryInitialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
initializePredefinedHandlesLocked();
|
initializePredefinedHandlesLocked();
|
||||||
for (size_t i = 0; i < kPredefinedKeyCount; ++i) {
|
for (auto &g_predefinedHandle : g_predefinedHandles) {
|
||||||
existingKeys.insert(predefinedHandles[i].canonicalPath);
|
g_existingKeys.insert(g_predefinedHandle.canonicalPath);
|
||||||
}
|
}
|
||||||
registryInitialized = true;
|
g_registryInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace advapi32 {
|
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) {
|
LSTATUS WIN_FUNC RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) {
|
||||||
std::string subKeyString = lpSubKey ? wideStringToString(lpSubKey) : std::string("(null)");
|
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);
|
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);
|
DEBUG_LOG("RegOpenKeyExW: ignoring WOW64 access mask 0x%x\n", samDesired ^ sanitizedAccess);
|
||||||
}
|
}
|
||||||
(void)sanitizedAccess;
|
(void)sanitizedAccess;
|
||||||
std::lock_guard<std::mutex> lock(registryMutex);
|
std::lock_guard<std::mutex> lock(g_registryMutex);
|
||||||
ensureRegistryInitializedLocked();
|
ensureRegistryInitializedLocked();
|
||||||
RegistryKeyHandleData *baseHandle = handleDataFromHKeyLocked(hKey);
|
RegistryKeyHandleData *baseHandle = handleDataFromHKeyLocked(hKey);
|
||||||
if (!baseHandle) {
|
if (!baseHandle) {
|
||||||
@ -176,7 +266,7 @@ LSTATUS WIN_FUNC RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REG
|
|||||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||||
return 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;
|
wibo::lastError = ERROR_FILE_NOT_FOUND;
|
||||||
return 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);
|
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) {
|
LSTATUS WIN_FUNC RegCloseKey(HKEY hKey) {
|
||||||
DEBUG_LOG("RegCloseKey(%p)\n", hKey);
|
DEBUG_LOG("RegCloseKey(%p)\n", hKey);
|
||||||
if (isPredefinedKeyHandle(hKey)) {
|
if (isPredefinedKeyHandle(hKey)) {
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
struct FILETIME;
|
||||||
|
|
||||||
#ifndef HKEY_CLASSES_ROOT
|
#ifndef HKEY_CLASSES_ROOT
|
||||||
#define HKEY_CLASSES_ROOT ((HKEY)(uintptr_t)0x80000000u)
|
#define HKEY_CLASSES_ROOT ((HKEY)(uintptr_t)0x80000000u)
|
||||||
#endif
|
#endif
|
||||||
@ -23,13 +25,30 @@
|
|||||||
|
|
||||||
constexpr DWORD REG_OPTION_OPEN_LINK = 0x00000008;
|
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_64KEY = 0x00000100;
|
||||||
constexpr REGSAM KEY_WOW64_32KEY = 0x00000200;
|
constexpr REGSAM KEY_WOW64_32KEY = 0x00000200;
|
||||||
|
|
||||||
namespace advapi32 {
|
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 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 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);
|
LSTATUS WIN_FUNC RegCloseKey(HKEY hKey);
|
||||||
|
|
||||||
} // namespace advapi32
|
} // namespace advapi32
|
||||||
|
@ -23,7 +23,9 @@
|
|||||||
#include "kernel32/winnt.h"
|
#include "kernel32/winnt.h"
|
||||||
#include "kernel32/wow64apiset.h"
|
#include "kernel32/wow64apiset.h"
|
||||||
|
|
||||||
static void *resolveByName(const char *name) {
|
namespace {
|
||||||
|
|
||||||
|
void *resolveByName(const char *name) {
|
||||||
// errhandlingapi.h
|
// errhandlingapi.h
|
||||||
if (strcmp(name, "GetLastError") == 0)
|
if (strcmp(name, "GetLastError") == 0)
|
||||||
return (void *)kernel32::GetLastError;
|
return (void *)kernel32::GetLastError;
|
||||||
@ -97,6 +99,8 @@ static void *resolveByName(const char *name) {
|
|||||||
return (void *)kernel32::SetThreadPriority;
|
return (void *)kernel32::SetThreadPriority;
|
||||||
if (strcmp(name, "GetThreadPriority") == 0)
|
if (strcmp(name, "GetThreadPriority") == 0)
|
||||||
return (void *)kernel32::GetThreadPriority;
|
return (void *)kernel32::GetThreadPriority;
|
||||||
|
if (strcmp(name, "GetPriorityClass") == 0)
|
||||||
|
return (void *)kernel32::GetPriorityClass;
|
||||||
if (strcmp(name, "GetProcessAffinityMask") == 0)
|
if (strcmp(name, "GetProcessAffinityMask") == 0)
|
||||||
return (void *)kernel32::GetProcessAffinityMask;
|
return (void *)kernel32::GetProcessAffinityMask;
|
||||||
if (strcmp(name, "SetProcessAffinityMask") == 0)
|
if (strcmp(name, "SetProcessAffinityMask") == 0)
|
||||||
@ -293,6 +297,10 @@ static void *resolveByName(const char *name) {
|
|||||||
return (void *)kernel32::WriteConsoleW;
|
return (void *)kernel32::WriteConsoleW;
|
||||||
if (strcmp(name, "GetConsoleOutputCP") == 0)
|
if (strcmp(name, "GetConsoleOutputCP") == 0)
|
||||||
return (void *)kernel32::GetConsoleOutputCP;
|
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)
|
if (strcmp(name, "PeekConsoleInputA") == 0)
|
||||||
return (void *)kernel32::PeekConsoleInputA;
|
return (void *)kernel32::PeekConsoleInputA;
|
||||||
if (strcmp(name, "ReadConsoleInputA") == 0)
|
if (strcmp(name, "ReadConsoleInputA") == 0)
|
||||||
@ -323,6 +331,18 @@ static void *resolveByName(const char *name) {
|
|||||||
return (void *)kernel32::GetFileAttributesA;
|
return (void *)kernel32::GetFileAttributesA;
|
||||||
if (strcmp(name, "GetFileAttributesW") == 0)
|
if (strcmp(name, "GetFileAttributesW") == 0)
|
||||||
return (void *)kernel32::GetFileAttributesW;
|
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)
|
if (strcmp(name, "WriteFile") == 0)
|
||||||
return (void *)kernel32::WriteFile;
|
return (void *)kernel32::WriteFile;
|
||||||
if (strcmp(name, "FlushFileBuffers") == 0)
|
if (strcmp(name, "FlushFileBuffers") == 0)
|
||||||
@ -339,6 +359,8 @@ static void *resolveByName(const char *name) {
|
|||||||
return (void *)kernel32::CreateFileMappingW;
|
return (void *)kernel32::CreateFileMappingW;
|
||||||
if (strcmp(name, "MapViewOfFile") == 0)
|
if (strcmp(name, "MapViewOfFile") == 0)
|
||||||
return (void *)kernel32::MapViewOfFile;
|
return (void *)kernel32::MapViewOfFile;
|
||||||
|
if (strcmp(name, "MapViewOfFileEx") == 0)
|
||||||
|
return (void *)kernel32::MapViewOfFileEx;
|
||||||
if (strcmp(name, "UnmapViewOfFile") == 0)
|
if (strcmp(name, "UnmapViewOfFile") == 0)
|
||||||
return (void *)kernel32::UnmapViewOfFile;
|
return (void *)kernel32::UnmapViewOfFile;
|
||||||
if (strcmp(name, "DeleteFileA") == 0)
|
if (strcmp(name, "DeleteFileA") == 0)
|
||||||
@ -541,6 +563,8 @@ static void *resolveByName(const char *name) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
wibo::Module lib_kernel32 = {
|
wibo::Module lib_kernel32 = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"kernel32",
|
"kernel32",
|
||||||
|
@ -288,6 +288,100 @@ DWORD WIN_FUNC GetFileAttributesW(LPCWSTR lpFileName) {
|
|||||||
return GetFileAttributesA(str.c_str());
|
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,
|
BOOL WIN_FUNC WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||||
LPOVERLAPPED lpOverlapped) {
|
LPOVERLAPPED lpOverlapped) {
|
||||||
DEBUG_LOG("WriteFile(%p, %u)\n", hFile, nNumberOfBytesToWrite);
|
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_NOT_CONTENT_INDEXED = 0x00002000;
|
||||||
constexpr DWORD FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
|
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_UNKNOWN = 0x0000;
|
||||||
constexpr DWORD FILE_TYPE_DISK = 0x0001;
|
constexpr DWORD FILE_TYPE_DISK = 0x0001;
|
||||||
constexpr DWORD FILE_TYPE_CHAR = 0x0002;
|
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);
|
BOOL WIN_FUNC FindClose(HANDLE hFindFile);
|
||||||
DWORD WIN_FUNC GetFileAttributesA(LPCSTR lpFileName);
|
DWORD WIN_FUNC GetFileAttributesA(LPCSTR lpFileName);
|
||||||
DWORD WIN_FUNC GetFileAttributesW(LPCWSTR 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,
|
BOOL WIN_FUNC WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||||
LPOVERLAPPED lpOverlapped);
|
LPOVERLAPPED lpOverlapped);
|
||||||
BOOL WIN_FUNC ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
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);
|
const FILETIME *lpLastWriteTime);
|
||||||
BOOL WIN_FUNC GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation);
|
BOOL WIN_FUNC GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation);
|
||||||
DWORD WIN_FUNC GetFileType(HANDLE hFile);
|
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
|
} // namespace kernel32
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "handleapi.h"
|
#include "handleapi.h"
|
||||||
|
|
||||||
|
#include "dll/advapi32/internal.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
@ -9,10 +10,6 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
namespace advapi32 {
|
|
||||||
void releaseToken(void *tokenPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace kernel32 {
|
namespace kernel32 {
|
||||||
|
|
||||||
BOOL WIN_FUNC DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle,
|
BOOL WIN_FUNC DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle,
|
||||||
@ -151,12 +148,7 @@ BOOL WIN_FUNC CloseHandle(HANDLE hObject) {
|
|||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
} else if (data.type == handles::TYPE_PROCESS) {
|
} else if (data.type == handles::TYPE_PROCESS) {
|
||||||
auto *proc = reinterpret_cast<processes::Process *>(data.ptr);
|
delete reinterpret_cast<processes::Process *>(data.ptr);
|
||||||
if (proc) {
|
|
||||||
delete proc;
|
|
||||||
} else {
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
} else if (data.type == handles::TYPE_TOKEN) {
|
} else if (data.type == handles::TYPE_TOKEN) {
|
||||||
advapi32::releaseToken(data.ptr);
|
advapi32::releaseToken(data.ptr);
|
||||||
} else if (data.type == handles::TYPE_MUTEX) {
|
} 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);
|
lpName ? name.c_str() : nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,
|
static LPVOID mapViewOfFileInternal(MappingObject *mapping, DWORD dwDesiredAccess, uint64_t offset,
|
||||||
DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap) {
|
SIZE_T dwNumberOfBytesToMap, LPVOID baseAddress) {
|
||||||
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);
|
|
||||||
if (!mapping) {
|
if (!mapping) {
|
||||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -322,8 +313,6 @@ LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess,
|
|||||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t offset = (static_cast<uint64_t>(dwFileOffsetHigh) << 32) | dwFileOffsetLow;
|
|
||||||
if (mapping->anonymous && offset != 0) {
|
if (mapping->anonymous && offset != 0) {
|
||||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -331,11 +320,7 @@ LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess,
|
|||||||
size_t maxSize = mapping->maxSize;
|
size_t maxSize = mapping->maxSize;
|
||||||
uint64_t length = static_cast<uint64_t>(dwNumberOfBytesToMap);
|
uint64_t length = static_cast<uint64_t>(dwNumberOfBytesToMap);
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
if (maxSize == 0) {
|
if (maxSize == 0 || offset > maxSize) {
|
||||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (offset > maxSize) {
|
|
||||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -353,28 +338,27 @@ LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess,
|
|||||||
int prot = PROT_READ;
|
int prot = PROT_READ;
|
||||||
bool wantWrite = (dwDesiredAccess & FILE_MAP_WRITE) != 0;
|
bool wantWrite = (dwDesiredAccess & FILE_MAP_WRITE) != 0;
|
||||||
bool wantExecute = (dwDesiredAccess & FILE_MAP_EXECUTE) != 0;
|
bool wantExecute = (dwDesiredAccess & FILE_MAP_EXECUTE) != 0;
|
||||||
|
bool wantCopy = (dwDesiredAccess & FILE_MAP_COPY) != 0;
|
||||||
|
|
||||||
if (mapping->protect == PAGE_READWRITE) {
|
if (mapping->protect == PAGE_READWRITE) {
|
||||||
if (wantWrite) {
|
if (wantWrite || wantCopy) {
|
||||||
prot |= PROT_WRITE;
|
prot |= PROT_WRITE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (wantWrite && (dwDesiredAccess & FILE_MAP_COPY) == 0) {
|
if (wantWrite && !wantCopy) {
|
||||||
wibo::lastError = ERROR_ACCESS_DENIED;
|
wibo::lastError = ERROR_ACCESS_DENIED;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
if (wantCopy) {
|
||||||
|
prot |= PROT_WRITE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (wantExecute) {
|
if (wantExecute) {
|
||||||
prot |= PROT_EXEC;
|
prot |= PROT_EXEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flags = 0;
|
int flags = (mapping->anonymous ? MAP_ANONYMOUS : 0) | (wantCopy ? MAP_PRIVATE : MAP_SHARED);
|
||||||
if (mapping->anonymous) {
|
const size_t pageSize = static_cast<size_t>(sysconf(_SC_PAGESIZE));
|
||||||
flags |= MAP_ANONYMOUS;
|
|
||||||
}
|
|
||||||
flags |= (dwDesiredAccess & FILE_MAP_COPY) ? MAP_PRIVATE : MAP_SHARED;
|
|
||||||
|
|
||||||
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));
|
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));
|
size_t offsetDelta = static_cast<size_t>(offset - static_cast<uint64_t>(alignedOffset));
|
||||||
uint64_t requestedLength = length + offsetDelta;
|
uint64_t requestedLength = length + offsetDelta;
|
||||||
@ -389,18 +373,84 @@ LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mmapFd = mapping->anonymous ? -1 : mapping->fd;
|
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) {
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
void *viewPtr = static_cast<uint8_t *>(mapBase) + offsetDelta;
|
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};
|
g_viewInfo[viewPtr] = ViewInfo{mapBase, mapLength, mapping};
|
||||||
mapping->refCount++;
|
mapping->refCount++;
|
||||||
wibo::lastError = ERROR_SUCCESS;
|
wibo::lastError = ERROR_SUCCESS;
|
||||||
return viewPtr;
|
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) {
|
BOOL WIN_FUNC UnmapViewOfFile(LPCVOID lpBaseAddress) {
|
||||||
DEBUG_LOG("UnmapViewOfFile(%p)\n", lpBaseAddress);
|
DEBUG_LOG("UnmapViewOfFile(%p)\n", lpBaseAddress);
|
||||||
auto it = g_viewInfo.find(const_cast<void *>(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);
|
DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCWSTR lpName);
|
||||||
LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,
|
LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,
|
||||||
DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap);
|
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);
|
BOOL WIN_FUNC UnmapViewOfFile(LPCVOID lpBaseAddress);
|
||||||
|
|
||||||
LPVOID WIN_FUNC VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
|
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;
|
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,
|
BOOL WIN_FUNC GetThreadTimes(HANDLE hThread, FILETIME *lpCreationTime, FILETIME *lpExitTime, FILETIME *lpKernelTime,
|
||||||
FILETIME *lpUserTime) {
|
FILETIME *lpUserTime) {
|
||||||
DEBUG_LOG("GetThreadTimes(%p, %p, %p, %p, %p)\n", hThread, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
|
DEBUG_LOG("GetThreadTimes(%p, %p, %p, %p, %p)\n", hThread, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
|
||||||
|
@ -61,6 +61,7 @@ struct STARTUPINFOW {
|
|||||||
using LPSTARTUPINFOW = STARTUPINFOW *;
|
using LPSTARTUPINFOW = STARTUPINFOW *;
|
||||||
|
|
||||||
constexpr DWORD TLS_OUT_OF_INDEXES = 0xFFFFFFFFu;
|
constexpr DWORD TLS_OUT_OF_INDEXES = 0xFFFFFFFFu;
|
||||||
|
constexpr DWORD NORMAL_PRIORITY_CLASS = 0x00000020;
|
||||||
|
|
||||||
typedef DWORD(WIN_FUNC *LPTHREAD_START_ROUTINE)(LPVOID);
|
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 GetExitCodeThread(HANDLE hThread, LPDWORD lpExitCode);
|
||||||
BOOL WIN_FUNC SetThreadPriority(HANDLE hThread, int nPriority);
|
BOOL WIN_FUNC SetThreadPriority(HANDLE hThread, int nPriority);
|
||||||
int WIN_FUNC GetThreadPriority(HANDLE hThread);
|
int WIN_FUNC GetThreadPriority(HANDLE hThread);
|
||||||
|
DWORD WIN_FUNC GetPriorityClass(HANDLE hProcess);
|
||||||
BOOL WIN_FUNC GetThreadTimes(HANDLE hThread, FILETIME *lpCreationTime, FILETIME *lpExitTime, FILETIME *lpKernelTime,
|
BOOL WIN_FUNC GetThreadTimes(HANDLE hThread, FILETIME *lpCreationTime, FILETIME *lpExitTime, FILETIME *lpKernelTime,
|
||||||
FILETIME *lpUserTime);
|
FILETIME *lpUserTime);
|
||||||
BOOL WIN_FUNC CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
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;
|
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,
|
BOOL WIN_FUNC PeekConsoleInputA(HANDLE hConsoleInput, INPUT_RECORD *lpBuffer, DWORD nLength,
|
||||||
LPDWORD lpNumberOfEventsRead) {
|
LPDWORD lpNumberOfEventsRead) {
|
||||||
DEBUG_LOG("STUB: PeekConsoleInputA(%p, %p, %u)\n", hConsoleInput, lpBuffer, nLength);
|
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 GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, CONSOLE_SCREEN_BUFFER_INFO *lpConsoleScreenBufferInfo);
|
||||||
BOOL WIN_FUNC WriteConsoleW(HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumberOfCharsToWrite,
|
BOOL WIN_FUNC WriteConsoleW(HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumberOfCharsToWrite,
|
||||||
LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved);
|
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,
|
BOOL WIN_FUNC PeekConsoleInputA(HANDLE hConsoleInput, INPUT_RECORD *lpBuffer, DWORD nLength,
|
||||||
LPDWORD lpNumberOfEventsRead);
|
LPDWORD lpNumberOfEventsRead);
|
||||||
BOOL WIN_FUNC ReadConsoleInputA(HANDLE hConsoleInput, INPUT_RECORD *lpBuffer, DWORD nLength,
|
BOOL WIN_FUNC ReadConsoleInputA(HANDLE hConsoleInput, INPUT_RECORD *lpBuffer, DWORD nLength,
|
||||||
|
1
errors.h
1
errors.h
@ -9,6 +9,7 @@
|
|||||||
#define ERROR_INVALID_HANDLE 6
|
#define ERROR_INVALID_HANDLE 6
|
||||||
#define ERROR_NOT_ENOUGH_MEMORY 8
|
#define ERROR_NOT_ENOUGH_MEMORY 8
|
||||||
#define ERROR_NO_MORE_FILES 18
|
#define ERROR_NO_MORE_FILES 18
|
||||||
|
#define ERROR_NO_MORE_ITEMS 259
|
||||||
#define ERROR_FILE_EXISTS 80
|
#define ERROR_FILE_EXISTS 80
|
||||||
#define ERROR_READ_FAULT 30
|
#define ERROR_READ_FAULT 30
|
||||||
#define ERROR_HANDLE_EOF 38
|
#define ERROR_HANDLE_EOF 38
|
||||||
|
Loading…
x
Reference in New Issue
Block a user