8 #ifndef INVALID_FILE_ATTRIBUTES
9 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
18 #define IS_DIR_SEPARATOR_P(c) (c == L'\\' || c == L'/')
19 #define IS_DIR_UNC_P(c) (IS_DIR_SEPARATOR_P(c[0]) && IS_DIR_SEPARATOR_P(c[1]))
22 #define INVALID_CODE_PAGE 51932
23 #define PATH_BUFFER_SIZE MAX_PATH * 2
25 #define insecure_obj_p(obj, level) ((level) >= 4 || ((level) > 0 && OBJ_TAINTED(obj)))
43 len = MultiByteToWideChar(code_page, 0, str, -1,
NULL, 0) + 1;
44 *wstr = (
wchar_t *)
xmalloc(len *
sizeof(
wchar_t));
46 MultiByteToWideChar(code_page, 0, str, -1, *wstr, len);
55 len = WideCharToMultiByte(code_page, 0, wstr, -1,
NULL, 0,
NULL,
NULL);
56 *str = (
char *)
xmalloc(len *
sizeof(
char));
57 WideCharToMultiByte(code_page, 0, wstr, -1, *str, len,
NULL,
NULL);
74 wchar_t *buffer =
NULL;
75 size_t buffer_len = 0, len = 0;
84 if (len = GetEnvironmentVariableW(L
"HOME",
NULL, 0)) {
88 else if (len = GetEnvironmentVariableW(L
"HOMEDRIVE",
NULL, 0)) {
90 if (len = GetEnvironmentVariableW(L
"HOMEPATH",
NULL, 0)) {
98 else if (len = GetEnvironmentVariableW(L
"USERPROFILE",
NULL, 0)) {
105 buffer = (
wchar_t *)
xmalloc(buffer_len *
sizeof(
wchar_t));
110 GetEnvironmentVariableW(L
"HOME", buffer, buffer_len);
114 len = GetEnvironmentVariableW(L
"HOMEDRIVE", buffer, buffer_len);
115 GetEnvironmentVariableW(L
"HOMEPATH", buffer + len, buffer_len - len);
119 GetEnvironmentVariableW(L
"USERPROFILE", buffer, buffer_len);
139 static const wchar_t prime[] = L
":$DATA";
140 enum { prime_len = (
sizeof(prime) /
sizeof(
wchar_t)) -1 };
142 if (size <= prime_len || _wcsnicmp(wfullpath + size - prime_len, prime, prime_len) != 0)
147 if (wfullpath[size - (prime_len + 1)] ==
':') {
149 size -= prime_len + 1;
150 wfullpath[
size] = L
'\0';
154 wchar_t *pos = wfullpath + size - (prime_len + 1);
158 wfullpath[
size] = L
'\0';
171 return AreFileApisANSI() ? CP_ACP : CP_OEMCP;
179 const char *n = (
const char *)name;
180 if (strncmp(
"CP", n, 2) == 0) {
182 if (code_page != 0) {
187 unsigned int i =
count;
188 cp->
count = count = ((idx + 4) & ~31 | 28);
189 cp->
table = table =
realloc(table, count *
sizeof(*table));
192 table[idx] = (USHORT)code_page;
224 #define fix_string_encoding(str, encoding) rb_str_conv_enc((str), (encoding), rb_utf8_encoding())
233 WIN32_FIND_DATAW find_data;
245 size_t const max_short_name_size = 8 + 1 + 3;
246 size_t const max_extension_size = 3;
247 size_t path_len = 1, extension_len = 0;
248 wchar_t *pos = *wfullpath;
250 if (size == 3 && pos[1] == L
':' && pos[2] == L
'\\' && pos[3] == L
'\0') {
256 if (wcspbrk(pos, L
"*?")) {
260 pos = *wfullpath + size - 1;
262 if (!extension_len && *pos == L
'.') {
263 extension_len = path_len - 1;
265 if (path_len > max_short_name_size || extension_len > max_extension_size) {
272 find_handle = FindFirstFileW(*wfullpath, &find_data);
273 if (find_handle != INVALID_HANDLE_VALUE) {
274 size_t trail_pos = wcslen(*wfullpath);
275 size_t file_len = wcslen(find_data.cFileName);
277 FindClose(find_handle);
278 while (trail_pos > 0) {
283 size = trail_pos + 1 + file_len;
284 if ((size + 1) >
sizeof(*wfullpath) /
sizeof((*wfullpath)[0])) {
285 wchar_t *
buf = (
wchar_t *)
xmalloc((size + 1) *
sizeof(wchar_t));
286 wcsncpy(buf, *wfullpath, trail_pos + 1);
291 wcsncpy(*wfullpath + trail_pos + 1, find_data.cFileName, file_len + 1);
300 wchar_t *wuser = *wpath + offset;
301 wchar_t *pos = wuser;
330 size_t size = 0, wpath_len = 0, wdir_len = 0, whome_len = 0;
331 size_t buffer_len = 0;
332 char *fullpath =
NULL;
333 wchar_t *wfullpath =
NULL, *wpath =
NULL, *wpath_pos =
NULL;
334 wchar_t *wdir =
NULL, *wdir_pos =
NULL;
335 wchar_t *whome =
NULL, *buffer =
NULL, *buffer_pos =
NULL;
337 VALUE path = fname, dir = dname;
339 wchar_t path_drive = L
'\0', dir_drive = L
'\0';
373 if (abs_mode == 0 && wpath_len > 0 && wpath_pos[0] == L
'~' &&
383 whome_len = wcslen(whome);
385 if (PathIsRelativeW(whome) && !(whome_len >= 2 &&
IS_DIR_UNC_P(whome))) {
410 else if (wpath_len >= 2 && wpath_pos[1] == L
':') {
417 path_drive = wpath_pos[0];
420 else if (abs_mode == 0 && wpath_len >= 2 && wpath_pos[0] == L
'~') {
430 if (!ignore_dir && !
NIL_P(dir)) {
442 if (abs_mode == 0 && wdir_len > 0 && wdir_pos[0] == L
'~' &&
453 whome_len = wcslen(whome);
455 if (PathIsRelativeW(whome) && !(whome_len >= 2 &&
IS_DIR_UNC_P(whome))) {
472 else if (wdir_len >= 2 && wdir[1] == L
':') {
482 size_t separators = 0;
484 while (pos < wdir_len && separators < 2) {
494 else if (abs_mode == 0 && wdir_len >= 2 && wdir_pos[0] == L
'~') {
507 if (!ignore_dir && path_drive && dir_drive) {
508 if (towupper(path_drive) == towupper(dir_drive)) {
520 if (!ignore_dir && wpath_len >= 2 &&
IS_DIR_UNC_P(wpath)) {
532 buffer_len = wpath_len + 1 + wdir_len + 1 + whome_len + 1;
534 buffer = buffer_pos = (
wchar_t *)
xmalloc((buffer_len + 1) *
sizeof(wchar_t));
538 wcsncpy(buffer_pos, whome, whome_len);
539 buffer_pos += whome_len;
543 if (whome_len && wcsrchr(L
"\\/:", buffer_pos[-1]) ==
NULL) {
544 buffer_pos[0] = L
'\\';
553 wcsncpy(buffer_pos, wdir_pos, wdir_len);
554 buffer_pos += wdir_len;
558 if (wdir_len && wcsrchr(L
"\\/:", buffer_pos[-1]) ==
NULL) {
559 buffer_pos[0] = L
'\\';
565 wcsncpy(buffer_pos, wpath_pos, wpath_len);
566 buffer_pos += wpath_len;
570 if (wpath_len == 0) {
571 buffer_pos[0] = L
'.';
576 buffer_pos[0] = L
'\0';
579 if (!tainted && PathIsRelativeW(buffer) && !(buffer_len >= 2 &&
IS_DIR_UNC_P(buffer)))
587 wfullpath = (
wchar_t *)
xmalloc(size *
sizeof(
wchar_t));
588 size = GetFullPathNameW(buffer, size, wfullpath,
NULL);
591 wfullpath = wfullpath_buffer;
596 wfullpath[size - 2] != L
':' &&
599 wfullpath[
size] = L
'\0';
603 if (wfullpath[size - 1] == L
'.') {
605 wfullpath[
size] = L
'\0';
619 size = WideCharToMultiByte(cp, 0, wfullpath, size,
NULL, 0,
NULL,
NULL);
662 if (wfullpath && wfullpath != wfullpath_buffer)
681 attr = GetFileAttributesW(wpath);
683 (attr & FILE_ATTRIBUTE_DIRECTORY)) {
687 HANDLE h = CreateFileW(wpath, GENERIC_READ,
688 FILE_SHARE_READ | FILE_SHARE_WRITE,
689 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);
690 if (h != INVALID_HANDLE_VALUE) {
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)
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)
VALUE rb_str_resize(VALUE, long)
SSL_METHOD *(* func)(void)
#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)