mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 07:53:07 +00:00
[NTVDM]
Implement basic DOS country info (some stuff is not implemented yet, but the basic functionality is there). This is needed by Microsoft Diagnostics 2.0+ (amongst others)... See also r66039. CORE-9903 #resolve svn path=/trunk/; revision=68363
This commit is contained in:
parent
cf5ce092b5
commit
4a2b05ae84
5 changed files with 488 additions and 56 deletions
|
@ -30,6 +30,7 @@ list(APPEND SOURCE
|
||||||
hardware/video/svga.c
|
hardware/video/svga.c
|
||||||
dos/dos32krnl/bios.c
|
dos/dos32krnl/bios.c
|
||||||
dos/dos32krnl/condrv.c
|
dos/dos32krnl/condrv.c
|
||||||
|
dos/dos32krnl/country.c
|
||||||
dos/dos32krnl/device.c
|
dos/dos32krnl/device.c
|
||||||
dos/dos32krnl/dos.c
|
dos/dos32krnl/dos.c
|
||||||
dos/dos32krnl/dosfiles.c
|
dos/dos32krnl/dosfiles.c
|
||||||
|
|
289
reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/country.c
Normal file
289
reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/country.c
Normal file
|
@ -0,0 +1,289 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: GPL - See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Virtual DOS Machine
|
||||||
|
* FILE: dos/dos32krnl/country.c
|
||||||
|
* PURPOSE: DOS32 Country support
|
||||||
|
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
||||||
|
*
|
||||||
|
* NOTE: Support for default (english) language only.
|
||||||
|
* For other languages, please use COUNTRY.SYS
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
|
||||||
|
#include "ntvdm.h"
|
||||||
|
#include "emulator.h"
|
||||||
|
|
||||||
|
#include "country.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
/* PRIVATE VARIABLES **********************************************************/
|
||||||
|
|
||||||
|
/* CaseMap routine: should call INT 65h, AL=20h */
|
||||||
|
// ATM, just do nothing.
|
||||||
|
static const BYTE CaseMapRoutine[] =
|
||||||
|
{
|
||||||
|
0xCB // retf
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
#define DATATABLE(name, type, len) \
|
||||||
|
typedef struct _##name \
|
||||||
|
{ \
|
||||||
|
WORD Size; \
|
||||||
|
type Data[(len)]; \
|
||||||
|
} name
|
||||||
|
|
||||||
|
DATATABLE(UPPERCASE, CHAR, 0xFF-0x80+1);
|
||||||
|
DATATABLE(LOWERCASE, CHAR, 0xFF-0x00+1);
|
||||||
|
DATATABLE(FNAMETERM, BYTE, 22);
|
||||||
|
DATATABLE(COLLATE , BYTE, 0xFF-0x00+1);
|
||||||
|
DATATABLE(DBCSLEAD , WORD, 0x00+1);
|
||||||
|
|
||||||
|
typedef struct _COUNTRY_DATA
|
||||||
|
{
|
||||||
|
BYTE CaseMapRoutine[sizeof(CaseMapRoutine)];
|
||||||
|
UPPERCASE UpCaseTbl; // Used also for filename uppercase
|
||||||
|
LOWERCASE LoCaseTbl;
|
||||||
|
FNAMETERM FNameTermTbl;
|
||||||
|
COLLATE CollateTbl;
|
||||||
|
DBCSLEAD DBCSLeadTbl;
|
||||||
|
} COUNTRY_DATA, *PCOUNTRY_DATA;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
/* Global data contained in guest memory */
|
||||||
|
static WORD CountryDataSegment;
|
||||||
|
static PCOUNTRY_DATA CountryData;
|
||||||
|
|
||||||
|
WORD YesNoTable[2] = { MAKEWORD('Y', 0), MAKEWORD('N', 0) };
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See: http://www.ctyme.com/intr/rb-3163.htm#Table1754
|
||||||
|
* http://www.ctyme.com/intr/rb-3164.htm
|
||||||
|
* http://www.ctyme.com/intr/rb-3166.htm
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
|
WORD
|
||||||
|
DosGetCountryInfo(IN OUT PWORD CountryId,
|
||||||
|
OUT PDOS_COUNTRY_INFO CountryInfo)
|
||||||
|
{
|
||||||
|
INT Return;
|
||||||
|
DWORD NumVal;
|
||||||
|
|
||||||
|
Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IDATE | LOCALE_RETURN_NUMBER, // LOCALE_ILDATE | LOCALE_RETURN_NUMBER
|
||||||
|
(LPSTR)&NumVal,
|
||||||
|
sizeof(NumVal));
|
||||||
|
if (Return == 0) return LOWORD(GetLastError());
|
||||||
|
CountryInfo->DateTimeFormat = (WORD)NumVal;
|
||||||
|
|
||||||
|
Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SCURRENCY,
|
||||||
|
(LPSTR)&CountryInfo->CurrencySymbol,
|
||||||
|
sizeof(CountryInfo->CurrencySymbol));
|
||||||
|
if (Return == 0) return LOWORD(GetLastError());
|
||||||
|
|
||||||
|
Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND,
|
||||||
|
(LPSTR)&CountryInfo->ThousandSep,
|
||||||
|
sizeof(CountryInfo->ThousandSep));
|
||||||
|
if (Return == 0) return LOWORD(GetLastError());
|
||||||
|
|
||||||
|
Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL,
|
||||||
|
(LPSTR)&CountryInfo->DecimalSep,
|
||||||
|
sizeof(CountryInfo->DecimalSep));
|
||||||
|
if (Return == 0) return LOWORD(GetLastError());
|
||||||
|
|
||||||
|
Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDATE,
|
||||||
|
(LPSTR)&CountryInfo->DateSep,
|
||||||
|
sizeof(CountryInfo->DateSep));
|
||||||
|
if (Return == 0) return LOWORD(GetLastError());
|
||||||
|
|
||||||
|
Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_STIME,
|
||||||
|
(LPSTR)&CountryInfo->TimeSep,
|
||||||
|
sizeof(CountryInfo->TimeSep));
|
||||||
|
if (Return == 0) return LOWORD(GetLastError());
|
||||||
|
|
||||||
|
// NOTE: '4: Symbol replace decimal separator' is unsupported.
|
||||||
|
Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ICURRENCY | LOCALE_RETURN_NUMBER,
|
||||||
|
(LPSTR)&NumVal,
|
||||||
|
sizeof(NumVal));
|
||||||
|
if (Return == 0) return LOWORD(GetLastError());
|
||||||
|
CountryInfo->CurrencyFormat = (BYTE)NumVal;
|
||||||
|
|
||||||
|
Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ICURRDIGITS | LOCALE_RETURN_NUMBER, // LOCALE_IDIGITS | LOCALE_RETURN_NUMBER
|
||||||
|
(LPSTR)&NumVal,
|
||||||
|
sizeof(NumVal));
|
||||||
|
if (Return == 0) return LOWORD(GetLastError());
|
||||||
|
CountryInfo->CurrencyDigitsNum = (BYTE)NumVal;
|
||||||
|
|
||||||
|
Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ITIME | LOCALE_RETURN_NUMBER,
|
||||||
|
(LPSTR)&NumVal,
|
||||||
|
sizeof(NumVal));
|
||||||
|
if (Return == 0) return LOWORD(GetLastError());
|
||||||
|
CountryInfo->TimeFormat = (BYTE)NumVal;
|
||||||
|
|
||||||
|
CountryInfo->CaseMapPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, CaseMapRoutine), CountryDataSegment);
|
||||||
|
|
||||||
|
// CountryInfo->DataListSep;
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
WORD
|
||||||
|
DosGetCountryInfoEx(IN BYTE InfoId,
|
||||||
|
IN WORD CodePage,
|
||||||
|
IN WORD CountryId,
|
||||||
|
OUT PDOS_COUNTRY_INFO_2 CountryInfo,
|
||||||
|
IN OUT PWORD BufferSize)
|
||||||
|
{
|
||||||
|
// FIXME: use: CodePage; CountryId
|
||||||
|
// FIXME: Check BufferSize
|
||||||
|
// FIXME: Use NLSFUNC resident?
|
||||||
|
|
||||||
|
switch (InfoId)
|
||||||
|
{
|
||||||
|
/* Get General Internationalization Info (similar to AX=3800h) */
|
||||||
|
case 0x01:
|
||||||
|
{
|
||||||
|
WORD ErrorCode;
|
||||||
|
ErrorCode = DosGetCountryInfo(&CountryId,
|
||||||
|
&CountryInfo->CountryInfoEx.CountryInfo);
|
||||||
|
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
|
||||||
|
CountryInfo->CountryInfoEx.Size = sizeof(CountryInfo->CountryInfoEx);
|
||||||
|
CountryInfo->CountryInfoEx.CountryId = CountryId;
|
||||||
|
// CountryInfo->CodePage;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get Pointer to Uppercase Table */
|
||||||
|
case 0x02:
|
||||||
|
CountryInfo->UpCaseTblPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, UpCaseTbl), CountryDataSegment);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Get Pointer to Lowercase Table */
|
||||||
|
case 0x03:
|
||||||
|
CountryInfo->LoCaseTblPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, LoCaseTbl), CountryDataSegment);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Get Pointer to Filename Uppercase Table */
|
||||||
|
case 0x04:
|
||||||
|
CountryInfo->FNameUpCaseTblPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, UpCaseTbl), CountryDataSegment);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Get Pointer to Filename Terminator Table */
|
||||||
|
case 0x05:
|
||||||
|
CountryInfo->FNameTermTblPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, FNameTermTbl), CountryDataSegment);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Get Pointer to Collating Sequence Table */
|
||||||
|
case 0x06:
|
||||||
|
CountryInfo->CollateTblPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, CollateTbl), CountryDataSegment);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Get Pointer to Double-Byte Character Set Table */
|
||||||
|
case 0x07:
|
||||||
|
CountryInfo->DBCSLeadTblPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, DBCSLeadTbl), CountryDataSegment);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
CountryInfo->InfoId = InfoId;
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
WORD DosIfCharYesNo(WORD Char)
|
||||||
|
{
|
||||||
|
Char = toupper(Char);
|
||||||
|
|
||||||
|
/* NO-type */
|
||||||
|
if (Char == YesNoTable[1])
|
||||||
|
return 0x0000;
|
||||||
|
/* YES-type */
|
||||||
|
if (Char == YesNoTable[0])
|
||||||
|
return 0x0001;
|
||||||
|
/* Unknown type */
|
||||||
|
return 0x0002;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHAR DosToUpper(CHAR Char)
|
||||||
|
{
|
||||||
|
// FIXME: Use the current locale
|
||||||
|
return toupper(Char);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID DosToUpperStrN(PCHAR DestStr, PCHAR SrcStr, WORD Length)
|
||||||
|
{
|
||||||
|
while (Length-- > 0)
|
||||||
|
*DestStr++ = toupper(*SrcStr++);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID DosToUpperStrZ(PSTR DestStr, PSTR SrcStr)
|
||||||
|
{
|
||||||
|
while (*SrcStr)
|
||||||
|
*DestStr++ = toupper(*SrcStr++);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN DosCountryInitialize(VOID)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
|
||||||
|
/* Initialize some memory to store country information */
|
||||||
|
// FIXME: Can we use instead some static area from the DOS data structure??
|
||||||
|
CountryDataSegment = DosAllocateMemory(sizeof(COUNTRY_DATA), NULL);
|
||||||
|
if (CountryDataSegment == 0) return FALSE;
|
||||||
|
CountryData = (PCOUNTRY_DATA)SEG_OFF_TO_PTR(CountryDataSegment, 0x0000);
|
||||||
|
|
||||||
|
RtlMoveMemory(CountryData->CaseMapRoutine,
|
||||||
|
CaseMapRoutine,
|
||||||
|
sizeof(CaseMapRoutine));
|
||||||
|
|
||||||
|
CountryData->UpCaseTbl.Size = ARRAYSIZE(CountryData->UpCaseTbl.Data);
|
||||||
|
for (i = 0; i < CountryData->UpCaseTbl.Size; ++i)
|
||||||
|
CountryData->UpCaseTbl.Data[i] = 0x80 + i;
|
||||||
|
|
||||||
|
CountryData->LoCaseTbl.Size = ARRAYSIZE(CountryData->LoCaseTbl.Data);
|
||||||
|
for (i = 0; i < CountryData->LoCaseTbl.Size; ++i)
|
||||||
|
CountryData->LoCaseTbl.Data[i] = i;
|
||||||
|
|
||||||
|
CountryData->FNameTermTbl.Size = ARRAYSIZE(CountryData->FNameTermTbl.Data);
|
||||||
|
CountryData->FNameTermTbl.Data[ 0] = 0x01; // Dummy Byte
|
||||||
|
CountryData->FNameTermTbl.Data[ 1] = 0x00; // Lowest permissible Character Value for Filename
|
||||||
|
CountryData->FNameTermTbl.Data[ 2] = 0xFF; // Highest permissible Character Value for Filename
|
||||||
|
CountryData->FNameTermTbl.Data[ 3] = 0x00; // Dummy Byte
|
||||||
|
CountryData->FNameTermTbl.Data[ 4] = 0x00; // First excluded Character in Range \ all characters in this
|
||||||
|
CountryData->FNameTermTbl.Data[ 5] = 0x20; // Last excluded Character in Range / range are illegal
|
||||||
|
CountryData->FNameTermTbl.Data[ 6] = 0x02; // Dummy Byte
|
||||||
|
CountryData->FNameTermTbl.Data[ 7] = 14; // Number of illegal (terminator) Characters
|
||||||
|
// CountryData->FNameTermTbl.Data[ 8] = ".\"/\\[]:|<>+=;,"; // Characters which terminate a Filename
|
||||||
|
CountryData->FNameTermTbl.Data[ 8] = '.';
|
||||||
|
CountryData->FNameTermTbl.Data[ 9] = '\"';
|
||||||
|
CountryData->FNameTermTbl.Data[10] = '/';
|
||||||
|
CountryData->FNameTermTbl.Data[11] = '\\';
|
||||||
|
CountryData->FNameTermTbl.Data[12] = '[';
|
||||||
|
CountryData->FNameTermTbl.Data[13] = ']';
|
||||||
|
CountryData->FNameTermTbl.Data[14] = ':';
|
||||||
|
CountryData->FNameTermTbl.Data[15] = '|';
|
||||||
|
CountryData->FNameTermTbl.Data[16] = '<';
|
||||||
|
CountryData->FNameTermTbl.Data[17] = '>';
|
||||||
|
CountryData->FNameTermTbl.Data[18] = '+';
|
||||||
|
CountryData->FNameTermTbl.Data[19] = '=';
|
||||||
|
CountryData->FNameTermTbl.Data[20] = ';';
|
||||||
|
CountryData->FNameTermTbl.Data[21] = ',';
|
||||||
|
|
||||||
|
CountryData->CollateTbl.Size = ARRAYSIZE(CountryData->CollateTbl.Data);
|
||||||
|
for (i = 0; i < CountryData->LoCaseTbl.Size; ++i)
|
||||||
|
CountryData->LoCaseTbl.Data[i] = i;
|
||||||
|
|
||||||
|
CountryData->DBCSLeadTbl.Size = 0; // Empty DBCS table
|
||||||
|
CountryData->DBCSLeadTbl.Data[0] = 0x0000;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
99
reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/country.h
Normal file
99
reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/country.h
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: GPL - See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Virtual DOS Machine
|
||||||
|
* FILE: dos/dos32krnl/country.h
|
||||||
|
* PURPOSE: DOS32 Country support
|
||||||
|
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
||||||
|
*
|
||||||
|
* NOTE: Support for default (english) language only.
|
||||||
|
* For other languages, please use COUNTRY.SYS
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _COUNTRY_H_
|
||||||
|
#define _COUNTRY_H_
|
||||||
|
|
||||||
|
/* DEFINITIONS ****************************************************************/
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
#if 0 // Keep here for information purposes only
|
||||||
|
// DOS 2.00-2.10 country info structure
|
||||||
|
typedef struct _DOS_COUNTRY_INFO_OLD
|
||||||
|
{
|
||||||
|
WORD DateTimeFormat;
|
||||||
|
CHAR CurrencySymbol[2];
|
||||||
|
CHAR ThousandSep[2];
|
||||||
|
CHAR DecimalSep[2];
|
||||||
|
BYTE Reserved[24];
|
||||||
|
} DOS_COUNTRY_INFO_OLD, *PDOS_COUNTRY_INFO_OLD;
|
||||||
|
C_ASSERT(sizeof(DOS_COUNTRY_INFO_OLD) == 0x20);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// DOS 2.11+ compatible country info structure
|
||||||
|
typedef struct _DOS_COUNTRY_INFO
|
||||||
|
{
|
||||||
|
WORD DateTimeFormat;
|
||||||
|
CHAR CurrencySymbol[5];
|
||||||
|
CHAR ThousandSep[2];
|
||||||
|
CHAR DecimalSep[2];
|
||||||
|
CHAR DateSep[2];
|
||||||
|
CHAR TimeSep[2];
|
||||||
|
BYTE CurrencyFormat;
|
||||||
|
BYTE CurrencyDigitsNum;
|
||||||
|
BYTE TimeFormat;
|
||||||
|
DWORD CaseMapPtr;
|
||||||
|
CHAR DataListSep[2];
|
||||||
|
BYTE Reserved[10];
|
||||||
|
} DOS_COUNTRY_INFO, *PDOS_COUNTRY_INFO;
|
||||||
|
C_ASSERT(sizeof(DOS_COUNTRY_INFO) == 0x22);
|
||||||
|
|
||||||
|
typedef struct _DOS_COUNTRY_INFO_EX
|
||||||
|
{
|
||||||
|
WORD Size;
|
||||||
|
WORD CountryId;
|
||||||
|
WORD CodePage;
|
||||||
|
DOS_COUNTRY_INFO CountryInfo;
|
||||||
|
} DOS_COUNTRY_INFO_EX, *PDOS_COUNTRY_INFO_EX;
|
||||||
|
C_ASSERT(sizeof(DOS_COUNTRY_INFO_EX) == 0x28);
|
||||||
|
|
||||||
|
typedef struct _DOS_COUNTRY_INFO_2
|
||||||
|
{
|
||||||
|
BYTE InfoId;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
DOS_COUNTRY_INFO_EX CountryInfoEx;
|
||||||
|
|
||||||
|
DWORD UpCaseTblPtr;
|
||||||
|
DWORD LoCaseTblPtr;
|
||||||
|
|
||||||
|
DWORD FNameUpCaseTblPtr;
|
||||||
|
DWORD FNameTermTblPtr;
|
||||||
|
|
||||||
|
DWORD CollateTblPtr;
|
||||||
|
DWORD DBCSLeadTblPtr;
|
||||||
|
};
|
||||||
|
} DOS_COUNTRY_INFO_2, *PDOS_COUNTRY_INFO_2;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
|
WORD
|
||||||
|
DosGetCountryInfo(IN OUT PWORD CountryId,
|
||||||
|
OUT PDOS_COUNTRY_INFO CountryInfo);
|
||||||
|
|
||||||
|
WORD
|
||||||
|
DosGetCountryInfoEx(IN BYTE InfoId,
|
||||||
|
IN WORD CodePage,
|
||||||
|
IN WORD CountryId,
|
||||||
|
OUT PDOS_COUNTRY_INFO_2 CountryInfo,
|
||||||
|
IN OUT PWORD BufferSize);
|
||||||
|
|
||||||
|
WORD DosIfCharYesNo(WORD Char);
|
||||||
|
CHAR DosToUpper(CHAR Char);
|
||||||
|
VOID DosToUpperStrN(PCHAR DestStr, PCHAR SrcStr, WORD Length);
|
||||||
|
VOID DosToUpperStrZ(PSTR DestStr, PSTR SrcStr);
|
||||||
|
|
||||||
|
BOOLEAN DosCountryInitialize(VOID);
|
||||||
|
|
||||||
|
#endif
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "dos.h"
|
#include "dos.h"
|
||||||
#include "dos/dem.h"
|
#include "dos/dem.h"
|
||||||
|
#include "country.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "handle.h"
|
#include "handle.h"
|
||||||
#include "dosfiles.h"
|
#include "dosfiles.h"
|
||||||
|
@ -895,59 +896,21 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
/* Get/Set Country-dependent Information */
|
/* Get/Set Country-dependent Information */
|
||||||
case 0x38:
|
case 0x38:
|
||||||
{
|
{
|
||||||
INT Return;
|
WORD CountryId = getAL() < 0xFF ? getAL() : getBX();
|
||||||
PDOS_COUNTRY_CODE_BUFFER CountryCodeBuffer =
|
WORD ErrorCode;
|
||||||
(PDOS_COUNTRY_CODE_BUFFER)SEG_OFF_TO_PTR(getDS(), getDX());
|
|
||||||
|
|
||||||
if (getAL() == 0x00)
|
ErrorCode = DosGetCountryInfo(&CountryId,
|
||||||
|
(PDOS_COUNTRY_INFO)SEG_OFF_TO_PTR(getDS(), getDX()));
|
||||||
|
|
||||||
|
if (ErrorCode == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Get */
|
|
||||||
Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IDATE,
|
|
||||||
(LPSTR)&CountryCodeBuffer->TimeFormat,
|
|
||||||
sizeof(CountryCodeBuffer->TimeFormat));
|
|
||||||
if (Return == 0)
|
|
||||||
{
|
|
||||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
|
||||||
setAX(LOWORD(GetLastError()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SCURRENCY,
|
|
||||||
(LPSTR)&CountryCodeBuffer->CurrencySymbol,
|
|
||||||
sizeof(CountryCodeBuffer->CurrencySymbol));
|
|
||||||
if (Return == 0)
|
|
||||||
{
|
|
||||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
|
||||||
setAX(LOWORD(GetLastError()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND,
|
|
||||||
(LPSTR)&CountryCodeBuffer->ThousandSep,
|
|
||||||
sizeof(CountryCodeBuffer->ThousandSep));
|
|
||||||
if (Return == 0)
|
|
||||||
{
|
|
||||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
|
||||||
setAX(LOWORD(GetLastError()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL,
|
|
||||||
(LPSTR)&CountryCodeBuffer->DecimalSep,
|
|
||||||
sizeof(CountryCodeBuffer->DecimalSep));
|
|
||||||
if (Return == 0)
|
|
||||||
{
|
|
||||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
|
||||||
setAX(LOWORD(GetLastError()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||||
|
setBX(CountryId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: NOT IMPLEMENTED
|
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||||
UNIMPLEMENTED;
|
setAX(ErrorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -1616,7 +1579,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// FIXME: Check for buffer validity?
|
// FIXME: Check for buffer validity?
|
||||||
// It should be a ASCIZ path ending with a '\' + 13 zero bytes
|
// It should be a ASCIIZ path ending with a '\' + 13 zero bytes
|
||||||
// to receive the generated filename.
|
// to receive the generated filename.
|
||||||
|
|
||||||
/* First create the temporary file */
|
/* First create the temporary file */
|
||||||
|
@ -1769,6 +1732,91 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Extended Country Information */
|
||||||
|
case 0x65:
|
||||||
|
{
|
||||||
|
switch (getAL())
|
||||||
|
{
|
||||||
|
case 0x01: case 0x02: case 0x03:
|
||||||
|
case 0x04: case 0x05: case 0x06:
|
||||||
|
case 0x07:
|
||||||
|
{
|
||||||
|
WORD BufferSize = getCX();
|
||||||
|
WORD ErrorCode;
|
||||||
|
ErrorCode = DosGetCountryInfoEx(getAL(),
|
||||||
|
getBX(),
|
||||||
|
getDX(),
|
||||||
|
(PDOS_COUNTRY_INFO_2)SEG_OFF_TO_PTR(getES(), getDI()),
|
||||||
|
&BufferSize);
|
||||||
|
if (ErrorCode == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||||
|
setCX(BufferSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||||
|
setAX(ErrorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Country-dependent Character Capitalization -- Character */
|
||||||
|
case 0x20:
|
||||||
|
/* Country-dependent Filename Capitalization -- Character */
|
||||||
|
case 0xA0:
|
||||||
|
{
|
||||||
|
setDL(DosToUpper(getDL()));
|
||||||
|
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||||
|
// setAX(ERROR_SUCCESS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Country-dependent Character Capitalization -- Counted ASCII String */
|
||||||
|
case 0x21:
|
||||||
|
/* Country-dependent Filename Capitalization -- Counted ASCII String */
|
||||||
|
case 0xA1:
|
||||||
|
{
|
||||||
|
PCHAR Str = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX());
|
||||||
|
// FIXME: Check for NULL ptr!!
|
||||||
|
DosToUpperStrN(Str, Str, getCX());
|
||||||
|
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||||
|
// setAX(ERROR_SUCCESS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Country-dependent Character Capitalization -- ASCIIZ String */
|
||||||
|
case 0x22:
|
||||||
|
/* Country-dependent Filename Capitalization -- ASCIIZ String */
|
||||||
|
case 0xA2:
|
||||||
|
{
|
||||||
|
PSTR Str = (PSTR)SEG_OFF_TO_PTR(getDS(), getDX());
|
||||||
|
// FIXME: Check for NULL ptr!!
|
||||||
|
DosToUpperStrZ(Str, Str);
|
||||||
|
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||||
|
// setAX(ERROR_SUCCESS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine if Character represents YES/NO Response */
|
||||||
|
case 0x23:
|
||||||
|
{
|
||||||
|
setAX(DosIfCharYesNo(MAKEWORD(getDL(), getDH())));
|
||||||
|
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
DPRINT1("INT 21h, AH = 65h, subfunction AL = %Xh NOT IMPLEMENTED\n",
|
||||||
|
getAL());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set Handle Count */
|
/* Set Handle Count */
|
||||||
case 0x67:
|
case 0x67:
|
||||||
{
|
{
|
||||||
|
@ -2139,6 +2187,9 @@ BOOLEAN DosKRNLInitialize(VOID)
|
||||||
/* Unimplemented DOS interrupts */
|
/* Unimplemented DOS interrupts */
|
||||||
RegisterDosInt32(0x2A, NULL); // Network - Installation Check
|
RegisterDosInt32(0x2A, NULL); // Network - Installation Check
|
||||||
|
|
||||||
|
/* Initialize country data */
|
||||||
|
DosCountryInitialize();
|
||||||
|
|
||||||
/* Load the CON driver */
|
/* Load the CON driver */
|
||||||
ConDrvInitialize();
|
ConDrvInitialize();
|
||||||
|
|
||||||
|
|
|
@ -125,14 +125,6 @@ typedef struct _DOS_FIND_FILE_BLOCK
|
||||||
CHAR FileName[13];
|
CHAR FileName[13];
|
||||||
} DOS_FIND_FILE_BLOCK, *PDOS_FIND_FILE_BLOCK;
|
} DOS_FIND_FILE_BLOCK, *PDOS_FIND_FILE_BLOCK;
|
||||||
|
|
||||||
typedef struct _DOS_COUNTRY_CODE_BUFFER
|
|
||||||
{
|
|
||||||
WORD TimeFormat;
|
|
||||||
WORD CurrencySymbol;
|
|
||||||
WORD ThousandSep;
|
|
||||||
WORD DecimalSep;
|
|
||||||
} DOS_COUNTRY_CODE_BUFFER, *PDOS_COUNTRY_CODE_BUFFER;
|
|
||||||
|
|
||||||
typedef struct _DOS_SDA
|
typedef struct _DOS_SDA
|
||||||
{
|
{
|
||||||
BYTE PrinterEchoFlag;
|
BYTE PrinterEchoFlag;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue