diff --git a/src/dutil/acl2util.cpp b/src/dutil/acl2util.cpp index 5aba60f..598f12e 100644 --- a/src/dutil/acl2util.cpp +++ b/src/dutil/acl2util.cpp @@ -23,7 +23,7 @@ NOTE: psczSid should be freed with StrFree() ********************************************************************/ extern "C" HRESULT DAPI AclCalculateServiceSidString( __in LPCWSTR wzServiceName, - __in int cchServiceName, + __in SIZE_T cchServiceName, __deref_out_z LPWSTR* psczSid ) { @@ -39,7 +39,7 @@ extern "C" HRESULT DAPI AclCalculateServiceSidString( if (0 == cchServiceName) { - hr = ::StringCchLengthW(wzServiceName, INT_MAX, reinterpret_cast(&cchServiceName)); + hr = ::StringCchLengthW(wzServiceName, STRSAFE_MAX_CCH, reinterpret_cast(&cchServiceName)); AclExitOnFailure(hr, "Failed to get the length of the service name."); } @@ -49,7 +49,7 @@ extern "C" HRESULT DAPI AclCalculateServiceSidString( pbHash = reinterpret_cast(MemAlloc(cbHash, TRUE)); AclExitOnNull(pbHash, hr, E_OUTOFMEMORY, "Failed to allocate hash byte array."); - hr = CrypHashBuffer(reinterpret_cast(sczUpperServiceName), cchServiceName * 2, PROV_RSA_FULL, CALG_SHA1, pbHash, cbHash); + hr = CrypHashBuffer(reinterpret_cast(sczUpperServiceName), cchServiceName * sizeof(WCHAR), PROV_RSA_FULL, CALG_SHA1, pbHash, cbHash); AclExitOnNull(pbHash, hr, E_OUTOFMEMORY, "Failed to hash the service name."); hr = StrAllocFormatted(psczSid, L"S-1-5-80-%u-%u-%u-%u-%u", @@ -80,7 +80,7 @@ extern "C" HRESULT DAPI AclGetAccountSidStringEx( ) { HRESULT hr = S_OK; - int cchAccount = 0; + SIZE_T cchAccount = 0; PSID psid = NULL; LPWSTR pwz = NULL; LPWSTR sczSid = NULL; @@ -103,7 +103,7 @@ extern "C" HRESULT DAPI AclGetAccountSidStringEx( { if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr) { - HRESULT hrLength = ::StringCchLengthW(wzAccount, INT_MAX, reinterpret_cast(&cchAccount)); + HRESULT hrLength = ::StringCchLengthW(wzAccount, STRSAFE_MAX_CCH, reinterpret_cast(&cchAccount)); AclExitOnFailure(hrLength, "Failed to get the length of the account name."); if (11 < cchAccount && CSTR_EQUAL == CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, L"NT SERVICE\\", 11, wzAccount, 11)) diff --git a/src/dutil/apuputil.cpp b/src/dutil/apuputil.cpp index 6f5825b..eb96d51 100644 --- a/src/dutil/apuputil.cpp +++ b/src/dutil/apuputil.cpp @@ -388,7 +388,7 @@ static HRESULT ParseEnclosure( if (dwDigestStringLength != cchDigestString) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); - ApupExitOnRootFailure(hr, "Invalid digest length (%zu) for digest algorithm (%u).", cchDigestString, dwDigestStringLength); + ApupExitOnRootFailure(hr, "Invalid digest length (%Iu) for digest algorithm (%u).", cchDigestString, dwDigestStringLength); } pEnclosure->cbDigest = sizeof(BYTE) * dwDigestLength; diff --git a/src/dutil/buffutil.cpp b/src/dutil/buffutil.cpp index a6d3ac9..b6d58cc 100644 --- a/src/dutil/buffutil.cpp +++ b/src/dutil/buffutil.cpp @@ -70,7 +70,7 @@ extern "C" HRESULT BuffReadNumber64( __in SIZE_T cbBuffer, __inout SIZE_T* piBuffer, __out DWORD64* pdw64 -) + ) { Assert(pbBuffer); Assert(piBuffer); @@ -98,11 +98,11 @@ LExit: } extern "C" HRESULT BuffReadPointer( - __in_bcount(cbBuffer) const BYTE * pbBuffer, + __in_bcount(cbBuffer) const BYTE* pbBuffer, __in SIZE_T cbBuffer, __inout SIZE_T* piBuffer, __out DWORD_PTR* pdw64 -) + ) { Assert(pbBuffer); Assert(piBuffer); @@ -141,8 +141,8 @@ extern "C" HRESULT BuffReadString( Assert(pscz); HRESULT hr = S_OK; - DWORD cch = 0; - DWORD cb = 0; + SIZE_T cch = 0; + SIZE_T cb = 0; SIZE_T cbAvailable = 0; // get availiable data size @@ -150,19 +150,19 @@ extern "C" HRESULT BuffReadString( BuffExitOnRootFailure(hr, "Failed to calculate available data size for character count."); // verify buffer size - if (sizeof(DWORD) > cbAvailable) + if (sizeof(SIZE_T) > cbAvailable) { hr = E_INVALIDARG; BuffExitOnRootFailure(hr, "Buffer too small."); } // read character count - cch = *(const DWORD*)(pbBuffer + *piBuffer); + cch = *(const SIZE_T*)(pbBuffer + *piBuffer); - hr = ::DWordMult(cch, static_cast(sizeof(WCHAR)), &cb); + hr = ::SIZETMult(cch, sizeof(WCHAR), &cb); BuffExitOnRootFailure(hr, "Overflow while multiplying to calculate buffer size"); - hr = ::SIZETAdd(*piBuffer, sizeof(DWORD), piBuffer); + hr = ::SIZETAdd(*piBuffer, sizeof(SIZE_T), piBuffer); BuffExitOnRootFailure(hr, "Overflow while adding to calculate buffer size"); // get availiable data size @@ -198,8 +198,8 @@ extern "C" HRESULT BuffReadStringAnsi( Assert(pscz); HRESULT hr = S_OK; - DWORD cch = 0; - DWORD cb = 0; + SIZE_T cch = 0; + SIZE_T cb = 0; SIZE_T cbAvailable = 0; // get availiable data size @@ -207,19 +207,19 @@ extern "C" HRESULT BuffReadStringAnsi( BuffExitOnRootFailure(hr, "Failed to calculate available data size for character count."); // verify buffer size - if (sizeof(DWORD) > cbAvailable) + if (sizeof(SIZE_T) > cbAvailable) { hr = E_INVALIDARG; BuffExitOnRootFailure(hr, "Buffer too small."); } // read character count - cch = *(const DWORD*)(pbBuffer + *piBuffer); + cch = *(const SIZE_T*)(pbBuffer + *piBuffer); - hr = ::DWordMult(cch, static_cast(sizeof(CHAR)), &cb); + hr = ::SIZETMult(cch, sizeof(CHAR), &cb); BuffExitOnRootFailure(hr, "Overflow while multiplying to calculate buffer size"); - hr = ::SIZETAdd(*piBuffer, sizeof(DWORD), piBuffer); + hr = ::SIZETAdd(*piBuffer, sizeof(SIZE_T), piBuffer); BuffExitOnRootFailure(hr, "Overflow while adding to calculate buffer size"); // get availiable data size @@ -257,23 +257,24 @@ extern "C" HRESULT BuffReadStream( Assert(pcbStream); HRESULT hr = S_OK; - DWORD64 cb = 0; + SIZE_T cb = 0; SIZE_T cbAvailable = 0; + errno_t err = 0; // get availiable data size hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable); BuffExitOnRootFailure(hr, "Failed to calculate available data size for stream size."); // verify buffer size - if (sizeof(DWORD64) > cbAvailable) + if (sizeof(SIZE_T) > cbAvailable) { hr = E_INVALIDARG; BuffExitOnRootFailure(hr, "Buffer too small."); } // read stream size - cb = *(const DWORD64*)(pbBuffer + *piBuffer); - *piBuffer += sizeof(DWORD64); + cb = *(const SIZE_T*)(pbBuffer + *piBuffer); + *piBuffer += sizeof(SIZE_T); // get availiable data size hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable); @@ -287,15 +288,20 @@ extern "C" HRESULT BuffReadStream( } // allocate buffer - *ppbStream = (BYTE*)MemAlloc((SIZE_T)cb, TRUE); + *ppbStream = (BYTE*)MemAlloc(cb, TRUE); BuffExitOnNull(*ppbStream, hr, E_OUTOFMEMORY, "Failed to allocate stream."); // read stream data - memcpy_s(*ppbStream, cbBuffer - *piBuffer, pbBuffer + *piBuffer, (SIZE_T)cb); - *piBuffer += (SIZE_T)cb; + err = memcpy_s(*ppbStream, cbBuffer - *piBuffer, pbBuffer + *piBuffer, cb); + if (err) + { + BuffExitOnRootFailure(hr = E_INVALIDARG, "Failed to read stream from buffer, error: %d", err); + } + + *piBuffer += cb; // return stream size - *pcbStream = (SIZE_T)cb; + *pcbStream = cb; LExit: return hr; @@ -304,7 +310,7 @@ LExit: extern "C" HRESULT BuffWriteNumber( __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer, __inout SIZE_T* piBuffer, - __in DWORD_PTR dw + __in DWORD dw ) { Assert(ppbBuffer); @@ -317,7 +323,7 @@ extern "C" HRESULT BuffWriteNumber( BuffExitOnFailure(hr, "Failed to ensure buffer size."); // copy data to buffer - *(DWORD_PTR*)(*ppbBuffer + *piBuffer) = dw; + *(DWORD*)(*ppbBuffer + *piBuffer) = dw; *piBuffer += sizeof(DWORD); LExit: @@ -351,7 +357,7 @@ extern "C" HRESULT BuffWritePointer( __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer, __inout SIZE_T* piBuffer, __in DWORD_PTR dw -) + ) { Assert(ppbBuffer); Assert(piBuffer); @@ -380,19 +386,33 @@ extern "C" HRESULT BuffWriteString( Assert(piBuffer); HRESULT hr = S_OK; - DWORD cch = (DWORD)lstrlenW(scz); - SIZE_T cb = cch * sizeof(WCHAR); + SIZE_T cch = 0; + 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.") + } + + cb = cch * sizeof(WCHAR); // make sure we have a buffer with sufficient space - hr = EnsureBufferSize(ppbBuffer, *piBuffer + (sizeof(DWORD) + cb)); + hr = EnsureBufferSize(ppbBuffer, *piBuffer + (sizeof(SIZE_T) + cb)); BuffExitOnFailure(hr, "Failed to ensure buffer size."); // copy character count to buffer - *(DWORD*)(*ppbBuffer + *piBuffer) = cch; - *piBuffer += sizeof(DWORD); + *(SIZE_T*)(*ppbBuffer + *piBuffer) = cch; + *piBuffer += sizeof(SIZE_T); // copy data to buffer - memcpy_s(*ppbBuffer + *piBuffer, cb, scz, cb); + err = memcpy_s(*ppbBuffer + *piBuffer, cb, scz, cb); + if (err) + { + BuffExitOnRootFailure(hr = E_INVALIDARG, "Failed to write string to buffer: '%ls', error: %d", scz, err); + } + *piBuffer += cb; LExit: @@ -409,19 +429,33 @@ extern "C" HRESULT BuffWriteStringAnsi( Assert(piBuffer); HRESULT hr = S_OK; - DWORD cch = (DWORD)lstrlenA(scz); - SIZE_T cb = cch * sizeof(CHAR); + SIZE_T cch = 0; + 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.") + } + + cb = cch * sizeof(CHAR); // make sure we have a buffer with sufficient space - hr = EnsureBufferSize(ppbBuffer, *piBuffer + (sizeof(DWORD) + cb)); + hr = EnsureBufferSize(ppbBuffer, *piBuffer + (sizeof(SIZE_T) + cb)); BuffExitOnFailure(hr, "Failed to ensure buffer size."); // copy character count to buffer - *(DWORD*)(*ppbBuffer + *piBuffer) = cch; - *piBuffer += sizeof(DWORD); + *(SIZE_T*)(*ppbBuffer + *piBuffer) = cch; + *piBuffer += sizeof(SIZE_T); // copy data to buffer - memcpy_s(*ppbBuffer + *piBuffer, cb, scz, cb); + err = memcpy_s(*ppbBuffer + *piBuffer, cb, scz, cb); + if (err) + { + BuffExitOnRootFailure(hr = E_INVALIDARG, "Failed to write string to buffer: '%hs', error: %d", scz, err); + } + *piBuffer += cb; LExit: @@ -440,18 +474,24 @@ extern "C" HRESULT BuffWriteStream( Assert(pbStream); HRESULT hr = S_OK; - DWORD64 cb = cbStream; + SIZE_T cb = cbStream; + errno_t err = 0; // make sure we have a buffer with sufficient space - hr = EnsureBufferSize(ppbBuffer, *piBuffer + cbStream + sizeof(DWORD64)); + hr = EnsureBufferSize(ppbBuffer, *piBuffer + cbStream + sizeof(SIZE_T)); BuffExitOnFailure(hr, "Failed to ensure buffer size."); // copy byte count to buffer - *(DWORD64*)(*ppbBuffer + *piBuffer) = cb; - *piBuffer += sizeof(DWORD64); + *(SIZE_T*)(*ppbBuffer + *piBuffer) = cb; + *piBuffer += sizeof(SIZE_T); // copy data to buffer - memcpy_s(*ppbBuffer + *piBuffer, cbStream, pbStream, cbStream); + 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; LExit: diff --git a/src/dutil/cryputil.cpp b/src/dutil/cryputil.cpp index c5c1b22..24bb83f 100644 --- a/src/dutil/cryputil.cpp +++ b/src/dutil/cryputil.cpp @@ -291,6 +291,9 @@ HRESULT DAPI CrypHashBuffer( HRESULT hr = S_OK; HCRYPTPROV hProv = NULL; HCRYPTHASH hHash = NULL; + DWORD cbDataHashed = 0; + SIZE_T cbTotal = 0; + SIZE_T cbRemaining = 0; // get handle to the crypto provider if (!::CryptAcquireContextW(&hProv, NULL, NULL, dwProvType, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) @@ -304,10 +307,17 @@ HRESULT DAPI CrypHashBuffer( CrypExitWithLastError(hr, "Failed to initiate hash."); } - if (!::CryptHashData(hHash, pbBuffer, static_cast(cbBuffer), 0)) + do { - CrypExitWithLastError(hr, "Failed to hash data."); - } + cbRemaining = cbBuffer - cbTotal; + cbDataHashed = (DWORD)min(DWORD_MAX, cbRemaining); + if (!::CryptHashData(hHash, pbBuffer + cbTotal, cbDataHashed, 0)) + { + CrypExitWithLastError(hr, "Failed to hash data."); + } + + cbTotal += cbDataHashed; + } while (cbTotal < cbBuffer); // get hash value if (!::CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &cbHash, 0)) diff --git a/src/dutil/deputil.cpp b/src/dutil/deputil.cpp index 362b334..2e6d6a6 100644 --- a/src/dutil/deputil.cpp +++ b/src/dutil/deputil.cpp @@ -122,9 +122,7 @@ DAPI_(HRESULT) DepCheckDependency( LPWSTR sczKey = NULL; HKEY hkKey = NULL; DWORD64 dw64Version = 0; - int cchMinVersion = 0; DWORD64 dw64MinVersion = 0; - int cchMaxVersion = 0; DWORD64 dw64MaxVersion = 0; BOOL fAllowEqual = FALSE; LPWSTR sczName = NULL; @@ -171,10 +169,9 @@ DAPI_(HRESULT) DepCheckDependency( // Check MinVersion if provided. if (wzMinVersion) { - cchMinVersion = lstrlenW(wzMinVersion); - if (0 < cchMinVersion) + if (*wzMinVersion) { - hr = FileVersionFromStringEx(wzMinVersion, cchMinVersion, &dw64MinVersion); + hr = FileVersionFromStringEx(wzMinVersion, 0, &dw64MinVersion); DepExitOnFailure(hr, "Failed to get the 64-bit version number from \"%ls\".", wzMinVersion); fAllowEqual = iAttributes & RequiresAttributesMinVersionInclusive; @@ -206,10 +203,9 @@ DAPI_(HRESULT) DepCheckDependency( // Check MaxVersion if provided. if (wzMaxVersion) { - cchMaxVersion = lstrlenW(wzMaxVersion); - if (0 < cchMaxVersion) + if (*wzMaxVersion) { - hr = FileVersionFromStringEx(wzMaxVersion, cchMaxVersion, &dw64MaxVersion); + hr = FileVersionFromStringEx(wzMaxVersion, 0, &dw64MaxVersion); DepExitOnFailure(hr, "Failed to get the 64-bit version number from \"%ls\".", wzMaxVersion); fAllowEqual = iAttributes & RequiresAttributesMaxVersionInclusive; diff --git a/src/dutil/dirutil.cpp b/src/dutil/dirutil.cpp index b10e71f..ae2c5e1 100644 --- a/src/dutil/dirutil.cpp +++ b/src/dutil/dirutil.cpp @@ -400,7 +400,7 @@ extern "C" HRESULT DAPI DirGetCurrent( DirExitOnFailure(hr, "Failed to determine size of current directory."); } - DWORD cchRequired = ::GetCurrentDirectoryW(static_cast(cch), 0 == cch ? NULL : *psczCurrentDirectory); + DWORD cchRequired = ::GetCurrentDirectoryW((DWORD)min(DWORD_MAX, cch), 0 == cch ? NULL : *psczCurrentDirectory); if (0 == cchRequired) { DirExitWithLastError(hr, "Failed to get current directory."); diff --git a/src/dutil/dutil.cpp b/src/dutil/dutil.cpp index c500191..56b8520 100644 --- a/src/dutil/dutil.cpp +++ b/src/dutil/dutil.cpp @@ -127,9 +127,13 @@ extern "C" void DAPI Dutil_AssertMsg( hAssertFile = ::CreateFileA(szPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE != hAssertFile) { - ::SetFilePointer(hAssertFile, 0, 0, FILE_END); - ::StringCchCatA(szMsg, countof(szMsg), "\r\n"); - ::WriteFile(hAssertFile, szMsg, lstrlenA(szMsg), &cch, NULL); + if (INVALID_SET_FILE_POINTER != ::SetFilePointer(hAssertFile, 0, 0, FILE_END)) + { + if (SUCCEEDED(::StringCchCatA(szMsg, countof(szMsg), "\r\n"))) + { + ::WriteFile(hAssertFile, szMsg, lstrlenA(szMsg), &cch, NULL); + } + } } } } diff --git a/src/dutil/eseutil.cpp b/src/dutil/eseutil.cpp index d2bd7dc..b9455d4 100644 --- a/src/dutil/eseutil.cpp +++ b/src/dutil/eseutil.cpp @@ -312,12 +312,14 @@ HRESULT AllocIndexCreateStruct( EseExitOnNull(*ppjicIndexCreate, hr, E_OUTOFMEMORY, "Failed to allocate index create structure for database"); // Record the size including both null terminators - the struct requires this - DWORD dwSize = 0; - dwSize = lstrlen(pszMultiSzKeys) + 1; // add 1 to include null character at the end - EseExitOnFailure(hr, "Failed to get size of keys string"); + size_t cchSize = 0; + hr = ::StringCchLengthA(pszMultiSzKeys, STRSAFE_MAX_LENGTH, &cchSize); + EseExitOnRootFailure(hr, "Failed to get size of keys string"); + + ++cchSize; // add 1 to include null character at the end // At this point convert all question marks to null characters - for (i = 0; i < dwSize; ++i) + for (i = 0; i < cchSize; ++i) { if ('?' == pszMultiSzKeys[i]) { @@ -328,7 +330,7 @@ HRESULT AllocIndexCreateStruct( (*ppjicIndexCreate)->cbStruct = sizeof(JET_INDEXCREATE); (*ppjicIndexCreate)->szIndexName = pszIndexName; (*ppjicIndexCreate)->szKey = pszMultiSzKeys; - (*ppjicIndexCreate)->cbKey = dwSize; + (*ppjicIndexCreate)->cbKey = (DWORD)cchSize; (*ppjicIndexCreate)->grbit = JET_bitIndexUnique | JET_bitIndexPrimary; (*ppjicIndexCreate)->ulDensity = 80; (*ppjicIndexCreate)->lcid = 1033; @@ -884,7 +886,16 @@ HRESULT DAPI EseSetColumnString( { HRESULT hr = S_OK; JET_ERR jEr = JET_errSuccess; - ULONG cbValueSize = static_cast((wcslen(pwzValue) + 1) * sizeof(WCHAR)); // add 1 for null character, then multiply by size of WCHAR to get bytes + size_t cchValue = 0; + ULONG cbValueSize = 0; + + if (pwzValue) + { + hr = ::StringCchLengthW(pwzValue, STRSAFE_MAX_LENGTH, &cchValue); + EseExitOnRootFailure(hr, "Failed to get string length: %ls", pwzValue); + } + + cbValueSize = static_cast((cchValue + 1) * sizeof(WCHAR)); // add 1 for null character, then multiply by size of WCHAR to get bytes jEr = JetSetColumn(jsSession, tsTable.jtTable, tsTable.pcsColumns[dwColumn].jcColumn, pwzValue, cbValueSize, 0, NULL); ExitOnJetFailure(jEr, hr, "Failed to set string value into column of database: %ls", pwzValue); @@ -1196,11 +1207,17 @@ HRESULT DAPI EseSetQueryColumnString( { HRESULT hr = S_OK; DWORD dwStringSize = 0; + size_t cchString = 0; ESE_QUERY *peqHandle = static_cast(eqhHandle); JET_GRBIT jGrb = 0; - dwStringSize = sizeof(WCHAR) * (lstrlenW(pszString) + 1); // Add 1 for null terminator + if (pszString) + { + hr = ::StringCchLengthW(pszString, STRSAFE_MAX_LENGTH, &cchString); + EseExitOnRootFailure(hr, "Failed to get size of column string"); + } + dwStringSize = static_cast(sizeof(WCHAR) * (cchString + 1)); // Add 1 for null terminator if (fFinal) { diff --git a/src/dutil/fileutil.cpp b/src/dutil/fileutil.cpp index 6cc2a80..1822727 100644 --- a/src/dutil/fileutil.cpp +++ b/src/dutil/fileutil.cpp @@ -155,40 +155,33 @@ __out LPWSTR *ppwzFileNameNoExtension Assert(wzFileName && *wzFileName); HRESULT hr = S_OK; - - SIZE_T cchFileName = wcslen(wzFileName); - + size_t cchFileName = 0; LPWSTR pwzFileNameNoExtension = NULL; - DWORD cchFileNameNoExtension = 0; - - // Filename without extension can not be longer than _MAX_FNAME - // Filename without extension should also not be longer than filename itself - if (_MAX_FNAME > cchFileName) - { - cchFileNameNoExtension = (DWORD) cchFileName; - } - else - { - cchFileNameNoExtension = _MAX_FNAME; - } - + size_t cchFileNameNoExtension = 0; + errno_t err = 0; + + hr = ::StringCchLengthW(wzFileName, STRSAFE_MAX_LENGTH, &cchFileName); + FileExitOnRootFailure(hr, "failed to get length of file name: %ls", wzFileName); + + cchFileNameNoExtension = cchFileName + 1; + hr = StrAlloc(&pwzFileNameNoExtension, cchFileNameNoExtension); FileExitOnFailure(hr, "failed to allocate space for File Name without extension"); - + // _wsplitpath_s can handle drive/path/filename/extension - errno_t err = _wsplitpath_s(wzFileName, NULL, NULL, NULL, NULL, pwzFileNameNoExtension, cchFileNameNoExtension, NULL, NULL); - if (0 != err) + err = _wsplitpath_s(wzFileName, NULL, NULL, NULL, NULL, pwzFileNameNoExtension, cchFileNameNoExtension, NULL, NULL); + if (err) { hr = E_INVALIDARG; - FileExitOnFailure(hr, "failed to parse filename: %ls", wzFileName); + FileExitOnRootFailure(hr, "failed to parse filename: '%ls', error: %d", wzFileName, err); } - + *ppwzFileNameNoExtension = pwzFileNameNoExtension; pwzFileNameNoExtension = NULL; - + LExit: ReleaseStr(pwzFileNameNoExtension); - + return hr; } @@ -237,8 +230,12 @@ extern "C" HRESULT DAPI FileAddSuffixToBaseName( HRESULT hr = S_OK; LPWSTR sczNewFileName = NULL; + size_t cchFileName = 0; - LPCWSTR wzExtension = wzFileName + lstrlenW(wzFileName); + hr = ::StringCchLengthW(wzFileName, STRSAFE_MAX_CCH, &cchFileName); + FileExitOnRootFailure(hr, "Failed to get length of file name: %ls", wzFileName); + + LPCWSTR wzExtension = wzFileName + cchFileName; while (wzFileName < wzExtension && L'.' != *wzExtension) { --wzExtension; @@ -410,7 +407,7 @@ LExit: *******************************************************************/ extern "C" HRESULT DAPI FileVersionFromStringEx( __in_z LPCWSTR wzVersion, - __in DWORD cchVersion, + __in SIZE_T cchVersion, __out DWORD64* pqwVersion ) { @@ -428,7 +425,9 @@ extern "C" HRESULT DAPI FileVersionFromStringEx( // get string length if not provided if (0 >= cchVersion) { - cchVersion = lstrlenW(wzVersion); + hr = ::StringCchLengthW(wzVersion, STRSAFE_MAX_CCH, reinterpret_cast(&cchVersion)); + FileExitOnRootFailure(hr, "Failed to get length of file version string: %ls", wzVersion); + if (0 >= cchVersion) { ExitFunction1(hr = E_INVALIDARG); @@ -996,6 +995,41 @@ LExit: return hr; } +extern "C" HRESULT DAPI FileReadHandle( + __in HANDLE hFile, + __in_bcount(cbDest) LPBYTE pbDest, + __in SIZE_T cbDest + ) +{ + HRESULT hr = 0; + DWORD cbDataRead = 0; + SIZE_T cbRemaining = cbDest; + SIZE_T cbTotal = 0; + + while (0 < cbRemaining) + { + if (!::ReadFile(hFile, pbDest + cbTotal, (DWORD)min(DWORD_MAX, cbRemaining), &cbDataRead, NULL)) + { + DWORD er = ::GetLastError(); + if (ERROR_MORE_DATA == er) + { + hr = S_OK; + } + else + { + hr = HRESULT_FROM_WIN32(er); + } + FileExitOnRootFailure(hr, "Failed to read data from file handle."); + } + + cbRemaining -= cbDataRead; + cbTotal += cbDataRead; + } + +LExit: + return hr; +} + /******************************************************************* FileWrite - write a file from memory @@ -1044,18 +1078,20 @@ extern "C" HRESULT DAPI FileWriteHandle( { HRESULT hr = S_OK; DWORD cbDataWritten = 0; - DWORD cbTotal = 0; + SIZE_T cbTotal = 0; + SIZE_T cbRemaining = cbData; // Write out all of the data. - do + while (0 < cbRemaining) { - if (!::WriteFile(hFile, pbData + cbTotal, (DWORD)(cbData - cbTotal), &cbDataWritten, NULL)) + if (!::WriteFile(hFile, pbData + cbTotal, (DWORD)min(DWORD_MAX, cbRemaining), &cbDataWritten, NULL)) { FileExitOnLastError(hr, "Failed to write data to file handle."); } + cbRemaining -= cbDataWritten; cbTotal += cbDataWritten; - } while (cbTotal < cbData); + } LExit: return hr; @@ -1115,7 +1151,7 @@ extern "C" HRESULT DAPI FileCopyUsingHandlesWithProgress( __in DWORD64 cbCopy, __in_opt LPPROGRESS_ROUTINE lpProgressRoutine, __in_opt LPVOID lpData -) + ) { HRESULT hr = S_OK; DWORD64 cbTotalCopied = 0; @@ -1135,21 +1171,24 @@ extern "C" HRESULT DAPI FileCopyUsingHandlesWithProgress( liSourceSize.QuadPart = cbCopy; } - dwResult = lpProgressRoutine(liSourceSize, liTotalCopied, liZero, liZero, 0, CALLBACK_STREAM_SWITCH, hSource, hTarget, lpData); - switch (dwResult) + if (lpProgressRoutine) { - case PROGRESS_CONTINUE: - break; + dwResult = lpProgressRoutine(liSourceSize, liTotalCopied, liZero, liZero, 0, CALLBACK_STREAM_SWITCH, hSource, hTarget, lpData); + switch (dwResult) + { + case PROGRESS_CONTINUE: + break; - case PROGRESS_CANCEL: - ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_REQUEST_ABORTED)); + case PROGRESS_CANCEL: + ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_REQUEST_ABORTED)); - case PROGRESS_STOP: - ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_REQUEST_ABORTED)); + case PROGRESS_STOP: + ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_REQUEST_ABORTED)); - case PROGRESS_QUIET: - lpProgressRoutine = NULL; - break; + case PROGRESS_QUIET: + lpProgressRoutine = NULL; + break; + } } // Set size of the target file. @@ -1929,23 +1968,27 @@ extern "C" HRESULT DAPI FileFromString( LPSTR sczUtf8String = NULL; BYTE *pbFullFileBuffer = NULL; const BYTE *pcbFullFileBuffer = NULL; - DWORD cbFullFileBuffer = 0; - DWORD cbStrLen = 0; + SIZE_T cbFullFileBuffer = 0; + SIZE_T cbStrLen = 0; switch (feEncoding) { case FILE_ENCODING_UTF8: hr = StrAnsiAllocString(&sczUtf8String, sczString, 0, CP_UTF8); FileExitOnFailure(hr, "Failed to convert string to UTF-8 to write UTF-8 file"); - - cbFullFileBuffer = lstrlenA(sczUtf8String); + + hr = ::StringCchLengthA(sczUtf8String, STRSAFE_MAX_CCH, reinterpret_cast(&cbFullFileBuffer)); + FileExitOnRootFailure(hr, "Failed to get length of UTF-8 string"); + pcbFullFileBuffer = reinterpret_cast(sczUtf8String); break; case FILE_ENCODING_UTF8_WITH_BOM: hr = StrAnsiAllocString(&sczUtf8String, sczString, 0, CP_UTF8); FileExitOnFailure(hr, "Failed to convert string to UTF-8 to write UTF-8 file"); - - cbStrLen = lstrlenA(sczUtf8String); + + hr = ::StringCchLengthA(sczUtf8String, STRSAFE_MAX_CCH, reinterpret_cast(&cbStrLen)); + FileExitOnRootFailure(hr, "Failed to get length of UTF-8 string"); + cbFullFileBuffer = sizeof(UTF8BOM) + cbStrLen; pbFullFileBuffer = reinterpret_cast(MemAlloc(cbFullFileBuffer, TRUE)); @@ -1956,11 +1999,17 @@ extern "C" HRESULT DAPI FileFromString( pcbFullFileBuffer = pbFullFileBuffer; break; case FILE_ENCODING_UTF16: - cbFullFileBuffer = lstrlenW(sczString) * sizeof(WCHAR); + hr = ::StringCchLengthW(sczString, STRSAFE_MAX_CCH, reinterpret_cast(&cbStrLen)); + FileExitOnRootFailure(hr, "Failed to get length of string"); + + cbFullFileBuffer = cbStrLen * sizeof(WCHAR); pcbFullFileBuffer = reinterpret_cast(sczString); break; case FILE_ENCODING_UTF16_WITH_BOM: - cbStrLen = lstrlenW(sczString) * sizeof(WCHAR); + hr = ::StringCchLengthW(sczString, STRSAFE_MAX_CCH, reinterpret_cast(&cbStrLen)); + FileExitOnRootFailure(hr, "Failed to get length of string"); + + cbStrLen *= sizeof(WCHAR); cbFullFileBuffer = sizeof(UTF16BOM) + cbStrLen; pbFullFileBuffer = reinterpret_cast(MemAlloc(cbFullFileBuffer, TRUE)); diff --git a/src/dutil/inc/aclutil.h b/src/dutil/inc/aclutil.h index 144e461..ac03f9a 100644 --- a/src/dutil/inc/aclutil.h +++ b/src/dutil/inc/aclutil.h @@ -140,7 +140,7 @@ HRESULT DAPI AclAddAdminToSecurityDescriptor( // Following code in acl2util.cpp due to dependency on crypt32.dll. HRESULT DAPI AclCalculateServiceSidString( __in LPCWSTR wzServiceName, - __in int cchServiceName, + __in SIZE_T cchServiceName, __deref_out_z LPWSTR* psczSid ); HRESULT DAPI AclGetAccountSidStringEx( diff --git a/src/dutil/inc/buffutil.h b/src/dutil/inc/buffutil.h index 7509f76..322209e 100644 --- a/src/dutil/inc/buffutil.h +++ b/src/dutil/inc/buffutil.h @@ -57,7 +57,7 @@ HRESULT BuffReadStream( HRESULT BuffWriteNumber( __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer, __inout SIZE_T* piBuffer, - __in DWORD_PTR dw + __in DWORD dw ); HRESULT BuffWriteNumber64( __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer, diff --git a/src/dutil/inc/fileutil.h b/src/dutil/inc/fileutil.h index 319c550..d3e326f 100644 --- a/src/dutil/inc/fileutil.h +++ b/src/dutil/inc/fileutil.h @@ -62,7 +62,7 @@ HRESULT DAPI FileVersionFromString( ); HRESULT DAPI FileVersionFromStringEx( __in_z LPCWSTR wzVersion, - __in DWORD cchVersion, + __in SIZE_T cchVersion, __out DWORD64* pqwVersion ); HRESULT DAPI FileVersionToStringEx( @@ -130,6 +130,11 @@ HRESULT DAPI FileReadPartialEx( __in BOOL fPartialOK, __in DWORD dwShareMode ); +HRESULT DAPI FileReadHandle( + __in HANDLE hFile, + __in_bcount(cbDest) LPBYTE pbDest, + __in SIZE_T cbDest + ); HRESULT DAPI FileWrite( __in_z LPCWSTR pwzFileName, __in DWORD dwFlagsAndAttributes, diff --git a/src/dutil/inc/pathutil.h b/src/dutil/inc/pathutil.h index 719ee7d..579b845 100644 --- a/src/dutil/inc/pathutil.h +++ b/src/dutil/inc/pathutil.h @@ -177,6 +177,18 @@ DAPI_(HRESULT) PathConcat( __deref_out_z LPWSTR* psczCombined ); +/******************************************************************* + PathConcatCch - like .NET's Path.Combine, lets you build up a path + one piece -- file or directory -- at a time. +*******************************************************************/ +DAPI_(HRESULT) PathConcatCch( + __in_opt LPCWSTR wzPath1, + __in SIZE_T cchPath1, + __in_opt LPCWSTR wzPath2, + __in SIZE_T cchPath2, + __deref_out_z LPWSTR* psczCombined + ); + /******************************************************************* PathEnsureQuoted - ensures that a path is quoted; optionally, this function also terminates a directory with a backslash diff --git a/src/dutil/inc/strutil.h b/src/dutil/inc/strutil.h index cf8c751..1cff9ab 100644 --- a/src/dutil/inc/strutil.h +++ b/src/dutil/inc/strutil.h @@ -277,12 +277,12 @@ void DAPI StrStringToLower( HRESULT DAPI StrAllocStringToUpperInvariant( __deref_out_z LPWSTR* pscz, __in_z LPCWSTR wzSource, - __in int cchSource + __in SIZE_T cchSource ); HRESULT DAPI StrAllocStringToLowerInvariant( __deref_out_z LPWSTR* pscz, __in_z LPCWSTR wzSource, - __in int cchSource + __in SIZE_T cchSource ); HRESULT DAPI StrArrayAllocString( diff --git a/src/dutil/inc/verutil.h b/src/dutil/inc/verutil.h index 3caa17e..5247bb6 100644 --- a/src/dutil/inc/verutil.h +++ b/src/dutil/inc/verutil.h @@ -74,7 +74,7 @@ void DAPI VerFreeVersion( *******************************************************************/ HRESULT DAPI VerParseVersion( __in_z LPCWSTR wzVersion, - __in DWORD cchVersion, + __in SIZE_T cchVersion, __in BOOL fStrict, __out VERUTIL_VERSION** ppVersion ); diff --git a/src/dutil/inetutil.cpp b/src/dutil/inetutil.cpp index f75849f..8dace55 100644 --- a/src/dutil/inetutil.cpp +++ b/src/dutil/inetutil.cpp @@ -86,7 +86,8 @@ extern "C" HRESULT DAPI InternetQueryInfoString( ) { HRESULT hr = S_OK; - DWORD_PTR cbValue = 0; + SIZE_T cbOriginal = 0; + DWORD cbValue = 0; DWORD dwIndex = 0; // If nothing was provided start off with some arbitrary size. @@ -96,10 +97,12 @@ extern "C" HRESULT DAPI InternetQueryInfoString( InetExitOnFailure(hr, "Failed to allocate memory for value."); } - hr = StrSize(*psczValue, &cbValue); + hr = StrSize(*psczValue, &cbOriginal); InetExitOnFailure(hr, "Failed to get size of value."); - if (!::HttpQueryInfoW(hRequest, dwInfo, static_cast(*psczValue), reinterpret_cast(&cbValue), &dwIndex)) + cbValue = (DWORD)min(DWORD_MAX, cbOriginal); + + if (!::HttpQueryInfoW(hRequest, dwInfo, static_cast(*psczValue), &cbValue, &dwIndex)) { DWORD er = ::GetLastError(); if (ERROR_INSUFFICIENT_BUFFER == er) @@ -109,7 +112,7 @@ extern "C" HRESULT DAPI InternetQueryInfoString( hr = StrAlloc(psczValue, cbValue / sizeof(WCHAR)); InetExitOnFailure(hr, "Failed to allocate value."); - if (!::HttpQueryInfoW(hRequest, dwInfo, static_cast(*psczValue), reinterpret_cast(&cbValue), &dwIndex)) + if (!::HttpQueryInfoW(hRequest, dwInfo, static_cast(*psczValue), &cbValue, &dwIndex)) { er = ::GetLastError(); } diff --git a/src/dutil/logutil.cpp b/src/dutil/logutil.cpp index 3525127..ac68036 100644 --- a/src/dutil/logutil.cpp +++ b/src/dutil/logutil.cpp @@ -776,11 +776,15 @@ extern "C" HRESULT LogStringWorkRaw( Assert(szLogData && *szLogData); HRESULT hr = S_OK; + size_t cchLogData = 0; DWORD cbLogData = 0; DWORD cbTotal = 0; DWORD cbWrote = 0; - cbLogData = lstrlenA(szLogData); + hr = ::StringCchLengthA(szLogData, STRSAFE_MAX_CCH, &cchLogData); + LoguExitOnRootFailure(hr, "Failed to get length of raw string"); + + cbLogData = (DWORD)cchLogData; // If the log hasn't been initialized yet, store it in a buffer if (INVALID_HANDLE_VALUE == LogUtil_hLog) diff --git a/src/dutil/metautil.cpp b/src/dutil/metautil.cpp index 109cd31..f313fc1 100644 --- a/src/dutil/metautil.cpp +++ b/src/dutil/metautil.cpp @@ -299,7 +299,14 @@ extern "C" HRESULT DAPI MetaGetValue( MetaExitOnNull(pmr->pbMDData, hr, E_OUTOFMEMORY, "failed to allocate memory for metabase value"); } else // set the size of the data to the actual size of the memory - pmr->dwMDDataLen = (DWORD)MemSize(pmr->pbMDData); + { + SIZE_T cb = MemSize(pmr->pbMDData); + if (cb > DWORD_MAX) + { + MetaExitOnRootFailure(hr = E_INVALIDSTATE, "metabase data is too large: %Iu", cb); + } + pmr->dwMDDataLen = (DWORD)cb; + } hr = piMetabase->GetData(mhKey, wzKey, pmr, &cbRequired); if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr) diff --git a/src/dutil/pathutil.cpp b/src/dutil/pathutil.cpp index 183849a..7c3cfe0 100644 --- a/src/dutil/pathutil.cpp +++ b/src/dutil/pathutil.cpp @@ -181,7 +181,7 @@ DAPI_(HRESULT) PathGetDirectory( ) { HRESULT hr = S_OK; - DWORD cchDirectory = DWORD_MAX; + size_t cchDirectory = SIZE_T_MAX; for (LPCWSTR wz = wzPath; *wz; ++wz) { @@ -191,11 +191,11 @@ DAPI_(HRESULT) PathGetDirectory( // : => relative path from mapped root if (L'\\' == *wz || L'/' == *wz || (L':' == *wz && wz == wzPath + 1)) { - cchDirectory = static_cast(wz - wzPath) + 1; + cchDirectory = static_cast(wz - wzPath) + 1; } } - if (DWORD_MAX == cchDirectory) + if (SIZE_T_MAX == cchDirectory) { // we were given just a file name, so there's no directory available return S_FALSE; @@ -233,7 +233,7 @@ DAPI_(HRESULT) PathGetParentPath( if (wzParent) { - DWORD cchPath = static_cast(wzParent - wzPath) + 1; + size_t cchPath = static_cast(wzParent - wzPath) + 1; hr = StrAllocString(psczParent, wzPath, cchPath); PathExitOnFailure(hr, "Failed to copy directory."); @@ -260,6 +260,7 @@ DAPI_(HRESULT) PathExpand( DWORD cch = 0; LPWSTR sczExpandedPath = NULL; DWORD cchExpandedPath = 0; + SIZE_T cbSize = 0; LPWSTR sczFullPath = NULL; @@ -305,8 +306,10 @@ DAPI_(HRESULT) PathExpand( } PathExitOnFailure(hr, "Failed to prefix long path after expanding environment variables."); - hr = StrMaxLength(sczExpandedPath, reinterpret_cast(&cchExpandedPath)); + hr = StrMaxLength(sczExpandedPath, &cbSize); PathExitOnFailure(hr, "Failed to get max length of expanded path."); + + cchExpandedPath = (DWORD)min(DWORD_MAX, cbSize); } } @@ -317,7 +320,7 @@ DAPI_(HRESULT) PathExpand( { LPWSTR wzFileName = NULL; LPCWSTR wzPath = sczExpandedPath ? sczExpandedPath : wzRelativePath; - DWORD cchFullPath = PATH_GOOD_ENOUGH < cchExpandedPath ? cchExpandedPath : PATH_GOOD_ENOUGH; + DWORD cchFullPath = max(PATH_GOOD_ENOUGH, cchExpandedPath); hr = StrAlloc(&sczFullPath, cchFullPath); PathExitOnFailure(hr, "Failed to allocate space for full path."); @@ -836,8 +839,7 @@ DAPI_(BOOL) PathIsAbsolute( __in_z LPCWSTR wzPath ) { - DWORD dwLength = lstrlenW(wzPath); - return (1 < dwLength) && (wzPath[0] == L'\\') || (wzPath[1] == L':'); + return wzPath && wzPath[0] && wzPath[1] && (wzPath[0] == L'\\') || (wzPath[1] == L':'); } @@ -846,28 +848,40 @@ DAPI_(HRESULT) PathConcat( __in_opt LPCWSTR wzPath2, __deref_out_z LPWSTR* psczCombined ) +{ + return PathConcatCch(wzPath1, 0, wzPath2, 0, psczCombined); +} + + +DAPI_(HRESULT) PathConcatCch( + __in_opt LPCWSTR wzPath1, + __in SIZE_T cchPath1, + __in_opt LPCWSTR wzPath2, + __in SIZE_T cchPath2, + __deref_out_z LPWSTR* psczCombined + ) { HRESULT hr = S_OK; if (!wzPath2 || !*wzPath2) { - hr = StrAllocString(psczCombined, wzPath1, 0); + hr = StrAllocString(psczCombined, wzPath1, cchPath1); PathExitOnFailure(hr, "Failed to copy just path1 to output."); } else if (!wzPath1 || !*wzPath1 || PathIsAbsolute(wzPath2)) { - hr = StrAllocString(psczCombined, wzPath2, 0); + hr = StrAllocString(psczCombined, wzPath2, cchPath2); PathExitOnFailure(hr, "Failed to copy just path2 to output."); } else { - hr = StrAllocString(psczCombined, wzPath1, 0); + hr = StrAllocString(psczCombined, wzPath1, cchPath1); PathExitOnFailure(hr, "Failed to copy path1 to output."); hr = PathBackslashTerminate(psczCombined); PathExitOnFailure(hr, "Failed to backslashify."); - hr = StrAllocConcat(psczCombined, wzPath2, 0); + hr = StrAllocConcat(psczCombined, wzPath2, cchPath2); PathExitOnFailure(hr, "Failed to append path2 to output."); } @@ -1001,15 +1015,25 @@ DAPI_(HRESULT) PathGetHierarchyArray( LPWSTR sczPathCopy = NULL; LPWSTR sczNewPathCopy = NULL; DWORD cArraySpacesNeeded = 0; + size_t cchPath = 0; - for (int i = 0; i < lstrlenW(wzPath); ++i) + hr = ::StringCchLengthW(wzPath, STRSAFE_MAX_LENGTH, &cchPath); + PathExitOnRootFailure(hr, "Failed to get string length of path: %ls", wzPath); + + if (!cchPath) + { + ExitFunction1(hr = E_INVALIDARG); + } + + for (size_t i = 0; i < cchPath; ++i) { if (wzPath[i] == L'\\') { ++cArraySpacesNeeded; } } - if (wzPath[lstrlenW(wzPath) - 1] != L'\\') + + if (wzPath[cchPath - 1] != L'\\') { ++cArraySpacesNeeded; } @@ -1034,10 +1058,12 @@ DAPI_(HRESULT) PathGetHierarchyArray( hr = StrAllocString((*prgsczPathArray) + cArraySpacesNeeded - 1 - i, sczPathCopy, 0); PathExitOnFailure(hr, "Failed to copy path"); + DWORD cchPathCopy = lstrlenW(sczPathCopy); + // If it ends in a backslash, it's a directory path, so cut off everything the last backslash before we get the directory portion of the path - if (wzPath[lstrlenW(sczPathCopy) - 1] == L'\\') + if (wzPath[cchPathCopy - 1] == L'\\') { - sczPathCopy[lstrlenW(sczPathCopy) - 1] = L'\0'; + sczPathCopy[cchPathCopy - 1] = L'\0'; } hr = PathGetDirectory(sczPathCopy, &sczNewPathCopy); diff --git a/src/dutil/regutil.cpp b/src/dutil/regutil.cpp index afd2d08..cb61793 100644 --- a/src/dutil/regutil.cpp +++ b/src/dutil/regutil.cpp @@ -294,12 +294,15 @@ extern "C" HRESULT DAPI RegKeyEnum( { HRESULT hr = S_OK; DWORD er = ERROR_SUCCESS; + SIZE_T cb = 0; DWORD cch = 0; if (psczKey && *psczKey) { - hr = StrMaxLength(*psczKey, reinterpret_cast(&cch)); + hr = StrMaxLength(*psczKey, &cb); RegExitOnFailure(hr, "Failed to determine length of string."); + + cch = (DWORD)min(DWORD_MAX, cb); } if (2 > cch) @@ -462,6 +465,7 @@ extern "C" HRESULT DAPI RegReadString( { HRESULT hr = S_OK; DWORD er = ERROR_SUCCESS; + SIZE_T cbValue = 0; DWORD cch = 0; DWORD cb = 0; DWORD dwType = 0; @@ -469,8 +473,10 @@ extern "C" HRESULT DAPI RegReadString( if (psczValue && *psczValue) { - hr = StrMaxLength(*psczValue, reinterpret_cast(&cch)); + hr = StrMaxLength(*psczValue, &cbValue); RegExitOnFailure(hr, "Failed to determine length of string."); + + cch = (DWORD)min(DWORD_MAX, cbValue); } if (2 > cch) @@ -1000,18 +1006,18 @@ static HRESULT WriteStringToRegistry( __in_z_opt LPCWSTR wzName, __in_z_opt LPCWSTR wzValue, __in DWORD dwType -) + ) { HRESULT hr = S_OK; DWORD er = ERROR_SUCCESS; - DWORD cbValue = 0; + size_t cbValue = 0; if (wzValue) { - hr = ::StringCbLengthW(wzValue, STRSAFE_MAX_CCH * sizeof(TCHAR), reinterpret_cast(&cbValue)); + hr = ::StringCbLengthW(wzValue, STRSAFE_MAX_CCH * sizeof(TCHAR), &cbValue); RegExitOnFailure(hr, "Failed to determine length of registry value: %ls", wzName); - er = vpfnRegSetValueExW(hk, wzName, 0, dwType, reinterpret_cast(wzValue), cbValue); + er = vpfnRegSetValueExW(hk, wzName, 0, dwType, reinterpret_cast(wzValue), static_cast(cbValue)); RegExitOnWin32Error(er, hr, "Failed to set registry value: %ls", wzName); } else diff --git a/src/dutil/reswutil.cpp b/src/dutil/reswutil.cpp index 42b49c5..e78de84 100644 --- a/src/dutil/reswutil.cpp +++ b/src/dutil/reswutil.cpp @@ -288,13 +288,16 @@ static HRESULT StringBlockChangeString( { HRESULT hr = S_OK; LPWSTR pwzData = NULL; - DWORD cchData = lstrlenW(szData); + size_t cchData = 0; + + hr = ::StringCchLengthW(szData, STRSAFE_MAX_LENGTH, &cchData); + ReswExitOnRootFailure(hr, "Failed to get block string length."); pwzData = static_cast(MemAlloc((cchData + 1) * sizeof(WCHAR), TRUE)); ReswExitOnNull(pwzData, hr, E_OUTOFMEMORY, "Failed to allocate new block string."); hr = ::StringCchCopyW(pwzData, cchData + 1, szData); - ReswExitOnFailure(hr, "Failed to copy new block string."); + ReswExitOnRootFailure(hr, "Failed to copy new block string."); ReleaseNullMem(pStrBlock->rgwz[dwStringId]); diff --git a/src/dutil/strutil.cpp b/src/dutil/strutil.cpp index daa090c..550d616 100644 --- a/src/dutil/strutil.cpp +++ b/src/dutil/strutil.cpp @@ -46,7 +46,7 @@ static HRESULT AllocFormattedArgsHelper( static HRESULT StrAllocStringMapInvariant( __deref_out_z LPWSTR* pscz, __in_z LPCWSTR wzSource, - __in int cchSource, + __in SIZE_T cchSource, __in DWORD dwMapFlags ); @@ -146,7 +146,7 @@ HRESULT DAPI StrTrimCapacity( SIZE_T cchLen = 0; hr = ::StringCchLengthW(*ppwz, STRSAFE_MAX_CCH, reinterpret_cast(&cchLen)); - StrExitOnFailure(hr, "Failed to calculate length of string"); + StrExitOnRootFailure(hr, "Failed to calculate length of string"); ++cchLen; // Add 1 for null-terminator @@ -170,7 +170,7 @@ HRESULT DAPI StrTrimWhitespace( ) { HRESULT hr = S_OK; - int i = 0; + size_t i = 0; LPWSTR sczResult = NULL; // Ignore beginning whitespace @@ -179,7 +179,9 @@ HRESULT DAPI StrTrimWhitespace( wzSource++; } - i = lstrlenW(wzSource); + hr = ::StringCchLengthW(wzSource, STRSAFE_MAX_CCH, &i); + StrExitOnRootFailure(hr, "Failed to get length of string"); + // Overwrite ending whitespace with null characters if (0 < i) { @@ -291,7 +293,7 @@ HRESULT DAPI StrAnsiTrimWhitespace( ) { HRESULT hr = S_OK; - int i = 0; + size_t i = 0; LPSTR sczResult = NULL; // Ignore beginning whitespace @@ -300,7 +302,9 @@ HRESULT DAPI StrAnsiTrimWhitespace( szSource++; } - i = lstrlen(szSource); + hr = ::StringCchLengthA(szSource, STRSAFE_MAX_CCH, &i); + StrExitOnRootFailure(hr, "Failed to get length of string"); + // Overwrite ending whitespace with null characters if (0 < i) { @@ -395,14 +399,15 @@ static HRESULT AllocStringHelper( cch /= sizeof(WCHAR); //convert the count in bytes to count in characters } - if (0 == cchSource) + if (0 == cchSource && wzSource) { - cchSource = lstrlenW(wzSource); + hr = ::StringCchLengthW(wzSource, STRSAFE_MAX_CCH, reinterpret_cast(&cchSource)); + StrExitOnRootFailure(hr, "failed to get length of source string"); } SIZE_T cchNeeded; hr = ::ULongPtrAdd(cchSource, 1, &cchNeeded); // add one for the null terminator - StrExitOnFailure(hr, "source string is too long"); + StrExitOnRootFailure(hr, "source string is too long"); if (cch < cchNeeded) { @@ -604,19 +609,20 @@ HRESULT DAPI StrAnsiAllocStringAnsi( if (-1 == cch) { hr = E_INVALIDARG; - StrExitOnFailure(hr, "failed to get size of destination string"); + StrExitOnRootFailure(hr, "failed to get size of destination string"); } cch /= sizeof(CHAR); //convert the count in bytes to count in characters } - if (0 == cchSource) + if (0 == cchSource && szSource) { - cchSource = lstrlenA(szSource); + hr = ::StringCchLengthA(szSource, STRSAFE_MAX_CCH, reinterpret_cast(&cchSource)); + StrExitOnRootFailure(hr, "failed to get length of source string"); } SIZE_T cchNeeded; hr = ::ULongPtrAdd(cchSource, 1, &cchNeeded); // add one for the null terminator - StrExitOnFailure(hr, "source string is too long"); + StrExitOnRootFailure(hr, "source string is too long"); if (cch < cchNeeded) { @@ -1075,7 +1081,7 @@ static HRESULT AllocFormattedArgsHelper( SIZE_T cch = 0; LPWSTR pwzOriginal = NULL; SIZE_T cbOriginal = 0; - SIZE_T cchOriginal = 0; + size_t cchOriginal = 0; if (*ppwz) { @@ -1083,11 +1089,13 @@ static HRESULT AllocFormattedArgsHelper( if (-1 == cbOriginal) { hr = E_INVALIDARG; - StrExitOnFailure(hr, "failed to get size of destination string"); + StrExitOnRootFailure(hr, "failed to get size of destination string"); } cch = cbOriginal / sizeof(WCHAR); //convert the count in bytes to count in characters - cchOriginal = lstrlenW(*ppwz); + + hr = ::StringCchLengthW(*ppwz, STRSAFE_MAX_CCH, &cchOriginal); + StrExitOnRootFailure(hr, "failed to get length of original string"); } if (0 == cch) // if there is no space in the string buffer @@ -1124,7 +1132,7 @@ static HRESULT AllocFormattedArgsHelper( hr = S_FALSE; } } while (S_FALSE == hr); - StrExitOnFailure(hr, "failed to format string"); + StrExitOnRootFailure(hr, "failed to format string"); LExit: if (pwzOriginal && fZeroOnRealloc) @@ -1155,7 +1163,7 @@ extern "C" HRESULT DAPI StrAnsiAllocFormattedArgs( HRESULT hr = S_OK; SIZE_T cch = *ppsz ? MemSize(*ppsz) / sizeof(CHAR) : 0; LPSTR pszOriginal = NULL; - DWORD cchOriginal = 0; + size_t cchOriginal = 0; if (*ppsz) { @@ -1163,11 +1171,12 @@ extern "C" HRESULT DAPI StrAnsiAllocFormattedArgs( if (-1 == cch) { hr = E_INVALIDARG; - StrExitOnFailure(hr, "failed to get size of destination string"); + StrExitOnRootFailure(hr, "failed to get size of destination string"); } cch /= sizeof(CHAR); //convert the count in bytes to count in characters - cchOriginal = lstrlenA(*ppsz); + hr = ::StringCchLengthA(*ppsz, STRSAFE_MAX_CCH, &cchOriginal); + StrExitOnRootFailure(hr, "failed to get length of original string"); } if (0 == cch) // if there is no space in the string buffer @@ -1202,7 +1211,7 @@ extern "C" HRESULT DAPI StrAnsiAllocFormattedArgs( hr = S_FALSE; } } while (S_FALSE == hr); - StrExitOnFailure(hr, "failed to format string"); + StrExitOnRootFailure(hr, "failed to format string"); LExit: ReleaseStr(pszOriginal); @@ -1375,6 +1384,8 @@ extern "C" HRESULT DAPI StrReplaceString( HRESULT hr = S_FALSE; LPCWSTR wzSubLocation = NULL; LPWSTR pwzBuffer = NULL; + size_t cchOldSubString = 0; + size_t cchNewSubString = 0; if (!*ppwzOriginal) { @@ -1387,8 +1398,20 @@ extern "C" HRESULT DAPI StrReplaceString( ExitFunction(); } + if (wzOldSubString) + { + hr = ::StringCchLengthW(wzOldSubString, STRSAFE_MAX_CCH, &cchOldSubString); + StrExitOnRootFailure(hr, "Failed to get old string length."); + } + + if (wzNewSubString) + { + hr = ::StringCchLengthW(wzNewSubString, STRSAFE_MAX_CCH, &cchNewSubString); + StrExitOnRootFailure(hr, "Failed to get new string length."); + } + hr = ::PtrdiffTToDWord(wzSubLocation - *ppwzOriginal, pdwStartIndex); - StrExitOnFailure(hr, "Failed to diff pointers."); + StrExitOnRootFailure(hr, "Failed to diff pointers."); hr = StrAllocString(&pwzBuffer, *ppwzOriginal, wzSubLocation - *ppwzOriginal); StrExitOnFailure(hr, "Failed to duplicate string."); @@ -1398,14 +1421,14 @@ extern "C" HRESULT DAPI StrReplaceString( hr = StrAllocConcat(&pwzBuffer, wzNewSubString, 0); StrExitOnFailure(hr, "Failed to append new string."); - hr = StrAllocConcat(&pwzBuffer, wzSubLocation + wcslen(wzOldSubString), 0); + hr = StrAllocConcat(&pwzBuffer, wzSubLocation + cchOldSubString, 0); StrExitOnFailure(hr, "Failed to append post string."); hr = StrFree(*ppwzOriginal); StrExitOnFailure(hr, "Failed to free original string."); *ppwzOriginal = pwzBuffer; - *pdwStartIndex = *pdwStartIndex + static_cast(wcslen(wzNewSubString)); + *pdwStartIndex = *pdwStartIndex + static_cast(cchNewSubString); hr = S_OK; LExit: @@ -1516,15 +1539,18 @@ extern "C" HRESULT DAPI StrHexDecode( Assert(wzSource && pbDest); HRESULT hr = S_OK; - DWORD cchSource = lstrlenW(wzSource); - DWORD i; - BYTE b; + size_t cchSource = 0; + size_t i = 0; + BYTE b = 0; + + hr = ::StringCchLengthW(wzSource, STRSAFE_MAX_CCH, &cchSource); + StrExitOnRootFailure(hr, "Failed to get length of hex string: %ls", wzSource); Assert(0 == cchSource % 2); if (cbDest < cchSource / 2) { hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - StrExitOnRootFailure(hr, "Insufficient buffer to decode string '%ls' len: %u into %u bytes.", wzSource, cchSource, cbDest); + StrExitOnRootFailure(hr, "Insufficient buffer to decode string '%ls' len: %Iu into %Iu bytes.", wzSource, cchSource, cbDest); } for (i = 0; i < cchSource / 2; ++i) @@ -1728,17 +1754,20 @@ extern "C" HRESULT DAPI StrAllocBase85Decode( ) { HRESULT hr = S_OK; - SIZE_T cchSource = lstrlenW(wzSource); + size_t cchSource = 0; DWORD_PTR i, n, k; - BYTE* pbDest; - SIZE_T cbDest; + BYTE* pbDest = 0; + SIZE_T cbDest = 0; if (!wzSource || !ppbDest || !pcbDest) { - return E_INVALIDARG; + ExitFunction1(hr = E_INVALIDARG); } + hr = ::StringCchLengthW(wzSource, STRSAFE_MAX_CCH, &cchSource); + StrExitOnRootFailure(hr, "failed to get length of base 85 string: %ls", wzSource); + // evaluate size of output and check it k = cchSource / 5; cbDest = k << 2; @@ -1932,7 +1961,8 @@ extern "C" HRESULT DAPI MultiSzPrepend( StrExitOnFailure(hr, "failed to get length of multisz"); } - cchInsert = lstrlenW(pwzInsert); + hr = ::StringCchLengthW(pwzInsert, STRSAFE_MAX_CCH, reinterpret_cast(&cchInsert)); + StrExitOnRootFailure(hr, "failed to get length of insert string"); cchResult = cchInsert + cchMultiSz + 1; @@ -1942,7 +1972,7 @@ extern "C" HRESULT DAPI MultiSzPrepend( // Prepend hr = ::StringCchCopyW(pwzResult, cchResult, pwzInsert); - StrExitOnFailure(hr, "failed to copy prepend string: %ls", pwzInsert); + StrExitOnRootFailure(hr, "failed to copy prepend string: %ls", pwzInsert); // If there was no MULTISZ, double null terminate our result, otherwise, copy the MULTISZ in if (0 == cchMultiSz) @@ -2207,9 +2237,12 @@ extern "C" HRESULT DAPI MultiSzInsertString( SIZE_T cchProgress = 0; LPWSTR pwzResult = NULL; SIZE_T cchResult = 0; - SIZE_T cchString = lstrlenW(pwzInsert); + SIZE_T cchString = 0; SIZE_T cchMultiSz = 0; + hr = ::StringCchLengthW(pwzInsert, STRSAFE_MAX_CCH, reinterpret_cast(&cchString)); + StrExitOnRootFailure(hr, "failed to get length of insert string"); + if (pcchMultiSz && 0 != *pcchMultiSz) { cchMultiSz = *pcchMultiSz; @@ -2464,11 +2497,15 @@ extern "C" HRESULT DAPI StrStringToInt64( INT iSign = 1; INT nDigit = 0; LARGE_INTEGER liValue = { }; + size_t cchString = 0; // get string length if not provided if (0 >= cchIn) { - cchIn = lstrlenW(wzIn); + hr = ::StringCchLengthW(wzIn, STRSAFE_MAX_CCH, &cchString); + StrExitOnRootFailure(hr, "Failed to get length of string."); + + cchIn = (DWORD)cchString; if (0 >= cchIn) { ExitFunction1(hr = E_INVALIDARG); @@ -2524,11 +2561,15 @@ extern "C" HRESULT DAPI StrStringToUInt64( DWORD nDigit = 0; ULONGLONG ullValue = 0; ULONGLONG ull = 0; + size_t cchString = 0; // get string length if not provided if (0 >= cchIn) { - cchIn = lstrlenW(wzIn); + hr = ::StringCchLengthW(wzIn, STRSAFE_MAX_CCH, &cchString); + StrExitOnRootFailure(hr, "Failed to get length of string."); + + cchIn = (DWORD)cchString; if (0 >= cchIn) { ExitFunction1(hr = E_INVALIDARG); @@ -2588,7 +2629,7 @@ StrAllocStringToUpperInvariant - creates an upper-case copy of a string. extern "C" HRESULT DAPI StrAllocStringToUpperInvariant( __deref_out_z LPWSTR* pscz, __in_z LPCWSTR wzSource, - __in int cchSource + __in SIZE_T cchSource ) { return StrAllocStringMapInvariant(pscz, wzSource, cchSource, LCMAP_UPPERCASE); @@ -2601,7 +2642,7 @@ StrAllocStringToLowerInvariant - creates an lower-case copy of a string. extern "C" HRESULT DAPI StrAllocStringToLowerInvariant( __deref_out_z LPWSTR* pscz, __in_z LPCWSTR wzSource, - __in int cchSource + __in SIZE_T cchSource ) { return StrAllocStringMapInvariant(pscz, wzSource, cchSource, LCMAP_LOWERCASE); @@ -2704,7 +2745,7 @@ Note: Assumes source and destination buffers will be the same. static HRESULT StrAllocStringMapInvariant( __deref_out_z LPWSTR* pscz, __in_z LPCWSTR wzSource, - __in int cchSource, + __in SIZE_T cchSource, __in DWORD dwMapFlags ) { @@ -2718,11 +2759,15 @@ static HRESULT StrAllocStringMapInvariant( // Need the actual string size for LCMapString. This includes the null-terminator // but LCMapString doesn't care either way. hr = ::StringCchLengthW(*pscz, INT_MAX, reinterpret_cast(&cchSource)); - StrExitOnFailure(hr, "Failed to get the length of the string."); + StrExitOnRootFailure(hr, "Failed to get the length of the string."); + } + else if (INT_MAX < cchSource) + { + StrExitOnRootFailure(hr = E_INVALIDARG, "Source string is too long: %Iu", cchSource); } // Convert the copy of the string to upper or lower case in-place. - if (0 == ::LCMapStringW(LOCALE_INVARIANT, dwMapFlags, *pscz, cchSource, *pscz, cchSource)) + if (0 == ::LCMapStringW(LOCALE_INVARIANT, dwMapFlags, *pscz, static_cast(cchSource), *pscz, static_cast(cchSource))) { StrExitWithLastError(hr, "Failed to convert the string case."); } diff --git a/src/dutil/thmutil.cpp b/src/dutil/thmutil.cpp index d87e997..d200a0e 100644 --- a/src/dutil/thmutil.cpp +++ b/src/dutil/thmutil.cpp @@ -1519,13 +1519,16 @@ DAPI_(HRESULT) ThemeGetTextControl( { HRESULT hr = S_OK; HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); + SIZE_T cbSize = 0; DWORD cchText = 0; DWORD cchTextRead = 0; // Ensure the string has room for at least one character. - hr = StrMaxLength(*psczText, reinterpret_cast(&cchText)); + hr = StrMaxLength(*psczText, &cbSize); ThmExitOnFailure(hr, "Failed to get text buffer length."); + cchText = (DWORD)min(DWORD_MAX, cbSize); + if (!cchText) { cchText = GROW_WINDOW_TEXT; diff --git a/src/dutil/verutil.cpp b/src/dutil/verutil.cpp index fdb5a10..21626f9 100644 --- a/src/dutil/verutil.cpp +++ b/src/dutil/verutil.cpp @@ -244,7 +244,7 @@ DAPI_(void) VerFreeVersion( DAPI_(HRESULT) VerParseVersion( __in_z LPCWSTR wzVersion, - __in DWORD cchVersion, + __in SIZE_T cchVersion, __in BOOL fStrict, __out VERUTIL_VERSION** ppVersion ) @@ -267,9 +267,14 @@ DAPI_(HRESULT) VerParseVersion( } // Get string length if not provided. - if (0 == cchVersion) + if (!cchVersion) { - cchVersion = lstrlenW(wzVersion); + hr = ::StringCchLengthW(wzVersion, STRSAFE_MAX_CCH, reinterpret_cast(&cchVersion)); + VerExitOnRootFailure(hr, "Failed to get length of version string: %ls", wzVersion); + } + else if (INT_MAX < cchVersion) + { + VerExitOnRootFailure(hr = E_INVALIDARG, "Version string is too long: %Iu", cchVersion); } if (L'v' == *wzVersion || L'V' == *wzVersion) diff --git a/src/dutil/xmlutil.cpp b/src/dutil/xmlutil.cpp index 6ecd244..0f1e611 100644 --- a/src/dutil/xmlutil.cpp +++ b/src/dutil/xmlutil.cpp @@ -1305,7 +1305,7 @@ extern "C" HRESULT DAPI XmlSaveDocumentToBuffer( XmlExitOnFailure(hr, "Failed to get stream size."); // allocate buffer - pbDest = static_cast(MemAlloc((SIZE_T)statstg.cbSize.LowPart, TRUE)); + pbDest = static_cast(MemAlloc(statstg.cbSize.LowPart, TRUE)); XmlExitOnNull(pbDest, hr, E_OUTOFMEMORY, "Failed to allocate destination buffer."); // read data from stream diff --git a/src/test/DUtilUnitTest/FileUtilTest.cpp b/src/test/DUtilUnitTest/FileUtilTest.cpp index 0087a1d..ac071ef 100644 --- a/src/test/DUtilUnitTest/FileUtilTest.cpp +++ b/src/test/DUtilUnitTest/FileUtilTest.cpp @@ -50,7 +50,7 @@ namespace DutilTests } private: - void TestFile(LPWSTR wzDir, LPCWSTR wzTempDir, LPWSTR wzFileName, DWORD dwExpectedStringLength, FILE_ENCODING feExpectedEncoding) + void TestFile(LPWSTR wzDir, LPCWSTR wzTempDir, LPWSTR wzFileName, size_t cbExpectedStringLength, FILE_ENCODING feExpectedEncoding) { HRESULT hr = S_OK; LPWSTR sczFullPath = NULL; @@ -61,6 +61,7 @@ namespace DutilTests DWORD cbFile1 = 0; BYTE *pbFile2 = NULL; DWORD cbFile2 = 0; + size_t cbActualStringLength = 0; try { @@ -77,10 +78,13 @@ namespace DutilTests NativeAssert::Succeeded(hr, "FileToString() returned NULL for file: {0}", sczFullPath); } - if ((DWORD)lstrlenW(sczContents) != dwExpectedStringLength) + hr = ::StringCchLengthW(sczContents, STRSAFE_MAX_CCH, &cbActualStringLength); + NativeAssert::Succeeded(hr, "Failed to get length of text from file: {0}", sczFullPath); + + if (cbActualStringLength != cbExpectedStringLength) { hr = E_FAIL; - ExitOnFailure(hr, "FileToString() returned wrong size for file: %ls (expected size %u, found size %u)", sczFullPath, dwExpectedStringLength, lstrlenW(sczContents)); + ExitOnFailure(hr, "FileToString() returned wrong size for file: %ls (expected size %Iu, found size %Iu)", sczFullPath, cbExpectedStringLength, cbActualStringLength); } if (feEncodingFound != feExpectedEncoding)