diff options
Diffstat (limited to 'src/dutil/cabutil.cpp')
| -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 | } |
