diff options
Diffstat (limited to '')
-rw-r--r-- | src/dutil/cabutil.cpp | 52 |
1 files changed, 43 insertions, 9 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 | } |