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 'src')
-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 | ); |