4126 4127 // Transfers data from WIN32_FILE_ATTRIBUTE_DATA structure to struct stat 4128 static void file_attribute_data_to_stat(struct stat* sbuf, WIN32_FILE_ATTRIBUTE_DATA file_data) { 4129 ::memset((void*)sbuf, 0, sizeof(struct stat)); 4130 sbuf->st_size = (_off_t)make_double_word(file_data.nFileSizeHigh, file_data.nFileSizeLow); 4131 sbuf->st_mtime = make_double_word(file_data.ftLastWriteTime.dwHighDateTime, 4132 file_data.ftLastWriteTime.dwLowDateTime); 4133 sbuf->st_ctime = make_double_word(file_data.ftCreationTime.dwHighDateTime, 4134 file_data.ftCreationTime.dwLowDateTime); 4135 sbuf->st_atime = make_double_word(file_data.ftLastAccessTime.dwHighDateTime, 4136 file_data.ftLastAccessTime.dwLowDateTime); 4137 if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { 4138 sbuf->st_mode |= S_IFDIR; 4139 } else { 4140 sbuf->st_mode |= S_IFREG; 4141 } 4142 } 4143 4144 static errno_t convert_to_unicode(char const* char_path, LPWSTR* unicode_path) { 4145 // Get required buffer size to convert to Unicode 4146 int unicode_path_len = MultiByteToWideChar(CP_THREAD_ACP, 4147 MB_ERR_INVALID_CHARS, 4148 char_path, -1, 4149 NULL, 0); 4150 if (unicode_path_len == 0) { 4151 return EINVAL; 4152 } 4153 4154 *unicode_path = NEW_C_HEAP_ARRAY(WCHAR, unicode_path_len, mtInternal); 4155 4156 int result = MultiByteToWideChar(CP_THREAD_ACP, 4157 MB_ERR_INVALID_CHARS, 4158 char_path, -1, 4159 *unicode_path, unicode_path_len); 4160 assert(result == unicode_path_len, "length already checked above"); 4161 4162 return ERROR_SUCCESS; 4163 } 4164 4165 static errno_t get_full_path(LPCWSTR unicode_path, LPWSTR* full_path) { 4166 // Get required buffer size to convert to full path. The return 4167 // value INCLUDES the terminating null character. 4168 DWORD full_path_len = GetFullPathNameW(unicode_path, 0, NULL, NULL); 4169 if (full_path_len == 0) { 4170 return EINVAL; 4171 } 4172 4173 *full_path = NEW_C_HEAP_ARRAY(WCHAR, full_path_len, mtInternal); 4174 4175 // When the buffer has sufficient size, the return value EXCLUDES the 4176 // terminating null character | 4126 4127 // Transfers data from WIN32_FILE_ATTRIBUTE_DATA structure to struct stat 4128 static void file_attribute_data_to_stat(struct stat* sbuf, WIN32_FILE_ATTRIBUTE_DATA file_data) { 4129 ::memset((void*)sbuf, 0, sizeof(struct stat)); 4130 sbuf->st_size = (_off_t)make_double_word(file_data.nFileSizeHigh, file_data.nFileSizeLow); 4131 sbuf->st_mtime = make_double_word(file_data.ftLastWriteTime.dwHighDateTime, 4132 file_data.ftLastWriteTime.dwLowDateTime); 4133 sbuf->st_ctime = make_double_word(file_data.ftCreationTime.dwHighDateTime, 4134 file_data.ftCreationTime.dwLowDateTime); 4135 sbuf->st_atime = make_double_word(file_data.ftLastAccessTime.dwHighDateTime, 4136 file_data.ftLastAccessTime.dwLowDateTime); 4137 if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { 4138 sbuf->st_mode |= S_IFDIR; 4139 } else { 4140 sbuf->st_mode |= S_IFREG; 4141 } 4142 } 4143 4144 static errno_t convert_to_unicode(char const* char_path, LPWSTR* unicode_path) { 4145 // Get required buffer size to convert to Unicode 4146 int unicode_path_len = MultiByteToWideChar(CP_ACP, 4147 MB_ERR_INVALID_CHARS, 4148 char_path, -1, 4149 NULL, 0); 4150 if (unicode_path_len == 0) { 4151 return EINVAL; 4152 } 4153 4154 *unicode_path = NEW_C_HEAP_ARRAY(WCHAR, unicode_path_len, mtInternal); 4155 4156 int result = MultiByteToWideChar(CP_ACP, 4157 MB_ERR_INVALID_CHARS, 4158 char_path, -1, 4159 *unicode_path, unicode_path_len); 4160 assert(result == unicode_path_len, "length already checked above"); 4161 4162 return ERROR_SUCCESS; 4163 } 4164 4165 static errno_t get_full_path(LPCWSTR unicode_path, LPWSTR* full_path) { 4166 // Get required buffer size to convert to full path. The return 4167 // value INCLUDES the terminating null character. 4168 DWORD full_path_len = GetFullPathNameW(unicode_path, 0, NULL, NULL); 4169 if (full_path_len == 0) { 4170 return EINVAL; 4171 } 4172 4173 *full_path = NEW_C_HEAP_ARRAY(WCHAR, full_path_len, mtInternal); 4174 4175 // When the buffer has sufficient size, the return value EXCLUDES the 4176 // terminating null character |