7 #ifndef INVALID_FILE_ATTRIBUTES
8 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
14 #define IS_DIR_SEPARATOR_P(c) (c == L'\\' || c == L'/')
15 #define IS_DIR_UNC_P(c) (IS_DIR_SEPARATOR_P(c[0]) && IS_DIR_SEPARATOR_P(c[1]))
18 #define INVALID_CODE_PAGE 51932
19 #define PATH_BUFFER_SIZE MAX_PATH * 2
21 #define insecure_obj_p(obj, level) ((level) >= 4 || ((level) > 0 && OBJ_TAINTED(obj)))
42 len = MultiByteToWideChar(code_page, 0,
RSTRING_PTR(str), -1,
NULL, 0) + 1;
43 *wstr = (
wchar_t *)
xmalloc(len *
sizeof(
wchar_t));
47 MultiByteToWideChar(code_page, 0,
RSTRING_PTR(str), -1, *wstr, len);
56 len = WideCharToMultiByte(code_page, 0, wstr, -1,
NULL, 0,
NULL,
NULL);
57 *str = (
char *)
xmalloc(len *
sizeof(
char));
58 WideCharToMultiByte(code_page, 0, wstr, -1, *str, len,
NULL,
NULL);
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;
183 VALUE code_page_value, name_key;
200 name_key = (
VALUE)&fake_str;
204 if (code_page_value !=
Qnil)
205 return (UINT)
FIX2INT(code_page_value);
210 if (!
NIL_P(encoding)) {
222 if (names_ary !=
Qundef) {
227 if (code_page != 0) {
257 WIN32_FIND_DATAW find_data;
269 size_t const max_short_name_size = 8 + 1 + 3;
270 size_t const max_extension_size = 3;
271 size_t path_len = 1, extension_len = 0;
272 wchar_t *pos = *wfullpath;
274 if (size == 3 && pos[1] == L
':' && pos[2] == L
'\\' && pos[3] == L
'\0') {
280 if (wcspbrk(pos, L
"*?")) {
284 pos = *wfullpath + size - 1;
286 if (!extension_len && *pos == L
'.') {
287 extension_len = path_len - 1;
289 if (path_len > max_short_name_size || extension_len > max_extension_size) {
296 find_handle = FindFirstFileW(*wfullpath, &find_data);
297 if (find_handle != INVALID_HANDLE_VALUE) {
298 size_t trail_pos = wcslen(*wfullpath);
299 size_t file_len = wcslen(find_data.cFileName);
301 FindClose(find_handle);
302 while (trail_pos > 0) {
307 size = trail_pos + 1 + file_len;
308 if ((size + 1) >
sizeof(*wfullpath) /
sizeof((*wfullpath)[0])) {
309 wchar_t *
buf = (
wchar_t *)
xmalloc((size + 1) *
sizeof(wchar_t));
310 wcsncpy(buf, *wfullpath, trail_pos + 1);
315 wcsncpy(*wfullpath + trail_pos + 1, find_data.cFileName, file_len + 1);
324 wchar_t *wuser = *wpath + offset;
325 wchar_t *pos = wuser;
354 size_t size = 0, wpath_len = 0, wdir_len = 0, whome_len = 0;
355 size_t buffer_len = 0;
356 char *fullpath =
NULL;
357 wchar_t *wfullpath =
NULL, *wpath =
NULL, *wpath_pos =
NULL;
358 wchar_t *wdir =
NULL, *wdir_pos =
NULL;
359 wchar_t *whome =
NULL, *buffer =
NULL, *buffer_pos =
NULL;
361 VALUE path = fname, dir = dname;
363 wchar_t path_drive = L
'\0', dir_drive = L
'\0';
394 if (abs_mode == 0 && wpath_len > 0 && wpath_pos[0] == L
'~' &&
404 whome_len = wcslen(whome);
406 if (PathIsRelativeW(whome) && !(whome_len >= 2 &&
IS_DIR_UNC_P(whome))) {
428 else if (wpath_len >= 2 && wpath_pos[1] == L
':') {
435 path_drive = wpath_pos[0];
438 else if (abs_mode == 0 && wpath_len >= 2 && wpath_pos[0] == L
'~') {
448 if (!ignore_dir && !
NIL_P(dir)) {
457 if (abs_mode == 0 && wdir_len > 0 && wdir_pos[0] == L
'~' &&
468 whome_len = wcslen(whome);
470 if (PathIsRelativeW(whome) && !(whome_len >= 2 &&
IS_DIR_UNC_P(whome))) {
486 else if (wdir_len >= 2 && wdir[1] == L
':') {
496 size_t separators = 0;
498 while (pos < wdir_len && separators < 2) {
508 else if (abs_mode == 0 && wdir_len >= 2 && wdir_pos[0] == L
'~') {
521 if (!ignore_dir && path_drive && dir_drive) {
522 if (towupper(path_drive) == towupper(dir_drive)) {
534 if (!ignore_dir && wpath_len >= 2 &&
IS_DIR_UNC_P(wpath)) {
546 buffer_len = wpath_len + 1 + wdir_len + 1 + whome_len + 1;
548 buffer = buffer_pos = (
wchar_t *)
xmalloc((buffer_len + 1) *
sizeof(wchar_t));
552 wcsncpy(buffer_pos, whome, whome_len);
553 buffer_pos += whome_len;
557 if (whome_len && wcsrchr(L
"\\/:", buffer_pos[-1]) ==
NULL) {
558 buffer_pos[0] = L
'\\';
567 wcsncpy(buffer_pos, wdir_pos, wdir_len);
568 buffer_pos += wdir_len;
572 if (wdir_len && wcsrchr(L
"\\/:", buffer_pos[-1]) ==
NULL) {
573 buffer_pos[0] = L
'\\';
579 wcsncpy(buffer_pos, wpath_pos, wpath_len);
580 buffer_pos += wpath_len;
584 if (wpath_len == 0) {
585 buffer_pos[0] = L
'.';
590 buffer_pos[0] = L
'\0';
593 if (!tainted && PathIsRelativeW(buffer) && !(buffer_len >= 2 &&
IS_DIR_UNC_P(buffer)))
601 wfullpath = (
wchar_t *)
xmalloc(size *
sizeof(
wchar_t));
602 size = GetFullPathNameW(buffer, size, wfullpath,
NULL);
605 wfullpath = wfullpath_buffer;
610 wfullpath[size - 2] != L
':' &&
613 wfullpath[
size] = L
'\0';
617 if (wfullpath[size - 1] == L
'.') {
619 wfullpath[
size] = L
'\0';
633 size = WideCharToMultiByte(cp, 0, wfullpath, size,
NULL, 0,
NULL,
NULL);
676 if (wfullpath && wfullpath != wfullpath_buffer)
689 DWORD attr = GetFileAttributes(path);
691 attr & FILE_ATTRIBUTE_DIRECTORY) {
695 HANDLE h = CreateFile(path, GENERIC_READ,
696 FILE_SHARE_READ | FILE_SHARE_WRITE,
697 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);
698 if (h != INVALID_HANDLE_VALUE) {