Sync with trunk r63192.

svn path=/branches/condrv_restructure/; revision=63193
This commit is contained in:
Hermès Bélusca-Maïto 2014-05-08 14:40:52 +00:00
commit 7a0c3bde06
192 changed files with 39769 additions and 5166 deletions

View file

@ -58,7 +58,6 @@ VOID Usage(VOID)
int _tmain (int argc, TCHAR *argv[])
{
INT i;
INT LineLen1, LineLen2;
FILE *fp1, *fp2; // file pointers
PTCHAR Line1 = (TCHAR *)malloc(STRBUF * sizeof(TCHAR));
PTCHAR Line2 = (TCHAR *)malloc(STRBUF * sizeof(TCHAR));
@ -156,8 +155,8 @@ int _tmain (int argc, TCHAR *argv[])
_tprintf(_T("Comparing %s and %s...\n"), File1, File2);
while ((LineLen1 = GetLine(Line1, fp1) != 0) &&
(LineLen2 = GetLine(Line2, fp2) != 0))
while ((GetLine(Line1, fp1) != 0) &&
(GetLine(Line2, fp2) != 0))
{
// LineCount++;
while ((*Line1 != '\0') && (*Line2 != '\0'))

View file

@ -268,7 +268,7 @@ UpdateViewMenu(PMAIN_WND_INFO Info)
CheckMenuItem(hMenu,
IDC_SHOWHIDDEN,
MF_BYCOMMAND | (Info->bShowHidden) ? MF_CHECKED : MF_UNCHECKED);
MF_BYCOMMAND | (Info->bShowHidden ? MF_CHECKED : MF_UNCHECKED));
}

View file

@ -1303,13 +1303,13 @@ void shell(int argc, const char *argv[])
if (argc > 1)
{
strncat(CmdLine, " /C", MAX_PATH);
strncat(CmdLine, " /C", MAX_PATH - strlen(CmdLine) - 1);
}
for (i=1; i<argc; i++)
{
strncat(CmdLine, " ", MAX_PATH);
strncat(CmdLine, argv[i], MAX_PATH);
strncat(CmdLine, " ", MAX_PATH - strlen(CmdLine) - 1);
strncat(CmdLine, argv[i], MAX_PATH - strlen(CmdLine) - 1);
}
StartupInfo.cb = sizeof( StartupInfo );

View file

@ -333,8 +333,8 @@ LPTSTR GetConnectionDescription(LPTSTR lpClass)
(PBYTE)lpKeyClass,
&dwDataSize) != ERROR_SUCCESS)
{
lpKeyClass = NULL;
HeapFree(ProcessHeap, 0, lpKeyClass);
lpKeyClass = NULL;
continue;
}
}

View file

@ -709,7 +709,7 @@ char* TANSIParser::ParseEscapeANSI(char* pszBuffer, char* pszBufferEnd)
case 'n':
if (iCurrentParam == 1 && iParam[0]==5) {
// report the cursor position
Network.WriteString("\x1B[0n", 6);
Network.WriteString("\x1B[0n", 4);
break;
}
if (iCurrentParam == 1 && iParam[0]==6){

File diff suppressed because it is too large Load diff

View file

@ -181,44 +181,58 @@ typedef struct
} BIOS_DISK, *PBIOS_DISK;
PPARTLIST
CreatePartitionList (SHORT Left,
CreatePartitionList(
SHORT Left,
SHORT Top,
SHORT Right,
SHORT Bottom);
VOID
DestroyPartitionList (PPARTLIST List);
DestroyPartitionList(
PPARTLIST List);
VOID
DrawPartitionList (PPARTLIST List);
DrawPartitionList(
PPARTLIST List);
DWORD
SelectPartition(PPARTLIST List, ULONG DiskNumber, ULONG PartitionNumber);
SelectPartition(
PPARTLIST List,
ULONG DiskNumber,
ULONG PartitionNumber);
BOOL
SetMountedDeviceValues(PPARTLIST List);
SetMountedDeviceValues(
PPARTLIST List);
VOID
ScrollDownPartitionList (PPARTLIST List);
ScrollDownPartitionList(
PPARTLIST List);
VOID
ScrollUpPartitionList (PPARTLIST List);
ScrollUpPartitionList(
PPARTLIST List);
VOID
CreateNewPartition (PPARTLIST List,
CreateNewPartition(
PPARTLIST List,
ULONGLONG PartitionSize,
BOOLEAN AutoCreate);
VOID
DeleteCurrentPartition (PPARTLIST List);
DeleteCurrentPartition(
PPARTLIST List);
VOID
CheckActiveBootPartition (PPARTLIST List);
CheckActiveBootPartition(
PPARTLIST List);
BOOLEAN
CheckForLinuxFdiskPartitions (PPARTLIST List);
CheckForLinuxFdiskPartitions(
PPARTLIST List);
BOOLEAN
WritePartitionsToDisk (PPARTLIST List);
WritePartitionsToDisk(
PPARTLIST List);
/* EOF */

View file

@ -397,13 +397,13 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
/* build command line for CreateProcess(): FullName + " " + rest */
BOOL quoted = !!_tcschr(First, ' ');
_tcscpy(szFullCmdLine, quoted ? _T("\"") : _T(""));
_tcsncat(szFullCmdLine, First, CMDLINE_LENGTH - _tcslen(szFullCmdLine));
_tcsncat(szFullCmdLine, quoted ? _T("\"") : _T(""), CMDLINE_LENGTH - _tcslen(szFullCmdLine));
_tcsncat(szFullCmdLine, First, CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
_tcsncat(szFullCmdLine, quoted ? _T("\"") : _T(""), CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
if (*rest)
{
_tcsncat(szFullCmdLine, _T(" "), CMDLINE_LENGTH - _tcslen(szFullCmdLine));
_tcsncat(szFullCmdLine, rest, CMDLINE_LENGTH - _tcslen(szFullCmdLine));
_tcsncat(szFullCmdLine, _T(" "), CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
_tcsncat(szFullCmdLine, rest, CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
}
TRACE ("[EXEC: %s]\n", debugstr_aw(szFullCmdLine));

View file

@ -1636,7 +1636,8 @@ HKCU,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons",,0x00
HKCU,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu",,0x00000012
HKCU,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu","{208D2C60-3AEA-1069-A2D7-08002B30309D}",0x00010001,0x00000000
HKCU,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}",,0x00000012
HKCU,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced","ListviewShadow",0x00010001,0x1
HKCU,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced","ListviewShadow",0x00010001,0x00000001
HKCU,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced","HideFileExt",0x00010001,0x00000000
; default shell
HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon",,0x00000012

View file

@ -36,6 +36,9 @@ if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
add_compile_flags("-Wno-microsoft")
endif()
if(DBG)
add_compile_flags_language("-Wold-style-declaration -Wdeclaration-after-statement" "C")
endif()
add_compile_flags_language("-fno-rtti -fno-exceptions" "CXX")
#bug

View file

@ -56,7 +56,8 @@ add_compile_flags("/wd4290")
# - C4163: 'identifier': not available as an intrinsic function
# - C4229: modifiers on data are ignored
# - C4700: uninitialized variable usage
add_compile_flags("/we4013 /we4020 /we4022 /we4047 /we4098 /we4113 /we4129 /we4163 /we4229 /we4700")
# - C4603: macro is not defined or definition is different after precompiled header use
add_compile_flags("/we4013 /we4020 /we4022 /we4047 /we4098 /we4113 /we4129 /we4163 /we4229 /we4700 /we4603")
# Enable warnings above the default level, but don't treat them as errors:
# - C4115: named type definition in parentheses

View file

@ -59,6 +59,6 @@ echo Preparing reactos...
cd ../reactos
rm -f CMakeCache.txt
cmake -G "$CMAKE_GENERATOR" -DENABLE_CCACHE:BOOL=1 -DCMAKE_TOOLCHAIN_FILE:FILEPATH=toolchain-gcc.cmake -DARCH:STRING=$ARCH -DREACTOS_BUILD_TOOLS_DIR:PATH="$REACTOS_BUILD_TOOLS_DIR" $ROS_CMAKEOPTS "$REACTOS_SOURCE_DIR"
cmake -G "$CMAKE_GENERATOR" -DENABLE_CCACHE:BOOL=0 -DCMAKE_TOOLCHAIN_FILE:FILEPATH=toolchain-gcc.cmake -DARCH:STRING=$ARCH -DREACTOS_BUILD_TOOLS_DIR:PATH="$REACTOS_BUILD_TOOLS_DIR" $ROS_CMAKEOPTS "$REACTOS_SOURCE_DIR"
echo Configure script complete! Enter directories and execute appropriate build commands \(ex: ninja, make, makex, etc...\).

View file

@ -607,9 +607,9 @@ static HRESULT WINAPI IEnumDMO_fnNext(
hres = RegQueryValueExW(hkey, NULL, NULL, NULL, (LPBYTE) szValue, &len);
if (ERROR_SUCCESS == hres)
{
Names[count] = HeapAlloc(GetProcessHeap(), 0, strlenW(szValue) + 1);
Names[count] = HeapAlloc(GetProcessHeap(), 0, (strlenW(szValue) + 1) * sizeof(WCHAR));
if (Names[count])
strcmpW(Names[count], szValue);
strcpyW(Names[count], szValue);
}
wsprintfW(szGuidKey,szToGuidFmt,szNextKey);
CLSIDFromString(szGuidKey, &pCLSID[count]);

View file

@ -40,6 +40,7 @@ add_library(ntdll SHARED
${SOURCE}
${ntdll_asm}
def/ntdll.rc
${CMAKE_CURRENT_BINARY_DIR}/ntdll_stubs.c
${CMAKE_CURRENT_BINARY_DIR}/ntdll.def)
set_module_type(ntdll win32dll HOTPATCHABLE ENTRYPOINT 0)

View file

@ -101,6 +101,9 @@ CsrAllocateCaptureBuffer(IN ULONG ArgumentCount,
/* Align it to a 4-byte boundary */
BufferSize = (BufferSize + 3) & ~3;
/* Add the size of the alignment padding for each argument */
BufferSize += ArgumentCount * 3;
/* Allocate memory from the port heap */
CaptureBuffer = RtlAllocateHeap(CsrPortHeap, HEAP_ZERO_MEMORY, BufferSize);
if (CaptureBuffer == NULL) return NULL;

View file

@ -175,7 +175,7 @@
@ stdcall NtGetCurrentProcessorNumber() ; 5.2 and higher
@ stdcall NtGetDevicePowerState(ptr ptr)
@ stdcall NtGetPlugPlayEvent(long long ptr long)
;@ stdcall NtGetTickCount()
@ stdcall -stub NtGetTickCount()
@ stdcall NtGetWriteWatch(long long ptr long ptr ptr ptr)
@ stdcall NtImpersonateAnonymousToken(ptr)
@ stdcall NtImpersonateClientOfPort(ptr ptr)

View file

@ -82,8 +82,8 @@ LdrAlternateResourcesEnabled(VOID)
return FALSE;
}
ULONG_PTR
FORCEINLINE
ULONG_PTR
LdrpMakeCookie(VOID)
{
/* Generate a cookie */

View file

@ -221,7 +221,7 @@ GetDeviceCapabilities(
caps->vDriverVersion = 0x0100;
memset(caps->szPname, 0, sizeof(caps->szPname));
memcpy(caps->szPname, L"PC speaker\0", strlen("PC speaker\0") * 2);
wcscpy(caps->szPname, L"PC speaker");
caps->wTechnology = MOD_SQSYNTH;

View file

@ -2301,7 +2301,7 @@ CreateProcessInternalW(IN HANDLE hUserToken,
BOOLEAN InJob, SaferNeeded, UseLargePages, HavePrivilege;
BOOLEAN QuerySection, SkipSaferAndAppCompat;
CONTEXT Context;
BASE_API_MESSAGE CsrMsg;
BASE_API_MESSAGE CsrMsg[2];
PBASE_CREATE_PROCESS CreateProcessMsg;
PCSR_CAPTURE_BUFFER CaptureBuffer;
PVOID BaseAddress, PrivilegeState, RealTimePrivilegeState;
@ -2431,8 +2431,8 @@ CreateProcessInternalW(IN HANDLE hUserToken,
IsWowApp = FALSE;
/* Set message structures */
CreateProcessMsg = &CsrMsg.Data.CreateProcessRequest;
CheckVdmMsg = &CsrMsg.Data.CheckVDMRequest;
CreateProcessMsg = &CsrMsg[0].Data.CreateProcessRequest;
CheckVdmMsg = &CsrMsg[1].Data.CheckVDMRequest;
/* Clear the more complex structures by zeroing out their entire memory */
RtlZeroMemory(&Context, sizeof(Context));
@ -3197,7 +3197,7 @@ StartScan:
/* Pick which kind of WOW mode we want to run in */
VdmBinaryType = (dwCreationFlags &
CREATE_SEPARATE_WOW_VDM) ?
BINARY_TYPE_WOW : BINARY_TYPE_SEPARATE_WOW;
BINARY_TYPE_SEPARATE_WOW : BINARY_TYPE_WOW;
/* Get all the VDM settings and current status */
Status = BaseCheckVDM(VdmBinaryType,
@ -3205,7 +3205,7 @@ StartScan:
lpCommandLine,
lpCurrentDirectory,
&VdmAnsiEnv,
&CsrMsg,
&CsrMsg[1],
&VdmTask,
dwCreationFlags,
&StartupInfo,
@ -3342,7 +3342,7 @@ StartScan:
lpCommandLine,
lpCurrentDirectory,
&VdmAnsiEnv,
&CsrMsg,
&CsrMsg[1],
&VdmTask,
dwCreationFlags,
&StartupInfo,
@ -3966,6 +3966,8 @@ StartScan:
&VdmWaitObject,
VdmTask,
VdmBinaryType);
if (!Result)
{
/* Bail out on failure */
DPRINT1("Failed to update VDM with wait object\n");
@ -4335,7 +4337,7 @@ StartScan:
}
/* We are finally ready to call CSRSS to tell it about our new process! */
CsrClientCallServer((PCSR_API_MESSAGE)&CsrMsg,
CsrClientCallServer((PCSR_API_MESSAGE)&CsrMsg[0],
CaptureBuffer,
CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX,
BasepCreateProcess),
@ -4349,12 +4351,12 @@ StartScan:
}
/* Check if CSRSS failed to accept ownership of the new Windows process */
if (!NT_SUCCESS(CsrMsg.Status))
if (!NT_SUCCESS(CsrMsg[0].Status))
{
/* Terminate the process and enter failure path with the CSRSS status */
DPRINT1("Failed to tell csrss about new process\n");
BaseSetLastNTError(CsrMsg.Status);
NtTerminateProcess(ProcessHandle, CsrMsg.Status);
BaseSetLastNTError(CsrMsg[0].Status);
NtTerminateProcess(ProcessHandle, CsrMsg[0].Status);
Result = FALSE;
goto Quickie;
}

View file

@ -64,7 +64,7 @@ BaseIsDosApplication(IN PUNICODE_STRING PathName,
return 0;
}
BOOL
NTSTATUS
WINAPI
BaseCheckVDM(IN ULONG BinaryType,
IN PCWCH ApplicationName,
@ -77,9 +77,354 @@ BaseCheckVDM(IN ULONG BinaryType,
IN LPSTARTUPINFOW StartupInfo,
IN HANDLE hUserToken OPTIONAL)
{
/* This is not supported */
UNIMPLEMENTED;
return FALSE;
NTSTATUS Status;
PBASE_CHECK_VDM CheckVdm = &ApiMessage->Data.CheckVDMRequest;
PCSR_CAPTURE_BUFFER CaptureBuffer;
PWCHAR CurrentDir = NULL;
PWCHAR ShortAppName = NULL;
PWCHAR ShortCurrentDir = NULL;
ULONG Length;
PCHAR AnsiCmdLine = NULL;
PCHAR AnsiAppName = NULL;
PCHAR AnsiCurDirectory = NULL;
PCHAR AnsiDesktop = NULL;
PCHAR AnsiTitle = NULL;
PCHAR AnsiReserved = NULL;
STARTUPINFOA AnsiStartupInfo;
ULONG NumStrings = 5;
if (CurrentDirectory == NULL)
{
/* Allocate memory for the current directory path */
Length = GetCurrentDirectoryW(0, NULL);
CurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
Length * sizeof(WCHAR));
if (CurrentDir == NULL)
{
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
/* Get the current directory */
GetCurrentDirectoryW(Length, CurrentDir);
CurrentDirectory = CurrentDir;
}
/* Calculate the size of the short application name */
Length = GetShortPathNameW(ApplicationName, NULL, 0);
/* Allocate memory for the short application name */
ShortAppName = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
Length * sizeof(WCHAR));
if (!ShortAppName)
{
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
/* Get the short application name */
if (!GetShortPathNameW(ApplicationName, ShortAppName, Length))
{
/* Try to determine which error occurred */
switch (GetLastError())
{
case ERROR_NOT_ENOUGH_MEMORY:
{
Status = STATUS_NO_MEMORY;
break;
}
case ERROR_INVALID_PARAMETER:
{
Status = STATUS_INVALID_PARAMETER;
break;
}
default:
{
Status = STATUS_OBJECT_PATH_INVALID;
}
}
goto Cleanup;
}
/* Calculate the size of the short current directory path */
Length = GetShortPathNameW(CurrentDirectory, NULL, 0);
/* Allocate memory for the short current directory path */
ShortCurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
Length * sizeof(WCHAR));
if (!ShortCurrentDir)
{
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
/* Get the short current directory path */
if (!GetShortPathNameW(CurrentDirectory, ShortCurrentDir, Length))
{
/* Try to determine which error occurred */
switch (GetLastError())
{
case ERROR_NOT_ENOUGH_MEMORY:
{
Status = STATUS_NO_MEMORY;
break;
}
case ERROR_INVALID_PARAMETER:
{
Status = STATUS_INVALID_PARAMETER;
break;
}
default:
{
Status = STATUS_OBJECT_PATH_INVALID;
}
}
goto Cleanup;
}
/* Setup the input parameters */
CheckVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
CheckVdm->BinaryType = BinaryType;
CheckVdm->CodePage = CP_ACP;
CheckVdm->dwCreationFlags = CreationFlags;
CheckVdm->CurDrive = CurrentDirectory[0] - L'A';
CheckVdm->CmdLen = wcslen(CommandLine) + 1;
CheckVdm->AppLen = wcslen(ShortAppName) + 1;
CheckVdm->PifLen = 0; // TODO: PIF file support!
CheckVdm->CurDirectoryLen = wcslen(ShortCurrentDir) + 1;
CheckVdm->EnvLen = AnsiEnvironment->Length;
CheckVdm->DesktopLen = (StartupInfo->lpDesktop != NULL) ? (wcslen(StartupInfo->lpDesktop) + 1) : 0;
CheckVdm->TitleLen = (StartupInfo->lpTitle != NULL) ? (wcslen(StartupInfo->lpTitle) + 1) : 0;
CheckVdm->ReservedLen = (StartupInfo->lpReserved != NULL) ? (wcslen(StartupInfo->lpReserved) + 1) : 0;
if (StartupInfo->dwFlags & STARTF_USESTDHANDLES)
{
/* Set the standard handles */
CheckVdm->StdIn = StartupInfo->hStdInput;
CheckVdm->StdOut = StartupInfo->hStdOutput;
CheckVdm->StdErr = StartupInfo->hStdError;
}
/* Allocate memory for the ANSI strings */
AnsiCmdLine = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CmdLen);
AnsiAppName = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->AppLen);
AnsiCurDirectory = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CurDirectoryLen);
if (StartupInfo->lpDesktop) AnsiDesktop = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
CheckVdm->DesktopLen);
if (StartupInfo->lpTitle) AnsiTitle = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
CheckVdm->TitleLen);
if (StartupInfo->lpReserved) AnsiReserved = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
CheckVdm->ReservedLen);
if (!AnsiCmdLine
|| !AnsiAppName
|| !AnsiCurDirectory
|| (StartupInfo->lpDesktop && !AnsiDesktop)
|| (StartupInfo->lpTitle && !AnsiTitle)
|| (StartupInfo->lpReserved && !AnsiReserved))
{
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
/* Convert the command line into an ANSI string */
WideCharToMultiByte(CP_ACP,
0,
CommandLine,
CheckVdm->CmdLen,
AnsiCmdLine,
CheckVdm->CmdLen,
NULL,
NULL);
/* Convert the short application name into an ANSI string */
WideCharToMultiByte(CP_ACP,
0,
ShortAppName,
CheckVdm->AppLen,
AnsiAppName,
CheckVdm->AppLen,
NULL,
NULL);
/* Convert the short current directory path into an ANSI string */
WideCharToMultiByte(CP_ACP,
0,
ShortCurrentDir,
CheckVdm->CurDirectoryLen,
AnsiCurDirectory,
CheckVdm->CurDirectoryLen,
NULL,
NULL);
if (StartupInfo->lpDesktop)
{
/* Convert the desktop name into an ANSI string */
WideCharToMultiByte(CP_ACP,
0,
StartupInfo->lpDesktop,
CheckVdm->DesktopLen,
AnsiDesktop,
CheckVdm->DesktopLen,
NULL,
NULL);
NumStrings++;
}
if (StartupInfo->lpTitle)
{
/* Convert the title into an ANSI string */
WideCharToMultiByte(CP_ACP,
0,
StartupInfo->lpTitle,
CheckVdm->TitleLen,
AnsiTitle,
CheckVdm->TitleLen,
NULL,
NULL);
NumStrings++;
}
if (StartupInfo->lpReserved)
{
/* Convert the reserved value into an ANSI string */
WideCharToMultiByte(CP_ACP,
0,
StartupInfo->lpReserved,
CheckVdm->ReservedLen,
AnsiReserved,
CheckVdm->ReservedLen,
NULL,
NULL);
NumStrings++;
}
/* Fill the ANSI startup info structure */
RtlCopyMemory(&AnsiStartupInfo, StartupInfo, sizeof(STARTUPINFO));
AnsiStartupInfo.lpReserved = AnsiReserved;
AnsiStartupInfo.lpDesktop = AnsiDesktop;
AnsiStartupInfo.lpTitle = AnsiTitle;
/* Allocate the capture buffer */
CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings,
CheckVdm->CmdLen
+ CheckVdm->AppLen
+ CheckVdm->PifLen
+ CheckVdm->CurDirectoryLen
+ CheckVdm->DesktopLen
+ CheckVdm->TitleLen
+ CheckVdm->ReservedLen
+ CheckVdm->EnvLen
+ sizeof(STARTUPINFOA));
if (CaptureBuffer == NULL)
{
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
/* Capture the command line */
CsrCaptureMessageBuffer(CaptureBuffer,
AnsiCmdLine,
CheckVdm->CmdLen,
(PVOID*)&CheckVdm->CmdLine);
/* Capture the application name */
CsrCaptureMessageBuffer(CaptureBuffer,
AnsiAppName,
CheckVdm->AppLen,
(PVOID*)&CheckVdm->AppName);
CheckVdm->PifFile = NULL; // TODO: PIF file support!
/* Capture the current directory */
CsrCaptureMessageBuffer(CaptureBuffer,
AnsiCurDirectory,
CheckVdm->CurDirectoryLen,
(PVOID*)&CheckVdm->CurDirectory);
/* Capture the environment */
CsrCaptureMessageBuffer(CaptureBuffer,
AnsiEnvironment->Buffer,
CheckVdm->EnvLen,
(PVOID*)&CheckVdm->Env);
/* Capture the startup info structure */
CsrCaptureMessageBuffer(CaptureBuffer,
&AnsiStartupInfo,
sizeof(STARTUPINFOA),
(PVOID*)&CheckVdm->StartupInfo);
if (StartupInfo->lpDesktop)
{
/* Capture the desktop name */
CsrCaptureMessageBuffer(CaptureBuffer,
AnsiDesktop,
CheckVdm->DesktopLen,
(PVOID*)&CheckVdm->Desktop);
}
else CheckVdm->Desktop = NULL;
if (StartupInfo->lpTitle)
{
/* Capture the title */
CsrCaptureMessageBuffer(CaptureBuffer,
AnsiTitle,
CheckVdm->TitleLen,
(PVOID*)&CheckVdm->Title);
}
else CheckVdm->Title = NULL;
if (StartupInfo->lpReserved)
{
/* Capture the reserved parameter */
CsrCaptureMessageBuffer(CaptureBuffer,
AnsiReserved,
CheckVdm->ReservedLen,
(PVOID*)&CheckVdm->Reserved);
}
else CheckVdm->Reserved = NULL;
/* Send the message to CSRSS */
Status = CsrClientCallServer((PCSR_API_MESSAGE)ApiMessage,
CaptureBuffer,
CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepCheckVDM),
sizeof(BASE_CHECK_VDM));
/* Write back the task ID */
*iTask = CheckVdm->iTask;
Cleanup:
/* Free the ANSI strings */
if (AnsiCmdLine) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCmdLine);
if (AnsiAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiAppName);
if (AnsiCurDirectory) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCurDirectory);
if (AnsiDesktop) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiDesktop);
if (AnsiTitle) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiTitle);
if (AnsiReserved) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiReserved);
/* Free the capture buffer */
CsrFreeCaptureBuffer(CaptureBuffer);
/* Free the short paths */
if (ShortAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortAppName);
if (ShortCurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortCurrentDir);
/* Free the current directory, if it was allocated here */
if (CurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDir);
return Status;
}
BOOL
@ -89,10 +434,9 @@ BaseUpdateVDMEntry(IN ULONG UpdateIndex,
IN ULONG IndexInfo,
IN ULONG BinaryType)
{
#if 0 // Unimplemented in BASESRV
NTSTATUS Status;
BASE_API_MESSAGE ApiMessage;
PBASE_UPDATE_VDM_ENTRY UpdateVdmEntry = &ApiMessage.Data.UpdateVdmEntry;
PBASE_UPDATE_VDM_ENTRY UpdateVdmEntry = &ApiMessage.Data.UpdateVDMEntryRequest;
/* Check what update is being sent */
switch (UpdateIndex)
@ -155,7 +499,7 @@ BaseUpdateVDMEntry(IN ULONG UpdateIndex,
/* Return it to the caller */
*WaitHandle = UpdateVdmEntry->WaitObjectForParent;
}
#endif
/* We made it */
return TRUE;
}
@ -165,11 +509,10 @@ WINAPI
BaseCheckForVDM(IN HANDLE ProcessHandle,
OUT LPDWORD ExitCode)
{
#if 0 // Unimplemented in BASESRV
NTSTATUS Status;
EVENT_BASIC_INFORMATION EventBasicInfo;
BASE_API_MESSAGE ApiMessage;
PBASE_GET_VDM_EXIT_CODE GetVdmExitCode = &ApiMessage.Data.GetVdmExitCode;
PBASE_GET_VDM_EXIT_CODE GetVdmExitCode = &ApiMessage.Data.GetVDMExitCodeRequest;
/* It's VDM if the process is actually a wait handle (an event) */
Status = NtQueryEvent(ProcessHandle,
@ -192,7 +535,6 @@ BaseCheckForVDM(IN HANDLE ProcessHandle,
/* Get the exit code from the reply */
*ExitCode = GetVdmExitCode->ExitCode;
#endif
return TRUE;
}
@ -335,7 +677,7 @@ BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment,
if (!lpEnvironment)
{
/* Nope, create one */
Status = RtlCreateEnvironment(TRUE, (PWCHAR*)&Environment);
Status = RtlCreateEnvironment(TRUE, &Environment);
if (!NT_SUCCESS(Status)) goto Quickie;
}
else
@ -376,6 +718,7 @@ BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment,
p = NewEnvironment;
/* FIXME: Code here */
DPRINT1("BaseCreateVDMEnvironment is half-plemented!\n");
/* Terminate it */
*p++ = UNICODE_NULL;
@ -574,7 +917,7 @@ InternalGetBinaryType(HANDLE hFile)
return BINARY_PE_EXE32;
}
if(!memcmp(magic, "NE", 1))
if(!memcmp(magic, "NE", 2))
{
/* This is a Windows executable (NE) header. This can
* mean either a 16-bit OS/2 or a 16-bit Windows or even a
@ -755,46 +1098,399 @@ CmdBatNotification (
}
/*
* @unimplemented
* @implemented
*/
DWORD
VOID
WINAPI
ExitVDM (
DWORD Unknown0,
DWORD Unknown1
)
ExitVDM(BOOL IsWow, ULONG iWowTask)
{
STUB;
return 0;
BASE_API_MESSAGE ApiMessage;
PBASE_EXIT_VDM ExitVdm = &ApiMessage.Data.ExitVDMRequest;
/* Setup the input parameters */
ExitVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
ExitVdm->iWowTask = IsWow ? iWowTask : 0; /* Always zero for DOS tasks */
ExitVdm->WaitObjectForVDM = NULL;
/* Call CSRSS */
CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
NULL,
CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepExitVDM),
sizeof(BASE_EXIT_VDM));
/* Close the returned wait object handle, if any */
if (NT_SUCCESS(ApiMessage.Status) && (ExitVdm->WaitObjectForVDM != NULL))
{
CloseHandle(ExitVdm->WaitObjectForVDM);
}
}
/*
* @implemented
*/
BOOL
WINAPI
GetNextVDMCommand(PVDM_COMMAND_INFO CommandData)
{
NTSTATUS Status;
BOOL Result = FALSE;
BASE_API_MESSAGE ApiMessage;
PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommand = &ApiMessage.Data.GetNextVDMCommandRequest;
PBASE_IS_FIRST_VDM IsFirstVdm = &ApiMessage.Data.IsFirstVDMRequest;
PBASE_SET_REENTER_COUNT SetReenterCount = &ApiMessage.Data.SetReenterCountRequest;
PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
ULONG NumStrings = 0;
if (CommandData != NULL)
{
if (CommandData->VDMState & (VDM_NOT_LOADED | VDM_NOT_READY | VDM_READY))
{
/* Clear the structure */
ZeroMemory(GetNextVdmCommand, sizeof(*GetNextVdmCommand));
/* Setup the input parameters */
GetNextVdmCommand->iTask = CommandData->TaskId;
GetNextVdmCommand->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
GetNextVdmCommand->CmdLen = CommandData->CmdLen;
GetNextVdmCommand->AppLen = CommandData->AppLen;
GetNextVdmCommand->PifLen = CommandData->PifLen;
GetNextVdmCommand->CurDirectoryLen = CommandData->CurDirectoryLen;
GetNextVdmCommand->EnvLen = CommandData->EnvLen;
GetNextVdmCommand->DesktopLen = CommandData->DesktopLen;
GetNextVdmCommand->TitleLen = CommandData->TitleLen;
GetNextVdmCommand->ReservedLen = CommandData->ReservedLen;
GetNextVdmCommand->VDMState = CommandData->VDMState;
/* Count the number of strings */
if (CommandData->CmdLen) NumStrings++;
if (CommandData->AppLen) NumStrings++;
if (CommandData->PifLen) NumStrings++;
if (CommandData->CurDirectoryLen) NumStrings++;
if (CommandData->EnvLen) NumStrings++;
if (CommandData->DesktopLen) NumStrings++;
if (CommandData->TitleLen) NumStrings++;
if (CommandData->ReservedLen) NumStrings++;
/* Allocate the capture buffer */
CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings + 1,
GetNextVdmCommand->CmdLen
+ GetNextVdmCommand->AppLen
+ GetNextVdmCommand->PifLen
+ GetNextVdmCommand->CurDirectoryLen
+ GetNextVdmCommand->EnvLen
+ GetNextVdmCommand->DesktopLen
+ GetNextVdmCommand->TitleLen
+ GetNextVdmCommand->ReservedLen
+ sizeof(STARTUPINFOA));
if (CaptureBuffer == NULL)
{
BaseSetLastNTError(STATUS_NO_MEMORY);
goto Cleanup;
}
/* Allocate memory for the startup info */
CsrAllocateMessagePointer(CaptureBuffer,
sizeof(STARTUPINFOA),
(PVOID*)&GetNextVdmCommand->StartupInfo);
if (CommandData->CmdLen)
{
/* Allocate memory for the command line */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->CmdLen,
(PVOID*)&GetNextVdmCommand->CmdLine);
}
if (CommandData->AppLen)
{
/* Allocate memory for the application name */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->AppLen,
(PVOID*)&GetNextVdmCommand->AppName);
}
if (CommandData->PifLen)
{
/* Allocate memory for the PIF file name */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->PifLen,
(PVOID*)&GetNextVdmCommand->PifFile);
}
if (CommandData->CurDirectoryLen)
{
/* Allocate memory for the current directory */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->CurDirectoryLen,
(PVOID*)&GetNextVdmCommand->CurDirectory);
}
if (CommandData->EnvLen)
{
/* Allocate memory for the environment */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->EnvLen,
(PVOID*)&GetNextVdmCommand->Env);
}
if (CommandData->DesktopLen)
{
/* Allocate memory for the desktop name */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->DesktopLen,
(PVOID*)&GetNextVdmCommand->Desktop);
}
if (CommandData->TitleLen)
{
/* Allocate memory for the title */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->TitleLen,
(PVOID*)&GetNextVdmCommand->Title);
}
if (CommandData->ReservedLen)
{
/* Allocate memory for the reserved parameter */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->ReservedLen,
(PVOID*)&GetNextVdmCommand->Reserved);
}
do
{
/* Call CSRSS */
Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
CaptureBuffer,
CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepGetNextVDMCommand),
sizeof(BASE_GET_NEXT_VDM_COMMAND));
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
goto Cleanup;
}
/* Did we receive an event handle? */
if (GetNextVdmCommand->WaitObjectForVDM != NULL)
{
/* Wait for the event to become signaled and try again */
Status = NtWaitForSingleObject(GetNextVdmCommand->WaitObjectForVDM,
FALSE,
NULL);
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
goto Cleanup;
}
/* Set the retry flag and clear the exit code */
GetNextVdmCommand->VDMState |= VDM_FLAG_RETRY;
GetNextVdmCommand->ExitCode = 0;
}
}
while (GetNextVdmCommand->WaitObjectForVDM != NULL);
/* Write back the standard handles */
CommandData->StdIn = GetNextVdmCommand->StdIn;
CommandData->StdOut = GetNextVdmCommand->StdOut;
CommandData->StdErr = GetNextVdmCommand->StdErr;
/* Write back the startup info */
RtlMoveMemory(&CommandData->StartupInfo,
GetNextVdmCommand->StartupInfo,
sizeof(STARTUPINFOA));
if (CommandData->CmdLen)
{
/* Write back the command line */
RtlMoveMemory(CommandData->CmdLine,
GetNextVdmCommand->CmdLine,
GetNextVdmCommand->CmdLen);
/* Set the actual length */
CommandData->CmdLen = GetNextVdmCommand->CmdLen;
}
if (CommandData->AppLen)
{
/* Write back the application name */
RtlMoveMemory(CommandData->AppName,
GetNextVdmCommand->AppName,
GetNextVdmCommand->AppLen);
/* Set the actual length */
CommandData->AppLen = GetNextVdmCommand->AppLen;
}
if (CommandData->PifLen)
{
/* Write back the PIF file name */
RtlMoveMemory(CommandData->PifFile,
GetNextVdmCommand->PifFile,
GetNextVdmCommand->PifLen);
/* Set the actual length */
CommandData->PifLen = GetNextVdmCommand->PifLen;
}
if (CommandData->CurDirectoryLen)
{
/* Write back the current directory */
RtlMoveMemory(CommandData->CurDirectory,
GetNextVdmCommand->CurDirectory,
GetNextVdmCommand->CurDirectoryLen);
/* Set the actual length */
CommandData->CurDirectoryLen = GetNextVdmCommand->CurDirectoryLen;
}
if (CommandData->EnvLen)
{
/* Write back the environment */
RtlMoveMemory(CommandData->Env,
GetNextVdmCommand->Env,
GetNextVdmCommand->EnvLen);
/* Set the actual length */
CommandData->EnvLen = GetNextVdmCommand->EnvLen;
}
if (CommandData->DesktopLen)
{
/* Write back the desktop name */
RtlMoveMemory(CommandData->Desktop,
GetNextVdmCommand->Desktop,
GetNextVdmCommand->DesktopLen);
/* Set the actual length */
CommandData->DesktopLen = GetNextVdmCommand->DesktopLen;
}
if (CommandData->TitleLen)
{
/* Write back the title */
RtlMoveMemory(CommandData->Title,
GetNextVdmCommand->Title,
GetNextVdmCommand->TitleLen);
/* Set the actual length */
CommandData->TitleLen = GetNextVdmCommand->TitleLen;
}
if (CommandData->ReservedLen)
{
/* Write back the reserved parameter */
RtlMoveMemory(CommandData->Reserved,
GetNextVdmCommand->Reserved,
GetNextVdmCommand->ReservedLen);
/* Set the actual length */
CommandData->ReservedLen = GetNextVdmCommand->ReservedLen;
}
/* Write the remaining output parameters */
CommandData->TaskId = GetNextVdmCommand->iTask;
CommandData->CreationFlags = GetNextVdmCommand->dwCreationFlags;
CommandData->CodePage = GetNextVdmCommand->CodePage;
CommandData->ExitCode = GetNextVdmCommand->ExitCode;
CommandData->CurrentDrive = GetNextVdmCommand->CurrentDrive;
CommandData->VDMState = GetNextVdmCommand->VDMState;
CommandData->ComingFromBat = GetNextVdmCommand->fComingFromBat;
/* It was successful */
Result = TRUE;
}
else if ((CommandData->VDMState == VDM_INC_REENTER_COUNT)
|| (CommandData->VDMState == VDM_DEC_REENTER_COUNT))
{
/* Setup the input parameters */
SetReenterCount->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
SetReenterCount->fIncDec = CommandData->VDMState;
/* Call CSRSS */
Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
NULL,
CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepSetReenterCount),
sizeof(BASE_SET_REENTER_COUNT));
BaseSetLastNTError(Status);
Result = NT_SUCCESS(Status);
}
else
{
BaseSetLastNTError(STATUS_INVALID_PARAMETER);
Result = FALSE;
}
}
else
{
/* Call CSRSS */
Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
NULL,
CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepIsFirstVDM),
sizeof(BASE_IS_FIRST_VDM));
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
goto Cleanup;
}
/* Return TRUE if this is the first VDM */
Result = IsFirstVdm->FirstVDM;
}
Cleanup:
if (CaptureBuffer != NULL) CsrFreeCaptureBuffer(CaptureBuffer);
return Result;
}
/*
* @unimplemented
* @implemented
*/
DWORD
WINAPI
GetNextVDMCommand (
DWORD Unknown0
)
GetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
{
STUB;
return 0;
}
BASE_API_MESSAGE ApiMessage;
PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest;
PCSR_CAPTURE_BUFFER CaptureBuffer;
/*
* @unimplemented
*/
DWORD
WINAPI
GetVDMCurrentDirectories (
DWORD Unknown0,
DWORD Unknown1
)
{
STUB;
/* Allocate the capture buffer */
CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs);
if (CaptureBuffer == NULL)
{
BaseSetLastNTError(STATUS_NO_MEMORY);
return 0;
}
/* Setup the input parameters */
VDMCurrentDirsRequest->cchCurDirs = cchCurDirs;
CsrAllocateMessagePointer(CaptureBuffer,
cchCurDirs,
(PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs);
/* Call CSRSS */
CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
CaptureBuffer,
CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepGetVDMCurDirs),
sizeof(BASE_GETSET_VDM_CURDIRS));
/* Set the last error */
BaseSetLastNTError(ApiMessage.Status);
if (NT_SUCCESS(ApiMessage.Status))
{
/* Copy the result */
RtlMoveMemory(lpszzCurDirs, VDMCurrentDirsRequest->lpszzCurDirs, cchCurDirs);
}
/* Free the capture buffer */
CsrFreeCaptureBuffer(CaptureBuffer);
/* Return the size if it was successful, or if the buffer was too small */
return (NT_SUCCESS(ApiMessage.Status) || (ApiMessage.Status == STATUS_BUFFER_TOO_SMALL))
? VDMCurrentDirsRequest->cchCurDirs : 0;
}
@ -851,17 +1547,44 @@ RegisterWowExec (
/*
* @unimplemented
* @implemented
*/
BOOL
WINAPI
SetVDMCurrentDirectories (
DWORD Unknown0,
DWORD Unknown1
)
SetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
{
STUB;
BASE_API_MESSAGE ApiMessage;
PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest;
PCSR_CAPTURE_BUFFER CaptureBuffer;
/* Allocate the capture buffer */
CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs);
if (CaptureBuffer == NULL)
{
BaseSetLastNTError(STATUS_NO_MEMORY);
return FALSE;
}
/* Setup the input parameters */
VDMCurrentDirsRequest->cchCurDirs = cchCurDirs;
CsrCaptureMessageBuffer(CaptureBuffer,
lpszzCurDirs,
cchCurDirs,
(PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs);
/* Call CSRSS */
CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
CaptureBuffer,
CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepSetVDMCurDirs),
sizeof(BASE_GETSET_VDM_CURDIRS));
/* Free the capture buffer */
CsrFreeCaptureBuffer(CaptureBuffer);
/* Set the last error */
BaseSetLastNTError(ApiMessage.Status);
return NT_SUCCESS(ApiMessage.Status) ? TRUE : FALSE;
}
/*
@ -882,12 +1605,15 @@ VDMConsoleOperation (
/*
* @unimplemented
*/
DWORD
BOOL
WINAPI
VDMOperationStarted (
DWORD Unknown0
)
VDMOperationStarted(IN ULONG Unknown0)
{
STUB;
return 0;
DPRINT1("VDMOperationStarted(%d)\n", Unknown0);
return
BaseUpdateVDMEntry(VdmEntryUpdateControlCHandler,
NULL,
0,
Unknown0);
}

View file

@ -8,42 +8,6 @@
#pragma once
/* CONSTANTS ******************************************************************/
typedef enum _VDM_ENTRY_CODE
{
VdmEntryUndo,
VdmEntryUpdateProcess,
VdmEntryUpdateControlCHandler
} VDM_ENTRY_CODE;
//
// Undo States
//
#define VDM_UNDO_PARTIAL 0x01
#define VDM_UNDO_FULL 0x02
#define VDM_UNDO_REUSE 0x04
#define VDM_UNDO_COMPLETED 0x08
//
// Binary Types to share with VDM
//
#define BINARY_TYPE_EXE 0x01
#define BINARY_TYPE_COM 0x02
#define BINARY_TYPE_PIF 0x03
#define BINARY_TYPE_DOS 0x10
#define BINARY_TYPE_SEPARATE_WOW 0x20
#define BINARY_TYPE_WOW 0x40
#define BINARY_TYPE_WOW_EX 0x80
//
// VDM States
//
#define VDM_NOT_LOADED 0x01
#define VDM_NOT_READY 0x02
#define VDM_READY 0x04
/* FUNCTION PROTOTYPES ********************************************************/
BOOL
@ -87,7 +51,7 @@ BaseCheckForVDM(
OUT LPDWORD ExitCode
);
BOOL
NTSTATUS
WINAPI
BaseCheckVDM(
IN ULONG BinaryType,

View file

@ -46,6 +46,7 @@
#include <win/basemsg.h>
#include <win/console.h>
#include <win/conmsg.h>
#include <win/vdm.h>
/* DDK Driver Headers */
#include <mountmgr.h>

View file

@ -10,7 +10,7 @@
* Samuel Serapión
*/
/* synched with wine 1.1.26 */
/* Partly synched with Wine 1.7.17 */
#include <k32.h>
@ -178,11 +178,15 @@ BOOL WINAPI FindActCtxSectionGuid(DWORD dwFlags, const GUID* lpExtGuid,
ULONG ulId, const GUID* lpSearchGuid,
PACTCTX_SECTION_KEYED_DATA pInfo)
{
FIXME("%08x %s %u %s %p\n", dwFlags, debugstr_guid(lpExtGuid),
ulId, debugstr_guid(lpSearchGuid), pInfo);
SetLastError( ERROR_CALL_NOT_IMPLEMENTED);
NTSTATUS status;
if ((status = RtlFindActivationContextSectionGuid(dwFlags, lpExtGuid, ulId, lpSearchGuid, pInfo)))
{
SetLastError(RtlNtStatusToDosError(status));
return FALSE;
}
return TRUE;
}
/* EOF */

View file

@ -480,8 +480,8 @@ SockReenableAsyncSelectEvent (
typedef VOID (*PASYNC_COMPLETION_ROUTINE)(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock);
DWORD
FORCEINLINE
DWORD
MsafdReturnWithErrno(NTSTATUS Status,
LPINT Errno,
DWORD Received,

View file

@ -25,12 +25,12 @@
struct NBCmdQueue;
/* Allocates a new command queue from heap. */
struct NBCmdQueue *NBCmdQueueCreate(HANDLE heap);
struct NBCmdQueue *NBCmdQueueCreate(HANDLE heap) DECLSPEC_HIDDEN;
/* Adds ncb to queue. Assumes queue is not NULL, and ncb is not already in the
* queue. If ncb is already in the queue, returns NRC_TOOMANY.
*/
UCHAR NBCmdQueueAdd(struct NBCmdQueue *queue, PNCB ncb);
UCHAR NBCmdQueueAdd(struct NBCmdQueue *queue, PNCB ncb) DECLSPEC_HIDDEN;
/* Cancels the given ncb. Blocks until the command completes. Implicitly
* removes ncb from the queue. Assumes queue and ncb are not NULL, and that
@ -39,23 +39,23 @@ UCHAR NBCmdQueueAdd(struct NBCmdQueue *queue, PNCB ncb);
* completed before it could be cancelled, and various other return values for
* different failures.
*/
UCHAR NBCmdQueueCancel(struct NBCmdQueue *queue, PNCB ncb);
UCHAR NBCmdQueueCancel(struct NBCmdQueue *queue, PNCB ncb) DECLSPEC_HIDDEN;
/* Sets the return code of the given ncb, and implicitly removes the command
* from the queue. Assumes queue and ncb are not NULL, and that ncb has been
* added to queue previously.
* Returns NRC_GOODRET on success.
*/
UCHAR NBCmdQueueComplete(struct NBCmdQueue *queue, PNCB ncb, UCHAR retcode);
UCHAR NBCmdQueueComplete(struct NBCmdQueue *queue, PNCB ncb, UCHAR retcode) DECLSPEC_HIDDEN;
/* Cancels all pending commands in the queue (useful for a RESET or a shutdown).
* Returns when all commands have been completed.
*/
UCHAR NBCmdQueueCancelAll(struct NBCmdQueue *queue);
UCHAR NBCmdQueueCancelAll(struct NBCmdQueue *queue) DECLSPEC_HIDDEN;
/* Frees all memory associated with the queue. Blocks until all commands
* pending in the queue have been completed.
*/
void NBCmdQueueDestroy(struct NBCmdQueue *queue);
void NBCmdQueueDestroy(struct NBCmdQueue *queue) DECLSPEC_HIDDEN;
#endif /* __NBCMDQUEUE_H__ */

View file

@ -45,7 +45,7 @@ typedef struct _NBNameCacheEntry
/* Allocates a new name cache from heap, and sets the expire time on new
* entries to entryExpireTimeMS after a cache entry is added.
*/
struct NBNameCache *NBNameCacheCreate(HANDLE heap, DWORD entryExpireTimeMS);
struct NBNameCache *NBNameCacheCreate(HANDLE heap, DWORD entryExpireTimeMS) DECLSPEC_HIDDEN;
/* Adds an entry to the cache. The entry is assumed to have been allocated
* from the same heap as the name cache; the name cache will own the entry
@ -54,14 +54,14 @@ struct NBNameCache *NBNameCacheCreate(HANDLE heap, DWORD entryExpireTimeMS);
* same name was in the cache, the entry is replaced. Returns TRUE on success
* or FALSE on failure.
*/
BOOL NBNameCacheAddEntry(struct NBNameCache *cache, NBNameCacheEntry *entry);
BOOL NBNameCacheAddEntry(struct NBNameCache *cache, NBNameCacheEntry *entry) DECLSPEC_HIDDEN;
/* Finds the entry with name name in the cache and returns a pointer to it, or
* NULL if it isn't found.
*/
const NBNameCacheEntry *NBNameCacheFindEntry(struct NBNameCache *cache,
const UCHAR name[NCBNAMSZ]);
const UCHAR name[NCBNAMSZ]) DECLSPEC_HIDDEN;
void NBNameCacheDestroy(struct NBNameCache *cache);
void NBNameCacheDestroy(struct NBNameCache *cache) DECLSPEC_HIDDEN;
#endif /* ndef __WINE_NBNAMECACHE_H */

View file

@ -289,7 +289,7 @@ static UCHAR NetBTWaitForNameResponse(const NetBTAdapter *adapter, SOCKET fd,
if (fd == INVALID_SOCKET) return NRC_BADDR;
if (!answerCallback) return NRC_BADDR;
while (!found && ret == NRC_GOODRET && (now = GetTickCount()) < waitUntil)
while (!found && ret == NRC_GOODRET && (int)((now = GetTickCount()) - waitUntil) < 0)
{
DWORD msToWait = waitUntil - now;
struct fd_set fds;
@ -399,9 +399,8 @@ static BOOL NetBTFindNameAnswerCallback(void *pVoid, WORD answerCount,
{
if (queryData->cacheEntry == NULL)
{
queryData->cacheEntry = HeapAlloc(
GetProcessHeap(), 0, sizeof(NBNameCacheEntry) +
(answerCount - 1) * sizeof(DWORD));
queryData->cacheEntry = HeapAlloc(GetProcessHeap(), 0,
FIELD_OFFSET(NBNameCacheEntry, addresses[answerCount]));
if (queryData->cacheEntry)
queryData->cacheEntry->numAddresses = 0;
else
@ -533,8 +532,8 @@ static UCHAR NetBTinetResolve(const UCHAR name[NCBNAMSZ],
if (addr != INADDR_NONE)
{
*cacheEntry = HeapAlloc(GetProcessHeap(),
0, sizeof(NBNameCacheEntry));
*cacheEntry = HeapAlloc(GetProcessHeap(), 0,
FIELD_OFFSET(NBNameCacheEntry, addresses[1]));
if (*cacheEntry)
{
memcpy((*cacheEntry)->name, name, NCBNAMSZ);
@ -558,9 +557,8 @@ static UCHAR NetBTinetResolve(const UCHAR name[NCBNAMSZ],
;
if (host->h_addr_list && host->h_addr_list[0])
{
*cacheEntry = HeapAlloc(
GetProcessHeap(), 0, sizeof(NBNameCacheEntry) +
(i - 1) * sizeof(DWORD));
*cacheEntry = HeapAlloc(GetProcessHeap(), 0,
FIELD_OFFSET(NBNameCacheEntry, addresses[i]));
if (*cacheEntry)
{
memcpy((*cacheEntry)->name, name, NCBNAMSZ);
@ -569,7 +567,7 @@ static UCHAR NetBTinetResolve(const UCHAR name[NCBNAMSZ],
(*cacheEntry)->numAddresses = i;
for (i = 0; i < (*cacheEntry)->numAddresses; i++)
(*cacheEntry)->addresses[i] =
(DWORD)host->h_addr_list[i];
*(DWORD*)host->h_addr_list[i];
}
else
ret = NRC_OSRESNOTAV;
@ -995,7 +993,7 @@ static UCHAR NetBTCall(void *adapt, PNCB ncb, void **sess)
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
sizeof(timeout));
}
if (ncb->ncb_rto > 0)
if (ncb->ncb_sto > 0)
{
timeout = ncb->ncb_sto * 500;
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout,
@ -1489,13 +1487,17 @@ void NetBTInit(void)
NetBTNameEncode */
char *ptr, *lenPtr;
for (ptr = gScopeID + 1; ptr - gScopeID < sizeof(gScopeID) && *ptr; )
for (ptr = gScopeID + 1, lenPtr = gScopeID; ptr - gScopeID < sizeof(gScopeID) && *ptr; ++ptr)
{
for (lenPtr = ptr - 1, *lenPtr = 0;
ptr - gScopeID < sizeof(gScopeID) && *ptr && *ptr != '.';
ptr++)
*lenPtr += 1;
ptr++;
if (*ptr == '.')
{
lenPtr = ptr;
*lenPtr = 0;
}
else
{
++*lenPtr;
}
}
}
if (RegQueryValueExW(hKey, CacheTimeoutW, NULL, NULL,

View file

@ -20,9 +20,7 @@
#include <lmserver.h>
WINE_DEFAULT_DEBUG_CHANNEL(netbios);
static HMODULE NETAPI32_hModule;
WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
@ -30,19 +28,15 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
{
DisableThreadLibraryCalls(hinstDLL);
NETAPI32_hModule = hinstDLL;
NetBIOSInit();
NetBTInit();
break;
}
case DLL_PROCESS_DETACH:
{
if (lpvReserved) break;
NetBIOSShutdown();
break;
}
}
return TRUE;
}
@ -83,9 +77,27 @@ NET_API_STATUS WINAPI NetServerEnumEx(
LMCSTR domain,
LMCSTR FirstNameToReturn)
{
FIXME("Stub (%s %d %p %d %p %p %d %s %p)\n", debugstr_w(ServerName),
Level, Bufptr, PrefMaxlen, EntriesRead, totalentries, servertype,
debugstr_w(domain), debugstr_w(FirstNameToReturn));
FIXME("Stub (%s %d %p %d %p %p %d %s %s)\n",
debugstr_w(ServerName), Level, Bufptr, PrefMaxlen, EntriesRead, totalentries,
servertype, debugstr_w(domain), debugstr_w(FirstNameToReturn));
return ERROR_NO_BROWSER_SERVERS_FOUND;
}
/************************************************************
* NetServerDiskEnum (NETAPI32.@)
*/
NET_API_STATUS WINAPI NetServerDiskEnum(
LMSTR ServerName,
DWORD Level,
LPBYTE *Bufptr,
DWORD PrefMaxlen,
LPDWORD EntriesRead,
LPDWORD totalentries,
LPDWORD Resume_Handle)
{
FIXME("Stub (%s %d %p %d %p %p %p)\n", debugstr_w(ServerName),
Level, Bufptr, PrefMaxlen, EntriesRead, totalentries, Resume_Handle);
return ERROR_NO_BROWSER_SERVERS_FOUND;
}
@ -162,51 +174,6 @@ NET_API_STATUS WINAPI NetStatisticsGet(LMSTR server, LMSTR service,
return NERR_InternalError;
}
DWORD WINAPI NetpNetBiosStatusToApiStatus(DWORD nrc)
{
DWORD ret;
switch (nrc)
{
case NRC_GOODRET:
ret = NO_ERROR;
break;
case NRC_NORES:
ret = NERR_NoNetworkResource;
break;
case NRC_DUPNAME:
ret = NERR_AlreadyExists;
break;
case NRC_NAMTFUL:
ret = NERR_TooManyNames;
break;
case NRC_ACTSES:
ret = NERR_DeleteLater;
break;
case NRC_REMTFUL:
ret = ERROR_REM_NOT_LIST;
break;
case NRC_NOCALL:
ret = NERR_NameNotFound;
break;
case NRC_NOWILD:
ret = ERROR_INVALID_PARAMETER;
break;
case NRC_INUSE:
ret = NERR_DuplicateName;
break;
case NRC_NAMERR:
ret = ERROR_INVALID_PARAMETER;
break;
case NRC_NAMCONF:
ret = NERR_DuplicateName;
break;
default:
ret = NERR_NetworkError;
}
return ret;
}
NET_API_STATUS
WINAPI
NetpNtStatusToApiStatus(NTSTATUS Status)
@ -242,3 +209,31 @@ NET_API_STATUS WINAPI NetUseEnum(LMSTR server, DWORD level, LPBYTE* bufptr, DWOR
entriesread, totalentries, resumehandle);
return ERROR_NOT_SUPPORTED;
}
NET_API_STATUS WINAPI NetScheduleJobAdd(LPCWSTR server, LPBYTE bufptr, LPDWORD jobid)
{
FIXME("stub (%s, %p, %p)\n", debugstr_w(server), bufptr, jobid);
return NERR_Success;
}
NET_API_STATUS WINAPI NetScheduleJobDel(LPCWSTR server, DWORD minjobid, DWORD maxjobid)
{
FIXME("stub (%s, %d, %d)\n", debugstr_w(server), minjobid, maxjobid);
return NERR_Success;
}
NET_API_STATUS WINAPI NetScheduleJobEnum(LPCWSTR server, LPBYTE* bufptr, DWORD prefmaxsize, LPDWORD entriesread,
LPDWORD totalentries, LPDWORD resumehandle)
{
FIXME("stub (%s, %p, %d, %p, %p, %p)\n", debugstr_w(server), bufptr, prefmaxsize, entriesread, totalentries, resumehandle);
*entriesread = 0;
*totalentries = 0;
return NERR_Success;
}
NET_API_STATUS WINAPI NetUseGetInfo(LMSTR server, LMSTR name, DWORD level, LPBYTE *bufptr)
{
FIXME("stub (%p, %p, %d, %p)\n", server, name, level, bufptr);
return ERROR_NOT_SUPPORTED;
}

View file

@ -19,6 +19,7 @@
#include <iphlpapi.h>
#include <wine/debug.h>
#include <wine/unicode.h>
#define NTOS_MODE_USER
#include <ndk/rtlfuncs.h>

View file

@ -201,13 +201,13 @@
@ stub NetReplImportDirLock
@ stub NetReplImportDirUnlock
@ stub NetReplSetInfo
@ stub NetScheduleJobAdd
@ stub NetScheduleJobDel
@ stub NetScheduleJobEnum
@ stdcall NetScheduleJobAdd(wstr ptr ptr)
@ stdcall NetScheduleJobDel(wstr long long)
@ stdcall NetScheduleJobEnum(wstr ptr long ptr ptr ptr)
@ stub NetScheduleJobGetInfo
@ stub NetServerComputerNameAdd
@ stub NetServerComputerNameDel
@ stub NetServerDiskEnum
@ stdcall NetServerDiskEnum(wstr long ptr long ptr ptr ptr)
@ stdcall NetServerEnum(wstr long ptr long ptr ptr long wstr ptr)
@ stdcall NetServerEnumEx(wstr long ptr long ptr ptr long wstr wstr)
@ stdcall NetServerGetInfo(wstr long ptr)
@ -238,7 +238,7 @@
@ stdcall NetUseAdd(wstr long ptr ptr)
@ stub NetUseDel
@ stdcall NetUseEnum(wstr long ptr long ptr ptr ptr)
@ stub NetUseGetInfo
@ stdcall NetUseGetInfo(ptr ptr long ptr)
@ stdcall NetUserAdd(wstr long ptr ptr)
@ stdcall NetUserChangePassword(wstr wstr wstr wstr)
@ stdcall NetUserDel(wstr wstr)

View file

@ -49,7 +49,7 @@ typedef struct _NetBIOSSession
* is not NULL, the adapter is considered valid. (transport is a pointer to
* an entry in a NetBIOSTransportTableEntry.) data has data for the callers of
* NetBIOSEnumAdapters to be able to see. The lana is repeated there, even
* though I don't use it internally--it's for transports to use reenabling
* though I don't use it internally--it's for transports to use re-enabling
* adapters using NetBIOSEnableAdapter.
*/
typedef struct _NetBIOSAdapter
@ -858,3 +858,48 @@ UCHAR WINAPI Netbios(PNCB ncb)
TRACE("returning 0x%02x\n", ret);
return ret;
}
DWORD WINAPI NetpNetBiosStatusToApiStatus(DWORD nrc)
{
DWORD ret;
switch (nrc)
{
case NRC_GOODRET:
ret = NO_ERROR;
break;
case NRC_NORES:
ret = NERR_NoNetworkResource;
break;
case NRC_DUPNAME:
ret = NERR_AlreadyExists;
break;
case NRC_NAMTFUL:
ret = NERR_TooManyNames;
break;
case NRC_ACTSES:
ret = NERR_DeleteLater;
break;
case NRC_REMTFUL:
ret = ERROR_REM_NOT_LIST;
break;
case NRC_NOCALL:
ret = NERR_NameNotFound;
break;
case NRC_NOWILD:
ret = ERROR_INVALID_PARAMETER;
break;
case NRC_INUSE:
ret = NERR_DuplicateName;
break;
case NRC_NAMERR:
ret = ERROR_INVALID_PARAMETER;
break;
case NRC_NAMCONF:
ret = NERR_DuplicateName;
break;
default:
ret = NERR_NetworkError;
}
return ret;
}

View file

@ -26,8 +26,8 @@
* Public functions
*/
void NetBIOSInit(void);
void NetBIOSShutdown(void);
void NetBIOSInit(void) DECLSPEC_HIDDEN;
void NetBIOSShutdown(void) DECLSPEC_HIDDEN;
struct _NetBIOSTransport;
@ -35,7 +35,7 @@ struct _NetBIOSTransport;
* a unique id (the transport_id of ACTION_HEADER, for example) and an
* implementation. Returns TRUE on success, and FALSE on failure.
*/
BOOL NetBIOSRegisterTransport(ULONG id, struct _NetBIOSTransport *transport);
BOOL NetBIOSRegisterTransport(ULONG id, struct _NetBIOSTransport *transport) DECLSPEC_HIDDEN;
/* Registers an adapter with the given transport and ifIndex with NetBIOS.
* ifIndex is an interface index usable by the IpHlpApi. ifIndex is not
@ -45,21 +45,21 @@ BOOL NetBIOSRegisterTransport(ULONG id, struct _NetBIOSTransport *transport);
* FIXME: need functions for retrieving the name and hardware index, rather
* than assuming a correlation with IpHlpApi.
*/
BOOL NetBIOSRegisterAdapter(ULONG transport, DWORD ifIndex, void *adapter);
BOOL NetBIOSRegisterAdapter(ULONG transport, DWORD ifIndex, void *adapter) DECLSPEC_HIDDEN;
/* During enumeration, all adapters from your transport are disabled
* internally. If an adapter is still valid, reenable it with this function.
* internally. If an adapter is still valid, re-enable it with this function.
* Adapters you don't enable will have their transport's NetBIOSCleanupAdapter
* function (see below) called on them, and will be removed from the table.
* (This is to deal with lack of plug-and-play--sorry.)
*/
void NetBIOSEnableAdapter(UCHAR lana);
void NetBIOSEnableAdapter(UCHAR lana) DECLSPEC_HIDDEN;
/* Gets a quick count of the number of NetBIOS adapters. Not guaranteed not
* to change from one call to the next, depending on what's been enumerated
* lately. See also NetBIOSEnumAdapters.
*/
UCHAR NetBIOSNumAdapters(void);
UCHAR NetBIOSNumAdapters(void) DECLSPEC_HIDDEN;
typedef struct _NetBIOSAdapterImpl {
UCHAR lana;
@ -78,7 +78,7 @@ typedef BOOL (*NetBIOSEnumAdaptersCallback)(UCHAR totalLANAs, UCHAR lanaIndex,
* Your callback should return FALSE if it no longer wishes to be called.
*/
void NetBIOSEnumAdapters(ULONG transport, NetBIOSEnumAdaptersCallback cb,
void *closure);
void *closure) DECLSPEC_HIDDEN;
/* Hangs up the session identified in the NCB; the NCB need not be a NCBHANGUP.
* Will result in the transport's hangup function being called, so release any
@ -86,7 +86,7 @@ void NetBIOSEnumAdapters(ULONG transport, NetBIOSEnumAdaptersCallback cb,
* This function is intended for use by a transport, if the session is closed
* by some error in the transport layer.
*/
void NetBIOSHangupSession(const NCB *ncb);
void NetBIOSHangupSession(const NCB *ncb) DECLSPEC_HIDDEN;
/**
* Functions a transport implementation must implement
@ -172,6 +172,6 @@ typedef struct _NetBIOSTransport
/* Not defined by MS, so make my own private define: */
#define TRANSPORT_NBT "MNBT"
void NetBTInit(void);
void NetBTInit(void) DECLSPEC_HIDDEN;
#endif /* ndef __WINE_NETBIOS_H__ */

View file

@ -30,29 +30,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
*
* Checks whether the server name indicates local machine.
*/
BOOL NETAPI_IsLocalComputer(LMCSTR ServerName)
DECLSPEC_HIDDEN BOOL NETAPI_IsLocalComputer( LMCSTR name )
{
if (!ServerName)
{
return TRUE;
}
else if (ServerName[0] == '\0')
return TRUE;
else
{
DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
BOOL Result;
LPWSTR buf;
WCHAR buf[MAX_COMPUTERNAME_LENGTH + 1];
DWORD size = sizeof(buf) / sizeof(buf[0]);
BOOL ret;
NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &buf);
Result = GetComputerNameW(buf, &dwSize);
if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
ServerName += 2;
Result = Result && !lstrcmpW(ServerName, buf);
NetApiBufferFree(buf);
if (!name || !name[0]) return TRUE;
return Result;
}
ret = GetComputerNameW( buf, &size );
if (ret && name[0] == '\\' && name[1] == '\\') name += 2;
return ret && !strcmpiW( name, buf );
}
static void wprint_mac(WCHAR* buffer, int len, const MIB_IFROW *ifRow)

View file

@ -3515,7 +3515,7 @@ BOOL WINAPI PathRelativePathToW(LPWSTR lpszPath, LPCWSTR lpszFrom, DWORD dwAttrF
if(!(dwAttrFrom & FILE_ATTRIBUTE_DIRECTORY))
PathRemoveFileSpecW(szFrom);
if(!(dwAttrFrom & FILE_ATTRIBUTE_DIRECTORY))
if(!(dwAttrTo & FILE_ATTRIBUTE_DIRECTORY))
PathRemoveFileSpecW(szTo);
/* Paths can only be relative if they have a common root */

View file

@ -22,7 +22,7 @@ static INT SCROLL_TrackingBar = 0;
static INT SCROLL_TrackingPos = 0;
static INT SCROLL_TrackingVal = 0;
void static ScreenToWindow( HWND hWnd, POINT* pt)
static void ScreenToWindow( HWND hWnd, POINT* pt)
{
RECT rcWnd;
GetWindowRect(hWnd, &rcWnd);

View file

@ -45,8 +45,8 @@ typedef VLONG *PVLONG;
/* FUNCTIONS *****************************************************************/
VOID
static __inline
VOID
AcquireReadLock(IN PWAH_SEARCH_TABLE Table,
IN PVLONG *Count)
{
@ -70,8 +70,8 @@ AcquireReadLock(IN PWAH_SEARCH_TABLE Table,
} while (TRUE);
}
VOID
static __inline
VOID
ReleaseReadLock(IN PWAH_SEARCH_TABLE Table,
IN PVLONG Count)
{
@ -139,8 +139,8 @@ DoWaitForReaders(IN PWAH_SEARCH_TABLE Table,
}
}
VOID
static __inline
VOID
TryWaitForReaders(IN PWAH_SEARCH_TABLE Table)
{
PVLONG OldCount = Table->CurrentCount;

View file

@ -95,8 +95,8 @@ ReadWriteMode(UCHAR Mode)
}
VOID
FORCEINLINE
VOID
SetPixel(IN ULONG Left,
IN ULONG Top,
IN UCHAR Color)

View file

@ -15,8 +15,8 @@
PCHAR NmiBegin = "NMI4NMI@";
VOID
FORCEINLINE
VOID
NmiClearFlag(VOID)
{
((PCHAR)&KiBugCheckData[4])[0] -= (NmiBegin[3] | NmiBegin[7]);

View file

@ -351,8 +351,8 @@ NpReleaseVcb(VOID)
// Function to process deferred IRPs outside the VCB lock but still within the
// critical region
//
VOID
FORCEINLINE
VOID
NpCompleteDeferredIrps(IN PLIST_ENTRY DeferredList)
{
PLIST_ENTRY ThisEntry, NextEntry;

View file

@ -23,6 +23,10 @@ _Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
static DRIVER_DISPATCH i8042DeviceControl;
_Dispatch_type_(IRP_MJ_INTERNAL_DEVICE_CONTROL)
static DRIVER_DISPATCH i8042InternalDeviceControl;
_Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
static DRIVER_DISPATCH i8042SystemControl;
_Dispatch_type_(IRP_MJ_POWER)
static DRIVER_DISPATCH i8042Power;
DRIVER_INITIALIZE DriverEntry;
NTSTATUS NTAPI
@ -468,6 +472,27 @@ i8042InternalDeviceControl(
return Status;
}
static NTSTATUS NTAPI
i8042Power(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PFDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
PDEVICE_OBJECT LowerDevice = DeviceExtension->LowerDevice;
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(LowerDevice, Irp);
}
static NTSTATUS NTAPI
i8042SystemControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return ForwardIrpAndForget(DeviceObject, Irp);
}
NTSTATUS NTAPI
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
@ -531,6 +556,8 @@ DriverEntry(
DriverObject->MajorFunction[IRP_MJ_CLOSE] = i8042Close;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = i8042DeviceControl;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = i8042InternalDeviceControl;
DriverObject->MajorFunction[IRP_MJ_POWER] = i8042Power;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = i8042SystemControl;
DriverObject->MajorFunction[IRP_MJ_PNP] = i8042Pnp;
return STATUS_SUCCESS;

View file

@ -19,6 +19,7 @@
/* FUNCTIONS *****************************************************************/
static KDEFERRED_ROUTINE i8042MouDpcRoutine;
static KDEFERRED_ROUTINE i8042DpcRoutineMouseTimeout;
/*
* These functions are callbacks for filter driver custom interrupt
@ -346,7 +347,6 @@ i8042MouDpcRoutine(
* I'll just send the 'disable mouse port' command to the controller
* and say the mouse doesn't exist.
*/
static KDEFERRED_ROUTINE i8042DpcRoutineMouseTimeout;
static VOID NTAPI
i8042DpcRoutineMouseTimeout(
IN PKDPC Dpc,

View file

@ -479,7 +479,10 @@ StartProcedure(
/* Start the mouse */
Irql = KeAcquireInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt);
i8042IsrWritePort(DeviceExtension, MOU_CMD_RESET, CTRL_WRITE_MOUSE);
/* HACK: the mouse has already been reset in i8042DetectMouse. This second
reset prevents some touchpads/mice from working (Dell D531, D600).
See CORE-6901
i8042IsrWritePort(DeviceExtension, MOU_CMD_RESET, CTRL_WRITE_MOUSE); */
KeReleaseInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt, Irql);
}
@ -682,21 +685,8 @@ i8042Pnp(
{
case BusRelations:
{
PDEVICE_RELATIONS DeviceRelations;
TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
DeviceRelations = ExAllocatePoolWithTag(PagedPool,
sizeof(DEVICE_RELATIONS),
I8042PRT_TAG);
if (DeviceRelations)
{
DeviceRelations->Count = 0;
Information = (ULONG_PTR)DeviceRelations;
Status = STATUS_SUCCESS;
}
else
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
return ForwardIrpAndForget(DeviceObject, Irp);
}
case RemovalRelations:
{
@ -706,7 +696,6 @@ i8042Pnp(
default:
ERR_(I8042PRT, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
Stack->Parameters.QueryDeviceRelations.Type);
ASSERT(FALSE);
return ForwardIrpAndForget(DeviceObject, Irp);
}
break;
@ -714,17 +703,12 @@ i8042Pnp(
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* (optional) 0x0d */
{
TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
/* Nothing to do */
Status = Irp->IoStatus.Status;
break;
return ForwardIrpAndForget(DeviceObject, Irp);
}
case IRP_MN_QUERY_PNP_DEVICE_STATE: /* 0x14 */
{
TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
/* Nothing much to tell */
Information = 0;
Status = STATUS_SUCCESS;
break;
return ForwardIrpAndForget(DeviceObject, Irp);
}
default:
{

View file

@ -89,8 +89,8 @@ HalVectorToIRQL[16] =
/* PRIVATE FUNCTIONS **********************************************************/
ULONG
FORCEINLINE
ULONG
IOApicRead(UCHAR Register)
{
/* Select the register, then do the read */
@ -98,8 +98,8 @@ IOApicRead(UCHAR Register)
return *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN);
}
VOID
FORCEINLINE
VOID
IOApicWrite(UCHAR Register, ULONG Value)
{
/* Select the register, then do the write */
@ -107,8 +107,8 @@ IOApicWrite(UCHAR Register, ULONG Value)
*(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN) = Value;
}
VOID
FORCEINLINE
VOID
ApicWriteIORedirectionEntry(
UCHAR Index,
IOAPIC_REDIRECTION_REGISTER ReDirReg)
@ -117,8 +117,8 @@ ApicWriteIORedirectionEntry(
IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1);
}
IOAPIC_REDIRECTION_REGISTER
FORCEINLINE
IOAPIC_REDIRECTION_REGISTER
ApicReadIORedirectionEntry(
UCHAR Index)
{
@ -130,8 +130,8 @@ ApicReadIORedirectionEntry(
return ReDirReg;
}
VOID
FORCEINLINE
VOID
ApicRequestInterrupt(IN UCHAR Vector, UCHAR TriggerMode)
{
APIC_COMMAND_REGISTER CommandRegister;
@ -147,24 +147,24 @@ ApicRequestInterrupt(IN UCHAR Vector, UCHAR TriggerMode)
ApicWrite(APIC_ICR0, CommandRegister.Long0);
}
VOID
FORCEINLINE
VOID
ApicSendEOI(void)
{
//ApicWrite(APIC_EOI, 0);
HackEoi();
}
KIRQL
FORCEINLINE
KIRQL
ApicGetProcessorIrql(VOID)
{
/* Read the TPR and convert it to an IRQL */
return TprToIrql(ApicRead(APIC_PPR));
}
KIRQL
FORCEINLINE
KIRQL
ApicGetCurrentIrql(VOID)
{
#ifdef _M_AMD64
@ -184,8 +184,8 @@ ApicGetCurrentIrql(VOID)
#endif
}
VOID
FORCEINLINE
VOID
ApicSetIrql(KIRQL Irql)
{
#ifdef _M_AMD64
@ -200,8 +200,8 @@ ApicSetIrql(KIRQL Irql)
#define ApicRaiseIrql ApicSetIrql
#ifdef APIC_LAZY_IRQL
VOID
FORCEINLINE
VOID
ApicLowerIrql(KIRQL Irql)
{
__writefsbyte(FIELD_OFFSET(KPCR, Irql), Irql);

View file

@ -258,15 +258,15 @@ typedef union _IOAPIC_REDIRECTION_REGISTER
};
} IOAPIC_REDIRECTION_REGISTER;
ULONG
FORCEINLINE
ULONG
ApicRead(ULONG Offset)
{
return *(volatile ULONG *)(APIC_BASE + Offset);
}
VOID
FORCEINLINE
VOID
ApicWrite(ULONG Offset, ULONG Value)
{
*(volatile ULONG *)(APIC_BASE + Offset) = Value;

View file

@ -25,8 +25,8 @@ static UCHAR RtcMinimumClockRate = 6; /* Minimum rate 6: 16 Hz / 62.5 ms */
static UCHAR RtcMaximumClockRate = 10; /* Maximum rate 10: 256 Hz / 3.9 ms */
ULONG
FORCEINLINE
ULONG
RtcClockRateToIncrement(UCHAR Rate)
{
ULONG Freqency = ((32768 << 1) >> Rate);

View file

@ -782,8 +782,8 @@ HalpEndSoftwareInterrupt(IN KIRQL OldIrql,
/* EDGE INTERRUPT DISMISSAL FUNCTIONS *****************************************/
BOOLEAN
FORCEINLINE
BOOLEAN
_HalpDismissIrqGeneric(IN KIRQL Irql,
IN ULONG Irq,
OUT PKIRQL OldIrql)
@ -925,8 +925,8 @@ HalpDismissIrq07(IN KIRQL Irql,
/* LEVEL INTERRUPT DISMISSAL FUNCTIONS ****************************************/
BOOLEAN
FORCEINLINE
BOOLEAN
_HalpDismissIrqLevel(IN KIRQL Irql,
IN ULONG Irq,
OUT PKIRQL OldIrql)
@ -1248,8 +1248,8 @@ HalEndSystemInterrupt(IN KIRQL OldIrql,
/* SOFTWARE INTERRUPT TRAPS ***************************************************/
VOID
FORCEINLINE
VOID
DECLSPEC_NORETURN
_HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)
{
@ -1304,8 +1304,8 @@ HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)
_HalpApcInterruptHandler(TrapFrame);
}
KIRQL
FORCEINLINE
KIRQL
_HalpDispatchInterruptHandler(VOID)
{
KIRQL CurrentIrql;

51
include/ddk/isvbop.h Normal file
View file

@ -0,0 +1,51 @@
/*
* isvbop.h
*
* Windows NT Device Driver Kit
*
* This file is part of the ReactOS DDK package.
*
* Contributors:
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* This source code is offered for use in the public domain. You may
* use, modify or distribute it freely.
*
* This code is distributed in the hope that it will be useful but
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
* DISCLAIMED. This includes but is not limited to warranties of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
/*
* The corresponding ASM header of this file is isvbop.inc.
*/
#pragma once
/* BOP Identifiers */
#define BOP_3RDPARTY 0x58 // 3rd-party VDD BOP
#define BOP_UNSIMULATE 0xFE // Stop execution
#if defined(__GNUC__)
#define RegisterModule() __asm__(".byte 0xC4, 0xC4, %c0, 0" : : "i"(BOP_3RDPARTY))
#define UnRegisterModule() __asm__(".byte 0xC4, 0xC4, %c0, 1" : : "i"(BOP_3RDPARTY))
#define DispatchCall() __asm__(".byte 0xC4, 0xC4, %c0, 2" : : "i"(BOP_3RDPARTY))
#define VDDUnSimulate16() __asm__(".byte 0xC4, 0xC4, %c0" : : "i"(BOP_UNSIMULATE))
#elif defined(_MSC_VER)
#define RegisterModule() _asm _emit 0xC4 _asm _emit 0xC4 _asm _emit BOP_3RDPARTY _asm _emit 0
#define UnRegisterModule() _asm _emit 0xC4 _asm _emit 0xC4 _asm _emit BOP_3RDPARTY _asm _emit 1
#define DispatchCall() _asm _emit 0xC4 _asm _emit 0xC4 _asm _emit BOP_3RDPARTY _asm _emit 2
#define VDDUnSimulate16() _asm _emit 0xC4 _asm _emit 0xC4 _asm _emit BOP_UNSIMULATE
#else
#error Unknown compiler for inline assembler
#endif
/* EOF */

49
include/ddk/isvbop.inc Normal file
View file

@ -0,0 +1,49 @@
/*
* isvbop.inc
*
* Windows NT Device Driver Kit
*
* This file is part of the ReactOS DDK package.
*
* Contributors:
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* This source code is offered for use in the public domain. You may
* use, modify or distribute it freely.
*
* This code is distributed in the hope that it will be useful but
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
* DISCLAIMED. This includes but is not limited to warranties of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
/*
* This is the corresponding ASM header for isvbop.h.
* Please refer to isvbop.h for information about these interfaces.
*/
#include <asm.inc>
BOP_3RDPARTY = HEX(58)
BOP_UNSIMULATE = HEX(FE)
MACRO(RegisterModule)
.byte HEX(C4), HEX(C4), BOP_3RDPARTY, 0
ENDM
MACRO(UnRegisterModule)
.byte HEX(C4), HEX(C4), BOP_3RDPARTY, 1
ENDM
MACRO(DispatchCall)
.byte HEX(C4), HEX(C4), BOP_3RDPARTY, 2
ENDM
MACRO(VDDUnSimulate16)
.byte HEX(C4), HEX(C4), BOP_UNSIMULATE
ENDM
/* EOF */

161
include/ddk/nt_vdd.h Normal file
View file

@ -0,0 +1,161 @@
/*
* nt_vdd.h
*
* Windows NT Device Driver Kit
*
* This file is part of the ReactOS DDK package.
*
* Contributors:
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* This source code is offered for use in the public domain. You may
* use, modify or distribute it freely.
*
* This code is distributed in the hope that it will be useful but
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
* DISCLAIMED. This includes but is not limited to warranties of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#pragma once
#define _NT_VDD
#ifdef __cplusplus
extern "C" {
#endif
/*
* VDM Control
*/
VOID
WINAPI
VDDSimulate16(VOID);
VOID
WINAPI
VDDTerminateVDM(VOID);
/*
* I/O Port services
*/
typedef VOID (*PFNVDD_INB) (WORD iport, PBYTE data);
typedef VOID (*PFNVDD_INW) (WORD iport, PWORD data);
typedef VOID (*PFNVDD_INSB) (WORD iport, PBYTE data, WORD count);
typedef VOID (*PFNVDD_INSW) (WORD iport, PWORD data, WORD count);
typedef VOID (*PFNVDD_OUTB) (WORD iport, BYTE data);
typedef VOID (*PFNVDD_OUTW) (WORD iport, WORD data);
typedef VOID (*PFNVDD_OUTSB) (WORD iport, PBYTE data, WORD count);
typedef VOID (*PFNVDD_OUTSW) (WORD iport, PWORD data, WORD count);
typedef struct _VDD_IO_HANDLERS
{
PFNVDD_INB inb_handler;
PFNVDD_INW inw_handler;
PFNVDD_INSB insb_handler;
PFNVDD_INSW insw_handler;
PFNVDD_OUTB outb_handler;
PFNVDD_OUTW outw_handler;
PFNVDD_OUTSB outsb_handler;
PFNVDD_OUTSW outsw_handler;
} VDD_IO_HANDLERS, *PVDD_IO_HANDLERS;
typedef struct _VDD_IO_PORTRANGE
{
WORD First;
WORD Last;
} VDD_IO_PORTRANGE, *PVDD_IO_PORTRANGE;
BOOL
WINAPI
VDDInstallIOHook
(
HANDLE hVdd,
WORD cPortRange,
PVDD_IO_PORTRANGE pPortRange,
PVDD_IO_HANDLERS IOhandler
);
VOID
WINAPI
VDDDeInstallIOHook
(
HANDLE hVdd,
WORD cPortRange,
PVDD_IO_PORTRANGE pPortRange
);
/*
* Memory services
*/
typedef enum
{
VDM_V86,
VDM_PM
} VDM_MODE;
#ifndef MSW_PE
#define MSW_PE 0x0001
#endif
#define getMODE() ((getMSW() & MSW_PE) ? VDM_PM : VDM_V86)
PBYTE
WINAPI
Sim32pGetVDMPointer
(
IN ULONG Address,
IN BOOLEAN ProtectedMode
);
PBYTE
WINAPI
MGetVdmPointer
(
IN ULONG Address,
IN ULONG Size,
IN BOOLEAN ProtectedMode
);
PVOID
WINAPI
VdmMapFlat
(
IN USHORT Segment,
IN ULONG Offset,
IN VDM_MODE Mode
);
BOOL
WINAPI
VdmFlushCache
(
IN USHORT Segment,
IN ULONG Offset,
IN ULONG Size,
IN VDM_MODE Mode
);
BOOL
WINAPI
VdmUnmapFlat
(
IN USHORT Segment,
IN ULONG Offset,
IN PVOID Buffer,
IN VDM_MODE Mode
);
#ifdef __cplusplus
}
#endif
/* EOF */

254
include/ddk/vddsvc.h Normal file
View file

@ -0,0 +1,254 @@
/*
* vddsvc.h
*
* Windows NT Device Driver Kit
*
* This file is part of the ReactOS DDK package.
*
* Contributors:
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* This source code is offered for use in the public domain. You may
* use, modify or distribute it freely.
*
* This code is distributed in the hope that it will be useful but
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
* DISCLAIMED. This includes but is not limited to warranties of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#pragma once
#ifndef _NT_VDD
#include <nt_vdd.h>
#endif
/*
* Interrupts services
*/
#define ICA_MASTER 0
#define ICA_SLAVE 1
VOID
WINAPI
call_ica_hw_interrupt
(
INT ms,
BYTE line,
INT count
);
#define VDDSimulateInterrupt(ms, line, count) \
call_ica_hw_interrupt((ms), (line), (count)) // Windows specifies a count of 1 ...
/*
* Registers manipulation
*/
PVOID WINAPI getIntelRegistersPointer(VOID);
#ifdef __i386__
ULONG WINAPI getEAX(VOID);
VOID WINAPI setEAX(ULONG);
USHORT WINAPI getAX(VOID);
VOID WINAPI setAX(USHORT);
UCHAR WINAPI getAH(VOID);
VOID WINAPI setAH(UCHAR);
UCHAR WINAPI getAL(VOID);
VOID WINAPI setAL(UCHAR);
ULONG WINAPI getEBX(VOID);
VOID WINAPI setEBX(ULONG);
USHORT WINAPI getBX(VOID);
VOID WINAPI setBX(USHORT);
UCHAR WINAPI getBH(VOID);
VOID WINAPI setBH(UCHAR);
UCHAR WINAPI getBL(VOID);
VOID WINAPI setBL(UCHAR);
ULONG WINAPI getECX(VOID);
VOID WINAPI setECX(ULONG);
USHORT WINAPI getCX(VOID);
VOID WINAPI setCX(USHORT);
UCHAR WINAPI getCH(VOID);
VOID WINAPI setCH(UCHAR);
UCHAR WINAPI getCL(VOID);
VOID WINAPI setCL(UCHAR);
ULONG WINAPI getEDX(VOID);
VOID WINAPI setEDX(ULONG);
USHORT WINAPI getDX(VOID);
VOID WINAPI setDX(USHORT);
UCHAR WINAPI getDH(VOID);
VOID WINAPI setDH(UCHAR);
UCHAR WINAPI getDL(VOID);
VOID WINAPI setDL(UCHAR);
ULONG WINAPI getESP(VOID);
VOID WINAPI setESP(ULONG);
USHORT WINAPI getSP(VOID);
VOID WINAPI setSP(USHORT);
ULONG WINAPI getEBP(VOID);
VOID WINAPI setEBP(ULONG);
USHORT WINAPI getBP(VOID);
VOID WINAPI setBP(USHORT);
ULONG WINAPI getESI(VOID);
VOID WINAPI setESI(ULONG);
USHORT WINAPI getSI(VOID);
VOID WINAPI setSI(USHORT);
ULONG WINAPI getEDI(VOID);
VOID WINAPI setEDI(ULONG);
USHORT WINAPI getDI(VOID);
VOID WINAPI setDI(USHORT);
ULONG WINAPI getEIP(VOID);
VOID WINAPI setEIP(ULONG);
USHORT WINAPI getIP(VOID);
VOID WINAPI setIP(USHORT);
USHORT WINAPI getCS(VOID);
VOID WINAPI setCS(USHORT);
USHORT WINAPI getSS(VOID);
VOID WINAPI setSS(USHORT);
USHORT WINAPI getDS(VOID);
VOID WINAPI setDS(USHORT);
USHORT WINAPI getES(VOID);
VOID WINAPI setES(USHORT);
USHORT WINAPI getFS(VOID);
VOID WINAPI setFS(USHORT);
USHORT WINAPI getGS(VOID);
VOID WINAPI setGS(USHORT);
ULONG WINAPI getCF(VOID);
VOID WINAPI setCF(ULONG);
ULONG WINAPI getPF(VOID);
VOID WINAPI setPF(ULONG);
ULONG WINAPI getAF(VOID);
VOID WINAPI setAF(ULONG);
ULONG WINAPI getZF(VOID);
VOID WINAPI setZF(ULONG);
ULONG WINAPI getSF(VOID);
VOID WINAPI setSF(ULONG);
ULONG WINAPI getIF(VOID);
VOID WINAPI setIF(ULONG);
ULONG WINAPI getDF(VOID);
VOID WINAPI setDF(ULONG);
ULONG WINAPI getOF(VOID);
VOID WINAPI setOF(ULONG);
ULONG WINAPI getEFLAGS(VOID);
VOID WINAPI setEFLAGS(ULONG);
USHORT WINAPI getMSW(VOID);
VOID WINAPI setMSW(USHORT);
#else
ULONG WINAPI c_getEAX(VOID);
VOID WINAPI c_setEAX(ULONG);
USHORT WINAPI c_getAX(VOID);
VOID WINAPI c_setAX(USHORT);
UCHAR WINAPI c_getAH(VOID);
VOID WINAPI c_setAH(UCHAR);
UCHAR WINAPI c_getAL(VOID);
VOID WINAPI c_setAL(UCHAR);
ULONG WINAPI c_getEBX(VOID);
VOID WINAPI c_setEBX(ULONG);
USHORT WINAPI c_getBX(VOID);
VOID WINAPI c_setBX(USHORT);
UCHAR WINAPI c_getBH(VOID);
VOID WINAPI c_setBH(UCHAR);
UCHAR WINAPI c_getBL(VOID);
VOID WINAPI c_setBL(UCHAR);
ULONG WINAPI c_getECX(VOID);
VOID WINAPI c_setECX(ULONG);
USHORT WINAPI c_getCX(VOID);
VOID WINAPI c_setCX(USHORT);
UCHAR WINAPI c_getCH(VOID);
VOID WINAPI c_setCH(UCHAR);
UCHAR WINAPI c_getCL(VOID);
VOID WINAPI c_setCL(UCHAR);
ULONG WINAPI c_getEDX(VOID);
VOID WINAPI c_setEDX(ULONG);
USHORT WINAPI c_getDX(VOID);
VOID WINAPI c_setDX(USHORT);
UCHAR WINAPI c_getDH(VOID);
VOID WINAPI c_setDH(UCHAR);
UCHAR WINAPI c_getDL(VOID);
VOID WINAPI c_setDL(UCHAR);
ULONG WINAPI c_getESP(VOID);
VOID WINAPI c_setESP(ULONG);
USHORT WINAPI c_getSP(VOID);
VOID WINAPI c_setSP(USHORT);
ULONG WINAPI c_getEBP(VOID);
VOID WINAPI c_setEBP(ULONG);
USHORT WINAPI c_getBP(VOID);
VOID WINAPI c_setBP(USHORT);
ULONG WINAPI c_getESI(VOID);
VOID WINAPI c_setESI(ULONG);
USHORT WINAPI c_getSI(VOID);
VOID WINAPI c_setSI(USHORT);
ULONG WINAPI c_getEDI(VOID);
VOID WINAPI c_setEDI(ULONG);
USHORT WINAPI c_getDI(VOID);
VOID WINAPI c_setDI(USHORT);
ULONG WINAPI c_getEIP(VOID);
VOID WINAPI c_setEIP(ULONG);
USHORT WINAPI c_getIP(VOID);
VOID WINAPI c_setIP(USHORT);
USHORT WINAPI c_getCS(VOID);
VOID WINAPI c_setCS(USHORT);
USHORT WINAPI c_getSS(VOID);
VOID WINAPI c_setSS(USHORT);
USHORT WINAPI c_getDS(VOID);
VOID WINAPI c_setDS(USHORT);
USHORT WINAPI c_getES(VOID);
VOID WINAPI c_setES(USHORT);
USHORT WINAPI c_getFS(VOID);
VOID WINAPI c_setFS(USHORT);
USHORT WINAPI c_getGS(VOID);
VOID WINAPI c_setGS(USHORT);
ULONG WINAPI c_getCF(VOID);
VOID WINAPI c_setCF(ULONG);
ULONG WINAPI c_getPF(VOID);
VOID WINAPI c_setPF(ULONG);
ULONG WINAPI c_getAF(VOID);
VOID WINAPI c_setAF(ULONG);
ULONG WINAPI c_getZF(VOID);
VOID WINAPI c_setZF(ULONG);
ULONG WINAPI c_getSF(VOID);
VOID WINAPI c_setSF(ULONG);
ULONG WINAPI c_getIF(VOID);
VOID WINAPI c_setIF(ULONG);
ULONG WINAPI c_getDF(VOID);
VOID WINAPI c_setDF(ULONG);
ULONG WINAPI c_getOF(VOID);
VOID WINAPI c_setOF(ULONG);
USHORT WINAPI c_getMSW(VOID);
VOID WINAPI c_setMSW(USHORT);
#endif
/* EOF */

View file

@ -3654,7 +3654,7 @@ RtlFindActivationContextSectionString(
_In_ ULONG dwFlags,
_In_ const GUID *ExtensionGuid,
_In_ ULONG SectionType,
_In_ PUNICODE_STRING SectionName,
_In_ const UNICODE_STRING *SectionName,
_Inout_ PVOID ReturnedData
);
@ -4419,6 +4419,17 @@ RtlCloneMemoryStream(
#endif // NTOS_MODE_USER
NTSYSAPI
NTSTATUS
NTAPI
RtlFindActivationContextSectionGuid(
ULONG flags,
const GUID *extguid,
ULONG section_kind,
const GUID *guid,
void *ptr
);
#ifdef __cplusplus
}
#endif

View file

@ -5,30 +5,30 @@
#if 0
VOID
FORCEINLINE
VOID
KdRosDumpAllThreads(VOID)
{
KdSystemDebugControl(' soR', (PVOID)DumpAllThreads, 0, 0, 0, 0, 0);
}
VOID
FORCEINLINE
VOID
KdRosDumpUserThreads(VOID)
{
KdSystemDebugControl(' soR', (PVOID)DumpUserThreads, 0, 0, 0, 0, 0);
}
VOID
FORCEINLINE
VOID
KdRosDumpArmPfnDatabase(VOID)
{
KdSystemDebugControl(' soR', (PVOID)KdSpare3, 0, 0, 0, 0, 0);
}
#endif
VOID
FORCEINLINE
VOID
KdRosSetDebugCallback(
ULONG Id,
PVOID Callback)
@ -36,8 +36,8 @@ KdRosSetDebugCallback(
KdSystemDebugControl('CsoR', Callback, Id, 0, 0, 0, 0);
}
VOID
FORCEINLINE
VOID
KdRosDumpStackFrames(
ULONG Count,
PULONG_PTR Backtrace)
@ -46,16 +46,16 @@ KdRosDumpStackFrames(
}
#if KDBG
VOID
FORCEINLINE
VOID
KdRosRegisterCliCallback(
PVOID Callback)
{
KdSystemDebugControl('RbdK', Callback, FALSE, 0, 0, 0, 0);
}
VOID
FORCEINLINE
VOID
KdRosDeregisterCliCallback(
PVOID Callback)
{

View file

@ -0,0 +1,562 @@
/*
* Fast486 386/486 CPU Emulation Library
* fast486.h
*
* Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _FAST486_H_
#define _FAST486_H_
#pragma once
/* DEFINES ********************************************************************/
#ifndef FASTCALL
#define FASTCALL __fastcall
#endif
#define FAST486_NUM_GEN_REGS 8
#define FAST486_NUM_SEG_REGS 6
#define FAST486_NUM_CTRL_REGS 3
#define FAST486_NUM_DBG_REGS 6
#define FAST486_NUM_FPU_REGS 8
#define FAST486_CR0_PE (1 << 0)
#define FAST486_CR0_MP (1 << 1)
#define FAST486_CR0_EM (1 << 2)
#define FAST486_CR0_TS (1 << 3)
#define FAST486_CR0_ET (1 << 4)
#define FAST486_CR0_NE (1 << 5)
#define FAST486_CR0_WP (1 << 16)
#define FAST486_CR0_AM (1 << 18)
#define FAST486_CR0_NW (1 << 29)
#define FAST486_CR0_CD (1 << 30)
#define FAST486_CR0_PG (1 << 31)
#define FAST486_DR4_B0 (1 << 0)
#define FAST486_DR4_B1 (1 << 1)
#define FAST486_DR4_B2 (1 << 2)
#define FAST486_DR4_B3 (1 << 3)
#define FAST486_DR4_BD (1 << 13)
#define FAST486_DR4_BS (1 << 14)
#define FAST486_DR4_BT (1 << 15)
#define FAST486_DR5_L0 (1 << 0)
#define FAST486_DR5_G0 (1 << 1)
#define FAST486_DR5_L1 (1 << 2)
#define FAST486_DR5_G1 (1 << 3)
#define FAST486_DR5_L2 (1 << 4)
#define FAST486_DR5_G2 (1 << 5)
#define FAST486_DR5_L3 (1 << 6)
#define FAST486_DR5_G3 (1 << 7)
#define FAST486_DR5_LE (1 << 8)
#define FAST486_DR5_GE (1 << 9)
#define FAST486_DR5_GD (1 << 13)
#define FAST486_DBG_BREAK_EXEC 0
#define FAST486_DBG_BREAK_WRITE 1
#define FAST486_DBG_BREAK_READWRITE 3
#define FAST486_DR4_RESERVED 0xFFFF1FF0
#define FAST486_DR5_RESERVED 0x0000DC00
#define FAST486_IDT_TASK_GATE 0x5
#define FAST486_IDT_INT_GATE 0x6
#define FAST486_IDT_TRAP_GATE 0x7
#define FAST486_IDT_INT_GATE_32 0xE
#define FAST486_IDT_TRAP_GATE_32 0xF
#define FAST486_LDT_SIGNATURE 0x02
#define FAST486_TSS_SIGNATURE 0x09
#define FAST486_PREFIX_SEG (1 << 0)
#define FAST486_PREFIX_OPSIZE (1 << 1)
#define FAST486_PREFIX_ADSIZE (1 << 2)
#define FAST486_PREFIX_LOCK (1 << 3)
#define FAST486_PREFIX_REPNZ (1 << 4)
#define FAST486_PREFIX_REP (1 << 5)
struct _FAST486_STATE;
typedef struct _FAST486_STATE FAST486_STATE, *PFAST486_STATE;
typedef enum _FAST486_GEN_REGS
{
FAST486_REG_EAX,
FAST486_REG_ECX,
FAST486_REG_EDX,
FAST486_REG_EBX,
FAST486_REG_ESP,
FAST486_REG_EBP,
FAST486_REG_ESI,
FAST486_REG_EDI
} FAST486_GEN_REGS, *PFAST486_GEN_REGS;
typedef enum _FAST486_SEG_REGS
{
FAST486_REG_ES,
FAST486_REG_CS,
FAST486_REG_SS,
FAST486_REG_DS,
FAST486_REG_FS,
FAST486_REG_GS
} FAST486_SEG_REGS, *PFAST486_SEG_REGS;
typedef enum _FAST486_CTRL_REGS
{
FAST486_REG_CR0 = 0,
FAST486_REG_CR2 = 1,
FAST486_REG_CR3 = 2,
} FAST486_CTRL_REGS, *PFAST486_CTRL_REGS;
typedef enum _FAST486_DBG_REGS
{
FAST486_REG_DR0 = 0,
FAST486_REG_DR1 = 1,
FAST486_REG_DR2 = 2,
FAST486_REG_DR3 = 3,
FAST486_REG_DR4 = 4,
FAST486_REG_DR5 = 5,
FAST486_REG_DR6 = 4, // alias to DR4
FAST486_REG_DR7 = 5 // alias to DR5
} FAST486_DBG_REGS, *PFAST486_DBG_REGS;
typedef enum _FAST486_EXCEPTIONS
{
FAST486_EXCEPTION_DE = 0x00,
FAST486_EXCEPTION_DB = 0x01,
FAST486_EXCEPTION_BP = 0x03,
FAST486_EXCEPTION_OF = 0x04,
FAST486_EXCEPTION_BR = 0x05,
FAST486_EXCEPTION_UD = 0x06,
FAST486_EXCEPTION_NM = 0x07,
FAST486_EXCEPTION_DF = 0x08,
FAST486_EXCEPTION_TS = 0x0A,
FAST486_EXCEPTION_NP = 0x0B,
FAST486_EXCEPTION_SS = 0x0C,
FAST486_EXCEPTION_GP = 0x0D,
FAST486_EXCEPTION_PF = 0x0E,
FAST486_EXCEPTION_MF = 0x10,
FAST486_EXCEPTION_AC = 0x11,
FAST486_EXCEPTION_MC = 0x12
} FAST486_EXCEPTIONS, *PFAST486_EXCEPTIONS;
typedef enum _FAST486_INT_STATUS
{
FAST486_INT_NONE = 0,
FAST486_INT_EXECUTE = 1,
FAST486_INT_SIGNAL = 2
} FAST486_INT_STATUS, *PFAST486_INT_STATUS;
typedef
VOID
(NTAPI *FAST486_MEM_READ_PROC)
(
PFAST486_STATE State,
ULONG Address,
PVOID Buffer,
ULONG Size
);
typedef
VOID
(NTAPI *FAST486_MEM_WRITE_PROC)
(
PFAST486_STATE State,
ULONG Address,
PVOID Buffer,
ULONG Size
);
typedef
VOID
(NTAPI *FAST486_IO_READ_PROC)
(
PFAST486_STATE State,
ULONG Port,
PVOID Buffer,
ULONG DataCount,
UCHAR DataSize
);
typedef
VOID
(NTAPI *FAST486_IO_WRITE_PROC)
(
PFAST486_STATE State,
ULONG Port,
PVOID Buffer,
ULONG DataCount,
UCHAR DataSize
);
typedef
VOID
(NTAPI *FAST486_IDLE_PROC)
(
PFAST486_STATE State
);
typedef
VOID
(NTAPI *FAST486_BOP_PROC)
(
PFAST486_STATE State,
UCHAR BopCode
);
typedef
UCHAR
(NTAPI *FAST486_INT_ACK_PROC)
(
PFAST486_STATE State
);
typedef union _FAST486_REG
{
union
{
struct
{
UCHAR LowByte;
UCHAR HighByte;
};
USHORT LowWord;
};
ULONG Long;
} FAST486_REG, *PFAST486_REG;
typedef struct _FAST486_SEG_REG
{
USHORT Selector;
/* Descriptor cache */
ULONG Accessed : 1;
ULONG ReadWrite : 1;
ULONG DirConf : 1;
ULONG Executable : 1;
ULONG SystemType : 1;
ULONG Dpl : 2;
ULONG Present : 1;
ULONG Size : 1;
ULONG Limit;
ULONG Base;
} FAST486_SEG_REG, *PFAST486_SEG_REG;
typedef struct
{
USHORT Selector;
ULONG Base;
ULONG Limit;
} FAST486_LDT_REG;
typedef struct
{
USHORT Selector;
ULONG Base;
ULONG Limit;
BOOLEAN Busy;
} FAST486_TASK_REG, *PFAST486_TASK_REG;
#pragma pack(push, 1)
typedef struct
{
ULONG Limit : 16;
ULONG Base : 16;
ULONG BaseMid : 8;
ULONG Accessed : 1;
ULONG ReadWrite : 1;
ULONG DirConf : 1;
ULONG Executable : 1;
ULONG SystemType : 1;
ULONG Dpl : 2;
ULONG Present : 1;
ULONG LimitHigh : 4;
ULONG Avl : 1;
ULONG Reserved : 1;
ULONG Size : 1;
ULONG Granularity : 1;
ULONG BaseHigh : 8;
} FAST486_GDT_ENTRY, *PFAST486_GDT_ENTRY;
/* Verify the structure size */
C_ASSERT(sizeof(FAST486_GDT_ENTRY) == sizeof(ULONGLONG));
typedef struct
{
ULONG Limit : 16;
ULONG Base : 16;
ULONG BaseMid : 8;
ULONG Signature : 5;
ULONG Dpl : 2;
ULONG Present : 1;
ULONG LimitHigh : 4;
ULONG Avl : 1;
ULONG Reserved : 2;
ULONG Granularity : 1;
ULONG BaseHigh : 8;
} FAST486_SYSTEM_DESCRIPTOR, *PFAST486_SYSTEM_DESCRIPTOR;
/* Verify the structure size */
C_ASSERT(sizeof(FAST486_SYSTEM_DESCRIPTOR) == sizeof(ULONGLONG));
typedef struct
{
ULONG Offset : 16;
ULONG Selector : 16;
ULONG ParamCount : 5;
ULONG Reserved : 3;
ULONG Type : 4;
ULONG SystemType : 1;
ULONG Dpl : 2;
ULONG Present : 1;
ULONG OffsetHigh : 16;
} FAST486_CALL_GATE, *PFAST486_CALL_GATE;
/* Verify the structure size */
C_ASSERT(sizeof(FAST486_CALL_GATE) == sizeof(ULONGLONG));
typedef struct
{
ULONG Offset : 16;
ULONG Selector : 16;
ULONG Zero : 8;
ULONG Type : 4;
ULONG Storage : 1;
ULONG Dpl : 2;
ULONG Present : 1;
ULONG OffsetHigh : 16;
} FAST486_IDT_ENTRY, *PFAST486_IDT_ENTRY;
/* Verify the structure size */
C_ASSERT(sizeof(FAST486_IDT_ENTRY) == sizeof(ULONGLONG));
#pragma pack(pop)
typedef struct _FAST486_TABLE_REG
{
USHORT Size;
ULONG Address;
} FAST486_TABLE_REG, *PFAST486_TABLE_REG;
typedef union _FAST486_FLAGS_REG
{
USHORT LowWord;
ULONG Long;
struct
{
ULONG Cf : 1;
ULONG AlwaysSet : 1;
ULONG Pf : 1;
ULONG Reserved0 : 1;
ULONG Af : 1;
ULONG Reserved1 : 1;
ULONG Zf : 1;
ULONG Sf : 1;
ULONG Tf : 1;
ULONG If : 1;
ULONG Df : 1;
ULONG Of : 1;
ULONG Iopl : 2;
ULONG Nt : 1;
ULONG Reserved2 : 1;
ULONG Rf : 1;
ULONG Vm : 1;
ULONG Ac : 1;
// ULONG Reserved : 13;
};
} FAST486_FLAGS_REG, *PFAST486_FLAGS_REG;
typedef struct _FAST486_TSS
{
ULONG Link;
ULONG Esp0;
ULONG Ss0;
ULONG Esp1;
ULONG Ss1;
ULONG Esp2;
ULONG Ss2;
ULONG Cr3;
ULONG Eip;
ULONG Eflags;
ULONG Eax;
ULONG Ecx;
ULONG Edx;
ULONG Ebx;
ULONG Esp;
ULONG Ebp;
ULONG Esi;
ULONG Edi;
ULONG Es;
ULONG Cs;
ULONG Ss;
ULONG Ds;
ULONG Fs;
ULONG Gs;
ULONG Ldtr;
ULONG IopbOffset;
} FAST486_TSS, *PFAST486_TSS;
typedef struct _FAST486_FPU_DATA_REG
{
ULONGLONG Mantissa;
USHORT Exponent;
} FAST486_FPU_DATA_REG, *PFAST486_FPU_DATA_REG;
typedef union _FAST486_FPU_STATUS_REG
{
USHORT Value;
struct
{
ULONG Ie : 1;
ULONG De : 1;
ULONG Ze : 1;
ULONG Oe : 1;
ULONG Ue : 1;
ULONG Pe : 1;
ULONG Sf : 1;
ULONG Es : 1;
ULONG Code0 : 1;
ULONG Code1 : 1;
ULONG Code2 : 1;
ULONG Top : 3;
ULONG Code3 : 1;
ULONG Busy : 1;
};
} FAST486_FPU_STATUS_REG, *PFAST486_FPU_STATUS_REG;
typedef union _FAST486_FPU_CONTROL_REG
{
USHORT Value;
struct
{
ULONG Im : 1;
ULONG Dm : 1;
ULONG Zm : 1;
ULONG Om : 1;
ULONG Um : 1;
ULONG Pm : 1;
ULONG Reserved : 2;
ULONG Pc : 2;
ULONG Rc : 2;
ULONG Inf : 1;
// ULONG Reserved1 : 3;
};
} FAST486_FPU_CONTROL_REG, *PFAST486_FPU_CONTROL_REG;
struct _FAST486_STATE
{
FAST486_MEM_READ_PROC MemReadCallback;
FAST486_MEM_WRITE_PROC MemWriteCallback;
FAST486_IO_READ_PROC IoReadCallback;
FAST486_IO_WRITE_PROC IoWriteCallback;
FAST486_IDLE_PROC IdleCallback;
FAST486_BOP_PROC BopCallback;
FAST486_INT_ACK_PROC IntAckCallback;
FAST486_REG GeneralRegs[FAST486_NUM_GEN_REGS];
FAST486_SEG_REG SegmentRegs[FAST486_NUM_SEG_REGS];
FAST486_REG InstPtr, SavedInstPtr;
FAST486_FLAGS_REG Flags;
FAST486_TABLE_REG Gdtr, Idtr;
FAST486_LDT_REG Ldtr;
FAST486_TASK_REG TaskReg;
UCHAR Cpl;
ULONG ControlRegisters[FAST486_NUM_CTRL_REGS];
ULONG DebugRegisters[FAST486_NUM_DBG_REGS];
ULONG ExceptionCount;
ULONG PrefixFlags;
FAST486_SEG_REGS SegmentOverride;
FAST486_INT_STATUS IntStatus;
UCHAR PendingIntNum;
PULONG Tlb;
FAST486_FPU_DATA_REG FpuRegisters[FAST486_NUM_FPU_REGS];
FAST486_FPU_STATUS_REG FpuStatus;
FAST486_FPU_CONTROL_REG FpuControl;
USHORT FpuTag;
};
/* FUNCTIONS ******************************************************************/
VOID
NTAPI
Fast486Initialize(PFAST486_STATE State,
FAST486_MEM_READ_PROC MemReadCallback,
FAST486_MEM_WRITE_PROC MemWriteCallback,
FAST486_IO_READ_PROC IoReadCallback,
FAST486_IO_WRITE_PROC IoWriteCallback,
FAST486_IDLE_PROC IdleCallback,
FAST486_BOP_PROC BopCallback,
FAST486_INT_ACK_PROC IntAckCallback,
PULONG Tlb);
VOID
NTAPI
Fast486Reset(PFAST486_STATE State);
VOID
NTAPI
Fast486Continue(PFAST486_STATE State);
VOID
NTAPI
Fast486StepInto(PFAST486_STATE State);
VOID
NTAPI
Fast486StepOver(PFAST486_STATE State);
VOID
NTAPI
Fast486StepOut(PFAST486_STATE State);
VOID
NTAPI
Fast486DumpState(PFAST486_STATE State);
VOID
NTAPI
Fast486Interrupt(PFAST486_STATE State, UCHAR Number);
VOID
NTAPI
Fast486InterruptSignal(PFAST486_STATE State);
VOID
NTAPI
Fast486ExecuteAt(PFAST486_STATE State, USHORT Segment, ULONG Offset);
VOID
NTAPI
Fast486SetStack(PFAST486_STATE State, USHORT Segment, ULONG Offset);
VOID
NTAPI
Fast486SetSegment
(
PFAST486_STATE State,
FAST486_SEG_REGS Segment,
USHORT Selector
);
#endif // _FAST486_H_
/* EOF */

View file

@ -283,10 +283,13 @@ _SEH3$_AutoCleanup(
#define _SEH3$_DEFINE_FILTER_FUNC(_Name, expression) \
_SEH3$_NESTED_FUNC_OPEN(_Name) \
/* Declare the intrinsics for exception filters */ \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wshadow\"") \
inline __attribute__((always_inline, gnu_inline)) \
unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionPointers->ExceptionRecord->ExceptionCode; } \
inline __attribute__((always_inline, gnu_inline)) \
void * _exception_info() { return _SEH3$_TrylevelFrame.ExceptionPointers; } \
_Pragma("GCC diagnostic pop") \
\
/* Now handle the actual filter expression */ \
return (expression); \
@ -345,6 +348,9 @@ _SEH3$_AutoCleanup(
(void)&&_SEH3$_l_OnException; \
(void)&&_SEH3$_l_BeforeFilterOrFinally; \
(void)&&_SEH3$_l_FilterOrFinally; \
\
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
\
/* Count the try level. Outside of any __try, _SEH3$_TryLevel is 0 */ \
enum { \
@ -357,6 +363,8 @@ _SEH3$_AutoCleanup(
\
/* Allocate a registration frame */ \
volatile SEH3$_REGISTRATION_FRAME _SEH3$_AUTO_CLEANUP _SEH3$_TrylevelFrame; \
\
_Pragma("GCC diagnostic pop") \
\
goto _SEH3$_l_BeforeTry; \
/* Silence warning */ goto _SEH3$_l_AfterTry; \
@ -373,6 +381,9 @@ _SEH3$_AutoCleanup(
\
_SEH3$_l_BeforeTry: (void)0; \
_SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
\
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
\
/* Forward declaration of the filter function */ \
_SEH3$_DECLARE_FILTER_FUNC(_SEH3$_FilterFunction); \
@ -421,6 +432,9 @@ _SEH3$_AutoCleanup(
\
_SEH3$_l_BeforeTry: (void)0; \
_SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
\
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
\
/* Forward declaration of the finally function */ \
_SEH3$_DECLARE_FILTER_FUNC(_SEH3$_FinallyFunction); \
@ -458,6 +472,8 @@ _SEH3$_AutoCleanup(
\
/* Implementation of the auto cleanup function */ \
_SEH3$_DEFINE_CLEANUP_FUNC(_SEH3$_AutoCleanup); \
\
_Pragma("GCC diagnostic pop") \
\
/* Close the outer scope */ \
} while (0);

View file

@ -429,14 +429,14 @@ typedef struct
typedef struct
{
HANDLE ConsoleHandle;
HANDLE OutputHandle;
BOOL Unicode;
SMALL_RECT ScrollRectangle;
BOOL UseClipRectangle;
SMALL_RECT ClipRectangle;
BOOL UseClipRectangle;
COORD DestinationOrigin;
CHAR_INFO Fill;
BOOLEAN Unicode;
} CONSOLE_SCROLLSCREENBUFFER, *PCONSOLE_SCROLLSCREENBUFFER;
@ -674,20 +674,27 @@ typedef struct
typedef struct
{
DWORD Length;
DWORD ExeLength;
LPWSTR ExeName;
HANDLE ConsoleHandle;
USHORT ExeLength;
PVOID ExeName;
ULONG Length;
BOOLEAN Unicode;
BOOLEAN Unicode2;
} CONSOLE_GETALLALIASESLENGTH, *PCONSOLE_GETALLALIASESLENGTH;
typedef struct
{
DWORD Length;
LPWSTR ExeNames;
HANDLE ConsoleHandle;
ULONG Length ; // ExeLength; // ExesLength
PVOID ExeNames;
BOOLEAN Unicode;
} CONSOLE_GETALIASESEXES, *PCONSOLE_GETALIASESEXES;
typedef struct
{
DWORD Length;
HANDLE ConsoleHandle;
ULONG Length;
BOOLEAN Unicode;
} CONSOLE_GETALIASESEXESLENGTH, *PCONSOLE_GETALIASESEXESLENGTH;
@ -710,6 +717,13 @@ typedef struct
UNICODE_STRING ExeName;
} CONSOLE_EXPUNGECOMMANDHISTORY, *PCONSOLE_EXPUNGECOMMANDHISTORY;
typedef struct
{
UINT HistoryBufferSize;
UINT NumberOfHistoryBuffers;
DWORD dwFlags;
} CONSOLE_GETSETHISTORYINFO, *PCONSOLE_GETSETHISTORYINFO;
typedef struct
{
UNICODE_STRING ExeName;
@ -718,10 +732,9 @@ typedef struct
typedef struct
{
UINT HistoryBufferSize;
UINT NumberOfHistoryBuffers;
DWORD dwFlags;
} CONSOLE_GETSETHISTORYINFO, *PCONSOLE_GETSETHISTORYINFO;
HANDLE ConsoleHandle;
ULONG Mode;
} CONSOLE_SETHISTORYMODE, *PCONSOLE_SETHISTORYMODE;
@ -841,8 +854,9 @@ typedef struct _CONSOLE_API_MESSAGE
CONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest;
CONSOLE_GETCOMMANDHISTORYLENGTH GetCommandHistoryLengthRequest;
CONSOLE_EXPUNGECOMMANDHISTORY ExpungeCommandHistoryRequest;
CONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest;
CONSOLE_GETSETHISTORYINFO HistoryInfoRequest;
CONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest;
CONSOLE_SETHISTORYMODE SetHistoryModeRequest;
/* Input and Output Code Pages */
CONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest;

View file

@ -0,0 +1,117 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Base API Server DLL
* FILE: include/reactos/subsys/win/vdm.h
* PURPOSE: Public definitions for the Virtual Dos Machine
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
* Alex Ionescu (alex.ionescu@reactos.org)
*/
#ifndef _VDM_H
#define _VDM_H
#pragma once
/* CONSTANTS & TYPES **********************************************************/
typedef enum _VDM_ENTRY_CODE
{
VdmEntryUndo,
VdmEntryUpdateProcess,
VdmEntryUpdateControlCHandler
} VDM_ENTRY_CODE;
//
// Undo States
//
#define VDM_UNDO_PARTIAL 0x01
#define VDM_UNDO_FULL 0x02
#define VDM_UNDO_REUSE 0x04
#define VDM_UNDO_COMPLETED 0x08
//
// Binary Types to share with VDM
//
#define BINARY_TYPE_EXE 0x01
#define BINARY_TYPE_COM 0x02
#define BINARY_TYPE_PIF 0x03
#define BINARY_TYPE_DOS 0x10
#define BINARY_TYPE_SEPARATE_WOW 0x20
#define BINARY_TYPE_WOW 0x40
#define BINARY_TYPE_WOW_EX 0x80
//
// VDM States
//
#define VDM_NOT_LOADED 0x01
#define VDM_NOT_READY 0x02
#define VDM_READY 0x04
//
// VDM Flags
//
#define VDM_FLAG_FIRST_TASK 0x01
#define VDM_FLAG_WOW 0x02
#define VDM_FLAG_DOS 0x04
#define VDM_FLAG_RETRY 0x08
#define VDM_INC_REENTER_COUNT 0x10
#define VDM_DEC_REENTER_COUNT 0x20
#define VDM_FLAG_NESTED_TASK 0x40
#define VDM_FLAG_DONT_WAIT 0x80
#define VDM_GET_FIRST_COMMAND 0x100
#define VDM_GET_ENVIRONMENT 0x400
#define VDM_FLAG_SEPARATE_WOW 0x800
#define VDM_LIST_WOW_PROCESSES 0x1000
#define VDM_LIST_WOW_TASKS 0x4000
#define VDM_ADD_WOW_TASK 0x8000
typedef struct
{
ULONG TaskId;
ULONG CreationFlags;
ULONG ExitCode;
ULONG CodePage;
HANDLE StdIn;
HANDLE StdOut;
HANDLE StdErr;
LPSTR CmdLine;
LPSTR AppName;
LPSTR PifFile;
LPSTR CurDirectory;
LPSTR Env;
ULONG EnvLen;
STARTUPINFOA StartupInfo;
LPSTR Desktop;
ULONG DesktopLen;
LPSTR Title;
ULONG TitleLen;
LPVOID Reserved;
ULONG ReservedLen;
USHORT CmdLen;
USHORT AppLen;
USHORT PifLen;
USHORT CurDirectoryLen;
USHORT VDMState;
USHORT CurrentDrive;
BOOLEAN ComingFromBat;
} VDM_COMMAND_INFO, *PVDM_COMMAND_INFO;
/* FUNCTION PROTOTYPES ********************************************************/
BOOL
WINAPI
GetNextVDMCommand(
IN OUT PVDM_COMMAND_INFO CommandData OPTIONAL
);
VOID
WINAPI
ExitVDM(
IN BOOL IsWow,
IN ULONG iWowTask
);
#endif // _VDM_H
/* EOF */

View file

@ -343,9 +343,9 @@ extern int spawnvp(int mode, const char *cmdname, const char * const argv[]);
#if defined(_MSC_VER) || (defined(__i386__) && defined(__GNUC__) && !defined(WINE_PORT_NO_INTERLOCKED))
#define interlocked_cmpxchg InterlockedCompareExchange
#define interlocked_cmpxchg_ptr InterlockedCompareExchangePtr
#define interlocked_cmpxchg_ptr InterlockedCompareExchangePointer
#define interlocked_xchg InterlockedExchange
#define interlocked_xchg_ptr InterlockedExchangePtr
#define interlocked_xchg_ptr InterlockedExchangePointer
#define interlocked_xchg_add InterlockedExchangeAdd

View file

@ -11,6 +11,7 @@ add_subdirectory(cryptlib)
#add_subdirectory(dnslib) Nothing links to this lib.
add_subdirectory(drivers)
add_subdirectory(epsapi)
add_subdirectory(fast486)
add_subdirectory(fslib)
add_subdirectory(lsalib)
add_subdirectory(ppcmmu)

View file

@ -0,0 +1,12 @@
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/fast486)
list(APPEND SOURCE
fast486.c
opcodes.c
opgroups.c
extraops.c
common.c
fpu.c)
add_library(fast486 ${SOURCE})

339
lib/fast486/COPYING Normal file
View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

356
lib/fast486/common.c Normal file
View file

@ -0,0 +1,356 @@
/*
* Fast486 386/486 CPU Emulation Library
* common.c
*
* Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* INCLUDES *******************************************************************/
#include <windef.h>
// #define NDEBUG
#include <debug.h>
#include <fast486.h>
#include "common.h"
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN
Fast486ReadMemory(PFAST486_STATE State,
FAST486_SEG_REGS SegmentReg,
ULONG Offset,
BOOLEAN InstFetch,
PVOID Buffer,
ULONG Size)
{
ULONG LinearAddress;
PFAST486_SEG_REG CachedDescriptor;
ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
/* Get the cached descriptor */
CachedDescriptor = &State->SegmentRegs[SegmentReg];
if ((Offset + Size - 1) > CachedDescriptor->Limit)
{
/* Read beyond limit */
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
/* Check for protected mode */
if (State->ControlRegisters[0] & FAST486_CR0_PE)
{
/* Privilege checks */
if (!CachedDescriptor->Present)
{
Fast486Exception(State, FAST486_EXCEPTION_NP);
return FALSE;
}
if ((!InstFetch && (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl))
|| (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
{
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
if (InstFetch)
{
if (!CachedDescriptor->Executable)
{
/* Data segment not executable */
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
}
else
{
if (CachedDescriptor->Executable && (!CachedDescriptor->ReadWrite))
{
/* Code segment not readable */
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
}
}
/* Find the linear address */
LinearAddress = CachedDescriptor->Base + Offset;
/* Read from the linear address */
return Fast486ReadLinearMemory(State, LinearAddress, Buffer, Size);
}
BOOLEAN
Fast486WriteMemory(PFAST486_STATE State,
FAST486_SEG_REGS SegmentReg,
ULONG Offset,
PVOID Buffer,
ULONG Size)
{
ULONG LinearAddress;
PFAST486_SEG_REG CachedDescriptor;
ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
/* Get the cached descriptor */
CachedDescriptor = &State->SegmentRegs[SegmentReg];
if ((Offset + Size - 1) > CachedDescriptor->Limit)
{
/* Write beyond limit */
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
/* Check for protected mode */
if (State->ControlRegisters[0] & FAST486_CR0_PE)
{
/* Privilege checks */
if (!CachedDescriptor->Present)
{
Fast486Exception(State, FAST486_EXCEPTION_NP);
return FALSE;
}
if ((GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
|| (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
{
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
if (CachedDescriptor->Executable)
{
/* Code segment not writable */
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
else if (!CachedDescriptor->ReadWrite)
{
/* Data segment not writeable */
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
}
/* Find the linear address */
LinearAddress = CachedDescriptor->Base + Offset;
/* Write to the linear address */
return Fast486WriteLinearMemory(State, LinearAddress, Buffer, Size);
}
BOOLEAN
Fast486InterruptInternal(PFAST486_STATE State,
USHORT SegmentSelector,
ULONG Offset,
BOOLEAN InterruptGate)
{
/* Check for protected mode */
if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
{
FAST486_TSS Tss;
USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector;
ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long;
/* Check if the interrupt handler is more privileged */
if (Fast486GetCurrentPrivLevel(State) > GET_SEGMENT_RPL(SegmentSelector))
{
/* Read the TSS */
if (!Fast486ReadLinearMemory(State,
State->TaskReg.Base,
&Tss,
sizeof(Tss)))
{
/* Exception occurred */
return FALSE;
}
/* Check the new (higher) privilege level */
switch (GET_SEGMENT_RPL(SegmentSelector))
{
case 0:
{
if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss0))
{
/* Exception occurred */
return FALSE;
}
State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp0;
break;
}
case 1:
{
if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss1))
{
/* Exception occurred */
return FALSE;
}
State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp1;
break;
}
case 2:
{
if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss2))
{
/* Exception occurred */
return FALSE;
}
State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp2;
break;
}
default:
{
/* Should never reach here! */
ASSERT(FALSE);
}
}
/* Push SS selector */
if (!Fast486StackPush(State, OldSs)) return FALSE;
/* Push stack pointer */
if (!Fast486StackPush(State, OldEsp)) return FALSE;
}
}
else
{
if (State->SegmentRegs[FAST486_REG_CS].Size)
{
/* Set OPSIZE, because INT always pushes 16-bit values in real mode */
State->PrefixFlags |= FAST486_PREFIX_OPSIZE;
}
}
/* Push EFLAGS */
if (!Fast486StackPush(State, State->Flags.Long)) return FALSE;
/* Push CS selector */
if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector)) return FALSE;
/* Push the instruction pointer */
if (!Fast486StackPush(State, State->InstPtr.Long)) return FALSE;
if (InterruptGate)
{
/* Disable interrupts after a jump to an interrupt gate handler */
State->Flags.If = FALSE;
}
/* Load new CS */
if (!Fast486LoadSegment(State, FAST486_REG_CS, SegmentSelector))
{
/* An exception occurred during the jump */
return FALSE;
}
if (State->SegmentRegs[FAST486_REG_CS].Size)
{
/* 32-bit code segment, use EIP */
State->InstPtr.Long = Offset;
}
else
{
/* 16-bit code segment, use IP */
State->InstPtr.LowWord = LOWORD(Offset);
}
return TRUE;
}
VOID
FASTCALL
Fast486ExceptionWithErrorCode(PFAST486_STATE State,
FAST486_EXCEPTIONS ExceptionCode,
ULONG ErrorCode)
{
FAST486_IDT_ENTRY IdtEntry;
/* Increment the exception count */
State->ExceptionCount++;
/* Check if the exception occurred more than once */
if (State->ExceptionCount > 1)
{
/* Then this is a double fault */
ExceptionCode = FAST486_EXCEPTION_DF;
}
/* Check if this is a triple fault */
if (State->ExceptionCount == 3)
{
/* Reset the CPU */
Fast486Reset(State);
return;
}
/* Restore the IP to the saved IP */
State->InstPtr = State->SavedInstPtr;
if (!Fast486GetIntVector(State, ExceptionCode, &IdtEntry))
{
/*
* If this function failed, that means Fast486Exception
* was called again, so just return in this case.
*/
return;
}
/* Perform the interrupt */
if (!Fast486InterruptInternal(State,
IdtEntry.Selector,
MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh),
IdtEntry.Type))
{
/*
* If this function failed, that means Fast486Exception
* was called again, so just return in this case.
*/
return;
}
if (EXCEPTION_HAS_ERROR_CODE(ExceptionCode)
&& (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE))
{
/* Push the error code */
if (!Fast486StackPush(State, ErrorCode))
{
/*
* If this function failed, that means Fast486Exception
* was called again, so just return in this case.
*/
return;
}
}
/* Reset the exception count */
State->ExceptionCount = 0;
}
/* EOF */

180
lib/fast486/common.h Normal file
View file

@ -0,0 +1,180 @@
/*
* Fast486 386/486 CPU Emulation Library
* common.h
*
* Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _COMMON_H_
#define _COMMON_H_
#pragma once
/* DEFINES ********************************************************************/
#define SIGN_FLAG_BYTE 0x80
#define SIGN_FLAG_WORD 0x8000
#define SIGN_FLAG_LONG 0x80000000
#define REAL_MODE_FLAGS_MASK 0x57FD5
#define PROT_MODE_FLAGS_MASK 0x50DD5
/* Block size for string operations */
#define STRING_BLOCK_SIZE 4096
#define GET_SEGMENT_RPL(s) ((s) & 3)
#define GET_SEGMENT_INDEX(s) ((s) & 0xFFF8)
#define SEGMENT_TABLE_INDICATOR (1 << 2)
#define EXCEPTION_HAS_ERROR_CODE(x) (((x) == 8) || ((x) >= 10 && (x) <= 14))
#define NO_LOCK_PREFIX()\
if (State->PrefixFlags & FAST486_PREFIX_LOCK)\
{\
Fast486Exception(State, FAST486_EXCEPTION_UD);\
return FALSE;\
}
#define TOGGLE_OPSIZE(x)\
if (State->PrefixFlags & FAST486_PREFIX_OPSIZE) x = !x;
#define TOGGLE_ADSIZE(x)\
if (State->PrefixFlags & FAST486_PREFIX_ADSIZE) x = !x;
#define SWAP(x, y) { (x) ^= (y); (y) ^= (x); (x) ^= (y); }
#define ALIGNMENT_CHECK(x, a) if (State->Flags.Ac \
&& (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_AM)\
&& (State->Cpl == 3)\
&& (((x) % (a)) != 0))\
{\
Fast486Exception(State, FAST486_EXCEPTION_AC);\
return FALSE;\
}
#define PAGE_ALIGN(x) ((x) & 0xFFFFF000)
#define PAGE_OFFSET(x) ((x) & 0x00000FFF)
#define GET_ADDR_PDE(x) ((x) >> 22)
#define GET_ADDR_PTE(x) (((x) >> 12) & 0x3FF)
#define INVALID_TLB_FIELD 0xFFFFFFFF
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
typedef struct _FAST486_MOD_REG_RM
{
FAST486_GEN_REGS Register;
BOOLEAN Memory;
union
{
FAST486_GEN_REGS SecondRegister;
ULONG MemoryAddress;
};
} FAST486_MOD_REG_RM, *PFAST486_MOD_REG_RM;
#pragma pack(push, 1)
typedef union _FAST486_PAGE_DIR
{
struct
{
ULONG Present : 1;
ULONG Writeable : 1;
ULONG Usermode : 1;
ULONG WriteThrough : 1;
ULONG NoCache : 1;
ULONG Accessed : 1;
ULONG AlwaysZero : 1;
ULONG Size : 1;
ULONG Unused : 4;
ULONG TableAddress : 20;
};
ULONG Value;
} FAST486_PAGE_DIR, *PFAST486_PAGE_DIR;
C_ASSERT(sizeof(FAST486_PAGE_DIR) == sizeof(ULONG));
typedef union _FAST486_PAGE_TABLE
{
struct
{
ULONG Present : 1;
ULONG Writeable : 1;
ULONG Usermode : 1;
ULONG WriteThrough : 1;
ULONG NoCache : 1;
ULONG Accessed : 1;
ULONG Dirty : 1;
ULONG AlwaysZero : 1;
ULONG Global : 1;
ULONG Unused : 3;
ULONG Address : 20;
};
ULONG Value;
} FAST486_PAGE_TABLE, *PFAST486_PAGE_TABLE;
C_ASSERT(sizeof(FAST486_PAGE_DIR) == sizeof(ULONG));
#pragma pack(pop)
/* FUNCTIONS ******************************************************************/
BOOLEAN
Fast486ReadMemory
(
PFAST486_STATE State,
FAST486_SEG_REGS SegmentReg,
ULONG Offset,
BOOLEAN InstFetch,
PVOID Buffer,
ULONG Size
);
BOOLEAN
Fast486WriteMemory
(
PFAST486_STATE State,
FAST486_SEG_REGS SegmentReg,
ULONG Offset,
PVOID Buffer,
ULONG Size
);
BOOLEAN
Fast486InterruptInternal
(
PFAST486_STATE State,
USHORT SegmentSelector,
ULONG Offset,
BOOLEAN InterruptGate
);
VOID
FASTCALL
Fast486ExceptionWithErrorCode
(
PFAST486_STATE State,
FAST486_EXCEPTIONS ExceptionCode,
ULONG ErrorCode
);
/* INLINED FUNCTIONS **********************************************************/
#include "common.inl"
#endif // _COMMON_H_
/* EOF */

1324
lib/fast486/common.inl Normal file

File diff suppressed because it is too large Load diff

2387
lib/fast486/extraops.c Normal file

File diff suppressed because it is too large Load diff

67
lib/fast486/extraops.h Normal file
View file

@ -0,0 +1,67 @@
/*
* Fast486 386/486 CPU Emulation Library
* extraops.h
*
* Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _EXTRAOPS_H_
#define _EXTRAOPS_H_
#pragma once
/* DEFINES ********************************************************************/
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLar);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLsl);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeClts);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreControlReg);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreDebugReg);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadControlReg);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadDebugReg);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushFs);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopFs);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBitTest);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShld);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushGs);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopGs);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBts);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShrd);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeImul);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchgByte);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchg);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLss);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtr);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLfsLgs);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxByte);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxWord);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtc);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsf);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsr);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxByte);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxWord);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalJmp);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalSet);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXaddByte);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXadd);
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBswap);
FAST486_OPCODE_HANDLER(Fast486OpcodeExtended);
#endif // _EXTRAOPS_H_
/* EOF */

463
lib/fast486/fast486.c Normal file
View file

@ -0,0 +1,463 @@
/*
* Fast486 386/486 CPU Emulation Library
* fast486.c
*
* Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* INCLUDES *******************************************************************/
#include <windef.h>
// #define NDEBUG
#include <debug.h>
#include <fast486.h>
#include "common.h"
#include "opcodes.h"
/* DEFINES ********************************************************************/
typedef enum
{
FAST486_STEP_INTO,
FAST486_STEP_OVER,
FAST486_STEP_OUT,
FAST486_CONTINUE
} FAST486_EXEC_CMD;
/* PRIVATE FUNCTIONS **********************************************************/
static
inline
VOID
NTAPI
Fast486ExecutionControl(PFAST486_STATE State, FAST486_EXEC_CMD Command)
{
UCHAR Opcode;
INT ProcedureCallCount = 0;
/* Main execution loop */
do
{
/* Check if this is a new instruction */
if (State->PrefixFlags == 0) State->SavedInstPtr = State->InstPtr;
/* Perform an instruction fetch */
if (!Fast486FetchByte(State, &Opcode))
{
/* Exception occurred */
State->PrefixFlags = 0;
continue;
}
// TODO: Check for CALL/RET to update ProcedureCallCount.
if (Fast486OpcodeHandlers[Opcode] != NULL)
{
/* Call the opcode handler */
Fast486OpcodeHandlers[Opcode](State, Opcode);
}
else
{
/* This is not a valid opcode */
Fast486Exception(State, FAST486_EXCEPTION_UD);
}
if (Fast486OpcodeHandlers[Opcode] == Fast486OpcodePrefix)
{
/* This is a prefix, go to the next instruction immediately */
continue;
}
/* A non-prefix opcode has been executed, reset the prefix flags */
State->PrefixFlags = 0;
/*
* Check if there is an interrupt to execute, or a hardware interrupt signal
* while interrupts are enabled.
*/
if (State->IntStatus == FAST486_INT_EXECUTE)
{
FAST486_IDT_ENTRY IdtEntry;
/* Get the interrupt vector */
if (Fast486GetIntVector(State, State->PendingIntNum, &IdtEntry))
{
/* Perform the interrupt */
Fast486InterruptInternal(State,
IdtEntry.Selector,
MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh),
IdtEntry.Type);
/* Restore the prefix flags, which would be set to OPSIZE for 32-bit real mode */
State->PrefixFlags = 0;
}
/* Clear the interrupt status */
State->IntStatus = FAST486_INT_NONE;
}
else if (State->Flags.If
&& (State->IntAckCallback != NULL)
&& (State->IntStatus == FAST486_INT_SIGNAL))
{
/* Acknowledge the interrupt to get the number */
State->PendingIntNum = State->IntAckCallback(State);
/* Set the interrupt status to execute on the next instruction */
State->IntStatus = FAST486_INT_EXECUTE;
}
}
while ((Command == FAST486_CONTINUE)
|| (Command == FAST486_STEP_OVER && ProcedureCallCount > 0)
|| (Command == FAST486_STEP_OUT && ProcedureCallCount >= 0)
|| (Fast486OpcodeHandlers[Opcode] == Fast486OpcodePrefix));
}
/* DEFAULT CALLBACKS **********************************************************/
static VOID
NTAPI
Fast486MemReadCallback(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
{
UNREFERENCED_PARAMETER(State);
RtlMoveMemory(Buffer, (PVOID)Address, Size);
}
static VOID
NTAPI
Fast486MemWriteCallback(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
{
UNREFERENCED_PARAMETER(State);
RtlMoveMemory((PVOID)Address, Buffer, Size);
}
static VOID
NTAPI
Fast486IoReadCallback(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize)
{
UNREFERENCED_PARAMETER(State);
UNREFERENCED_PARAMETER(Port);
UNREFERENCED_PARAMETER(Buffer);
UNREFERENCED_PARAMETER(DataCount);
UNREFERENCED_PARAMETER(DataSize);
}
static VOID
NTAPI
Fast486IoWriteCallback(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize)
{
UNREFERENCED_PARAMETER(State);
UNREFERENCED_PARAMETER(Port);
UNREFERENCED_PARAMETER(Buffer);
UNREFERENCED_PARAMETER(DataCount);
UNREFERENCED_PARAMETER(DataSize);
}
static VOID
NTAPI
Fast486IdleCallback(PFAST486_STATE State)
{
UNREFERENCED_PARAMETER(State);
}
static VOID
NTAPI
Fast486BopCallback(PFAST486_STATE State, UCHAR BopCode)
{
UNREFERENCED_PARAMETER(State);
UNREFERENCED_PARAMETER(BopCode);
}
static UCHAR
NTAPI
Fast486IntAckCallback(PFAST486_STATE State)
{
UNREFERENCED_PARAMETER(State);
/* Return something... */
return 0;
}
/* PUBLIC FUNCTIONS ***********************************************************/
VOID
NTAPI
Fast486Initialize(PFAST486_STATE State,
FAST486_MEM_READ_PROC MemReadCallback,
FAST486_MEM_WRITE_PROC MemWriteCallback,
FAST486_IO_READ_PROC IoReadCallback,
FAST486_IO_WRITE_PROC IoWriteCallback,
FAST486_IDLE_PROC IdleCallback,
FAST486_BOP_PROC BopCallback,
FAST486_INT_ACK_PROC IntAckCallback,
PULONG Tlb)
{
/* Set the callbacks (or use default ones if some are NULL) */
State->MemReadCallback = (MemReadCallback ? MemReadCallback : Fast486MemReadCallback );
State->MemWriteCallback = (MemWriteCallback ? MemWriteCallback : Fast486MemWriteCallback);
State->IoReadCallback = (IoReadCallback ? IoReadCallback : Fast486IoReadCallback );
State->IoWriteCallback = (IoWriteCallback ? IoWriteCallback : Fast486IoWriteCallback );
State->IdleCallback = (IdleCallback ? IdleCallback : Fast486IdleCallback );
State->BopCallback = (BopCallback ? BopCallback : Fast486BopCallback );
State->IntAckCallback = (IntAckCallback ? IntAckCallback : Fast486IntAckCallback );
/* Set the TLB (if given) */
State->Tlb = Tlb;
/* Reset the CPU */
Fast486Reset(State);
}
VOID
NTAPI
Fast486Reset(PFAST486_STATE State)
{
FAST486_SEG_REGS i;
FAST486_MEM_READ_PROC MemReadCallback = State->MemReadCallback;
FAST486_MEM_WRITE_PROC MemWriteCallback = State->MemWriteCallback;
FAST486_IO_READ_PROC IoReadCallback = State->IoReadCallback;
FAST486_IO_WRITE_PROC IoWriteCallback = State->IoWriteCallback;
FAST486_IDLE_PROC IdleCallback = State->IdleCallback;
FAST486_BOP_PROC BopCallback = State->BopCallback;
FAST486_INT_ACK_PROC IntAckCallback = State->IntAckCallback;
PULONG Tlb = State->Tlb;
/* Clear the entire structure */
RtlZeroMemory(State, sizeof(*State));
/* Initialize the registers */
State->Flags.AlwaysSet = 1;
State->InstPtr.LowWord = 0xFFF0;
/* Set the CPL to 0 */
State->Cpl = 0;
/* Initialize segments */
for (i = 0; i < FAST486_NUM_SEG_REGS; i++)
{
State->SegmentRegs[i].Selector = 0;
State->SegmentRegs[i].Base = 0;
State->SegmentRegs[i].Limit = 0xFFFF;
State->SegmentRegs[i].Present = TRUE;
State->SegmentRegs[i].ReadWrite = TRUE;
State->SegmentRegs[i].Executable = FALSE;
State->SegmentRegs[i].DirConf = FALSE;
State->SegmentRegs[i].SystemType = 1; // Segment descriptor
State->SegmentRegs[i].Dpl = 0;
State->SegmentRegs[i].Size = FALSE; // 16-bit
}
/* Initialize the code segment */
State->SegmentRegs[FAST486_REG_CS].Executable = TRUE;
State->SegmentRegs[FAST486_REG_CS].Selector = 0xF000;
State->SegmentRegs[FAST486_REG_CS].Base = 0xFFFF0000;
/* Initialize the IDT */
State->Idtr.Size = 0x3FF;
State->Idtr.Address = 0;
#ifndef FAST486_NO_FPU
/* Initialize CR0 */
State->ControlRegisters[FAST486_REG_CR0] |= FAST486_CR0_ET;
#endif
/* Restore the callbacks and TLB */
State->MemReadCallback = MemReadCallback;
State->MemWriteCallback = MemWriteCallback;
State->IoReadCallback = IoReadCallback;
State->IoWriteCallback = IoWriteCallback;
State->IdleCallback = IdleCallback;
State->BopCallback = BopCallback;
State->IntAckCallback = IntAckCallback;
State->Tlb = Tlb;
}
VOID
NTAPI
Fast486DumpState(PFAST486_STATE State)
{
DPRINT1("\nCPU currently executing in %s mode at %04X:%08X\n",
(State->ControlRegisters[0] & FAST486_CR0_PE) ? "protected" : "real",
State->SegmentRegs[FAST486_REG_CS].Selector,
State->InstPtr.Long);
DPRINT1("\nGeneral purpose registers:\n"
"EAX = %08X\tECX = %08X\tEDX = %08X\tEBX = %08X\n"
"ESP = %08X\tEBP = %08X\tESI = %08X\tEDI = %08X\n",
State->GeneralRegs[FAST486_REG_EAX].Long,
State->GeneralRegs[FAST486_REG_ECX].Long,
State->GeneralRegs[FAST486_REG_EDX].Long,
State->GeneralRegs[FAST486_REG_EBX].Long,
State->GeneralRegs[FAST486_REG_ESP].Long,
State->GeneralRegs[FAST486_REG_EBP].Long,
State->GeneralRegs[FAST486_REG_ESI].Long,
State->GeneralRegs[FAST486_REG_EDI].Long);
DPRINT1("\nSegment registers:\n"
"ES = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n"
"CS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n"
"SS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n"
"DS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n"
"FS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n"
"GS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n",
State->SegmentRegs[FAST486_REG_ES].Selector,
State->SegmentRegs[FAST486_REG_ES].Base,
State->SegmentRegs[FAST486_REG_ES].Limit,
State->SegmentRegs[FAST486_REG_ES].Dpl,
State->SegmentRegs[FAST486_REG_CS].Selector,
State->SegmentRegs[FAST486_REG_CS].Base,
State->SegmentRegs[FAST486_REG_CS].Limit,
State->SegmentRegs[FAST486_REG_CS].Dpl,
State->SegmentRegs[FAST486_REG_SS].Selector,
State->SegmentRegs[FAST486_REG_SS].Base,
State->SegmentRegs[FAST486_REG_SS].Limit,
State->SegmentRegs[FAST486_REG_SS].Dpl,
State->SegmentRegs[FAST486_REG_DS].Selector,
State->SegmentRegs[FAST486_REG_DS].Base,
State->SegmentRegs[FAST486_REG_DS].Limit,
State->SegmentRegs[FAST486_REG_DS].Dpl,
State->SegmentRegs[FAST486_REG_FS].Selector,
State->SegmentRegs[FAST486_REG_FS].Base,
State->SegmentRegs[FAST486_REG_FS].Limit,
State->SegmentRegs[FAST486_REG_FS].Dpl,
State->SegmentRegs[FAST486_REG_GS].Selector,
State->SegmentRegs[FAST486_REG_GS].Base,
State->SegmentRegs[FAST486_REG_GS].Limit,
State->SegmentRegs[FAST486_REG_GS].Dpl);
DPRINT1("\nFlags: %08X (%s %s %s %s %s %s %s %s %s %s %s %s) Iopl: %u\n",
State->Flags.Long,
State->Flags.Cf ? "CF" : "cf",
State->Flags.Pf ? "PF" : "pf",
State->Flags.Af ? "AF" : "af",
State->Flags.Zf ? "ZF" : "zf",
State->Flags.Sf ? "SF" : "sf",
State->Flags.Tf ? "TF" : "tf",
State->Flags.If ? "IF" : "if",
State->Flags.Df ? "DF" : "df",
State->Flags.Of ? "OF" : "of",
State->Flags.Nt ? "NT" : "nt",
State->Flags.Rf ? "RF" : "rf",
State->Flags.Vm ? "VM" : "vm",
State->Flags.Iopl);
DPRINT1("\nControl Registers:\n"
"CR0 = %08X\tCR2 = %08X\tCR3 = %08X\n",
State->ControlRegisters[FAST486_REG_CR0],
State->ControlRegisters[FAST486_REG_CR2],
State->ControlRegisters[FAST486_REG_CR3]);
DPRINT1("\nDebug Registers:\n"
"DR0 = %08X\tDR1 = %08X\tDR2 = %08X\n"
"DR3 = %08X\tDR4 = %08X\tDR5 = %08X\n",
State->DebugRegisters[FAST486_REG_DR0],
State->DebugRegisters[FAST486_REG_DR1],
State->DebugRegisters[FAST486_REG_DR2],
State->DebugRegisters[FAST486_REG_DR3],
State->DebugRegisters[FAST486_REG_DR4],
State->DebugRegisters[FAST486_REG_DR5]);
}
VOID
NTAPI
Fast486Continue(PFAST486_STATE State)
{
/* Call the internal function */
Fast486ExecutionControl(State, FAST486_CONTINUE);
}
VOID
NTAPI
Fast486StepInto(PFAST486_STATE State)
{
/* Call the internal function */
Fast486ExecutionControl(State, FAST486_STEP_INTO);
}
VOID
NTAPI
Fast486StepOver(PFAST486_STATE State)
{
/* Call the internal function */
Fast486ExecutionControl(State, FAST486_STEP_OVER);
}
VOID
NTAPI
Fast486StepOut(PFAST486_STATE State)
{
/* Call the internal function */
Fast486ExecutionControl(State, FAST486_STEP_OUT);
}
VOID
NTAPI
Fast486Interrupt(PFAST486_STATE State, UCHAR Number)
{
/* Set the interrupt status and the number */
State->IntStatus = FAST486_INT_EXECUTE;
State->PendingIntNum = Number;
}
VOID
NTAPI
Fast486InterruptSignal(PFAST486_STATE State)
{
/* Set the interrupt status */
State->IntStatus = FAST486_INT_SIGNAL;
}
VOID
NTAPI
Fast486ExecuteAt(PFAST486_STATE State, USHORT Segment, ULONG Offset)
{
/* Load the new CS */
if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment))
{
/* An exception occurred, let the handler execute instead */
return;
}
/* Set the new IP */
State->InstPtr.Long = Offset;
}
VOID
NTAPI
Fast486SetStack(PFAST486_STATE State, USHORT Segment, ULONG Offset)
{
/* Load the new SS */
if (!Fast486LoadSegment(State, FAST486_REG_SS, Segment))
{
/* An exception occurred, let the handler execute instead */
return;
}
/* Set the new SP */
State->GeneralRegs[FAST486_REG_ESP].Long = Offset;
}
VOID
NTAPI
Fast486SetSegment(PFAST486_STATE State,
FAST486_SEG_REGS Segment,
USHORT Selector)
{
/* Call the internal function */
Fast486LoadSegment(State, Segment, Selector);
}
/* EOF */

236
lib/fast486/fpu.c Normal file
View file

@ -0,0 +1,236 @@
/*
* Fast486 386/486 CPU Emulation Library
* fpu.c
*
* Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* INCLUDES *******************************************************************/
#include <windef.h>
// #define NDEBUG
#include <debug.h>
#include <fast486.h>
#include "common.h"
#include "opcodes.h"
#include "fpu.h"
/* PUBLIC FUNCTIONS ***********************************************************/
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
/* Get the operands */
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
/* Exception occurred */
return FALSE;
}
FPU_CHECK();
#ifndef FAST486_NO_FPU
// TODO: NOT IMPLEMENTED
UNIMPLEMENTED;
return FALSE;
#else
/* Do nothing */
return TRUE;
#endif
}
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
/* Get the operands */
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
/* Exception occurred */
return FALSE;
}
FPU_CHECK();
#ifndef FAST486_NO_FPU
// TODO: NOT IMPLEMENTED
UNIMPLEMENTED;
return FALSE;
#else
/* Do nothing */
return TRUE;
#endif
}
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
/* Get the operands */
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
/* Exception occurred */
return FALSE;
}
FPU_CHECK();
#ifndef FAST486_NO_FPU
// TODO: NOT IMPLEMENTED
UNIMPLEMENTED;
return FALSE;
#else
/* Do nothing */
return TRUE;
#endif
}
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
/* Get the operands */
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
/* Exception occurred */
return FALSE;
}
FPU_CHECK();
#ifndef FAST486_NO_FPU
// TODO: NOT IMPLEMENTED
UNIMPLEMENTED;
return FALSE;
#else
/* Do nothing */
return TRUE;
#endif
}
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
/* Get the operands */
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
/* Exception occurred */
return FALSE;
}
FPU_CHECK();
#ifndef FAST486_NO_FPU
// TODO: NOT IMPLEMENTED
UNIMPLEMENTED;
return FALSE;
#else
/* Do nothing */
return TRUE;
#endif
}
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
/* Get the operands */
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
/* Exception occurred */
return FALSE;
}
FPU_CHECK();
#ifndef FAST486_NO_FPU
// TODO: NOT IMPLEMENTED
UNIMPLEMENTED;
return FALSE;
#else
/* Do nothing */
return TRUE;
#endif
}
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
/* Get the operands */
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
/* Exception occurred */
return FALSE;
}
FPU_CHECK();
#ifndef FAST486_NO_FPU
// TODO: NOT IMPLEMENTED
UNIMPLEMENTED;
return FALSE;
#else
/* Do nothing */
return TRUE;
#endif
}
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
/* Get the operands */
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
/* Exception occurred */
return FALSE;
}
FPU_CHECK();
#ifndef FAST486_NO_FPU
// TODO: NOT IMPLEMENTED
UNIMPLEMENTED;
return FALSE;
#else
/* Do nothing */
return TRUE;
#endif
}
/* EOF */

62
lib/fast486/fpu.h Normal file
View file

@ -0,0 +1,62 @@
/*
* Fast486 386/486 CPU Emulation Library
* fpu.h
*
* Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _FPU_H_
#define _FPU_H_
#pragma once
/* DEFINES ********************************************************************/
#define FPU_CHECK() if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_EM) \
{ \
Fast486Exception(State, FAST486_EXCEPTION_NM); \
return FALSE; \
}
#define FPU_ST(i) State->FpuRegisters[(State->FpuStatus.Top + (i)) % FAST486_NUM_FPU_REGS]
enum
{
FPU_SINGLE_PRECISION = 0,
FPU_DOUBLE_PRECISION = 2,
FPU_DOUBLE_EXT_PRECISION = 3
};
enum
{
FPU_TAG_VALID = 0,
FPU_TAG_ZERO = 1,
FPU_TAG_SPECIAL = 2,
FPU_TAG_EMPTY = 3
};
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8);
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9);
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA);
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB);
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC);
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD);
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE);
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF);
#endif // _FPU_H_
/* EOF */

6312
lib/fast486/opcodes.c Normal file

File diff suppressed because it is too large Load diff

157
lib/fast486/opcodes.h Normal file
View file

@ -0,0 +1,157 @@
/*
* Fast486 386/486 CPU Emulation Library
* opcodes.h
*
* Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _OPCODES_H_
#define _OPCODES_H_
#pragma once
/* DEFINES ********************************************************************/
#define FAST486_NUM_OPCODE_HANDLERS 256
#define FAST486_OPCODE_WRITE_REG (1 << 1)
#define FAST486_OPCODE_HANDLER(x) \
BOOLEAN FASTCALL x(PFAST486_STATE State, UCHAR Opcode)
typedef BOOLEAN (FASTCALL *FAST486_OPCODE_HANDLER_PROC)(PFAST486_STATE, UCHAR);
extern
FAST486_OPCODE_HANDLER_PROC
Fast486OpcodeHandlers[FAST486_NUM_OPCODE_HANDLERS];
FAST486_OPCODE_HANDLER(Fast486OpcodePrefix);
FAST486_OPCODE_HANDLER(Fast486OpcodeIncrement);
FAST486_OPCODE_HANDLER(Fast486OpcodeDecrement);
FAST486_OPCODE_HANDLER(Fast486OpcodePushReg);
FAST486_OPCODE_HANDLER(Fast486OpcodePopReg);
FAST486_OPCODE_HANDLER(Fast486OpcodeNop);
FAST486_OPCODE_HANDLER(Fast486OpcodeExchangeEax);
FAST486_OPCODE_HANDLER(Fast486OpcodeShortConditionalJmp);
FAST486_OPCODE_HANDLER(Fast486OpcodeClearCarry);
FAST486_OPCODE_HANDLER(Fast486OpcodeSetCarry);
FAST486_OPCODE_HANDLER(Fast486OpcodeComplCarry);
FAST486_OPCODE_HANDLER(Fast486OpcodeClearInt);
FAST486_OPCODE_HANDLER(Fast486OpcodeSetInt);
FAST486_OPCODE_HANDLER(Fast486OpcodeClearDir);
FAST486_OPCODE_HANDLER(Fast486OpcodeSetDir);
FAST486_OPCODE_HANDLER(Fast486OpcodeHalt);
FAST486_OPCODE_HANDLER(Fast486OpcodeInByte);
FAST486_OPCODE_HANDLER(Fast486OpcodeIn);
FAST486_OPCODE_HANDLER(Fast486OpcodeOutByte);
FAST486_OPCODE_HANDLER(Fast486OpcodeOut);
FAST486_OPCODE_HANDLER(Fast486OpcodeShortJump);
FAST486_OPCODE_HANDLER(Fast486OpcodeMovRegImm);
FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteRegImm);
FAST486_OPCODE_HANDLER(Fast486OpcodeAddByteModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeAddModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeAddAl);
FAST486_OPCODE_HANDLER(Fast486OpcodeAddEax);
FAST486_OPCODE_HANDLER(Fast486OpcodeOrByteModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeOrModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeOrAl);
FAST486_OPCODE_HANDLER(Fast486OpcodeOrEax);
FAST486_OPCODE_HANDLER(Fast486OpcodeAndByteModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeAndModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeAndAl);
FAST486_OPCODE_HANDLER(Fast486OpcodeAndEax);
FAST486_OPCODE_HANDLER(Fast486OpcodeXorByteModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeXorModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeXorAl);
FAST486_OPCODE_HANDLER(Fast486OpcodeXorEax);
FAST486_OPCODE_HANDLER(Fast486OpcodeTestByteModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeTestModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeTestAl);
FAST486_OPCODE_HANDLER(Fast486OpcodeTestEax);
FAST486_OPCODE_HANDLER(Fast486OpcodeXchgByteModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeXchgModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodePushEs);
FAST486_OPCODE_HANDLER(Fast486OpcodePopEs);
FAST486_OPCODE_HANDLER(Fast486OpcodePushCs);
FAST486_OPCODE_HANDLER(Fast486OpcodeAdcByteModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeAdcModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeAdcAl);
FAST486_OPCODE_HANDLER(Fast486OpcodeAdcEax);
FAST486_OPCODE_HANDLER(Fast486OpcodePushSs);
FAST486_OPCODE_HANDLER(Fast486OpcodePopSs);
FAST486_OPCODE_HANDLER(Fast486OpcodeSbbByteModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeSbbModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeSbbAl);
FAST486_OPCODE_HANDLER(Fast486OpcodeSbbEax);
FAST486_OPCODE_HANDLER(Fast486OpcodePushDs);
FAST486_OPCODE_HANDLER(Fast486OpcodePopDs);
FAST486_OPCODE_HANDLER(Fast486OpcodeDaa);
FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubByteModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubAl);
FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubEax);
FAST486_OPCODE_HANDLER(Fast486OpcodeDas);
FAST486_OPCODE_HANDLER(Fast486OpcodeAaa);
FAST486_OPCODE_HANDLER(Fast486OpcodeAas);
FAST486_OPCODE_HANDLER(Fast486OpcodePushAll);
FAST486_OPCODE_HANDLER(Fast486OpcodePopAll);
FAST486_OPCODE_HANDLER(Fast486OpcodeBound);
FAST486_OPCODE_HANDLER(Fast486OpcodeArpl);
FAST486_OPCODE_HANDLER(Fast486OpcodePushImm);
FAST486_OPCODE_HANDLER(Fast486OpcodeImulModrmImm);
FAST486_OPCODE_HANDLER(Fast486OpcodePushByteImm);
FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeMovModrm);
FAST486_OPCODE_HANDLER(Fast486OpcodeMovStoreSeg);
FAST486_OPCODE_HANDLER(Fast486OpcodeLea);
FAST486_OPCODE_HANDLER(Fast486OpcodeMovLoadSeg);
FAST486_OPCODE_HANDLER(Fast486OpcodeCwde);
FAST486_OPCODE_HANDLER(Fast486OpcodeCdq);
FAST486_OPCODE_HANDLER(Fast486OpcodeCallAbs);
FAST486_OPCODE_HANDLER(Fast486OpcodeWait);
FAST486_OPCODE_HANDLER(Fast486OpcodePushFlags);
FAST486_OPCODE_HANDLER(Fast486OpcodePopFlags);
FAST486_OPCODE_HANDLER(Fast486OpcodeSahf);
FAST486_OPCODE_HANDLER(Fast486OpcodeLahf);
FAST486_OPCODE_HANDLER(Fast486OpcodeRet);
FAST486_OPCODE_HANDLER(Fast486OpcodeLdsLes);
FAST486_OPCODE_HANDLER(Fast486OpcodeEnter);
FAST486_OPCODE_HANDLER(Fast486OpcodeLeave);
FAST486_OPCODE_HANDLER(Fast486OpcodeRetFarImm);
FAST486_OPCODE_HANDLER(Fast486OpcodeRetFar);
FAST486_OPCODE_HANDLER(Fast486OpcodeInt);
FAST486_OPCODE_HANDLER(Fast486OpcodeIret);
FAST486_OPCODE_HANDLER(Fast486OpcodeAam);
FAST486_OPCODE_HANDLER(Fast486OpcodeAad);
FAST486_OPCODE_HANDLER(Fast486OpcodeXlat);
FAST486_OPCODE_HANDLER(Fast486OpcodeLoop);
FAST486_OPCODE_HANDLER(Fast486OpcodeJecxz);
FAST486_OPCODE_HANDLER(Fast486OpcodeCall);
FAST486_OPCODE_HANDLER(Fast486OpcodeJmp);
FAST486_OPCODE_HANDLER(Fast486OpcodeJmpAbs);
FAST486_OPCODE_HANDLER(Fast486OpcodeMovAlOffset);
FAST486_OPCODE_HANDLER(Fast486OpcodeMovEaxOffset);
FAST486_OPCODE_HANDLER(Fast486OpcodeMovOffsetAl);
FAST486_OPCODE_HANDLER(Fast486OpcodeMovOffsetEax);
FAST486_OPCODE_HANDLER(Fast486OpcodeSalc);
FAST486_OPCODE_HANDLER(Fast486OpcodeMovs);
FAST486_OPCODE_HANDLER(Fast486OpcodeCmps);
FAST486_OPCODE_HANDLER(Fast486OpcodeStos);
FAST486_OPCODE_HANDLER(Fast486OpcodeLods);
FAST486_OPCODE_HANDLER(Fast486OpcodeScas);
FAST486_OPCODE_HANDLER(Fast486OpcodeIns);
FAST486_OPCODE_HANDLER(Fast486OpcodeOuts);
#endif // _OPCODES_H_

2370
lib/fast486/opgroups.c Normal file

File diff suppressed because it is too large Load diff

53
lib/fast486/opgroups.h Normal file
View file

@ -0,0 +1,53 @@
/*
* Fast486 386/486 CPU Emulation Library
* opgroups.h
*
* Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _OPGROUPS_H_
#define _OPGROUPS_H_
#pragma once
/* DEFINES ********************************************************************/
FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroup83);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8F);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC0);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC1);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC6);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC7);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD0);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD2);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F00);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FB9);
FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA);
#endif // _OPGROUPS_H_
/* EOF */

File diff suppressed because it is too large Load diff

View file

@ -39,7 +39,8 @@ struct __thread_data {
struct tm *time_buffer; /* buffer for localtime/gmtime */
char *efcvt_buffer; /* buffer for ecvt/fcvt */
int unk3[2];
void *unk4[4];
void *unk4[3];
EXCEPTION_POINTERS *xcptinfo;
int fpecode;
struct MSVCRT_threadmbcinfostruct *mbcinfo;
struct MSVCRT_threadlocaleinfostruct *locinfo;

View file

@ -1,9 +1,9 @@
#include <stdlib.h>
#include <precomp.h>
/*
* @unimplemented
* @implemented
*/
void **__pxcptinfoptrs (void)
void** __pxcptinfoptrs(void)
{
return NULL;
return (void**)&msvcrt_get_thread_data()->xcptinfo;
}

View file

@ -258,7 +258,7 @@ gdi32 -
reactos/dll/win32/gdi32/objects/linedda.c # Synced at 20090410
kernel32 -
reactos/dll/win32/kernel32/wine/actctx.c # Partly synced
reactos/dll/win32/kernel32/wine/actctx.c # Partly synced with Wine 1.7.17
reactos/dll/win32/kernel32/wine/comm.c # Synced in r52754
reactos/dll/win32/kernel32/wine/lzexpand.c # Synced in r52754
reactos/dll/win32/kernel32/wine/profile.c # Synced in r52754
@ -275,6 +275,7 @@ kernel32 -
msvcrt -
reactos/lib/sdk/crt/except/cpp.c # Synced at 20080528
reactos/lib/sdk/crt/except/cppexcept.c # Synced at 20071111
reactos/lib/sdk/crt/signal/xcptinfo.c # Synced to Wine-1.7.17
reactos/lib/sdk/crt/string/scanf.c/h # Synced to Wine-1_1_27
reactos/lib/sdk/crt/strings/wcs.c # Synced at 20080611
reactos/lib/sdk/crt/wine/heap.c # Synced at 20080529

View file

@ -180,6 +180,11 @@ KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame,
StopChecking = FALSE;
}
#else
#define KiExitTrapDebugChecks(x, y)
#define KiFillTrapFrameDebug(x)
#endif
FORCEINLINE
VOID
KiExitSystemCallDebugChecks(IN ULONG SystemCall,
@ -219,11 +224,6 @@ KiExitSystemCallDebugChecks(IN ULONG SystemCall,
}
}
}
#else
#define KiExitTrapDebugChecks(x, y)
#define KiFillTrapFrameDebug(x)
#define KiExitSystemCallDebugChecks(x, y)
#endif
//
// Generic Exit Routine

View file

@ -280,7 +280,14 @@ l_ReadHeaderFromFile:
nStatus = ReadFileCb(File, &lnOffset, sizeof(IMAGE_NT_HEADERS64), &pData, &pBuffer, &cbReadSize);
if(!NT_SUCCESS(nStatus))
DIE(("ReadFile failed, status %08X\n", nStatus));
{
NTSTATUS ReturnedStatus = nStatus;
/* If it attempted to read past the end of the file, it means e_lfanew is invalid */
if (ReturnedStatus == STATUS_END_OF_FILE) nStatus = STATUS_ROS_EXEFMT_UNKNOWN_FORMAT;
DIE(("ReadFile failed, status %08X\n", ReturnedStatus));
}
ASSERT(pData);
ASSERT(pBuffer);

View file

@ -1,6 +1,4 @@
if(ARCH STREQUAL "i386")
add_subdirectory(ntvdm)
endif()
add_subdirectory(ntvdm)
add_subdirectory(win)
add_subdirectory(win32)

View file

@ -1,11 +1,42 @@
include_directories(.)
include_directories(
${REACTOS_SOURCE_DIR}/include/reactos/libs/fast486
ntvdm)
add_executable(ntvdm
spec2def(ntvdm.exe ntvdm.spec)
list(APPEND SOURCE
bios/bios32/bios32.c
bios/bios32/kbdbios32.c
bios/bios32/vidbios32.c
bios/bios.c
bios/kbdbios.c
bios/rom.c
bios/vidbios.c
hardware/cmos.c
hardware/pic.c
hardware/ps2.c
hardware/speaker.c
hardware/timer.c
hardware/vga.c
dos/dos32krnl/bios.c
dos/dos32krnl/dos.c
dos/dem.c
bop.c
callback.c
clock.c
emulator.c
io.c
registers.c
utils.c
vddsup.c
ntvdm.c
ntvdm.rc)
ntvdm.rc
${CMAKE_CURRENT_BINARY_DIR}/ntvdm.def)
set_module_type(ntvdm win32cui)
add_importlibs(ntvdm ntdll user32 gdi32 advapi32 msvcrt kernel32)
add_dependencies(ntvdm ndk bugcodes)
add_executable(ntvdm ${SOURCE})
set_module_type(ntvdm win32cui UNICODE)
set_image_base(ntvdm 0x0F000000)
target_link_libraries(ntvdm fast486)
add_importlibs(ntvdm user32 gdi32 advapi32 msvcrt kernel32 ntdll)
add_cd_file(TARGET ntvdm DESTINATION reactos/system32 FOR all)

View file

@ -0,0 +1,211 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: bios.c
* PURPOSE: VDM BIOS Support Library
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *******************************************************************/
#define NDEBUG
#include "emulator.h"
#include "callback.h"
#include "bop.h"
#include "bios.h"
#include "bios32/bios32.h"
#include "rom.h"
#include "io.h"
#include "hardware/cmos.h"
/* DEFINES ********************************************************************/
/* BOP Identifiers */
#define BOP_BIOSINIT 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
// to let the virtual machine initialize itself
// the IVT and its hardware.
#define BOP_EQUIPLIST 0x11
#define BOP_GETMEMSIZE 0x12
/* PRIVATE VARIABLES **********************************************************/
static BOOLEAN Bios32Loaded = FALSE;
static CALLBACK16 __BiosContext;
PBIOS_DATA_AREA Bda;
/* PRIVATE FUNCTIONS **********************************************************/
static VOID WINAPI BiosInitBop(LPWORD Stack)
{
BOOLEAN Success;
/* Load the second part of the Windows NTVDM BIOS image */
LPCSTR BiosFileName = "bios1.rom";
PVOID BiosLocation = (PVOID)TO_LINEAR(BIOS_SEGMENT, 0x0000);
DWORD BiosSize = 0;
/* Disable interrupts */
setIF(0);
DisplayMessage(L"You are loading Windows NTVDM BIOS!\n");
/* Initialize a private callback context */
InitializeContext(&__BiosContext, BIOS_SEGMENT, 0x0000);
Success = LoadRom(BiosFileName, BiosLocation, &BiosSize);
DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
if (Success == FALSE)
{
/* Stop the VDM */
EmulatorTerminate();
return;
}
// DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
// L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x",
// BiosLocation,
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 0),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 1),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 2),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 3),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 4),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 5),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 6),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 7),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9),
// (PVOID)((ULONG_PTR)BiosLocation + BiosSize - 2),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 2),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 1),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 0));
/* Initialize IVT and hardware */
/* Initialize the Keyboard and Video BIOS */
if (!KbdBiosInitialize() || !VidBiosInitialize())
{
/* Stop the VDM */
EmulatorTerminate();
return;
}
/* Load VGA BIOS */
// Success = LoadRom("v7vga.rom", (PVOID)0xC0000, &BiosSize);
// DPRINT1("VGA BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
/* Enable interrupts */
setIF(1);
///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
/* Load some ROMs */
// Success = LoadRom("boot.bin", (PVOID)0xE0000, &BiosSize);
// DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
SearchAndInitRoms(&__BiosContext);
}
/* PUBLIC FUNCTIONS ***********************************************************/
VOID WINAPI BiosEquipmentService(LPWORD Stack)
{
/* Return the equipment list */
setAX(Bda->EquipmentList);
}
VOID WINAPI BiosGetMemorySize(LPWORD Stack)
{
/* Return the conventional memory size in kB, typically 640 kB */
setAX(Bda->MemorySize);
}
BOOLEAN
BiosInitialize(IN LPCSTR BiosFileName)
{
BOOLEAN Success = FALSE;
/* Disable interrupts */
setIF(0);
/* Initialize the BDA pointer */
Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0);
/* Register the BIOS support BOPs */
RegisterBop(BOP_BIOSINIT , BiosInitBop);
RegisterBop(BOP_EQUIPLIST , BiosEquipmentService);
RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize);
if (BiosFileName)
{
PVOID BiosLocation = NULL;
DWORD BiosSize = 0;
Success = LoadBios(BiosFileName, &BiosLocation, &BiosSize);
DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
if (!Success) return FALSE;
DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x",
BiosLocation,
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 0),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 1),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 2),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 3),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 4),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 5),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 6),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 7),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9),
(PVOID)((ULONG_PTR)BiosLocation + BiosSize - 2),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 2),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 1),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 0));
DisplayMessage(L"POST at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
TO_LINEAR(getCS(), getIP()),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 0),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 1),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 2),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 3),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 4));
/* Boot it up */
/*
* The CPU is already in reset-mode so that
* CS:IP points to F000:FFF0 as required.
*/
DisplayMessage(L"CS=0x%p ; IP=0x%p", getCS(), getIP());
// setCS(0xF000);
// setIP(0xFFF0);
Success = TRUE;
}
else
{
Success = Bios32Loaded = Bios32Initialize();
}
/* Enable interrupts */
setIF(1);
return Success;
}
VOID
BiosCleanup(VOID)
{
if (Bios32Loaded) Bios32Cleanup();
}
/* EOF */

View file

@ -0,0 +1,118 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: bios.h
* PURPOSE: VDM BIOS Support Library
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
#ifndef _BIOS_H_
#define _BIOS_H_
/* INCLUDES *******************************************************************/
#include "ntvdm.h"
#include "kbdbios.h"
#include "vidbios.h"
/* DEFINES ********************************************************************/
#define BDA_SEGMENT 0x40
#define BIOS_SEGMENT 0xF000
#define BIOS_EQUIPMENT_LIST 0x2C // HACK: Disable FPU for now
/*
* BIOS Data Area at 0040:XXXX
*
* See: http://webpages.charter.net/danrollins/techhelp/0093.HTM
* and: http://www.bioscentral.com/misc/bda.htm
* for more information.
*/
#pragma pack(push, 1)
typedef struct
{
WORD SerialPorts[4]; // 0x00
WORD ParallelPorts[3]; // 0x08
WORD EbdaSegment; // 0x0e - ParallelPort in PC/XT
WORD EquipmentList; // 0x10
BYTE Reserved0; // 0x12 - Errors in PCjr infrared keyboard link
WORD MemorySize; // 0x13
WORD Reserved1; // 0x15 - Scratch pad for manufacturing error tests
WORD KeybdShiftFlags; // 0x17
BYTE AlternateKeypad; // 0x19
WORD KeybdBufferHead; // 0x1a
WORD KeybdBufferTail; // 0x1c
WORD KeybdBuffer[BIOS_KBD_BUFFER_SIZE]; // 0x1e
BYTE DriveRecalibrate; // 0x3e
BYTE DriveMotorStatus; // 0x3f
BYTE MotorShutdownCounter; // 0x40
BYTE LastDisketteOperation; // 0x41
BYTE Reserved2[7]; // 0x42
BYTE VideoMode; // 0x49
WORD ScreenColumns; // 0x4a
WORD VideoPageSize; // 0x4c
WORD VideoPageOffset; // 0x4e
WORD CursorPosition[BIOS_MAX_PAGES]; // 0x50
BYTE CursorEndLine; // 0x60
BYTE CursorStartLine; // 0x61
BYTE VideoPage; // 0x62
WORD CrtBasePort; // 0x63
BYTE CrtModeControl; // 0x65
BYTE CrtColorPaletteMask; // 0x66
BYTE CassetteData[5]; // 0x67
DWORD TickCounter; // 0x6c
BYTE MidnightPassed; // 0x70
BYTE BreakFlag; // 0x71
WORD SoftReset; // 0x72
BYTE LastDiskOperation; // 0x74
BYTE NumDisks; // 0x75
BYTE DriveControlByte; // 0x76
BYTE DiskPortOffset; // 0x77
BYTE LptTimeOut[4]; // 0x78
BYTE ComTimeOut[4]; // 0x7c
WORD KeybdBufferStart; // 0x80
WORD KeybdBufferEnd; // 0x82
BYTE ScreenRows; // 0x84
WORD CharacterHeight; // 0x85
BYTE EGAFlags[2]; // 0x87
BYTE VGAFlags[2]; // 0x89
DWORD Reserved3; // 0x8b
BYTE Reserved4; // 0x8f
BYTE Reserved5[2]; // 0x90
BYTE Reserved6[2]; // 0x92
BYTE Reserved7[2]; // 0x94
WORD Reserved8; // 0x96
DWORD Reserved9; // 0x98
DWORD Reserved10; // 0x9c
DWORD Reserved11[2]; // 0xa0
DWORD EGAPtr; // 0xa8
BYTE Reserved12[68]; // 0xac
BYTE Reserved13[16]; // 0xf0
DWORD Reserved14; // 0x100
BYTE Reserved15[12]; // 0x104
BYTE Reserved16[17]; // 0x110
BYTE Reserved17[15]; // 0x121
BYTE Reserved18[3]; // 0x130
} BIOS_DATA_AREA, *PBIOS_DATA_AREA;
#pragma pack(pop)
C_ASSERT(sizeof(BIOS_DATA_AREA) == 0x133);
/* FUNCTIONS ******************************************************************/
extern PBIOS_DATA_AREA Bda;
VOID WINAPI BiosEquipmentService(LPWORD Stack);
VOID WINAPI BiosGetMemorySize(LPWORD Stack);
BOOLEAN
BiosInitialize(IN LPCSTR BiosFileName);
VOID
BiosCleanup(VOID);
#endif // _BIOS_H_
/* EOF */

View file

@ -0,0 +1,403 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: bios32.c
* PURPOSE: VDM 32-bit BIOS
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
/* INCLUDES *******************************************************************/
#define NDEBUG
#include "emulator.h"
#include "callback.h"
#include "bop.h"
#include "../bios.h"
#include "../rom.h"
#include "bios32.h"
#include "bios32p.h"
#include "kbdbios32.h"
#include "vidbios32.h"
#include "io.h"
#include "hardware/cmos.h"
#include "hardware/pic.h"
#include "hardware/timer.h"
/* PRIVATE VARIABLES **********************************************************/
CALLBACK16 BiosContext;
/* PRIVATE FUNCTIONS **********************************************************/
static VOID WINAPI BiosException(LPWORD Stack)
{
/* Get the exception number and call the emulator API */
BYTE ExceptionNumber = LOBYTE(Stack[STACK_INT_NUM]);
EmulatorException(ExceptionNumber, Stack);
}
static VOID WINAPI BiosMiscService(LPWORD Stack)
{
switch (getAH())
{
/* Wait */
case 0x86:
{
/*
* Interval in microseconds in CX:DX
* See Ralf Brown: http://www.ctyme.com/intr/rb-1525.htm
* for more information.
*/
Sleep(MAKELONG(getDX(), getCX()));
/* Clear CF */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
/* Copy Extended Memory */
case 0x87:
{
DWORD Count = (DWORD)getCX() * 2;
PFAST486_GDT_ENTRY Gdt = (PFAST486_GDT_ENTRY)SEG_OFF_TO_PTR(getES(), getSI());
DWORD SourceBase = Gdt[2].Base + (Gdt[2].BaseMid << 16) + (Gdt[2].BaseHigh << 24);
DWORD SourceLimit = Gdt[2].Limit + (Gdt[2].LimitHigh << 16);
DWORD DestBase = Gdt[3].Base + (Gdt[3].BaseMid << 16) + (Gdt[3].BaseHigh << 24);
DWORD DestLimit = Gdt[3].Limit + (Gdt[3].LimitHigh << 16);
/* Check for flags */
if (Gdt[2].Granularity) SourceLimit = (SourceLimit << 12) | 0xFFF;
if (Gdt[3].Granularity) DestLimit = (DestLimit << 12) | 0xFFF;
if ((Count > SourceLimit) || (Count > DestLimit))
{
setAX(0x80);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
/* Copy */
RtlMoveMemory((PVOID)((ULONG_PTR)BaseAddress + DestBase),
(PVOID)((ULONG_PTR)BaseAddress + SourceBase),
Count);
setAX(ERROR_SUCCESS);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
/* Get Extended Memory Size */
case 0x88:
{
UCHAR Low, High;
/*
* Return the (usable) extended memory (after 1 MB)
* size in kB from CMOS.
*/
IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_ACTUAL_EXT_MEMORY_LOW);
Low = IOReadB(CMOS_DATA_PORT);
IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_ACTUAL_EXT_MEMORY_HIGH);
High = IOReadB(CMOS_DATA_PORT);
setAX(MAKEWORD(Low, High));
/* Clear CF */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
default:
{
DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n",
getAH());
}
}
}
static VOID WINAPI BiosTimeService(LPWORD Stack)
{
switch (getAH())
{
case 0x00:
{
/* Set AL to 1 if midnight had passed, 0 otherwise */
setAL(Bda->MidnightPassed ? 0x01 : 0x00);
/* Return the tick count in CX:DX */
setCX(HIWORD(Bda->TickCounter));
setDX(LOWORD(Bda->TickCounter));
/* Reset the midnight flag */
Bda->MidnightPassed = FALSE;
break;
}
case 0x01:
{
/* Set the tick count to CX:DX */
Bda->TickCounter = MAKELONG(getDX(), getCX());
/* Reset the midnight flag */
Bda->MidnightPassed = FALSE;
break;
}
default:
{
DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n",
getAH());
}
}
}
static VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack)
{
/* Increase the system tick count */
Bda->TickCounter++;
}
// From SeaBIOS
static VOID PicSetIRQMask(USHORT off, USHORT on)
{
UCHAR pic1off = off, pic1on = on, pic2off = off>>8, pic2on = on>>8;
IOWriteB(PIC_MASTER_DATA, (IOReadB(PIC_MASTER_DATA) & ~pic1off) | pic1on);
IOWriteB(PIC_SLAVE_DATA , (IOReadB(PIC_SLAVE_DATA ) & ~pic2off) | pic2on);
}
// From SeaBIOS
VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func)
{
UCHAR vector;
PicSetIRQMask(1 << hwirq, 0);
if (hwirq < 8)
vector = BIOS_PIC_MASTER_INT + hwirq;
else
vector = BIOS_PIC_SLAVE_INT + hwirq - 8;
RegisterBiosInt32(vector, func);
}
VOID PicIRQComplete(LPWORD Stack)
{
/* Get the interrupt number */
BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]);
/*
* If this was a PIC IRQ, send an End-of-Interrupt to the PIC.
*/
if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8)
{
/* It was an IRQ from the master PIC */
IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI);
}
else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8)
{
/* It was an IRQ from the slave PIC */
IOWriteB(PIC_SLAVE_CMD , PIC_OCW2_EOI);
IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI);
}
}
static VOID WINAPI BiosHandleMasterPicIRQ(LPWORD Stack)
{
BYTE IrqNumber;
IOWriteB(PIC_MASTER_CMD, PIC_OCW3_READ_ISR /* == 0x0B */);
IrqNumber = IOReadB(PIC_MASTER_CMD);
DPRINT("Master - IrqNumber = 0x%x\n", IrqNumber);
PicIRQComplete(Stack);
}
static VOID WINAPI BiosHandleSlavePicIRQ(LPWORD Stack)
{
BYTE IrqNumber;
IOWriteB(PIC_SLAVE_CMD, PIC_OCW3_READ_ISR /* == 0x0B */);
IrqNumber = IOReadB(PIC_SLAVE_CMD);
DPRINT("Slave - IrqNumber = 0x%x\n", IrqNumber);
PicIRQComplete(Stack);
}
// Timer IRQ 0
static VOID WINAPI BiosTimerIrq(LPWORD Stack)
{
/*
* Perform the system timer interrupt.
*
* Do not call directly BiosSystemTimerInterrupt(Stack);
* because some programs may hook only BIOS_SYS_TIMER_INTERRUPT
* for their purpose...
*/
/** EmulatorInterrupt(BIOS_SYS_TIMER_INTERRUPT); **/
Int32Call(&BiosContext, BIOS_SYS_TIMER_INTERRUPT);
PicIRQComplete(Stack);
}
static VOID BiosHwSetup(VOID)
{
/* Initialize the master and the slave PICs (cascade mode) */
IOWriteB(PIC_MASTER_CMD, PIC_ICW1 | PIC_ICW1_ICW4);
IOWriteB(PIC_SLAVE_CMD , PIC_ICW1 | PIC_ICW1_ICW4);
/*
* Set the interrupt vector offsets for each PIC
* (base IRQs: 0x08-0x0F for IRQ 0-7, 0x70-0x77 for IRQ 8-15)
*/
IOWriteB(PIC_MASTER_DATA, BIOS_PIC_MASTER_INT);
IOWriteB(PIC_SLAVE_DATA , BIOS_PIC_SLAVE_INT );
/* Tell the master PIC that there is a slave PIC at IRQ 2 */
IOWriteB(PIC_MASTER_DATA, 1 << 2);
/* Tell the slave PIC its cascade identity */
IOWriteB(PIC_SLAVE_DATA , 2);
/* Make sure both PICs are in 8086 mode */
IOWriteB(PIC_MASTER_DATA, PIC_ICW4_8086);
IOWriteB(PIC_SLAVE_DATA , PIC_ICW4_8086);
/* Clear the masks for both PICs */
// IOWriteB(PIC_MASTER_DATA, 0x00);
// IOWriteB(PIC_SLAVE_DATA , 0x00);
/* Disable all IRQs */
IOWriteB(PIC_MASTER_DATA, 0xFF);
IOWriteB(PIC_SLAVE_DATA , 0xFF);
/* Initialize PIT Counter 0 */
IOWriteB(PIT_COMMAND_PORT, 0x34);
IOWriteB(PIT_DATA_PORT(0), 0x00);
IOWriteB(PIT_DATA_PORT(0), 0x00);
/* Initialize PIT Counter 1 */
IOWriteB(PIT_COMMAND_PORT, 0x74);
IOWriteB(PIT_DATA_PORT(1), 0x00);
IOWriteB(PIT_DATA_PORT(1), 0x00);
/* Initialize PIT Counter 2 */
IOWriteB(PIT_COMMAND_PORT, 0xB4);
IOWriteB(PIT_DATA_PORT(2), 0x00);
IOWriteB(PIT_DATA_PORT(2), 0x00);
EnableHwIRQ(0, BiosTimerIrq);
}
static VOID InitializeBiosInt32(VOID)
{
USHORT i;
// USHORT Offset = 0;
/* Initialize the callback context */
InitializeContext(&BiosContext, BIOS_SEGMENT, 0x0000);
/* Register the BIOS 32-bit Interrupts */
for (i = 0x00; i <= 0xFF; i++)
{
// Offset += RegisterInt32(MAKELONG(Offset, BIOS_SEGMENT), i, NULL, NULL);
BiosContext.NextOffset += RegisterInt32(MAKELONG(BiosContext.NextOffset,
BiosContext.Segment),
i, NULL, NULL);
}
/* Initialize the exception vector interrupts to a default Exception handler */
for (i = 0; i < 8; i++)
RegisterBiosInt32(i, BiosException);
/* Initialize HW vector interrupts to a default HW handler */
for (i = BIOS_PIC_MASTER_INT; i < BIOS_PIC_MASTER_INT + 8; i++)
RegisterBiosInt32(i, BiosHandleMasterPicIRQ);
for (i = BIOS_PIC_SLAVE_INT ; i < BIOS_PIC_SLAVE_INT + 8; i++)
RegisterBiosInt32(i, BiosHandleSlavePicIRQ);
/* Initialize software vector handlers */
RegisterBiosInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService );
RegisterBiosInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize );
RegisterBiosInt32(BIOS_MISC_INTERRUPT , BiosMiscService );
RegisterBiosInt32(BIOS_TIME_INTERRUPT , BiosTimeService );
RegisterBiosInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt);
/* Some interrupts are in fact addresses to tables */
((PULONG)BaseAddress)[0x1E] = (ULONG)NULL;
((PULONG)BaseAddress)[0x41] = (ULONG)NULL;
((PULONG)BaseAddress)[0x46] = (ULONG)NULL;
((PULONG)BaseAddress)[0x48] = (ULONG)NULL;
((PULONG)BaseAddress)[0x49] = (ULONG)NULL;
}
/* PUBLIC FUNCTIONS ***********************************************************/
/*
* The BIOS POST (Power On-Self Test)
*/
BOOLEAN Bios32Initialize(VOID)
{
BOOLEAN Success;
UCHAR Low, High;
/* Initialize the stack */
// That's what says IBM... (stack at 30:00FF going downwards)
// setSS(0x0000);
// setSP(0x0400);
setSS(0x0050); // Stack at 50:0400, going downwards
setSP(0x0400);
/* Set data segment */
setDS(BDA_SEGMENT);
/* Initialize the BDA contents */
Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
/*
* Retrieve the conventional memory size
* in kB from CMOS, typically 640 kB.
*/
IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_BASE_MEMORY_LOW);
Low = IOReadB(CMOS_DATA_PORT);
IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_BASE_MEMORY_HIGH);
High = IOReadB(CMOS_DATA_PORT);
Bda->MemorySize = MAKEWORD(Low, High);
/* Register the BIOS 32-bit Interrupts */
InitializeBiosInt32();
/* Initialize platform hardware (PIC/PIT chips, ...) */
BiosHwSetup();
/* Initialize the Keyboard and Video BIOS */
if (!KbdBios32Initialize() || !VidBios32Initialize()) return FALSE;
///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
/* Load some ROMs */
Success = LoadRom("boot.bin", (PVOID)0xE0000, NULL);
DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
SearchAndInitRoms(&BiosContext);
/* We are done */
return TRUE;
}
VOID Bios32Cleanup(VOID)
{
VidBios32Cleanup();
KbdBios32Cleanup();
}
/* EOF */

View file

@ -0,0 +1,32 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: bios32.h
* PURPOSE: VDM 32-bit BIOS
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
#ifndef _BIOS32_H_
#define _BIOS32_H_
/* INCLUDES *******************************************************************/
#include "ntvdm.h"
// #include "../bios.h"
/* DEFINES ********************************************************************/
// #define BIOS_EQUIPMENT_INTERRUPT 0x11
// #define BIOS_MEMORY_SIZE 0x12
// #define BIOS_MISC_INTERRUPT 0x15
// #define BIOS_TIME_INTERRUPT 0x1A
// #define BIOS_SYS_TIMER_INTERRUPT 0x1C
/* FUNCTIONS ******************************************************************/
BOOLEAN Bios32Initialize(VOID);
VOID Bios32Cleanup(VOID);
#endif // _BIOS32_H_
/* EOF */

View file

@ -0,0 +1,45 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: bios32.h
* PURPOSE: VDM 32-bit BIOS
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
#ifndef _BIOS32P_H_
#define _BIOS32P_H_
/* INCLUDES *******************************************************************/
#include "ntvdm.h"
#include "../bios.h"
/**/ #include "callback.h" /**/
/* DEFINES ********************************************************************/
#define BIOS_PIC_MASTER_INT 0x08
#define BIOS_PIC_SLAVE_INT 0x70
#define BIOS_EQUIPMENT_INTERRUPT 0x11
#define BIOS_MEMORY_SIZE 0x12
#define BIOS_MISC_INTERRUPT 0x15
#define BIOS_TIME_INTERRUPT 0x1A
#define BIOS_SYS_TIMER_INTERRUPT 0x1C
/* FUNCTIONS ******************************************************************/
extern CALLBACK16 BiosContext;
#define RegisterBiosInt32(IntNumber, IntHandler) \
do { \
BiosContext.NextOffset += RegisterInt32(MAKELONG(BiosContext.NextOffset, \
BiosContext.Segment), \
(IntNumber), (IntHandler), NULL); \
} while(0);
VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func);
VOID PicIRQComplete(LPWORD Stack);
#endif // _BIOS32P_H_
/* EOF */

View file

@ -0,0 +1,293 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: kbdbios32.c
* PURPOSE: VDM Keyboard 32-bit BIOS
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
/* INCLUDES *******************************************************************/
#define NDEBUG
#include "emulator.h"
#include "callback.h"
#include "kbdbios32.h"
#include "../kbdbios.h"
#include "bios32p.h"
#include "io.h"
#include "hardware/ps2.h"
/* PRIVATE VARIABLES **********************************************************/
static BYTE BiosKeyboardMap[256];
/* PRIVATE FUNCTIONS **********************************************************/
static BOOLEAN BiosKbdBufferPush(WORD Data)
{
/* Get the location of the element after the tail */
WORD NextElement = Bda->KeybdBufferTail + sizeof(WORD);
/* Wrap it around if it's at or beyond the end */
if (NextElement >= Bda->KeybdBufferEnd) NextElement = Bda->KeybdBufferStart;
/* If it's full, fail */
if (NextElement == Bda->KeybdBufferHead) return FALSE;
/* Put the value in the queue */
*((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferTail)) = Data;
Bda->KeybdBufferTail += sizeof(WORD);
/* Check if we are at, or have passed, the end of the buffer */
if (Bda->KeybdBufferTail >= Bda->KeybdBufferEnd)
{
/* Return it to the beginning */
Bda->KeybdBufferTail = Bda->KeybdBufferStart;
}
/* Return success */
return TRUE;
}
static BOOLEAN BiosKbdBufferTop(LPWORD Data)
{
/* If it's empty, fail */
if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE;
/* Otherwise, get the value and return success */
*Data = *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferHead));
return TRUE;
}
static BOOLEAN BiosKbdBufferPop(VOID)
{
/* If it's empty, fail */
if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE;
/* Remove the value from the queue */
Bda->KeybdBufferHead += sizeof(WORD);
/* Check if we are at, or have passed, the end of the buffer */
if (Bda->KeybdBufferHead >= Bda->KeybdBufferEnd)
{
/* Return it to the beginning */
Bda->KeybdBufferHead = Bda->KeybdBufferStart;
}
/* Return success */
return TRUE;
}
static WORD BiosPeekCharacter(VOID)
{
WORD CharacterData = 0;
/* Get the key from the queue, but don't remove it */
if (BiosKbdBufferTop(&CharacterData)) return CharacterData;
else return 0xFFFF;
}
WORD BiosGetCharacter(VOID)
{
WORD CharacterData = 0;
/* Check if there is a key available */
if (BiosKbdBufferTop(&CharacterData))
{
/* A key was available, remove it from the queue */
BiosKbdBufferPop();
}
else
{
/* No key available. Set the handler CF to repeat the BOP */
setCF(1);
// CharacterData = 0xFFFF;
}
return CharacterData;
}
static VOID WINAPI BiosKeyboardService(LPWORD Stack)
{
switch (getAH())
{
/* Wait for keystroke and read */
case 0x00:
/* Wait for extended keystroke and read */
case 0x10: // FIXME: Temporarily do the same as INT 16h, 00h
{
/* Read the character (and wait if necessary) */
setAX(BiosGetCharacter());
break;
}
/* Get keystroke status */
case 0x01:
/* Get extended keystroke status */
case 0x11: // FIXME: Temporarily do the same as INT 16h, 01h
{
WORD Data = BiosPeekCharacter();
if (Data != 0xFFFF)
{
/* There is a character, clear ZF and return it */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
setAX(Data);
}
else
{
/* No character, set ZF */
Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF;
}
break;
}
/* Get shift status */
case 0x02:
{
/* Return the lower byte of the keyboard shift status word */
setAL(LOBYTE(Bda->KeybdShiftFlags));
break;
}
/* Reserved */
case 0x04:
{
DPRINT1("BIOS Function INT 16h, AH = 0x04 is RESERVED\n");
break;
}
/* Push keystroke */
case 0x05:
{
/* Return 0 if success, 1 if failure */
setAL(BiosKbdBufferPush(getCX()) == FALSE);
break;
}
/* Get extended shift status */
case 0x12:
{
/*
* Be careful! The returned word is similar to Bda->KeybdShiftFlags
* but the high byte is organized differently:
* the bytes 2 and 3 of the high byte are not the same...
*/
WORD KeybdShiftFlags = (Bda->KeybdShiftFlags & 0xF3FF);
/* Return the extended keyboard shift status word */
setAX(KeybdShiftFlags);
break;
}
default:
{
DPRINT1("BIOS Function INT 16h, AH = 0x%02X NOT IMPLEMENTED\n",
getAH());
}
}
}
// Keyboard IRQ 1
static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
{
BYTE ScanCode, VirtualKey;
WORD Character;
/* Get the scan code and virtual key code */
ScanCode = IOReadB(PS2_DATA_PORT);
VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
/* Check if this is a key press or release */
if (!(ScanCode & (1 << 7)))
{
/* Key press */
if (VirtualKey == VK_NUMLOCK ||
VirtualKey == VK_CAPITAL ||
VirtualKey == VK_SCROLL ||
VirtualKey == VK_INSERT)
{
/* For toggle keys, toggle the lowest bit in the keyboard map */
BiosKeyboardMap[VirtualKey] ^= ~(1 << 0);
}
/* Set the highest bit */
BiosKeyboardMap[VirtualKey] |= (1 << 7);
/* Find out which character this is */
Character = 0;
if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0)
{
/* Not ASCII */
Character = 0;
}
/* Push it onto the BIOS keyboard queue */
BiosKbdBufferPush(MAKEWORD(Character, ScanCode));
}
else
{
/* Key release, unset the highest bit */
BiosKeyboardMap[VirtualKey] &= ~(1 << 7);
}
/* Clear the keyboard flags */
Bda->KeybdShiftFlags = 0;
/* Set the appropriate flags based on the state */
if (BiosKeyboardMap[VK_RSHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RSHIFT;
if (BiosKeyboardMap[VK_LSHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LSHIFT;
if (BiosKeyboardMap[VK_CONTROL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CTRL;
if (BiosKeyboardMap[VK_MENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_ALT;
if (BiosKeyboardMap[VK_SCROLL] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL_ON;
if (BiosKeyboardMap[VK_NUMLOCK] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK_ON;
if (BiosKeyboardMap[VK_CAPITAL] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK_ON;
if (BiosKeyboardMap[VK_INSERT] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT_ON;
if (BiosKeyboardMap[VK_RMENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RALT;
if (BiosKeyboardMap[VK_LMENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LALT;
if (BiosKeyboardMap[VK_SNAPSHOT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SYSRQ;
if (BiosKeyboardMap[VK_PAUSE] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_PAUSE;
if (BiosKeyboardMap[VK_SCROLL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL;
if (BiosKeyboardMap[VK_NUMLOCK] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK;
if (BiosKeyboardMap[VK_CAPITAL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK;
if (BiosKeyboardMap[VK_INSERT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT;
PicIRQComplete(Stack);
}
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN KbdBios32Initialize(VOID)
{
/* Initialize the common Keyboard BIOS Support Library */
if (!KbdBiosInitialize()) return FALSE;
/* Initialize the BDA */
Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer);
Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD);
Bda->KeybdBufferHead = Bda->KeybdBufferTail = 0;
/* Register the BIOS 32-bit Interrupts */
/* Initialize software vector handlers */
RegisterBiosInt32(BIOS_KBD_INTERRUPT, BiosKeyboardService);
/* Set up the HW vector interrupts */
EnableHwIRQ(1, BiosKeyboardIrq);
// EnableHwIRQ(12, BiosMouseIrq);
return TRUE;
}
VOID KbdBios32Cleanup(VOID)
{
/* Cleanup the common Keyboard BIOS Support Library */
KbdBiosCleanup();
}
/* EOF */

View file

@ -0,0 +1,46 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: kbdbios32.h
* PURPOSE: VDM Keyboard 32-bit BIOS
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
#ifndef _KBDBIOS32_H_
#define _KBDBIOS32_H_
/* INCLUDES *******************************************************************/
#include "ntvdm.h"
/* DEFINES ********************************************************************/
// #define BIOS_KBD_INTERRUPT 0x16
#define BIOS_KBD_BUFFER_SIZE 16
#define BDA_KBDFLAG_RSHIFT (1 << 0)
#define BDA_KBDFLAG_LSHIFT (1 << 1)
#define BDA_KBDFLAG_CTRL (1 << 2)
#define BDA_KBDFLAG_ALT (1 << 3)
#define BDA_KBDFLAG_SCROLL_ON (1 << 4)
#define BDA_KBDFLAG_NUMLOCK_ON (1 << 5)
#define BDA_KBDFLAG_CAPSLOCK_ON (1 << 6)
#define BDA_KBDFLAG_INSERT_ON (1 << 7)
#define BDA_KBDFLAG_RALT (1 << 8)
#define BDA_KBDFLAG_LALT (1 << 9)
#define BDA_KBDFLAG_SYSRQ (1 << 10)
#define BDA_KBDFLAG_PAUSE (1 << 11)
#define BDA_KBDFLAG_SCROLL (1 << 12)
#define BDA_KBDFLAG_NUMLOCK (1 << 13)
#define BDA_KBDFLAG_CAPSLOCK (1 << 14)
#define BDA_KBDFLAG_INSERT (1 << 15)
/* FUNCTIONS ******************************************************************/
BOOLEAN KbdBios32Initialize(VOID);
VOID KbdBios32Cleanup(VOID);
#endif // _KBDBIOS32_H_
/* EOF */

View file

@ -0,0 +1,41 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: vidbios32.c
* PURPOSE: VDM Video 32-bit BIOS
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*
* NOTE: All of the real code is in bios/vidbios.c
*/
/* INCLUDES *******************************************************************/
#define NDEBUG
#include "emulator.h"
#include "callback.h"
#include "vidbios32.h"
#include "../vidbios.h"
#include "bios32p.h"
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN VidBios32Initialize(VOID)
{
/* Initialize the common Video BIOS Support Library */
if (!VidBiosInitialize()) return FALSE;
/* Register the BIOS 32-bit Interrupts */
RegisterBiosInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService);
return TRUE;
}
VOID VidBios32Cleanup(VOID)
{
/* Cleanup the common Video BIOS Support Library */
VidBiosCleanup();
}
/* EOF */

View file

@ -0,0 +1,29 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: vidbios32.h
* PURPOSE: VDM Video 32-bit BIOS
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*
* NOTE: All of the real code is in bios/vidbios.c
*/
#ifndef _VIDBIOS32_H_
#define _VIDBIOS32_H_
/* INCLUDES *******************************************************************/
#include "ntvdm.h"
/* DEFINES ********************************************************************/
// #define BIOS_VIDEO_INTERRUPT 0x10
/* FUNCTIONS ******************************************************************/
BOOLEAN VidBios32Initialize(VOID);
VOID VidBios32Cleanup(VOID);
#endif // _VIDBIOS32_H_
/* EOF */

View file

@ -0,0 +1,51 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: kbdbios.c
* PURPOSE: VDM Keyboard BIOS Support Library
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *******************************************************************/
#define NDEBUG
#include "emulator.h"
#include "callback.h"
#include "bop.h"
#include "bios.h"
// #include "kbdbios.h"
/* DEFINES ********************************************************************/
/* BOP Identifiers */
#define BOP_KBD_IRQ 0x09
#define BOP_KBD_INT 0x16
/* PUBLIC FUNCTIONS ***********************************************************/
static VOID WINAPI KbdBiosIRQ(LPWORD Stack)
{
DPRINT1("KbdBiosIRQ is UNIMPLEMENTED\n");
}
static VOID WINAPI KbdBiosINT(LPWORD Stack)
{
DPRINT1("KbdBiosINT is UNIMPLEMENTED\n");
}
BOOLEAN KbdBiosInitialize(VOID)
{
/* Register the BIOS support BOPs */
RegisterBop(BOP_KBD_IRQ, KbdBiosIRQ);
RegisterBop(BOP_KBD_INT, KbdBiosINT);
return TRUE;
}
VOID KbdBiosCleanup(VOID)
{
}
/* EOF */

View file

@ -0,0 +1,31 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: kbdbios.h
* PURPOSE: VDM Keyboard BIOS Support Library
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
#ifndef _KBDBIOS_H_
#define _KBDBIOS_H_
/* INCLUDES *******************************************************************/
#include "ntvdm.h"
/* DEFINES ********************************************************************/
#define BIOS_KBD_INTERRUPT 0x16
#define BIOS_KBD_BUFFER_SIZE 16
/* FUNCTIONS ******************************************************************/
WORD BiosGetCharacter(VOID);
BOOLEAN KbdBiosInitialize(VOID);
VOID KbdBiosCleanup(VOID);
#endif // _KBDBIOS_H_
/* EOF */

227
subsystems/ntvdm/bios/rom.c Normal file
View file

@ -0,0 +1,227 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: rom.c
* PURPOSE: ROM Support Functions
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *******************************************************************/
#define NDEBUG
#include "emulator.h"
#include "callback.h"
#include "utils.h"
#include "rom.h"
/* PRIVATE FUNCTIONS **********************************************************/
static HANDLE
OpenRomFile(IN PCSTR RomFileName,
OUT PULONG RomSize OPTIONAL)
{
HANDLE hRomFile;
ULONG ulRomSize = 0;
/* Open the ROM image file */
hRomFile = FileOpen(RomFileName, &ulRomSize);
/* If we failed, bail out */
if (hRomFile == NULL) return NULL;
/*
* The size of the ROM image file is at most 256kB. For instance,
* the SeaBIOS image, which includes also expansion ROMs inside it,
* covers the range C000:0000 to F000:FFFF .
*/
if (ulRomSize > 0x40000)
{
/* We failed, bail out */
DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)", ulRomSize);
FileClose(hRomFile);
return NULL;
}
/* Success, return file handle and size if needed */
if (RomSize) *RomSize = ulRomSize;
return hRomFile;
}
static BOOLEAN
LoadRomFileByHandle(IN HANDLE RomFileHandle,
IN PVOID RomLocation,
IN ULONG RomSize,
OUT PULONG BytesRead)
{
/*
* The size of the ROM image file is at most 256kB. For instance,
* the SeaBIOS image, which includes also expansion ROMs inside it,
* covers the range C000:0000 to F000:FFFF .
*/
if (RomSize > 0x40000)
{
DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)", RomSize);
return FALSE;
}
/* Attempt to load the ROM image file into memory */
return FileLoadByHandle(RomFileHandle,
REAL_TO_PHYS(RomLocation),
RomSize,
BytesRead);
}
static UCHAR
ComputeChecksum(IN ULONG RomLocation,
IN ULONG RomSize)
{
ULONG RomLastAddress = RomLocation + RomSize;
UCHAR Sum = 0x00; // Using a UCHAR guarantees that we wrap at 0xFF i.e. we do a sum modulo 0x100.
while (RomLocation < RomLastAddress)
{
Sum += *(PUCHAR)REAL_TO_PHYS(RomLocation);
++RomLocation;
}
return Sum;
}
static VOID
InitRomRange(IN PCALLBACK16 Context,
IN ULONG Start,
IN ULONG End,
IN ULONG Increment)
{
ULONG Address, AddressBoot;
ULONG RomSize;
UCHAR Checksum;
for (Address = Start; Address < End; Address += Increment)
{
/* Does the ROM have a valid signature? */
if (*(PUSHORT)REAL_TO_PHYS(Address) == OPTION_ROM_SIGNATURE)
{
/* Check the control sum of the ROM */
/*
* If this is an adapter ROM (Start: C8000, End: E0000), its
* reported size is stored in byte 2 of the ROM.
*
* If this is an expansion ROM (Start: E0000, End: F0000),
* its real length is 64kB.
*/
RomSize = *(PUCHAR)REAL_TO_PHYS(Address + 2) * 512;
if (Address >= 0xE0000) RomSize = 0x10000;
Checksum = ComputeChecksum(Address, RomSize);
if (Checksum == 0x00)
{
AddressBoot = Address + 3;
DPRINT1("Going to run @ address 0x%p\n", AddressBoot);
AddressBoot = MAKELONG((AddressBoot & 0xFFFF), (AddressBoot & 0xF0000) >> 4);
// setDS((Address & 0xF0000) >> 4);
setDS((Address & 0xFF000) >> 4);
RunCallback16(Context, AddressBoot);
// Call16((AddressBoot & 0xF0000) >> 4, (AddressBoot & 0xFFFF));
DPRINT1("Rom @ address 0x%p initialized\n", Address);
}
else
{
DPRINT1("Rom @ address 0x%p has invalid checksum of 0x%02x\n", Address, Checksum);
}
}
}
}
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN
LoadBios(IN PCSTR BiosFileName,
OUT PVOID* BiosLocation OPTIONAL,
OUT PULONG BiosSize OPTIONAL)
{
BOOLEAN Success;
HANDLE hBiosFile;
ULONG ulBiosSize = 0;
PVOID pBiosLocation;
/* Open the BIOS image file */
hBiosFile = OpenRomFile(BiosFileName, &ulBiosSize);
/* If we failed, bail out */
if (hBiosFile == NULL) return FALSE;
/* BIOS location needs to be aligned on 32-bit boundary */
// (PVOID)((ULONG_PTR)BaseAddress + ROM_AREA_END + 1 - ulBiosSize)
pBiosLocation = MEM_ALIGN_DOWN(TO_LINEAR(0xF000, 0xFFFF) + 1 - ulBiosSize, sizeof(ULONG));
/* Attempt to load the BIOS image file into memory */
Success = LoadRomFileByHandle(hBiosFile,
pBiosLocation,
ulBiosSize,
&ulBiosSize);
DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
/* Close the BIOS image file */
FileClose(hBiosFile);
/* In case of success, return BIOS location and size if needed */
if (Success)
{
if (BiosLocation) *BiosLocation = pBiosLocation;
if (BiosSize) *BiosSize = ulBiosSize;
}
return Success;
}
BOOLEAN
LoadRom(IN PCSTR RomFileName,
IN PVOID RomLocation,
OUT PULONG RomSize OPTIONAL)
{
BOOLEAN Success;
HANDLE hRomFile;
ULONG ulRomSize = 0;
/* Open the ROM image file */
hRomFile = OpenRomFile(RomFileName, &ulRomSize);
/* If we failed, bail out */
if (hRomFile == NULL) return FALSE;
/* Attempt to load the ROM image file into memory */
Success = LoadRomFileByHandle(hRomFile,
RomLocation,
ulRomSize,
&ulRomSize);
DPRINT1("ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
/* Close the ROM image file and return */
FileClose(hRomFile);
/* In case of success, return ROM size if needed */
if (Success)
{
if (RomSize) *RomSize = ulRomSize;
}
return Success;
}
VOID
SearchAndInitRoms(IN PCALLBACK16 Context)
{
/* Adapters ROMs -- Start: C8000, End: E0000, 2kB blocks */
InitRomRange(Context, 0xC8000, 0xE0000, 0x0800);
/* Expansion ROM -- Start: E0000, End: F0000, 64kB block */
InitRomRange(Context, 0xE0000, 0xEFFFF, 0x10000);
}
/* EOF */

View file

@ -0,0 +1,40 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: rom.h
* PURPOSE: ROM Support Functions
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
#ifndef _ROM_H_
#define _ROM_H_
/* INCLUDES *******************************************************************/
#include "ntvdm.h"
/* DEFINES ********************************************************************/
#define ROM_AREA_START 0xE0000
#define ROM_AREA_END 0xFFFFF
#define OPTION_ROM_SIGNATURE 0xAA55
/* FUNCTIONS ******************************************************************/
BOOLEAN
LoadBios(IN PCSTR BiosFileName,
OUT PVOID* BiosLocation OPTIONAL,
OUT PULONG BiosSize OPTIONAL);
BOOLEAN
LoadRom(IN PCSTR RomFileName,
IN PVOID RomLocation,
OUT PULONG RomSize OPTIONAL);
VOID
SearchAndInitRoms(IN PCALLBACK16 Context);
#endif // _ROM_H_
/* EOF */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,49 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: vidbios.h
* PURPOSE: VDM Video BIOS Support Library
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
#ifndef _VIDBIOS_H_
#define _VIDBIOS_H_
/* INCLUDES *******************************************************************/
#include "ntvdm.h"
/* DEFINES ********************************************************************/
#define BIOS_VIDEO_INTERRUPT 0x10
#define CONSOLE_FONT_HEIGHT 8
#define BIOS_DEFAULT_VIDEO_MODE 0x03
#define BIOS_MAX_PAGES 8
#define BIOS_MAX_VIDEO_MODE 0x13
#define DEFAULT_ATTRIBUTE 0x07
#define GRAPHICS_VIDEO_SEG 0xA000
#define TEXT_VIDEO_SEG 0xB800
enum
{
SCROLL_DIRECTION_UP,
SCROLL_DIRECTION_DOWN,
SCROLL_DIRECTION_LEFT,
SCROLL_DIRECTION_RIGHT
};
/* FUNCTIONS ******************************************************************/
VOID WINAPI VidBiosVideoService(LPWORD Stack);
VOID VidBiosSyncCursorPosition(VOID);
BOOLEAN VidBiosInitialize(VOID);
VOID VidBiosCleanup(VOID);
#endif // _VIDBIOS_H_
/* EOF */

50
subsystems/ntvdm/bop.c Normal file
View file

@ -0,0 +1,50 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: bop.c
* PURPOSE: BIOS Operation Handlers
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *******************************************************************/
// #define NDEBUG
#include "emulator.h"
#include "bop.h"
/* PRIVATE VARIABLES **********************************************************/
/*
* This is the list of registered BOP handlers.
*/
EMULATOR_BOP_PROC BopProc[EMULATOR_MAX_BOP_NUM] = { NULL };
/* PUBLIC FUNCTIONS ***********************************************************/
VOID RegisterBop(BYTE BopCode, EMULATOR_BOP_PROC BopHandler)
{
BopProc[BopCode] = BopHandler;
}
VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode)
{
WORD StackSegment, StackPointer;
LPWORD Stack;
/* Get the SS:SP */
StackSegment = State->SegmentRegs[FAST486_REG_SS].Selector;
StackPointer = State->GeneralRegs[FAST486_REG_ESP].LowWord;
/* Get the stack */
Stack = (LPWORD)SEG_OFF_TO_PTR(StackSegment, StackPointer);
/* Call the BOP handler */
if (BopProc[BopCode] != NULL)
BopProc[BopCode](Stack);
else
DPRINT("Invalid BOP code: 0x%02X\n", BopCode);
}
/* EOF */

28
subsystems/ntvdm/bop.h Normal file
View file

@ -0,0 +1,28 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: bop.h
* PURPOSE: BIOS Operation Handlers
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
#ifndef _BOP_H_
#define _BOP_H_
/* DEFINES ********************************************************************/
/* BOP Identifiers */
#define EMULATOR_BOP 0xC4C4
#define EMULATOR_MAX_BOP_NUM 0xFF + 1
/* FUNCTIONS ******************************************************************/
typedef VOID (WINAPI *EMULATOR_BOP_PROC)(LPWORD Stack);
VOID RegisterBop(BYTE BopCode, EMULATOR_BOP_PROC BopHandler);
VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode);
#endif // _BOP_H_
/* EOF */

293
subsystems/ntvdm/callback.c Normal file
View file

@ -0,0 +1,293 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: callback.c
* PURPOSE: 16 and 32-bit Callbacks Support
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *******************************************************************/
#define NDEBUG
#include "emulator.h"
#include "callback.h"
#include "bop.h"
#include <isvbop.h>
/* PRIVATE VARIABLES **********************************************************/
/*
* This is the list of registered 32-bit Interrupt handlers.
*/
EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT32_NUM] = { NULL };
/* BOP Identifiers */
#define BOP_CONTROL 0xFF // Control BOP Handler
#define BOP_CONTROL_DEFFUNC 0x00 // Default Control BOP Function
/* 32-bit Interrupt dispatcher function code for the Control BOP Handler */
#define BOP_CONTROL_INT32 0xFF
#define BOP(num) LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), (num)
#define UnSimulate16(trap) \
do { \
*(PUSHORT)(trap) = EMULATOR_BOP; \
(trap) += sizeof(USHORT); \
*(trap) = BOP_UNSIMULATE; \
} while(0)
// #define UnSimulate16 MAKELONG(EMULATOR_BOP, BOP_UNSIMULATE) // BOP(BOP_UNSIMULATE)
#define CALL16_TRAMPOLINE_SIZE (1 * sizeof(ULONGLONG))
#define INT16_TRAMPOLINE_SIZE (1 * sizeof(ULONGLONG))
/* 16-bit generic interrupt code for calling a 32-bit interrupt handler */
BYTE Int16To32[] =
{
0xFA, // cli
/* Push the value of the interrupt to be called */
0x6A, 0xFF, // push i (patchable to 0x6A, 0xIntNum)
/* The counter variable (initialized to 0) */
0x6A, 0x00, // push 0
/* Stack variables */
0x83, 0xEC, 0x04, // sub sp, 4
/* The BOP Sequence */
// BOP_SEQ:
0xF8, // clc
BOP(BOP_CONTROL), // Control BOP
BOP_CONTROL_INT32, // 32-bit Interrupt dispatcher
0x73, 0x04, // jnc EXIT (offset +4)
0xFB, // sti
// HACK: The following instruction should be HLT!
0x90, // nop
0xEB, 0xF5, // jmp BOP_SEQ (offset -11)
// EXIT:
0x83, 0xC4, 0x08, // add sp, 8
0xCF, // iret
};
/* PUBLIC FUNCTIONS ***********************************************************/
VOID
InitializeContext(IN PCALLBACK16 Context,
IN USHORT Segment,
IN USHORT Offset)
{
Context->TrampolineFarPtr = MAKELONG(Offset, Segment);
Context->Segment = Segment;
Context->NextOffset = Offset + max(CALL16_TRAMPOLINE_SIZE,
INT16_TRAMPOLINE_SIZE);
}
VOID
Call16(IN USHORT Segment,
IN USHORT Offset)
{
/* Save CS:IP */
USHORT OrgCS = getCS();
USHORT OrgIP = getIP();
/* Set the new CS:IP */
setCS(Segment);
setIP(Offset);
DPRINT("Call16(%04X:%04X)\n", Segment, Offset);
/* Start CPU simulation */
EmulatorSimulate();
/* Restore CS:IP */
setCS(OrgCS);
setIP(OrgIP);
}
ULONG
RegisterCallback16(IN ULONG FarPtr,
IN LPBYTE CallbackCode,
IN SIZE_T CallbackSize,
OUT PSIZE_T CodeSize OPTIONAL)
{
LPBYTE CodeStart = (LPBYTE)FAR_POINTER(FarPtr);
LPBYTE Code = CodeStart;
SIZE_T OurCodeSize = CallbackSize;
if (CallbackCode == NULL) CallbackSize = 0;
if (CallbackCode)
{
/* 16-bit interrupt code */
RtlCopyMemory(Code, CallbackCode, CallbackSize);
Code += CallbackSize;
}
/* Return the real size of the code if needed */
if (CodeSize) *CodeSize = OurCodeSize; // == (ULONG_PTR)Code - (ULONG_PTR)CodeStart;
// /* Return the entry-point address for 32-bit calls */
// return (ULONG_PTR)(CodeStart + CallbackSize);
return OurCodeSize;
}
VOID
RunCallback16(IN PCALLBACK16 Context,
IN ULONG FarPtr)
{
PUCHAR TrampolineBase = (PUCHAR)FAR_POINTER(Context->TrampolineFarPtr);
PUCHAR Trampoline = TrampolineBase;
UCHAR OldTrampoline[CALL16_TRAMPOLINE_SIZE];
/* Save the old trampoline */
((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0];
DPRINT1("RunCallback16(0x%p)\n", FarPtr);
/* Build the generic entry-point for 16-bit far calls */
*Trampoline++ = 0x9A; // Call far seg:off
*(PULONG)Trampoline = FarPtr;
Trampoline += sizeof(ULONG);
UnSimulate16(Trampoline);
/* Perform the call */
Call16(HIWORD(Context->TrampolineFarPtr),
LOWORD(Context->TrampolineFarPtr));
/* Restore the old trampoline */
((PULONGLONG)TrampolineBase)[0] = ((PULONGLONG)&OldTrampoline)[0];
}
ULONG
RegisterInt16(IN ULONG FarPtr,
IN BYTE IntNumber,
IN LPBYTE CallbackCode,
IN SIZE_T CallbackSize,
OUT PSIZE_T CodeSize OPTIONAL)
{
/* Get a pointer to the IVT and set the corresponding entry (far pointer) */
LPDWORD IntVecTable = (LPDWORD)SEG_OFF_TO_PTR(0x0000, 0x0000);
IntVecTable[IntNumber] = FarPtr;
/* Register the 16-bit callback */
return RegisterCallback16(FarPtr,
CallbackCode,
CallbackSize,
CodeSize);
}
ULONG
RegisterInt32(IN ULONG FarPtr,
IN BYTE IntNumber,
IN EMULATOR_INT32_PROC IntHandler,
OUT PSIZE_T CodeSize OPTIONAL)
{
/* Array for holding our copy of the 16-bit interrupt callback */
BYTE IntCallback[sizeof(Int16To32)/sizeof(BYTE)];
/* Check whether the 32-bit interrupt was already registered */
// if (Int32Proc[IntNumber] != NULL)
// {
// DPRINT1("RegisterInt32: Interrupt 0x%X already registered!\n", IntNumber);
// return 0;
// }
/* Register the 32-bit interrupt handler */
Int32Proc[IntNumber] = IntHandler;
/* Copy the generic 16-bit interrupt callback and patch it */
RtlCopyMemory(IntCallback, Int16To32, sizeof(Int16To32));
IntCallback[2] = IntNumber;
/* Register the 16-bit interrupt callback */
return RegisterInt16(FarPtr,
IntNumber,
IntCallback,
sizeof(IntCallback),
CodeSize);
}
VOID
Int32Call(IN PCALLBACK16 Context,
IN BYTE IntNumber)
{
PUCHAR TrampolineBase = (PUCHAR)FAR_POINTER(Context->TrampolineFarPtr);
PUCHAR Trampoline = TrampolineBase;
UCHAR OldTrampoline[INT16_TRAMPOLINE_SIZE];
DPRINT("Int32Call(0x%X)\n", IntNumber);
/* Save the old trampoline */
((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0];
/* Build the generic entry-point for 16-bit calls */
if (IntNumber == 0x03)
{
/* We are redefining for INT 03h */
*Trampoline++ = 0xCC; // Call INT 03h
/** *Trampoline++ = 0x90; // nop **/
}
else
{
/* Normal interrupt */
*Trampoline++ = 0xCD; // Call INT XXh
*Trampoline++ = IntNumber;
}
UnSimulate16(Trampoline);
/* Perform the call */
Call16(HIWORD(Context->TrampolineFarPtr),
LOWORD(Context->TrampolineFarPtr));
/* Restore the old trampoline */
((PULONGLONG)TrampolineBase)[0] = ((PULONGLONG)&OldTrampoline)[0];
}
VOID WINAPI Int32Dispatch(LPWORD Stack)
{
/* Get the interrupt number */
BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]);
/* Call the 32-bit Interrupt handler */
if (Int32Proc[IntNum] != NULL)
Int32Proc[IntNum](Stack);
else
DPRINT1("Unhandled 32-bit interrupt: 0x%02X, AX = 0x%04X\n", IntNum, getAX());
}
static VOID WINAPI ControlBop(LPWORD Stack)
{
/* Get the Function Number and skip it */
BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
setIP(getIP() + 1);
if (FuncNum == BOP_CONTROL_INT32)
Int32Dispatch(Stack);
else
// DPRINT1("Unassigned Control BOP Function: 0x%02X\n", FuncNum);
DisplayMessage(L"Unassigned Control BOP Function: 0x%02X\n", FuncNum);
}
VOID InitializeCallbacks(VOID)
{
/* Register the Control BOP */
RegisterBop(BOP_CONTROL, ControlBop);
}
/* EOF */

View file

@ -0,0 +1,75 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: callback.h
* PURPOSE: 32-bit Interrupt Handlers
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
#ifndef _CALLBACK_H_
#define _CALLBACK_H_
/* DEFINES ********************************************************************/
/* 32-bit Interrupt Identifiers */
#define EMULATOR_MAX_INT32_NUM 0xFF + 1
#define INT_HANDLER_OFFSET 0x1000
#define COMMON_STUB_OFFSET 0x2000
typedef struct _CALLBACK16
{
ULONG TrampolineFarPtr; // Where the trampoline zone is placed
USHORT Segment;
USHORT NextOffset;
} CALLBACK16, *PCALLBACK16;
/* FUNCTIONS ******************************************************************/
typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack);
VOID
InitializeContext(IN PCALLBACK16 Context,
IN USHORT Segment,
IN USHORT Offset);
VOID
Call16(IN USHORT Segment,
IN USHORT Offset);
ULONG
RegisterCallback16(IN ULONG FarPtr,
IN LPBYTE CallbackCode,
IN SIZE_T CallbackSize,
OUT PSIZE_T CodeSize OPTIONAL);
VOID
RunCallback16(IN PCALLBACK16 Context,
IN ULONG FarPtr);
ULONG
RegisterInt16(IN ULONG FarPtr,
IN BYTE IntNumber,
IN LPBYTE CallbackCode,
IN SIZE_T CallbackSize,
OUT PSIZE_T CodeSize OPTIONAL);
ULONG
RegisterInt32(IN ULONG FarPtr,
IN BYTE IntNumber,
IN EMULATOR_INT32_PROC IntHandler,
OUT PSIZE_T CodeSize OPTIONAL);
VOID
Int32Call(IN PCALLBACK16 Context,
IN BYTE IntNumber);
VOID WINAPI Int32Dispatch(LPWORD Stack);
VOID InitializeCallbacks(VOID);
#endif // _CALLBACK_H_
/* EOF */

173
subsystems/ntvdm/clock.c Normal file
View file

@ -0,0 +1,173 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: clock.c
* PURPOSE: Clock for VDM
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *******************************************************************/
#define NDEBUG
#include "emulator.h"
// #include "clock.h"
#include "hardware/cmos.h"
#include "hardware/ps2.h"
#include "hardware/timer.h"
#include "hardware/vga.h"
/* DEFINES ********************************************************************/
/*
* Activate IPS_DISPLAY if you want to display the
* number of instructions per second, as well as
* the computed number of ticks for the PIT.
*/
// #define IPS_DISPLAY
/*
* Activate WORKING_TIMER when the PIT timing problem is fixed.
*/
// #define WORKING_TIMER
/* Processor speed */
#define STEPS_PER_CYCLE 256
#define KBD_INT_CYCLES 16
/* VARIABLES ******************************************************************/
LARGE_INTEGER StartPerfCount, Frequency;
LARGE_INTEGER LastTimerTick, LastRtcTick, Counter;
LONGLONG TimerTicks;
DWORD StartTickCount, CurrentTickCount;
DWORD LastClockUpdate;
DWORD LastVerticalRefresh;
INT KeyboardIntCounter = 0;
#ifdef IPS_DISPLAY
DWORD LastCyclePrintout;
DWORD Cycles = 0;
#endif
/* PUBLIC FUNCTIONS ***********************************************************/
VOID ClockUpdate(VOID)
{
extern BOOLEAN CpuSimulate;
UINT i;
#ifdef WORKING_TIMER
DWORD PitResolution = PitGetResolution();
#endif
DWORD RtcFrequency = RtcGetTicksPerSecond();
/* Get the current number of ticks */
CurrentTickCount = GetTickCount();
#ifdef WORKING_TIMER
if ((PitResolution <= 1000) && (RtcFrequency <= 1000))
{
/* Calculate the approximate performance counter value instead */
Counter.QuadPart = StartPerfCount.QuadPart
+ (CurrentTickCount - StartTickCount)
* (Frequency.QuadPart / 1000);
}
else
#endif
{
/* Get the current performance counter value */
QueryPerformanceCounter(&Counter);
}
/* Get the number of PIT ticks that have passed */
TimerTicks = ((Counter.QuadPart - LastTimerTick.QuadPart)
* PIT_BASE_FREQUENCY) / Frequency.QuadPart;
/* Update the PIT */
if (TimerTicks > 0)
{
PitClock(TimerTicks);
LastTimerTick = Counter;
}
/* Check for RTC update */
if ((CurrentTickCount - LastClockUpdate) >= 1000)
{
RtcTimeUpdate();
LastClockUpdate = CurrentTickCount;
}
/* Check for RTC periodic tick */
if ((Counter.QuadPart - LastRtcTick.QuadPart)
>= (Frequency.QuadPart / (LONGLONG)RtcFrequency))
{
RtcPeriodicTick();
LastRtcTick = Counter;
}
/* Check for vertical retrace */
if ((CurrentTickCount - LastVerticalRefresh) >= 15)
{
VgaRefreshDisplay();
LastVerticalRefresh = CurrentTickCount;
}
if (++KeyboardIntCounter == KBD_INT_CYCLES)
{
GenerateKeyboardInterrupts();
KeyboardIntCounter = 0;
}
/* Horizontal retrace occurs as fast as possible */
VgaHorizontalRetrace();
/* Continue CPU emulation */
for (i = 0; VdmRunning && CpuSimulate && (i < STEPS_PER_CYCLE); i++)
{
EmulatorStep();
#ifdef IPS_DISPLAY
Cycles++;
#endif
}
#ifdef IPS_DISPLAY
if ((CurrentTickCount - LastCyclePrintout) >= 1000)
{
DPRINT1("NTVDM: %lu Instructions Per Second; TimerTicks = %I64d\n", Cycles, TimerTicks);
LastCyclePrintout = CurrentTickCount;
Cycles = 0;
}
#endif
}
BOOLEAN ClockInitialize(VOID)
{
/* Initialize the performance counter (needed for hardware timers) */
if (!QueryPerformanceFrequency(&Frequency))
{
wprintf(L"FATAL: Performance counter not available\n");
return FALSE;
}
/* Find the starting performance and tick count */
StartTickCount = GetTickCount();
QueryPerformanceCounter(&StartPerfCount);
/* Set the different last counts to the starting count */
LastClockUpdate = LastVerticalRefresh =
#ifdef IPS_DISPLAY
LastCyclePrintout =
#endif
StartTickCount;
/* Set the last timer ticks to the current time */
LastTimerTick = LastRtcTick = StartPerfCount;
return TRUE;
}

Some files were not shown because too many files have changed in this diff Show more