diff options
author | Rob Mensching <rob@firegiant.com> | 2021-04-10 16:05:23 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2021-04-12 09:56:15 -0700 |
commit | 0c2b4cf3a439eda3e19d20fadfc65ddc7d0394c0 (patch) | |
tree | 825272bd86d365d8f2175fd6fadd9725c8b400ff | |
parent | ed0ef472c76ac0d2a3d7a138e4f3b7ad950a56bc (diff) | |
download | wix-0c2b4cf3a439eda3e19d20fadfc65ddc7d0394c0.tar.gz wix-0c2b4cf3a439eda3e19d20fadfc65ddc7d0394c0.tar.bz2 wix-0c2b4cf3a439eda3e19d20fadfc65ddc7d0394c0.zip |
Integrate fixes that make dutil a little more robust to failure
-rw-r--r-- | src/dutil/cabutil.cpp | 52 | ||||
-rw-r--r-- | src/dutil/fileutil.cpp | 128 | ||||
-rw-r--r-- | src/dutil/inc/fileutil.h | 9 | ||||
-rw-r--r-- | src/dutil/inc/regutil.h | 13 | ||||
-rw-r--r-- | src/dutil/regutil.cpp | 59 | ||||
-rw-r--r-- | src/dutil/wiutil.cpp | 18 |
6 files changed, 265 insertions, 14 deletions
diff --git a/src/dutil/cabutil.cpp b/src/dutil/cabutil.cpp index 4a6f7b7b..5d77e483 100644 --- a/src/dutil/cabutil.cpp +++ b/src/dutil/cabutil.cpp | |||
@@ -102,6 +102,29 @@ LExit: | |||
102 | } | 102 | } |
103 | 103 | ||
104 | 104 | ||
105 | static HANDLE OpenFileWithRetry( | ||
106 | __in LPCWSTR wzPath, | ||
107 | __in DWORD dwDesiredAccess, | ||
108 | __in DWORD dwCreationDisposition | ||
109 | ) | ||
110 | { | ||
111 | HANDLE hFile = INVALID_HANDLE_VALUE; | ||
112 | |||
113 | for (DWORD i = 0; i < 30; ++i) | ||
114 | { | ||
115 | hFile = ::CreateFileW(wzPath, dwDesiredAccess, FILE_SHARE_READ, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL); | ||
116 | if (INVALID_HANDLE_VALUE != hFile) | ||
117 | { | ||
118 | break; | ||
119 | } | ||
120 | |||
121 | ::Sleep(100); | ||
122 | } | ||
123 | |||
124 | return hFile; | ||
125 | } | ||
126 | |||
127 | |||
105 | /******************************************************************** | 128 | /******************************************************************** |
106 | CabInitialize - initializes internal static variables | 129 | CabInitialize - initializes internal static variables |
107 | 130 | ||
@@ -340,6 +363,7 @@ static __callback void DIAMONDAPI CabExtractFree(__in LPVOID pvData) | |||
340 | static __callback INT_PTR FAR DIAMONDAPI CabExtractOpen(__in_z PSTR pszFile, __in int oflag, __in int pmode) | 363 | static __callback INT_PTR FAR DIAMONDAPI CabExtractOpen(__in_z PSTR pszFile, __in int oflag, __in int pmode) |
341 | { | 364 | { |
342 | HRESULT hr = S_OK; | 365 | HRESULT hr = S_OK; |
366 | HANDLE hFile = INVALID_HANDLE_VALUE; | ||
343 | INT_PTR pFile = -1; | 367 | INT_PTR pFile = -1; |
344 | LPWSTR sczCabFile = NULL; | 368 | LPWSTR sczCabFile = NULL; |
345 | 369 | ||
@@ -353,19 +377,24 @@ static __callback INT_PTR FAR DIAMONDAPI CabExtractOpen(__in_z PSTR pszFile, __i | |||
353 | hr = StrAllocStringAnsi(&sczCabFile, pszFile, 0, CP_UTF8); | 377 | hr = StrAllocStringAnsi(&sczCabFile, pszFile, 0, CP_UTF8); |
354 | CabExitOnFailure(hr, "Failed to convert UTF8 cab file name to wide character string"); | 378 | CabExitOnFailure(hr, "Failed to convert UTF8 cab file name to wide character string"); |
355 | 379 | ||
356 | pFile = reinterpret_cast<INT_PTR>(::CreateFileW(sczCabFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)); | 380 | hFile = OpenFileWithRetry(sczCabFile, GENERIC_READ, OPEN_EXISTING); |
357 | if (INVALID_HANDLE_VALUE == reinterpret_cast<HANDLE>(pFile)) | 381 | if (INVALID_HANDLE_VALUE == hFile) |
358 | { | 382 | { |
359 | CabExitWithLastError(hr, "failed to open file: %ls", sczCabFile); | 383 | CabExitWithLastError(hr, "failed to open file: %ls", sczCabFile); |
360 | } | 384 | } |
361 | 385 | ||
386 | pFile = reinterpret_cast<INT_PTR>(hFile); | ||
387 | |||
362 | if (vdw64EmbeddedOffset) | 388 | if (vdw64EmbeddedOffset) |
363 | { | 389 | { |
364 | hr = CabExtractSeek(pFile, 0, 0); | 390 | hr = CabExtractSeek(pFile, 0, 0); |
365 | CabExitOnFailure(hr, "Failed to seek to embedded offset %I64d", vdw64EmbeddedOffset); | 391 | CabExitOnFailure(hr, "Failed to seek to embedded offset %I64d", vdw64EmbeddedOffset); |
366 | } | 392 | } |
367 | 393 | ||
394 | hFile = INVALID_HANDLE_VALUE; | ||
395 | |||
368 | LExit: | 396 | LExit: |
397 | ReleaseFileHandle(hFile); | ||
369 | ReleaseStr(sczCabFile); | 398 | ReleaseStr(sczCabFile); |
370 | 399 | ||
371 | return FAILED(hr) ? -1 : pFile; | 400 | return FAILED(hr) ? -1 : pFile; |
@@ -460,6 +489,7 @@ static __callback INT_PTR DIAMONDAPI CabExtractCallback(__in FDINOTIFICATIONTYPE | |||
460 | Assert(pFDINotify->pv); | 489 | Assert(pFDINotify->pv); |
461 | 490 | ||
462 | HRESULT hr = S_OK; | 491 | HRESULT hr = S_OK; |
492 | HANDLE hFile = INVALID_HANDLE_VALUE; | ||
463 | INT_PTR ipResult = 0; // result to return on success | 493 | INT_PTR ipResult = 0; // result to return on success |
464 | 494 | ||
465 | CAB_CALLBACK_STRUCT* pccs = static_cast<CAB_CALLBACK_STRUCT*>(pFDINotify->pv); | 495 | CAB_CALLBACK_STRUCT* pccs = static_cast<CAB_CALLBACK_STRUCT*>(pFDINotify->pv); |
@@ -503,7 +533,6 @@ static __callback INT_PTR DIAMONDAPI CabExtractCallback(__in FDINOTIFICATIONTYPE | |||
503 | CabExitWithLastError(hr, "failed to get time for resource: %ls", wz); | 533 | CabExitWithLastError(hr, "failed to get time for resource: %ls", wz); |
504 | } | 534 | } |
505 | ::LocalFileTimeToFileTime(&ftLocal, &ft); | 535 | ::LocalFileTimeToFileTime(&ftLocal, &ft); |
506 | |||
507 | 536 | ||
508 | WCHAR wzPath[MAX_PATH]; | 537 | WCHAR wzPath[MAX_PATH]; |
509 | hr = ::StringCchCopyW(wzPath, countof(wzPath), pccs->pwzExtractDir); | 538 | hr = ::StringCchCopyW(wzPath, countof(wzPath), pccs->pwzExtractDir); |
@@ -511,21 +540,24 @@ static __callback INT_PTR DIAMONDAPI CabExtractCallback(__in FDINOTIFICATIONTYPE | |||
511 | hr = ::StringCchCatW(wzPath, countof(wzPath), wz); | 540 | hr = ::StringCchCatW(wzPath, countof(wzPath), wz); |
512 | CabExitOnFailure(hr, "failed to concat onto path: %ls file: %ls", wzPath, wz); | 541 | CabExitOnFailure(hr, "failed to concat onto path: %ls file: %ls", wzPath, wz); |
513 | 542 | ||
514 | ipResult = reinterpret_cast<INT_PTR>(::CreateFileW(wzPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)); | 543 | hFile = OpenFileWithRetry(wzPath, GENERIC_WRITE, CREATE_ALWAYS); |
515 | if (INVALID_HANDLE_VALUE == reinterpret_cast<HANDLE>(ipResult)) | 544 | if (INVALID_HANDLE_VALUE == hFile) |
516 | { | 545 | { |
517 | CabExitWithLastError(hr, "failed to create file: %ls", wzPath); | 546 | CabExitWithLastError(hr, "failed to create file: %ls", wzPath); |
518 | } | 547 | } |
519 | 548 | ||
520 | ::SetFileTime(reinterpret_cast<HANDLE>(ipResult), &ft, &ft, &ft); // try to set the file time (who cares if it fails) | 549 | ::SetFileTime(hFile, &ft, &ft, &ft); // try to set the file time (who cares if it fails) |
521 | 550 | ||
522 | if (::SetFilePointer(reinterpret_cast<HANDLE>(ipResult), pFDINotify->cb, NULL, FILE_BEGIN)) // try to set the end of the file (don't worry if this fails) | 551 | if (::SetFilePointer(hFile, pFDINotify->cb, NULL, FILE_BEGIN)) // try to set the end of the file (don't worry if this fails) |
523 | { | 552 | { |
524 | if (::SetEndOfFile(reinterpret_cast<HANDLE>(ipResult))) | 553 | if (::SetEndOfFile(hFile)) |
525 | { | 554 | { |
526 | ::SetFilePointer(reinterpret_cast<HANDLE>(ipResult), 0, NULL, FILE_BEGIN); // reset the file pointer | 555 | ::SetFilePointer(hFile, 0, NULL, FILE_BEGIN); // reset the file pointer |
527 | } | 556 | } |
528 | } | 557 | } |
558 | |||
559 | ipResult = reinterpret_cast<INT_PTR>(hFile); | ||
560 | hFile = INVALID_HANDLE_VALUE; | ||
529 | } | 561 | } |
530 | else // resource wasn't requested, skip it | 562 | else // resource wasn't requested, skip it |
531 | { | 563 | { |
@@ -579,5 +611,7 @@ static __callback INT_PTR DIAMONDAPI CabExtractCallback(__in FDINOTIFICATIONTYPE | |||
579 | }; | 611 | }; |
580 | 612 | ||
581 | LExit: | 613 | LExit: |
614 | ReleaseFileHandle(hFile); | ||
615 | |||
582 | return (S_OK == hr) ? ipResult : -1; | 616 | return (S_OK == hr) ? ipResult : -1; |
583 | } | 617 | } |
diff --git a/src/dutil/fileutil.cpp b/src/dutil/fileutil.cpp index c76017de..06a44b45 100644 --- a/src/dutil/fileutil.cpp +++ b/src/dutil/fileutil.cpp | |||
@@ -1106,6 +1106,134 @@ LExit: | |||
1106 | 1106 | ||
1107 | 1107 | ||
1108 | /******************************************************************* | 1108 | /******************************************************************* |
1109 | FileCopyUsingHandlesWithProgress | ||
1110 | |||
1111 | *******************************************************************/ | ||
1112 | extern "C" HRESULT DAPI FileCopyUsingHandlesWithProgress( | ||
1113 | __in HANDLE hSource, | ||
1114 | __in HANDLE hTarget, | ||
1115 | __in DWORD64 cbCopy, | ||
1116 | __in_opt LPPROGRESS_ROUTINE lpProgressRoutine, | ||
1117 | __in_opt LPVOID lpData, | ||
1118 | __in_opt LPBOOL pbCancel, | ||
1119 | __out_opt DWORD64* pcbCopied | ||
1120 | ) | ||
1121 | { | ||
1122 | HRESULT hr = S_OK; | ||
1123 | BOOL fStop = FALSE; | ||
1124 | BOOL fCanceled = FALSE; | ||
1125 | DWORD64 cbTotalCopied = 0; | ||
1126 | BYTE rgbData[64 * 1024]; | ||
1127 | DWORD cbRead = 0; | ||
1128 | |||
1129 | LARGE_INTEGER liSourceSize = { }; | ||
1130 | LARGE_INTEGER liTotalCopied = { }; | ||
1131 | LARGE_INTEGER liZero = { }; | ||
1132 | DWORD dwResult = 0; | ||
1133 | |||
1134 | hr = FileSizeByHandle(hSource, &liSourceSize.QuadPart); | ||
1135 | FileExitOnFailure(hr, "Failed to get size of source."); | ||
1136 | |||
1137 | if (0 < cbCopy && cbCopy < (DWORD64)liSourceSize.QuadPart) | ||
1138 | { | ||
1139 | liSourceSize.QuadPart = cbCopy; | ||
1140 | } | ||
1141 | |||
1142 | dwResult = lpProgressRoutine(liSourceSize, liTotalCopied, liZero, liZero, 0, CALLBACK_STREAM_SWITCH, hSource, hTarget, lpData); | ||
1143 | switch (dwResult) | ||
1144 | { | ||
1145 | case PROGRESS_CONTINUE: | ||
1146 | break; | ||
1147 | |||
1148 | case PROGRESS_CANCEL: | ||
1149 | fCanceled = TRUE; | ||
1150 | fStop = TRUE; | ||
1151 | break; | ||
1152 | |||
1153 | case PROGRESS_STOP: | ||
1154 | fStop = TRUE; | ||
1155 | break; | ||
1156 | |||
1157 | case PROGRESS_QUIET: | ||
1158 | lpProgressRoutine = NULL; | ||
1159 | break; | ||
1160 | } | ||
1161 | |||
1162 | // Set size of the target file. | ||
1163 | ::SetFilePointerEx(hTarget, liSourceSize, NULL, FILE_BEGIN); | ||
1164 | |||
1165 | if (!::SetEndOfFile(hTarget)) | ||
1166 | { | ||
1167 | FileExitWithLastError(hr, "Failed to set end of target file."); | ||
1168 | } | ||
1169 | |||
1170 | if (!::SetFilePointerEx(hTarget, liZero, NULL, FILE_BEGIN)) | ||
1171 | { | ||
1172 | FileExitWithLastError(hr, "Failed to reset target file pointer."); | ||
1173 | } | ||
1174 | |||
1175 | // Copy with progress. | ||
1176 | while (!fStop && (0 == cbCopy || cbTotalCopied < cbCopy)) | ||
1177 | { | ||
1178 | cbRead = static_cast<DWORD>((0 == cbCopy) ? countof(rgbData) : min(countof(rgbData), cbCopy - cbTotalCopied)); | ||
1179 | if (!::ReadFile(hSource, rgbData, cbRead, &cbRead, NULL)) | ||
1180 | { | ||
1181 | FileExitWithLastError(hr, "Failed to read from source."); | ||
1182 | } | ||
1183 | |||
1184 | if (cbRead) | ||
1185 | { | ||
1186 | hr = FileWriteHandle(hTarget, rgbData, cbRead); | ||
1187 | FileExitOnFailure(hr, "Failed to write to target."); | ||
1188 | |||
1189 | cbTotalCopied += cbRead; | ||
1190 | |||
1191 | if (lpProgressRoutine) | ||
1192 | { | ||
1193 | liTotalCopied.QuadPart = cbTotalCopied; | ||
1194 | dwResult = lpProgressRoutine(liSourceSize, liTotalCopied, liZero, liZero, 0, CALLBACK_CHUNK_FINISHED, hSource, hTarget, lpData); | ||
1195 | switch (dwResult) | ||
1196 | { | ||
1197 | case PROGRESS_CONTINUE: | ||
1198 | break; | ||
1199 | |||
1200 | case PROGRESS_CANCEL: | ||
1201 | fCanceled = TRUE; | ||
1202 | fStop = TRUE; | ||
1203 | break; | ||
1204 | |||
1205 | case PROGRESS_STOP: | ||
1206 | fStop = TRUE; | ||
1207 | break; | ||
1208 | |||
1209 | case PROGRESS_QUIET: | ||
1210 | lpProgressRoutine = NULL; | ||
1211 | break; | ||
1212 | } | ||
1213 | } | ||
1214 | } | ||
1215 | else | ||
1216 | { | ||
1217 | fStop = TRUE; | ||
1218 | } | ||
1219 | } | ||
1220 | |||
1221 | LExit: | ||
1222 | if (pbCancel) | ||
1223 | { | ||
1224 | *pbCancel = fCanceled; | ||
1225 | } | ||
1226 | |||
1227 | if (pcbCopied) | ||
1228 | { | ||
1229 | *pcbCopied = cbTotalCopied; | ||
1230 | } | ||
1231 | |||
1232 | return hr; | ||
1233 | } | ||
1234 | |||
1235 | |||
1236 | /******************************************************************* | ||
1109 | FileEnsureCopy | 1237 | FileEnsureCopy |
1110 | 1238 | ||
1111 | *******************************************************************/ | 1239 | *******************************************************************/ |
diff --git a/src/dutil/inc/fileutil.h b/src/dutil/inc/fileutil.h index 7caa62b8..48830043 100644 --- a/src/dutil/inc/fileutil.h +++ b/src/dutil/inc/fileutil.h | |||
@@ -148,6 +148,15 @@ HRESULT DAPI FileCopyUsingHandles( | |||
148 | __in DWORD64 cbCopy, | 148 | __in DWORD64 cbCopy, |
149 | __out_opt DWORD64* pcbCopied | 149 | __out_opt DWORD64* pcbCopied |
150 | ); | 150 | ); |
151 | HRESULT DAPI FileCopyUsingHandlesWithProgress( | ||
152 | __in HANDLE hSource, | ||
153 | __in HANDLE hTarget, | ||
154 | __in DWORD64 cbCopy, | ||
155 | __in_opt LPPROGRESS_ROUTINE lpProgressRoutine, | ||
156 | __in_opt LPVOID lpData, | ||
157 | __in_opt LPBOOL pbCancel, | ||
158 | __out_opt DWORD64* pcbCopied | ||
159 | ); | ||
151 | HRESULT DAPI FileEnsureCopy( | 160 | HRESULT DAPI FileEnsureCopy( |
152 | __in_z LPCWSTR wzSource, | 161 | __in_z LPCWSTR wzSource, |
153 | __in_z LPCWSTR wzTarget, | 162 | __in_z LPCWSTR wzTarget, |
diff --git a/src/dutil/inc/regutil.h b/src/dutil/inc/regutil.h index 2f09d244..75284940 100644 --- a/src/dutil/inc/regutil.h +++ b/src/dutil/inc/regutil.h | |||
@@ -226,6 +226,19 @@ HRESULT DAPI RegQueryKey( | |||
226 | __out_opt DWORD* pcSubKeys, | 226 | __out_opt DWORD* pcSubKeys, |
227 | __out_opt DWORD* pcValues | 227 | __out_opt DWORD* pcValues |
228 | ); | 228 | ); |
229 | HRESULT DAPI RegKeyReadNumber( | ||
230 | __in HKEY hk, | ||
231 | __in_z LPCWSTR wzSubKey, | ||
232 | __in_z_opt LPCWSTR wzName, | ||
233 | __in BOOL f64Bit, | ||
234 | __out DWORD* pdwValue | ||
235 | ); | ||
236 | BOOL DAPI RegValueExists( | ||
237 | __in HKEY hk, | ||
238 | __in_z LPCWSTR wzSubKey, | ||
239 | __in_z_opt LPCWSTR wzName, | ||
240 | __in BOOL f64Bit | ||
241 | ); | ||
229 | 242 | ||
230 | #ifdef __cplusplus | 243 | #ifdef __cplusplus |
231 | } | 244 | } |
diff --git a/src/dutil/regutil.cpp b/src/dutil/regutil.cpp index e1ef19e8..afd2d089 100644 --- a/src/dutil/regutil.cpp +++ b/src/dutil/regutil.cpp | |||
@@ -283,7 +283,7 @@ LExit: | |||
283 | 283 | ||
284 | 284 | ||
285 | /******************************************************************** | 285 | /******************************************************************** |
286 | RegKeyEnum - enumerates a registry key. | 286 | RegKeyEnum - enumerates child registry keys. |
287 | 287 | ||
288 | *********************************************************************/ | 288 | *********************************************************************/ |
289 | extern "C" HRESULT DAPI RegKeyEnum( | 289 | extern "C" HRESULT DAPI RegKeyEnum( |
@@ -340,7 +340,7 @@ LExit: | |||
340 | 340 | ||
341 | 341 | ||
342 | /******************************************************************** | 342 | /******************************************************************** |
343 | RegValueEnum - enumerates a registry value. | 343 | RegValueEnum - enumerates registry values. |
344 | 344 | ||
345 | *********************************************************************/ | 345 | *********************************************************************/ |
346 | HRESULT DAPI RegValueEnum( | 346 | HRESULT DAPI RegValueEnum( |
@@ -939,6 +939,61 @@ LExit: | |||
939 | return hr; | 939 | return hr; |
940 | } | 940 | } |
941 | 941 | ||
942 | /******************************************************************** | ||
943 | RegKeyReadNumber - reads a DWORD registry key value as a number from | ||
944 | a specified subkey. | ||
945 | |||
946 | *********************************************************************/ | ||
947 | extern "C" HRESULT DAPI RegKeyReadNumber( | ||
948 | __in HKEY hk, | ||
949 | __in_z LPCWSTR wzSubKey, | ||
950 | __in_z_opt LPCWSTR wzName, | ||
951 | __in BOOL f64Bit, | ||
952 | __out DWORD* pdwValue | ||
953 | ) | ||
954 | { | ||
955 | HRESULT hr = S_OK; | ||
956 | HKEY hkKey = NULL; | ||
957 | |||
958 | hr = RegOpen(hk, wzSubKey, KEY_READ | f64Bit ? KEY_WOW64_64KEY : 0, &hkKey); | ||
959 | RegExitOnFailure(hr, "Failed to open key: %ls", wzSubKey); | ||
960 | |||
961 | hr = RegReadNumber(hkKey, wzName, pdwValue); | ||
962 | RegExitOnFailure(hr, "Failed to read value: %ls/@%ls", wzSubKey, wzName); | ||
963 | |||
964 | LExit: | ||
965 | ReleaseRegKey(hkKey); | ||
966 | |||
967 | return hr; | ||
968 | } | ||
969 | |||
970 | /******************************************************************** | ||
971 | RegValueExists - determines whether a named value exists in a | ||
972 | specified subkey. | ||
973 | |||
974 | *********************************************************************/ | ||
975 | extern "C" BOOL DAPI RegValueExists( | ||
976 | __in HKEY hk, | ||
977 | __in_z LPCWSTR wzSubKey, | ||
978 | __in_z_opt LPCWSTR wzName, | ||
979 | __in BOOL f64Bit | ||
980 | ) | ||
981 | { | ||
982 | HRESULT hr = S_OK; | ||
983 | HKEY hkKey = NULL; | ||
984 | DWORD dwType = 0; | ||
985 | |||
986 | hr = RegOpen(hk, wzSubKey, KEY_READ | f64Bit ? KEY_WOW64_64KEY : 0, &hkKey); | ||
987 | RegExitOnFailure(hr, "Failed to open key: %ls", wzSubKey); | ||
988 | |||
989 | hr = RegGetType(hkKey, wzName, &dwType); | ||
990 | RegExitOnFailure(hr, "Failed to read value type: %ls/@%ls", wzSubKey, wzName); | ||
991 | |||
992 | LExit: | ||
993 | ReleaseRegKey(hkKey); | ||
994 | |||
995 | return SUCCEEDED(hr); | ||
996 | } | ||
942 | 997 | ||
943 | static HRESULT WriteStringToRegistry( | 998 | static HRESULT WriteStringToRegistry( |
944 | __in HKEY hk, | 999 | __in HKEY hk, |
diff --git a/src/dutil/wiutil.cpp b/src/dutil/wiutil.cpp index ffbfe85a..f1984266 100644 --- a/src/dutil/wiutil.cpp +++ b/src/dutil/wiutil.cpp | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | 5 | ||
6 | // Exit macros | 6 | // Exit macros |
7 | #define WiuExitTrace(x, s, ...) ExitTraceSource(DUTIL_SOURCE_WIUTIL, x, s, __VA_ARGS__) | ||
7 | #define WiuExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_WIUTIL, x, s, __VA_ARGS__) | 8 | #define WiuExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_WIUTIL, x, s, __VA_ARGS__) |
8 | #define WiuExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_WIUTIL, x, s, __VA_ARGS__) | 9 | #define WiuExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_WIUTIL, x, s, __VA_ARGS__) |
9 | #define WiuExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_WIUTIL, x, s, __VA_ARGS__) | 10 | #define WiuExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_WIUTIL, x, s, __VA_ARGS__) |
@@ -692,12 +693,23 @@ extern "C" HRESULT DAPI WiuEnumRelatedProductCodes( | |||
692 | 693 | ||
693 | if (fReturnHighestVersionOnly) | 694 | if (fReturnHighestVersionOnly) |
694 | { | 695 | { |
695 | // get the version | 696 | // try to get the version but if the product registration is broken |
697 | // (for whatever reason), skip this product | ||
696 | hr = WiuGetProductInfo(wzCurrentProductCode, L"VersionString", &sczInstalledVersion); | 698 | hr = WiuGetProductInfo(wzCurrentProductCode, L"VersionString", &sczInstalledVersion); |
697 | WiuExitOnFailure(hr, "Failed to get version for product code: %ls", wzCurrentProductCode); | 699 | if (FAILED(hr)) |
700 | { | ||
701 | WiuExitTrace(hr, "Could not get product version for product code: %ls, skipping...", wzCurrentProductCode); | ||
702 | continue; | ||
703 | } | ||
698 | 704 | ||
705 | // try to parse the product version but if it is corrupt (for whatever | ||
706 | // reason), skip it | ||
699 | hr = FileVersionFromStringEx(sczInstalledVersion, 0, &qwCurrentVersion); | 707 | hr = FileVersionFromStringEx(sczInstalledVersion, 0, &qwCurrentVersion); |
700 | WiuExitOnFailure(hr, "Failed to convert version: %ls to DWORD64 for product code: %ls", sczInstalledVersion, wzCurrentProductCode); | 708 | if (FAILED(hr)) |
709 | { | ||
710 | WiuExitTrace(hr, "Could not convert version: %ls to DWORD64 for product code: %ls, skipping...", sczInstalledVersion, wzCurrentProductCode); | ||
711 | continue; | ||
712 | } | ||
701 | 713 | ||
702 | // if this is the first product found then it is the highest version (for now) | 714 | // if this is the first product found then it is the highest version (for now) |
703 | if (0 == *pcRelatedProducts) | 715 | if (0 == *pcRelatedProducts) |