* Fix handling of return codes from newer Windows APIs

* Fix a handle-leak in Windows stat implementation
* Return actual error code when path creation succeeds but file creation doesn't
This commit is contained in:
Vas Crabb 2016-03-19 21:07:16 +11:00
parent 9a299f35f3
commit 57f61b2bae

View File

@ -19,6 +19,7 @@
#include "osdcore.h" #include "osdcore.h"
#include <cassert> #include <cassert>
#include <cstring>
// standard windows headers // standard windows headers
#include <windows.h> #include <windows.h>
@ -59,15 +60,11 @@ public:
// attempt to set the file pointer // attempt to set the file pointer
LARGE_INTEGER largeOffset; LARGE_INTEGER largeOffset;
largeOffset.QuadPart = offset; largeOffset.QuadPart = offset;
DWORD result(SetFilePointerEx(m_handle, largeOffset, NULL, FILE_BEGIN)); if (!SetFilePointerEx(m_handle, largeOffset, nullptr, FILE_BEGIN))
if (INVALID_SET_FILE_POINTER == result) return win_error_to_file_error(GetLastError());
{
DWORD const err(GetLastError());
if (NO_ERROR != err)
win_error_to_file_error(err);
}
// then perform the read // then perform the read
DWORD result = 0;
if (!ReadFile(m_handle, buffer, length, &result, NULL)) if (!ReadFile(m_handle, buffer, length, &result, NULL))
return win_error_to_file_error(GetLastError()); return win_error_to_file_error(GetLastError());
@ -80,15 +77,11 @@ public:
// attempt to set the file pointer // attempt to set the file pointer
LARGE_INTEGER largeOffset; LARGE_INTEGER largeOffset;
largeOffset.QuadPart = offset; largeOffset.QuadPart = offset;
DWORD result(SetFilePointerEx(m_handle, largeOffset, NULL, FILE_BEGIN)); if (!SetFilePointerEx(m_handle, largeOffset, nullptr, FILE_BEGIN))
if (INVALID_SET_FILE_POINTER == result) return win_error_to_file_error(GetLastError());
{
DWORD const err(GetLastError());
if (NO_ERROR != err)
win_error_to_file_error(err);
}
// then perform the write // then perform the write
DWORD result = 0;
if (!WriteFile(m_handle, buffer, length, &result, NULL)) if (!WriteFile(m_handle, buffer, length, &result, NULL))
return win_error_to_file_error(GetLastError()); return win_error_to_file_error(GetLastError());
@ -101,13 +94,8 @@ public:
// attempt to set the file pointer // attempt to set the file pointer
LARGE_INTEGER largeOffset; LARGE_INTEGER largeOffset;
largeOffset.QuadPart = offset; largeOffset.QuadPart = offset;
DWORD const result(SetFilePointerEx(m_handle, largeOffset, NULL, FILE_BEGIN)); if (!SetFilePointerEx(m_handle, largeOffset, nullptr, FILE_BEGIN))
if (INVALID_SET_FILE_POINTER == result) return win_error_to_file_error(GetLastError());
{
DWORD const err(GetLastError());
if (NO_ERROR != err)
win_error_to_file_error(err);
}
// then perform the truncation // then perform the truncation
if (!SetEndOfFile(m_handle)) if (!SetEndOfFile(m_handle))
@ -167,7 +155,7 @@ DWORD create_path_recursive(TCHAR *path)
// if the path already exists, we're done // if the path already exists, we're done
WIN32_FILE_ATTRIBUTE_DATA fileinfo; WIN32_FILE_ATTRIBUTE_DATA fileinfo;
if (GetFileAttributesEx(path, GetFileExInfoStandard, &fileinfo) != INVALID_FILE_ATTRIBUTES) if (GetFileAttributesEx(path, GetFileExInfoStandard, &fileinfo))
return NO_ERROR; return NO_ERROR;
else if (!CreateDirectory(path, NULL)) else if (!CreateDirectory(path, NULL))
return GetLastError(); return GetLastError();
@ -241,12 +229,15 @@ osd_file::error osd_file::open(std::string const &orig_path, UINT32 openflags, p
// attempt to reopen the file // attempt to reopen the file
if (err == NO_ERROR) if (err == NO_ERROR)
{
h = CreateFile(t_path, access, sharemode, NULL, disposition, 0, NULL); h = CreateFile(t_path, access, sharemode, NULL, disposition, 0, NULL);
err = GetLastError();
}
} }
} }
// if we still failed, clean up and free // if we still failed, clean up and free
if (h == INVALID_HANDLE_VALUE) if (INVALID_HANDLE_VALUE == h)
return win_error_to_file_error(err); return win_error_to_file_error(err);
} }
@ -365,44 +356,39 @@ int osd_get_physical_drive_geometry(const char *filename, UINT32 *cylinders, UIN
osd_directory_entry *osd_stat(const std::string &path) osd_directory_entry *osd_stat(const std::string &path)
{ {
osd_directory_entry *result = NULL;
TCHAR *t_path;
HANDLE find = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA find_data;
// convert the path to TCHARs // convert the path to TCHARs
t_path = tstring_from_utf8(path.c_str()); std::unique_ptr<TCHAR, void (*)(void *)> const t_path(tstring_from_utf8(path.c_str()), &osd_free);
if (t_path == NULL) if (!t_path)
goto done; return nullptr;
// is this path a root directory (e.g. - C:)? // is this path a root directory (e.g. - C:)?
WIN32_FIND_DATA find_data;
std::memset(&find_data, 0, sizeof(find_data));
if (isalpha(path[0]) && (path[1] == ':') && (path[2] == '\0')) if (isalpha(path[0]) && (path[1] == ':') && (path[2] == '\0'))
{ {
// need to do special logic for root directories // need to do special logic for root directories
memset(&find_data, 0, sizeof(find_data)); if (!GetFileAttributesEx(t_path.get(), GetFileExInfoStandard, &find_data.dwFileAttributes))
GetFileAttributesEx(t_path, GetFileExInfoStandard, &find_data.dwFileAttributes); find_data.dwFileAttributes = INVALID_FILE_ATTRIBUTES;
} }
else else
{ {
// attempt to find the first file // attempt to find the first file
find = FindFirstFileEx(t_path, FindExInfoStandard, &find_data, FindExSearchNameMatch, NULL, 0); HANDLE find = FindFirstFileEx(t_path.get(), FindExInfoStandard, &find_data, FindExSearchNameMatch, NULL, 0);
if (find == INVALID_HANDLE_VALUE) if (find == INVALID_HANDLE_VALUE)
goto done; return nullptr;
FindClose(find);
} }
// create an osd_directory_entry; be sure to make sure that the caller can // create an osd_directory_entry; be sure to make sure that the caller can
// free all resources by just freeing the resulting osd_directory_entry // free all resources by just freeing the resulting osd_directory_entry
result = (osd_directory_entry *)osd_malloc_array(sizeof(*result) + path.length() + 1); osd_directory_entry *const result = (osd_directory_entry *)osd_malloc_array(sizeof(*result) + path.length() + 1);
if (!result) if (!result)
goto done; return nullptr;
strcpy(((char *) result) + sizeof(*result), path.c_str()); strcpy(((char *) result) + sizeof(*result), path.c_str());
result->name = ((char *) result) + sizeof(*result); result->name = ((char *) result) + sizeof(*result);
result->type = win_attributes_to_entry_type(find_data.dwFileAttributes); result->type = win_attributes_to_entry_type(find_data.dwFileAttributes);
result->size = find_data.nFileSizeLow | ((UINT64) find_data.nFileSizeHigh << 32); result->size = find_data.nFileSizeLow | ((UINT64) find_data.nFileSizeHigh << 32);
done:
if (t_path != NULL)
osd_free(t_path);
return result; return result;
} }