Chromium Code Reviews| Index: runtime/bin/file_win.cc |
| diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc |
| index b23049dce5bfc7241347d89db5fae8060409d6d5..3101e6658f38bf9d28cdbb499e3192f73a2b685f 100644 |
| --- a/runtime/bin/file_win.cc |
| +++ b/runtime/bin/file_win.cc |
| @@ -279,6 +279,73 @@ off_t File::LengthFromPath(const char* name) { |
| } |
| +char* File::LinkTarget(const char* pathname) { |
| + const wchar_t* name = StringUtils::Utf8ToWide(pathname); |
| + HANDLE dir_handle = CreateFileW( |
| + name, |
| + GENERIC_READ, |
| + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
| + NULL, |
| + OPEN_EXISTING, |
| + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, |
| + NULL); |
| + free(const_cast<wchar_t*>(name)); |
| + if (dir_handle == INVALID_HANDLE_VALUE) { |
| + return NULL; |
| + } |
| + |
| + int reparse_data_buffer_size = |
| + sizeof REPARSE_DATA_BUFFER + 2 * (MAX_PATH + 1) * sizeof WCHAR; |
| + REPARSE_DATA_BUFFER* reparse_data_buffer = |
| + static_cast<REPARSE_DATA_BUFFER*>(calloc(reparse_data_buffer_size, 1)); |
| + DWORD received_bytes; |
| + int result = DeviceIoControl( |
| + dir_handle, |
| + FSCTL_GET_REPARSE_POINT, |
| + NULL, |
| + 0, |
| + reparse_data_buffer, |
| + reparse_data_buffer_size, |
| + &received_bytes, |
| + NULL); |
| + if (CloseHandle(dir_handle) == 0) return NULL; |
|
Søren Gjesse
2013/03/18 12:28:03
Here it seems like we are clearing the last error
Bill Hesse
2013/03/18 16:13:27
Yes. Fixed.
|
| + if (result == 0) return NULL; |
| + if (reparse_data_buffer->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT) { |
|
Søren Gjesse
2013/03/18 12:28:03
Here GetLastError will return NOERROR, so we get a
Bill Hesse
2013/03/18 16:13:27
Now we are returning Not a Reparse Point.
|
| + return NULL; |
| + } |
| + wchar_t* target = reparse_data_buffer->MountPointReparseBuffer.PathBuffer + |
| + reparse_data_buffer->MountPointReparseBuffer.SubstituteNameOffset; |
| + size_t target_length = |
| + reparse_data_buffer->MountPointReparseBuffer.SubstituteNameLength; |
| + // Remove "\??\" from beginning of target. |
| + if (target_length <= 4 || wcsncmp(L"\\??\\", target, 4) != 0) return NULL; |
|
Søren Gjesse
2013/03/18 12:28:03
Ditto.
Bill Hesse
2013/03/18 16:13:27
Changed. Now, we just skip removing \??\ if it is
|
| + int utf8_length = WideCharToMultiByte(CP_UTF8, |
|
Søren Gjesse
2013/03/18 12:28:03
Indentation.
|
| + 0, |
| + target + 4, |
| + target_length - 4, |
| + NULL, |
| + 0, |
| + NULL, |
| + NULL); |
|
Søren Gjesse
2013/03/18 12:28:03
Can this call fail?
Bill Hesse
2013/03/18 16:13:27
If it fails, it returns 0, and the next call to it
|
| + char* utf8_target = reinterpret_cast<char*>(malloc(utf8_length + 1)); |
| + if (0 == WideCharToMultiByte(CP_UTF8, |
| + 0, |
| + target + 4, |
| + target_length - 4, |
| + utf8_target, |
| + utf8_length, |
| + NULL, |
| + NULL)) { |
| + free(reparse_data_buffer); |
| + free(utf8_target); |
|
Søren Gjesse
2013/03/18 12:28:03
Set an error code?
Bill Hesse
2013/03/18 16:13:27
Done.
|
| + return NULL; |
| + } |
| + utf8_target[utf8_length] = '\0'; |
| + free(reparse_data_buffer); |
| + return utf8_target; |
| +} |
| + |
| + |
| time_t File::LastModified(const char* name) { |
| struct _stat st; |
| const wchar_t* system_name = StringUtils::Utf8ToWide(name); |