From be1c6deb1847d66124bf163d64343770e8ad2015 Mon Sep 17 00:00:00 2001 From: Jukka Heinonen Date: Tue, 10 Dec 2002 19:58:39 +0000 Subject: [PATCH] Move int21 country information handling to winedos. Improve country information handling. Move collate table to upper memory. --- dlls/winedos/int21.c | 381 ++++++++++++++++++++++++++++++++++++++++++- include/miscemu.h | 1 - msdos/dosmem.c | 78 --------- msdos/int21.c | 97 ----------- 4 files changed, 372 insertions(+), 185 deletions(-) diff --git a/dlls/winedos/int21.c b/dlls/winedos/int21.c index b35917b99c4..fa2a7b6cfbf 100644 --- a/dlls/winedos/int21.c +++ b/dlls/winedos/int21.c @@ -44,6 +44,330 @@ extern void WINAPI INT_Int21Handler( CONTEXT86 *context ); WINE_DEFAULT_DEBUG_CHANNEL(int21); +#include "pshpack1.h" + +/* + * Structure for DOS data that can be accessed directly from applications. + * Real and protected mode pointers will be returned to this structure so + * the structure must be correctly packed. + */ +typedef struct _INT21_HEAP { + WORD uppercase_size; /* Size of the following table in bytes */ + BYTE uppercase_table[128]; /* Uppercase equivalents of chars from 0x80 to 0xff. */ + + WORD lowercase_size; /* Size of the following table in bytes */ + BYTE lowercase_table[256]; /* Lowercase equivalents of chars from 0x00 to 0xff. */ + + WORD collating_size; /* Size of the following table in bytes */ + BYTE collating_table[256]; /* Values used to sort characters from 0x00 to 0xff. */ + + WORD filename_size; /* Size of the following filename data in bytes */ + BYTE filename_reserved1; /* 0x01 for MS-DOS 3.30-6.00 */ + BYTE filename_lowest; /* Lowest permissible character value for filename */ + BYTE filename_highest; /* Highest permissible character value for filename */ + BYTE filename_reserved2; /* 0x00 for MS-DOS 3.30-6.00 */ + BYTE filename_exclude_first; /* First illegal character in permissible range */ + BYTE filename_exclude_last; /* Last illegal character in permissible range */ + BYTE filename_reserved3; /* 0x02 for MS-DOS 3.30-6.00 */ + BYTE filename_illegal_size; /* Number of terminators in the following table */ + BYTE filename_illegal_table[16]; /* Characters which terminate a filename */ + + WORD dbcs_size; /* Number of valid ranges in the following table */ + BYTE dbcs_table[16]; /* Start/end bytes for N ranges and 00/00 as terminator */ + + BYTE misc_indos; /* Interrupt 21 nesting flag */ +} INT21_HEAP; + +#include "poppack.h" + + +/*********************************************************************** + * INT21_GetSystemCountryCode + * + * Return DOS country code for default system locale. + */ +static WORD INT21_GetSystemCountryCode() +{ + /* + * FIXME: Determine country code. We should probably use + * DOSCONF structure for that. + */ + return GetSystemDefaultLangID(); +} + + +/*********************************************************************** + * INT21_FillCountryInformation + * + * Fill 34-byte buffer with country information data using + * default system locale. + */ +static void INT21_FillCountryInformation( BYTE *buffer ) +{ + /* 00 - WORD: date format + * 00 = mm/dd/yy + * 01 = dd/mm/yy + * 02 = yy/mm/dd + */ + *(WORD*)(buffer + 0) = 0; /* FIXME: Get from locale */ + + /* 02 - BYTE[5]: ASCIIZ currency symbol string */ + buffer[2] = '$'; /* FIXME: Get from locale */ + buffer[3] = 0; + + /* 07 - BYTE[2]: ASCIIZ thousands separator */ + buffer[7] = 0; /* FIXME: Get from locale */ + buffer[8] = 0; + + /* 09 - BYTE[2]: ASCIIZ decimal separator */ + buffer[9] = '.'; /* FIXME: Get from locale */ + buffer[10] = 0; + + /* 11 - BYTE[2]: ASCIIZ date separator */ + buffer[11] = '/'; /* FIXME: Get from locale */ + buffer[12] = 0; + + /* 13 - BYTE[2]: ASCIIZ time separator */ + buffer[13] = ':'; /* FIXME: Get from locale */ + buffer[14] = 0; + + /* 15 - BYTE: Currency format + * bit 2 = set if currency symbol replaces decimal point + * bit 1 = number of spaces between value and currency symbol + * bit 0 = 0 if currency symbol precedes value + * 1 if currency symbol follows value + */ + buffer[15] = 0; /* FIXME: Get from locale */ + + /* 16 - BYTE: Number of digits after decimal in currency */ + buffer[16] = 0; /* FIXME: Get from locale */ + + /* 17 - BYTE: Time format + * bit 0 = 0 if 12-hour clock + * 1 if 24-hour clock + */ + buffer[17] = 1; /* FIXME: Get from locale */ + + /* 18 - DWORD: Address of case map routine */ + *(DWORD*)(buffer + 18) = 0; /* FIXME: ptr to case map routine */ + + /* 22 - BYTE[2]: ASCIIZ data-list separator */ + buffer[22] = ','; /* FIXME: Get from locale */ + buffer[23] = 0; + + /* 24 - BYTE[10]: Reserved */ + memset( buffer + 24, 0, 10 ); +} + + +/*********************************************************************** + * INT21_FillHeap + * + * Initialize DOS heap. + */ +static void INT21_FillHeap( INT21_HEAP *heap ) +{ + static const char terminators[] = "\"\\./[]:|<>+=;,"; + int i; + + /* + * Uppercase table. + */ + heap->uppercase_size = 128; + for (i = 0; i < 128; i++) + heap->uppercase_table[i] = toupper( 128 + i ); + + /* + * Lowercase table. + */ + heap->lowercase_size = 256; + for (i = 0; i < 256; i++) + heap->lowercase_table[i] = tolower( i ); + + /* + * Collating table. + */ + heap->collating_size = 256; + for (i = 0; i < 256; i++) + heap->collating_table[i] = i; + + /* + * Filename table. + */ + heap->filename_size = 8 + strlen(terminators); + heap->filename_illegal_size = strlen(terminators); + strcpy( heap->filename_illegal_table, terminators ); + + heap->filename_reserved1 = 0x01; + heap->filename_lowest = 0; /* FIXME: correct value? */ + heap->filename_highest = 0xff; /* FIXME: correct value? */ + heap->filename_reserved2 = 0x00; + heap->filename_exclude_first = 0x00; /* FIXME: correct value? */ + heap->filename_exclude_last = 0x00; /* FIXME: correct value? */ + heap->filename_reserved3 = 0x02; + + /* + * DBCS lead byte table. This table is empty. + */ + heap->dbcs_size = 0; + memset( heap->dbcs_table, 0, sizeof(heap->dbcs_table) ); + + /* + * Initialize InDos flag. + */ + heap->misc_indos = 0; +} + + +/*********************************************************************** + * INT21_GetHeapSelector + * + * Get segment/selector for DOS heap (INT21_HEAP). + * Creates and initializes heap on first call. + */ +static WORD INT21_GetHeapSelector( CONTEXT86 *context ) +{ + static WORD heap_segment = 0; + static WORD heap_selector = 0; + static BOOL heap_initialized = FALSE; + + if (!heap_initialized) + { + INT21_HEAP *ptr = DOSVM_AllocDataUMB( sizeof(INT21_HEAP), + &heap_segment, + &heap_selector ); + INT21_FillHeap( ptr ); + heap_initialized = TRUE; + } + + if (!ISV86(context) && DOSVM_IsWin16()) + return heap_selector; + else + return heap_segment; +} + + +/*********************************************************************** + * INT21_ExtendedCountryInformation + * + * Handler for function 0x65. + */ +static void INT21_ExtendedCountryInformation( CONTEXT86 *context ) +{ + BYTE *dataptr = CTX_SEG_OFF_TO_LIN( context, context->SegEs, context->Edi ); + + TRACE( "GET EXTENDED COUNTRY INFORMATION, subfunction %02x\n", + AL_reg(context) ); + + /* + * Check subfunctions that are passed country and code page. + */ + if (AL_reg(context) >= 0x01 && AL_reg(context) <= 0x07) + { + WORD country = DX_reg(context); + WORD codepage = BX_reg(context); + + if (country != 0xffff && country != INT21_GetSystemCountryCode()) + FIXME( "Requested info on non-default country %04x\n", country ); + + if (codepage != 0xffff && codepage != GetOEMCP()) + FIXME( "Requested info on non-default code page %04x\n", codepage ); + } + + switch (AL_reg(context)) { + case 0x00: /* SET GENERAL INTERNATIONALIZATION INFO */ + INT_BARF( context, 0x21 ); + SET_CFLAG( context ); + break; + + case 0x01: /* GET GENERAL INTERNATIONALIZATION INFO */ + TRACE( "Get general internationalization info\n" ); + dataptr[0] = 0x01; /* Info ID */ + *(WORD*)(dataptr+1) = 38; /* Size of the following info */ + *(WORD*)(dataptr+3) = INT21_GetSystemCountryCode(); /* Country ID */ + *(WORD*)(dataptr+5) = GetOEMCP(); /* Code page */ + INT21_FillCountryInformation( dataptr + 7 ); + SET_CX( context, 41 ); /* Size of returned info */ + break; + + case 0x02: /* GET POINTER TO UPPERCASE TABLE */ + case 0x04: /* GET POINTER TO FILENAME UPPERCASE TABLE */ + TRACE( "Get pointer to uppercase table\n" ); + dataptr[0] = AL_reg(context); /* Info ID */ + *(DWORD*)(dataptr+1) = MAKESEGPTR( INT21_GetHeapSelector( context ), + offsetof(INT21_HEAP, uppercase_size) ); + SET_CX( context, 5 ); /* Size of returned info */ + break; + + case 0x03: /* GET POINTER TO LOWERCASE TABLE */ + TRACE( "Get pointer to lowercase table\n" ); + dataptr[0] = 0x03; /* Info ID */ + *(DWORD*)(dataptr+1) = MAKESEGPTR( INT21_GetHeapSelector( context ), + offsetof(INT21_HEAP, lowercase_size) ); + SET_CX( context, 5 ); /* Size of returned info */ + break; + + case 0x05: /* GET POINTER TO FILENAME TERMINATOR TABLE */ + TRACE("Get pointer to filename terminator table\n"); + dataptr[0] = 0x05; /* Info ID */ + *(DWORD*)(dataptr+1) = MAKESEGPTR( INT21_GetHeapSelector( context ), + offsetof(INT21_HEAP, filename_size) ); + SET_CX( context, 5 ); /* Size of returned info */ + break; + + case 0x06: /* GET POINTER TO COLLATING SEQUENCE TABLE */ + TRACE("Get pointer to collating sequence table\n"); + dataptr[0] = 0x06; /* Info ID */ + *(DWORD*)(dataptr+1) = MAKESEGPTR( INT21_GetHeapSelector( context ), + offsetof(INT21_HEAP, collating_size) ); + SET_CX( context, 5 ); /* Size of returned info */ + break; + + case 0x07: /* GET POINTER TO DBCS LEAD BYTE TABLE */ + TRACE("Get pointer to DBCS lead byte table\n"); + dataptr[0] = 0x07; /* Info ID */ + *(DWORD*)(dataptr+1) = MAKESEGPTR( INT21_GetHeapSelector( context ), + offsetof(INT21_HEAP, dbcs_size) ); + SET_CX( context, 5 ); /* Size of returned info */ + break; + + case 0x20: /* CAPITALIZE CHARACTER */ + case 0xa0: /* CAPITALIZE FILENAME CHARACTER */ + TRACE("Convert char to uppercase\n"); + SET_DL( context, toupper(DL_reg(context)) ); + break; + + case 0x21: /* CAPITALIZE STRING */ + case 0xa1: /* CAPITALIZE COUNTED FILENAME STRING */ + TRACE("Convert string to uppercase with length\n"); + { + char *ptr = (char *)CTX_SEG_OFF_TO_LIN( context, + context->SegDs, + context->Edx ); + WORD len = CX_reg(context); + while (len--) { *ptr = toupper(*ptr); ptr++; } + } + break; + + case 0x22: /* CAPITALIZE ASCIIZ STRING */ + case 0xa2: /* CAPITALIZE ASCIIZ FILENAME */ + TRACE("Convert ASCIIZ string to uppercase\n"); + _strupr( (LPSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx) ); + break; + + case 0x23: /* DETERMINE IF CHARACTER REPRESENTS YES/NO RESPONSE */ + INT_BARF( context, 0x21 ); + SET_CFLAG( context ); + break; + + default: + INT_BARF( context, 0x21 ); + SET_CFLAG(context); + break; + } +} + + /*********************************************************************** * INT21_GetPSP * @@ -501,10 +825,15 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context ) case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */ case 0x33: /* MULTIPLEXED */ - case 0x34: /* GET ADDRESS OF INDOS FLAG */ INT_Int21Handler( context ); break; + case 0x34: /* GET ADDRESS OF INDOS FLAG */ + TRACE( "GET ADDRESS OF INDOS FLAG\n" ); + context->SegEs = INT21_GetHeapSelector( context ); + SET_BX( context, offsetof(INT21_HEAP, misc_indos) ); + break; + case 0x35: /* GET INTERRUPT VECTOR */ TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context)); { @@ -524,10 +853,20 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context ) break; case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */ - TRACE( "GET COUNTRY-SPECIFIC INFORMATION for country 0x%02x\n", - AL_reg(context) ); - SET_AX( context, 0x02 ); /* no country support available */ - SET_CFLAG( context ); + TRACE( "GET COUNTRY-SPECIFIC INFORMATION\n" ); + if (AL_reg(context)) + { + WORD country = AL_reg(context); + if (country == 0xff) + country = BX_reg(context); + if (country != INT21_GetSystemCountryCode()) + FIXME( "Requested info on non-default country %04x\n", country ); + } + INT21_FillCountryInformation( CTX_SEG_OFF_TO_LIN(context, + context->SegDs, + context->Edx) ); + SET_AX( context, INT21_GetSystemCountryCode() ); + SET_BX( context, INT21_GetSystemCountryCode() ); break; case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */ @@ -723,16 +1062,26 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context ) case 0x5e: /* NETWORK 5E */ case 0x5f: /* NETWORK 5F */ case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */ - case 0x61: /* UNUSED */ INT_Int21Handler( context ); break; + case 0x61: /* UNUSED */ + SET_AL( context, 0 ); + break; + case 0x62: /* GET PSP ADDRESS */ INT21_GetPSP( context ); break; case 0x63: /* MISC. LANGUAGE SUPPORT */ - INT_Int21Handler( context ); + switch (AL_reg(context)) { + case 0x00: /* GET DOUBLE BYTE CHARACTER SET LEAD-BYTE TABLE */ + TRACE( "GET DOUBLE BYTE CHARACTER SET LEAD-BYTE TABLE\n" ); + context->SegDs = INT21_GetHeapSelector( context ); + SET_SI( context, offsetof(INT21_HEAP, dbcs_table) ); + SET_AL( context, 0 ); /* success */ + break; + } break; case 0x64: /* OS/2 DOS BOX */ @@ -740,9 +1089,23 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context ) SET_CFLAG(context); break; - case 0x65: /* GET EXTENDED COUNTRY INFORMATION */ + case 0x65: /* EXTENDED COUNTRY INFORMATION */ + INT21_ExtendedCountryInformation( context ); + break; + case 0x66: /* GLOBAL CODE PAGE TABLE */ - INT_Int21Handler( context ); + switch (AL_reg(context)) + { + case 0x01: + TRACE( "GET GLOBAL CODE PAGE TABLE\n" ); + SET_BX( context, GetOEMCP() ); + SET_DX( context, GetOEMCP() ); + break; + case 0x02: + FIXME( "SET GLOBAL CODE PAGE TABLE, active %d, system %d - ignored\n", + BX_reg(context), DX_reg(context) ); + break; + } break; case 0x67: /* SET HANDLE COUNT */ diff --git a/include/miscemu.h b/include/miscemu.h index edd1765e5b1..311163dfa33 100644 --- a/include/miscemu.h +++ b/include/miscemu.h @@ -162,7 +162,6 @@ typedef struct extern WORD DOSMEM_0000H; extern WORD DOSMEM_BiosDataSeg; extern WORD DOSMEM_BiosSysSeg; -extern DWORD DOSMEM_CollateTable; /* msdos/dosmem.c */ extern BOOL DOSMEM_Init(BOOL); diff --git a/msdos/dosmem.c b/msdos/dosmem.c index 8c72dc625b0..a868ddb0930 100644 --- a/msdos/dosmem.c +++ b/msdos/dosmem.c @@ -50,8 +50,6 @@ WORD DOSMEM_0000H; /* segment at 0:0 */ WORD DOSMEM_BiosDataSeg; /* BIOS data segment at 0x40:0 */ WORD DOSMEM_BiosSysSeg; /* BIOS ROM segment at 0xf000:0 */ -DWORD DOSMEM_CollateTable; - /* use 2 low bits of 'size' for the housekeeping */ #define DM_BLOCK_DEBUG 0xABE00000 @@ -306,80 +304,6 @@ static void DOSMEM_FillBiosSegments(void) *(pBiosSys+0xfffe) = 0xfc; } -/*********************************************************************** - * DOSMEM_InitCollateTable - * - * Initialises the collate table (character sorting, language dependent) - */ -static void DOSMEM_InitCollateTable() -{ - DWORD x; - unsigned char *tbl; - int i; - - x = GlobalDOSAlloc16(258); - DOSMEM_CollateTable = MAKELONG(0,(x>>16)); - tbl = DOSMEM_MapRealToLinear(DOSMEM_CollateTable); - *(WORD*)tbl = 0x100; - tbl += 2; - for ( i = 0; i < 0x100; i++) *tbl++ = i; -} - -/*********************************************************************** - * DOSMEM_InitErrorTable - * - * Initialises the error tables (DOS 5+) - */ -static void DOSMEM_InitErrorTable() -{ -#if 0 /* no longer used */ - DWORD x; - char *call; - - /* We will use a snippet of real mode code that calls */ - /* a WINE-only interrupt to handle moving the requested */ - /* message into the buffer... */ - - /* FIXME - There is still something wrong... */ - - /* FIXME - Find hex values for opcodes... - - (On call, AX contains message number - DI contains 'offset' (??) - Resturn, ES:DI points to counted string ) - - PUSH BX - MOV BX, AX - MOV AX, (arbitrary subfunction number) - INT (WINE-only interrupt) - POP BX - RET - - */ - - const int code = 4; - const int buffer = 80; - const int SIZE_TO_ALLOCATE = code + buffer; - - /* FIXME - Complete rewrite of the table system to save */ - /* precious DOS space. Now, we return the 0001:???? as */ - /* DOS 4+ (??, it seems to be the case in MS 7.10) treats that */ - /* as a special case and programs will use the alternate */ - /* interface (a farcall returned with INT 24 (AX = 0x122e, DL = */ - /* 0x08) which lets us have a smaller memory footprint anyway. */ - - x = GlobalDOSAlloc16(SIZE_TO_ALLOCATE); - - DOSMEM_ErrorCall = MAKELONG(0,(x>>16)); - DOSMEM_ErrorBuffer = DOSMEM_ErrorCall + code; - - call = DOSMEM_MapRealToLinear(DOSMEM_ErrorCall); - - memset(call, 0, SIZE_TO_ALLOCATE); -#endif - /* FIXME - Copy assembly into buffer here */ -} - /*********************************************************************** * DOSMEM_InitMemory * @@ -480,8 +404,6 @@ BOOL DOSMEM_Init(BOOL dos_init) DOSMEM_FillBiosSegments(); DOSMEM_FillIsrTable(); DOSMEM_InitMemory(); - DOSMEM_InitCollateTable(); - DOSMEM_InitErrorTable(); already_done = 1; } else if (dos_init && !already_mapped) diff --git a/msdos/int21.c b/msdos/int21.c index 6ef08ebe73a..cc2148f7199 100644 --- a/msdos/int21.c +++ b/msdos/int21.c @@ -122,15 +122,12 @@ struct EDPB /* FAT32 extended Drive Parameter Block */ }; -WORD CodePage = 437; DWORD dpbsegptr; struct DosHeap { - BYTE InDosFlag; BYTE mediaID; BYTE biosdate[8]; struct DPB dpb; - BYTE DummyDBCSLeadTable[6]; }; static struct DosHeap *heap; static WORD DosHeapHandle; @@ -153,9 +150,7 @@ static BOOL INT21_CreateHeap(void) } heap = (struct DosHeap *) GlobalLock16(DosHeapHandle); dpbsegptr = MAKESEGPTR(DosHeapHandle,(int)&heap->dpb-(int)heap); - heap->InDosFlag = 0; strcpy(heap->biosdate, "01/01/80"); - memset(heap->DummyDBCSLeadTable, 0, 6); return TRUE; } @@ -751,21 +746,6 @@ static BOOL INT21_GetCurrentDirectory( CONTEXT86 *context ) } -static void INT21_GetDBCSLeadTable( CONTEXT86 *context ) -{ - if (heap || INT21_CreateHeap()) - { /* return an empty table just as DOS 4.0+ does */ - context->SegDs = DosHeapHandle; - SET_SI( context, (int)&heap->DummyDBCSLeadTable - (int)heap ); - } - else - { - SET_AX( context, 0x1 ); /* error */ - SET_CFLAG(context); - } -} - - static int INT21_GetDiskSerialNumber( CONTEXT86 *context ) { BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx); @@ -1167,13 +1147,6 @@ void WINAPI INT_Int21Handler( CONTEXT86 *context ) } break; - case 0x34: /* GET ADDRESS OF INDOS FLAG */ - TRACE("GET ADDRESS OF INDOS FLAG\n"); - if (!heap) INT21_CreateHeap(); - context->SegEs = DosHeapHandle; - SET_BX( context, (int)&heap->InDosFlag - (int)heap ); - break; - case 0x36: /* GET FREE DISK SPACE */ TRACE("GET FREE DISK SPACE FOR DRIVE %s\n", INT21_DriveName( DL_reg(context))); @@ -1639,76 +1612,6 @@ void WINAPI INT_Int21Handler( CONTEXT86 *context ) } break; - case 0x61: /* UNUSED */ - case 0x63: /* misc. language support */ - switch (AL_reg(context)) { - case 0x00: /* GET DOUBLE BYTE CHARACTER SET LEAD-BYTE TABLE */ - INT21_GetDBCSLeadTable(context); - break; - } - break; - - case 0x65:{/* GET EXTENDED COUNTRY INFORMATION */ - BYTE *dataptr=CTX_SEG_OFF_TO_LIN(context, context->SegEs,context->Edi); - TRACE("GET EXTENDED COUNTRY INFORMATION code page %d country %d\n", - BX_reg(context), DX_reg(context)); - switch (AL_reg(context)) { - case 0x01: - TRACE("\tget general internationalization info\n"); - dataptr[0] = 0x1; - *(WORD*)(dataptr+1) = 41; - *(WORD*)(dataptr+3) = GetSystemDefaultLangID(); - *(WORD*)(dataptr+5) = CodePage; - *(DWORD*)(dataptr+0x19) = 0; /* FIXME: ptr to case map routine */ - break; - case 0x06: - TRACE("\tget pointer to collating sequence table\n"); - dataptr[0] = 0x06; - *(DWORD*)(dataptr+1) = MAKELONG(DOSMEM_CollateTable & 0xFFFF,DOSMEM_AllocSelector(DOSMEM_CollateTable>>16)); - SET_CX( context, 258 );/*FIXME: size of table?*/ - break; - case 0x20: - TRACE("\tConvert char to uppercase\n"); - SET_DL( context, toupper(DL_reg(context)) ); - break; - case 0x21: - TRACE("\tconvert string to uppercase with length\n"); - { - char *ptr = (char *)CTX_SEG_OFF_TO_LIN(context,context->SegDs,context->Edx); - WORD len = CX_reg(context); - while (len--) { *ptr = toupper(*ptr); ptr++; } - } - break; - case 0x22: - TRACE("\tConvert ASCIIZ string to uppercase\n"); - _strupr( (LPSTR)CTX_SEG_OFF_TO_LIN(context,context->SegDs,context->Edx) ); - break; - default: - TRACE("\tunimplemented function %d\n",AL_reg(context)); - INT_BARF( context, 0x21 ); - SET_CFLAG(context); - break; - } - break; - } - case 0x66: /* GLOBAL CODE PAGE TABLE */ - switch (AL_reg(context)) - { - case 0x01: - TRACE("GET GLOBAL CODE PAGE TABLE\n"); - SET_BX( context, CodePage ); - SET_DX( context, CodePage ); - RESET_CFLAG(context); - break; - case 0x02: - TRACE("SET GLOBAL CODE PAGE TABLE active page %d system page %d\n", - BX_reg(context),DX_reg(context)); - CodePage = BX_reg(context); - RESET_CFLAG(context); - break; - } - break; - case 0x68: /* "FFLUSH" - COMMIT FILE */ case 0x6a: /* COMMIT FILE */ TRACE("FFLUSH/COMMIT handle %d\n",BX_reg(context));