diff --git a/native/nt/object_api.cpp b/native/nt/object_api.cpp index 33fda97..545123f 100644 --- a/native/nt/object_api.cpp +++ b/native/nt/object_api.cpp @@ -47,6 +47,13 @@ void NativeObjectAPI::register_served(ApiRegistry ®istry, NativeObjects &obje if (status) call.fail(error(status), 0); else call.ret(1); }); + // PulseEvent: signalled for whoever waits now, and not signalled after. + registry.add("PulseEvent", 1, [&objects](ApiCall &call) { + uint32_t status=objects.set_event(call[0], true).status; + if (!status) status=objects.set_event(call[0], false).status; + if (status) call.fail(error(status), 0); + else call.ret(1); + }); } bool NativeObjectAPI::dispatch(std::string_view name) diff --git a/native/nt/registry_api.cpp b/native/nt/registry_api.cpp index 556935b..cb34790 100644 --- a/native/nt/registry_api.cpp +++ b/native/nt/registry_api.cpp @@ -954,6 +954,47 @@ void register_registry_api(ApiRegistry ®istry, KernelContext &context, Native call.ret(0); }; registry.add("RegGetValueW", 7, [get_value](ApiCall &call) { get_value(call, true); }); + // RegQueryValue, from 16-bit Windows: the unnamed value of a subkey, always as text; a key without one reads as the empty text. + for (const bool wide : {true, false}) + registry.add(wide ? "RegQueryValueW" : "RegQueryValueA", 4, [&hive, &context, text_of, view, ansi_page, wide](ApiCall &call) { + uint64_t key = call[0]; + uint64_t opened = 0; + const auto subkey = call[1] ? text_of(call, call[1], wide) : std::u16string{}; + if (!subkey.empty()) { + const auto status = hive.open(key, view(key, subkey, 0), opened); + if (status) { + call.ret(status); + return; + } + key = opened; + } + uint32_t type = 0; + std::vector data; + const auto status = hive.query(key, u"", type, data); + if (opened) { + hive.close(opened); + context.objects.release_reserved(opened); + } + if (status && status != 2) { + call.ret(status); + return; + } + if (status || !is_text(type)) data.assign(wide ? 2 : 1, 0); + else if (!wide) data = to_ansi_bytes(data, ansi_page); + if (!call[2]) { + if (call[3]) call.store(call[3], uint32_t(data.size())); + call.ret(0); + return; + } + const uint32_t capacity = call[3] ? call.load(call[3]) : 0; + if (call[3]) call.store(call[3], uint32_t(data.size())); + if (data.size() > capacity) { + call.ret(error_more_data); + return; + } + call.write(call[2], data); + call.ret(0); + }); registry.add("RegGetValueA", 7, [get_value](ApiCall &call) { get_value(call, false); }); // RegSetKeyValue creates the subkey when it is missing, then writes the value as RegSetValueEx does. for (const bool wide : {true, false}) diff --git a/native/nt/registry_words.inc b/native/nt/registry_words.inc index dd3a583..48cd681 100644 --- a/native/nt/registry_words.inc +++ b/native/nt/registry_words.inc @@ -6,6 +6,7 @@ {"ActivateActCtx", 2}, {"AddAccessAllowedAce", 4}, {"AddAccessDeniedAce", 4}, +{"AddAtomA", 1}, {"AddDllDirectory", 1}, {"AddVectoredContinueHandler", 2}, {"AddVectoredExceptionHandler", 2}, @@ -89,6 +90,7 @@ {"CertFreeCertificateContext", 1}, {"CertGetCertificateChain", 8}, {"CertGetCertificateContextProperty", 4}, +{"CertGetEnhancedKeyUsage", 4}, {"CertGetNameStringW", 6}, {"CertNameToStrW", 5}, {"CertOpenStore", 5}, @@ -122,7 +124,9 @@ {"CoInitializeEx", 2}, {"CoInitializeSecurity", 9}, {"CoLockObjectExternal", 3}, +{"CoRegisterClassObject", 5}, {"CoRegisterMessageFilter", 2}, +{"CoRevokeClassObject", 1}, {"CoTaskMemAlloc", 1}, {"CoTaskMemFree", 1}, {"CoTaskMemRealloc", 2}, @@ -138,6 +142,7 @@ {"ConnectEx", 7}, {"ConnectNamedPipe", 2}, {"ControlService", 3}, +{"ConvertInterfaceGuidToLuid", 2}, {"ConvertSidToStringSidW", 2}, {"ConvertStringSidToSidW", 2}, {"CopyFileExW", 6}, @@ -291,6 +296,7 @@ {"FileTimeToSystemTime", 2}, {"FillRect", 3}, {"FillRgn", 3}, +{"FindAtomA", 1}, {"FindClose", 1}, {"FindCloseChangeNotification", 1}, {"FindFirstChangeNotificationW", 3}, @@ -337,6 +343,7 @@ {"GetCaretBlinkTime", 0}, {"GetCaretPos", 1}, {"GetCharABCWidthsW", 4}, +{"GetCharWidth32W", 4}, {"GetCharWidthInfo", 2}, {"GetCharWidthW", 4}, {"GetClassWord", 2}, @@ -354,9 +361,12 @@ {"GetConsoleOutputCP", 0}, {"GetCurrentActCtx", 1}, {"GetCurrentDirectoryW", 2}, +{"GetCurrentInputMessageSource", 1}, {"GetCurrentProcess", 0}, +{"GetCurrentProcessExplicitAppUserModelID", 1}, {"GetCurrentThread", 0}, {"GetCursor", 0}, +{"GetCursorInfo", 1}, {"GetCursorPos", 1}, {"GetDCEx", 3}, {"GetDIBColorTable", 4}, @@ -375,6 +385,7 @@ {"GetDynamicTimeZoneInformation", 1}, {"GetEnvironmentStringsW", 0}, {"GetEnvironmentVariableW", 3}, +{"GetErrorMode", 0}, {"GetExitCodeProcess", 2}, {"GetExitCodeThread", 2}, {"GetExtendedTcpTable", 6}, @@ -400,6 +411,7 @@ {"GetGuiResources", 2}, {"GetHandleInformation", 2}, {"GetICMProfileW", 3}, +{"GetIfEntry2", 1}, {"GetIsImmersiveColorUsingHighContrast", 1}, {"GetKeyNameTextW", 3}, {"GetKeyState", 1}, @@ -507,6 +519,7 @@ {"GetSystemMenu", 2}, {"GetSystemMetrics", 1}, {"GetSystemMetricsForDpi", 2}, +{"GetSystemPaletteUse", 1}, {"GetSystemPowerStatus", 1}, {"GetSystemPreferredUILanguages", 4}, {"GetSystemTime", 1}, @@ -561,6 +574,7 @@ {"GetUserNameExW", 3}, {"GetUserObjectInformationW", 5}, {"GetUserPreferredUILanguages", 4}, +{"GetUserProfileDirectoryW", 3}, {"GetVersion", 0}, {"GetVersionExA", 1}, {"GetVersionExW", 1}, @@ -616,6 +630,7 @@ {"ImmGetIMEFileNameA", 3}, {"ImmGetIMEFileNameW", 3}, {"ImmGetOpenStatus", 1}, +{"ImmGetProperty", 2}, {"ImmIsIME", 1}, {"ImmNotifyIME", 4}, {"ImmReleaseContext", 2}, @@ -625,6 +640,7 @@ {"ImmSetCompositionWindow", 2}, {"ImmSetOpenStatus", 2}, {"InflateRect", 3}, +{"InheritWindowMonitor", 2}, {"InitOnceBeginInitialize", 4}, {"InitOnceComplete", 3}, {"InitOnceExecuteOnce", 4}, @@ -695,6 +711,7 @@ {"IsDestinationReachableW", 2}, {"IsEnclaveTypeSupported", 1}, {"IsIconic", 1}, +{"IsImmersiveProcess", 1}, {"IsNetworkAlive", 1}, {"IsProcessDPIAware", 0}, {"IsProcessInJob", 3}, @@ -711,8 +728,10 @@ {"IsValidLocale", 2}, {"IsValidSecurityDescriptor", 1}, {"IsValidSid", 1}, +{"IsWinEventHookInstalled", 1}, {"IsWindowArranged", 1}, {"IsWindowEnabled", 1}, +{"IsWindowRedirectedForPrint", 1}, {"IsWow64Process", 2}, {"IsWow64Process2", 3}, {"IsZoomed", 1}, @@ -734,6 +753,7 @@ {"LoadImageW", 6}, {"LoadMenuA", 2}, {"LoadStringA", 4}, +{"LoadUserProfileW", 2}, {"LocalAlloc", 2}, {"LocalFree", 1}, {"LocalLock", 1}, @@ -801,6 +821,8 @@ {"OleUninitialize", 0}, {"OpenClipboard", 1}, {"OpenDesktopW", 4}, +{"OpenEventLogA", 2}, +{"OpenEventLogW", 2}, {"OpenEventW", 3}, {"OpenFileMappingW", 3}, {"OpenJobObjectW", 3}, @@ -853,6 +875,7 @@ {"PolylineTo", 3}, {"PostMessageA", 4}, {"PostQueuedCompletionStatus", 4}, +{"PowerDeterminePlatformRoleEx", 1}, {"PrefetchVirtualMemory", 4}, {"Process32First", 2}, {"Process32FirstW", 2}, @@ -860,6 +883,7 @@ {"Process32NextW", 2}, {"ProcessIdToSessionId", 2}, {"ProcessPrng", 2}, +{"PulseEvent", 1}, {"QueryDepthSList", 1}, {"QueryDisplayConfig", 6}, {"QueryInformationJobObject", 5}, @@ -932,8 +956,10 @@ {"RegOpenKeyW", 3}, {"RegQueryInfoKeyA", 12}, {"RegQueryInfoKeyW", 12}, +{"RegQueryValueA", 4}, {"RegQueryValueExA", 6}, {"RegQueryValueExW", 6}, +{"RegQueryValueW", 4}, {"RegSetValueExA", 6}, {"RegSetValueExW", 6}, {"RegisterApplicationRestart", 2}, @@ -949,6 +975,7 @@ {"RegisterServiceCtrlHandlerExW", 3}, {"RegisterServiceCtrlHandlerW", 2}, {"RegisterSuspendResumeNotification", 2}, +{"RegisterTouchHitTestingWindow", 2}, {"RegisterTouchWindow", 2}, {"RegisterTraceGuidsW", 8}, {"RegisterWaitForSingleObject", 6}, @@ -968,6 +995,7 @@ {"RemoveVectoredContinueHandler", 1}, {"RemoveVectoredExceptionHandler", 1}, {"ReplaceFileW", 6}, +{"ResolveLocaleName", 3}, {"RestoreDC", 2}, {"ResumeThread", 1}, {"RevokeDragDrop", 1}, @@ -1013,12 +1041,15 @@ {"SHGetFolderPathW", 5}, {"SHGetKnownFolderPath", 4}, {"SHGetPathFromIDListW", 2}, +{"SHGetSettings", 2}, {"SHGetSpecialFolderLocation", 3}, {"SHGetSpecialFolderPathW", 4}, {"SLGetWindowsInformation", 4}, {"SLGetWindowsInformationDWORD", 2}, {"SaveDC", 1}, +{"ScriptApplyDigitSubstitution", 3}, {"ScriptBreak", 4}, +{"ScriptGetFontProperties", 3}, {"ScriptStringAnalyse", 13}, {"ScriptStringCPtoX", 4}, {"ScriptStringFree", 1}, @@ -1085,7 +1116,9 @@ {"SetProcessDPIAware", 0}, {"SetProcessDpiAwareness", 1}, {"SetProcessDpiAwarenessContext", 1}, +{"SetProcessInformation", 4}, {"SetProcessMitigationPolicy", 3}, +{"SetProcessPriorityBoost", 2}, {"SetProcessShutdownParameters", 2}, {"SetProcessWindowStation", 1}, {"SetPropA", 3}, @@ -1110,15 +1143,16 @@ {"SetThreadDescription", 2}, {"SetThreadDesktop", 1}, {"SetThreadDpiAwarenessContext", 1}, -{"SetThreadPreferredUILanguages", 3}, {"SetThreadErrorMode", 3}, {"SetThreadInformation", 4}, {"SetThreadLocale", 1}, +{"SetThreadPreferredUILanguages", 3}, {"SetThreadPriority", 2}, {"SetThreadPriorityBoost", 2}, {"SetThreadStackGuarantee", 1}, {"SetTokenInformation", 4}, {"SetUnhandledExceptionFilter", 1}, +{"SetUserObjectInformationW", 4}, {"SetViewportOrgEx", 4}, {"SetWinEventHook", 7}, {"SetWindowContextHelpId", 2}, @@ -1202,6 +1236,7 @@ {"UnhookWinEvent", 1}, {"UnhookWindowsHookEx", 1}, {"UnionRect", 3}, +{"UnloadUserProfile", 2}, {"UnlockFile", 5}, {"UnlockFileEx", 5}, {"UnmapViewOfFile", 1}, @@ -1214,6 +1249,7 @@ {"UnregisterTraceGuids", 1}, {"UnregisterWait", 1}, {"UnregisterWaitEx", 2}, +{"UpdateLayeredWindow", 9}, {"UpdateProcThreadAttribute", 7}, {"UrlFixupW", 3}, {"VariantClear", 1}, @@ -1222,6 +1258,7 @@ {"VerQueryValueW", 4}, {"VerSetConditionMask", 3}, {"VerifyVersionInfoW", 3}, +{"VkKeyScanExW", 2}, {"VkKeyScanW", 1}, {"WSACleanup", 0}, {"WSACloseEvent", 1}, @@ -1246,8 +1283,10 @@ {"WSASocketA", 6}, {"WSASocketW", 6}, {"WSAStartup", 2}, +{"WTSEnumerateSessionsW", 5}, {"WTSFreeMemory", 1}, {"WTSQuerySessionInformationW", 5}, +{"WTSQueryUserToken", 2}, {"WTSRegisterSessionNotification", 2}, {"WTSUnRegisterSessionNotification", 1}, {"WaitForInputIdle", 2}, @@ -1293,6 +1332,8 @@ {"WindowsGetStringLen", 1}, {"WindowsGetStringRawBuffer", 2}, {"WindowsIsStringEmpty", 1}, +{"Wow64DisableWow64FsRedirection", 1}, +{"Wow64RevertWow64FsRedirection", 1}, {"WriteConsoleW", 5}, {"WriteFile", 5}, {"WritePrivateProfileStringW", 4}, diff --git a/native/nt/text_api.cpp b/native/nt/text_api.cpp index 7fdbfbf..ac056dc 100644 --- a/native/nt/text_api.cpp +++ b/native/nt/text_api.cpp @@ -1093,6 +1093,16 @@ void register_text_api(ApiRegistry ®istry, KernelContext &context) call.put_wide(buffer, name, size_t(capacity)); call.ret(name.size() + 1); }; + // The one locale there is answers for its own name, its language alone, and no name at all. + registry.add("ResolveLocaleName", 3, [locale_name](ApiCall &call) { + const auto name = call[0] ? call.wide(call[0], 85) : std::u16string{}; + if (!name.empty() && compare_fold(name, u"en-US") != 0 && compare_fold(name, u"en") != 0) { + if (call[1] && call.i32(2) > 0) call.put_wide(call[1], u"", size_t(call.i32(2))); + call.ret(1); + return; + } + locale_name(call, call[1], call[1] ? call.i32(2) : 0); + }); registry.add("GetUserDefaultLocaleName", 2, [locale_name](ApiCall &call) { locale_name(call, call[0], call.i32(1)); }); registry.add("GetSystemDefaultLocaleName", 2, [locale_name](ApiCall &call) { locale_name(call, call[0], call.i32(1)); }); // A name the table does not know, as the culture-neutral "x-none" programs use, is not a locale. No name is the user's, the empty one