From 0d3d54992104288e9ee0c834d0b96e8502fd2d42 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Thu, 11 Jan 2024 18:26:20 -0800 Subject: Move the BootstrapperApplication out of proc --- src/libs/dutil/WixToolset.DUtil/buffutil.cpp | 271 +++++++++++++--- src/libs/dutil/WixToolset.DUtil/dutil.cpp | 39 ++- src/libs/dutil/WixToolset.DUtil/inc/buffutil.h | 115 ++++++- src/libs/dutil/WixToolset.DUtil/inc/dlutil.h | 1 + src/libs/dutil/WixToolset.DUtil/inc/dutil.h | 7 + src/libs/dutil/WixToolset.DUtil/inc/pipeutil.h | 115 ++++++- src/libs/dutil/WixToolset.DUtil/monutil.cpp | 12 +- src/libs/dutil/WixToolset.DUtil/pipeutil.cpp | 351 ++++++++++++++++++--- src/libs/dutil/WixToolset.DUtil/strutil.cpp | 32 +- src/libs/dutil/WixToolset.DUtil/thmutil.cpp | 4 +- src/libs/dutil/test/DUtilUnitTest/PipeUtilTest.cpp | 21 +- 11 files changed, 831 insertions(+), 137 deletions(-) (limited to 'src/libs') diff --git a/src/libs/dutil/WixToolset.DUtil/buffutil.cpp b/src/libs/dutil/WixToolset.DUtil/buffutil.cpp index acde4dc9..270bfc85 100644 --- a/src/libs/dutil/WixToolset.DUtil/buffutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/buffutil.cpp @@ -33,6 +33,8 @@ static HRESULT EnsureBufferSize( // functions +// Buffer read functions + extern "C" HRESULT BuffReadNumber( __in_bcount(cbBuffer) const BYTE* pbBuffer, __in SIZE_T cbBuffer, @@ -55,7 +57,7 @@ extern "C" HRESULT BuffReadNumber( if (sizeof(DWORD) > cbAvailable) { hr = E_INVALIDARG; - BuffExitOnRootFailure(hr, "Buffer too small."); + BuffExitOnRootFailure(hr, "Buffer too small to read number. cbAvailable: %u", cbAvailable); } *pdw = *(const DWORD*)(pbBuffer + *piBuffer); @@ -87,7 +89,7 @@ extern "C" HRESULT BuffReadNumber64( if (sizeof(DWORD64) > cbAvailable) { hr = E_INVALIDARG; - BuffExitOnRootFailure(hr, "Buffer too small."); + BuffExitOnRootFailure(hr, "Buffer too small to read 64-bit number. cbAvailable: %u", cbAvailable); } *pdw64 = *(const DWORD64*)(pbBuffer + *piBuffer); @@ -119,7 +121,7 @@ extern "C" HRESULT BuffReadPointer( if (sizeof(DWORD_PTR) > cbAvailable) { hr = E_INVALIDARG; - BuffExitOnRootFailure(hr, "Buffer too small."); + BuffExitOnRootFailure(hr, "Buffer too small to read pointer. cbAvailable: %u", cbAvailable); } *pdw64 = *(const DWORD_PTR*)(pbBuffer + *piBuffer); @@ -141,7 +143,7 @@ extern "C" HRESULT BuffReadString( Assert(pscz); HRESULT hr = S_OK; - SIZE_T cch = 0; + DWORD cch = 0; SIZE_T cb = 0; SIZE_T cbAvailable = 0; @@ -150,19 +152,19 @@ extern "C" HRESULT BuffReadString( BuffExitOnRootFailure(hr, "Failed to calculate available data size for character count."); // verify buffer size - if (sizeof(SIZE_T) > cbAvailable) + if (sizeof(DWORD) > cbAvailable) { hr = E_INVALIDARG; - BuffExitOnRootFailure(hr, "Buffer too small."); + BuffExitOnRootFailure(hr, "Buffer too small to read size of string. cbAvailable: %u", cbAvailable); } // read character count - cch = *(const SIZE_T*)(pbBuffer + *piBuffer); + cch = *(const DWORD*)(pbBuffer + *piBuffer); hr = ::SIZETMult(cch, sizeof(WCHAR), &cb); BuffExitOnRootFailure(hr, "Overflow while multiplying to calculate buffer size"); - hr = ::SIZETAdd(*piBuffer, sizeof(SIZE_T), piBuffer); + hr = ::SIZETAdd(*piBuffer, sizeof(cch), piBuffer); BuffExitOnRootFailure(hr, "Overflow while adding to calculate buffer size"); // get availiable data size @@ -173,7 +175,7 @@ extern "C" HRESULT BuffReadString( if (cb > cbAvailable) { hr = E_INVALIDARG; - BuffExitOnRootFailure(hr, "Buffer too small to hold character data."); + BuffExitOnRootFailure(hr, "Buffer too small to read string data. cbAvailable: %u, cb: %u", cbAvailable, cb); } // copy character data @@ -198,7 +200,7 @@ extern "C" HRESULT BuffReadStringAnsi( Assert(pscz); HRESULT hr = S_OK; - SIZE_T cch = 0; + DWORD cch = 0; SIZE_T cb = 0; SIZE_T cbAvailable = 0; @@ -207,19 +209,19 @@ extern "C" HRESULT BuffReadStringAnsi( BuffExitOnRootFailure(hr, "Failed to calculate available data size for character count."); // verify buffer size - if (sizeof(SIZE_T) > cbAvailable) + if (sizeof(DWORD) > cbAvailable) { hr = E_INVALIDARG; - BuffExitOnRootFailure(hr, "Buffer too small."); + BuffExitOnRootFailure(hr, "Buffer too small to read size of ANSI string. cbAvailable: %u", cbAvailable); } // read character count - cch = *(const SIZE_T*)(pbBuffer + *piBuffer); + cch = *(const DWORD*)(pbBuffer + *piBuffer); hr = ::SIZETMult(cch, sizeof(CHAR), &cb); BuffExitOnRootFailure(hr, "Overflow while multiplying to calculate buffer size"); - hr = ::SIZETAdd(*piBuffer, sizeof(SIZE_T), piBuffer); + hr = ::SIZETAdd(*piBuffer, sizeof(cch), piBuffer); BuffExitOnRootFailure(hr, "Overflow while adding to calculate buffer size"); // get availiable data size @@ -230,7 +232,7 @@ extern "C" HRESULT BuffReadStringAnsi( if (cb > cbAvailable) { hr = E_INVALIDARG; - BuffExitOnRootFailure(hr, "Buffer too small to hold character count."); + BuffExitOnRootFailure(hr, "Buffer too small to read ANSI string data. cbAvailable: %u, cb: %u", cbAvailable, cb); } // copy character data @@ -266,15 +268,15 @@ extern "C" HRESULT BuffReadStream( BuffExitOnRootFailure(hr, "Failed to calculate available data size for stream size."); // verify buffer size - if (sizeof(SIZE_T) > cbAvailable) + if (sizeof(DWORD) > cbAvailable) { hr = E_INVALIDARG; - BuffExitOnRootFailure(hr, "Buffer too small."); + BuffExitOnRootFailure(hr, "Buffer too small to read size of stream. cbAvailable: %u, cb: %u", cbAvailable, cb); } // read stream size - cb = *(const SIZE_T*)(pbBuffer + *piBuffer); - *piBuffer += sizeof(SIZE_T); + cb = *(const DWORD*)(pbBuffer + *piBuffer); + *piBuffer += sizeof(DWORD); // get availiable data size hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable); @@ -284,7 +286,7 @@ extern "C" HRESULT BuffReadStream( if (cb > cbAvailable) { hr = E_INVALIDARG; - BuffExitOnRootFailure(hr, "Buffer too small to hold byte count."); + BuffExitOnRootFailure(hr, "Buffer too small to read stream data. cbAvailable: %u, cb: %u", cbAvailable, cb); } // allocate buffer @@ -307,6 +309,52 @@ LExit: return hr; } + +// Buffer Reader read functions + +extern "C" HRESULT BuffReaderReadNumber( + __in BUFF_READER* pReader, + __out DWORD* pdw + ) +{ + return BuffReadNumber(pReader->pbData, pReader->cbData, &pReader->iBuffer, pdw); +} + +extern "C" HRESULT BuffReaderReadNumber64( + __in BUFF_READER* pReader, + __out DWORD64* pdw64 + ) +{ + return BuffReadNumber64(pReader->pbData, pReader->cbData, &pReader->iBuffer, pdw64); +} + +extern "C" HRESULT BuffReaderReadPointer( + __in BUFF_READER* pReader, + __out DWORD_PTR* pdw + ) +{ + return BuffReadPointer(pReader->pbData, pReader->cbData, &pReader->iBuffer, pdw); +} + +extern "C" HRESULT BuffReaderReadString( + __in BUFF_READER* pReader, + __deref_out_z LPWSTR* pscz + ) +{ + return BuffReadString(pReader->pbData, pReader->cbData, &pReader->iBuffer, pscz); +} + +extern "C" HRESULT BuffReaderReadStringAnsi( + __in BUFF_READER* pReader, + __deref_out_z LPSTR* pscz + ) +{ + return BuffReadStringAnsi(pReader->pbData, pReader->cbData, &pReader->iBuffer, pscz); +} + + +// Buffer write functions + extern "C" HRESULT BuffWriteNumber( __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer, __inout SIZE_T* piBuffer, @@ -323,7 +371,7 @@ extern "C" HRESULT BuffWriteNumber( BuffExitOnFailure(hr, "Failed to ensure buffer size."); // copy data to buffer - *(DWORD*)(*ppbBuffer + *piBuffer) = dw; + *reinterpret_cast(*ppbBuffer + *piBuffer) = dw; *piBuffer += sizeof(DWORD); LExit: @@ -386,25 +434,35 @@ extern "C" HRESULT BuffWriteString( Assert(piBuffer); HRESULT hr = S_OK; - SIZE_T cch = 0; + DWORD cch = 0; // This value *MUST* be treated as a DWORD to be marshalled over the pipe between 32-bit and 64-bit process the same. SIZE_T cb = 0; errno_t err = 0; if (scz) { - hr = ::StringCchLengthW(scz, STRSAFE_MAX_CCH, reinterpret_cast(&cch)); - BuffExitOnRootFailure(hr, "Failed to get string size.") + size_t size = 0; + + hr = ::StringCchLengthW(scz, STRSAFE_MAX_CCH, &size); + BuffExitOnRootFailure(hr, "Failed to get string size."); + + if (size > DWORD_MAX) + { + hr = E_INVALIDARG; + BuffExitOnRootFailure(hr, "String too long to write to buffer."); + } + + cch = static_cast(size); } cb = cch * sizeof(WCHAR); - // make sure we have a buffer with sufficient space - hr = EnsureBufferSize(ppbBuffer, *piBuffer + (sizeof(SIZE_T) + cb)); + // make sure we have a buffer with sufficient space for the length plus the string without terminator. + hr = EnsureBufferSize(ppbBuffer, *piBuffer + sizeof(DWORD) + cb); BuffExitOnFailure(hr, "Failed to ensure buffer size."); - // copy character count to buffer - *(SIZE_T*)(*ppbBuffer + *piBuffer) = cch; - *piBuffer += sizeof(SIZE_T); + // copy the character count to buffer as a DWORD + *reinterpret_cast(*ppbBuffer + *piBuffer) = cch; + *piBuffer += sizeof(DWORD); // copy data to buffer err = memcpy_s(*ppbBuffer + *piBuffer, cb, scz, cb); @@ -429,25 +487,35 @@ extern "C" HRESULT BuffWriteStringAnsi( Assert(piBuffer); HRESULT hr = S_OK; - SIZE_T cch = 0; + DWORD cch = 0; // This value *MUST* be treated as a DWORD to be marshalled over the pipe between 32-bit and 64-bit process the same. SIZE_T cb = 0; errno_t err = 0; if (scz) { - hr = ::StringCchLengthA(scz, STRSAFE_MAX_CCH, reinterpret_cast(&cch)); - BuffExitOnRootFailure(hr, "Failed to get string size.") + size_t size = 0; + + hr = ::StringCchLengthA(scz, STRSAFE_MAX_CCH, &size); + BuffExitOnRootFailure(hr, "Failed to get ANSI string size.") + + if (size > DWORD_MAX) + { + hr = E_INVALIDARG; + BuffExitOnRootFailure(hr, "ANSI string too long to write to buffer."); + } + + cch = static_cast(size); } cb = cch * sizeof(CHAR); // make sure we have a buffer with sufficient space - hr = EnsureBufferSize(ppbBuffer, *piBuffer + (sizeof(SIZE_T) + cb)); + hr = EnsureBufferSize(ppbBuffer, *piBuffer + (sizeof(DWORD) + cb)); BuffExitOnFailure(hr, "Failed to ensure buffer size."); // copy character count to buffer - *(SIZE_T*)(*ppbBuffer + *piBuffer) = cch; - *piBuffer += sizeof(SIZE_T); + *reinterpret_cast(*ppbBuffer + *piBuffer) = cch; + *piBuffer += sizeof(DWORD); // copy data to buffer err = memcpy_s(*ppbBuffer + *piBuffer, cb, scz, cb); @@ -474,30 +542,143 @@ extern "C" HRESULT BuffWriteStream( Assert(pbStream); HRESULT hr = S_OK; - SIZE_T cb = cbStream; + DWORD cb = 0; errno_t err = 0; + if (cbStream > DWORD_MAX) + { + hr = E_INVALIDARG; + BuffExitOnRootFailure(hr, "Stream too large to write to buffer."); + } + + cb = static_cast(cbStream); + // make sure we have a buffer with sufficient space - hr = EnsureBufferSize(ppbBuffer, *piBuffer + cbStream + sizeof(SIZE_T)); + hr = EnsureBufferSize(ppbBuffer, *piBuffer + cbStream + sizeof(DWORD)); BuffExitOnFailure(hr, "Failed to ensure buffer size."); // copy byte count to buffer - *(SIZE_T*)(*ppbBuffer + *piBuffer) = cb; - *piBuffer += sizeof(SIZE_T); + *reinterpret_cast(*ppbBuffer + *piBuffer) = cb; + *piBuffer += sizeof(DWORD); - // copy data to buffer - err = memcpy_s(*ppbBuffer + *piBuffer, cbStream, pbStream, cbStream); - if (err) + if (cbStream) { - BuffExitOnRootFailure(hr = E_INVALIDARG, "Failed to write stream to buffer, error: %d", err); - } + // copy data to buffer + err = memcpy_s(*ppbBuffer + *piBuffer, cbStream, pbStream, cbStream); + if (err) + { + BuffExitOnRootFailure(hr = E_INVALIDARG, "Failed to write stream to buffer, error: %d", err); + } - *piBuffer += cbStream; + *piBuffer += cbStream; + } LExit: return hr; } +// Buffer-based write functions + +extern "C" HRESULT BuffWriteNumberToBuffer( + __in BUFF_BUFFER* pBuffer, + __out DWORD dw + ) +{ + return BuffWriteNumber(&pBuffer->pbData, &pBuffer->cbData, dw); +} + +extern "C" HRESULT BuffWriteNumber64ToBuffer( + __in BUFF_BUFFER* pBuffer, + __out DWORD64 dw64 + ) +{ + return BuffWriteNumber64(&pBuffer->pbData, &pBuffer->cbData, dw64); +} + +extern "C" HRESULT BuffWritePointerToBuffer( + __in BUFF_BUFFER* pBuffer, + __out DWORD_PTR dw + ) +{ + return BuffWritePointer(&pBuffer->pbData, &pBuffer->cbData, dw); +} + +extern "C" HRESULT BuffWriteStringToBuffer( + __in BUFF_BUFFER* pBuffer, + __in_z_opt LPCWSTR scz + ) +{ + return BuffWriteString(&pBuffer->pbData, &pBuffer->cbData, scz); +} + +extern "C" HRESULT BuffWriteStringAnsiToBuffer( + __in BUFF_BUFFER* pBuffer, + __in_z_opt LPCSTR scz + ) +{ + return BuffWriteStringAnsi(&pBuffer->pbData, &pBuffer->cbData, scz); +} + +extern "C" HRESULT BuffWriteStreamToBuffer( + __in BUFF_BUFFER* pBuffer, + __in_bcount(cbStream) const BYTE* pbStream, + __in SIZE_T cbStream + ) +{ + return BuffWriteStream(&pBuffer->pbData, &pBuffer->cbData, pbStream, cbStream); +} + +// Buffer Writer write functions + +extern "C" HRESULT BuffWriterWriteNumber( + __in BUFF_WRITER* pWriter, + __out DWORD dw + ) +{ + return BuffWriteNumber(pWriter->ppbData, pWriter->pcbData, dw); +} + +extern "C" HRESULT BuffWriterWriteNumber64( + __in BUFF_WRITER* pWriter, + __out DWORD64 dw64 + ) +{ + return BuffWriteNumber64(pWriter->ppbData, pWriter->pcbData, dw64); +} + +extern "C" HRESULT BuffWriterWritePointer( + __in BUFF_WRITER* pWriter, + __out DWORD_PTR dw + ) +{ + return BuffWritePointer(pWriter->ppbData, pWriter->pcbData, dw); +} + +extern "C" HRESULT BuffWriterWriteString( + __in BUFF_WRITER* pWriter, + __in_z_opt LPCWSTR scz + ) +{ + return BuffWriteString(pWriter->ppbData, pWriter->pcbData, scz); +} + +extern "C" HRESULT BuffWriterWriteStringAnsi( + __in BUFF_WRITER* pWriter, + __in_z_opt LPCSTR scz + ) +{ + return BuffWriteStringAnsi(pWriter->ppbData, pWriter->pcbData, scz); +} + +extern "C" HRESULT BuffWriterWriteStream( + __in BUFF_WRITER* pWriter, + __in_bcount(cbStream) const BYTE* pbStream, + __in SIZE_T cbStream + ) +{ + return BuffWriteStream(pWriter->ppbData, pWriter->pcbData, pbStream, cbStream); +} + // helper functions diff --git a/src/libs/dutil/WixToolset.DUtil/dutil.cpp b/src/libs/dutil/WixToolset.DUtil/dutil.cpp index 83b53f64..3f0d1658 100644 --- a/src/libs/dutil/WixToolset.DUtil/dutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/dutil.cpp @@ -50,6 +50,19 @@ DAPI_(void) DutilUninitialize() vpfnTraceErrorCallback = NULL; } + +DAPI_(HRESULT) DutilSizetToDword(SIZE_T sizet, DWORD* pdw) +{ + if (DWORD_MAX < sizet) + { + return E_INVALIDARG; + } + + *pdw = static_cast(sizet); + return S_OK; +} + + DAPI_(BOOL) DutilSuppressTraceErrorSource() { if (DWORD_MAX == vtdwSuppressTraceErrorSource) @@ -169,7 +182,7 @@ extern "C" void DAPI Dutil_AssertMsg( DExitOnFailure(hr, "failed to concat string while building assert message"); id = ::MessageBoxA(0, szMsg, "Debug Assert Message", - MB_SERVICE_NOTIFICATION | MB_TOPMOST | + MB_SERVICE_NOTIFICATION | MB_TOPMOST | MB_DEFBUTTON2 | MB_ABORTRETRYIGNORE); } } @@ -206,7 +219,7 @@ Dutil_Assert *******************************************************************/ extern "C" void DAPI Dutil_Assert( - __in_z LPCSTR szFile, + __in_z LPCSTR szFile, __in int iLine ) { @@ -229,8 +242,8 @@ Dutil_AssertSz *******************************************************************/ extern "C" void DAPI Dutil_AssertSz( - __in_z LPCSTR szFile, - __in int iLine, + __in_z LPCSTR szFile, + __in int iLine, __in_z __format_string LPCSTR szMsg ) { @@ -278,10 +291,10 @@ Dutil_Trace *******************************************************************/ extern "C" void DAPIV Dutil_Trace( - __in_z LPCSTR szFile, - __in int iLine, - __in REPORT_LEVEL rl, - __in_z __format_string LPCSTR szFormat, + __in_z LPCSTR szFile, + __in int iLine, + __in REPORT_LEVEL rl, + __in_z __format_string LPCSTR szFormat, ... ) { @@ -355,11 +368,11 @@ Dutil_TraceError *******************************************************************/ extern "C" void DAPIV Dutil_TraceError( - __in_z LPCSTR szFile, - __in int iLine, - __in REPORT_LEVEL rl, - __in HRESULT hrError, - __in_z __format_string LPCSTR szFormat, + __in_z LPCSTR szFile, + __in int iLine, + __in REPORT_LEVEL rl, + __in HRESULT hrError, + __in_z __format_string LPCSTR szFormat, ... ) { diff --git a/src/libs/dutil/WixToolset.DUtil/inc/buffutil.h b/src/libs/dutil/WixToolset.DUtil/inc/buffutil.h index 322209e6..116b67bd 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/buffutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/buffutil.h @@ -9,9 +9,35 @@ extern "C" { // macro definitions -#define ReleaseBuffer ReleaseMem -#define ReleaseNullBuffer ReleaseNullMem -#define BuffFree MemFree +#define ReleaseBuffer(b) BuffFree(b) +#define ReleaseNullBuffer(b) BuffFree(b) +#define BuffFree(b) if (b.pbData) { MemFree(b.pbData); b.pbData = NULL; } b.cbData = 0 + + +// structs + +// A buffer that owns its data and must be freed with BuffFree(). +typedef struct _BUFF_BUFFER +{ + LPBYTE pbData; + SIZE_T cbData; +} BUFF_BUFFER; + +// A read-only buffer with internal pointer that can be advanced for multiple reads. +typedef struct _BUFF_READER +{ + LPCBYTE pbData; + SIZE_T cbData; + + SIZE_T iBuffer; +} BUFF_READER; + +// A write buffer that does not own its data. +typedef struct _BUFF_WRITER +{ + LPBYTE *ppbData; + SIZE_T *pcbData; +} BUFF_WRITER; // function declarations @@ -53,6 +79,37 @@ HRESULT BuffReadStream( __deref_inout_bcount(*pcbStream) BYTE** ppbStream, __out SIZE_T* pcbStream ); +HRESULT BuffSkipExtraData( + __in SIZE_T cbExpectedSize, + __in SIZE_T cbActualSize, + __inout SIZE_T* piBuffer + ); + +HRESULT BuffReaderReadNumber( + __in BUFF_READER* pReader, + __out DWORD* pdw + ); +HRESULT BuffReaderReadNumber64( + __in BUFF_READER* pReader, + __out DWORD64* pdw64 + ); +HRESULT BuffReaderReadPointer( + __in BUFF_READER* pReader, + __out DWORD_PTR* pdw +); +HRESULT BuffReaderReadString( + __in BUFF_READER* pReader, + __deref_out_z LPWSTR* pscz + ); +HRESULT BuffReaderReadStringAnsi( + __in BUFF_READER* pReader, + __deref_out_z LPSTR* pscz + ); +HRESULT BuffReaderReadStream( + __in BUFF_READER* pReader, + __deref_inout_bcount(*pcbStream) BYTE** ppbStream, + __out SIZE_T* pcbStream + ); HRESULT BuffWriteNumber( __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer, @@ -86,6 +143,58 @@ HRESULT BuffWriteStream( __in SIZE_T cbStream ); +HRESULT BuffWriteNumberToBuffer( + __in BUFF_BUFFER* pBuffer, + __in DWORD dw + ); +HRESULT BuffWriteNumber64ToBuffer( + __in BUFF_BUFFER* pBuffer, + __in DWORD64 dw64 + ); +HRESULT BuffWritePointerToBuffer( + __in BUFF_BUFFER* pBuffer, + __in DWORD_PTR dw + ); +HRESULT BuffWriteStringToBuffer( + __in BUFF_BUFFER* pBuffer, + __in_z_opt LPCWSTR scz + ); +HRESULT BuffWriteStringAnsiToBuffer( + __in BUFF_BUFFER* pBuffer, + __in_z_opt LPCSTR scz + ); +HRESULT BuffWriteStreamToBuffer( + __in BUFF_BUFFER* pBuffer, + __in_bcount(cbStream) const BYTE* pbStream, + __in SIZE_T cbStream + ); + +HRESULT BuffWriterWriteNumber( + __in BUFF_WRITER* pWriter, + __in DWORD dw + ); +HRESULT BuffWriterWriteNumber64( + __in BUFF_WRITER* pWriter, + __in DWORD64 dw64 + ); +HRESULT BuffWriterWritePointer( + __in BUFF_WRITER* pWriter, + __in DWORD_PTR dw + ); +HRESULT BuffWriterWriteString( + __in BUFF_WRITER* pWriter, + __in_z_opt LPCWSTR scz + ); +HRESULT BuffWriterWriteStringAnsi( + __in BUFF_WRITER* pWriter, + __in_z_opt LPCSTR scz + ); +HRESULT BuffWriterWriteStream( + __in BUFF_WRITER* pWriter, + __in_bcount(cbStream) const BYTE* pbStream, + __in SIZE_T cbStream + ); + #ifdef __cplusplus } #endif diff --git a/src/libs/dutil/WixToolset.DUtil/inc/dlutil.h b/src/libs/dutil/WixToolset.DUtil/inc/dlutil.h index 3e95103a..912c2732 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/dlutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/dlutil.h @@ -27,6 +27,7 @@ typedef struct _DOWNLOAD_SOURCE LPWSTR sczUrl; LPWSTR sczUser; LPWSTR sczPassword; + LPWSTR sczAuthorizationHeader; } DOWNLOAD_SOURCE; typedef struct _DOWNLOAD_CACHE_CALLBACK diff --git a/src/libs/dutil/WixToolset.DUtil/inc/dutil.h b/src/libs/dutil/WixToolset.DUtil/inc/dutil.h index 4a172f46..7d8c7d81 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/dutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/dutil.h @@ -41,6 +41,13 @@ HRESULT DAPI DutilInitialize( *******************************************************************/ void DAPI DutilUninitialize(); +/******************************************************************* + DutilSizetToDword - safely convert SIZE_T to DWORD. + + Returns + E_INVALIDARG - If SIZE_T value is greater than DWORD_MAX. +********************************************************************/ +HRESULT DAPI DutilSizetToDword(SIZE_T sizet, DWORD* pdw); /******************************************************************** DutilSuppressTraceErrorSource - tells dutil to skip calling diff --git a/src/libs/dutil/WixToolset.DUtil/inc/pipeutil.h b/src/libs/dutil/WixToolset.DUtil/inc/pipeutil.h index d16d768c..e92462d2 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/pipeutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/pipeutil.h @@ -6,7 +6,9 @@ extern "C" { #endif -#define ReleasePipeHandle(h) if (h != INVALID_HANDLE_VALUE) { ::CloseHandle(h); } +// macro definitions + +#define ReleasePipeHandle(h) if (h != INVALID_HANDLE_VALUE) { ::CloseHandle(h); h = INVALID_HANDLE_VALUE; } #define ReleasePipeMessage(pMsg) if (pMsg) { PipeFreeMessage(pMsg); } @@ -27,6 +29,23 @@ typedef struct _PIPE_MESSAGE LPVOID pvData; } PIPE_MESSAGE; +typedef struct _PIPE_RPC_HANDLE +{ + HANDLE hPipe; + CRITICAL_SECTION cs; + + BOOL fInitialized; + BOOL fOwnHandle; +} PIPE_RPC_HANDLE; + +typedef struct _PIPE_RPC_RESULT +{ + HRESULT hr; + + DWORD cbData; + LPBYTE pbData; +} PIPE_RPC_RESULT; + // functions @@ -72,16 +91,86 @@ DAPI_(HRESULT) PipeReadMessage( ); /******************************************************************* - PipeWriteMessage - writes a message to the pipe. + PipeRpcInitiailize - initializes a RPC pipe handle from a pipe handle. *******************************************************************/ -DAPI_(HRESULT) PipeWriteMessage( +DAPI_(void) PipeRpcInitialize( + __in PIPE_RPC_HANDLE* phRpcPipe, __in HANDLE hPipe, + __in BOOL fTakeHandleOwnership +); + +/******************************************************************* + PipeRpcInitialized - checks if a RPC pipe handle is initialized. + +*******************************************************************/ +DAPI_(BOOL) PipeRpcInitialized( + __in PIPE_RPC_HANDLE* phRpcPipe +); + +/******************************************************************* + PipeRpcUninitiailize - uninitializes a RPC pipe handle. + +*******************************************************************/ +DAPI_(void) PipeRpcUninitiailize( + __in PIPE_RPC_HANDLE* phRpcPipe +); + +/******************************************************************* + PipeRpcReadMessage - reads a message from the pipe. Free with + PipeFreeMessage(). + +*******************************************************************/ +DAPI_(HRESULT) PipeRpcReadMessage( + __in PIPE_RPC_HANDLE* phRpcPipe, + __in PIPE_MESSAGE* pMsg +); + +/******************************************************************* + PipeRpcRequest - sends message and reads a response over the pipe. + Free with PipeFreeRpcResult(). + +*******************************************************************/ +DAPI_(HRESULT) PipeRpcRequest( + __in PIPE_RPC_HANDLE* phRpcPipe, + __in DWORD dwMessageType, + __in_bcount(cbArgs) LPVOID pbArgs, + __in SIZE_T cbArgs, + __in PIPE_RPC_RESULT* pResult +); + +/******************************************************************* + PipeRpcResponse - sends response over the pipe. + +*******************************************************************/ +DAPI_(HRESULT) PipeRpcResponse( + __in PIPE_RPC_HANDLE* phPipe, + __in DWORD dwMessageType, + __in HRESULT hrResult, + __in_bcount(cbResult) LPVOID pvResult, + __in SIZE_T cbResult + ); + +/******************************************************************* + PipeRpcWriteMessage - writes a message to the pipe. + +*******************************************************************/ +DAPI_(HRESULT) PipeRpcWriteMessage( + __in PIPE_RPC_HANDLE* phPipe, __in DWORD dwMessageType, __in_bcount_opt(cbData) LPVOID pvData, __in SIZE_T cbData ); +/******************************************************************* + PipeWriteDisconnect - writes a message to the pipe indicating the + client should disconnect. + +*******************************************************************/ +DAPI_(HRESULT) PipeWriteDisconnect( + __in HANDLE hPipe + ); + /******************************************************************* PipeFreeMessage - frees any memory allocated in PipeReadMessage. @@ -90,15 +179,35 @@ DAPI_(void) PipeFreeMessage( __in PIPE_MESSAGE* pMsg ); +/******************************************************************* + PipeFreeRpcResult - frees any memory allocated in PipeRpcRequest. + +*******************************************************************/ +DAPI_(void) PipeFreeRpcResult( + __in PIPE_RPC_RESULT* pResult +); + /******************************************************************* PipeServerWaitForClientConnect - Called from the server process to wait for a client to connect back to the provided pipe. *******************************************************************/ DAPI_(HRESULT) PipeServerWaitForClientConnect( + __in HANDLE hClientProcess, __in HANDLE hPipe ); +/******************************************************************* + PipeWriteMessage - writes a message to the pipe. + +*******************************************************************/ +DAPI_(HRESULT) PipeWriteMessage( + __in HANDLE hPipe, + __in DWORD dwMessageType, + __in_bcount_opt(cbData) LPVOID pvData, + __in SIZE_T cbData +); + #ifdef __cplusplus } #endif diff --git a/src/libs/dutil/WixToolset.DUtil/monutil.cpp b/src/libs/dutil/WixToolset.DUtil/monutil.cpp index d7bcfa52..b42332ef 100644 --- a/src/libs/dutil/WixToolset.DUtil/monutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/monutil.cpp @@ -1209,7 +1209,7 @@ static DWORD WINAPI WaiterThread( ZeroMemory(rgfProcessedIndex, sizeof(rgfProcessedIndex)); for (DWORD i = 0; i < pWaiterContext->cRequests; ++i) - { + { if (rgfProcessedIndex[i]) { // if we already processed this item due to UpdateWaitStatus swapping array indices, then skip it @@ -1244,7 +1244,7 @@ static DWORD WINAPI WaiterThread( ZeroMemory(rgfProcessedIndex, sizeof(rgfProcessedIndex)); for (DWORD i = 0; i < pWaiterContext->cRequests; ++i) - { + { if (rgfProcessedIndex[i]) { // if we already processed this item due to UpdateWaitStatus swapping array indices, then skip it @@ -1279,7 +1279,7 @@ static DWORD WINAPI WaiterThread( ZeroMemory(rgfProcessedIndex, sizeof(rgfProcessedIndex)); for (DWORD i = 0; i < pWaiterContext->cRequests; ++i) - { + { if (rgfProcessedIndex[i]) { // if we already processed this item due to UpdateWaitStatus swapping array indices, then skip it @@ -1308,7 +1308,7 @@ static DWORD WINAPI WaiterThread( case MON_MESSAGE_DRIVE_STATUS_UPDATE: ZeroMemory(rgfProcessedIndex, sizeof(rgfProcessedIndex)); for (DWORD i = 0; i < pWaiterContext->cRequests; ++i) - { + { if (rgfProcessedIndex[i]) { // if we already processed this item due to UpdateWaitStatus swapping array indices, then skip it @@ -1349,7 +1349,7 @@ static DWORD WINAPI WaiterThread( if (pInternalWait->dwSendIteration == static_cast(msg.lParam)) { for (DWORD i = 0; i < pWaiterContext->cRequests; ++i) - { + { if (MON_DIRECTORY == pWaiterContext->rgRequests[i].type && pWaiterContext->rgHandles[i + 1] == reinterpret_cast(pInternalWait->pvContext)) { // Release handles ASAP so the remove request will succeed @@ -1878,7 +1878,7 @@ static HRESULT CreateMonWindow( } *pHwnd = ::CreateWindowExW(0, wc.lpszClassName, L"", 0, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, HWND_DESKTOP, NULL, wc.hInstance, pm); - MonExitOnNullWithLastError(*pHwnd, hr, "Failed to create window."); + MonExitOnNullWithLastError(*pHwnd, hr, "Failed to create monitor window."); // Rumor has it that drive arrival / removal events can be lost in the rare event that some other application higher up in z-order is hanging if we don't make our window topmost // SWP_NOACTIVATE is important so the currently active window doesn't lose focus diff --git a/src/libs/dutil/WixToolset.DUtil/pipeutil.cpp b/src/libs/dutil/WixToolset.DUtil/pipeutil.cpp index 4aa69d56..8d0a5ed0 100644 --- a/src/libs/dutil/WixToolset.DUtil/pipeutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/pipeutil.cpp @@ -5,7 +5,7 @@ static const DWORD PIPE_64KB = 64 * 1024; static const LPCWSTR PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls"; - +static const DWORD PIPE_MESSAGE_DISCONNECT = 0xFFFFFFFF; // Exit macros #define PipeExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_PIPEUTIL, x, s, __VA_ARGS__) @@ -113,8 +113,19 @@ DAPI_(void) PipeFreeMessage( ReleaseNullMem(pMsg->pvData); pMsg->fAllocatedData = FALSE; } + + ZeroMemory(pMsg, sizeof(PIPE_MESSAGE)); } +DAPI_(void) PipeFreeRpcResult( + __in PIPE_RPC_RESULT* pResult +) +{ + if (pResult->pbData) + { + ReleaseNullMem(pResult->pbData); + } +} DAPI_(HRESULT) PipeOpen( __in_z LPCWSTR wzName, @@ -166,39 +177,281 @@ DAPI_(HRESULT) PipeReadMessage( ) { HRESULT hr = S_OK; - BYTE pbMessageIdAndByteCount[sizeof(DWORD) + sizeof(DWORD)] = { }; + DWORD rgdwMessageIdAndByteCount[2] = { }; + LPBYTE pbData = NULL; + DWORD cbData = 0; - hr = FileReadHandle(hPipe, pbMessageIdAndByteCount, sizeof(pbMessageIdAndByteCount)); + hr = FileReadHandle(hPipe, reinterpret_cast(rgdwMessageIdAndByteCount), sizeof(rgdwMessageIdAndByteCount)); if (HRESULT_FROM_WIN32(ERROR_BROKEN_PIPE) == hr) { - memset(pbMessageIdAndByteCount, 0, sizeof(pbMessageIdAndByteCount)); + memset(rgdwMessageIdAndByteCount, 0, sizeof(rgdwMessageIdAndByteCount)); hr = S_FALSE; } PipeExitOnFailure(hr, "Failed to read message from pipe."); - pMsg->dwMessageType = *(DWORD*)(pbMessageIdAndByteCount); - pMsg->cbData = *(DWORD*)(pbMessageIdAndByteCount + sizeof(DWORD)); - if (pMsg->cbData) + Trace(REPORT_STANDARD, "RPC pipe %p read message: %u recv cbData: %u", hPipe, rgdwMessageIdAndByteCount[0], rgdwMessageIdAndByteCount[1]); + + cbData = rgdwMessageIdAndByteCount[1]; + if (cbData) { - pMsg->pvData = MemAlloc(pMsg->cbData, FALSE); - PipeExitOnNull(pMsg->pvData, hr, E_OUTOFMEMORY, "Failed to allocate data for message."); + pbData = reinterpret_cast(MemAlloc(cbData, FALSE)); + PipeExitOnNull(pbData, hr, E_OUTOFMEMORY, "Failed to allocate data for message."); - hr = FileReadHandle(hPipe, reinterpret_cast(pMsg->pvData), pMsg->cbData); + hr = FileReadHandle(hPipe, pbData, cbData); PipeExitOnFailure(hr, "Failed to read data for message."); + } + + pMsg->dwMessageType = rgdwMessageIdAndByteCount[0]; + pMsg->cbData = cbData; + pMsg->pvData = pbData; + pbData = NULL; + + if (PIPE_MESSAGE_DISCONNECT == pMsg->dwMessageType) + { + hr = S_FALSE; + } + +LExit: + ReleaseMem(pbData); + + return hr; +} + +DAPI_(void) PipeRpcInitialize( + __in PIPE_RPC_HANDLE* phRpcPipe, + __in HANDLE hPipe, + __in BOOL fTakeHandleOwnership +) +{ + phRpcPipe->hPipe = hPipe; + if (phRpcPipe->hPipe != INVALID_HANDLE_VALUE) + { + ::InitializeCriticalSection(&phRpcPipe->cs); + phRpcPipe->fOwnHandle = fTakeHandleOwnership; + phRpcPipe->fInitialized = TRUE; + } +} + +DAPI_(BOOL) PipeRpcInitialized( + __in PIPE_RPC_HANDLE* phRpcPipe +) +{ + return phRpcPipe->fInitialized && phRpcPipe->hPipe != INVALID_HANDLE_VALUE; +} + +DAPI_(void) PipeRpcUninitiailize( + __in PIPE_RPC_HANDLE* phRpcPipe +) +{ + if (phRpcPipe->fInitialized) + { + ::DeleteCriticalSection(&phRpcPipe->cs); + + if (phRpcPipe->fOwnHandle) + { + ::CloseHandle(phRpcPipe->hPipe); + } + + phRpcPipe->hPipe = INVALID_HANDLE_VALUE; + phRpcPipe->fOwnHandle = FALSE; + phRpcPipe->fInitialized = FALSE; + } +} + +DAPI_(HRESULT) PipeRpcReadMessage( + __in PIPE_RPC_HANDLE* phRpcPipe, + __in PIPE_MESSAGE* pMsg +) +{ + HRESULT hr = S_OK; + + ::EnterCriticalSection(&phRpcPipe->cs); + + hr = PipeReadMessage(phRpcPipe->hPipe, pMsg); + PipeExitOnFailure(hr, "Failed to read message from RPC pipe."); + +LExit: + ::LeaveCriticalSection(&phRpcPipe->cs); + + return hr; +} + +DAPI_(HRESULT) PipeRpcRequest( + __in PIPE_RPC_HANDLE* phRpcPipe, + __in DWORD dwMessageType, + __in_bcount(cbArgs) LPVOID pvArgs, + __in SIZE_T cbArgs, + __in PIPE_RPC_RESULT* pResult +) +{ + HRESULT hr = S_OK; + HANDLE hPipe = phRpcPipe->hPipe; + BOOL fLocked = FALSE; + DWORD rgResultAndDataSize[2] = { }; + DWORD cbData = 0; + LPBYTE pbData = NULL; + + if (hPipe == INVALID_HANDLE_VALUE) + { + ExitFunction(); + } + + Trace(REPORT_STANDARD, "RPC pipe %p request message: %d send cbArgs: %u", hPipe, dwMessageType, cbArgs); + + ::EnterCriticalSection(&phRpcPipe->cs); + fLocked = TRUE; + + // Send the message. + hr = PipeRpcWriteMessage(phRpcPipe, dwMessageType, pvArgs, cbArgs); + PipeExitOnFailure(hr, "Failed to send RPC pipe request."); + + // Read the result and size of response data. + hr = FileReadHandle(hPipe, reinterpret_cast(rgResultAndDataSize), sizeof(rgResultAndDataSize)); + PipeExitOnFailure(hr, "Failed to read result and size of message."); + + pResult->hr = rgResultAndDataSize[0]; + cbData = rgResultAndDataSize[1]; + + Trace(REPORT_STANDARD, "RPC pipe %p request message: %d returned hr: 0x%x, cbData: %u", hPipe, dwMessageType, pResult->hr, cbData); + AssertSz(FAILED(pResult->hr) || pResult->hr == S_OK || pResult->hr == S_FALSE, "Unexpected HRESULT from RPC pipe request."); + + if (cbData) + { + pbData = reinterpret_cast(MemAlloc(cbData, TRUE)); + PipeExitOnNull(pbData, hr, E_OUTOFMEMORY, "Failed to allocate memory for RPC pipe results."); + + hr = FileReadHandle(hPipe, pbData, cbData); + PipeExitOnFailure(hr, "Failed to read result data."); + } + + pResult->cbData = cbData; + pResult->pbData = pbData; + pbData = NULL; + + hr = pResult->hr; + PipeExitOnFailure(hr, "RPC pipe client reported failure."); + +LExit: + ReleaseMem(pbData); + + if (fLocked) + { + ::LeaveCriticalSection(&phRpcPipe->cs); + } + + return hr; +} + +DAPI_(HRESULT) PipeRpcResponse( + __in PIPE_RPC_HANDLE* phRpcPipe, + __in DWORD +#if DEBUG + dwMessageType +#endif + , + __in HRESULT hrResult, + __in_bcount(cbResult) LPVOID pvResult, + __in SIZE_T cbResult + ) +{ + HRESULT hr = S_OK; + HANDLE hPipe = phRpcPipe->hPipe; + DWORD dwcbResult = 0; + + hr = DutilSizetToDword(pvResult ? cbResult : 0, &dwcbResult); + PipeExitOnFailure(hr, "Pipe message is too large."); + + Trace(REPORT_STANDARD, "RPC pipe %p response message: %d returned hr: 0x%x, cbResult: %u", hPipe, dwMessageType, hrResult, dwcbResult); - pMsg->fAllocatedData = TRUE; + ::EnterCriticalSection(&phRpcPipe->cs); + + hr = FileWriteHandle(hPipe, reinterpret_cast(&hrResult), sizeof(hrResult)); + PipeExitOnFailure(hr, "Failed to write RPC result code to pipe."); + + hr = FileWriteHandle(hPipe, reinterpret_cast(&dwcbResult), sizeof(dwcbResult)); + PipeExitOnFailure(hr, "Failed to write RPC result size to pipe."); + + if (dwcbResult) + { + hr = FileWriteHandle(hPipe, reinterpret_cast(pvResult), dwcbResult); + PipeExitOnFailure(hr, "Failed to write RPC result data to pipe."); } LExit: - if (!pMsg->fAllocatedData && pMsg->pvData) + ::LeaveCriticalSection(&phRpcPipe->cs); + + return hr; +} + +DAPI_(HRESULT) PipeRpcWriteMessage( + __in PIPE_RPC_HANDLE* phRpcPipe, + __in DWORD dwMessageType, + __in_bcount_opt(cbData) LPVOID pvData, + __in SIZE_T cbData +) +{ + HRESULT hr = S_OK; + + ::EnterCriticalSection(&phRpcPipe->cs); + + hr = PipeWriteMessage(phRpcPipe->hPipe, dwMessageType, pvData, cbData); + PipeExitOnFailure(hr, "Failed to write message type to RPC pipe."); + +LExit: + ::LeaveCriticalSection(&phRpcPipe->cs); + + return hr; +} + +DAPI_(HRESULT) PipeRpcWriteMessageReadResponse( + __in PIPE_RPC_HANDLE* phRpcPipe, + __in DWORD dwMessageType, + __in_bcount_opt(cbData) LPBYTE pbArgData, + __in SIZE_T cbArgData, + __in PIPE_RPC_RESULT* pResult +) +{ + HRESULT hr = S_OK; + DWORD rgResultAndSize[2] = { }; + LPBYTE pbResultData = NULL; + DWORD cbResultData = 0; + + hr = PipeWriteMessage(phRpcPipe->hPipe, dwMessageType, pbArgData, cbArgData); + PipeExitOnFailure(hr, "Failed to write message type to RPC pipe."); + + // Read the result and size of response. + hr = FileReadHandle(phRpcPipe->hPipe, reinterpret_cast(rgResultAndSize), sizeof(rgResultAndSize)); + ExitOnFailure(hr, "Failed to read result and size of message."); + + pResult->hr = rgResultAndSize[0]; + cbResultData = rgResultAndSize[1]; + + if (cbResultData) { - MemFree(pMsg->pvData); + pbResultData = reinterpret_cast(MemAlloc(cbResultData, TRUE)); + ExitOnNull(pbResultData, hr, E_OUTOFMEMORY, "Failed to allocate memory for BA results."); + + hr = FileReadHandle(phRpcPipe->hPipe, pbResultData, cbResultData); + ExitOnFailure(hr, "Failed to read result and size of message."); } + pResult->cbData = cbResultData; + pResult->pbData = pbResultData; + pbResultData = NULL; + + hr = pResult->hr; + ExitOnFailure(hr, "BA reported failure."); + +LExit: + ReleaseMem(pbResultData); + + ::LeaveCriticalSection(&phRpcPipe->cs); + return hr; } DAPI_(HRESULT) PipeServerWaitForClientConnect( + __in HANDLE hClientProcess, __in HANDLE hPipe ) { @@ -206,13 +459,13 @@ DAPI_(HRESULT) PipeServerWaitForClientConnect( DWORD dwPipeState = PIPE_READMODE_BYTE | PIPE_NOWAIT; // Temporarily make the pipe non-blocking so we will not get stuck in ::ConnectNamedPipe() forever - // if the child decides not to show up. + // if the client decides not to show up. if (!::SetNamedPipeHandleState(hPipe, &dwPipeState, NULL, NULL)) { PipeExitWithLastError(hr, "Failed to set pipe to non-blocking."); } - // Loop for a while waiting for a connection from child process. + // Loop for a while waiting for a connection from client process. DWORD cRetry = 0; do { @@ -237,7 +490,19 @@ DAPI_(HRESULT) PipeServerWaitForClientConnect( } ++cRetry; - ::Sleep(PIPE_WAIT_FOR_CONNECTION); + + // Ensure the client is still around. + hr = ::AppWaitForSingleObject(hClientProcess, PIPE_WAIT_FOR_CONNECTION); + if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr) + { + // Timeout out means the process is still there, that's good. + hr = HRESULT_FROM_WIN32(ERROR_PIPE_LISTENING); + } + else if (SUCCEEDED(hr)) + { + // Success means the process is gone, that's bad. + hr = HRESULT_FROM_WIN32(WAIT_ABANDONED); + } } else { @@ -259,6 +524,26 @@ LExit: return hr; } +DAPI_(HRESULT) PipeWriteDisconnect( + __in HANDLE hPipe + ) +{ + HRESULT hr = S_OK; + LPVOID pv = NULL; + SIZE_T cb = 0; + + hr = AllocatePipeMessage(PIPE_MESSAGE_DISCONNECT, NULL, 0, &pv, &cb); + ExitOnFailure(hr, "Failed to allocate message to write."); + + // Write the message. + hr = FileWriteHandle(hPipe, reinterpret_cast(pv), cb); + ExitOnFailure(hr, "Failed to write message type to pipe."); + +LExit: + ReleaseMem(pv); + return hr; +} + DAPI_(HRESULT) PipeWriteMessage( __in HANDLE hPipe, __in DWORD dwMessageType, @@ -266,22 +551,6 @@ DAPI_(HRESULT) PipeWriteMessage( __in SIZE_T cbData ) { -// HRESULT hr = S_OK; -// -// hr = FileWriteHandle(hPipe, reinterpret_cast(&dwMessageType), sizeof(dwMessageType)); -// PipeExitOnFailure(hr, "Failed to write message id to pipe."); -// -// hr = FileWriteHandle(hPipe, reinterpret_cast(&cbData), sizeof(cbData)); -// PipeExitOnFailure(hr, "Failed to write message data size to pipe."); -// -// if (pvData && cbData) -// { -// hr = FileWriteHandle(hPipe, reinterpret_cast(pvData), cbData); -// PipeExitOnFailure(hr, "Failed to write message data to pipe."); -// } -// -//LExit: -// return hr; HRESULT hr = S_OK; LPVOID pv = NULL; SIZE_T cb = 0; @@ -295,6 +564,7 @@ DAPI_(HRESULT) PipeWriteMessage( LExit: ReleaseMem(pv); + return hr; } @@ -302,7 +572,7 @@ static HRESULT AllocatePipeMessage( __in DWORD dwMessageType, __in_bcount_opt(cbData) LPVOID pvData, __in SIZE_T cbData, - __out_bcount(cb) LPVOID* ppvMessage, + __out_bcount(*pcbMessage) LPVOID* ppvMessage, __out SIZE_T* pcbMessage ) { @@ -311,21 +581,12 @@ static HRESULT AllocatePipeMessage( size_t cb = 0; DWORD dwcbData = 0; - // If no data was provided, ensure the count of bytes is zero. - if (!pvData) - { - cbData = 0; - } - else if (MAXDWORD < cbData) - { - ExitWithRootFailure(hr, E_INVALIDDATA, "Pipe message is too large."); - } + hr = DutilSizetToDword(pvData ? cbData : 0, &dwcbData); + PipeExitOnFailure(hr, "Pipe message is too large."); - hr = ::SizeTAdd(sizeof(dwMessageType) + sizeof(dwcbData), cbData, &cb); + hr = ::SizeTAdd(sizeof(dwMessageType) + sizeof(dwcbData), dwcbData, &cb); ExitOnRootFailure(hr, "Failed to calculate total pipe message size"); - dwcbData = (DWORD)cbData; - // Allocate the message. pv = MemAlloc(cb, FALSE); ExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to allocate memory for message."); diff --git a/src/libs/dutil/WixToolset.DUtil/strutil.cpp b/src/libs/dutil/WixToolset.DUtil/strutil.cpp index a483cf54..0a00c690 100644 --- a/src/libs/dutil/WixToolset.DUtil/strutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/strutil.cpp @@ -80,7 +80,7 @@ extern "C" HRESULT DAPI StrAllocSecure( /******************************************************************** AllocHelper - allocates or reuses dynamic string memory -If fZeroOnRealloc is true and the memory needs to reallocated, +If fZeroOnRealloc is true and the memory needs to reallocated, calls SecureZeroMemory on original block of memory after it is moved. NOTE: caller is responsible for freeing ppwz even if function fails @@ -350,8 +350,8 @@ extern "C" HRESULT DAPI StrAllocString( } /******************************************************************** -StrAllocStringSecure - allocates or reuses dynamic string memory and -copies in an existing string. If the memory needs to reallocated, +StrAllocStringSecure - allocates or reuses dynamic string memory and +copies in an existing string. If the memory needs to reallocated, calls SecureZeroMemory on original block of memory after it is moved. NOTE: caller is responsible for freeing ppwz even if function fails @@ -369,7 +369,7 @@ extern "C" HRESULT DAPI StrAllocStringSecure( /******************************************************************** AllocStringHelper - allocates or reuses dynamic string memory and copies in an existing string -If fZeroOnRealloc is true and the memory needs to reallocated, +If fZeroOnRealloc is true and the memory needs to reallocated, calls SecureZeroMemory on original block of memory after it is moved. NOTE: caller is responsible for freeing ppwz even if function fails @@ -623,7 +623,7 @@ LExit: /******************************************************************** -StrAllocPrefix - allocates or reuses dynamic string memory and +StrAllocPrefix - allocates or reuses dynamic string memory and prefixes a string NOTE: caller is responsible for freeing ppwz even if function fails @@ -703,8 +703,8 @@ extern "C" HRESULT DAPI StrAllocConcat( /******************************************************************** -StrAllocConcatSecure - allocates or reuses dynamic string memory and -adds an existing string. If the memory needs to reallocated, calls +StrAllocConcatSecure - allocates or reuses dynamic string memory and +adds an existing string. If the memory needs to reallocated, calls SecureZeroMemory on the original block of memory after it is moved. NOTE: caller is responsible for freeing ppwz even if function fails @@ -723,7 +723,7 @@ extern "C" HRESULT DAPI StrAllocConcatSecure( /******************************************************************** AllocConcatHelper - allocates or reuses dynamic string memory and adds an existing string -If fZeroOnRealloc is true and the memory needs to reallocated, +If fZeroOnRealloc is true and the memory needs to reallocated, calls SecureZeroMemory on original block of memory after it is moved. NOTE: caller is responsible for freeing ppwz even if function fails @@ -940,7 +940,7 @@ LExit: /******************************************************************** -StrAllocFormattedSecure - allocates or reuses dynamic string memory +StrAllocFormattedSecure - allocates or reuses dynamic string memory and formats it. If the memory needs to be reallocated, calls SecureZeroMemory on original block of memory after it is moved. @@ -990,7 +990,7 @@ extern "C" HRESULT DAPI StrAnsiAllocFormatted( /******************************************************************** -StrAllocFormattedArgs - allocates or reuses dynamic string memory +StrAllocFormattedArgs - allocates or reuses dynamic string memory and formats it with the passed in args NOTE: caller is responsible for freeing ppwz even if function fails @@ -1009,7 +1009,7 @@ extern "C" HRESULT DAPI StrAllocFormattedArgs( StrAllocFormattedArgsSecure - allocates or reuses dynamic string memory and formats it with the passed in args. -If the memory needs to reallocated, calls SecureZeroMemory on the +If the memory needs to reallocated, calls SecureZeroMemory on the original block of memory after it is moved. NOTE: caller is responsible for freeing ppwz even if function fails @@ -1028,7 +1028,7 @@ extern "C" HRESULT DAPI StrAllocFormattedArgsSecure( AllocFormattedArgsHelper - allocates or reuses dynamic string memory and formats it with the passed in args. -If fZeroOnRealloc is true and the memory needs to reallocated, +If fZeroOnRealloc is true and the memory needs to reallocated, calls SecureZeroMemory on original block of memory after it is moved. NOTE: caller is responsible for freeing ppwz even if function fails @@ -1108,7 +1108,7 @@ LExit: /******************************************************************** -StrAnsiAllocFormattedArgs - allocates or reuses dynamic ANSI string memory +StrAnsiAllocFormattedArgs - allocates or reuses dynamic ANSI string memory and formats it with the passed in args NOTE: caller is responsible for freeing ppsz even if function fails @@ -1946,7 +1946,7 @@ extern "C" HRESULT DAPI MultiSzPrepend( // Allocate the result buffer hr = StrAlloc(&pwzResult, cchResult + 1); StrExitOnFailure(hr, "failed to allocate result string"); - + // Prepend hr = ::StringCchCopyW(pwzResult, cchResult, pwzInsert); StrExitOnRootFailure(hr, "failed to copy prepend string: %ls", pwzInsert); @@ -2395,7 +2395,7 @@ extern "C" HRESULT DAPI StrStringToUInt16( ULONGLONG ull = 0; hr = StrStringToUInt64(wzIn, cchIn, &ull); - StrExitOnFailure(hr, "Failed to parse uint64."); + StrExitOnFailure(hr, "Failed to parse uint64 to convert to uint16."); if (USHORT_MAX < ull) { @@ -2447,7 +2447,7 @@ extern "C" HRESULT DAPI StrStringToUInt32( ULONGLONG ull = 0; hr = StrStringToUInt64(wzIn, cchIn, &ull); - StrExitOnFailure(hr, "Failed to parse uint64."); + StrExitOnFailure(hr, "Failed to parse uint64 to convert to uint32."); if (UINT_MAX < ull) { diff --git a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp index 7938cd0b..910b05c2 100644 --- a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp @@ -954,7 +954,7 @@ DAPI_(HRESULT) ThemeLocalize( LExit: ReleaseStr(sczCaption); - + return hr; } @@ -6312,7 +6312,7 @@ static HRESULT LoadControls( } pControl->hWnd = ::CreateWindowExW(dwWindowExBits, wzWindowClass, pControl->sczText, pControl->dwStyle | dwWindowBits, x, y, w, h, hwndParent, reinterpret_cast(wControlId), NULL, pControl); - ThmExitOnNullWithLastError(pControl->hWnd, hr, "Failed to create window."); + ThmExitOnNullWithLastError(pControl->hWnd, hr, "Failed to create control %ls window.", wzWindowClass); if (pControl->sczTooltip) { diff --git a/src/libs/dutil/test/DUtilUnitTest/PipeUtilTest.cpp b/src/libs/dutil/test/DUtilUnitTest/PipeUtilTest.cpp index 87a5e8f2..aa6874e4 100644 --- a/src/libs/dutil/test/DUtilUnitTest/PipeUtilTest.cpp +++ b/src/libs/dutil/test/DUtilUnitTest/PipeUtilTest.cpp @@ -23,6 +23,7 @@ namespace DutilTests HRESULT hr = S_OK; HANDLE hServerPipe = INVALID_HANDLE_VALUE; HANDLE hClientThread = NULL; + PIPE_RPC_HANDLE hRpc = { INVALID_HANDLE_VALUE }; PIPE_MESSAGE msg = { }; DWORD dwThread = 42; DWORD dwTestMessageId = 987654; @@ -32,6 +33,12 @@ namespace DutilTests hr = PipeCreate(L"DutilTest", NULL, &hServerPipe); NativeAssert::Succeeded(hr, "Failed to create server pipe."); + PipeRpcInitialize(&hRpc, hServerPipe, FALSE); + NativeAssert::Equal((DWORD_PTR)hServerPipe, (DWORD_PTR)hRpc.hPipe); + + BOOL fInitialized = PipeRpcInitialized(&hRpc); + NativeAssert::True(fInitialized); + hClientThread = ::CreateThread(NULL, 0, _TestPipeClientThreadProc, &dwTestMessageId, 0, NULL); if (hClientThread == 0) { @@ -39,10 +46,10 @@ namespace DutilTests return; } - hr = PipeServerWaitForClientConnect(hServerPipe); + hr = PipeServerWaitForClientConnect(hClientThread, hServerPipe); NativeAssert::Succeeded(hr, "Failed to wait for client to connect to pipe."); - hr = PipeReadMessage(hServerPipe, &msg); + hr = PipeRpcReadMessage(&hRpc, &msg); NativeAssert::Succeeded(hr, "Failed to read message from client."); NativeAssert::Equal(dwTestMessageId, msg.dwMessageType); @@ -57,6 +64,8 @@ namespace DutilTests ReleasePipeMessage(&msg); ReleaseHandle(hClientThread); ReleasePipeHandle(hServerPipe); + + PipeRpcUninitiailize(&hRpc); } } }; @@ -69,6 +78,7 @@ static DWORD STDAPICALLTYPE _TestPipeClientThreadProc( { HRESULT hr = S_OK; HANDLE hClientPipe = INVALID_HANDLE_VALUE; + PIPE_RPC_HANDLE hRpc = { INVALID_HANDLE_VALUE }; hr = PipeClientConnect(L"DutilTest", &hClientPipe); if (FAILED(hr)) @@ -76,14 +86,17 @@ static DWORD STDAPICALLTYPE _TestPipeClientThreadProc( return hr; } + PipeRpcInitialize(&hRpc, hClientPipe, TRUE); + ::Sleep(200); - hr = PipeWriteMessage(hClientPipe, *(LPDWORD)lpThreadParameter, NULL, 0); + hr = PipeRpcWriteMessage(&hRpc, *(LPDWORD)lpThreadParameter, NULL, 0); if (FAILED(hr)) { return hr; } - ReleasePipeHandle(hClientPipe); + PipeRpcUninitiailize(&hRpc); + return 12; } -- cgit v1.2.3-55-g6feb