diff --git a/FEXCore/Source/Interface/Context/Context.h b/FEXCore/Source/Interface/Context/Context.h index 148cc3a52..d9309cdfa 100644 --- a/FEXCore/Source/Interface/Context/Context.h +++ b/FEXCore/Source/Interface/Context/Context.h @@ -87,6 +87,8 @@ namespace FEXCore::Context { ExitReason RunUntilExit() override; + void ExecuteThread(FEXCore::Core::InternalThreadState *Thread) override; + void CompileRIP(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestRIP) override; int GetProgramStatus() const override; diff --git a/FEXCore/Source/Interface/Core/Core.cpp b/FEXCore/Source/Interface/Core/Core.cpp index 25a7505b6..42836a1e9 100644 --- a/FEXCore/Source/Interface/Core/Core.cpp +++ b/FEXCore/Source/Interface/Core/Core.cpp @@ -561,6 +561,10 @@ namespace FEXCore::Context { } } + void ContextImpl::ExecuteThread(FEXCore::Core::InternalThreadState *Thread) { + Dispatcher->ExecuteDispatch(Thread->CurrentFrame); + } + int ContextImpl::GetProgramStatus() const { return ParentThread->StatusCode; } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index a5b5c945d..acf89a2ad 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -71,11 +71,6 @@ void OpDispatchBuilder::SyscallOp(OpcodeArgs) { FEXCore::X86State::REG_RSP, }; - static constexpr SyscallArray GPRIndexes_Win32 = { - FEXCore::X86State::REG_RAX, - FEXCore::X86State::REG_RSP, - }; - SyscallFlags DefaultSyscallFlags = FEXCore::IR::SyscallFlags::DEFAULT; const auto OSABI = CTX->SyscallHandler->GetOSABI(); @@ -93,8 +88,9 @@ void OpDispatchBuilder::SyscallOp(OpcodeArgs) { DefaultSyscallFlags = FEXCore::IR::SyscallFlags::NORETURNEDRESULT; } else if (OSABI == FEXCore::HLE::SyscallOSABI::OS_WIN32) { - NumArguments = 2; - GPRIndexes = &GPRIndexes_Win32; + // Since the whole context is going to be saved at entry anyway, theres no need to do additional work to pass in args + NumArguments = 0; + GPRIndexes = nullptr; DefaultSyscallFlags = FEXCore::IR::SyscallFlags::NORETURNEDRESULT; } else if (OSABI == FEXCore::HLE::SyscallOSABI::OS_HANGOVER) { diff --git a/FEXCore/include/FEXCore/Core/Context.h b/FEXCore/include/FEXCore/Core/Context.h index 3b14bdfcd..661280ec3 100644 --- a/FEXCore/include/FEXCore/Core/Context.h +++ b/FEXCore/include/FEXCore/Core/Context.h @@ -176,6 +176,11 @@ namespace FEXCore::Context { */ FEX_DEFAULT_VISIBILITY virtual ExitReason RunUntilExit() = 0; + /** + * @brief Executes the supplied thread context on the current thread until a return is requested + */ + FEX_DEFAULT_VISIBILITY virtual void ExecuteThread(FEXCore::Core::InternalThreadState *Thread) = 0; + FEX_DEFAULT_VISIBILITY virtual void CompileRIP(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestRIP) = 0; /** diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 23f435815..7514e23ec 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -1,2 +1,6 @@ add_subdirectory(Common/) add_subdirectory(Tools/) + +if (MINGW_BUILD) + add_subdirectory(Windows/) +endif() diff --git a/Source/Windows/CMakeLists.txt b/Source/Windows/CMakeLists.txt new file mode 100644 index 000000000..3e2a3f205 --- /dev/null +++ b/Source/Windows/CMakeLists.txt @@ -0,0 +1,19 @@ +function(build_implib name) + add_custom_target(${name}lib ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.a) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.a + COMMAND ${CMAKE_DLLTOOL} -d ${CMAKE_CURRENT_SOURCE_DIR}/Defs/${name}.def -k -l lib${name}.a + COMMENT "Building lib${name}.a" + ) + + add_library(${name} SHARED IMPORTED) + set_property(TARGET ${name} PROPERTY IMPORTED_IMPLIB ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.a) + add_dependencies(${name} ${name}lib) +endfunction() + +build_implib(ntdll) +build_implib(wow64) + +if (_M_ARM_64) + add_subdirectory(WOW64) +endif() diff --git a/Source/Windows/Defs/ntdll.def b/Source/Windows/Defs/ntdll.def new file mode 100644 index 000000000..c6ba3b8e7 --- /dev/null +++ b/Source/Windows/Defs/ntdll.def @@ -0,0 +1,1378 @@ +; File generated automatically from wine/dlls/ntdll/ntdll.spec; do not edit! +; To generate: winebuild --def -E wine/dlls/ntdll/ntdll.spec > ntdll.def + +LIBRARY ntdll.dll + +EXPORTS + A_SHAFinal @1 + A_SHAInit @2 + A_SHAUpdate @3 + ApiSetQueryApiSetPresence @4 + ApiSetQueryApiSetPresenceEx @5 + CsrAllocateCaptureBuffer @6 PRIVATE + CsrAllocateCapturePointer @7 PRIVATE + CsrAllocateMessagePointer @8 PRIVATE + CsrCaptureMessageBuffer @9 PRIVATE + CsrCaptureMessageString @10 PRIVATE + CsrCaptureTimeout @11 PRIVATE + CsrClientCallServer @12 PRIVATE + CsrClientConnectToServer @13 PRIVATE + CsrClientMaxMessage @14 PRIVATE + CsrClientSendMessage @15 PRIVATE + CsrClientThreadConnect @16 PRIVATE + CsrFreeCaptureBuffer @17 PRIVATE + CsrIdentifyAlertableThread @18 PRIVATE + CsrNewThread @19 PRIVATE + CsrProbeForRead @20 PRIVATE + CsrProbeForWrite @21 PRIVATE + CsrSetPriorityClass @22 PRIVATE + CsrpProcessCallbackRequest @23 PRIVATE + DbgBreakPoint @24 + DbgPrint @25 + DbgPrintEx @26 + DbgPrompt @27 PRIVATE + DbgUiConnectToDbg @28 + DbgUiContinue @29 + DbgUiConvertStateChangeStructure @30 + DbgUiDebugActiveProcess @31 + DbgUiGetThreadDebugObject @32 + DbgUiIssueRemoteBreakin @33 + DbgUiRemoteBreakin @34 + DbgUiSetThreadDebugObject @35 + DbgUiStopDebugging @36 + DbgUiWaitStateChange @37 + DbgUserBreakPoint @38 + EtwEventActivityIdControl @39 + EtwEventEnabled @40 + EtwEventProviderEnabled @41 + EtwEventRegister @42 + EtwEventSetInformation @43 + EtwEventUnregister @44 + EtwEventWrite @45 + EtwEventWriteString @46 + EtwEventWriteTransfer @47 + EtwGetTraceEnableFlags @48 + EtwGetTraceEnableLevel @49 + EtwGetTraceLoggerHandle @50 + EtwLogTraceEvent @51 + EtwRegisterTraceGuidsA @52 + EtwRegisterTraceGuidsW @53 + EtwTraceMessage @54 + EtwTraceMessageVa @55 + EtwUnregisterTraceGuids @56 + KiRaiseUserExceptionDispatcher @57 + KiUserApcDispatcher @58 + KiUserCallbackDispatcher @59 + KiUserExceptionDispatcher @60 + LdrAccessResource @61 + LdrAddDllDirectory @62 + LdrAddRefDll @63 + LdrDisableThreadCalloutsForDll @64 + LdrEnumResources @65 PRIVATE + LdrEnumerateLoadedModules @66 + LdrFindEntryForAddress @67 + LdrFindResourceDirectory_U @68 + LdrFindResource_U @69 + LdrFlushAlternateResourceModules @70 PRIVATE + LdrGetDllDirectory @71 + LdrGetDllFullName @72 + LdrGetDllHandle @73 + LdrGetDllHandleEx @74 + LdrGetDllPath @75 + LdrGetProcedureAddress @76 + LdrInitShimEngineDynamic @77 PRIVATE + LdrInitializeThunk @78 + LdrLoadAlternateResourceModule @79 PRIVATE + LdrLoadDll @80 + LdrLockLoaderLock @81 + LdrProcessRelocationBlock @82 + LdrQueryImageFileExecutionOptions @83 + LdrQueryProcessModuleInformation @84 + LdrRegisterDllNotification @85 + LdrRemoveDllDirectory @86 + LdrResolveDelayLoadedAPI @87 + LdrSetAppCompatDllRedirectionCallback @88 PRIVATE + LdrSetDefaultDllDirectories @89 + LdrSetDllDirectory @90 + LdrSetDllManifestProber @91 PRIVATE + LdrShutdownProcess @92 + LdrShutdownThread @93 + LdrSystemDllInitBlock @94 DATA + LdrUnloadAlternateResourceModule @95 PRIVATE + LdrUnloadDll @96 + LdrUnlockLoaderLock @97 + LdrUnregisterDllNotification @98 + LdrVerifyImageMatchesChecksum @99 PRIVATE + MD4Final @100 + MD4Init @101 + MD4Update @102 + MD5Final @103 + MD5Init @104 + MD5Update @105 + NlsAnsiCodePage @106 DATA + NlsMbCodePageTag @107 DATA + NlsMbOemCodePageTag @108 DATA + NtAcceptConnectPort @109 + NtAccessCheck @110 + NtAccessCheckAndAuditAlarm @111 + NtAddAtom @112 + NtAdjustGroupsToken @113 + NtAdjustPrivilegesToken @114 + NtAlertResumeThread @115 + NtAlertThread @116 + NtAlertThreadByThreadId @117 + NtAllocateLocallyUniqueId @118 + NtAllocateUuids @119 + NtAllocateVirtualMemory @120 + NtAllocateVirtualMemoryEx @121 + NtAreMappedFilesTheSame @122 + NtAssignProcessToJobObject @123 + NtCallbackReturn @124 + NtCancelIoFile @125 + NtCancelIoFileEx @126 + NtCancelSynchronousIoFile @127 + NtCancelTimer @128 + NtClearEvent @129 + NtClose @130 + NtCommitTransaction @131 + NtCompareObjects @132 + NtCompleteConnectPort @133 + NtConnectPort @134 + NtContinue @135 + NtCreateDebugObject @136 + NtCreateDirectoryObject @137 + NtCreateEvent @138 + NtCreateFile @139 + NtCreateIoCompletion @140 + NtCreateJobObject @141 + NtCreateKey @142 + NtCreateKeyTransacted @143 + NtCreateKeyedEvent @144 + NtCreateLowBoxToken @145 + NtCreateMailslotFile @146 + NtCreateMutant @147 + NtCreateNamedPipeFile @148 + NtCreatePagingFile @149 + NtCreatePort @150 + NtCreateSection @151 + NtCreateSemaphore @152 + NtCreateSymbolicLinkObject @153 + NtCreateThread @154 + NtCreateThreadEx @155 + NtCreateTimer @156 + NtCreateTransaction @157 + NtCreateUserProcess @158 + NtDebugActiveProcess @159 + NtDebugContinue @160 + NtDelayExecution @161 + NtDeleteAtom @162 + NtDeleteFile @163 + NtDeleteKey @164 + NtDeleteValueKey @165 + NtDeviceIoControlFile @166 + NtDisplayString @167 + NtDuplicateObject @168 + NtDuplicateToken @169 + NtEnumerateKey @170 + NtEnumerateValueKey @171 + NtFilterToken @172 + NtFindAtom @173 + NtFlushBuffersFile @174 + NtFlushInstructionCache @175 + NtFlushKey @176 + NtFlushProcessWriteBuffers @177 + NtFlushVirtualMemory @178 + NtFreeVirtualMemory @179 + NtFsControlFile @180 + NtGetContextThread @181 + NtGetCurrentProcessorNumber @182 + NtGetNextThread @183 + NtGetNlsSectionPtr @184 + NtGetTickCount @185 + NtGetWriteWatch @186 + NtImpersonateAnonymousToken @187 + NtInitializeNlsFiles @188 + NtInitiatePowerAction @189 + NtIsProcessInJob @190 + NtListenPort @191 + NtLoadDriver @192 + NtLoadKey2 @193 + NtLoadKey @194 + NtLoadKeyEx @195 + NtLockFile @196 + NtLockVirtualMemory @197 + NtMakeTemporaryObject @198 + NtMapViewOfSection @199 + NtMapViewOfSectionEx @200 + NtNotifyChangeDirectoryFile @201 + NtNotifyChangeKey @202 + NtNotifyChangeMultipleKeys @203 + NtOpenDirectoryObject @204 + NtOpenEvent @205 + NtOpenFile @206 + NtOpenIoCompletion @207 + NtOpenJobObject @208 + NtOpenKey @209 + NtOpenKeyEx @210 + NtOpenKeyTransacted @211 + NtOpenKeyTransactedEx @212 + NtOpenKeyedEvent @213 + NtOpenMutant @214 + NtOpenProcess @215 + NtOpenProcessToken @216 + NtOpenProcessTokenEx @217 + NtOpenSection @218 + NtOpenSemaphore @219 + NtOpenSymbolicLinkObject @220 + NtOpenThread @221 + NtOpenThreadToken @222 + NtOpenThreadTokenEx @223 + NtOpenTimer @224 + NtPowerInformation @225 + NtPrivilegeCheck @226 + NtProtectVirtualMemory @227 + NtPulseEvent @228 + NtQueryAttributesFile @229 + NtQueryDefaultLocale @230 + NtQueryDefaultUILanguage @231 + NtQueryDirectoryFile @232 + NtQueryDirectoryObject @233 + NtQueryEaFile @234 + NtQueryEvent @235 + NtQueryFullAttributesFile @236 + NtQueryInformationAtom @237 + NtQueryInformationFile @238 + NtQueryInformationJobObject @239 + NtQueryInformationProcess @240 + NtQueryInformationThread @241 + NtQueryInformationToken @242 + NtQueryInstallUILanguage @243 + NtQueryIoCompletion @244 + NtQueryKey @245 + NtQueryLicenseValue @246 + NtQueryMultipleValueKey @247 + NtQueryMutant @248 + NtQueryObject @249 + NtQueryPerformanceCounter @250 + NtQuerySection @251 + NtQuerySecurityObject @252 + NtQuerySemaphore @253 + NtQuerySymbolicLinkObject @254 + NtQuerySystemEnvironmentValue @255 + NtQuerySystemEnvironmentValueEx @256 + NtQuerySystemInformation @257 + NtQuerySystemInformationEx @258 + NtQuerySystemTime @259 + NtQueryTimer @260 + NtQueryTimerResolution @261 + NtQueryValueKey @262 + NtQueryVirtualMemory @263 + NtQueryVolumeInformationFile @264 + NtQueueApcThread @265 + NtRaiseException @266 + NtRaiseHardError @267 + NtReadFile @268 + NtReadFileScatter @269 + NtReadVirtualMemory @270 + NtRegisterThreadTerminatePort @271 + NtReleaseKeyedEvent @272 + NtReleaseMutant @273 + NtReleaseSemaphore @274 + NtRemoveIoCompletion @275 + NtRemoveIoCompletionEx @276 + NtRemoveProcessDebug @277 + NtRenameKey @278 + NtReplaceKey @279 + NtReplyWaitReceivePort @280 + NtRequestWaitReplyPort @281 + NtResetEvent @282 + NtResetWriteWatch @283 + NtRestoreKey @284 + NtResumeProcess @285 + NtResumeThread @286 + NtRollbackTransaction @287 + NtSaveKey @288 + NtSecureConnectPort @289 + NtSetContextThread @290 + NtSetDebugFilterState @291 + NtSetDefaultLocale @292 + NtSetDefaultUILanguage @293 + NtSetEaFile @294 + NtSetEvent @295 + NtSetInformationDebugObject @296 + NtSetInformationFile @297 + NtSetInformationJobObject @298 + NtSetInformationKey @299 + NtSetInformationObject @300 + NtSetInformationProcess @301 + NtSetInformationThread @302 + NtSetInformationToken @303 + NtSetInformationVirtualMemory @304 + NtSetIntervalProfile @305 + NtSetIoCompletion @306 + NtSetLdtEntries @307 + NtSetSecurityObject @308 + NtSetSystemInformation @309 + NtSetSystemTime @310 + NtSetThreadExecutionState @311 + NtSetTimer @312 + NtSetTimerResolution @313 + NtSetValueKey @314 + NtSetVolumeInformationFile @315 + NtShutdownSystem @316 + NtSignalAndWaitForSingleObject @317 + NtSuspendProcess @318 + NtSuspendThread @319 + NtSystemDebugControl @320 + NtTerminateJobObject @321 + NtTerminateProcess @322 + NtTerminateThread @323 + NtTestAlert @324 + NtTraceControl @325 + NtUnloadDriver @326 + NtUnloadKey @327 + NtUnlockFile @328 + NtUnlockVirtualMemory @329 + NtUnmapViewOfSection @330 + NtUnmapViewOfSectionEx @331 + NtWaitForAlertByThreadId @332 + NtWaitForDebugEvent @333 + NtWaitForKeyedEvent @334 + NtWaitForMultipleObjects @335 + NtWaitForSingleObject @336 + NtWriteFile @337 + NtWriteFileGather @338 + NtWriteVirtualMemory @339 + NtYieldExecution @340 + PfxFindPrefix @341 PRIVATE + PfxInitialize @342 PRIVATE + PfxInsertPrefix @343 PRIVATE + PfxRemovePrefix @344 PRIVATE + RtlAbortRXact @345 PRIVATE + RtlAbsoluteToSelfRelativeSD @346 + RtlAcquirePebLock @347 + RtlAcquireResourceExclusive @348 + RtlAcquireResourceShared @349 + RtlAcquireSRWLockExclusive @350 + RtlAcquireSRWLockShared @351 + RtlActivateActivationContext @352 + RtlActivateActivationContextEx @353 + RtlActivateActivationContextUnsafeFast @354 PRIVATE + RtlAddAccessAllowedAce @355 + RtlAddAccessAllowedAceEx @356 + RtlAddAccessAllowedObjectAce @357 + RtlAddAccessDeniedAce @358 + RtlAddAccessDeniedAceEx @359 + RtlAddAccessDeniedObjectAce @360 + RtlAddAce @361 + RtlAddActionToRXact @362 PRIVATE + RtlAddAtomToAtomTable @363 + RtlAddAttributeActionToRXact @364 PRIVATE + RtlAddAuditAccessAce @365 + RtlAddAuditAccessAceEx @366 + RtlAddAuditAccessObjectAce @367 + RtlAddFunctionTable @368 + RtlAddGrowableFunctionTable @369 + RtlAddMandatoryAce @370 + RtlAddProcessTrustLabelAce @371 + RtlAddRefActivationContext @372 + RtlAddVectoredContinueHandler @373 + RtlAddVectoredExceptionHandler @374 + RtlAddressInSectionTable @375 + RtlAdjustPrivilege @376 + RtlAllocateAndInitializeSid @377 + RtlAllocateHandle @378 + RtlAllocateHeap @379 + RtlAnsiCharToUnicodeChar @380 + RtlAnsiStringToUnicodeSize @381 + RtlAnsiStringToUnicodeString @382 + RtlAppendAsciizToString @383 + RtlAppendStringToString @384 + RtlAppendUnicodeStringToString @385 + RtlAppendUnicodeToString @386 + RtlApplyRXact @387 PRIVATE + RtlApplyRXactNoFlush @388 PRIVATE + RtlAreAllAccessesGranted @389 + RtlAreAnyAccessesGranted @390 + RtlAreBitsClear @391 + RtlAreBitsSet @392 + RtlAssert @393 + RtlCaptureContext @394 + RtlCaptureStackBackTrace @395 + RtlCharToInteger @396 + RtlCheckRegistryKey @397 + RtlClearAllBits @398 + RtlClearBits @399 + RtlClosePropertySet @400 PRIVATE + RtlCompactHeap @401 + RtlCompareMemory @402 + RtlCompareMemoryUlong @403 + RtlCompareString @404 + RtlCompareUnicodeString @405 + RtlCompareUnicodeStrings @406 + RtlCompressBuffer @407 + RtlComputeCrc32 @408 + RtlConsoleMultiByteToUnicodeN @409 PRIVATE + RtlConvertExclusiveToShared @410 PRIVATE + RtlConvertSharedToExclusive @411 PRIVATE + RtlConvertSidToUnicodeString @412 + RtlConvertToAutoInheritSecurityObject @413 + RtlConvertUiListToApiList @414 PRIVATE + RtlCopyContext @415 + RtlCopyExtendedContext @416 + RtlCopyLuid @417 + RtlCopyLuidAndAttributesArray @418 + RtlCopyMemory @419 + RtlCopyMemoryNonTemporal=RtlCopyMemory @420 + RtlCopySecurityDescriptor @421 + RtlCopySid @422 + RtlCopySidAndAttributesArray @423 PRIVATE + RtlCopyString @424 + RtlCopyUnicodeString @425 + RtlCreateAcl @426 + RtlCreateActivationContext @427 + RtlCreateAndSetSD @428 PRIVATE + RtlCreateAtomTable @429 + RtlCreateEnvironment @430 + RtlCreateHeap @431 + RtlCreateProcessParameters @432 + RtlCreateProcessParametersEx @433 + RtlCreatePropertySet @434 PRIVATE + RtlCreateQueryDebugBuffer @435 + RtlCreateRegistryKey @436 + RtlCreateSecurityDescriptor @437 + RtlCreateTagHeap @438 PRIVATE + RtlCreateTimer @439 + RtlCreateTimerQueue @440 + RtlCreateUnicodeString @441 + RtlCreateUnicodeStringFromAsciiz @442 + RtlCreateUserProcess @443 + RtlCreateUserSecurityObject @444 PRIVATE + RtlCreateUserStack @445 + RtlCreateUserThread @446 + RtlCustomCPToUnicodeN @447 + RtlCutoverTimeToSystemTime @448 PRIVATE + RtlDeNormalizeProcessParams @449 + RtlDeactivateActivationContext @450 + RtlDeactivateActivationContextUnsafeFast @451 PRIVATE + RtlDebugPrintTimes @452 PRIVATE + RtlDecodePointer @453 + RtlDecodeSystemPointer=RtlDecodePointer @454 + RtlDecompressBuffer @455 + RtlDecompressFragment @456 + RtlDefaultNpAcl @457 + RtlDelete @458 PRIVATE + RtlDeleteAce @459 + RtlDeleteAtomFromAtomTable @460 + RtlDeleteCriticalSection @461 + RtlDeleteGrowableFunctionTable @462 + RtlDeleteElementGenericTable @463 PRIVATE + RtlDeleteElementGenericTableAvl @464 PRIVATE + RtlDeleteFunctionTable @465 + RtlDeleteNoSplay @466 PRIVATE + RtlDeleteOwnersRanges @467 PRIVATE + RtlDeleteRange @468 PRIVATE + RtlDeleteRegistryValue @469 + RtlDeleteResource @470 + RtlDeleteSecurityObject @471 + RtlDeleteTimer @472 + RtlDeleteTimerQueueEx @473 + RtlDeregisterWait @474 + RtlDeregisterWaitEx @475 + RtlDestroyAtomTable @476 + RtlDestroyEnvironment @477 + RtlDestroyHandleTable @478 + RtlDestroyHeap @479 + RtlDestroyProcessParameters @480 + RtlDestroyQueryDebugBuffer @481 + RtlDetermineDosPathNameType_U @482 + RtlDllShutdownInProgress @483 + RtlDoesFileExists_U @484 + RtlDosPathNameToNtPathName_U @485 + RtlDosPathNameToNtPathName_U_WithStatus @486 + RtlDosPathNameToRelativeNtPathName_U @487 + RtlDosPathNameToRelativeNtPathName_U_WithStatus @488 + RtlDosSearchPath_U @489 + RtlDowncaseUnicodeChar @490 + RtlDowncaseUnicodeString @491 + RtlDumpResource @492 + RtlDuplicateUnicodeString @493 + RtlEmptyAtomTable @494 + RtlEncodePointer @495 + RtlEncodeSystemPointer=RtlEncodePointer @496 + RtlEnterCriticalSection @497 + RtlEnumProcessHeaps @498 PRIVATE + RtlEnumerateGenericTable @499 PRIVATE + RtlEnumerateGenericTableWithoutSplaying @500 + RtlEnumerateProperties @501 PRIVATE + RtlEqualComputerName @502 + RtlEqualDomainName @503 + RtlEqualLuid @504 + RtlEqualPrefixSid @505 + RtlEqualSid @506 + RtlEqualString @507 + RtlEqualUnicodeString @508 + RtlEraseUnicodeString @509 + RtlExitUserProcess @510 + RtlExitUserThread @511 + RtlExpandEnvironmentStrings @512 + RtlExpandEnvironmentStrings_U @513 + RtlExtendHeap @514 PRIVATE + RtlFillMemory @515 + RtlFillMemoryUlong @516 + RtlFinalReleaseOutOfProcessMemoryStream @517 PRIVATE + RtlFindActivationContextSectionGuid @518 + RtlFindActivationContextSectionString @519 + RtlFindCharInUnicodeString @520 + RtlFindClearBits @521 + RtlFindClearBitsAndSet @522 + RtlFindClearRuns @523 + RtlFindExportedRoutineByName @524 + RtlFindLastBackwardRunClear @525 + RtlFindLastBackwardRunSet @526 + RtlFindLeastSignificantBit @527 + RtlFindLongestRunClear @528 + RtlFindLongestRunSet @529 + RtlFindMessage @530 + RtlFindMostSignificantBit @531 + RtlFindNextForwardRunClear @532 + RtlFindNextForwardRunSet @533 + RtlFindRange @534 PRIVATE + RtlFindSetBits @535 + RtlFindSetBitsAndClear @536 + RtlFindSetRuns @537 + RtlFirstEntrySList @538 + RtlFirstFreeAce @539 + RtlFlsAlloc @540 + RtlFlsFree @541 + RtlFlsGetValue @542 + RtlFlsSetValue @543 + RtlFlushPropertySet @544 PRIVATE + RtlFormatCurrentUserKeyPath @545 + RtlFormatMessage @546 + RtlFormatMessageEx @547 + RtlFreeActivationContextStack @548 + RtlFreeAnsiString @549 + RtlFreeHandle @550 + RtlFreeHeap @551 + RtlFreeOemString @552 + RtlFreeSid @553 + RtlFreeThreadActivationContextStack @554 + RtlFreeUnicodeString @555 + RtlFreeUserStack @556 + RtlGUIDFromString @557 + RtlGenerate8dot3Name @558 PRIVATE + RtlGetAce @559 + RtlGetActiveActivationContext @560 + RtlGetCallersAddress @561 PRIVATE + RtlGetCompressionWorkSpaceSize @562 + RtlGetControlSecurityDescriptor @563 + RtlGetCurrentDirectory_U @564 + RtlGetCurrentPeb @565 + RtlGetCurrentProcessorNumberEx @566 + RtlGetCurrentTransaction @567 + RtlGetDaclSecurityDescriptor @568 + RtlGetElementGenericTable @569 + RtlGetEnabledExtendedFeatures @570 + RtlGetExePath @571 + RtlGetExtendedContextLength @572 + RtlGetExtendedContextLength2 @573 + RtlGetExtendedFeaturesMask @574 + RtlGetFrame @575 + RtlGetFullPathName_U @576 + RtlGetGroupSecurityDescriptor @577 + RtlGetLastNtStatus @578 + RtlGetLastWin32Error @579 + RtlGetLocaleFileMappingAddress @580 + RtlGetLongestNtPathLength @581 + RtlGetNativeSystemInformation=NtQuerySystemInformation @582 + RtlGetNtGlobalFlags @583 + RtlGetNtProductType @584 + RtlGetNtVersionNumbers @585 + RtlGetOwnerSecurityDescriptor @586 + RtlGetProductInfo @587 + RtlGetProcessHeaps @588 + RtlGetProcessPreferredUILanguages @589 + RtlGetSaclSecurityDescriptor @590 + RtlGetSearchPath @591 + RtlGetSystemPreferredUILanguages @592 + RtlGetSystemTimePrecise @593 + RtlGetThreadErrorMode @594 + RtlGetThreadPreferredUILanguages @595 + RtlGetUnloadEventTrace @596 + RtlGetUnloadEventTraceEx @597 + RtlGetUserInfoHeap @598 + RtlGetUserPreferredUILanguages @599 + RtlGetVersion @600 + RtlGrowFunctionTable @601 + RtlGuidToPropertySetName @602 PRIVATE + RtlHashUnicodeString @603 + RtlIdentifierAuthoritySid @604 + RtlIdnToAscii @605 + RtlIdnToNameprepUnicode @606 + RtlIdnToUnicode @607 + RtlImageDirectoryEntryToData @608 + RtlImageNtHeader @609 + RtlImageRvaToSection @610 + RtlImageRvaToVa @611 + RtlImpersonateSelf @612 + RtlInitAnsiString @613 + RtlInitAnsiStringEx @614 + RtlInitCodePageTable @615 + RtlInitNlsTables @616 + RtlInitString @617 + RtlInitUnicodeString @618 + RtlInitUnicodeStringEx @619 + RtlInitializeBitMap @620 + RtlInitializeConditionVariable @621 + RtlInitializeContext @622 PRIVATE + RtlInitializeCriticalSection @623 + RtlInitializeCriticalSectionAndSpinCount @624 + RtlInitializeCriticalSectionEx @625 + RtlInitializeExtendedContext @626 + RtlInitializeExtendedContext2 @627 + RtlInitializeGenericTable @628 + RtlInitializeGenericTableAvl @629 + RtlInitializeHandleTable @630 + RtlInitializeRXact @631 PRIVATE + RtlInitializeResource @632 + RtlInitializeSListHead @633 + RtlInitializeSRWLock @634 + RtlInitializeSid @635 + RtlInsertElementGenericTable @636 PRIVATE + RtlInsertElementGenericTableAvl @637 + RtlInstallFunctionTableCallback @638 + RtlInt64ToUnicodeString @639 + RtlIntegerToChar @640 + RtlIntegerToUnicodeString @641 + RtlInterlockedFlushSList @642 + RtlInterlockedPopEntrySList @643 + RtlInterlockedPushEntrySList @644 + RtlInterlockedPushListSList @645 + RtlInterlockedPushListSListEx @646 + RtlIpv4AddressToStringA @647 + RtlIpv4AddressToStringExA @648 + RtlIpv4AddressToStringExW @649 + RtlIpv4AddressToStringW @650 + RtlIpv4StringToAddressA @651 + RtlIpv4StringToAddressExA @652 + RtlIpv4StringToAddressExW @653 + RtlIpv4StringToAddressW @654 + RtlIpv6AddressToStringA @655 + RtlIpv6AddressToStringExA @656 + RtlIpv6AddressToStringExW @657 + RtlIpv6AddressToStringW @658 + RtlIpv6StringToAddressA @659 + RtlIpv6StringToAddressExA @660 + RtlIpv6StringToAddressExW @661 + RtlIpv6StringToAddressW @662 + RtlIsActivationContextActive @663 + RtlIsCriticalSectionLocked @664 + RtlIsCriticalSectionLockedByThread @665 + RtlIsCurrentProcess @666 + RtlIsCurrentThread @667 + RtlIsDosDeviceName_U @668 + RtlIsEcCode @669 + RtlIsGenericTableEmpty @670 PRIVATE + RtlIsNameLegalDOS8Dot3 @671 + RtlIsNormalizedString @672 + RtlIsProcessorFeaturePresent @673 + RtlIsTextUnicode @674 + RtlIsValidHandle @675 + RtlIsValidIndexHandle @676 + RtlIsValidLocaleName @677 + RtlLargeIntegerToChar @678 + RtlLcidToLocaleName @679 + RtlLeaveCriticalSection @680 + RtlLengthRequiredSid @681 + RtlLengthSecurityDescriptor @682 + RtlLengthSid @683 + RtlLocalTimeToSystemTime @684 + RtlLocaleNameToLcid @685 + RtlLocateExtendedFeature @686 + RtlLocateExtendedFeature2 @687 + RtlLocateLegacyContext @688 + RtlLockHeap @689 + RtlLookupAtomInAtomTable @690 + RtlLookupElementGenericTable @691 + RtlLookupFunctionEntry @692 + RtlMakeSelfRelativeSD @693 + RtlMapGenericMask @694 + RtlMoveMemory @695 + RtlMultiByteToUnicodeN @696 + RtlMultiByteToUnicodeSize @697 + RtlNewInstanceSecurityObject @698 PRIVATE + RtlNewSecurityGrantedAccess @699 PRIVATE + RtlNewSecurityObject @700 + RtlNewSecurityObjectEx @701 + RtlNewSecurityObjectWithMultipleInheritance @702 + RtlNormalizeProcessParams @703 + RtlNormalizeString @704 + RtlNtStatusToDosError @705 + RtlNtStatusToDosErrorNoTeb @706 + RtlNumberGenericTableElements @707 + RtlNumberOfClearBits @708 + RtlNumberOfSetBits @709 + RtlOemStringToUnicodeSize @710 + RtlOemStringToUnicodeString @711 + RtlOemToUnicodeN @712 + RtlOpenCurrentUser @713 + RtlPcToFileHeader @714 + RtlPinAtomInAtomTable @715 + RtlPopFrame @716 + RtlPrefixString @717 + RtlPrefixUnicodeString @718 + RtlProcessFlsData @719 + RtlPropertySetNameToGuid @720 PRIVATE + RtlProtectHeap @721 PRIVATE + RtlPushFrame @722 + RtlQueryActivationContextApplicationSettings @723 + RtlQueryAtomInAtomTable @724 + RtlQueryDepthSList @725 + RtlQueryDynamicTimeZoneInformation @726 + RtlQueryEnvironmentVariable_U @727 + RtlQueryEnvironmentVariable @728 + RtlQueryHeapInformation @729 + RtlQueryInformationAcl @730 + RtlQueryInformationActivationContext @731 + RtlQueryInformationActiveActivationContext @732 PRIVATE + RtlQueryInterfaceMemoryStream @733 PRIVATE + RtlQueryPackageIdentity @734 + RtlQueryPerformanceCounter @735 + RtlQueryPerformanceFrequency @736 + RtlQueryProcessBackTraceInformation @737 PRIVATE + RtlQueryProcessDebugInformation @738 + RtlQueryProcessHeapInformation @739 PRIVATE + RtlQueryProcessLockInformation @740 PRIVATE + RtlQueryProcessPlaceholderCompatibilityMode @741 + RtlQueryProperties @742 PRIVATE + RtlQueryPropertyNames @743 PRIVATE + RtlQueryPropertySet @744 PRIVATE + RtlQueryRegistryValues @745 + RtlQueryRegistryValuesEx=RtlQueryRegistryValues @746 + RtlQuerySecurityObject @747 PRIVATE + RtlQueryTagHeap @748 PRIVATE + RtlQueryTimeZoneInformation @749 + RtlQueryUnbiasedInterruptTime @750 + RtlQueueApcWow64Thread @751 PRIVATE + RtlQueueWorkItem @752 + RtlRaiseException @753 + RtlRaiseStatus @754 + RtlRandom @755 + RtlRandomEx @756 + RtlReAllocateHeap @757 + RtlReadMemoryStream @758 PRIVATE + RtlReadOutOfProcessMemoryStream @759 PRIVATE + RtlRealPredecessor @760 PRIVATE + RtlRealSuccessor @761 PRIVATE + RtlRegisterSecureMemoryCacheCallback @762 PRIVATE + RtlRegisterWait @763 + RtlReleaseActivationContext @764 + RtlReleaseMemoryStream @765 PRIVATE + RtlReleasePath @766 + RtlReleasePebLock @767 + RtlReleaseRelativeName @768 + RtlReleaseResource @769 + RtlReleaseSRWLockExclusive @770 + RtlReleaseSRWLockShared @771 + RtlRemoteCall @772 PRIVATE + RtlRemoveVectoredContinueHandler @773 + RtlRemoveVectoredExceptionHandler @774 + RtlResetRtlTranslations @775 + RtlRestoreContext @776 + RtlRestoreLastWin32Error=RtlSetLastWin32Error @777 + RtlRevertMemoryStream @778 PRIVATE + RtlRunDecodeUnicodeString @779 PRIVATE + RtlRunEncodeUnicodeString @780 PRIVATE + RtlRunOnceBeginInitialize @781 + RtlRunOnceComplete @782 + RtlRunOnceExecuteOnce @783 + RtlRunOnceInitialize @784 + RtlSecondsSince1970ToTime @785 + RtlSecondsSince1980ToTime @786 + RtlSelfRelativeToAbsoluteSD @787 + RtlSetAllBits @788 + RtlSetBits @789 + RtlSetControlSecurityDescriptor @790 + RtlSetCriticalSectionSpinCount @791 + RtlSetCurrentDirectory_U @792 + RtlSetCurrentEnvironment @793 + RtlSetCurrentTransaction @794 + RtlSetDaclSecurityDescriptor @795 + RtlSetEnvironmentVariable @796 + RtlSetExtendedFeaturesMask @797 + RtlSetGroupSecurityDescriptor @798 + RtlSetHeapInformation @799 + RtlSetInformationAcl @800 PRIVATE + RtlSetIoCompletionCallback @801 + RtlSetLastWin32Error @802 + RtlSetLastWin32ErrorAndNtStatusFromNtStatus @803 + RtlSetOwnerSecurityDescriptor @804 + RtlSetProcessPreferredUILanguages @805 + RtlSetProperties @806 PRIVATE + RtlSetPropertyClassId @807 PRIVATE + RtlSetPropertyNames @808 PRIVATE + RtlSetPropertySetClassId @809 PRIVATE + RtlSetSaclSecurityDescriptor @810 + RtlSetSearchPathMode @811 + RtlSetSecurityObject @812 PRIVATE + RtlSetThreadErrorMode @813 + RtlSetThreadPreferredUILanguages @814 + RtlSetTimeZoneInformation @815 + RtlSetUnhandledExceptionFilter @816 + RtlSetUnicodeCallouts @817 PRIVATE + RtlSetUserFlagsHeap @818 + RtlSetUserValueHeap @819 + RtlSizeHeap @820 + RtlSleepConditionVariableCS @821 + RtlSleepConditionVariableSRW @822 + RtlSplay @823 PRIVATE + RtlStartRXact @824 PRIVATE + RtlStringFromGUID @825 + RtlSubAuthorityCountSid @826 + RtlSubAuthoritySid @827 + RtlSubtreePredecessor @828 PRIVATE + RtlSubtreeSuccessor @829 PRIVATE + RtlSystemTimeToLocalTime @830 + RtlTimeFieldsToTime @831 + RtlTimeToElapsedTimeFields @832 + RtlTimeToSecondsSince1970 @833 + RtlTimeToSecondsSince1980 @834 + RtlTimeToTimeFields @835 + RtlTryAcquireSRWLockExclusive @836 + RtlTryAcquireSRWLockShared @837 + RtlTryEnterCriticalSection @838 + RtlUTF8ToUnicodeN @839 + RtlUnicodeStringToAnsiSize @840 + RtlUnicodeStringToAnsiString @841 + RtlUnicodeStringToCountedOemString @842 PRIVATE + RtlUnicodeStringToInteger @843 + RtlUnicodeStringToOemSize @844 + RtlUnicodeStringToOemString @845 + RtlUnicodeToCustomCPN @846 + RtlUnicodeToMultiByteN @847 + RtlUnicodeToMultiByteSize @848 + RtlUnicodeToOemN @849 + RtlUnicodeToUTF8N @850 + RtlUniform @851 + RtlUnlockHeap @852 + RtlUnwind @853 + RtlUnwindEx @854 + RtlUpcaseUnicodeChar @855 + RtlUpcaseUnicodeString @856 + RtlUpcaseUnicodeStringToAnsiString @857 + RtlUpcaseUnicodeStringToCountedOemString @858 + RtlUpcaseUnicodeStringToOemString @859 + RtlUpcaseUnicodeToCustomCPN @860 + RtlUpcaseUnicodeToMultiByteN @861 + RtlUpcaseUnicodeToOemN @862 + RtlUpdateTimer @863 + RtlUpperChar @864 + RtlUpperString @865 + RtlUsageHeap @866 PRIVATE + RtlUserThreadStart @867 + RtlValidAcl @868 + RtlValidRelativeSecurityDescriptor @869 + RtlValidSecurityDescriptor @870 + RtlValidSid @871 + RtlValidateHeap @872 + RtlValidateProcessHeaps @873 PRIVATE + RtlVerifyVersionInfo @874 + RtlVirtualUnwind @875 + RtlWaitOnAddress @876 + RtlWakeAddressAll @877 + RtlWakeAddressSingle @878 + RtlWakeAllConditionVariable @879 + RtlWakeConditionVariable @880 + RtlWalkFrameChain @881 PRIVATE + RtlWalkHeap @882 + RtlWow64EnableFsRedirection @883 + RtlWow64EnableFsRedirectionEx @884 + RtlWow64GetCpuAreaInfo @885 + RtlWow64GetCurrentCpuArea @886 + RtlWow64GetCurrentMachine @887 + RtlWow64GetProcessMachines @888 + RtlWow64GetSharedInfoProcess @889 + RtlWow64GetThreadContext @890 + RtlWow64GetThreadSelectorEntry @891 + RtlWow64IsWowGuestMachineSupported @892 + RtlWow64SetThreadContext @893 + RtlWow64SuspendThread @894 + RtlWriteMemoryStream @895 PRIVATE + RtlWriteRegistryValue @896 + RtlZeroHeap @897 PRIVATE + RtlZeroMemory @898 + RtlZombifyActivationContext @899 + RtlpNtCreateKey @900 + RtlpNtEnumerateSubKey @901 + RtlpNtMakeTemporaryKey @902 + RtlpNtOpenKey @903 + RtlpNtQueryValueKey @904 + RtlpNtSetValueKey @905 + RtlpUnWaitCriticalSection @906 + RtlpWaitForCriticalSection @907 + RtlxAnsiStringToUnicodeSize=RtlAnsiStringToUnicodeSize @908 + RtlxOemStringToUnicodeSize=RtlOemStringToUnicodeSize @909 + RtlxUnicodeStringToAnsiSize=RtlUnicodeStringToAnsiSize @910 + RtlxUnicodeStringToOemSize=RtlUnicodeStringToOemSize @911 + TpAllocCleanupGroup @912 + TpAllocIoCompletion @913 + TpAllocPool @914 + TpAllocTimer @915 + TpAllocWait @916 + TpAllocWork @917 + TpCallbackLeaveCriticalSectionOnCompletion @918 + TpCallbackMayRunLong @919 + TpCallbackReleaseMutexOnCompletion @920 + TpCallbackReleaseSemaphoreOnCompletion @921 + TpCallbackSetEventOnCompletion @922 + TpCallbackUnloadDllOnCompletion @923 + TpCancelAsyncIoOperation @924 + TpDisassociateCallback @925 + TpIsTimerSet @926 + TpPostWork @927 + TpQueryPoolStackInformation @928 + TpReleaseCleanupGroup @929 + TpReleaseCleanupGroupMembers @930 + TpReleaseIoCompletion @931 + TpReleasePool @932 + TpReleaseTimer @933 + TpReleaseWait @934 + TpReleaseWork @935 + TpSetPoolMaxThreads @936 + TpSetPoolMinThreads @937 + TpSetPoolStackInformation @938 + TpSetTimer @939 + TpSetWait @940 + TpSimpleTryPost @941 + TpStartAsyncIoOperation @942 + TpWaitForIoCompletion @943 + TpWaitForTimer @944 + TpWaitForWait @945 + TpWaitForWork @946 + VerSetConditionMask @947 + WinSqmEndSession @948 + WinSqmIncrementDWORD @949 + WinSqmIsOptedIn @950 + WinSqmSetDWORD @951 + WinSqmStartSession @952 + ZwAcceptConnectPort=NtAcceptConnectPort @953 PRIVATE + ZwAccessCheck=NtAccessCheck @954 PRIVATE + ZwAccessCheckAndAuditAlarm=NtAccessCheckAndAuditAlarm @955 PRIVATE + ZwAddAtom=NtAddAtom @956 PRIVATE + ZwAdjustGroupsToken=NtAdjustGroupsToken @957 PRIVATE + ZwAdjustPrivilegesToken=NtAdjustPrivilegesToken @958 PRIVATE + ZwAlertResumeThread=NtAlertResumeThread @959 PRIVATE + ZwAlertThread=NtAlertThread @960 PRIVATE + ZwAlertThreadByThreadId=NtAlertThreadByThreadId @961 PRIVATE + ZwAllocateLocallyUniqueId=NtAllocateLocallyUniqueId @962 PRIVATE + ZwAllocateUuids=NtAllocateUuids @963 PRIVATE + ZwAllocateVirtualMemory=NtAllocateVirtualMemory @964 PRIVATE + ZwAllocateVirtualMemoryEx=NtAllocateVirtualMemoryEx @965 PRIVATE + ZwAreMappedFilesTheSame=NtAreMappedFilesTheSame @966 PRIVATE + ZwAssignProcessToJobObject=NtAssignProcessToJobObject @967 PRIVATE + ZwCancelIoFile=NtCancelIoFile @968 PRIVATE + ZwCancelIoFileEx=NtCancelIoFileEx @969 PRIVATE + ZwCancelSynchronousIoFile=NtCancelSynchronousIoFile @970 PRIVATE + ZwCancelTimer=NtCancelTimer @971 PRIVATE + ZwClearEvent=NtClearEvent @972 PRIVATE + ZwClose=NtClose @973 PRIVATE + ZwCompareObjects=NtCompareObjects @974 PRIVATE + ZwCompleteConnectPort=NtCompleteConnectPort @975 PRIVATE + ZwConnectPort=NtConnectPort @976 PRIVATE + ZwContinue=NtContinue @977 PRIVATE + ZwCreateDirectoryObject=NtCreateDirectoryObject @978 PRIVATE + ZwCreateEvent=NtCreateEvent @979 PRIVATE + ZwCreateFile=NtCreateFile @980 PRIVATE + ZwCreateIoCompletion=NtCreateIoCompletion @981 PRIVATE + ZwCreateJobObject=NtCreateJobObject @982 PRIVATE + ZwCreateKey=NtCreateKey @983 PRIVATE + ZwCreateKeyTransacted=NtCreateKeyTransacted @984 PRIVATE + ZwCreateKeyedEvent=NtCreateKeyedEvent @985 PRIVATE + ZwCreateLowBoxToken=NtCreateLowBoxToken @986 PRIVATE + ZwCreateMailslotFile=NtCreateMailslotFile @987 PRIVATE + ZwCreateMutant=NtCreateMutant @988 PRIVATE + ZwCreateNamedPipeFile=NtCreateNamedPipeFile @989 PRIVATE + ZwCreatePagingFile=NtCreatePagingFile @990 PRIVATE + ZwCreatePort=NtCreatePort @991 PRIVATE + ZwCreateSection=NtCreateSection @992 PRIVATE + ZwCreateSemaphore=NtCreateSemaphore @993 PRIVATE + ZwCreateSymbolicLinkObject=NtCreateSymbolicLinkObject @994 PRIVATE + ZwCreateThread=NtCreateThread @995 PRIVATE + ZwCreateThreadEx=NtCreateThreadEx @996 PRIVATE + ZwCreateTimer=NtCreateTimer @997 PRIVATE + ZwCreateUserProcess=NtCreateUserProcess @998 PRIVATE + ZwDebugActiveProcess=NtDebugActiveProcess @999 PRIVATE + ZwDebugContinue=NtDebugContinue @1000 PRIVATE + ZwDelayExecution=NtDelayExecution @1001 PRIVATE + ZwDeleteAtom=NtDeleteAtom @1002 PRIVATE + ZwDeleteFile=NtDeleteFile @1003 PRIVATE + ZwDeleteKey=NtDeleteKey @1004 PRIVATE + ZwDeleteValueKey=NtDeleteValueKey @1005 PRIVATE + ZwDeviceIoControlFile=NtDeviceIoControlFile @1006 PRIVATE + ZwDisplayString=NtDisplayString @1007 PRIVATE + ZwDuplicateObject=NtDuplicateObject @1008 PRIVATE + ZwDuplicateToken=NtDuplicateToken @1009 PRIVATE + ZwEnumerateKey=NtEnumerateKey @1010 PRIVATE + ZwEnumerateValueKey=NtEnumerateValueKey @1011 PRIVATE + ZwFilterToken=NtFilterToken @1012 PRIVATE + ZwFindAtom=NtFindAtom @1013 PRIVATE + ZwFlushBuffersFile=NtFlushBuffersFile @1014 PRIVATE + ZwFlushInstructionCache=NtFlushInstructionCache @1015 PRIVATE + ZwFlushKey=NtFlushKey @1016 PRIVATE + ZwFlushProcessWriteBuffers=NtFlushProcessWriteBuffers @1017 PRIVATE + ZwFlushVirtualMemory=NtFlushVirtualMemory @1018 PRIVATE + ZwFreeVirtualMemory=NtFreeVirtualMemory @1019 PRIVATE + ZwFsControlFile=NtFsControlFile @1020 PRIVATE + ZwGetContextThread=NtGetContextThread @1021 PRIVATE + ZwGetCurrentProcessorNumber=NtGetCurrentProcessorNumber @1022 PRIVATE + ZwGetNlsSectionPtr=NtGetNlsSectionPtr @1023 PRIVATE + ZwGetTickCount=NtGetTickCount @1024 PRIVATE + ZwGetWriteWatch=NtGetWriteWatch @1025 PRIVATE + ZwImpersonateAnonymousToken=NtImpersonateAnonymousToken @1026 PRIVATE + ZwInitializeNlsFiles=NtInitializeNlsFiles @1027 PRIVATE + ZwInitiatePowerAction=NtInitiatePowerAction @1028 PRIVATE + ZwIsProcessInJob=NtIsProcessInJob @1029 PRIVATE + ZwListenPort=NtListenPort @1030 PRIVATE + ZwLoadDriver=NtLoadDriver @1031 PRIVATE + ZwLoadKey2=NtLoadKey2 @1032 PRIVATE + ZwLoadKey=NtLoadKey @1033 PRIVATE + ZwLockFile=NtLockFile @1034 PRIVATE + ZwLockVirtualMemory=NtLockVirtualMemory @1035 PRIVATE + ZwMakeTemporaryObject=NtMakeTemporaryObject @1036 PRIVATE + ZwMapViewOfSection=NtMapViewOfSection @1037 PRIVATE + ZwMapViewOfSectionEx=NtMapViewOfSectionEx @1038 PRIVATE + ZwNotifyChangeDirectoryFile=NtNotifyChangeDirectoryFile @1039 PRIVATE + ZwNotifyChangeKey=NtNotifyChangeKey @1040 PRIVATE + ZwNotifyChangeMultipleKeys=NtNotifyChangeMultipleKeys @1041 PRIVATE + ZwOpenDirectoryObject=NtOpenDirectoryObject @1042 PRIVATE + ZwOpenEvent=NtOpenEvent @1043 PRIVATE + ZwOpenFile=NtOpenFile @1044 PRIVATE + ZwOpenIoCompletion=NtOpenIoCompletion @1045 PRIVATE + ZwOpenJobObject=NtOpenJobObject @1046 PRIVATE + ZwOpenKey=NtOpenKey @1047 PRIVATE + ZwOpenKeyEx=NtOpenKeyEx @1048 PRIVATE + ZwOpenKeyTransacted=NtOpenKeyTransacted @1049 PRIVATE + ZwOpenKeyTransactedEx=NtOpenKeyTransactedEx @1050 PRIVATE + ZwOpenKeyedEvent=NtOpenKeyedEvent @1051 PRIVATE + ZwOpenMutant=NtOpenMutant @1052 PRIVATE + ZwOpenProcess=NtOpenProcess @1053 PRIVATE + ZwOpenProcessToken=NtOpenProcessToken @1054 PRIVATE + ZwOpenProcessTokenEx=NtOpenProcessTokenEx @1055 PRIVATE + ZwOpenSection=NtOpenSection @1056 PRIVATE + ZwOpenSemaphore=NtOpenSemaphore @1057 PRIVATE + ZwOpenSymbolicLinkObject=NtOpenSymbolicLinkObject @1058 PRIVATE + ZwOpenThread=NtOpenThread @1059 PRIVATE + ZwOpenThreadToken=NtOpenThreadToken @1060 PRIVATE + ZwOpenThreadTokenEx=NtOpenThreadTokenEx @1061 PRIVATE + ZwOpenTimer=NtOpenTimer @1062 PRIVATE + ZwPowerInformation=NtPowerInformation @1063 PRIVATE + ZwPrivilegeCheck=NtPrivilegeCheck @1064 PRIVATE + ZwProtectVirtualMemory=NtProtectVirtualMemory @1065 PRIVATE + ZwPulseEvent=NtPulseEvent @1066 PRIVATE + ZwQueryAttributesFile=NtQueryAttributesFile @1067 PRIVATE + ZwQueryDefaultLocale=NtQueryDefaultLocale @1068 PRIVATE + ZwQueryDefaultUILanguage=NtQueryDefaultUILanguage @1069 PRIVATE + ZwQueryDirectoryFile=NtQueryDirectoryFile @1070 PRIVATE + ZwQueryDirectoryObject=NtQueryDirectoryObject @1071 PRIVATE + ZwQueryEaFile=NtQueryEaFile @1072 PRIVATE + ZwQueryEvent=NtQueryEvent @1073 PRIVATE + ZwQueryFullAttributesFile=NtQueryFullAttributesFile @1074 PRIVATE + ZwQueryInformationAtom=NtQueryInformationAtom @1075 PRIVATE + ZwQueryInformationFile=NtQueryInformationFile @1076 PRIVATE + ZwQueryInformationJobObject=NtQueryInformationJobObject @1077 PRIVATE + ZwQueryInformationProcess=NtQueryInformationProcess @1078 PRIVATE + ZwQueryInformationThread=NtQueryInformationThread @1079 PRIVATE + ZwQueryInformationToken=NtQueryInformationToken @1080 PRIVATE + ZwQueryInstallUILanguage=NtQueryInstallUILanguage @1081 PRIVATE + ZwQueryIoCompletion=NtQueryIoCompletion @1082 PRIVATE + ZwQueryKey=NtQueryKey @1083 PRIVATE + ZwQueryLicenseValue=NtQueryLicenseValue @1084 PRIVATE + ZwQueryMultipleValueKey=NtQueryMultipleValueKey @1085 PRIVATE + ZwQueryMutant=NtQueryMutant @1086 PRIVATE + ZwQueryObject=NtQueryObject @1087 PRIVATE + ZwQueryPerformanceCounter=NtQueryPerformanceCounter @1088 PRIVATE + ZwQuerySection=NtQuerySection @1089 PRIVATE + ZwQuerySecurityObject=NtQuerySecurityObject @1090 PRIVATE + ZwQuerySemaphore=NtQuerySemaphore @1091 PRIVATE + ZwQuerySymbolicLinkObject=NtQuerySymbolicLinkObject @1092 PRIVATE + ZwQuerySystemEnvironmentValue=NtQuerySystemEnvironmentValue @1093 PRIVATE + ZwQuerySystemEnvironmentValueEx=NtQuerySystemEnvironmentValueEx @1094 PRIVATE + ZwQuerySystemInformation=NtQuerySystemInformation @1095 PRIVATE + ZwQuerySystemInformationEx=NtQuerySystemInformationEx @1096 PRIVATE + ZwQuerySystemTime=NtQuerySystemTime @1097 PRIVATE + ZwQueryTimer=NtQueryTimer @1098 PRIVATE + ZwQueryTimerResolution=NtQueryTimerResolution @1099 PRIVATE + ZwQueryValueKey=NtQueryValueKey @1100 PRIVATE + ZwQueryVirtualMemory=NtQueryVirtualMemory @1101 PRIVATE + ZwQueryVolumeInformationFile=NtQueryVolumeInformationFile @1102 PRIVATE + ZwQueueApcThread=NtQueueApcThread @1103 PRIVATE + ZwRaiseException=NtRaiseException @1104 PRIVATE + ZwRaiseHardError=NtRaiseHardError @1105 PRIVATE + ZwReadFile=NtReadFile @1106 PRIVATE + ZwReadFileScatter=NtReadFileScatter @1107 PRIVATE + ZwReadVirtualMemory=NtReadVirtualMemory @1108 PRIVATE + ZwRegisterThreadTerminatePort=NtRegisterThreadTerminatePort @1109 PRIVATE + ZwReleaseKeyedEvent=NtReleaseKeyedEvent @1110 PRIVATE + ZwReleaseMutant=NtReleaseMutant @1111 PRIVATE + ZwReleaseSemaphore=NtReleaseSemaphore @1112 PRIVATE + ZwRemoveIoCompletion=NtRemoveIoCompletion @1113 PRIVATE + ZwRemoveIoCompletionEx=NtRemoveIoCompletionEx @1114 PRIVATE + ZwRemoveProcessDebug=NtRemoveProcessDebug @1115 PRIVATE + ZwRenameKey=NtRenameKey @1116 PRIVATE + ZwReplaceKey=NtReplaceKey @1117 PRIVATE + ZwReplyWaitReceivePort=NtReplyWaitReceivePort @1118 PRIVATE + ZwRequestWaitReplyPort=NtRequestWaitReplyPort @1119 PRIVATE + ZwResetEvent=NtResetEvent @1120 PRIVATE + ZwResetWriteWatch=NtResetWriteWatch @1121 PRIVATE + ZwRestoreKey=NtRestoreKey @1122 PRIVATE + ZwResumeProcess=NtResumeProcess @1123 PRIVATE + ZwResumeThread=NtResumeThread @1124 PRIVATE + ZwSaveKey=NtSaveKey @1125 PRIVATE + ZwSecureConnectPort=NtSecureConnectPort @1126 PRIVATE + ZwSetContextThread=NtSetContextThread @1127 PRIVATE + ZwSetDebugFilterState=NtSetDebugFilterState @1128 PRIVATE + ZwSetDefaultLocale=NtSetDefaultLocale @1129 PRIVATE + ZwSetDefaultUILanguage=NtSetDefaultUILanguage @1130 PRIVATE + ZwSetEaFile=NtSetEaFile @1131 PRIVATE + ZwSetEvent=NtSetEvent @1132 PRIVATE + ZwSetInformationDebugObject=NtSetInformationDebugObject @1133 PRIVATE + ZwSetInformationFile=NtSetInformationFile @1134 PRIVATE + ZwSetInformationJobObject=NtSetInformationJobObject @1135 PRIVATE + ZwSetInformationKey=NtSetInformationKey @1136 PRIVATE + ZwSetInformationObject=NtSetInformationObject @1137 PRIVATE + ZwSetInformationProcess=NtSetInformationProcess @1138 PRIVATE + ZwSetInformationThread=NtSetInformationThread @1139 PRIVATE + ZwSetInformationToken=NtSetInformationToken @1140 PRIVATE + ZwSetInformationVirtualMemory=NtSetInformationVirtualMemory @1141 PRIVATE + ZwSetIntervalProfile=NtSetIntervalProfile @1142 PRIVATE + ZwSetIoCompletion=NtSetIoCompletion @1143 PRIVATE + ZwSetLdtEntries=NtSetLdtEntries @1144 PRIVATE + ZwSetSecurityObject=NtSetSecurityObject @1145 PRIVATE + ZwSetSystemInformation=NtSetSystemInformation @1146 PRIVATE + ZwSetSystemTime=NtSetSystemTime @1147 PRIVATE + ZwSetThreadExecutionState=NtSetThreadExecutionState @1148 PRIVATE + ZwSetTimer=NtSetTimer @1149 PRIVATE + ZwSetTimerResolution=NtSetTimerResolution @1150 PRIVATE + ZwSetValueKey=NtSetValueKey @1151 PRIVATE + ZwSetVolumeInformationFile=NtSetVolumeInformationFile @1152 PRIVATE + ZwShutdownSystem=NtShutdownSystem @1153 PRIVATE + ZwSignalAndWaitForSingleObject=NtSignalAndWaitForSingleObject @1154 PRIVATE + ZwSuspendProcess=NtSuspendProcess @1155 PRIVATE + ZwSuspendThread=NtSuspendThread @1156 PRIVATE + ZwSystemDebugControl=NtSystemDebugControl @1157 PRIVATE + ZwTerminateJobObject=NtTerminateJobObject @1158 PRIVATE + ZwTerminateProcess=NtTerminateProcess @1159 PRIVATE + ZwTerminateThread=NtTerminateThread @1160 PRIVATE + ZwTestAlert=NtTestAlert @1161 PRIVATE + ZwTraceControl=NtTraceControl @1162 PRIVATE + ZwUnloadDriver=NtUnloadDriver @1163 PRIVATE + ZwUnloadKey=NtUnloadKey @1164 PRIVATE + ZwUnlockFile=NtUnlockFile @1165 PRIVATE + ZwUnlockVirtualMemory=NtUnlockVirtualMemory @1166 PRIVATE + ZwUnmapViewOfSection=NtUnmapViewOfSection @1167 PRIVATE + ZwUnmapViewOfSectionEx=NtUnmapViewOfSectionEx @1168 PRIVATE + ZwWaitForAlertByThreadId=NtWaitForAlertByThreadId @1169 PRIVATE + ZwWaitForDebugEvent=NtWaitForDebugEvent @1170 PRIVATE + ZwWaitForKeyedEvent=NtWaitForKeyedEvent @1171 PRIVATE + ZwWaitForMultipleObjects=NtWaitForMultipleObjects @1172 PRIVATE + ZwWaitForSingleObject=NtWaitForSingleObject @1173 PRIVATE + ZwWriteFile=NtWriteFile @1174 PRIVATE + ZwWriteFileGather=NtWriteFileGather @1175 PRIVATE + ZwWriteVirtualMemory=NtWriteVirtualMemory @1176 PRIVATE + ZwYieldExecution=NtYieldExecution @1177 PRIVATE + __C_specific_handler @1178 + __chkstk @1179 + __isascii @1180 + __iscsym @1181 + __iscsymf @1182 + __toascii @1183 + _atoi64 @1184 + _errno @1185 + _fltused @1186 PRIVATE + _i64toa @1187 + _i64toa_s @1188 + _i64tow @1189 + _i64tow_s @1190 + _itoa @1191 + _itoa_s @1192 + _itow @1193 + _itow_s @1194 + _lfind @1195 + _local_unwind @1196 + _ltoa @1197 + _ltoa_s @1198 + _ltow @1199 + _ltow_s @1200 + _makepath_s @1201 + _memccpy @1202 + _memicmp @1203 + _snprintf=NTDLL__snprintf @1204 + _snprintf_s @1205 + _snwprintf @1206 + _snwprintf_s @1207 + _splitpath @1208 + _splitpath_s @1209 + _strcmpi=_stricmp @1210 + _stricmp @1211 + _strlwr @1212 + _strlwr_s @1213 + _strnicmp @1214 + _strupr @1215 + _strupr_s @1216 + _swprintf=NTDLL_swprintf @1217 + _tolower @1218 + _toupper @1219 + _ui64toa @1220 + _ui64toa_s @1221 + _ui64tow @1222 + _ui64tow_s @1223 + _ultoa @1224 + _ultoa_s @1225 + _ultow @1226 + _ultow_s @1227 + _vscprintf @1228 + _vscwprintf @1229 + _vsnprintf @1230 + _vsnprintf_s @1231 + _vsnwprintf @1232 + _vsnwprintf_s @1233 + _vswprintf @1234 + _wcsicmp @1235 + _wcslwr @1236 + _wcslwr_s @1237 + _wcsnicmp @1238 + _wcstoi64 @1239 + _wcstoui64 @1240 + _wcsupr @1241 + _wcsupr_s @1242 + _wmakepath_s @1243 + _wsplitpath_s @1244 + _wtoi @1245 + _wtoi64 @1246 + _wtol @1247 + abs @1248 + atan @1249 + atan2 @1250 + atoi @1251 + atol @1252 + bsearch @1253 + bsearch_s @1254 + ceil @1255 + cos @1256 + fabs @1257 + floor @1258 + isalnum @1259 + isalpha @1260 + iscntrl @1261 + isdigit @1262 + isgraph @1263 + islower @1264 + isprint @1265 + ispunct @1266 + isspace @1267 + isupper @1268 + iswalnum @1269 + iswalpha @1270 + iswascii @1271 + iswctype @1272 + iswdigit @1273 + iswgraph @1274 + iswlower @1275 + iswprint @1276 + iswspace @1277 + iswxdigit @1278 + isxdigit @1279 + labs=abs @1280 + log @1281 + mbstowcs @1282 + memchr @1283 + memcmp @1284 + memcpy @1285 + memcpy_s @1286 + memmove @1287 + memmove_s @1288 + memset @1289 + pow @1290 + qsort @1291 + qsort_s @1292 + sin @1293 + sprintf=NTDLL_sprintf @1294 + sprintf_s @1295 + sqrt @1296 + sscanf @1297 + strcat @1298 + strcat_s @1299 + strchr @1300 + strcmp @1301 + strcpy @1302 + strcpy_s @1303 + strcspn @1304 + strlen @1305 + strncat @1306 + strncat_s @1307 + strncmp @1308 + strncpy @1309 + strncpy_s @1310 + strnlen @1311 + strpbrk @1312 + strrchr @1313 + strspn @1314 + strstr @1315 + strtok_s @1316 + strtol @1317 + strtoul @1318 + swprintf=NTDLL_swprintf @1319 + swprintf_s @1320 + tan @1321 + tolower @1322 + toupper @1323 + towlower @1324 + towupper @1325 + vDbgPrintEx @1326 + vDbgPrintExWithPrefix @1327 + vsprintf @1328 + vsprintf_s @1329 + vswprintf_s @1330 + wcscat @1331 + wcscat_s @1332 + wcschr @1333 + wcscmp @1334 + wcscpy @1335 + wcscpy_s @1336 + wcscspn @1337 + wcslen @1338 + wcsncat @1339 + wcsncat_s @1340 + wcsncmp @1341 + wcsncpy @1342 + wcsncpy_s @1343 + wcsnlen @1344 + wcspbrk @1345 + wcsrchr @1346 + wcsspn @1347 + wcsstr @1348 + wcstok @1349 + wcstok_s @1350 + wcstol @1351 + wcstombs @1352 + wcstoul @1353 + wine_server_call @1354 + wine_server_fd_to_handle @1355 + wine_server_handle_to_fd @1356 + __wine_unix_call @1357 + __wine_unix_spawnvp @1358 + __wine_ctrl_routine @1359 + __wine_syscall_dispatcher @1360 DATA PRIVATE + __wine_unix_call_dispatcher @1361 DATA PRIVATE + __wine_unixlib_handle @1362 DATA PRIVATE + __wine_dbg_write @1363 + __wine_dbg_get_channel_flags @1364 + __wine_dbg_header @1365 + __wine_dbg_output @1366 + __wine_dbg_strdup @1367 + wine_get_version @1368 + wine_get_build_id @1369 + wine_get_host_version @1370 + wine_nt_to_unix_file_name @1371 + wine_unix_to_nt_file_name @1372 diff --git a/Source/Windows/Defs/wow64.def b/Source/Windows/Defs/wow64.def new file mode 100644 index 000000000..e5291402c --- /dev/null +++ b/Source/Windows/Defs/wow64.def @@ -0,0 +1,33 @@ +; File generated automatically from wine/dlls/wow64/wow64.spec; do not edit! +; To generate: winebuild --def -E wine/dlls/wow64/wow64.spec > wow64.def + +LIBRARY wow64.dll + +EXPORTS + Wow64AllocThreadHeap @1 PRIVATE + Wow64AllocateHeap @2 PRIVATE + Wow64AllocateTemp @3 + Wow64ApcRoutine @4 + Wow64CheckIfNXEnabled @5 PRIVATE + Wow64EmulateAtlThunk @6 PRIVATE + Wow64FreeHeap @7 PRIVATE + Wow64FreeThreadHeap @8 PRIVATE + Wow64GetWow64ImageOption @9 PRIVATE + Wow64IsControlFlowGuardEnforced @10 PRIVATE + Wow64IsStackExtentsCheckEnforced @11 PRIVATE + Wow64KiUserCallbackDispatcher @12 + Wow64LdrpInitialize @13 + Wow64LogPrint @14 PRIVATE + Wow64NotifyUnsimulateComplete @15 PRIVATE + Wow64PassExceptionToGuest @16 + Wow64PrepareForDebuggerAttach @17 PRIVATE + Wow64PrepareForException @18 + Wow64RaiseException @19 + Wow64ShallowThunkAllocObjectAttributes32TO64_FNC @20 PRIVATE + Wow64ShallowThunkAllocSecurityQualityOfService32TO64_FNC @21 PRIVATE + Wow64ShallowThunkSIZE_T32TO64 @22 PRIVATE + Wow64ShallowThunkSIZE_T64TO32 @23 PRIVATE + Wow64SuspendLocalThread @24 + Wow64SystemServiceEx @25 + Wow64ValidateUserCallTarget @26 PRIVATE + Wow64ValidateUserCallTargetFilter @27 PRIVATE diff --git a/Source/Windows/WOW64/BTInterface.h b/Source/Windows/WOW64/BTInterface.h new file mode 100644 index 000000000..7ff7f019f --- /dev/null +++ b/Source/Windows/WOW64/BTInterface.h @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +#pragma once + +#include +#include +#include + +extern "C" { +void STDMETHODCALLTYPE BTCpuProcessInit(); +NTSTATUS STDMETHODCALLTYPE BTCpuThreadInit(); +NTSTATUS STDMETHODCALLTYPE BTCpuThreadTerm(HANDLE Thread); +void STDMETHODCALLTYPE *BTCpuGetBopCode(); +void STDMETHODCALLTYPE *__wine_get_unix_opcode(); +NTSTATUS STDMETHODCALLTYPE BTCpuGetContext(HANDLE Thread, HANDLE Process, void *Unknown, WOW64_CONTEXT *Context); +NTSTATUS STDMETHODCALLTYPE BTCpuSetContext(HANDLE Thread, HANDLE Process, void *Unknown, WOW64_CONTEXT *Context); +void STDMETHODCALLTYPE BTCpuSimulate(); +NTSTATUS STDMETHODCALLTYPE BTCpuSuspendLocalThread(HANDLE Thread, ULONG *Count); +NTSTATUS STDMETHODCALLTYPE BTCpuResetToConsistentState(EXCEPTION_POINTERS *Ptrs); +void STDMETHODCALLTYPE BTCpuFlushInstructionCache2(const void *Address, SIZE_T Size); +void STDMETHODCALLTYPE BTCpuNotifyMemoryAlloc(void *Address, SIZE_T Size, ULONG Type, ULONG Prot); +void STDMETHODCALLTYPE BTCpuNotifyMemoryProtect(void *Address, SIZE_T Size, ULONG NewProt); +void STDMETHODCALLTYPE BTCpuNotifyMemoryFree(void *Address, SIZE_T Size, ULONG FreeType); +void STDMETHODCALLTYPE BTCpuNotifyUnmapViewOfSection(void *Address, ULONG Flags); +BOOLEAN STDMETHODCALLTYPE BTCpuIsProcessorFeaturePresent(UINT Feature); +BOOLEAN STDMETHODCALLTYPE BTCpuUpdateProcessorInformation(SYSTEM_CPU_INFORMATION *Info); +} diff --git a/Source/Windows/WOW64/CMakeLists.txt b/Source/Windows/WOW64/CMakeLists.txt new file mode 100644 index 000000000..c1e0b22ab --- /dev/null +++ b/Source/Windows/WOW64/CMakeLists.txt @@ -0,0 +1,25 @@ +add_library(wow64fex SHARED + Module.cpp + libwow64fex.def +) + +target_include_directories(wow64fex PRIVATE + "${CMAKE_SOURCE_DIR}/Source/Windows/include/" + "${CMAKE_SOURCE_DIR}/Source/" +) + +target_link_libraries(wow64fex + PRIVATE + FEXCore + Common + CommonTools + wow64 + ntdll +) + +target_link_options(wow64fex PRIVATE "LINKER:--image-base,0x6f100000") + +install(TARGETS wow64fex + RUNTIME + DESTINATION bin + COMPONENT runtime) diff --git a/Source/Windows/WOW64/IntervalList.h b/Source/Windows/WOW64/IntervalList.h new file mode 100644 index 000000000..6c2b772a4 --- /dev/null +++ b/Source/Windows/WOW64/IntervalList.h @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: MIT +#pragma once + +#include +#include + +#include + +template +class IntervalList { +public: + using DifferenceType = decltype(std::declval() - std::declval()); + + struct Interval { + SizeType Offset; + SizeType End; + + Interval() = default; + + Interval(SizeType Offset, SizeType End) : Offset{Offset}, End{End} {} + }; + +private: + fextl::vector Intervals; ///< list of intervals sorted by their end offset + +public: + struct QueryResult { + bool Enclosed; ///< If the given offset was enclosed by an interval + DifferenceType Size; ///< Size of the interval starting from the query offset, or distance to the next interval if + /// `Enclosed` is false (if there is no next interval, size is 0) + }; + + void Clear() { + Intervals.clear(); + } + + void Insert(Interval Entry) { + if (Entry.Offset == Entry.End) { + return; + } + + auto [FirstIt, EndIt] = std::equal_range(Intervals.begin(), Intervals.end(), Entry, [](const auto &LHS, const auto &RHS) { + return LHS.End <= RHS.Offset; + }); + + if (FirstIt == EndIt) { + // No overlaps + Intervals.insert(FirstIt, Entry); + return; + } + + auto LastIt = std::prev(EndIt); + // FirstIt/LastIt are the lowest/highest offset intervals respectively that overlap with the new interval + + const SizeType Offset = std::min(Entry.Offset, FirstIt->Offset); + const SizeType End = std::max(LastIt->End, Entry.End); + + // Erase all overlapping entries but the first + const auto EraseStartIt = std::next(FirstIt); + const auto EraseEndIt = std::next(LastIt); + LastIt = Intervals.erase(EraseStartIt, EraseEndIt); + FirstIt = std::prev(LastIt); + + FirstIt->Offset = Offset; + FirstIt->End = End; + } + + void Remove(Interval Entry) { + if (Entry.Offset == Entry.End) { + return; + } + + auto [FirstIt, EndIt] = std::equal_range(Intervals.begin(), Intervals.end(), Entry, [](const auto &LHS, const auto &RHS) { + return LHS.End <= RHS.Offset; + }); + + if (FirstIt == EndIt) { + // No intersecting intervals present, nothing more to do + return; + } + + if (FirstIt->Offset < Entry.Offset && FirstIt->End > Entry.End) { + // The interval to be removed is fully enclosed by an existing interval + + // Break the single interval into two smaller intervals on either side on the interval being removed + const auto FirstPredecessorIt = Intervals.insert(FirstIt, *FirstIt); + FirstIt = std::next(FirstPredecessorIt); + FirstPredecessorIt->End = Entry.Offset; + FirstIt->Offset = Entry.End; + return; + } + + auto LastIt = std::prev(EndIt); + // FirstIt/LastIt are the lowest/highest offset intervals respectively that overlap with the new interval + + if (FirstIt->Offset < Entry.Offset) { + // The first overlap straddles the start of the interval to be removed + FirstIt->End = Entry.Offset; + if (FirstIt == LastIt) { + // No more overlaps left, nothing more to do + return; + } else { + FirstIt++; + } + } + + if (LastIt->End > Entry.End) { + // The last overlap straddles the end of the interval to be removed + LastIt->Offset = Entry.End; + if (LastIt == FirstIt) { + // No more overlaps left, nothing more to do + return; + } else { + LastIt--; + } + } + + // Now none of the overlaps straddle the edges of the interval to be removed they can all be erased + const auto EraseStartIt = FirstIt; + const auto EraseEndIt = std::next(LastIt); + Intervals.erase(EraseStartIt, EraseEndIt); + } + + QueryResult Query(SizeType Offset) { + const auto It = std::upper_bound(Intervals.begin(), Intervals.end(), Offset, [](const auto &LHS, const auto &RHS) { + return LHS < RHS.End; + }); // Lowest offset interval that (maybe) overlaps with the query offset + + if (It == Intervals.end()) { // No overlaps past offset + return {false, {}}; + } else if (It->Offset > Offset) { // No overlap, return the distance to the next possible overlap + return {false, It->Offset - Offset}; + } else { // Overlap, return the distance to the end of the overlap + return {true, It->End - Offset}; + } + } + + bool Intersect(Interval Entry) { + const auto It = std::upper_bound(Intervals.begin(), Intervals.end(), Entry, [](const auto &LHS, const auto &RHS) { + return LHS.Offset < RHS.End; + }); // Lowest offset interval that (maybe) overlaps with the query offset + + return It != Intervals.end() && It->Offset < Entry.End; + } +}; diff --git a/Source/Windows/WOW64/Module.cpp b/Source/Windows/WOW64/Module.cpp new file mode 100644 index 000000000..ee5dff680 --- /dev/null +++ b/Source/Windows/WOW64/Module.cpp @@ -0,0 +1,840 @@ +// SPDX-License-Identifier: MIT +/* +$info$ +tags: Bin|WOW64 +desc: Implements the WOW64 BT module API using FEXCore +$end_info$ +*/ + +// Thanks to André Zwing, whose ideas from https://github.com/AndreRH/hangover this code is based upon + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Common/Config.h" +#include "DummyHandlers.h" +#include "BTInterface.h" +#include "IntervalList.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ControlBits { + // When this is unset, a thread can be safely interrupted and have its context recovered + // IMPORTANT: This can only safely be written by the owning thread + static constexpr uint32_t IN_JIT{1U << 0}; + + // JIT entry polls this bit until it is unset, at which point CONTROL_IN_JIT will be set + static constexpr uint32_t PAUSED{1U << 1}; + + // When this is set, the CPU context stored in the CPU area has not yet been flushed to the FEX TLS + static constexpr uint32_t WOW_CPU_AREA_DIRTY{1U << 2}; +}; + +struct TLS { + enum class Slot : size_t { + ENTRY_CONTEXT = WOW64_TLS_MAX_NUMBER, + CONTROL_WORD = WOW64_TLS_MAX_NUMBER - 1, + THREAD_STATE = WOW64_TLS_MAX_NUMBER - 2, + }; + + _TEB *TEB; + + explicit TLS(_TEB *TEB) : TEB(TEB) {} + + std::atomic &ControlWord() const { + // TODO: Change this when libc++ gains std::atomic_ref support + return reinterpret_cast &>(TEB->TlsSlots[FEXCore::ToUnderlying(Slot::CONTROL_WORD)]); + } + + CONTEXT *&EntryContext() const { + return reinterpret_cast(TEB->TlsSlots[FEXCore::ToUnderlying(Slot::ENTRY_CONTEXT)]); + } + + FEXCore::Core::InternalThreadState *&ThreadState() const { + return reinterpret_cast(TEB->TlsSlots[FEXCore::ToUnderlying(Slot::THREAD_STATE)]); + } +}; + +class WowSyscallHandler; + +namespace { + namespace BridgeInstrs { + // These directly jumped to by the guest to make system calls + uint16_t Syscall{0x2ecd}; + uint16_t UnixCall{0x2ecd}; + } + + fextl::unique_ptr CTX; + fextl::unique_ptr SignalDelegator; + fextl::unique_ptr SyscallHandler; + + SYSTEM_CPU_INFORMATION CpuInfo{}; + + std::mutex ThreadSuspendLock; + + std::pair GetThreadTLS(HANDLE Thread) { + THREAD_BASIC_INFORMATION Info; + const NTSTATUS Err = NtQueryInformationThread(Thread, ThreadBasicInformation, &Info, sizeof(Info), nullptr); + return {Err, TLS{reinterpret_cast<_TEB *>(Info.TebBaseAddress)}}; + } + + TLS GetTLS() { + return TLS{NtCurrentTeb()}; + } + + uint64_t GetWowTEB(void *TEB) { + static constexpr size_t WowTEBOffsetMemberOffset{0x180c}; + return static_cast(*reinterpret_cast(reinterpret_cast(TEB) + WowTEBOffsetMemberOffset) + + reinterpret_cast(TEB)); + } + + bool IsAddressInJit(uint64_t Address) { + return GetTLS().ThreadState()->CPUBackend->IsAddressInCodeBuffer(Address); + } +} + +namespace Context { + void LoadStateFromWowContext(FEXCore::Core::InternalThreadState *Thread, uint64_t WowTEB, WOW64_CONTEXT *Context) { + auto &State = Thread->CurrentFrame->State; + + // General register state + + State.gregs[FEXCore::X86State::REG_RAX] = Context->Eax; + State.gregs[FEXCore::X86State::REG_RBX] = Context->Ebx; + State.gregs[FEXCore::X86State::REG_RCX] = Context->Ecx; + State.gregs[FEXCore::X86State::REG_RDX] = Context->Edx; + State.gregs[FEXCore::X86State::REG_RSI] = Context->Esi; + State.gregs[FEXCore::X86State::REG_RDI] = Context->Edi; + State.gregs[FEXCore::X86State::REG_RBP] = Context->Ebp; + State.gregs[FEXCore::X86State::REG_RSP] = Context->Esp; + + State.rip = Context->Eip; + CTX->SetFlagsFromCompactedEFLAGS(Thread, Context->EFlags); + + State.es_idx = Context->SegEs & 0xffff; + State.cs_idx = Context->SegCs & 0xffff; + State.ss_idx = Context->SegSs & 0xffff; + State.ds_idx = Context->SegDs & 0xffff; + State.fs_idx = Context->SegFs & 0xffff; + State.gs_idx = Context->SegGs & 0xffff; + + // The TEB is the only populated GDT entry by default + State.gdt[(Context->SegFs & 0xffff) >> 3].base = WowTEB; + State.fs_cached = WowTEB; + State.es_cached = 0; + State.cs_cached = 0; + State.ss_cached = 0; + State.ds_cached = 0; + + // Floating-point register state + const auto *XSave = reinterpret_cast(Context->ExtendedRegisters); + + memcpy(State.xmm.sse.data, XSave->XmmRegisters, sizeof(State.xmm.sse.data)); + memcpy(State.mm, XSave->FloatRegisters, sizeof(State.mm)); + + State.FCW = XSave->ControlWord; + State.flags[FEXCore::X86State::X87FLAG_C0_LOC] = (XSave->StatusWord >> 8) & 1; + State.flags[FEXCore::X86State::X87FLAG_C1_LOC] = (XSave->StatusWord >> 9) & 1; + State.flags[FEXCore::X86State::X87FLAG_C2_LOC] = (XSave->StatusWord >> 10) & 1; + State.flags[FEXCore::X86State::X87FLAG_C3_LOC] = (XSave->StatusWord >> 14) & 1; + State.flags[FEXCore::X86State::X87FLAG_TOP_LOC] = (XSave->StatusWord >> 11) & 0b111; + State.AbridgedFTW = XSave->TagWord; + } + + void StoreWowContextFromState(FEXCore::Core::InternalThreadState *Thread, WOW64_CONTEXT *Context) { + auto &State = Thread->CurrentFrame->State; + + // General register state + + Context->Eax = State.gregs[FEXCore::X86State::REG_RAX]; + Context->Ebx = State.gregs[FEXCore::X86State::REG_RBX]; + Context->Ecx = State.gregs[FEXCore::X86State::REG_RCX]; + Context->Edx = State.gregs[FEXCore::X86State::REG_RDX]; + Context->Esi = State.gregs[FEXCore::X86State::REG_RSI]; + Context->Edi = State.gregs[FEXCore::X86State::REG_RDI]; + Context->Ebp = State.gregs[FEXCore::X86State::REG_RBP]; + Context->Esp = State.gregs[FEXCore::X86State::REG_RSP]; + + Context->Eip = State.rip; + Context->EFlags = CTX->ReconstructCompactedEFLAGS(Thread); + + Context->SegEs = State.es_idx; + Context->SegCs = State.cs_idx; + Context->SegSs = State.ss_idx; + Context->SegDs = State.ds_idx; + Context->SegFs = State.fs_idx; + Context->SegGs = State.gs_idx; + + // Floating-point register state + + auto *XSave = reinterpret_cast(Context->ExtendedRegisters); + + memcpy(XSave->XmmRegisters, State.xmm.sse.data, sizeof(State.xmm.sse.data)); + memcpy(XSave->FloatRegisters, State.mm, sizeof(State.mm)); + + XSave->ControlWord = State.FCW; + XSave->StatusWord = + (State.flags[FEXCore::X86State::X87FLAG_TOP_LOC] << 11) | + (State.flags[FEXCore::X86State::X87FLAG_C0_LOC] << 8) | + (State.flags[FEXCore::X86State::X87FLAG_C1_LOC] << 9) | + (State.flags[FEXCore::X86State::X87FLAG_C2_LOC] << 10) | + (State.flags[FEXCore::X86State::X87FLAG_C3_LOC] << 14); + XSave->TagWord = State.AbridgedFTW; + + Context->FloatSave.ControlWord = XSave->ControlWord; + Context->FloatSave.StatusWord = XSave->StatusWord; + Context->FloatSave.TagWord = FEXCore::FPState::ConvertFromAbridgedFTW(XSave->StatusWord, State.mm, XSave->TagWord); + Context->FloatSave.ErrorOffset = XSave->ErrorOffset; + Context->FloatSave.ErrorSelector = XSave->ErrorSelector | (XSave->ErrorOpcode << 16); + Context->FloatSave.DataOffset = XSave->DataOffset; + Context->FloatSave.DataSelector = XSave->DataSelector; + Context->FloatSave.Cr0NpxState = XSave->StatusWord | 0xffff0000; + } + + NTSTATUS FlushThreadStateContext(HANDLE Thread) { + const auto [Err, TLS] = GetThreadTLS(Thread); + if (Err) { + return Err; + } + + WOW64_CONTEXT TmpWowContext{ + .ContextFlags = WOW64_CONTEXT_FULL | WOW64_CONTEXT_EXTENDED_REGISTERS + }; + + Context::StoreWowContextFromState(TLS.ThreadState(), &TmpWowContext); + return RtlWow64SetThreadContext(Thread, &TmpWowContext); + } + + void ReconstructThreadState(CONTEXT *Context) { + const auto &Config = SignalDelegator->GetConfig(); + auto *Thread = GetTLS().ThreadState(); + auto &State = Thread->CurrentFrame->State; + + State.rip = CTX->RestoreRIPFromHostPC(Thread, Context->Pc); + + // Spill all SRA GPRs + for (size_t i = 0; i < Config.SRAGPRCount; i++) { + State.gregs[i] = Context->X[Config.SRAGPRMapping[i]]; + } + + // Spill all SRA FPRs + for (size_t i = 0; i < Config.SRAFPRCount; i++) { + memcpy(State.xmm.sse.data[i], &Context->V[Config.SRAFPRMapping[i]], sizeof(__uint128_t)); + } + } + + WOW64_CONTEXT ReconstructWowContext(CONTEXT *Context) { + ReconstructThreadState(Context); + + WOW64_CONTEXT WowContext{ + .ContextFlags = WOW64_CONTEXT_ALL, + }; + + auto *XSave = reinterpret_cast(WowContext.ExtendedRegisters); + XSave->ControlWord = 0x27f; + XSave->MxCsr = 0x1f80; + + Context::StoreWowContextFromState(GetTLS().ThreadState(), &WowContext); + return WowContext; + } + + bool HandleUnalignedAccess(CONTEXT *Context) { + if (!GetTLS().ThreadState()->CPUBackend->IsAddressInCodeBuffer(Context->Pc)) { + return false; + } + + FEX_CONFIG_OPT(ParanoidTSO, PARANOIDTSO); + const auto Result = FEXCore::ArchHelpers::Arm64::HandleUnalignedAccess(ParanoidTSO(), Context->Pc, &Context->X0); + if (!Result.first) { + return false; + } + + Context->Pc += Result.second; + return true; + } + + void LockJITContext() { + uint32_t Expected = GetTLS().ControlWord().load(), New; + + // Spin until PAUSED is unset, setting IN_JIT when that occurs + do { + Expected = Expected & ~ControlBits::PAUSED; + New = (Expected | ControlBits::IN_JIT) & ~ControlBits::WOW_CPU_AREA_DIRTY; + } while (!GetTLS().ControlWord().compare_exchange_weak(Expected, New, std::memory_order::relaxed)); + std::atomic_signal_fence(std::memory_order::seq_cst); + + // If the CPU area is dirty, flush it to the JIT context before reentry + if (Expected & ControlBits::WOW_CPU_AREA_DIRTY) { + WOW64_CONTEXT *WowContext; + RtlWow64GetCurrentCpuArea(nullptr, reinterpret_cast(&WowContext), nullptr); + Context::LoadStateFromWowContext(GetTLS().ThreadState(), GetWowTEB(NtCurrentTeb()), WowContext); + } + } + + void UnlockJITContext() { + std::atomic_signal_fence(std::memory_order::seq_cst); + GetTLS().ControlWord().fetch_and(~ControlBits::IN_JIT, std::memory_order::relaxed); + } + + bool HandleSuspendInterrupt(CONTEXT *Context, uint64_t FaultAddress) { + if (FaultAddress != reinterpret_cast(&GetTLS().ThreadState()->InterruptFaultPage)) { + return false; + } + + void *TmpAddress = reinterpret_cast(FaultAddress); + SIZE_T TmpSize = FHU::FEX_PAGE_SIZE; + ULONG TmpProt; + NtProtectVirtualMemory(NtCurrentProcess(), &TmpAddress, &TmpSize, PAGE_READWRITE, &TmpProt); + + // Since interrupts only happen at the start of blocks, the reconstructed state should be entirely accurate + ReconstructThreadState(Context); + + // Yield to the suspender + UnlockJITContext(); + LockJITContext(); + + // Adjust context to return to the dispatcher, reloading SRA from thread state + const auto &Config = SignalDelegator->GetConfig(); + Context->Pc = Config.AbsoluteLoopTopAddressFillSRA; + return true; + } +} + +namespace Invalidation { + static IntervalList RWXIntervals; + static std::mutex RWXIntervalsLock; + + void HandleMemoryProtectionNotification(uint64_t Address, uint64_t Size, ULONG Prot) { + const auto AlignedBase = Address & FHU::FEX_PAGE_MASK; + const auto AlignedSize = (Address - AlignedBase + Size + FHU::FEX_PAGE_SIZE - 1) & FHU::FEX_PAGE_MASK; + + if (Prot & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE)) { + CTX->InvalidateGuestCodeRange(GetTLS().ThreadState(), AlignedBase, AlignedSize); + } + + if (Prot & PAGE_EXECUTE_READWRITE) { + LogMan::Msg::DFmt("Add SMC interval: {:X} - {:X}", AlignedBase, AlignedBase + AlignedSize); + std::scoped_lock Lock(RWXIntervalsLock); + RWXIntervals.Insert({AlignedBase, AlignedBase + AlignedSize}); + } else { + std::scoped_lock Lock(RWXIntervalsLock); + RWXIntervals.Remove({AlignedBase, AlignedBase + AlignedSize}); + } + } + + void InvalidateContainingSection(uint64_t Address, bool Free) { + MEMORY_BASIC_INFORMATION Info; + if (NtQueryVirtualMemory(NtCurrentProcess(), reinterpret_cast(Address), MemoryBasicInformation, &Info, sizeof(Info), nullptr)) + return; + + const auto SectionBase = reinterpret_cast(Info.AllocationBase); + const auto SectionSize = reinterpret_cast(Info.BaseAddress) + Info.RegionSize + - reinterpret_cast(Info.AllocationBase); + CTX->InvalidateGuestCodeRange(GetTLS().ThreadState(), SectionBase, SectionSize); + + if (Free) { + std::scoped_lock Lock(RWXIntervalsLock); + RWXIntervals.Remove({SectionBase, SectionBase + SectionSize}); + } + } + + void InvalidateAlignedInterval(uint64_t Address, uint64_t Size, bool Free) { + const auto AlignedBase = Address & FHU::FEX_PAGE_MASK; + const auto AlignedSize = (Address - AlignedBase + Size + FHU::FEX_PAGE_SIZE - 1) & FHU::FEX_PAGE_MASK; + CTX->InvalidateGuestCodeRange(GetTLS().ThreadState(), AlignedBase, AlignedSize); + + if (Free) { + std::scoped_lock Lock(RWXIntervalsLock); + RWXIntervals.Remove({AlignedBase, AlignedBase + AlignedSize}); + } + } + + void ReprotectRWXIntervals(uint64_t Address, uint64_t Size) { + const auto End = Address + Size; + std::scoped_lock Lock(RWXIntervalsLock); + + do { + const auto Query = RWXIntervals.Query(Address); + if (Query.Enclosed) { + void *TmpAddress = reinterpret_cast(Address); + SIZE_T TmpSize = static_cast(std::min(End, Address + Query.Size) - Address); + ULONG TmpProt; + NtProtectVirtualMemory(NtCurrentProcess(), &TmpAddress, &TmpSize, PAGE_EXECUTE_READ, &TmpProt); + } else if (!Query.Size) { + // No more regions past `Address` in the interval list + break; + } + + Address += Query.Size; + } while (Address < End); + } + + bool HandleRWXAccessViolation(uint64_t FaultAddress) { + const bool NeedsInvalidate = [](uint64_t Address) { + std::unique_lock Lock(RWXIntervalsLock); + const bool Enclosed = RWXIntervals.Query(Address).Enclosed; + // Invalidate just the single faulting page + if (!Enclosed) + return false; + + ULONG TmpProt; + void *TmpAddress = reinterpret_cast(Address); + SIZE_T TmpSize = 1; + NtProtectVirtualMemory(NtCurrentProcess(), &TmpAddress, &TmpSize, PAGE_EXECUTE_READWRITE, &TmpProt); + return true; + }(FaultAddress); + + if (NeedsInvalidate) { + // RWXIntervalsLock cannot be held during invalidation + CTX->InvalidateGuestCodeRange(GetTLS().ThreadState(), FaultAddress & FHU::FEX_PAGE_MASK, FHU::FEX_PAGE_SIZE); + return true; + } + return false; + } +} + +namespace Logging { + void MsgHandler(LogMan::DebugLevels Level, char const *Message) { + const auto Output = fextl::fmt::format("[{}][{:X}] {}\n", LogMan::DebugLevelStr(Level), GetCurrentThreadId(), Message); + __wine_dbg_output(Output.c_str()); + } + + void AssertHandler(char const *Message) { + const auto Output = fextl::fmt::format("[ASSERT] {}\n", Message); + __wine_dbg_output(Output.c_str()); + } + + void Init() { + LogMan::Throw::InstallHandler(AssertHandler); + LogMan::Msg::InstallHandler(MsgHandler); + } +} + +class WowSyscallHandler : public FEXCore::HLE::SyscallHandler, public FEXCore::Allocator::FEXAllocOperators { +public: + WowSyscallHandler() { + OSABI = FEXCore::HLE::SyscallOSABI::OS_WIN32; + } + + uint64_t HandleSyscall(FEXCore::Core::CpuStateFrame *Frame, FEXCore::HLE::SyscallArguments *Args) override { + const uint64_t ReturnRIP = *(uint32_t *)(Frame->State.gregs[FEXCore::X86State::REG_RSP]); // Return address from the stack + uint64_t ReturnRSP = Frame->State.gregs[FEXCore::X86State::REG_RSP] + 4; // Stack pointer after popping return address + uint64_t ReturnRAX = 0; + + if (Frame->State.rip == (uint64_t)&BridgeInstrs::UnixCall) { + struct StackLayout { + unixlib_handle_t Handle; + UINT32 ID; + ULONG32 Args; + } *StackArgs = reinterpret_cast(ReturnRSP); + + ReturnRSP += sizeof(StackLayout); + + Context::UnlockJITContext(); + ReturnRAX = static_cast(__wine_unix_call(StackArgs->Handle, StackArgs->ID, ULongToPtr(StackArgs->Args))); + Context::LockJITContext(); + } else if (Frame->State.rip == (uint64_t)&BridgeInstrs::Syscall) { + const uint64_t EntryRAX = Frame->State.gregs[FEXCore::X86State::REG_RAX]; + + Context::UnlockJITContext(); + ReturnRAX = static_cast(Wow64SystemServiceEx(static_cast(EntryRAX), + reinterpret_cast(ReturnRSP + 4))); + Context::LockJITContext(); + + } + // If a new context has been set, use it directly and don't return to the syscall caller + if (Frame->State.rip == (uint64_t)&BridgeInstrs::Syscall || + Frame->State.rip == (uint64_t)&BridgeInstrs::UnixCall) { + Frame->State.gregs[FEXCore::X86State::REG_RAX] = ReturnRAX; + Frame->State.gregs[FEXCore::X86State::REG_RSP] = ReturnRSP; + Frame->State.rip = ReturnRIP; + } + + // NORETURNEDRESULT causes this result to be ignored since we restore all registers back from memory after a syscall anyway + return 0; + } + + FEXCore::HLE::SyscallABI GetSyscallABI(uint64_t Syscall) override { + return { .NumArgs = 0, .HasReturn = false, .HostSyscallNumber = -1 }; + } + + FEXCore::HLE::AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestAddr) override { + return {0, 0}; + } + + void MarkGuestExecutableRange(FEXCore::Core::InternalThreadState *Thread, uint64_t Start, uint64_t Length) override { + Invalidation::ReprotectRWXIntervals(Start, Length); + } +}; + +void BTCpuProcessInit() { + Logging::Init(); + FEX::Config::InitializeConfigs(); + FEXCore::Config::Initialize(); + FEXCore::Config::AddLayer(FEX::Config::CreateGlobalMainLayer()); + FEXCore::Config::AddLayer(FEX::Config::CreateMainLayer()); + FEXCore::Config::Load(); + FEXCore::Config::ReloadMetaLayer(); + + FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_IS_INTERPRETER, "0"); + FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_INTERPRETER_INSTALLED, "0"); + FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_IS64BIT_MODE, "0"); + + // Not applicable to Windows + FEXCore::Config::EraseSet(FEXCore::Config::ConfigOption::CONFIG_TSOAUTOMIGRATION, "0"); + + FEXCore::Context::InitializeStaticTables(FEXCore::Context::MODE_32BIT); + + SignalDelegator = fextl::make_unique(); + SyscallHandler = fextl::make_unique(); + + CTX = FEXCore::Context::Context::CreateNewContext(); + CTX->InitializeContext(); + CTX->SetSignalDelegator(SignalDelegator.get()); + CTX->SetSyscallHandler(SyscallHandler.get()); + CTX->InitCore(0, 0); + + CpuInfo.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL; + + // Baseline FEX feature-set + CpuInfo.ProcessorFeatureBits = CPU_FEATURE_VME | CPU_FEATURE_TSC | CPU_FEATURE_CMOV | CPU_FEATURE_PGE | + CPU_FEATURE_PSE | CPU_FEATURE_MTRR | CPU_FEATURE_CX8 | CPU_FEATURE_MMX | + CPU_FEATURE_X86 | CPU_FEATURE_PAT | CPU_FEATURE_FXSR | CPU_FEATURE_SEP | + CPU_FEATURE_SSE | CPU_FEATURE_3DNOW | CPU_FEATURE_SSE2 | CPU_FEATURE_SSE3 | + CPU_FEATURE_CX128 | CPU_FEATURE_NX | CPU_FEATURE_SSSE3 | CPU_FEATURE_SSE41 | + CPU_FEATURE_PAE | CPU_FEATURE_DAZ; + + // Features that require specific host CPU support + const auto CPUIDResult01 = CTX->RunCPUIDFunction(0x01, 0); + if (CPUIDResult01.ecx & (1 << 20)) { + CpuInfo.ProcessorFeatureBits |= CPU_FEATURE_SSE42; + } + if (CPUIDResult01.ecx & (1 << 27)) { + CpuInfo.ProcessorFeatureBits |= CPU_FEATURE_XSAVE; + } + if (CPUIDResult01.ecx & (1 << 28)) { + CpuInfo.ProcessorFeatureBits |= CPU_FEATURE_AVX; + } + + const auto CPUIDResult07 = CTX->RunCPUIDFunction(0x07, 0); + if (CPUIDResult07.ebx & (1 << 5)) { + CpuInfo.ProcessorFeatureBits |= CPU_FEATURE_AVX2; + } + + const auto FamilyIdentifier = CPUIDResult01.eax; + CpuInfo.ProcessorLevel = ((FamilyIdentifier >> 8) & 0xf) + ((FamilyIdentifier >> 20) & 0xff); // Family + CpuInfo.ProcessorRevision = (FamilyIdentifier & 0xf0000) >> 4; // Extended Model + CpuInfo.ProcessorRevision |= (FamilyIdentifier & 0xf0) << 4; // Model + CpuInfo.ProcessorRevision |= FamilyIdentifier & 0xf; // Stepping +} + +NTSTATUS BTCpuThreadInit() { + GetTLS().ThreadState() = CTX->CreateThread(nullptr, 0); + + return STATUS_SUCCESS; +} + +NTSTATUS BTCpuThreadTerm(HANDLE Thread) { + const auto [Err, TLS] = GetThreadTLS(Thread); + if (Err) { + return Err; + } + + CTX->DestroyThread(TLS.ThreadState()); + return STATUS_SUCCESS; +} + +void *BTCpuGetBopCode() { + return &BridgeInstrs::Syscall; +} + +void *__wine_get_unix_opcode() { + return &BridgeInstrs::UnixCall; +} + +NTSTATUS BTCpuGetContext(HANDLE Thread, HANDLE Process, void *Unknown, WOW64_CONTEXT *Context) { + auto [Err, TLS] = GetThreadTLS(Thread); + if (Err) { + return Err; + } + + if (!(TLS.ControlWord().load(std::memory_order::relaxed) & ControlBits::WOW_CPU_AREA_DIRTY)) { + if (Err = Context::FlushThreadStateContext(Thread); Err) { + return Err; + } + } + + return RtlWow64GetThreadContext(Thread, Context); +} + +NTSTATUS BTCpuSetContext(HANDLE Thread, HANDLE Process, void *Unknown, WOW64_CONTEXT *Context) { + auto [Err, TLS] = GetThreadTLS(Thread); + if (Err) { + return Err; + } + + + // Back-up the input context incase we've been passed the CPU area (the flush below would wipe it out otherwise) + WOW64_CONTEXT TmpContext = *Context; + + if (!(TLS.ControlWord().load(std::memory_order::relaxed) & ControlBits::WOW_CPU_AREA_DIRTY)) { + if (Err = Context::FlushThreadStateContext(Thread); Err) { + return Err; + } + } + + // Merge the input context into the CPU area then pass the full context into the JIT + if (Err = RtlWow64SetThreadContext(Thread, &TmpContext); Err) { + return Err; + } + + TmpContext.ContextFlags = WOW64_CONTEXT_FULL | WOW64_CONTEXT_EXTENDED_REGISTERS; + + if (Err = RtlWow64GetThreadContext(Thread, &TmpContext); Err) { + return Err; + } + + Context::LoadStateFromWowContext(TLS.ThreadState(), GetWowTEB(TLS.TEB), &TmpContext); + return STATUS_SUCCESS; +} + +void BTCpuSimulate() { + CONTEXT entry_context; + RtlCaptureContext(&entry_context); + + // APC handling calls BTCpuSimulate from syscalls and then use NtContinue to return to the previous context, + // to avoid the saved context being clobbered in this case only save the entry context highest in the stack + if (!GetTLS().EntryContext() || GetTLS().EntryContext()->Sp <= entry_context.Sp) { + GetTLS().EntryContext() = &entry_context; + } + + Context::LockJITContext(); + CTX->ExecuteThread(GetTLS().ThreadState()); + Context::UnlockJITContext(); +} + +NTSTATUS BTCpuSuspendLocalThread(HANDLE Thread, ULONG *Count) { + THREAD_BASIC_INFORMATION Info; + if (NTSTATUS Err = NtQueryInformationThread(Thread, ThreadBasicInformation, &Info, sizeof(Info), nullptr); Err) { + return Err; + } + + const auto ThreadTID = reinterpret_cast(Info.ClientId.UniqueThread); + if (ThreadTID == GetCurrentThreadId()) { + LogMan::Msg::DFmt("Suspending self"); + // Mark the CPU area as dirty, to force the JIT context to be restored from it on entry as it may be changed using + // SetThreadContext (which doesn't use the BTCpu API) + if (!(GetTLS().ControlWord().fetch_or(ControlBits::WOW_CPU_AREA_DIRTY, std::memory_order::relaxed) & + ControlBits::WOW_CPU_AREA_DIRTY)) { + if (NTSTATUS Err = Context::FlushThreadStateContext(Thread); Err) { + return Err; + } + } + + return NtSuspendThread(Thread, Count); + } + + LogMan::Msg::DFmt("Suspending thread: {:X}", ThreadTID); + + auto [Err, TLS] = GetThreadTLS(Thread); + if (Err) { + return Err; + } + + std::scoped_lock Lock(ThreadSuspendLock); + // If CONTROL_IN_JIT is unset at this point, then it can never be set (and thus the JIT cannot be reentered) as + // CONTROL_PAUSED has been set, as such, while this may redundantly request interrupts in rare cases it will never + // miss them + if (TLS.ControlWord().fetch_or(ControlBits::PAUSED, std::memory_order::relaxed) & ControlBits::IN_JIT) { + LogMan::Msg::DFmt("Thread {:X} is in JIT, polling for interrupt", ThreadTID); + + ULONG TmpProt; + void *TmpAddress = &TLS.ThreadState()->InterruptFaultPage; + SIZE_T TmpSize = FHU::FEX_PAGE_SIZE; + NtProtectVirtualMemory(NtCurrentProcess(), &TmpAddress, &TmpSize, PAGE_READONLY, &TmpProt); + } + + // Spin until the JIT is interrupted + while (TLS.ControlWord().load() & ControlBits::IN_JIT); + + // The JIT has now been interrupted and the context stored in the thread's CPU area is up-to-date + if (Err = NtSuspendThread(Thread, Count); Err) { + TLS.ControlWord().fetch_and(~ControlBits::PAUSED, std::memory_order::relaxed); + return Err; + } + + CONTEXT TmpContext{ + .ContextFlags = CONTEXT_INTEGER, + }; + + // NtSuspendThread may return before the thread is actually suspended, so a sync operation like NtGetContextThread + // needs to be called to ensure it is before we unset CONTROL_PAUSED + std::ignore = NtGetContextThread(Thread, &TmpContext); + + // Mark the CPU area as dirty, to force the JIT context to be restored from it on entry as it may be changed using + // SetThreadContext (which doesn't use the BTCpu API) + if (!(TLS.ControlWord().fetch_or(ControlBits::WOW_CPU_AREA_DIRTY, std::memory_order::relaxed) & ControlBits::WOW_CPU_AREA_DIRTY)) { + if (Err = Context::FlushThreadStateContext(Thread); Err) { + return Err; + } + } + + LogMan::Msg::DFmt("Thread suspended: {:X}", ThreadTID); + + // Now the thread is suspended on the host, unset CONTROL_PAUSED so that NtResumeThread will + // continue execution in the JIT + TLS.ControlWord().fetch_and(~ControlBits::PAUSED, std::memory_order::relaxed); + + return Err; +} + +NTSTATUS BTCpuResetToConsistentState(EXCEPTION_POINTERS *Ptrs) { + auto *Context = Ptrs->ContextRecord; + const auto *Exception = Ptrs->ExceptionRecord; + if (Exception->ExceptionCode == EXCEPTION_DATATYPE_MISALIGNMENT && Context::HandleUnalignedAccess(Context)) { + LogMan::Msg::DFmt("Handled unaligned atomic: new pc: {:X}", Context->Pc); + NtContinue(Context, FALSE); + } + + if (Exception->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { + const auto FaultAddress = static_cast(Exception->ExceptionInformation[1]); + + if (Invalidation::HandleRWXAccessViolation(FaultAddress)) { + LogMan::Msg::DFmt("Handled self-modifying code: pc: {:X} fault: {:X}", Context->Pc, FaultAddress); + NtContinue(Context, FALSE); + } + + if (Context::HandleSuspendInterrupt(Context, FaultAddress)) { + LogMan::Msg::DFmt("Resumed from suspend"); + NtContinue(Context, FALSE); + } + } + + if (!IsAddressInJit(Context->Pc)) { + return STATUS_SUCCESS; + } + + LogMan::Msg::DFmt("Reconstructing context"); + + WOW64_CONTEXT WowContext = Context::ReconstructWowContext(Context); + LogMan::Msg::DFmt("pc: {:X} eip: {:X}", Context->Pc, WowContext.Eip); + + BTCpuSetContext(GetCurrentThread(), GetCurrentProcess(), nullptr, &WowContext); + Context::UnlockJITContext(); + + // Replace the host context with one captured before JIT entry so host code can unwind + memcpy(Context, GetTLS().EntryContext(), sizeof(*Context)); + + return STATUS_SUCCESS; +} + +void BTCpuFlushInstructionCache2(const void *Address, SIZE_T Size) { + Invalidation::InvalidateAlignedInterval(reinterpret_cast(Address), static_cast(Size), false); +} + +void BTCpuNotifyMemoryAlloc(void *Address, SIZE_T Size, ULONG Type, ULONG Prot) { + Invalidation::HandleMemoryProtectionNotification(reinterpret_cast(Address), static_cast(Size), + Prot); +} + +void BTCpuNotifyMemoryProtect(void *Address, SIZE_T Size, ULONG NewProt) { + Invalidation::HandleMemoryProtectionNotification(reinterpret_cast(Address), static_cast(Size), + NewProt); +} + +void BTCpuNotifyMemoryFree(void *Address, SIZE_T Size, ULONG FreeType) { + if (!Size) { + Invalidation::InvalidateContainingSection(reinterpret_cast(Address), true); + } else if (FreeType & MEM_DECOMMIT) { + Invalidation::InvalidateAlignedInterval(reinterpret_cast(Address), static_cast(Size), true); + } +} + +void BTCpuNotifyUnmapViewOfSection(void *Address, ULONG Flags) { + Invalidation::InvalidateContainingSection(reinterpret_cast(Address), true); +} + +BOOLEAN WINAPI BTCpuIsProcessorFeaturePresent(UINT Feature) { + switch (Feature) { + case PF_FLOATING_POINT_PRECISION_ERRATA: + return FALSE; + case PF_FLOATING_POINT_EMULATED: + return FALSE; + case PF_COMPARE_EXCHANGE_DOUBLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_CX8); + case PF_MMX_INSTRUCTIONS_AVAILABLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_MMX); + case PF_XMMI_INSTRUCTIONS_AVAILABLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_SSE); + case PF_3DNOW_INSTRUCTIONS_AVAILABLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_3DNOW); + case PF_RDTSC_INSTRUCTION_AVAILABLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_TSC); + case PF_PAE_ENABLED: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_PAE); + case PF_XMMI64_INSTRUCTIONS_AVAILABLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_SSE2); + case PF_SSE3_INSTRUCTIONS_AVAILABLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_SSE3); + case PF_SSSE3_INSTRUCTIONS_AVAILABLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_SSSE3); + case PF_XSAVE_ENABLED: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_XSAVE); + case PF_COMPARE_EXCHANGE128: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_CX128); + case PF_SSE_DAZ_MODE_AVAILABLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_DAZ); + case PF_NX_ENABLED: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_NX); + case PF_SECOND_LEVEL_ADDRESS_TRANSLATION: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_2NDLEV); + case PF_VIRT_FIRMWARE_ENABLED: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_VIRT); + case PF_RDWRFSGSBASE_AVAILABLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_RDFS); + case PF_FASTFAIL_AVAILABLE: + return TRUE; + case PF_SSE4_1_INSTRUCTIONS_AVAILABLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_SSE41); + case PF_SSE4_2_INSTRUCTIONS_AVAILABLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_SSE42); + case PF_AVX_INSTRUCTIONS_AVAILABLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_AVX); + case PF_AVX2_INSTRUCTIONS_AVAILABLE: + return !!(CpuInfo.ProcessorFeatureBits & CPU_FEATURE_AVX2); + default: + LogMan::Msg::DFmt("Unknown CPU feature: {:X}", Feature); + return FALSE; + } +} + +BOOLEAN BTCpuUpdateProcessorInformation(SYSTEM_CPU_INFORMATION *Info) { + Info->ProcessorArchitecture = CpuInfo.ProcessorArchitecture; + Info->ProcessorLevel = CpuInfo.ProcessorLevel; + Info->ProcessorRevision = CpuInfo.ProcessorRevision; + Info->ProcessorFeatureBits = CpuInfo.ProcessorFeatureBits; + return TRUE; +} diff --git a/Source/Windows/WOW64/libwow64fex.def b/Source/Windows/WOW64/libwow64fex.def new file mode 100644 index 000000000..f78953474 --- /dev/null +++ b/Source/Windows/WOW64/libwow64fex.def @@ -0,0 +1,20 @@ +LIBRARY libwow64fex.dll + +EXPORTS + BTCpuFlushInstructionCache2 + BTCpuGetBopCode + BTCpuGetContext + BTCpuIsProcessorFeaturePresent + BTCpuNotifyMemoryAlloc + BTCpuNotifyMemoryProtect + BTCpuNotifyMemoryFree + BTCpuNotifyUnmapViewOfSection + BTCpuProcessInit + BTCpuResetToConsistentState + BTCpuSetContext + BTCpuSimulate + BTCpuSuspendLocalThread + BTCpuThreadInit + BTCpuThreadTerm + BTCpuUpdateProcessorInformation + __wine_get_unix_opcode diff --git a/Source/Windows/include/wine/debug.h b/Source/Windows/include/wine/debug.h new file mode 100644 index 000000000..70a4868e0 --- /dev/null +++ b/Source/Windows/include/wine/debug.h @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// SPDX-FileCopyrightText: Copyright 1999 Patrik Stridvall + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int __cdecl __wine_dbg_output( const char *str ); + +#ifdef __cplusplus +} +#endif diff --git a/Source/Windows/include/wine/unixlib.h b/Source/Windows/include/wine/unixlib.h new file mode 100644 index 000000000..bca7ae3a8 --- /dev/null +++ b/Source/Windows/include/wine/unixlib.h @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// SPDX-FileCopyrightText: Copyright (C) 2021 Alexandre Julliard + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef UINT64 unixlib_handle_t; + +NTSTATUS WINAPI __wine_unix_call( unixlib_handle_t handle, unsigned int code, void *args ); + +#ifdef __cplusplus +} +#endif diff --git a/Source/Windows/include/winternl.h b/Source/Windows/include/winternl.h new file mode 100644 index 000000000..dddcc6963 --- /dev/null +++ b/Source/Windows/include/winternl.h @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// SPDX-FileCopyrightText: Copyright (C) the Wine project + +#pragma once + +#include_next + +#ifdef __cplusplus +extern "C" { +#endif + +#define NtCurrentProcess() ((HANDLE)~(ULONG_PTR)0) + +#define WOW64_TLS_MAX_NUMBER 19 + +typedef struct _THREAD_BASIC_INFORMATION +{ + NTSTATUS ExitStatus; + PVOID TebBaseAddress; + CLIENT_ID ClientId; + ULONG_PTR AffinityMask; + LONG Priority; + LONG BasePriority; +} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; + +/* System Information Class 0x01 */ + +typedef struct _SYSTEM_CPU_INFORMATION { + USHORT ProcessorArchitecture; + USHORT ProcessorLevel; + USHORT ProcessorRevision; + USHORT MaximumProcessors; + ULONG ProcessorFeatureBits; +} SYSTEM_CPU_INFORMATION, *PSYSTEM_CPU_INFORMATION; + +/* definitions of bits in the Feature set for the x86 processors */ +#define CPU_FEATURE_VME 0x00000005 /* Virtual 86 Mode Extensions */ +#define CPU_FEATURE_TSC 0x00000002 /* Time Stamp Counter available */ +#define CPU_FEATURE_CMOV 0x00000008 /* Conditional Move instruction*/ +#define CPU_FEATURE_PGE 0x00000014 /* Page table Entry Global bit */ +#define CPU_FEATURE_PSE 0x00000024 /* Page Size Extension */ +#define CPU_FEATURE_MTRR 0x00000040 /* Memory Type Range Registers */ +#define CPU_FEATURE_CX8 0x00000080 /* Compare and eXchange 8 byte instr. */ +#define CPU_FEATURE_MMX 0x00000100 /* Multi Media eXtensions */ +#define CPU_FEATURE_X86 0x00000200 /* seems to be always ON, on the '86 */ +#define CPU_FEATURE_PAT 0x00000400 /* Page Attribute Table */ +#define CPU_FEATURE_FXSR 0x00000800 /* FXSAVE and FXSTORE instructions */ +#define CPU_FEATURE_SEP 0x00001000 /* SYSENTER and SYSEXIT instructions */ +#define CPU_FEATURE_SSE 0x00002000 /* SSE extensions (ext. MMX) */ +#define CPU_FEATURE_3DNOW 0x00004000 /* 3DNOW instructions available */ +#define CPU_FEATURE_SSE2 0x00010000 /* SSE2 extensions (XMMI64) */ +#define CPU_FEATURE_DS 0x00020000 /* Debug Store */ +#define CPU_FEATURE_HTT 0x00040000 /* Hyper Threading Technology */ +#define CPU_FEATURE_SSE3 0x00080000 /* SSE3 extensions */ +#define CPU_FEATURE_CX128 0x00100000 /* cmpxchg16b instruction */ +#define CPU_FEATURE_XSAVE 0x00800000 /* XSAVE instructions */ +#define CPU_FEATURE_2NDLEV 0x04000000 /* Second-level address translation */ +#define CPU_FEATURE_VIRT 0x08000000 /* Virtualization support */ +#define CPU_FEATURE_RDFS 0x10000000 /* RDFSBASE etc. instructions */ +#define CPU_FEATURE_NX 0x20000000 /* Data execution prevention */ + +/* FIXME: following values are made up, actual flags are unknown */ +#define CPU_FEATURE_SSSE3 0x00008000 /* SSSE3 instructions */ +#define CPU_FEATURE_SSE41 0x01000000 /* SSE41 instructions */ +#define CPU_FEATURE_SSE42 0x02000000 /* SSE42 instructions */ +#define CPU_FEATURE_AVX 0x40000000 /* AVX instructions */ +#define CPU_FEATURE_AVX2 0x80000000 /* AVX2 instructions */ +#define CPU_FEATURE_PAE 0x00200000 +#define CPU_FEATURE_DAZ 0x00400000 + +typedef enum _MEMORY_INFORMATION_CLASS { + MemoryBasicInformation, + MemoryWorkingSetInformation, + MemoryMappedFilenameInformation, + MemoryRegionInformation, + MemoryWorkingSetExInformation, + MemorySharedCommitInformation, + MemoryImageInformation, + MemoryRegionInformationEx, + MemoryPrivilegedBasicInformation, + MemoryEnclaveImageInformation, + MemoryBasicInformationCapped, + MemoryPhysicalContiguityInformation, + MemoryBadInformation, + MemoryBadInformationAllProcesses, +#ifdef __WINESRC__ + MemoryWineUnixFuncs = 1000, + MemoryWineUnixWow64Funcs, +#endif +} MEMORY_INFORMATION_CLASS; + +NTSTATUS WINAPI Wow64SystemServiceEx(UINT,UINT*); + +NTSTATUS WINAPI RtlWow64SetThreadContext(HANDLE,const WOW64_CONTEXT*); +NTSTATUS WINAPI RtlWow64GetThreadContext(HANDLE,WOW64_CONTEXT*); +NTSTATUS WINAPI RtlWow64GetCurrentCpuArea(USHORT*,void**,void**); + +NTSTATUS WINAPI NtSuspendThread(HANDLE,PULONG); +NTSTATUS WINAPI NtGetContextThread(HANDLE,CONTEXT*); +NTSTATUS WINAPI NtContinue(PCONTEXT,BOOLEAN); +NTSTATUS WINAPI NtQueryVirtualMemory(HANDLE,LPCVOID,MEMORY_INFORMATION_CLASS,PVOID,SIZE_T,SIZE_T*); +NTSTATUS WINAPI NtProtectVirtualMemory(HANDLE,PVOID*,SIZE_T*,ULONG,ULONG*); + +#ifdef __cplusplus +} +#endif