msvcrt: Use newer ioinfo structure for _MSVC_VER >= 80.

Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
Signed-off-by: Piotr Caban <piotr@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2022-04-04 18:52:19 +03:00 committed by Alexandre Julliard
parent 4c90f58bb5
commit 1c9e9ec360
2 changed files with 118 additions and 40 deletions

View File

@ -97,17 +97,17 @@ static void test_ioinfo_flags(void)
info = &__pioinfo[tempfd / MSVCRT_FD_BLOCK_SIZE][tempfd % MSVCRT_FD_BLOCK_SIZE];
ok(!!info, "NULL info.\n");
ok(info->handle == handle, "Unexpected handle %p, expected %p.\n", info->handle, handle);
todo_wine ok(info->exflag == 1, "Unexpected exflag %#x.\n", info->exflag);
ok(info->exflag == 1, "Unexpected exflag %#x.\n", info->exflag);
ok(info->wxflag == (WX_TEXT | WX_OPEN), "Unexpected wxflag %#x.\n", info->wxflag);
todo_wine ok(info->unicode, "Unicode is not set.\n");
todo_wine ok(info->textmode == 2, "Unexpected textmode %d.\n", info->textmode);
ok(info->unicode, "Unicode is not set.\n");
ok(info->textmode == 2, "Unexpected textmode %d.\n", info->textmode);
p__close(tempfd);
ok(info->handle == INVALID_HANDLE_VALUE, "Unexpected handle %p.\n", info->handle);
todo_wine ok(info->exflag == 1, "Unexpected exflag %#x.\n", info->exflag);
todo_wine ok(info->unicode, "Unicode is not set.\n");
ok(info->exflag == 1, "Unexpected exflag %#x.\n", info->exflag);
ok(info->unicode, "Unicode is not set.\n");
ok(!info->wxflag, "Unexpected wxflag %#x.\n", info->wxflag);
todo_wine ok(info->textmode == 2, "Unexpected textmode %d.\n", info->textmode);
ok(info->textmode == 2, "Unexpected textmode %d.\n", info->textmode);
info = &__pioinfo[(tempfd + 4) / MSVCRT_FD_BLOCK_SIZE][(tempfd + 4) % MSVCRT_FD_BLOCK_SIZE];
ok(!!info, "NULL info.\n");
@ -119,7 +119,7 @@ static void test_ioinfo_flags(void)
ok(tempfd != -1, "_open failed with error: %d\n", errno);
info = &__pioinfo[tempfd / MSVCRT_FD_BLOCK_SIZE][tempfd % MSVCRT_FD_BLOCK_SIZE];
ok(!!info, "NULL info.\n");
todo_wine ok(info->exflag == 1, "Unexpected exflag %#x.\n", info->exflag);
ok(info->exflag == 1, "Unexpected exflag %#x.\n", info->exflag);
ok(info->wxflag == (WX_TEXT | WX_OPEN), "Unexpected wxflag %#x.\n", info->wxflag);
ok(!info->unicode, "Unicode is not set.\n");
ok(!info->textmode, "Unexpected textmode %d.\n", info->textmode);
@ -129,10 +129,10 @@ static void test_ioinfo_flags(void)
ok(tempfd != -1, "_open failed with error: %d\n", errno);
info = &__pioinfo[tempfd / MSVCRT_FD_BLOCK_SIZE][tempfd % MSVCRT_FD_BLOCK_SIZE];
ok(!!info, "NULL info.\n");
todo_wine ok(info->exflag == 1, "Unexpected exflag %#x.\n", info->exflag);
ok(info->exflag == 1, "Unexpected exflag %#x.\n", info->exflag);
ok(info->wxflag == (WX_TEXT | WX_OPEN), "Unexpected wxflag %#x.\n", info->wxflag);
ok(!info->unicode, "Unicode is not set.\n");
todo_wine ok(info->textmode == 1, "Unexpected textmode %d.\n", info->textmode);
ok(info->textmode == 1, "Unexpected textmode %d.\n", info->textmode);
p__close(tempfd);
unlink(tempf);

View File

@ -85,22 +85,22 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
#define WX_TTY 0x40
#define WX_TEXT 0x80
/* values for exflag - it's used differently in msvcr90.dll*/
#define EF_UTF8 0x01
#define EF_UTF16 0x02
#define EF_CRIT_INIT 0x04
#define EF_UNK_UNICODE 0x08
static char utf8_bom[3] = { 0xef, 0xbb, 0xbf };
static char utf16_bom[2] = { 0xff, 0xfe };
enum textmode
{
TEXTMODE_ANSI,
TEXTMODE_UTF8,
TEXTMODE_UTF16LE,
};
/* FIXME: this should be allocated dynamically */
#define MSVCRT_MAX_FILES 2048
#define MSVCRT_FD_BLOCK_SIZE 32
#define MSVCRT_INTERNAL_BUFSIZ 4096
/* ioinfo structure size is different in msvcrXX.dll's */
typedef struct {
HANDLE handle;
unsigned char wxflag;
@ -129,6 +129,82 @@ ioinfo * MSVCRT___pioinfo[MSVCRT_MAX_FILES/MSVCRT_FD_BLOCK_SIZE] = { 0 };
*/
ioinfo MSVCRT___badioinfo = { INVALID_HANDLE_VALUE, WX_TEXT };
#if _MSVCR_VER >= 80
static inline BOOL ioinfo_is_crit_init(ioinfo *info)
{
return info->exflag & 1;
}
static inline void ioinfo_set_crit_init(ioinfo *info)
{
info->exflag |= 1;
}
static inline enum textmode ioinfo_get_textmode(ioinfo *info)
{
return info->textmode;
}
static inline void ioinfo_set_textmode(ioinfo *info, enum textmode mode)
{
info->textmode = mode;
}
static inline void ioinfo_set_unicode(ioinfo *info, BOOL unicode)
{
info->unicode = !!unicode;
}
#else
#define EF_UTF8 0x01
#define EF_UTF16 0x02
#define EF_CRIT_INIT 0x04
#define EF_UNK_UNICODE 0x08
static inline BOOL ioinfo_is_crit_init(ioinfo *info)
{
return info->exflag & EF_CRIT_INIT;
}
static inline void ioinfo_set_crit_init(ioinfo *info)
{
info->exflag |= EF_CRIT_INIT;
}
static inline enum textmode ioinfo_get_textmode(ioinfo *info)
{
if (info->exflag & EF_UTF8)
return TEXTMODE_UTF8;
if (info->exflag & EF_UTF16)
return TEXTMODE_UTF16LE;
return TEXTMODE_ANSI;
}
static inline void ioinfo_set_textmode(ioinfo *info, enum textmode mode)
{
info->exflag &= EF_CRIT_INIT | EF_UNK_UNICODE;
switch (mode)
{
case TEXTMODE_ANSI:
break;
case TEXTMODE_UTF8:
info->exflag |= EF_UTF8;
break;
case TEXTMODE_UTF16LE:
info->exflag |= EF_UTF16;
break;
}
}
static inline void ioinfo_set_unicode(ioinfo *info, BOOL unicode)
{
if (unicode)
info->exflag |= EF_UNK_UNICODE;
else
info->exflag &= ~EF_UNK_UNICODE;
}
#endif
typedef struct {
FILE file;
CRITICAL_SECTION crit;
@ -269,11 +345,11 @@ static inline ioinfo* get_ioinfo_nolock(int fd)
static inline void init_ioinfo_cs(ioinfo *info)
{
if(!(info->exflag & EF_CRIT_INIT)) {
if(!ioinfo_is_crit_init(info)) {
LOCK_FILES();
if(!(info->exflag & EF_CRIT_INIT)) {
if(!ioinfo_is_crit_init(info)) {
InitializeCriticalSection(&info->crit);
info->exflag |= EF_CRIT_INIT;
ioinfo_set_crit_init(info);
}
UNLOCK_FILES();
}
@ -363,7 +439,7 @@ static inline ioinfo* get_ioinfo_alloc(int *fd)
static inline void release_ioinfo(ioinfo *info)
{
if(info!=&MSVCRT___badioinfo && info->exflag & EF_CRIT_INIT)
if(info!=&MSVCRT___badioinfo && ioinfo_is_crit_init(info))
LeaveCriticalSection(&info->crit);
}
@ -430,7 +506,8 @@ static void msvcrt_set_fd(ioinfo *fdinfo, HANDLE hand, int flag)
fdinfo->lookahead[0] = '\n';
fdinfo->lookahead[1] = '\n';
fdinfo->lookahead[2] = '\n';
fdinfo->exflag &= EF_CRIT_INIT;
ioinfo_set_unicode(fdinfo, FALSE);
ioinfo_set_textmode(fdinfo, TEXTMODE_ANSI);
if (hand == MSVCRT_NO_CONSOLE) hand = 0;
switch (fdinfo-MSVCRT___pioinfo[0])
@ -1244,7 +1321,7 @@ void msvcrt_free_io(void)
for(j=0; j<MSVCRT_FD_BLOCK_SIZE; j++)
{
if(MSVCRT___pioinfo[i][j].exflag & EF_CRIT_INIT)
if(ioinfo_is_crit_init(&MSVCRT___pioinfo[i][j]))
DeleteCriticalSection(&MSVCRT___pioinfo[i][j].crit);
}
free(MSVCRT___pioinfo[i]);
@ -2363,12 +2440,12 @@ int CDECL _wsopen_dispatch( const wchar_t* path, int oflags, int shflags, int pm
return *_errno();
if (oflags & _O_WTEXT)
get_ioinfo_nolock(*fd)->exflag |= EF_UNK_UNICODE;
ioinfo_set_unicode(get_ioinfo_nolock(*fd), TRUE);
if (oflags & _O_U16TEXT)
get_ioinfo_nolock(*fd)->exflag |= EF_UTF16;
ioinfo_set_textmode(get_ioinfo_nolock(*fd), TEXTMODE_UTF16LE);
else if (oflags & _O_U8TEXT)
get_ioinfo_nolock(*fd)->exflag |= EF_UTF8;
ioinfo_set_textmode(get_ioinfo_nolock(*fd), TEXTMODE_UTF8);
TRACE(":fd (%d) handle (%p)\n", *fd, hand);
return 0;
@ -2785,14 +2862,14 @@ static int read_i(int fd, ioinfo *fdinfo, void *buf, unsigned int count)
return -1;
}
utf16 = (fdinfo->exflag & EF_UTF16) != 0;
if (((fdinfo->exflag&EF_UTF8) || utf16) && count&1)
utf16 = ioinfo_get_textmode(fdinfo) == TEXTMODE_UTF16LE;
if (ioinfo_get_textmode(fdinfo) != TEXTMODE_ANSI && count&1)
{
*_errno() = EINVAL;
return -1;
}
if((fdinfo->wxflag&WX_TEXT) && (fdinfo->exflag&EF_UTF8))
if((fdinfo->wxflag&WX_TEXT) && ioinfo_get_textmode(fdinfo) == TEXTMODE_UTF8)
return read_utf8(fdinfo, buf, count);
if (fdinfo->lookahead[0]!='\n' || ReadFile(fdinfo->handle, bufstart, count, &num_read, NULL))
@ -2948,7 +3025,8 @@ int CDECL _setmode(int fd,int mode)
{
ioinfo *info = get_ioinfo(fd);
int ret = info->wxflag & WX_TEXT ? _O_TEXT : _O_BINARY;
if(ret==_O_TEXT && (info->exflag & (EF_UTF8|EF_UTF16)))
if(ret==_O_TEXT && ioinfo_get_textmode(info) != TEXTMODE_ANSI)
ret = _O_WTEXT;
if(mode!=_O_TEXT && mode!=_O_BINARY && mode!=_O_WTEXT
@ -2965,18 +3043,18 @@ int CDECL _setmode(int fd,int mode)
if(mode == _O_BINARY) {
info->wxflag &= ~WX_TEXT;
info->exflag &= ~(EF_UTF8|EF_UTF16);
ioinfo_set_textmode(info, TEXTMODE_ANSI);
release_ioinfo(info);
return ret;
}
info->wxflag |= WX_TEXT;
if(mode == _O_TEXT)
info->exflag &= ~(EF_UTF8|EF_UTF16);
ioinfo_set_textmode(info, TEXTMODE_ANSI);
else if(mode == _O_U8TEXT)
info->exflag = (info->exflag & ~EF_UTF16) | EF_UTF8;
ioinfo_set_textmode(info, TEXTMODE_UTF8);
else
info->exflag = (info->exflag & ~EF_UTF8) | EF_UTF16;
ioinfo_set_textmode(info, TEXTMODE_UTF16LE);
release_ioinfo(info);
return ret;
@ -3436,7 +3514,7 @@ int CDECL _write(int fd, const void* buf, unsigned int count)
return -1;
}
if (((info->exflag&EF_UTF8) || (info->exflag&EF_UTF16)) && count&1)
if (ioinfo_get_textmode(info) != TEXTMODE_ANSI && count&1)
{
*_errno() = EINVAL;
release_ioinfo(info);
@ -3469,7 +3547,7 @@ int CDECL _write(int fd, const void* buf, unsigned int count)
char lfbuf[2048];
DWORD j = 0;
if (!(info->exflag & (EF_UTF8|EF_UTF16)) && console)
if (ioinfo_get_textmode(info) == TEXTMODE_ANSI && console)
{
char conv[sizeof(lfbuf)];
size_t len = 0;
@ -3521,7 +3599,7 @@ int CDECL _write(int fd, const void* buf, unsigned int count)
}
j = len * 2;
}
else if (!(info->exflag & (EF_UTF8|EF_UTF16)))
else if (ioinfo_get_textmode(info) == TEXTMODE_ANSI)
{
for (j = 0; i < count && j < sizeof(lfbuf)-1; i++, j++)
{
@ -3530,7 +3608,7 @@ int CDECL _write(int fd, const void* buf, unsigned int count)
lfbuf[j] = s[i];
}
}
else if (info->exflag & EF_UTF16 || console)
else if (ioinfo_get_textmode(info) == TEXTMODE_UTF16LE || console)
{
for (j = 0; i < count && j < sizeof(lfbuf)-3; i++, j++)
{
@ -3811,7 +3889,7 @@ wint_t CDECL _fgetwc_nolock(FILE* file)
wint_t ret;
int ch;
if((get_ioinfo_nolock(file->_file)->exflag & (EF_UTF8 | EF_UTF16))
if(ioinfo_get_textmode(get_ioinfo_nolock(file->_file)) != TEXTMODE_ANSI
|| !(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) {
char *p;
@ -4082,7 +4160,7 @@ wint_t CDECL _fputwc_nolock(wint_t wc, FILE* file)
fdinfo = get_ioinfo_nolock(file->_file);
if((fdinfo->wxflag&WX_TEXT) && !(fdinfo->exflag&(EF_UTF8|EF_UTF16))) {
if((fdinfo->wxflag&WX_TEXT) && ioinfo_get_textmode(fdinfo) == TEXTMODE_ANSI) {
char buf[MB_LEN_MAX];
int char_len;
@ -5595,7 +5673,7 @@ wint_t CDECL _ungetwc_nolock(wint_t wc, FILE * file)
if (wc == WEOF)
return WEOF;
if((get_ioinfo_nolock(file->_file)->exflag & (EF_UTF8 | EF_UTF16))
if(ioinfo_get_textmode(get_ioinfo_nolock(file->_file)) != TEXTMODE_ANSI
|| !(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) {
unsigned char * pp = (unsigned char *)&mwc;
int i;