aboutsummaryrefslogtreecommitdiff
path: root/src/dutil/cabutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/dutil/cabutil.cpp52
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
105static 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)
340static __callback INT_PTR FAR DIAMONDAPI CabExtractOpen(__in_z PSTR pszFile, __in int oflag, __in int pmode) 363static __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
368LExit: 396LExit:
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
581LExit: 613LExit:
614 ReleaseFileHandle(hFile);
615
582 return (S_OK == hr) ? ipResult : -1; 616 return (S_OK == hr) ? ipResult : -1;
583} 617}