Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/core/basetypes/MCDataStreamDecoder.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include "MCWin32.h" // should be first include.

#include "MCDataStreamDecoder.h"

#include "MCString.h"
Expand Down
86 changes: 85 additions & 1 deletion src/core/basetypes/MCWin32.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
#include "MCWin32.h"
#include <io.h>
#include <wchar.h>

FILE * mailcore::win32_fopen(const char * filename, const char * mode)
// DSK-658: caller frees. Returns NULL when the input is not valid UTF-8.
static wchar_t * win32_path_to_wide(const char * path)
{
if (path == NULL) {
return NULL;
}
int count = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, path, -1, NULL, 0);
if (count <= 0) {
return NULL;
}
wchar_t * widePath = (wchar_t *) malloc(count * sizeof(* widePath));
if (widePath == NULL) {
return NULL;
}
if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, path, -1, widePath, count) <= 0) {
free(widePath);
return NULL;
}
return widePath;
}

static FILE * win32_fopen_narrow(const char * filename, const char * mode)
{
FILE * f = NULL;
int r = fopen_s(&f, filename, mode);
Expand All @@ -11,6 +33,68 @@ FILE * mailcore::win32_fopen(const char * filename, const char * mode)
return f;
}

FILE * mailcore::win32_fopen(const char * filename, const char * mode)
{
if (mode == NULL) {
return win32_fopen_narrow(filename, mode);
}
size_t modeLength = strlen(mode);
wchar_t wideMode[16];
if (modeLength >= sizeof(wideMode) / sizeof(wideMode[0])) {
return win32_fopen_narrow(filename, mode);
}
wchar_t * wideFilename = win32_path_to_wide(filename);
if (wideFilename == NULL) {
return win32_fopen_narrow(filename, mode);
}
// mode is ASCII by contract, widen it char-by-char
for (size_t i = 0; i <= modeLength; i++) {
wideMode[i] = (wchar_t) (unsigned char) mode[i];
}
FILE * f = NULL;
errno_t r = _wfopen_s(&f, wideFilename, wideMode);
free(wideFilename);
if (r != 0) {
return NULL;
}
return f;
}

int mailcore::win32_unlink(const char * path)
{
wchar_t * widePath = win32_path_to_wide(path);
if (widePath == NULL) {
return _unlink(path);
}
int r = _wunlink(widePath);
free(widePath);
return r;
}

int mailcore::win32_mkdir(const char * path)
{
wchar_t * widePath = win32_path_to_wide(path);
if (widePath == NULL) {
return _mkdir(path);
}
int r = _wmkdir(widePath);
free(widePath);
return r;
}

int mailcore::win32_stat(const char * path, struct stat * buffer)
{
// struct stat is struct _stat64i32 in the UCRT unless _USE_32BIT_TIME_T is set
static_assert(sizeof(struct stat) == sizeof(struct _stat64i32), "unexpected struct stat layout");
wchar_t * widePath = win32_path_to_wide(path);
if (widePath == NULL) {
return _stat64i32(path, (struct _stat64i32 *) buffer);
}
int r = _wstat64i32(widePath, (struct _stat64i32 *) buffer);
free(widePath);
return r;
}

static const unsigned __int64 epoch = ((unsigned __int64)116444736000000000ULL);
/*
* timezone information is stored outside the kernel so tzp isn't used anymore.
Expand Down
13 changes: 11 additions & 2 deletions src/core/basetypes/MCWin32.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#include <sys/stat.h>
#include <errno.h>
#include <direct.h>
// io.h declares POSIX-compat unlink; must come before the macros below (DSK-658)
#include <io.h>
#include <wchar.h>

#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
Expand All @@ -29,8 +32,11 @@
#define strcasestr mailcore::win32_strcasestr
#define strdup _strdup
#define fileno _fileno
#define unlink _unlink
#define mkdir _mkdir
// DSK-658: paths are UTF-8; narrow CRT calls read them via the ANSI codepage
// and fail on non-ANSI paths, so route them through wide-char wrappers.
#define unlink mailcore::win32_unlink
#define mkdir mailcore::win32_mkdir
#define stat(path, buffer) mailcore::win32_stat(path, buffer)
Comment thread
OleksiiShvachenko marked this conversation as resolved.
#define fopen mailcore::win32_fopen
#define gmtime_r mailcore::win32_gmtime_r
#define localtime_r mailcore::win32_localtime_r
Expand Down Expand Up @@ -67,6 +73,9 @@ namespace mailcore {
int win32_gettimeofday(struct timeval * tp, struct timezone * tzp);

FILE * win32_fopen(const char * filename, const char * mode);
int win32_unlink(const char * path);
int win32_mkdir(const char * path);
int win32_stat(const char * path, struct stat * buffer);
int win32_vasprintf(char **strp, const char *fmt, va_list ap);
int win32_snprintf(char * str, size_t size, const char * format, ...);

Expand Down
2 changes: 2 additions & 0 deletions src/core/security/MCCertificateUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
// Copyright (c) 2013 MailCore. All rights reserved.
//

#include "MCWin32.h" // should be first include.

#include "MCCertificateUtils.h"

#if __APPLE__
Expand Down
13 changes: 11 additions & 2 deletions src/include/MailCore/MCWin32.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#include <sys/stat.h>
#include <errno.h>
#include <direct.h>
// io.h declares POSIX-compat unlink; must come before the macros below (DSK-658)
#include <io.h>
#include <wchar.h>

#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
Expand All @@ -29,8 +32,11 @@
#define strcasestr mailcore::win32_strcasestr
#define strdup _strdup
#define fileno _fileno
#define unlink _unlink
#define mkdir _mkdir
// DSK-658: paths are UTF-8; narrow CRT calls read them via the ANSI codepage
// and fail on non-ANSI paths, so route them through wide-char wrappers.
#define unlink mailcore::win32_unlink
#define mkdir mailcore::win32_mkdir
#define stat(path, buffer) mailcore::win32_stat(path, buffer)
#define fopen mailcore::win32_fopen
#define gmtime_r mailcore::win32_gmtime_r
#define localtime_r mailcore::win32_localtime_r
Expand Down Expand Up @@ -67,6 +73,9 @@ namespace mailcore {
int win32_gettimeofday(struct timeval * tp, struct timezone * tzp);

FILE * win32_fopen(const char * filename, const char * mode);
int win32_unlink(const char * path);
int win32_mkdir(const char * path);
int win32_stat(const char * path, struct stat * buffer);
int win32_vasprintf(char **strp, const char *fmt, va_list ap);
int win32_snprintf(char * str, size_t size, const char * format, ...);

Expand Down
Loading