diff options
Diffstat (limited to 'src/dutil/fileutil.cpp')
-rw-r--r-- | src/dutil/fileutil.cpp | 149 |
1 files changed, 99 insertions, 50 deletions
diff --git a/src/dutil/fileutil.cpp b/src/dutil/fileutil.cpp index 6cc2a80e..1822727a 100644 --- a/src/dutil/fileutil.cpp +++ b/src/dutil/fileutil.cpp | |||
@@ -155,40 +155,33 @@ __out LPWSTR *ppwzFileNameNoExtension | |||
155 | Assert(wzFileName && *wzFileName); | 155 | Assert(wzFileName && *wzFileName); |
156 | 156 | ||
157 | HRESULT hr = S_OK; | 157 | HRESULT hr = S_OK; |
158 | 158 | size_t cchFileName = 0; | |
159 | SIZE_T cchFileName = wcslen(wzFileName); | ||
160 | |||
161 | LPWSTR pwzFileNameNoExtension = NULL; | 159 | LPWSTR pwzFileNameNoExtension = NULL; |
162 | DWORD cchFileNameNoExtension = 0; | 160 | size_t cchFileNameNoExtension = 0; |
163 | 161 | errno_t err = 0; | |
164 | // Filename without extension can not be longer than _MAX_FNAME | 162 | |
165 | // Filename without extension should also not be longer than filename itself | 163 | hr = ::StringCchLengthW(wzFileName, STRSAFE_MAX_LENGTH, &cchFileName); |
166 | if (_MAX_FNAME > cchFileName) | 164 | FileExitOnRootFailure(hr, "failed to get length of file name: %ls", wzFileName); |
167 | { | 165 | |
168 | cchFileNameNoExtension = (DWORD) cchFileName; | 166 | cchFileNameNoExtension = cchFileName + 1; |
169 | } | 167 | |
170 | else | ||
171 | { | ||
172 | cchFileNameNoExtension = _MAX_FNAME; | ||
173 | } | ||
174 | |||
175 | hr = StrAlloc(&pwzFileNameNoExtension, cchFileNameNoExtension); | 168 | hr = StrAlloc(&pwzFileNameNoExtension, cchFileNameNoExtension); |
176 | FileExitOnFailure(hr, "failed to allocate space for File Name without extension"); | 169 | FileExitOnFailure(hr, "failed to allocate space for File Name without extension"); |
177 | 170 | ||
178 | // _wsplitpath_s can handle drive/path/filename/extension | 171 | // _wsplitpath_s can handle drive/path/filename/extension |
179 | errno_t err = _wsplitpath_s(wzFileName, NULL, NULL, NULL, NULL, pwzFileNameNoExtension, cchFileNameNoExtension, NULL, NULL); | 172 | err = _wsplitpath_s(wzFileName, NULL, NULL, NULL, NULL, pwzFileNameNoExtension, cchFileNameNoExtension, NULL, NULL); |
180 | if (0 != err) | 173 | if (err) |
181 | { | 174 | { |
182 | hr = E_INVALIDARG; | 175 | hr = E_INVALIDARG; |
183 | FileExitOnFailure(hr, "failed to parse filename: %ls", wzFileName); | 176 | FileExitOnRootFailure(hr, "failed to parse filename: '%ls', error: %d", wzFileName, err); |
184 | } | 177 | } |
185 | 178 | ||
186 | *ppwzFileNameNoExtension = pwzFileNameNoExtension; | 179 | *ppwzFileNameNoExtension = pwzFileNameNoExtension; |
187 | pwzFileNameNoExtension = NULL; | 180 | pwzFileNameNoExtension = NULL; |
188 | 181 | ||
189 | LExit: | 182 | LExit: |
190 | ReleaseStr(pwzFileNameNoExtension); | 183 | ReleaseStr(pwzFileNameNoExtension); |
191 | 184 | ||
192 | return hr; | 185 | return hr; |
193 | } | 186 | } |
194 | 187 | ||
@@ -237,8 +230,12 @@ extern "C" HRESULT DAPI FileAddSuffixToBaseName( | |||
237 | 230 | ||
238 | HRESULT hr = S_OK; | 231 | HRESULT hr = S_OK; |
239 | LPWSTR sczNewFileName = NULL; | 232 | LPWSTR sczNewFileName = NULL; |
233 | size_t cchFileName = 0; | ||
234 | |||
235 | hr = ::StringCchLengthW(wzFileName, STRSAFE_MAX_CCH, &cchFileName); | ||
236 | FileExitOnRootFailure(hr, "Failed to get length of file name: %ls", wzFileName); | ||
240 | 237 | ||
241 | LPCWSTR wzExtension = wzFileName + lstrlenW(wzFileName); | 238 | LPCWSTR wzExtension = wzFileName + cchFileName; |
242 | while (wzFileName < wzExtension && L'.' != *wzExtension) | 239 | while (wzFileName < wzExtension && L'.' != *wzExtension) |
243 | { | 240 | { |
244 | --wzExtension; | 241 | --wzExtension; |
@@ -410,7 +407,7 @@ LExit: | |||
410 | *******************************************************************/ | 407 | *******************************************************************/ |
411 | extern "C" HRESULT DAPI FileVersionFromStringEx( | 408 | extern "C" HRESULT DAPI FileVersionFromStringEx( |
412 | __in_z LPCWSTR wzVersion, | 409 | __in_z LPCWSTR wzVersion, |
413 | __in DWORD cchVersion, | 410 | __in SIZE_T cchVersion, |
414 | __out DWORD64* pqwVersion | 411 | __out DWORD64* pqwVersion |
415 | ) | 412 | ) |
416 | { | 413 | { |
@@ -428,7 +425,9 @@ extern "C" HRESULT DAPI FileVersionFromStringEx( | |||
428 | // get string length if not provided | 425 | // get string length if not provided |
429 | if (0 >= cchVersion) | 426 | if (0 >= cchVersion) |
430 | { | 427 | { |
431 | cchVersion = lstrlenW(wzVersion); | 428 | hr = ::StringCchLengthW(wzVersion, STRSAFE_MAX_CCH, reinterpret_cast<size_t*>(&cchVersion)); |
429 | FileExitOnRootFailure(hr, "Failed to get length of file version string: %ls", wzVersion); | ||
430 | |||
432 | if (0 >= cchVersion) | 431 | if (0 >= cchVersion) |
433 | { | 432 | { |
434 | ExitFunction1(hr = E_INVALIDARG); | 433 | ExitFunction1(hr = E_INVALIDARG); |
@@ -996,6 +995,41 @@ LExit: | |||
996 | return hr; | 995 | return hr; |
997 | } | 996 | } |
998 | 997 | ||
998 | extern "C" HRESULT DAPI FileReadHandle( | ||
999 | __in HANDLE hFile, | ||
1000 | __in_bcount(cbDest) LPBYTE pbDest, | ||
1001 | __in SIZE_T cbDest | ||
1002 | ) | ||
1003 | { | ||
1004 | HRESULT hr = 0; | ||
1005 | DWORD cbDataRead = 0; | ||
1006 | SIZE_T cbRemaining = cbDest; | ||
1007 | SIZE_T cbTotal = 0; | ||
1008 | |||
1009 | while (0 < cbRemaining) | ||
1010 | { | ||
1011 | if (!::ReadFile(hFile, pbDest + cbTotal, (DWORD)min(DWORD_MAX, cbRemaining), &cbDataRead, NULL)) | ||
1012 | { | ||
1013 | DWORD er = ::GetLastError(); | ||
1014 | if (ERROR_MORE_DATA == er) | ||
1015 | { | ||
1016 | hr = S_OK; | ||
1017 | } | ||
1018 | else | ||
1019 | { | ||
1020 | hr = HRESULT_FROM_WIN32(er); | ||
1021 | } | ||
1022 | FileExitOnRootFailure(hr, "Failed to read data from file handle."); | ||
1023 | } | ||
1024 | |||
1025 | cbRemaining -= cbDataRead; | ||
1026 | cbTotal += cbDataRead; | ||
1027 | } | ||
1028 | |||
1029 | LExit: | ||
1030 | return hr; | ||
1031 | } | ||
1032 | |||
999 | 1033 | ||
1000 | /******************************************************************* | 1034 | /******************************************************************* |
1001 | FileWrite - write a file from memory | 1035 | FileWrite - write a file from memory |
@@ -1044,18 +1078,20 @@ extern "C" HRESULT DAPI FileWriteHandle( | |||
1044 | { | 1078 | { |
1045 | HRESULT hr = S_OK; | 1079 | HRESULT hr = S_OK; |
1046 | DWORD cbDataWritten = 0; | 1080 | DWORD cbDataWritten = 0; |
1047 | DWORD cbTotal = 0; | 1081 | SIZE_T cbTotal = 0; |
1082 | SIZE_T cbRemaining = cbData; | ||
1048 | 1083 | ||
1049 | // Write out all of the data. | 1084 | // Write out all of the data. |
1050 | do | 1085 | while (0 < cbRemaining) |
1051 | { | 1086 | { |
1052 | if (!::WriteFile(hFile, pbData + cbTotal, (DWORD)(cbData - cbTotal), &cbDataWritten, NULL)) | 1087 | if (!::WriteFile(hFile, pbData + cbTotal, (DWORD)min(DWORD_MAX, cbRemaining), &cbDataWritten, NULL)) |
1053 | { | 1088 | { |
1054 | FileExitOnLastError(hr, "Failed to write data to file handle."); | 1089 | FileExitOnLastError(hr, "Failed to write data to file handle."); |
1055 | } | 1090 | } |
1056 | 1091 | ||
1092 | cbRemaining -= cbDataWritten; | ||
1057 | cbTotal += cbDataWritten; | 1093 | cbTotal += cbDataWritten; |
1058 | } while (cbTotal < cbData); | 1094 | } |
1059 | 1095 | ||
1060 | LExit: | 1096 | LExit: |
1061 | return hr; | 1097 | return hr; |
@@ -1115,7 +1151,7 @@ extern "C" HRESULT DAPI FileCopyUsingHandlesWithProgress( | |||
1115 | __in DWORD64 cbCopy, | 1151 | __in DWORD64 cbCopy, |
1116 | __in_opt LPPROGRESS_ROUTINE lpProgressRoutine, | 1152 | __in_opt LPPROGRESS_ROUTINE lpProgressRoutine, |
1117 | __in_opt LPVOID lpData | 1153 | __in_opt LPVOID lpData |
1118 | ) | 1154 | ) |
1119 | { | 1155 | { |
1120 | HRESULT hr = S_OK; | 1156 | HRESULT hr = S_OK; |
1121 | DWORD64 cbTotalCopied = 0; | 1157 | DWORD64 cbTotalCopied = 0; |
@@ -1135,21 +1171,24 @@ extern "C" HRESULT DAPI FileCopyUsingHandlesWithProgress( | |||
1135 | liSourceSize.QuadPart = cbCopy; | 1171 | liSourceSize.QuadPart = cbCopy; |
1136 | } | 1172 | } |
1137 | 1173 | ||
1138 | dwResult = lpProgressRoutine(liSourceSize, liTotalCopied, liZero, liZero, 0, CALLBACK_STREAM_SWITCH, hSource, hTarget, lpData); | 1174 | if (lpProgressRoutine) |
1139 | switch (dwResult) | ||
1140 | { | 1175 | { |
1141 | case PROGRESS_CONTINUE: | 1176 | dwResult = lpProgressRoutine(liSourceSize, liTotalCopied, liZero, liZero, 0, CALLBACK_STREAM_SWITCH, hSource, hTarget, lpData); |
1142 | break; | 1177 | switch (dwResult) |
1178 | { | ||
1179 | case PROGRESS_CONTINUE: | ||
1180 | break; | ||
1143 | 1181 | ||
1144 | case PROGRESS_CANCEL: | 1182 | case PROGRESS_CANCEL: |
1145 | ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_REQUEST_ABORTED)); | 1183 | ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_REQUEST_ABORTED)); |
1146 | 1184 | ||
1147 | case PROGRESS_STOP: | 1185 | case PROGRESS_STOP: |
1148 | ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_REQUEST_ABORTED)); | 1186 | ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_REQUEST_ABORTED)); |
1149 | 1187 | ||
1150 | case PROGRESS_QUIET: | 1188 | case PROGRESS_QUIET: |
1151 | lpProgressRoutine = NULL; | 1189 | lpProgressRoutine = NULL; |
1152 | break; | 1190 | break; |
1191 | } | ||
1153 | } | 1192 | } |
1154 | 1193 | ||
1155 | // Set size of the target file. | 1194 | // Set size of the target file. |
@@ -1929,23 +1968,27 @@ extern "C" HRESULT DAPI FileFromString( | |||
1929 | LPSTR sczUtf8String = NULL; | 1968 | LPSTR sczUtf8String = NULL; |
1930 | BYTE *pbFullFileBuffer = NULL; | 1969 | BYTE *pbFullFileBuffer = NULL; |
1931 | const BYTE *pcbFullFileBuffer = NULL; | 1970 | const BYTE *pcbFullFileBuffer = NULL; |
1932 | DWORD cbFullFileBuffer = 0; | 1971 | SIZE_T cbFullFileBuffer = 0; |
1933 | DWORD cbStrLen = 0; | 1972 | SIZE_T cbStrLen = 0; |
1934 | 1973 | ||
1935 | switch (feEncoding) | 1974 | switch (feEncoding) |
1936 | { | 1975 | { |
1937 | case FILE_ENCODING_UTF8: | 1976 | case FILE_ENCODING_UTF8: |
1938 | hr = StrAnsiAllocString(&sczUtf8String, sczString, 0, CP_UTF8); | 1977 | hr = StrAnsiAllocString(&sczUtf8String, sczString, 0, CP_UTF8); |
1939 | FileExitOnFailure(hr, "Failed to convert string to UTF-8 to write UTF-8 file"); | 1978 | FileExitOnFailure(hr, "Failed to convert string to UTF-8 to write UTF-8 file"); |
1940 | 1979 | ||
1941 | cbFullFileBuffer = lstrlenA(sczUtf8String); | 1980 | hr = ::StringCchLengthA(sczUtf8String, STRSAFE_MAX_CCH, reinterpret_cast<size_t*>(&cbFullFileBuffer)); |
1981 | FileExitOnRootFailure(hr, "Failed to get length of UTF-8 string"); | ||
1982 | |||
1942 | pcbFullFileBuffer = reinterpret_cast<BYTE *>(sczUtf8String); | 1983 | pcbFullFileBuffer = reinterpret_cast<BYTE *>(sczUtf8String); |
1943 | break; | 1984 | break; |
1944 | case FILE_ENCODING_UTF8_WITH_BOM: | 1985 | case FILE_ENCODING_UTF8_WITH_BOM: |
1945 | hr = StrAnsiAllocString(&sczUtf8String, sczString, 0, CP_UTF8); | 1986 | hr = StrAnsiAllocString(&sczUtf8String, sczString, 0, CP_UTF8); |
1946 | FileExitOnFailure(hr, "Failed to convert string to UTF-8 to write UTF-8 file"); | 1987 | FileExitOnFailure(hr, "Failed to convert string to UTF-8 to write UTF-8 file"); |
1947 | 1988 | ||
1948 | cbStrLen = lstrlenA(sczUtf8String); | 1989 | hr = ::StringCchLengthA(sczUtf8String, STRSAFE_MAX_CCH, reinterpret_cast<size_t*>(&cbStrLen)); |
1990 | FileExitOnRootFailure(hr, "Failed to get length of UTF-8 string"); | ||
1991 | |||
1949 | cbFullFileBuffer = sizeof(UTF8BOM) + cbStrLen; | 1992 | cbFullFileBuffer = sizeof(UTF8BOM) + cbStrLen; |
1950 | 1993 | ||
1951 | pbFullFileBuffer = reinterpret_cast<BYTE *>(MemAlloc(cbFullFileBuffer, TRUE)); | 1994 | pbFullFileBuffer = reinterpret_cast<BYTE *>(MemAlloc(cbFullFileBuffer, TRUE)); |
@@ -1956,11 +1999,17 @@ extern "C" HRESULT DAPI FileFromString( | |||
1956 | pcbFullFileBuffer = pbFullFileBuffer; | 1999 | pcbFullFileBuffer = pbFullFileBuffer; |
1957 | break; | 2000 | break; |
1958 | case FILE_ENCODING_UTF16: | 2001 | case FILE_ENCODING_UTF16: |
1959 | cbFullFileBuffer = lstrlenW(sczString) * sizeof(WCHAR); | 2002 | hr = ::StringCchLengthW(sczString, STRSAFE_MAX_CCH, reinterpret_cast<size_t*>(&cbStrLen)); |
2003 | FileExitOnRootFailure(hr, "Failed to get length of string"); | ||
2004 | |||
2005 | cbFullFileBuffer = cbStrLen * sizeof(WCHAR); | ||
1960 | pcbFullFileBuffer = reinterpret_cast<const BYTE *>(sczString); | 2006 | pcbFullFileBuffer = reinterpret_cast<const BYTE *>(sczString); |
1961 | break; | 2007 | break; |
1962 | case FILE_ENCODING_UTF16_WITH_BOM: | 2008 | case FILE_ENCODING_UTF16_WITH_BOM: |
1963 | cbStrLen = lstrlenW(sczString) * sizeof(WCHAR); | 2009 | hr = ::StringCchLengthW(sczString, STRSAFE_MAX_CCH, reinterpret_cast<size_t*>(&cbStrLen)); |
2010 | FileExitOnRootFailure(hr, "Failed to get length of string"); | ||
2011 | |||
2012 | cbStrLen *= sizeof(WCHAR); | ||
1964 | cbFullFileBuffer = sizeof(UTF16BOM) + cbStrLen; | 2013 | cbFullFileBuffer = sizeof(UTF16BOM) + cbStrLen; |
1965 | 2014 | ||
1966 | pbFullFileBuffer = reinterpret_cast<BYTE *>(MemAlloc(cbFullFileBuffer, TRUE)); | 2015 | pbFullFileBuffer = reinterpret_cast<BYTE *>(MemAlloc(cbFullFileBuffer, TRUE)); |