9 #ifndef INVALID_FILE_ATTRIBUTES 10 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) 19 #define IS_DIR_SEPARATOR_P(c) (c == L'\\' || c == L'/') 20 #define IS_DIR_UNC_P(c) (IS_DIR_SEPARATOR_P(c[0]) && IS_DIR_SEPARATOR_P(c[1])) 23 #define INVALID_CODE_PAGE 51932 24 #define PATH_BUFFER_SIZE MAX_PATH * 2 26 #define insecure_obj_p(obj, level) ((level) >= 4 || ((level) > 0 && OBJ_TAINTED(obj))) 44 len = MultiByteToWideChar(
code_page, 0, str, -1,
NULL, 0) + 1;
45 *wstr = (
wchar_t *)
xmalloc(len *
sizeof(
wchar_t));
47 MultiByteToWideChar(
code_page, 0, str, -1, *wstr, len);
57 *str = (
char *)
xmalloc(len *
sizeof(
char));
75 wchar_t *buffer =
NULL;
76 size_t buffer_len = 0, len = 0;
85 if (len = GetEnvironmentVariableW(L
"HOME",
NULL, 0)) {
89 else if (len = GetEnvironmentVariableW(L
"HOMEDRIVE",
NULL, 0)) {
91 if (len = GetEnvironmentVariableW(L
"HOMEPATH",
NULL, 0)) {
99 else if (len = GetEnvironmentVariableW(L
"USERPROFILE",
NULL, 0)) {
106 buffer = (
wchar_t *)
xmalloc(buffer_len *
sizeof(
wchar_t));
111 GetEnvironmentVariableW(L
"HOME", buffer, buffer_len);
115 len = GetEnvironmentVariableW(L
"HOMEDRIVE", buffer, buffer_len);
116 GetEnvironmentVariableW(L
"HOMEPATH", buffer + len, buffer_len - len);
120 GetEnvironmentVariableW(L
"USERPROFILE", buffer, buffer_len);
140 static const wchar_t prime[] = L
":$DATA";
141 enum { prime_len = (
sizeof(prime) /
sizeof(
wchar_t)) -1 };
143 if (
size <= prime_len || _wcsnicmp(wfullpath +
size - prime_len, prime, prime_len) != 0)
148 if (wfullpath[
size - (prime_len + 1)] ==
':') {
150 size -= prime_len + 1;
151 wfullpath[
size] = L
'\0';
155 wchar_t *pos = wfullpath +
size - (prime_len + 1);
159 wfullpath[
size] = L
'\0';
172 return AreFileApisANSI() ? CP_ACP : CP_OEMCP;
180 const char *n = (
const char *)
name;
181 if (strncmp(
"CP", n, 2) == 0) {
188 unsigned int i =
count;
225 #define fix_string_encoding(str, encoding) rb_str_conv_enc((str), (encoding), rb_utf8_encoding()) 234 WIN32_FIND_DATAW find_data;
246 size_t const max_short_name_size = 8 + 1 + 3;
247 size_t const max_extension_size = 3;
248 size_t path_len = 1, extension_len = 0;
249 wchar_t *pos = *wfullpath;
251 if (
size == 3 && pos[1] == L
':' && pos[2] == L
'\\' && pos[3] == L
'\0') {
257 if (wcspbrk(pos, L
"*?")) {
261 pos = *wfullpath +
size - 1;
263 if (!extension_len && *pos == L
'.') {
264 extension_len = path_len - 1;
266 if (path_len > max_short_name_size || extension_len > max_extension_size) {
273 find_handle = FindFirstFileW(*wfullpath, &find_data);
274 if (find_handle != INVALID_HANDLE_VALUE) {
275 size_t trail_pos = wcslen(*wfullpath);
276 size_t file_len = wcslen(find_data.cFileName);
278 FindClose(find_handle);
279 while (trail_pos > 0) {
284 size = trail_pos + 1 + file_len;
285 if ((
size + 1) >
sizeof(*wfullpath) /
sizeof((*wfullpath)[0])) {
287 wcsncpy(
buf, *wfullpath, trail_pos + 1);
292 wcsncpy(*wfullpath + trail_pos + 1, find_data.cFileName, file_len + 1);
301 wchar_t *wuser = *wpath + offset;
302 wchar_t *pos = wuser;
331 size_t size = 0, wpath_len = 0, wdir_len = 0, whome_len = 0;
332 size_t buffer_len = 0;
333 char *fullpath =
NULL;
334 wchar_t *wfullpath =
NULL, *wpath =
NULL, *wpath_pos =
NULL;
335 wchar_t *wdir =
NULL, *wdir_pos =
NULL;
336 wchar_t *whome =
NULL, *buffer =
NULL, *buffer_pos =
NULL;
338 VALUE path = fname, dir = dname;
340 wchar_t path_drive = L
'\0', dir_drive = L
'\0';
374 if (abs_mode == 0 && wpath_len > 0 && wpath_pos[0] == L
'~' &&
384 whome_len = wcslen(whome);
386 if (PathIsRelativeW(whome) && !(whome_len >= 2 &&
IS_DIR_UNC_P(whome))) {
411 else if (wpath_len >= 2 && wpath_pos[1] == L
':') {
418 path_drive = wpath_pos[0];
423 else if (abs_mode == 0 && wpath_len >= 2 && wpath_pos[0] == L
'~') {
433 if (!ignore_dir && !
NIL_P(dir)) {
445 if (abs_mode == 0 && wdir_len > 0 && wdir_pos[0] == L
'~' &&
456 whome_len = wcslen(whome);
458 if (PathIsRelativeW(whome) && !(whome_len >= 2 &&
IS_DIR_UNC_P(whome))) {
475 else if (wdir_len >= 2 && wdir[1] == L
':') {
485 size_t separators = 0;
487 while (pos < wdir_len && separators < 2) {
497 else if (abs_mode == 0 && wdir_len >= 2 && wdir_pos[0] == L
'~') {
510 if (!ignore_dir && path_drive && dir_drive) {
511 if (towupper(path_drive) != towupper(dir_drive)) {
519 if (!ignore_dir && wpath_len >= 2 &&
IS_DIR_UNC_P(wpath)) {
531 buffer_len = wpath_len + 1 + wdir_len + 1 + whome_len + 1;
533 buffer = buffer_pos = (
wchar_t *)
xmalloc((buffer_len + 1) *
sizeof(wchar_t));
537 wcsncpy(buffer_pos, whome, whome_len);
538 buffer_pos += whome_len;
542 if (whome_len && wcsrchr(L
"\\/:", buffer_pos[-1]) ==
NULL) {
543 buffer_pos[0] = L
'\\';
546 else if (!dir_drive && path_drive) {
547 *buffer_pos++ = path_drive;
548 *buffer_pos++ = L
':';
556 wcsncpy(buffer_pos, wdir_pos, wdir_len);
557 buffer_pos += wdir_len;
561 if (wdir_len && wcsrchr(L
"\\/:", buffer_pos[-1]) ==
NULL) {
562 buffer_pos[0] = L
'\\';
568 wcsncpy(buffer_pos, wpath_pos, wpath_len);
569 buffer_pos += wpath_len;
573 if (wpath_len == 0) {
574 buffer_pos[0] = L
'.';
579 buffer_pos[0] = L
'\0';
582 if (!tainted && PathIsRelativeW(buffer) && !(buffer_len >= 2 &&
IS_DIR_UNC_P(buffer)))
590 wfullpath = (
wchar_t *)
xmalloc(
size *
sizeof(
wchar_t));
594 wfullpath = wfullpath_buffer;
599 wfullpath[
size - 2] != L
':' &&
602 wfullpath[
size] = L
'\0';
606 if (wfullpath[
size - 1] == L
'.') {
608 wfullpath[
size] = L
'\0';
665 if (wfullpath && wfullpath != wfullpath_buffer)
677 return (
void *)CreateFileW(wpath, GENERIC_READ,
678 FILE_SHARE_READ | FILE_SHARE_WRITE,
679 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);
692 attr = GetFileAttributesW(wpath);
694 (attr & FILE_ATTRIBUTE_DIRECTORY)) {
700 if (h != INVALID_HANDLE_VALUE) {
static void * loadopen_func(void *wpath)
static int code_page_i(st_data_t name, st_data_t idx, st_data_t arg)
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
static UINT system_code_page(void)
#define ENC_CODERANGE_CLEAR(obj)
VALUE rb_enc_from_encoding(rb_encoding *encoding)
SSL_METHOD *(* func)(void)
void rb_str_set_len(VALUE, long)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
#define IS_DIR_SEPARATOR_P(c)
void Init_w32_codepage(void)
rb_encoding * rb_utf8_encoding(void)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
static void convert_wchar_to_mb(const wchar_t *wstr, char **str, size_t *str_len, UINT code_page)
static UINT code_page(rb_encoding *enc)
static size_t remove_invalid_alternative_data(wchar_t *wfullpath, size_t size)
void rb_enc_foreach_name(int(*func)(st_data_t name, st_data_t idx, st_data_t arg), st_data_t arg)
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
VALUE rb_str_resize(VALUE, long)
#define fix_string_encoding(str, encoding)
static wchar_t * home_dir(void)
unsigned char buf[MIME_BUF_SIZE]
#define rb_usascii_encindex()
void rb_str_modify(VALUE)
rb_encoding * rb_enc_get(VALUE obj)
static size_t replace_to_long_name(wchar_t **wfullpath, size_t size, int heap)
static struct code_page_table rb_code_page
static VALUE get_user_from_path(wchar_t **wpath, int offset, UINT cp, UINT path_cp, rb_encoding *path_encoding)
rb_encoding * rb_filesystem_encoding(void)
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
static void convert_mb_to_wchar(const char *str, wchar_t **wstr, size_t *wstr_len, UINT code_page)
int rb_file_load_ok(const char *path)
#define StringValuePtr(v)
#define rb_enc_to_index(enc)
#define INVALID_CODE_PAGE
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
int rb_enc_str_asciionly_p(VALUE)
#define INVALID_FILE_ATTRIBUTES
#define rb_ascii8bit_encindex()
static void replace_wchar(wchar_t *s, int find, int replace)
VALUE rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_name, VALUE result)