ReactOS  0.4.15-dev-1039-gb9754fa
country.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: GPL - See COPYING in the top level directory
3  * PROJECT: ReactOS Virtual DOS Machine
4  * FILE: subsystems/mvdm/ntvdm/dos/dos32krnl/country.c
5  * PURPOSE: DOS32 Country support
6  * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7  *
8  * NOTE: Support for default (english) language only.
9  * For other languages, please use COUNTRY.SYS
10  */
11 
12 /* INCLUDES *******************************************************************/
13 
14 #include "ntvdm.h"
15 
16 #define NDEBUG
17 #include <debug.h>
18 
19 #include "emulator.h"
20 
21 #include "country.h"
22 #include "memory.h"
23 
24 /* PRIVATE VARIABLES **********************************************************/
25 
26 /* CaseMap routine: should call INT 65h, AL=20h */
27 // ATM, just do nothing.
28 static const BYTE CaseMapRoutine[] =
29 {
30  0xCB // retf
31 };
32 
33 #pragma pack(push, 1)
34 
35 #define DATATABLE(name, type, len) \
36  typedef struct _##name \
37  { \
38  WORD Size; \
39  type Data[(len)]; \
40  } name
41 
42 DATATABLE(UPPERCASE, CHAR, 0xFF-0x80+1);
43 DATATABLE(LOWERCASE, CHAR, 0xFF-0x00+1);
44 DATATABLE(FNAMETERM, BYTE, 22);
45 DATATABLE(COLLATE , BYTE, 0xFF-0x00+1);
46 DATATABLE(DBCSLEAD , WORD, 0x00+1);
47 
48 typedef struct _COUNTRY_DATA
49 {
51  UPPERCASE UpCaseTbl; // Used also for filename uppercase
52  LOWERCASE LoCaseTbl;
53  FNAMETERM FNameTermTbl;
54  COLLATE CollateTbl;
55  DBCSLEAD DBCSLeadTbl;
57 
58 #pragma pack(pop)
59 
60 /* Global data contained in guest memory */
63 
64 WORD YesNoTable[2] = { MAKEWORD('Y', 0), MAKEWORD('N', 0) };
65 
66 /*
67  * See: http://www.ctyme.com/intr/rb-3163.htm#Table1754
68  * http://www.ctyme.com/intr/rb-3164.htm
69  * http://www.ctyme.com/intr/rb-3166.htm
70  */
71 
72 /* PRIVATE FUNCTIONS **********************************************************/
73 
74 /* PUBLIC FUNCTIONS ***********************************************************/
75 
76 WORD
78  OUT PDOS_COUNTRY_INFO CountryInfo)
79 {
80  INT Return;
81  DWORD NumVal;
82 
83  Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IDATE | LOCALE_RETURN_NUMBER, // LOCALE_ILDATE | LOCALE_RETURN_NUMBER
84  (LPSTR)&NumVal,
85  sizeof(NumVal));
86  if (Return == 0) return LOWORD(GetLastError());
87  CountryInfo->DateTimeFormat = (WORD)NumVal;
88 
90  (LPSTR)&CountryInfo->CurrencySymbol,
91  sizeof(CountryInfo->CurrencySymbol));
92  if (Return == 0) return LOWORD(GetLastError());
93 
95  (LPSTR)&CountryInfo->ThousandSep,
96  sizeof(CountryInfo->ThousandSep));
97  if (Return == 0) return LOWORD(GetLastError());
98 
100  (LPSTR)&CountryInfo->DecimalSep,
101  sizeof(CountryInfo->DecimalSep));
102  if (Return == 0) return LOWORD(GetLastError());
103 
105  (LPSTR)&CountryInfo->DateSep,
106  sizeof(CountryInfo->DateSep));
107  if (Return == 0) return LOWORD(GetLastError());
108 
110  (LPSTR)&CountryInfo->TimeSep,
111  sizeof(CountryInfo->TimeSep));
112  if (Return == 0) return LOWORD(GetLastError());
113 
114  // NOTE: '4: Symbol replace decimal separator' is unsupported.
115  Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ICURRENCY | LOCALE_RETURN_NUMBER,
116  (LPSTR)&NumVal,
117  sizeof(NumVal));
118  if (Return == 0) return LOWORD(GetLastError());
119  CountryInfo->CurrencyFormat = (BYTE)NumVal;
120 
121  Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ICURRDIGITS | LOCALE_RETURN_NUMBER, // LOCALE_IDIGITS | LOCALE_RETURN_NUMBER
122  (LPSTR)&NumVal,
123  sizeof(NumVal));
124  if (Return == 0) return LOWORD(GetLastError());
125  CountryInfo->CurrencyDigitsNum = (BYTE)NumVal;
126 
127  Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ITIME | LOCALE_RETURN_NUMBER,
128  (LPSTR)&NumVal,
129  sizeof(NumVal));
130  if (Return == 0) return LOWORD(GetLastError());
131  CountryInfo->TimeFormat = (BYTE)NumVal;
132 
134 
135  // CountryInfo->DataListSep;
136 
137  return ERROR_SUCCESS;
138 }
139 
140 WORD
142  IN WORD CodePage,
143  IN WORD CountryId,
144  OUT PDOS_COUNTRY_INFO_2 CountryInfo,
146 {
147  // FIXME: use: CodePage; CountryId
148  // FIXME: Check BufferSize
149  // FIXME: Use NLSFUNC resident?
150 
151  switch (InfoId)
152  {
153  /* Get General Internationalization Info (similar to AX=3800h) */
154  case 0x01:
155  {
156  WORD ErrorCode;
157  ErrorCode = DosGetCountryInfo(&CountryId,
158  &CountryInfo->CountryInfoEx.CountryInfo);
159  if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
160  CountryInfo->CountryInfoEx.Size = sizeof(CountryInfo->CountryInfoEx);
161  CountryInfo->CountryInfoEx.CountryId = CountryId;
162  // CountryInfo->CodePage;
163  break;
164  }
165 
166  /* Get Pointer to Uppercase Table */
167  case 0x02:
168  CountryInfo->UpCaseTblPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, UpCaseTbl), CountryDataSegment);
169  break;
170 
171  /* Get Pointer to Lowercase Table */
172  case 0x03:
173  CountryInfo->LoCaseTblPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, LoCaseTbl), CountryDataSegment);
174  break;
175 
176  /* Get Pointer to Filename Uppercase Table */
177  case 0x04:
178  CountryInfo->FNameUpCaseTblPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, UpCaseTbl), CountryDataSegment);
179  break;
180 
181  /* Get Pointer to Filename Terminator Table */
182  case 0x05:
183  CountryInfo->FNameTermTblPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, FNameTermTbl), CountryDataSegment);
184  break;
185 
186  /* Get Pointer to Collating Sequence Table */
187  case 0x06:
188  CountryInfo->CollateTblPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, CollateTbl), CountryDataSegment);
189  break;
190 
191  /* Get Pointer to Double-Byte Character Set Table */
192  case 0x07:
193  CountryInfo->DBCSLeadTblPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, DBCSLeadTbl), CountryDataSegment);
194  break;
195 
196  default:
198  }
199  CountryInfo->InfoId = InfoId;
200 
201  return ERROR_SUCCESS;
202 }
203 
205 {
206  Char = toupper(Char);
207 
208  /* NO-type */
209  if (Char == YesNoTable[1])
210  return 0x0000;
211  /* YES-type */
212  if (Char == YesNoTable[0])
213  return 0x0001;
214  /* Unknown type */
215  return 0x0002;
216 }
217 
219 {
220  // FIXME: Use the current locale
221  return toupper(Char);
222 }
223 
225 {
226  while (Length-- > 0)
227  *DestStr++ = toupper(*SrcStr++);
228 }
229 
230 VOID DosToUpperStrZ(PSTR DestStr, PSTR SrcStr)
231 {
232  while (*SrcStr)
233  *DestStr++ = toupper(*SrcStr++);
234 }
235 
237 {
238  UINT i;
239 
240  /* Initialize some memory to store country information */
241  // FIXME: Can we use instead some static area from the DOS data structure??
243  if (CountryDataSegment == 0) return FALSE;
245 
248  sizeof(CaseMapRoutine));
249 
251  for (i = 0; i < CountryData->UpCaseTbl.Size; ++i)
252  CountryData->UpCaseTbl.Data[i] = 0x80 + i;
253 
255  for (i = 0; i < CountryData->LoCaseTbl.Size; ++i)
256  CountryData->LoCaseTbl.Data[i] = i;
257 
259  CountryData->FNameTermTbl.Data[ 0] = 0x01; // Dummy Byte
260  CountryData->FNameTermTbl.Data[ 1] = 0x00; // Lowest permissible Character Value for Filename
261  CountryData->FNameTermTbl.Data[ 2] = 0xFF; // Highest permissible Character Value for Filename
262  CountryData->FNameTermTbl.Data[ 3] = 0x00; // Dummy Byte
263  CountryData->FNameTermTbl.Data[ 4] = 0x00; // First excluded Character in Range \ all characters in this
264  CountryData->FNameTermTbl.Data[ 5] = 0x20; // Last excluded Character in Range / range are illegal
265  CountryData->FNameTermTbl.Data[ 6] = 0x02; // Dummy Byte
266  CountryData->FNameTermTbl.Data[ 7] = 14; // Number of illegal (terminator) Characters
267 // CountryData->FNameTermTbl.Data[ 8] = ".\"/\\[]:|<>+=;,"; // Characters which terminate a Filename
268  CountryData->FNameTermTbl.Data[ 8] = '.';
269  CountryData->FNameTermTbl.Data[ 9] = '\"';
270  CountryData->FNameTermTbl.Data[10] = '/';
271  CountryData->FNameTermTbl.Data[11] = '\\';
272  CountryData->FNameTermTbl.Data[12] = '[';
273  CountryData->FNameTermTbl.Data[13] = ']';
274  CountryData->FNameTermTbl.Data[14] = ':';
275  CountryData->FNameTermTbl.Data[15] = '|';
276  CountryData->FNameTermTbl.Data[16] = '<';
277  CountryData->FNameTermTbl.Data[17] = '>';
278  CountryData->FNameTermTbl.Data[18] = '+';
279  CountryData->FNameTermTbl.Data[19] = '=';
280  CountryData->FNameTermTbl.Data[20] = ';';
281  CountryData->FNameTermTbl.Data[21] = ',';
282 
284  for (i = 0; i < CountryData->CollateTbl.Size; ++i)
285  CountryData->CollateTbl.Data[i] = i;
286 
287  CountryData->DBCSLeadTbl.Size = 0; // Empty DBCS table
288  CountryData->DBCSLeadTbl.Data[0] = 0x0000;
289 
290  return TRUE;
291 }
WORD YesNoTable[2]
Definition: country.c:64
signed char * PCHAR
Definition: retypes.h:7
#define IN
Definition: typedefs.h:39
VOID DosToUpperStrZ(PSTR DestStr, PSTR SrcStr)
Definition: country.c:230
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
#define ERROR_SUCCESS
Definition: deptool.c:10
VOID DosToUpperStrN(PCHAR DestStr, PCHAR SrcStr, WORD Length)
Definition: country.c:224
#define MAKEWORD(a, b)
Definition: typedefs.h:248
#define TRUE
Definition: types.h:120
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: lang.c:1018
#define LOCALE_IDATE
Definition: winnls.h:63
#define LOCALE_USER_DEFAULT
struct _COUNTRY_DATA * PCOUNTRY_DATA
char CHAR
Definition: xmlstorage.h:175
static WORD CountryDataSegment
Definition: country.c:61
COLLATE CollateTbl
Definition: country.c:54
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
char * LPSTR
Definition: xmlstorage.h:182
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
struct _COUNTRY_DATA COUNTRY_DATA
int32_t INT
Definition: typedefs.h:58
#define LOCALE_SCURRENCY
Definition: winnls.h:49
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define DATATABLE(name, type, len)
Definition: country.c:35
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BYTE CaseMapRoutine[sizeof(CaseMapRoutine)]
Definition: country.c:50
#define LOCALE_STHOUSAND
Definition: winnls.h:43
static const BYTE CaseMapRoutine[]
Definition: country.c:28
#define FALSE
Definition: types.h:117
static PCOUNTRY_DATA CountryData
Definition: country.c:62
#define MAKELONG(a, b)
Definition: typedefs.h:249
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable)
Definition: memory.c:136
#define LOCALE_SDECIMAL
Definition: winnls.h:42
#define LOCALE_STIME
Definition: winnls.h:59
CHAR DosToUpper(CHAR Char)
Definition: country.c:218
WORD * PWORD
Definition: pedump.c:67
BOOLEAN DosCountryInitialize(VOID)
Definition: country.c:236
#define LOCALE_ICURRENCY
Definition: winnls.h:56
int toupper(int c)
Definition: utclib.c:881
#define LOCALE_SDATE
Definition: winnls.h:58
#define BufferSize
Definition: classpnp.h:436
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
UPPERCASE UpCaseTbl
Definition: country.c:51
WORD DosGetCountryInfo(IN OUT PWORD CountryId, OUT PDOS_COUNTRY_INFO CountryInfo)
Definition: country.c:77
WORD DosGetCountryInfoEx(IN BYTE InfoId, IN WORD CodePage, IN WORD CountryId, OUT PDOS_COUNTRY_INFO_2 CountryInfo, IN OUT PWORD BufferSize)
Definition: country.c:141
unsigned char BYTE
Definition: xxhash.c:193
DBCSLEAD DBCSLeadTbl
Definition: country.c:55
#define LOCALE_ICURRDIGITS
Definition: winnls.h:54
#define LOCALE_ITIME
Definition: winnls.h:65
signed char * PSTR
Definition: retypes.h:7
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned int UINT
Definition: ndis.h:50
#define OUT
Definition: typedefs.h:40
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
LOWERCASE LoCaseTbl
Definition: country.c:52
WORD DosIfCharYesNo(WORD Char)
Definition: country.c:204
#define LOWORD(l)
Definition: pedump.c:82
FNAMETERM FNameTermTbl
Definition: country.c:53