diff options
| author | Rob Mensching <rob@firegiant.com> | 2024-12-28 12:04:00 -0800 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2025-02-11 15:49:33 -0800 |
| commit | a797638d231b568b3e53bb2f478c28b6c0d5a1dc (patch) | |
| tree | 065a51afd27f6d440a94f79daea56bb0d02e1605 /src | |
| parent | cfb2df2e88b9ee273852124bbbdb1342207e96f9 (diff) | |
| download | wix-a797638d231b568b3e53bb2f478c28b6c0d5a1dc.tar.gz wix-a797638d231b568b3e53bb2f478c28b6c0d5a1dc.tar.bz2 wix-a797638d231b568b3e53bb2f478c28b6c0d5a1dc.zip | |
Support extracting cabbed file straight to file handle
Diffstat (limited to '')
| -rw-r--r-- | src/burn/engine/cabextract.cpp | 126 | ||||
| -rw-r--r-- | src/burn/engine/cabextract.h | 4 |
2 files changed, 99 insertions, 31 deletions
diff --git a/src/burn/engine/cabextract.cpp b/src/burn/engine/cabextract.cpp index 56146a39..5663c3f7 100644 --- a/src/burn/engine/cabextract.cpp +++ b/src/burn/engine/cabextract.cpp | |||
| @@ -55,6 +55,14 @@ static INT_PTR CloseFileInfoCallback( | |||
| 55 | __in BURN_CONTAINER_CONTEXT* pContext, | 55 | __in BURN_CONTAINER_CONTEXT* pContext, |
| 56 | __inout FDINOTIFICATION *pFDINotify | 56 | __inout FDINOTIFICATION *pFDINotify |
| 57 | ); | 57 | ); |
| 58 | static HRESULT PrepareTargetFile( | ||
| 59 | __in long cb, | ||
| 60 | __in HANDLE hFile | ||
| 61 | ); | ||
| 62 | static void BestEffortSetFileTime( | ||
| 63 | __in FDINOTIFICATION* pFDINotify, | ||
| 64 | __in HANDLE hFile | ||
| 65 | ); | ||
| 58 | static LPVOID DIAMONDAPI CabAlloc( | 66 | static LPVOID DIAMONDAPI CabAlloc( |
| 59 | __in DWORD dwSize | 67 | __in DWORD dwSize |
| 60 | ); | 68 | ); |
| @@ -226,6 +234,28 @@ LExit: | |||
| 226 | return hr; | 234 | return hr; |
| 227 | } | 235 | } |
| 228 | 236 | ||
| 237 | extern "C" HRESULT CabExtractStreamToHandle( | ||
| 238 | __in BURN_CONTAINER_CONTEXT* pContext, | ||
| 239 | __in HANDLE hFile | ||
| 240 | ) | ||
| 241 | { | ||
| 242 | HRESULT hr = S_OK; | ||
| 243 | |||
| 244 | // set operation to move to next stream | ||
| 245 | pContext->Cabinet.operation = BURN_CAB_OPERATION_STREAM_TO_HANDLE; | ||
| 246 | pContext->Cabinet.hTargetFile = hFile; | ||
| 247 | |||
| 248 | // begin operation and wait | ||
| 249 | hr = BeginAndWaitForOperation(pContext); | ||
| 250 | ExitOnFailure(hr, "Failed to begin and wait for operation."); | ||
| 251 | |||
| 252 | // clear file handle | ||
| 253 | pContext->Cabinet.hTargetFile = INVALID_HANDLE_VALUE; | ||
| 254 | |||
| 255 | LExit: | ||
| 256 | return hr; | ||
| 257 | } | ||
| 258 | |||
| 229 | extern "C" HRESULT CabExtractSkipStream( | 259 | extern "C" HRESULT CabExtractSkipStream( |
| 230 | __in BURN_CONTAINER_CONTEXT* pContext | 260 | __in BURN_CONTAINER_CONTEXT* pContext |
| 231 | ) | 261 | ) |
| @@ -505,8 +535,6 @@ static INT_PTR CopyFileCallback( | |||
| 505 | { | 535 | { |
| 506 | HRESULT hr = S_OK; | 536 | HRESULT hr = S_OK; |
| 507 | INT_PTR ipResult = 1; // result to return on success | 537 | INT_PTR ipResult = 1; // result to return on success |
| 508 | LPWSTR pwzPath = NULL; | ||
| 509 | LARGE_INTEGER li = { }; | ||
| 510 | 538 | ||
| 511 | // set operation complete event | 539 | // set operation complete event |
| 512 | if (!::SetEvent(pContext->Cabinet.hOperationCompleteEvent)) | 540 | if (!::SetEvent(pContext->Cabinet.hOperationCompleteEvent)) |
| @@ -567,23 +595,14 @@ static INT_PTR CopyFileCallback( | |||
| 567 | ExitWithLastError(hr, "Failed to create file: %ls", pContext->Cabinet.wzTargetFile); | 595 | ExitWithLastError(hr, "Failed to create file: %ls", pContext->Cabinet.wzTargetFile); |
| 568 | } | 596 | } |
| 569 | 597 | ||
| 570 | // set file size | 598 | hr = PrepareTargetFile(pFDINotify->cb, pContext->Cabinet.hTargetFile); |
| 571 | li.QuadPart = pFDINotify->cb; | 599 | ExitOnFailure(hr, "Failed to prepare target file."); |
| 572 | if (!::SetFilePointerEx(pContext->Cabinet.hTargetFile, li, NULL, FILE_BEGIN)) | ||
| 573 | { | ||
| 574 | ExitWithLastError(hr, "Failed to set file pointer to end of file."); | ||
| 575 | } | ||
| 576 | 600 | ||
| 577 | if (!::SetEndOfFile(pContext->Cabinet.hTargetFile)) | 601 | break; |
| 578 | { | ||
| 579 | ExitWithLastError(hr, "Failed to set end of file."); | ||
| 580 | } | ||
| 581 | 602 | ||
| 582 | li.QuadPart = 0; | 603 | case BURN_CAB_OPERATION_STREAM_TO_HANDLE: |
| 583 | if (!::SetFilePointerEx(pContext->Cabinet.hTargetFile, li, NULL, FILE_BEGIN)) | 604 | hr = PrepareTargetFile(pFDINotify->cb, pContext->Cabinet.hTargetFile); |
| 584 | { | 605 | ExitOnFailure(hr, "Failed to prepare target file."); |
| 585 | ExitWithLastError(hr, "Failed to set file pointer to beginning of file."); | ||
| 586 | } | ||
| 587 | 606 | ||
| 588 | break; | 607 | break; |
| 589 | 608 | ||
| @@ -611,8 +630,6 @@ static INT_PTR CopyFileCallback( | |||
| 611 | } | 630 | } |
| 612 | 631 | ||
| 613 | LExit: | 632 | LExit: |
| 614 | ReleaseStr(pwzPath); | ||
| 615 | |||
| 616 | pContext->Cabinet.hrError = hr; | 633 | pContext->Cabinet.hrError = hr; |
| 617 | return SUCCEEDED(hr) ? ipResult : -1; | 634 | return SUCCEEDED(hr) ? ipResult : -1; |
| 618 | } | 635 | } |
| @@ -624,27 +641,24 @@ static INT_PTR CloseFileInfoCallback( | |||
| 624 | { | 641 | { |
| 625 | HRESULT hr = S_OK; | 642 | HRESULT hr = S_OK; |
| 626 | INT_PTR ipResult = 1; // result to return on success | 643 | INT_PTR ipResult = 1; // result to return on success |
| 627 | FILETIME ftLocal = { }; | ||
| 628 | FILETIME ft = { }; | ||
| 629 | 644 | ||
| 630 | // read operation | 645 | // read operation |
| 631 | switch (pContext->Cabinet.operation) | 646 | switch (pContext->Cabinet.operation) |
| 632 | { | 647 | { |
| 633 | case BURN_CAB_OPERATION_STREAM_TO_FILE: | 648 | case BURN_CAB_OPERATION_STREAM_TO_FILE: |
| 634 | // Make a best effort to set the time on the new file before | 649 | BestEffortSetFileTime(pFDINotify, pContext->Cabinet.hTargetFile); |
| 635 | // we close it. | ||
| 636 | if (::DosDateTimeToFileTime(pFDINotify->date, pFDINotify->time, &ftLocal)) | ||
| 637 | { | ||
| 638 | if (::LocalFileTimeToFileTime(&ftLocal, &ft)) | ||
| 639 | { | ||
| 640 | ::SetFileTime(pContext->Cabinet.hTargetFile, &ft, &ft, &ft); | ||
| 641 | } | ||
| 642 | } | ||
| 643 | 650 | ||
| 644 | // close file | 651 | // close file |
| 645 | ReleaseFile(pContext->Cabinet.hTargetFile); | 652 | ReleaseFile(pContext->Cabinet.hTargetFile); |
| 646 | break; | 653 | break; |
| 647 | 654 | ||
| 655 | case BURN_CAB_OPERATION_STREAM_TO_HANDLE: | ||
| 656 | BestEffortSetFileTime(pFDINotify, pContext->Cabinet.hTargetFile); | ||
| 657 | |||
| 658 | // Do NOT close file. | ||
| 659 | pContext->Cabinet.hTargetFile = INVALID_HANDLE_VALUE; | ||
| 660 | break; | ||
| 661 | |||
| 648 | case BURN_CAB_OPERATION_STREAM_TO_BUFFER: | 662 | case BURN_CAB_OPERATION_STREAM_TO_BUFFER: |
| 649 | break; | 663 | break; |
| 650 | 664 | ||
| @@ -676,6 +690,55 @@ LExit: | |||
| 676 | return SUCCEEDED(hr) ? ipResult : -1; | 690 | return SUCCEEDED(hr) ? ipResult : -1; |
| 677 | } | 691 | } |
| 678 | 692 | ||
| 693 | static HRESULT PrepareTargetFile( | ||
| 694 | __in long cb, | ||
| 695 | __in HANDLE hFile | ||
| 696 | ) | ||
| 697 | { | ||
| 698 | HRESULT hr = S_OK; | ||
| 699 | LARGE_INTEGER li = { }; | ||
| 700 | |||
| 701 | // set file size | ||
| 702 | li.QuadPart = cb; | ||
| 703 | if (!::SetFilePointerEx(hFile, li, NULL, FILE_BEGIN)) | ||
| 704 | { | ||
| 705 | ExitWithLastError(hr, "Failed to set file pointer to end of file."); | ||
| 706 | } | ||
| 707 | |||
| 708 | if (!::SetEndOfFile(hFile)) | ||
| 709 | { | ||
| 710 | ExitWithLastError(hr, "Failed to set end of file."); | ||
| 711 | } | ||
| 712 | |||
| 713 | li.QuadPart = 0; | ||
| 714 | if (!::SetFilePointerEx(hFile, li, NULL, FILE_BEGIN)) | ||
| 715 | { | ||
| 716 | ExitWithLastError(hr, "Failed to set file pointer to beginning of file."); | ||
| 717 | } | ||
| 718 | |||
| 719 | LExit: | ||
| 720 | return hr; | ||
| 721 | } | ||
| 722 | |||
| 723 | static void BestEffortSetFileTime( | ||
| 724 | __in FDINOTIFICATION* pFDINotify, | ||
| 725 | __in HANDLE hFile | ||
| 726 | ) | ||
| 727 | { | ||
| 728 | FILETIME ftLocal = { }; | ||
| 729 | FILETIME ft = { }; | ||
| 730 | |||
| 731 | // Make a best effort to set the time on the new file before | ||
| 732 | // we close it. | ||
| 733 | if (::DosDateTimeToFileTime(pFDINotify->date, pFDINotify->time, &ftLocal)) | ||
| 734 | { | ||
| 735 | if (::LocalFileTimeToFileTime(&ftLocal, &ft)) | ||
| 736 | { | ||
| 737 | ::SetFileTime(hFile, &ft, &ft, &ft); | ||
| 738 | } | ||
| 739 | } | ||
| 740 | } | ||
| 741 | |||
| 679 | static LPVOID DIAMONDAPI CabAlloc( | 742 | static LPVOID DIAMONDAPI CabAlloc( |
| 680 | __in DWORD dwSize | 743 | __in DWORD dwSize |
| 681 | ) | 744 | ) |
| @@ -759,7 +822,8 @@ static UINT FAR DIAMONDAPI CabWrite( | |||
| 759 | 822 | ||
| 760 | switch (pContext->Cabinet.operation) | 823 | switch (pContext->Cabinet.operation) |
| 761 | { | 824 | { |
| 762 | case BURN_CAB_OPERATION_STREAM_TO_FILE: | 825 | case BURN_CAB_OPERATION_STREAM_TO_FILE: __fallthrough; |
| 826 | case BURN_CAB_OPERATION_STREAM_TO_HANDLE: | ||
| 763 | // write file | 827 | // write file |
| 764 | if (!::WriteFile(pContext->Cabinet.hTargetFile, pv, cb, &cbWrite, NULL)) | 828 | if (!::WriteFile(pContext->Cabinet.hTargetFile, pv, cb, &cbWrite, NULL)) |
| 765 | { | 829 | { |
diff --git a/src/burn/engine/cabextract.h b/src/burn/engine/cabextract.h index 31667f2b..13f9ab5d 100644 --- a/src/burn/engine/cabextract.h +++ b/src/burn/engine/cabextract.h | |||
| @@ -27,6 +27,10 @@ HRESULT CabExtractStreamToBuffer( | |||
| 27 | __out BYTE** ppbBuffer, | 27 | __out BYTE** ppbBuffer, |
| 28 | __out SIZE_T* pcbBuffer | 28 | __out SIZE_T* pcbBuffer |
| 29 | ); | 29 | ); |
| 30 | HRESULT CabExtractStreamToHandle( | ||
| 31 | __in BURN_CONTAINER_CONTEXT* pContext, | ||
| 32 | __in HANDLE hFile | ||
| 33 | ); | ||
| 30 | HRESULT CabExtractSkipStream( | 34 | HRESULT CabExtractSkipStream( |
| 31 | __in BURN_CONTAINER_CONTEXT* pContext | 35 | __in BURN_CONTAINER_CONTEXT* pContext |
| 32 | ); | 36 | ); |
