1 |
/* PCSX2 - PS2 Emulator for PCs |
2 |
* Copyright (C) 2002-2010 PCSX2 Dev Team |
3 |
* |
4 |
* PCSX2 is free software: you can redistribute it and/or modify it under the terms |
5 |
* of the GNU Lesser General Public License as published by the Free Software Found- |
6 |
* ation, either version 3 of the License, or (at your option) any later version. |
7 |
* |
8 |
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
9 |
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
10 |
* PURPOSE. See the GNU General Public License for more details. |
11 |
* |
12 |
* You should have received a copy of the GNU General Public License along with PCSX2. |
13 |
* If not, see <http://www.gnu.org/licenses/>. |
14 |
*/ |
15 |
|
16 |
#include "PrecompiledHeader.h" |
17 |
#include "Win32.h" |
18 |
|
19 |
// Translates an Errno code into an exception. |
20 |
// Throws an exception based on the given error code (usually taken from ANSI C's errno) |
21 |
void StreamException_ThrowFromErrno( const wxString& streamname, errno_t errcode ) |
22 |
{ |
23 |
if( errcode == 0 ) return; |
24 |
|
25 |
switch( errcode ) |
26 |
{ |
27 |
case EINVAL: |
28 |
pxFailDev( L"Invalid argument" ); |
29 |
throw Exception::Stream( streamname ).SetDiagMsg(L"Invalid argument" ); |
30 |
|
31 |
case EACCES: // Access denied! |
32 |
throw Exception::AccessDenied( streamname ); |
33 |
|
34 |
case EMFILE: // Too many open files! |
35 |
throw Exception::CannotCreateStream( streamname ).SetDiagMsg(L"Too many open files"); // File handle allocation failure |
36 |
|
37 |
case EEXIST: |
38 |
throw Exception::CannotCreateStream( streamname ).SetDiagMsg(L"File already exists"); |
39 |
|
40 |
case ENOENT: // File not found! |
41 |
throw Exception::FileNotFound( streamname ); |
42 |
|
43 |
case EPIPE: |
44 |
throw Exception::BadStream( streamname ).SetDiagMsg(L"Broken pipe"); |
45 |
|
46 |
case EBADF: |
47 |
throw Exception::BadStream( streamname ).SetDiagMsg(L"Bad file number"); |
48 |
|
49 |
default: |
50 |
throw Exception::Stream( streamname ).SetDiagMsg(wxsFormat( L"General file/stream error [errno: %d]", errcode )); |
51 |
} |
52 |
} |
53 |
|
54 |
// Throws an exception based on the value returned from GetLastError. |
55 |
// Performs an option return value success/fail check on hresult. |
56 |
void StreamException_ThrowLastError( const wxString& streamname, HANDLE result ) |
57 |
{ |
58 |
if( result != INVALID_HANDLE_VALUE ) return; |
59 |
|
60 |
int error = GetLastError(); |
61 |
|
62 |
switch( error ) |
63 |
{ |
64 |
case ERROR_FILE_NOT_FOUND: |
65 |
throw Exception::FileNotFound( streamname ); |
66 |
|
67 |
case ERROR_PATH_NOT_FOUND: |
68 |
throw Exception::FileNotFound( streamname ); |
69 |
|
70 |
case ERROR_TOO_MANY_OPEN_FILES: |
71 |
throw Exception::CannotCreateStream( streamname ).SetDiagMsg(L"Too many open files"); |
72 |
|
73 |
case ERROR_ACCESS_DENIED: |
74 |
throw Exception::AccessDenied( streamname ); |
75 |
|
76 |
case ERROR_INVALID_HANDLE: |
77 |
throw Exception::BadStream( streamname ).SetDiagMsg(L"Stream object or handle is invalid"); |
78 |
|
79 |
case ERROR_SHARING_VIOLATION: |
80 |
throw Exception::AccessDenied( streamname ).SetDiagMsg(L"Sharing violation"); |
81 |
|
82 |
default: |
83 |
{ |
84 |
throw Exception::Stream( streamname ).SetDiagMsg(wxsFormat( L"General Win32 File/stream error [GetLastError: %d]", error )); |
85 |
} |
86 |
} |
87 |
} |
88 |
|
89 |
// returns TRUE if an error occurred. |
90 |
bool StreamException_LogFromErrno( const wxString& streamname, const wxChar* action, errno_t result ) |
91 |
{ |
92 |
try |
93 |
{ |
94 |
StreamException_ThrowFromErrno( streamname, result ); |
95 |
} |
96 |
catch( Exception::Stream& ex ) |
97 |
{ |
98 |
Console.WriteLn( Color_Yellow, L"%s: %s", action, ex.FormatDiagnosticMessage().c_str() ); |
99 |
return true; |
100 |
} |
101 |
return false; |
102 |
} |
103 |
|
104 |
// returns TRUE if an error occurred. |
105 |
bool StreamException_LogLastError( const wxString& streamname, const wxChar* action, HANDLE result ) |
106 |
{ |
107 |
try |
108 |
{ |
109 |
StreamException_ThrowLastError( streamname, result ); |
110 |
} |
111 |
catch( Exception::Stream& ex ) |
112 |
{ |
113 |
Console.WriteLn( Color_Yellow, L"%s: %s", action, ex.FormatDiagnosticMessage().c_str() ); |
114 |
return true; |
115 |
} |
116 |
return false; |
117 |
} |
118 |
|
119 |
// Sets the NTFS compression flag for a directory or file. This function does not operate |
120 |
// recursively. Set compressStatus to false to decompress compressed files (and do nothing |
121 |
// to already decompressed files). |
122 |
// |
123 |
// Exceptions thrown: None. |
124 |
// (Errors are logged to console. Failures are considered non-critical) |
125 |
// |
126 |
void NTFS_CompressFile( const wxString& file, bool compressStatus ) |
127 |
{ |
128 |
bool isFile = !wxDirExists( file ); |
129 |
|
130 |
if( isFile && !wxFileExists( file ) ) return; |
131 |
if( GetFileAttributes(file) & FILE_ATTRIBUTE_COMPRESSED ) return; |
132 |
if( !wxIsWritable( file ) ) return; |
133 |
|
134 |
const DWORD flags = isFile ? FILE_ATTRIBUTE_NORMAL : (FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_DIRECTORY); |
135 |
|
136 |
HANDLE bloated_crap = CreateFile( file, |
137 |
FILE_GENERIC_WRITE | FILE_GENERIC_READ, |
138 |
FILE_SHARE_READ | FILE_SHARE_DELETE, |
139 |
NULL, |
140 |
OPEN_EXISTING, |
141 |
flags, |
142 |
NULL |
143 |
); |
144 |
|
145 |
// Fail silently -- non-compression of files and folders is not an errorable offense. |
146 |
|
147 |
if( !StreamException_LogLastError( file, L"NTFS Compress Notice", bloated_crap ) ) |
148 |
{ |
149 |
DWORD bytesReturned = 0; |
150 |
DWORD compressMode = compressStatus ? COMPRESSION_FORMAT_DEFAULT : COMPRESSION_FORMAT_NONE; |
151 |
|
152 |
BOOL result = DeviceIoControl( |
153 |
bloated_crap, FSCTL_SET_COMPRESSION, |
154 |
&compressMode, 2, NULL, 0, |
155 |
&bytesReturned, NULL |
156 |
); |
157 |
|
158 |
if( !result ) |
159 |
StreamException_LogLastError( file, L"NTFS Compress Notice" ); |
160 |
|
161 |
CloseHandle( bloated_crap ); |
162 |
} |
163 |
} |