Save/restore fs/gs segments when re-entering host code

This commit is contained in:
2025-10-05 13:58:40 -06:00
parent 04516b246c
commit cd7baffc5e
44 changed files with 669 additions and 20 deletions

View File

@@ -8,6 +8,7 @@
namespace advapi32 {
BOOL WIN_FUNC OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("OpenProcessToken(%p, %u, %p)\n", ProcessHandle, DesiredAccess, TokenHandle);
if (!TokenHandle) {
wibo::lastError = ERROR_INVALID_PARAMETER;

View File

@@ -101,6 +101,7 @@ bool writeLocalSystemSid(Sid *sid) {
namespace advapi32 {
BOOL WIN_FUNC InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("InitializeAcl(%p, %u, %u)\n", pAcl, nAclLength, dwAclRevision);
if (!pAcl) {
wibo::lastError = ERROR_INVALID_PARAMETER;
@@ -131,6 +132,7 @@ BOOL WIN_FUNC InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision) {
}
BOOL WIN_FUNC AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("AddAccessAllowedAce(%p, %u, 0x%x, %p)\n", pAcl, dwAceRevision, AccessMask, pSid);
if (!pAcl || !pSid) {
wibo::lastError = ERROR_INVALID_PARAMETER;
@@ -200,6 +202,7 @@ BOOL WIN_FUNC AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMa
}
BOOL WIN_FUNC FindFirstFreeAce(PACL pAcl, LPVOID *pAce) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("FindFirstFreeAce(%p, %p)\n", pAcl, pAce);
if (!pAce) {
wibo::lastError = ERROR_INVALID_PARAMETER;
@@ -224,6 +227,7 @@ BOOL WIN_FUNC FindFirstFreeAce(PACL pAcl, LPVOID *pAce) {
BOOL WIN_FUNC GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL *pDacl,
LPBOOL lpbDaclDefaulted) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("GetSecurityDescriptorDacl(%p, %p, %p, %p)\n", pSecurityDescriptor, lpbDaclPresent, pDacl,
lpbDaclDefaulted);
if (!pSecurityDescriptor) {
@@ -261,6 +265,7 @@ BOOL WIN_FUNC GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor
}
PSID_IDENTIFIER_AUTHORITY WIN_FUNC GetSidIdentifierAuthority(PSID pSid) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("GetSidIdentifierAuthority(%p)\n", pSid);
if (!pSid) {
wibo::lastError = ERROR_INVALID_SID;
@@ -276,6 +281,7 @@ PSID_IDENTIFIER_AUTHORITY WIN_FUNC GetSidIdentifierAuthority(PSID pSid) {
}
PUCHAR WIN_FUNC GetSidSubAuthorityCount(PSID pSid) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("GetSidSubAuthorityCount(%p)\n", pSid);
if (!pSid) {
wibo::lastError = ERROR_INVALID_SID;
@@ -291,6 +297,7 @@ PUCHAR WIN_FUNC GetSidSubAuthorityCount(PSID pSid) {
}
PDWORD WIN_FUNC GetSidSubAuthority(PSID pSid, DWORD nSubAuthority) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("GetSidSubAuthority(%p, %u)\n", pSid, nSubAuthority);
if (!pSid) {
wibo::lastError = ERROR_INVALID_SID;
@@ -306,6 +313,7 @@ PDWORD WIN_FUNC GetSidSubAuthority(PSID pSid, DWORD nSubAuthority) {
}
BOOL WIN_FUNC ImpersonateLoggedOnUser(HANDLE hToken) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("STUB: ImpersonateLoggedOnUser(%p)\n", hToken);
(void)hToken;
wibo::lastError = ERROR_SUCCESS;
@@ -314,6 +322,7 @@ BOOL WIN_FUNC ImpersonateLoggedOnUser(HANDLE hToken) {
BOOL WIN_FUNC DuplicateTokenEx(HANDLE hExistingToken, DWORD dwDesiredAccess, void *lpTokenAttributes,
DWORD ImpersonationLevel, DWORD TokenType, PHANDLE phNewToken) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("DuplicateTokenEx(%p, 0x%x, %p, %u, %u, %p)\n", hExistingToken, dwDesiredAccess, lpTokenAttributes,
ImpersonationLevel, TokenType, phNewToken);
(void)lpTokenAttributes;
@@ -336,6 +345,7 @@ BOOL WIN_FUNC DuplicateTokenEx(HANDLE hExistingToken, DWORD dwDesiredAccess, voi
}
BOOL WIN_FUNC CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("CopySid(%u, %p, %p)\n", nDestinationSidLength, pDestinationSid, pSourceSid);
if (!pDestinationSid || !pSourceSid) {
wibo::lastError = ERROR_INVALID_PARAMETER;
@@ -353,6 +363,7 @@ BOOL WIN_FUNC CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pS
}
BOOL WIN_FUNC InitializeSid(PSID sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("InitializeSid(%p, %p, %u)\n", sid, pIdentifierAuthority, nSubAuthorityCount);
if (!sid || !pIdentifierAuthority) {
wibo::lastError = ERROR_INVALID_PARAMETER;
@@ -374,6 +385,7 @@ BOOL WIN_FUNC InitializeSid(PSID sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAutho
}
BOOL WIN_FUNC EqualSid(PSID pSid1, PSID pSid2) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("EqualSid(%p, %p)\n", pSid1, pSid2);
if (!pSid1 || !pSid2) {
wibo::lastError = ERROR_INVALID_SID;
@@ -398,6 +410,7 @@ BOOL WIN_FUNC EqualSid(PSID pSid1, PSID pSid2) {
BOOL WIN_FUNC SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR SecurityDescriptor) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("STUB: SetKernelObjectSecurity(%p, 0x%x, %p)\n", Handle, SecurityInformation, SecurityDescriptor);
(void)SecurityInformation;
if (!SecurityDescriptor) {
@@ -414,6 +427,7 @@ BOOL WIN_FUNC SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION Securi
}
BOOL WIN_FUNC InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("InitializeSecurityDescriptor(%p, %u)\n", pSecurityDescriptor, dwRevision);
if (!pSecurityDescriptor || dwRevision != SECURITY_DESCRIPTOR_REVISION) {
wibo::lastError = ERROR_INVALID_PARAMETER;
@@ -432,6 +446,7 @@ BOOL WIN_FUNC InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescrip
BOOL WIN_FUNC SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl,
BOOL bDaclDefaulted) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("SetSecurityDescriptorDacl(%p, %u, %p, %u)\n", pSecurityDescriptor, bDaclPresent, pDacl, bDaclDefaulted);
if (!pSecurityDescriptor || pSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION) {
wibo::lastError = ERROR_INVALID_PARAMETER;
@@ -454,6 +469,7 @@ BOOL WIN_FUNC SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor
BOOL WIN_FUNC GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass,
LPVOID TokenInformation, DWORD TokenInformationLength, LPDWORD ReturnLength) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("STUB: GetTokenInformation(%p, %u, %p, %u, %p)\n", TokenHandle, TokenInformationClass, TokenInformation,
TokenInformationLength, ReturnLength);
if (!ReturnLength) {
@@ -537,6 +553,7 @@ BOOL WIN_FUNC GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS To
BOOL WIN_FUNC AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState,
DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, LPDWORD ReturnLength) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("AdjustTokenPrivileges(%p, %u, %p, %u, %p, %p)\n", TokenHandle, DisableAllPrivileges, NewState,
BufferLength, PreviousState, ReturnLength);
(void)TokenHandle;
@@ -551,6 +568,7 @@ BOOL WIN_FUNC AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivilege
BOOL WIN_FUNC SetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass,
LPVOID TokenInformation, DWORD TokenInformationLength) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("STUB: SetTokenInformation(%p, %u, %p, %u)\n", TokenHandle, TokenInformationClass, TokenInformation,
TokenInformationLength);
(void)TokenInformationClass;

View File

@@ -83,6 +83,7 @@ namespace advapi32 {
BOOL WIN_FUNC LookupAccountSidW(LPCWSTR lpSystemName, PSID Sid, LPWSTR Name, LPDWORD cchName,
LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, SID_NAME_USE *peUse) {
WIN_API_SEGMENT_GUARD();
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);
@@ -113,6 +114,7 @@ BOOL WIN_FUNC LookupAccountSidW(LPCWSTR lpSystemName, PSID Sid, LPWSTR Name, LPD
}
BOOL WIN_FUNC LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("LookupPrivilegeValueA(%s, %s, %p)\n", lpSystemName ? lpSystemName : "(null)", lpName ? lpName : "(null)",
lpLuid);
(void)lpSystemName; // only local lookup supported
@@ -128,6 +130,7 @@ BOOL WIN_FUNC LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lp
}
BOOL WIN_FUNC LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("LookupPrivilegeValueW(%p, %p, %p)\n", lpSystemName, lpName, lpLuid);
(void)lpSystemName; // only local lookup supported
if (!lpName || !lpLuid) {
@@ -143,6 +146,7 @@ BOOL WIN_FUNC LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID
}
BOOL WIN_FUNC GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("GetUserNameA(%p, %p)\n", lpBuffer, pcbBuffer);
if (!pcbBuffer) {
wibo::lastError = ERROR_INVALID_PARAMETER;
@@ -162,6 +166,7 @@ BOOL WIN_FUNC GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer) {
}
BOOL WIN_FUNC GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("GetUserNameW(%p, %p)\n", lpBuffer, pcbBuffer);
if (!pcbBuffer) {
wibo::lastError = ERROR_INVALID_PARAMETER;

View File

@@ -205,6 +205,7 @@ HCRYPTHASH hashHandleFromObject(HashObject *hash) { return static_cast<HCRYPTHAS
namespace advapi32 {
BOOL WIN_FUNC CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("STUB: CryptReleaseContext(%p, %u)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hProv)), dwFlags);
(void)hProv;
(void)dwFlags;
@@ -214,6 +215,7 @@ BOOL WIN_FUNC CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags) {
BOOL WIN_FUNC CryptAcquireContextW(HCRYPTPROV *phProv, LPCWSTR pszContainer, LPCWSTR pszProvider, DWORD dwProvType,
DWORD dwFlags) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("STUB: CryptAcquireContextW(%p, %p, %p, %u, %u)\n", phProv, pszContainer, pszProvider, dwProvType,
dwFlags);
// to quote the guy above me: screw them for now
@@ -228,6 +230,7 @@ BOOL WIN_FUNC CryptAcquireContextW(HCRYPTPROV *phProv, LPCWSTR pszContainer, LPC
}
BOOL WIN_FUNC CryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("CryptGenRandom(%p)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hProv)));
(void)hProv;
if (!pbBuffer || dwLen == 0) {
@@ -246,6 +249,7 @@ BOOL WIN_FUNC CryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer) {
}
BOOL WIN_FUNC CryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("CryptCreateHash(%p, %u, %p, %u, %p)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hProv)), Algid,
reinterpret_cast<void *>(static_cast<uintptr_t>(hKey)), dwFlags, phHash);
(void)hProv;
@@ -276,6 +280,7 @@ BOOL WIN_FUNC CryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DW
}
BOOL WIN_FUNC CryptHashData(HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLen, DWORD dwFlags) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("CryptHashData(%p, %p, %u, %u)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hHash)), pbData,
dwDataLen, dwFlags);
if (dwFlags != 0) {
@@ -297,6 +302,7 @@ BOOL WIN_FUNC CryptHashData(HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLe
}
BOOL WIN_FUNC CryptGetHashParam(HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("CryptGetHashParam(%p, %u, %p, %p, %u)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hHash)),
dwParam, pbData, pdwDataLen, dwFlags);
if (dwFlags != 0 || !pdwDataLen) {
@@ -382,6 +388,7 @@ BOOL WIN_FUNC CryptGetHashParam(HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, D
}
BOOL WIN_FUNC CryptDestroyHash(HCRYPTHASH hHash) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("CryptDestroyHash(%p)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hHash)));
auto *hash = hashObjectFromHandle(hHash);
if (!hash) {

View File

@@ -128,6 +128,7 @@ namespace advapi32 {
LSTATUS WIN_FUNC RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, DWORD dwOptions,
REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult,
LPDWORD lpdwDisposition) {
WIN_API_SEGMENT_GUARD();
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,
@@ -196,6 +197,7 @@ LSTATUS WIN_FUNC RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LP
LSTATUS WIN_FUNC RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions,
REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult,
LPDWORD lpdwDisposition) {
WIN_API_SEGMENT_GUARD();
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);
@@ -213,6 +215,7 @@ LSTATUS WIN_FUNC RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPS
}
LSTATUS WIN_FUNC RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) {
WIN_API_SEGMENT_GUARD();
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);
if (!phkResult) {
@@ -271,6 +274,7 @@ LSTATUS WIN_FUNC RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REG
}
LSTATUS WIN_FUNC RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("RegOpenKeyExA(%p, %s, %u, 0x%x, %p)\n", hKey, lpSubKey ? lpSubKey : "(null)", ulOptions, samDesired,
phkResult);
LPCWSTR widePtr = nullptr;
@@ -284,6 +288,7 @@ LSTATUS WIN_FUNC RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGS
LSTATUS WIN_FUNC RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData,
LPDWORD lpcbData) {
WIN_API_SEGMENT_GUARD();
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);
@@ -305,6 +310,7 @@ LSTATUS WIN_FUNC RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpRese
LSTATUS WIN_FUNC RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData,
LPDWORD lpcbData) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("RegQueryValueExA(%p, %s, %p, %p, %p, %p)\n", hKey, lpValueName ? lpValueName : "(null)", lpReserved,
lpType, lpData, lpcbData);
std::vector<uint16_t> valueWideStorage;
@@ -317,6 +323,7 @@ LSTATUS WIN_FUNC RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReser
LSTATUS WIN_FUNC RegEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved,
LPWSTR lpClass, LPDWORD lpcchClass, FILETIME *lpftLastWriteTime) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("RegEnumKeyExW(%p, %u, %p, %p, %p, %p, %p, %p)\n", hKey, dwIndex, lpName, lpcchName, lpReserved, lpClass,
lpcchClass, lpftLastWriteTime);
(void)hKey;
@@ -344,6 +351,7 @@ LSTATUS WIN_FUNC RegEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD
LSTATUS WIN_FUNC RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved,
LPSTR lpClass, LPDWORD lpcchClass, FILETIME *lpftLastWriteTime) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("RegEnumKeyExA(%p, %u, %p, %p, %p, %p, %p, %p)\n", hKey, dwIndex, lpName, lpcchName, lpReserved, lpClass,
lpcchClass, lpftLastWriteTime);
(void)hKey;
@@ -370,6 +378,7 @@ LSTATUS WIN_FUNC RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD l
}
LSTATUS WIN_FUNC RegCloseKey(HKEY hKey) {
WIN_API_SEGMENT_GUARD();
DEBUG_LOG("RegCloseKey(%p)\n", hKey);
if (isPredefinedKeyHandle(hKey)) {
wibo::lastError = ERROR_SUCCESS;