From 859021f1661333340601c4b27808c44a3d055b23 Mon Sep 17 00:00:00 2001 From: Stephen Griffin Date: Sun, 25 Oct 2026 14:43:42 -0400 Subject: [PATCH 1/3] Remove first-party DevSkim banned C function findings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- MrMapi/MMAccounts.cpp | 22 +- MrMapi/MMEntryID.cpp | 4 +- MrMapi/MMErr.cpp | 12 +- MrMapi/MMFidMid.cpp | 4 +- MrMapi/MMFolder.cpp | 26 +- MrMapi/MMMapiMime.cpp | 62 +-- MrMapi/MMNamedProps.cpp | 8 +- MrMapi/MMProfile.cpp | 26 +- MrMapi/MMPropTag.cpp | 100 ++--- MrMapi/MMPst.cpp | 80 ++-- MrMapi/MMReceiveFolder.cpp | 10 +- MrMapi/MMSmartView.cpp | 6 +- MrMapi/MMStore.cpp | 22 +- MrMapi/MrMAPI.cpp | 24 +- MrMapi/mmcli.cpp | 537 ++++++++++++----------- UI/Dialogs/Editors/Editor.h | 2 +- core/mapi/processor/dumpStore.cpp | 10 +- core/smartview/AdditionalRenEntryIDs.cpp | 2 +- core/smartview/ExtendedFlags.cpp | 2 +- core/smartview/PCL.cpp | 2 +- core/smartview/WebViewPersistStream.cpp | 2 +- core/smartview/block/binaryParser.h | 2 +- core/utility/output.cpp | 2 +- core/utility/output.h | 8 +- core/utility/strings.h | 4 +- fuzz/fuzz.cpp | 10 +- 26 files changed, 497 insertions(+), 492 deletions(-) diff --git a/MrMapi/MMAccounts.cpp b/MrMapi/MMAccounts.cpp index 78ba1a8aa..2267f4226 100644 --- a/MrMapi/MMAccounts.cpp +++ b/MrMapi/MMAccounts.cpp @@ -16,7 +16,7 @@ void LogProp(LPOLKACCOUNT lpAccount, ULONG ulPropTag) const auto name = proptags::PropTagToPropName(ulPropTag, false).bestGuess; const auto tag = proptype::TypeToString(PROP_TYPE(ulPropTag)); - wprintf( + wprintf_s( L"Prop = %ws, Type = %ws, ", name.empty() ? strings::format(L"0x%08X", ulPropTag).c_str() : name.c_str(), tag.c_str()); @@ -25,20 +25,20 @@ void LogProp(LPOLKACCOUNT lpAccount, ULONG ulPropTag) case PT_UNICODE: if (pProp.Val.pwsz) { - wprintf(L"\"%ws\"", pProp.Val.pwsz); + wprintf_s(L"\"%ws\"", pProp.Val.pwsz); WC_H_S(lpAccount->FreeMemory(reinterpret_cast(pProp.Val.pwsz))); } break; case PT_LONG: - wprintf(L"0x%08lX", pProp.Val.dw); + wprintf_s(L"0x%08lX", pProp.Val.dw); break; case PT_BINARY: - wprintf(L"%ws", strings::BinToHexString(pProp.Val.bin.pb, pProp.Val.bin.cb, true).c_str()); + wprintf_s(L"%ws", strings::BinToHexString(pProp.Val.bin.pb, pProp.Val.bin.cb, true).c_str()); WC_H_S(lpAccount->FreeMemory(pProp.Val.bin.pb)); break; } - wprintf(L"\n"); + wprintf_s(L"\n"); } } @@ -46,7 +46,7 @@ void IterateAllProps(LPOLKACCOUNT lpAccount) { if (!lpAccount) return; - wprintf(L"Iterating all properties\n"); + wprintf_s(L"Iterating all properties\n"); for (auto i = 0; i < 0x8000; i++) { @@ -55,7 +55,7 @@ void IterateAllProps(LPOLKACCOUNT lpAccount) LogProp(lpAccount, PROP_TAG(PT_BINARY, i)); } - wprintf(L"Done iterating all properties\n"); + wprintf_s(L"Done iterating all properties\n"); } void EnumerateAccounts( @@ -66,7 +66,7 @@ void EnumerateAccounts( { LPOLKENUM lpAcctEnum = nullptr; - wprintf(L"Category: %ws\n", szCat.c_str()); + wprintf_s(L"Category: %ws\n", szCat.c_str()); EC_H_S(lpAcctMgr->EnumerateAccounts(pclsidCategory, nullptr, OLK_ACCOUNT_NO_FLAGS, &lpAcctEnum)); if (lpAcctEnum) { @@ -78,8 +78,8 @@ void EnumerateAccounts( EC_H_S(lpAcctEnum->Reset()); for (DWORD i = 0; i < cAccounts; i++) { - if (i > 0) wprintf(L"\n"); - wprintf(L"Account #%lu\n", i + 1); + if (i > 0) wprintf_s(L"\n"); + wprintf_s(L"Account #%lu\n", i + 1); LPUNKNOWN lpUnk = nullptr; EC_H_S(lpAcctEnum->GetNext(&lpUnk)); @@ -149,7 +149,7 @@ void DoAccounts(_In_opt_ LPMAPISESSION lpMAPISession) const auto bWizard = cli::switchWizard.isSet(); const auto profileName = mapi::GetProfileName(lpMAPISession); - wprintf(L"Enum Accounts\n"); + wprintf_s(L"Enum Accounts\n"); if (!profileName.empty()) { diff --git a/MrMapi/MMEntryID.cpp b/MrMapi/MMEntryID.cpp index 6c8137cc1..ef0afa0c6 100644 --- a/MrMapi/MMEntryID.cpp +++ b/MrMapi/MMEntryID.cpp @@ -29,9 +29,9 @@ HRESULT DoEntryID(_In_opt_ LPMDB lpMDB) hRes = WC_H_GETPROPS(message->GetProps(&tags, fMapiUnicode, &count, &props)); if (SUCCEEDED(hRes) && props && count == 1) { - wprintf(L"%ws\n", output::g_szXMLHeader.c_str()); + wprintf_s(L"%ws\n", output::g_szXMLHeader.c_str()); output::outputProperties(output::dbgLevel::NoDebug, stdout, count, props, message, true); - wprintf(L"\n"); + wprintf_s(L"\n"); if (PROP_TYPE(props[0].ulPropTag) == PT_ERROR) hRes = props[0].Value.err; } else if (SUCCEEDED(hRes)) diff --git a/MrMapi/MMErr.cpp b/MrMapi/MMErr.cpp index 231b10c30..a230225ed 100644 --- a/MrMapi/MMErr.cpp +++ b/MrMapi/MMErr.cpp @@ -11,7 +11,7 @@ namespace error void PrintErrFromNum(_In_ ULONG ulError) { - wprintf(L"0x%08lX = %ws\n", ulError, error::ErrorNameFromErrorCode(ulError).c_str()); + wprintf_s(L"0x%08lX = %ws\n", ulError, error::ErrorNameFromErrorCode(ulError).c_str()); } void PrintErrFromName(_In_ const std::wstring& lpszError) noexcept @@ -22,7 +22,7 @@ void PrintErrFromName(_In_ const std::wstring& lpszError) noexcept { if (0 == lstrcmpiW(szErr, error::g_ErrorArray[i].lpszName)) { - wprintf(L"0x%08lX = %ws\n", error::g_ErrorArray[i].ulErrorName, szErr); + wprintf_s(L"0x%08lX = %ws\n", error::g_ErrorArray[i].ulErrorName, szErr); } } } @@ -30,9 +30,9 @@ void PrintErrFromName(_In_ const std::wstring& lpszError) noexcept void PrintErrFromPartialName(_In_ const std::wstring& lpszError) noexcept { if (!lpszError.empty()) - wprintf(L"Searching for \"%ws\"\n", lpszError.c_str()); + wprintf_s(L"Searching for \"%ws\"\n", lpszError.c_str()); else - wprintf(L"Searching for all errors\n"); + wprintf_s(L"Searching for all errors\n"); ULONG ulNumMatches = 0; @@ -40,12 +40,12 @@ void PrintErrFromPartialName(_In_ const std::wstring& lpszError) noexcept { if (lpszError.empty() || nullptr != StrStrIW(error::g_ErrorArray[ulCur].lpszName, lpszError.c_str())) { - wprintf(L"0x%08lX = %ws\n", error::g_ErrorArray[ulCur].ulErrorName, error::g_ErrorArray[ulCur].lpszName); + wprintf_s(L"0x%08lX = %ws\n", error::g_ErrorArray[ulCur].ulErrorName, error::g_ErrorArray[ulCur].lpszName); ulNumMatches++; } } - wprintf(L"Found %lu matches.\n", ulNumMatches); + wprintf_s(L"Found %lu matches.\n", ulNumMatches); } void DoErrorParse() diff --git a/MrMapi/MMFidMid.cpp b/MrMapi/MMFidMid.cpp index 1c1a16d73..ff27f01c2 100644 --- a/MrMapi/MMFidMid.cpp +++ b/MrMapi/MMFidMid.cpp @@ -13,7 +13,7 @@ namespace mapiprocessor { void PrintFolder(const std::wstring& szFid, const std::wstring& szFolder) noexcept { - wprintf(L"%-15ws %ws\n", szFid.c_str(), szFolder.c_str()); + wprintf_s(L"%-15ws %ws\n", szFid.c_str(), szFolder.c_str()); } void PrintMessage( @@ -22,7 +22,7 @@ namespace mapiprocessor const std::wstring& szSubject, const std::wstring& szClass) noexcept { - wprintf( + wprintf_s( L" %-15ws %wc %ws (%ws)\n", szMid.c_str(), fAssociated ? L'A' : L'R', szSubject.c_str(), szClass.c_str()); } diff --git a/MrMapi/MMFolder.cpp b/MrMapi/MMFolder.cpp index f81e76fbf..bc9f51b50 100644 --- a/MrMapi/MMFolder.cpp +++ b/MrMapi/MMFolder.cpp @@ -330,13 +330,13 @@ void DumpHierarchyTable( { for (ULONG iTab = 0; iTab < ulDepth; iTab++) { - wprintf(L" "); + wprintf_s(L" "); } } if (PR_DISPLAY_NAME_W == lpRow->aRow[i].lpProps[ePR_DISPLAY_NAME_W].ulPropTag) { - wprintf(L"%ws\n", lpRow->aRow[i].lpProps[ePR_DISPLAY_NAME_W].Value.lpszW); + wprintf_s(L"%ws\n", lpRow->aRow[i].lpProps[ePR_DISPLAY_NAME_W].Value.lpszW); } if (PR_ENTRYID == lpRow->aRow[i].lpProps[ePR_ENTRYID].ulPropTag) @@ -539,21 +539,21 @@ void DumpSearchState( const auto hRes = WC_H(lpFolder->GetSearchCriteria(fMapiUnicode, &lpRes, &lpEntryList, &ulSearchState)); if (MAPI_E_NOT_INITIALIZED == hRes) { - wprintf(L"No search criteria has been set on this folder.\n"); + wprintf_s(L"No search criteria has been set on this folder.\n"); } else if (MAPI_E_NO_SUPPORT == hRes) { - wprintf(L"This does not appear to be a search folder.\n"); + wprintf_s(L"This does not appear to be a search folder.\n"); } else if (SUCCEEDED(hRes)) { auto szFlags = flags::InterpretFlags(flagSearchState, ulSearchState); - wprintf(L"Search state %ws == 0x%08X\n", szFlags.c_str(), ulSearchState); - wprintf(L"\n"); - wprintf(L"Search Scope:\n"); + wprintf_s(L"Search state %ws == 0x%08X\n", szFlags.c_str(), ulSearchState); + wprintf_s(L"\n"); + wprintf_s(L"Search Scope:\n"); output::outputEntryList(output::dbgLevel::NoDebug, stdout, lpEntryList); - wprintf(L"\n"); - wprintf(L"Search Criteria:\n"); + wprintf_s(L"\n"); + wprintf_s(L"Search Criteria:\n"); output::outputRestriction(output::dbgLevel::NoDebug, stdout, lpRes, nullptr); } @@ -573,10 +573,10 @@ void DoFolderProps(_In_opt_ LPMAPIFOLDER lpFolder) void DoFolderSize(_In_opt_ LPMAPIFOLDER lpFolder) { const LONGLONG ullSize = ComputeFolderSize(cli::switchProfile[0], lpFolder, cli::switchFolder[0]); - wprintf(L"Folder size (including subfolders)\n"); - wprintf(L"Bytes: %I64d\n", ullSize); - wprintf(L"KB: %I64d\n", ullSize / 1024); - wprintf(L"MB: %I64d\n", ullSize / (1024 * 1024)); + wprintf_s(L"Folder size (including subfolders)\n"); + wprintf_s(L"Bytes: %I64d\n", ullSize); + wprintf_s(L"KB: %I64d\n", ullSize / 1024); + wprintf_s(L"MB: %I64d\n", ullSize / (1024 * 1024)); } void DoChildFolders(_In_opt_ LPMAPIFOLDER lpFolder) diff --git a/MrMapi/MMMapiMime.cpp b/MrMapi/MMMapiMime.cpp index f53183454..b750e019e 100644 --- a/MrMapi/MMMapiMime.cpp +++ b/MrMapi/MMMapiMime.cpp @@ -18,67 +18,67 @@ void DoMAPIMIME(_In_opt_ LPMAPISESSION lpMAPISession) const auto cSetType = static_cast(cli::switchCharset.atULONG(1)); const auto cSetApplyType = static_cast(cli::switchCharset.atULONG(2)); - wprintf(L"Message File Converter\n"); - wprintf(L"Options specified:\n"); - wprintf(L" Input File: %ws\n", input.c_str()); - wprintf(L" Output File: %ws\n", output.c_str()); - wprintf(L" Conversion Type: "); + wprintf_s(L"Message File Converter\n"); + wprintf_s(L"Options specified:\n"); + wprintf_s(L" Input File: %ws\n", input.c_str()); + wprintf_s(L" Output File: %ws\n", output.c_str()); + wprintf_s(L" Conversion Type: "); if (cli::switchMAPI.isSet()) { - wprintf(L"MAPI -> MIME\n"); + wprintf_s(L"MAPI -> MIME\n"); - wprintf(L" Save Format: %ws\n", cli::switchRFC822.isSet() ? L"RFC822" : L"RFC1521"); + wprintf_s(L" Save Format: %ws\n", cli::switchRFC822.isSet() ? L"RFC822" : L"RFC1521"); if (cli::switchWrap.isSet()) { - wprintf(L" Line Wrap: "); + wprintf_s(L" Line Wrap: "); if (ulWrapLines == 0) - wprintf(L"OFF\n"); + wprintf_s(L"OFF\n"); else - wprintf(L"%lu\n", ulWrapLines); + wprintf_s(L"%lu\n", ulWrapLines); } } else if (cli::switchMAPI.isSet()) { - wprintf(L"MIME -> MAPI\n"); + wprintf_s(L"MIME -> MAPI\n"); if (cli::switchUnicode.isSet()) { - wprintf(L" Building Unicode MSG file\n"); + wprintf_s(L" Building Unicode MSG file\n"); } if (cli::switchCharset.isSet()) { - wprintf(L" CodePage: %lu\n", ulCodePage); - wprintf(L" CharSetType: "); + wprintf_s(L" CodePage: %lu\n", ulCodePage); + wprintf_s(L" CharSetType: "); switch (cSetType) { case CHARSET_BODY: - wprintf(L"CHARSET_BODY"); + wprintf_s(L"CHARSET_BODY"); break; case CHARSET_HEADER: - wprintf(L"CHARSET_HEADER"); + wprintf_s(L"CHARSET_HEADER"); break; case CHARSET_WEB: - wprintf(L"CHARSET_WEB"); + wprintf_s(L"CHARSET_WEB"); break; } - wprintf(L"\n"); - wprintf(L" CharSetApplyType: "); + wprintf_s(L"\n"); + wprintf_s(L" CharSetApplyType: "); switch (cSetApplyType) { case CSET_APPLY_UNTAGGED: - wprintf(L"CSET_APPLY_UNTAGGED"); + wprintf_s(L"CSET_APPLY_UNTAGGED"); break; case CSET_APPLY_ALL: - wprintf(L"CSET_APPLY_ALL"); + wprintf_s(L"CSET_APPLY_ALL"); break; case CSET_APPLY_TAG_ALL: - wprintf(L"CSET_APPLY_TAG_ALL"); + wprintf_s(L"CSET_APPLY_TAG_ALL"); break; } - wprintf(L"\n"); + wprintf_s(L"\n"); } } @@ -87,7 +87,7 @@ void DoMAPIMIME(_In_opt_ LPMAPISESSION lpMAPISession) auto szFlags = flags::InterpretFlags(flagCcsf, convertFlags); if (!szFlags.empty()) { - wprintf(L" Conversion Flags: %ws\n", szFlags.c_str()); + wprintf_s(L" Conversion Flags: %ws\n", szFlags.c_str()); } } @@ -96,13 +96,13 @@ void DoMAPIMIME(_In_opt_ LPMAPISESSION lpMAPISession) auto szType = flags::InterpretFlags(flagIet, ulEncodingType); if (!szType.empty()) { - wprintf(L" Encoding Type: %ws\n", szType.c_str()); + wprintf_s(L" Encoding Type: %ws\n", szType.c_str()); } } if (cli::switchAddressBook.isSet()) { - wprintf(L" Using Address Book\n"); + wprintf_s(L" Using Address Book\n"); } auto hRes = S_OK; @@ -111,7 +111,7 @@ void DoMAPIMIME(_In_opt_ LPMAPISESSION lpMAPISession) if (cli::switchAddressBook.isSet() && lpMAPISession) { hRes = WC_MAPI(lpMAPISession->OpenAddressBook(NULL, nullptr, AB_NO_DIALOG, &lpAdrBook)); - if (FAILED(hRes)) wprintf(L"OpenAddressBook returned an error: 0x%08lx\n", hRes); + if (FAILED(hRes)) wprintf_s(L"OpenAddressBook returned an error: 0x%08lx\n", hRes); } if (cli::switchMIME.isSet()) @@ -135,7 +135,7 @@ void DoMAPIMIME(_In_opt_ LPMAPISESSION lpMAPISession) hRes = WC_H(import::MyMimeOleGetCodePageCharset(ulCodePage, cSetType, &hCharSet)); if (FAILED(hRes)) { - wprintf(L"MimeOleGetCodePageCharset returned 0x%08lX\n", hRes); + wprintf_s(L"MimeOleGetCodePageCharset returned 0x%08lX\n", hRes); } } @@ -155,15 +155,15 @@ void DoMAPIMIME(_In_opt_ LPMAPISESSION lpMAPISession) if (SUCCEEDED(hRes)) { - wprintf(L"File converted successfully.\n"); + wprintf_s(L"File converted successfully.\n"); } else if (REGDB_E_CLASSNOTREG == hRes) { - wprintf(L"MAPI <-> MIME converter not found. Perhaps Outlook is not installed.\n"); + wprintf_s(L"MAPI <-> MIME converter not found. Perhaps Outlook is not installed.\n"); } else { - wprintf(L"Conversion returned an error: 0x%08lx\n", hRes); + wprintf_s(L"Conversion returned an error: 0x%08lx\n", hRes); } if (lpAdrBook) lpAdrBook->Release(); diff --git a/MrMapi/MMNamedProps.cpp b/MrMapi/MMNamedProps.cpp index 3a7241ff3..089326d3f 100644 --- a/MrMapi/MMNamedProps.cpp +++ b/MrMapi/MMNamedProps.cpp @@ -24,7 +24,7 @@ void WriteOutput(_In_opt_ FILE* fOut, _Printf_format_string_ LPCWSTR szMsg, Argu } else { - wprintf(L"%ws", szString.c_str()); + wprintf_s(L"%ws", szString.c_str()); } } @@ -175,12 +175,12 @@ void DoNamedProps(_In_opt_ LPMAPISESSION lpSession, _In_opt_ LPMDB lpMDB) fOut = output::MyOpenFileMode(output, L"wb"); if (!fOut) { - wprintf(L"Cannot open output file %ws\n", output.c_str()); + wprintf_s(L"Cannot open output file %ws\n", output.c_str()); return exit(-1); } } - wprintf(L"Dumping named properties...\n\n"); + wprintf_s(L"Dumping named properties...\n\n"); // Print the name of the profile and the parsed store entry-id so we can tell which mailbox this is const auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); @@ -245,6 +245,6 @@ void DoNamedProps(_In_opt_ LPMAPISESSION lpSession, _In_opt_ LPMDB lpMDB) cache::NamedPropertyToString(*name->getMapiNameId()).c_str()); } - wprintf(L"Completed.\n"); + wprintf_s(L"Completed.\n"); if (fOut) fclose(fOut); } \ No newline at end of file diff --git a/MrMapi/MMProfile.cpp b/MrMapi/MMProfile.cpp index be39b446f..86717543a 100644 --- a/MrMapi/MMProfile.cpp +++ b/MrMapi/MMProfile.cpp @@ -8,8 +8,8 @@ namespace output { void ExportProfileList() { - wprintf(L"Profile List\n"); - wprintf(L" # Default Name\n"); + wprintf_s(L"Profile List\n"); + wprintf_s(L" # Default Name\n"); LPMAPITABLE lpProfTable = nullptr; LPPROFADMIN lpProfAdmin = nullptr; @@ -36,30 +36,30 @@ namespace output { if (lpRows->cRows == 0) { - wprintf(L"No profiles exist\n"); + wprintf_s(L"No profiles exist\n"); } else { for (ULONG i = 0; i < lpRows->cRows; i++) { - wprintf(L"%2ul ", i); + wprintf_s(L"%2ul ", i); if (PR_DEFAULT_PROFILE == lpRows->aRow[i].lpProps[0].ulPropTag && lpRows->aRow[i].lpProps[0].Value.b) { - wprintf(L"* "); + wprintf_s(L"* "); } else { - wprintf(L" "); + wprintf_s(L" "); } if (strings::CheckStringProp(&lpRows->aRow[i].lpProps[1], PT_STRING8)) { - wprintf(L"%hs\n", lpRows->aRow[i].lpProps[1].Value.lpszA); + wprintf_s(L"%hs\n", lpRows->aRow[i].lpProps[1].Value.lpszA); } else { - wprintf(L"UNKNOWN\n"); + wprintf_s(L"UNKNOWN\n"); } } } @@ -80,11 +80,11 @@ namespace output { const auto szProfile = cli::switchProfile[0]; const auto szProfileSection = cli::switchProfileSection[0]; - wprintf(L"Profile Export\n"); - wprintf(L"Options specified:\n"); - wprintf(L" Profile: %ws\n", szProfile.c_str()); - wprintf(L" Profile section: %ws\n", szProfileSection.c_str()); - wprintf(L" Output File: %ws\n", output.c_str()); + wprintf_s(L"Profile Export\n"); + wprintf_s(L"Options specified:\n"); + wprintf_s(L" Profile: %ws\n", szProfile.c_str()); + wprintf_s(L" Profile section: %ws\n", szProfileSection.c_str()); + wprintf_s(L" Output File: %ws\n", output.c_str()); ExportProfile(szProfile, szProfileSection, cli::switchByteSwapped.isSet(), output); } else diff --git a/MrMapi/MMPropTag.cpp b/MrMapi/MMPropTag.cpp index 28accdd87..16deed1b0 100644 --- a/MrMapi/MMPropTag.cpp +++ b/MrMapi/MMPropTag.cpp @@ -30,35 +30,35 @@ void PrintType(_In_ ULONG ulPropTag) noexcept if (PROP_TYPE(ulPropTag) == propType.ulValue) { bFound = true; - wprintf(L"%ws", propType.lpszName); + wprintf_s(L"%ws", propType.lpszName); break; } } - if (!bFound) wprintf(L"0x%04lX = Unknown type", PROP_TYPE(ulPropTag)); + if (!bFound) wprintf_s(L"0x%04lX = Unknown type", PROP_TYPE(ulPropTag)); - if (bNeedInstance) wprintf(L" | MV_INSTANCE"); + if (bNeedInstance) wprintf_s(L" | MV_INSTANCE"); } void PrintKnownTypes() noexcept { // Do a linear search through PropTypeArray - ulPropTypeArray will be small - wprintf(L"%-18s%-9s%ws\n", L"Type", L"Hex", L"Decimal"); + wprintf_s(L"%-18s%-9s%ws\n", L"Type", L"Hex", L"Decimal"); for (const auto& propType : PropTypeArray) { - wprintf(L"%-15ws = 0x%04lX = %lu\n", propType.lpszName, propType.ulValue, propType.ulValue); + wprintf_s(L"%-15ws = 0x%04lX = %lu\n", propType.lpszName, propType.ulValue, propType.ulValue); } - wprintf(L"\n"); - wprintf(L"Types may also have the flag 0x%04X = %ws\n", MV_INSTANCE, L"MV_INSTANCE"); + wprintf_s(L"\n"); + wprintf_s(L"Types may also have the flag 0x%04X = %ws\n", MV_INSTANCE, L"MV_INSTANCE"); } // Print the tag found in the array at ulRow void PrintTag(_In_ ULONG ulRow) noexcept { - wprintf(L"0x%08lX,%ws,", PropTagArray[ulRow].ulValue, PropTagArray[ulRow].lpszName); + wprintf_s(L"0x%08lX,%ws,", PropTagArray[ulRow].ulValue, PropTagArray[ulRow].lpszName); PrintType(PropTagArray[ulRow].ulValue); - wprintf(L"\n"); + wprintf_s(L"\n"); } // Given a property tag, output the matching names and partially matching names @@ -88,12 +88,12 @@ void PrintTagFromNum(_In_ ULONG ulPropTag) ulPropID = ulPropTag; } - wprintf(L"Property tag 0x%08lX:\n", ulPropTag); + wprintf_s(L"Property tag 0x%08lX:\n", ulPropTag); if (ulPropID & 0x8000) { - wprintf(L"Since this property ID is greater than 0x8000 there is a good chance it is a named property.\n"); - wprintf(L"Only trust the following output if this property is known to be an address book property.\n"); + wprintf_s(L"Since this property ID is greater than 0x8000 there is a good chance it is a named property.\n"); + wprintf_s(L"Only trust the following output if this property is known to be an address book property.\n"); } std::vector ulExacts; @@ -102,7 +102,7 @@ void PrintTagFromNum(_In_ ULONG ulPropTag) if (!ulExacts.empty()) { - wprintf(L"\nExact matches:\n"); + wprintf_s(L"\nExact matches:\n"); for (const auto& ulCur : ulExacts) { PrintTag(ulCur); @@ -111,7 +111,7 @@ void PrintTagFromNum(_In_ ULONG ulPropTag) if (!ulPartials.empty()) { - wprintf(L"\nPartial matches:\n"); + wprintf_s(L"\nPartial matches:\n"); // let's print our partial matches for (const auto& ulCur : ulPartials) { @@ -127,9 +127,9 @@ void PrintTagFromName(_In_z_ LPCWSTR lpszPropName, _In_ ULONG ulType) if (cache::ulNoMatch != ulType) { - wprintf(L"Restricting output to "); + wprintf_s(L"Restricting output to "); PrintType(ulType); - wprintf(L"\n"); + wprintf_s(L"\n"); } auto bMatchFound = false; @@ -155,7 +155,7 @@ void PrintTagFromName(_In_z_ LPCWSTR lpszPropName, _In_ ULONG ulType) { if (cache::ulNoMatch == ulType) { - wprintf(L"\nOther exact matches:\n"); + wprintf_s(L"\nOther exact matches:\n"); } for (const auto& ulMatch : ulExacts) @@ -170,7 +170,7 @@ void PrintTagFromName(_In_z_ LPCWSTR lpszPropName, _In_ ULONG ulType) { if (cache::ulNoMatch == ulType) { - wprintf(L"\nOther partial matches:\n"); + wprintf_s(L"\nOther partial matches:\n"); } for (const auto& ulMatch : ulPartials) @@ -187,7 +187,7 @@ void PrintTagFromName(_In_z_ LPCWSTR lpszPropName, _In_ ULONG ulType) } } - if (!bMatchFound) wprintf(L"Property tag \"%ws\" not found\n", lpszPropName); + if (!bMatchFound) wprintf_s(L"Property tag \"%ws\" not found\n", lpszPropName); } // Search for properties matching lpszPropName on a substring @@ -195,15 +195,15 @@ void PrintTagFromName(_In_z_ LPCWSTR lpszPropName, _In_ ULONG ulType) void PrintTagFromPartialName(_In_opt_z_ LPCWSTR lpszPropName, _In_ ULONG ulType) noexcept { if (lpszPropName) - wprintf(L"Searching for \"%ws\"\n", lpszPropName); + wprintf_s(L"Searching for \"%ws\"\n", lpszPropName); else - wprintf(L"Searching for all properties\n"); + wprintf_s(L"Searching for all properties\n"); if (cache::ulNoMatch != ulType) { - wprintf(L"Restricting output to "); + wprintf_s(L"Restricting output to "); PrintType(ulType); - wprintf(L"\n"); + wprintf_s(L"\n"); } ULONG ulNumMatches = 0; @@ -218,7 +218,7 @@ void PrintTagFromPartialName(_In_opt_z_ LPCWSTR lpszPropName, _In_ ULONG ulType) } } - wprintf(L"Found %lu matches.\n", ulNumMatches); + wprintf_s(L"Found %lu matches.\n", ulNumMatches); } void PrintGUID(_In_ LPCGUID lpGUID) noexcept @@ -226,11 +226,11 @@ void PrintGUID(_In_ LPCGUID lpGUID) noexcept // PSUNKNOWN isn't a real guid - just a placeholder - don't print it if (!lpGUID || IsEqualGUID(*lpGUID, guid::PSUNKNOWN)) { - wprintf(L","); + wprintf_s(L","); return; } - wprintf( + wprintf_s( L"{%.8lX-%.4X-%.4X-%.2X%.2X-%.2X%.2X%.2X%.2X%.2X%.2X}", lpGUID->Data1, lpGUID->Data2, @@ -244,12 +244,12 @@ void PrintGUID(_In_ LPCGUID lpGUID) noexcept lpGUID->Data4[6], lpGUID->Data4[7]); - wprintf(L","); + wprintf_s(L","); for (const auto& guid : PropGuidArray) { if (IsEqualGUID(*lpGUID, *guid.lpGuid)) { - wprintf(L"%ws", guid.lpszName); + wprintf_s(L"%ws", guid.lpszName); break; } } @@ -259,7 +259,7 @@ void PrintGUIDs() noexcept { for (const auto& guid : PropGuidArray) { - wprintf( + wprintf_s( L"{%.8lX-%.4X-%.4X-%.2X%.2X-%.2X%.2X%.2X%.2X%.2X%.2X}", guid.lpGuid->Data1, guid.lpGuid->Data2, @@ -272,27 +272,27 @@ void PrintGUIDs() noexcept guid.lpGuid->Data4[5], guid.lpGuid->Data4[6], guid.lpGuid->Data4[7]); - wprintf(L",%ws\n", guid.lpszName); + wprintf_s(L",%ws\n", guid.lpszName); } } void PrintDispID(_In_ ULONG ulRow) noexcept { - wprintf(L"0x%04lX,%ws,", NameIDArray[ulRow].lValue, NameIDArray[ulRow].lpszName); + wprintf_s(L"0x%04lX,%ws,", NameIDArray[ulRow].lValue, NameIDArray[ulRow].lpszName); PrintGUID(NameIDArray[ulRow].lpGuid); - wprintf(L","); + wprintf_s(L","); if (PT_UNSPECIFIED != NameIDArray[ulRow].ulType) { PrintType(PROP_TAG(NameIDArray[ulRow].ulType, 0)); } - wprintf(L","); + wprintf_s(L","); if (NameIDArray[ulRow].lpszArea) { - wprintf(L"%ws", NameIDArray[ulRow].lpszArea); + wprintf_s(L"%ws", NameIDArray[ulRow].lpszArea); } - wprintf(L"\n"); + wprintf_s(L"\n"); } void PrintDispIDFromNum(_In_ ULONG ulDispID) noexcept @@ -300,13 +300,13 @@ void PrintDispIDFromNum(_In_ ULONG ulDispID) noexcept ULONG ulNumExacts = NULL; ULONG ulFirstExactMatch = cache::ulNoMatch; - wprintf(L"Dispid tag 0x%04lX:\n", ulDispID); + wprintf_s(L"Dispid tag 0x%04lX:\n", ulDispID); cache::FindNameIDArrayMatches(ulDispID, &ulNumExacts, &ulFirstExactMatch); if (ulNumExacts > 0 && cache::ulNoMatch != ulFirstExactMatch) { - wprintf(L"\nExact matches:\n"); + wprintf_s(L"\nExact matches:\n"); for (auto ulCur = ulFirstExactMatch; ulCur < ulFirstExactMatch + ulNumExacts; ulCur++) { PrintDispID(ulCur); @@ -336,7 +336,7 @@ void PrintDispIDFromName(_In_opt_z_ LPCWSTR lpszDispIDName) noexcept // We're gonna skip at least one, so only print if we have more than one if (ulNumExacts > 1) { - wprintf(L"\nOther exact matches:\n"); + wprintf_s(L"\nOther exact matches:\n"); for (ulCur = ulFirstExactMatch; ulCur < ulFirstExactMatch + ulNumExacts; ulCur++) { if (ulExactMatch == ulCur) continue; // skip this one @@ -349,16 +349,16 @@ void PrintDispIDFromName(_In_opt_z_ LPCWSTR lpszDispIDName) noexcept } } - if (!bMatchFound) wprintf(L"Property tag \"%ws\" not found\n", lpszDispIDName); + if (!bMatchFound) wprintf_s(L"Property tag \"%ws\" not found\n", lpszDispIDName); } // Search for properties matching lpszPropName on a substring void PrintDispIDFromPartialName(_In_opt_z_ LPCWSTR lpszDispIDName, _In_ ULONG ulType) noexcept { if (lpszDispIDName) - wprintf(L"Searching for \"%ws\"\n", lpszDispIDName); + wprintf_s(L"Searching for \"%ws\"\n", lpszDispIDName); else - wprintf(L"Searching for all properties\n"); + wprintf_s(L"Searching for all properties\n"); ULONG ulNumMatches = 0; @@ -372,7 +372,7 @@ void PrintDispIDFromPartialName(_In_opt_z_ LPCWSTR lpszDispIDName, _In_ ULONG ul } } - wprintf(L"Found %lu matches.\n", ulNumMatches); + wprintf_s(L"Found %lu matches.\n", ulNumMatches); } void PrintFlag(_In_ ULONG ulPropNum, _In_opt_z_ LPCWSTR lpszPropName, _In_ bool bIsDispid, _In_ ULONG ulFlagValue) @@ -408,9 +408,9 @@ void PrintFlag(_In_ ULONG ulPropNum, _In_opt_z_ LPCWSTR lpszPropName, _In_ bool if (ulCur != NameIDArray.size()) { - wprintf(L"Found named property %ws (0x%04lX) ", NameIDArray[ulCur].lpszName, NameIDArray[ulCur].lValue); + wprintf_s(L"Found named property %ws (0x%04lX) ", NameIDArray[ulCur].lpszName, NameIDArray[ulCur].lValue); PrintGUID(NameIDArray[ulCur].lpGuid); - wprintf(L".\n"); + wprintf_s(L".\n"); szFlags = smartview::InterpretNumberAsStringNamedProp( ulFlagValue, NameIDArray[ulCur].lValue, NameIDArray[ulCur].lpGuid); } @@ -440,18 +440,18 @@ void PrintFlag(_In_ ULONG ulPropNum, _In_opt_z_ LPCWSTR lpszPropName, _In_ bool if (ulCur != PropTagArray.size()) { - wprintf(L"Found property %ws (0x%08lX).\n", PropTagArray[ulCur].lpszName, PropTagArray[ulCur].ulValue); + wprintf_s(L"Found property %ws (0x%08lX).\n", PropTagArray[ulCur].lpszName, PropTagArray[ulCur].ulValue); szFlags = smartview::InterpretNumberAsStringProp(ulFlagValue, PropTagArray[ulCur].ulValue); } } if (!szFlags.empty()) { - wprintf(L"0x%08lX = %ws\n", ulFlagValue, szFlags.c_str()); + wprintf_s(L"0x%08lX = %ws\n", ulFlagValue, szFlags.c_str()); } else { - wprintf(L"No flag parsing found.\n"); + wprintf_s(L"No flag parsing found.\n"); } } @@ -507,8 +507,8 @@ void DoPropTags() if (cache::ulNoMatch != ulTypeNum) { PrintType(PROP_TAG(ulTypeNum, 0)); - wprintf(L" = 0x%04lX = %lu", ulTypeNum, ulTypeNum); - wprintf(L"\n"); + wprintf_s(L" = 0x%04lX = %lu", ulTypeNum, ulTypeNum); + wprintf_s(L"\n"); } else { @@ -530,7 +530,7 @@ void DoFlagSearch() noexcept { if (strings::compareInsensitive(flag.lpszName, lpszFlagName)) { - wprintf(L"%ws = 0x%08lX\n", flag.lpszName, flag.lFlagValue); + wprintf_s(L"%ws = 0x%08lX\n", flag.lpszName, flag.lFlagValue); break; } } diff --git a/MrMapi/MMPst.cpp b/MrMapi/MMPst.cpp index 19e9ab8bb..0a67e1b36 100644 --- a/MrMapi/MMPst.cpp +++ b/MrMapi/MMPst.cpp @@ -94,38 +94,38 @@ struct HEADER2UNICODE void PrintCryptType(BYTE bCryptMethod) noexcept { - wprintf(L"0x%02X (", bCryptMethod); + wprintf_s(L"0x%02X (", bCryptMethod); switch (bCryptMethod) { case NDB_CRYPT_NONE: - wprintf(L"not encoded"); + wprintf_s(L"not encoded"); break; case NDB_CRYPT_PERMUTE: - wprintf(L"permutative encoding"); + wprintf_s(L"permutative encoding"); break; case NDB_CRYPT_CYCLIC: - wprintf(L"cyclic encoding"); + wprintf_s(L"cyclic encoding"); break; } - wprintf(L")"); + wprintf_s(L")"); } void PrintAMAPValid(BYTE fAMapValid) noexcept { - wprintf(L"0x%02X (", fAMapValid); + wprintf_s(L"0x%02X (", fAMapValid); switch (fAMapValid) { case 0: - wprintf(L"not valid"); + wprintf_s(L"not valid"); break; case 1: case 2: - wprintf(L"valid"); + wprintf_s(L"valid"); break; } - wprintf(L")"); + wprintf_s(L")"); } #define KB (1024) @@ -138,34 +138,34 @@ void PrintFileSize(ULONGLONG ullFileSize) noexcept if (ullFileSize > GB) { scaledSize = ullFileSize / static_cast(GB); - wprintf(L"%.2f GB", scaledSize); + wprintf_s(L"%.2f GB", scaledSize); } else if (ullFileSize > MB) { scaledSize = ullFileSize / static_cast(MB); - wprintf(L"%.2f MB", scaledSize); + wprintf_s(L"%.2f MB", scaledSize); } else if (ullFileSize > KB) { scaledSize = ullFileSize / static_cast(KB); - wprintf(L"%.2f KB", scaledSize); + wprintf_s(L"%.2f KB", scaledSize); } - wprintf(L" (%I64u bytes)", ullFileSize); + wprintf_s(L" (%I64u bytes)", ullFileSize); } void DoPST() { const auto input = cli::switchInput[0]; - wprintf(L"Analyzing %ws\n", input.c_str()); + wprintf_s(L"Analyzing %ws\n", input.c_str()); struct _stat64 stats = {}; if (FAILED(EC_W32(_wstati64(input.c_str(), &stats)))) { - wprintf(L"Input file does not exist.\n"); + wprintf_s(L"Input file does not exist.\n"); if (cli::switchVerbose.isSet()) { - wprintf(L"errno = %d\n", errno); + wprintf_s(L"errno = %d\n", errno); } return; @@ -174,10 +174,10 @@ void DoPST() const auto fIn = output::MyOpenFileMode(input, L"rb"); if (!fIn) { - wprintf(L"Cannot open input file. Try closing Outlook and trying again.\n"); - wprintf(L"File Size (actual) = "); + wprintf_s(L"Cannot open input file. Try closing Outlook and trying again.\n"); + wprintf_s(L"File Size (actual) = "); PrintFileSize(stats.st_size); - wprintf(L"\n"); + wprintf_s(L"\n"); return; } @@ -191,7 +191,7 @@ void DoPST() if (NDBANSISMALL == pstHeader.wVer || NDBANSILARGE == pstHeader.wVer) { - wprintf(L"ANSI PST (%ws)\n", NDBANSISMALL == pstHeader.wVer ? L"small" : L"large"); + wprintf_s(L"ANSI PST (%ws)\n", NDBANSISMALL == pstHeader.wVer ? L"small" : L"large"); HEADER2ANSI h2Ansi = {0}; if (fread(&h2Ansi, sizeof(HEADER2ANSI), 1, fIn)) { @@ -203,7 +203,7 @@ void DoPST() } else if (NDBUNICODE == pstHeader.wVer || NDBUNICODE2 == pstHeader.wVer) { - wprintf(L"Unicode PST\n"); + wprintf_s(L"Unicode PST\n"); HEADER2UNICODE h2Unicode = {}; if (fread(&h2Unicode, sizeof(HEADER2UNICODE), 1, fIn)) { @@ -216,48 +216,48 @@ void DoPST() if (ibFileEof != static_cast(stats.st_size)) { - wprintf(L"File Size (header) = "); + wprintf_s(L"File Size (header) = "); PrintFileSize(ibFileEof); - wprintf(L"\n"); - wprintf(L"File Size (actual) = "); + wprintf_s(L"\n"); + wprintf_s(L"File Size (actual) = "); PrintFileSize(stats.st_size); - wprintf(L"\n"); + wprintf_s(L"\n"); } else { - wprintf(L"File Size = "); + wprintf_s(L"File Size = "); PrintFileSize(ibFileEof); - wprintf(L"\n"); + wprintf_s(L"\n"); } - wprintf(L"Free Space = "); + wprintf_s(L"Free Space = "); PrintFileSize(cbAMapFree); - wprintf(L"\n"); + wprintf_s(L"\n"); if (ibFileEof != 0) { const auto percentFree = cbAMapFree * 100.0 / ibFileEof; - wprintf(L"Percent free = %.2f%%\n", percentFree); + wprintf_s(L"Percent free = %.2f%%\n", percentFree); } if (cli::switchVerbose.isSet()) { - wprintf(L"\n"); - wprintf(L"fAMapValid = "); + wprintf_s(L"\n"); + wprintf_s(L"fAMapValid = "); PrintAMAPValid(fAMapValid); - wprintf(L"\n"); - wprintf(L"Crypt Method = "); + wprintf_s(L"\n"); + wprintf_s(L"Crypt Method = "); PrintCryptType(bCryptMethod); - wprintf(L"\n"); + wprintf_s(L"\n"); - wprintf(L"Magic Number = 0x%08X\n", pstHeader.dwMagic); - wprintf(L"wMagicClient = 0x%04X\n", pstHeader.wMagicClient); - wprintf(L"wVer = 0x%04X\n", pstHeader.wVer); - wprintf(L"wVerClient = 0x%04X\n", pstHeader.wVerClient); + wprintf_s(L"Magic Number = 0x%08X\n", pstHeader.dwMagic); + wprintf_s(L"wMagicClient = 0x%04X\n", pstHeader.wMagicClient); + wprintf_s(L"wVer = 0x%04X\n", pstHeader.wVer); + wprintf_s(L"wVerClient = 0x%04X\n", pstHeader.wVerClient); } } else { - wprintf(L"Could not read from file. File may be locked or empty.\n"); + wprintf_s(L"Could not read from file. File may be locked or empty.\n"); } fclose(fIn); diff --git a/MrMapi/MMReceiveFolder.cpp b/MrMapi/MMReceiveFolder.cpp index 358f70daa..9e7c79f98 100644 --- a/MrMapi/MMReceiveFolder.cpp +++ b/MrMapi/MMReceiveFolder.cpp @@ -11,11 +11,11 @@ void PrintReceiveFolderTable(_In_ LPMDB lpMDB) auto hRes = WC_MAPI(lpMDB->GetReceiveFolderTable(0, &lpReceiveFolderTable)); if (FAILED(hRes)) { - wprintf(L"\n", hRes); + wprintf_s(L"\n", hRes); return; } - wprintf(L"\n"); + wprintf_s(L"\n"); if (lpReceiveFolderTable) { @@ -36,7 +36,7 @@ void PrintReceiveFolderTable(_In_ LPMDB lpMDB) for (ULONG i = 0; i < lpRows->cRows; i++) { - wprintf(L"\n", iRow); + wprintf_s(L"\n", iRow); output::outputProperties( output::dbgLevel::NoDebug, stdout, @@ -44,7 +44,7 @@ void PrintReceiveFolderTable(_In_ LPMDB lpMDB) lpRows->aRow[i].lpProps, nullptr, false); - wprintf(L"\n"); + wprintf_s(L"\n"); iRow++; } } @@ -52,7 +52,7 @@ void PrintReceiveFolderTable(_In_ LPMDB lpMDB) if (lpRows) FreeProws(lpRows); } - wprintf(L"\n"); + wprintf_s(L"\n"); if (lpReceiveFolderTable) { lpReceiveFolderTable->Release(); diff --git a/MrMapi/MMSmartView.cpp b/MrMapi/MMSmartView.cpp index 64d9aa113..d93329d48 100644 --- a/MrMapi/MMSmartView.cpp +++ b/MrMapi/MMSmartView.cpp @@ -21,7 +21,7 @@ namespace smartviewfile HRESULT Failure(const wchar_t* message, HRESULT result) { - wprintf(L"SmartView: %ws (0x%08lX).\n", message, result); + wprintf_s(L"SmartView: %ws (0x%08lX).\n", message, result); return WC_H(result); } @@ -110,7 +110,7 @@ namespace smartviewfile const auto szString = operations.parse(sBin, parser); if (output.empty()) { - if (!szString.empty() && wprintf(L"%ws\n", strings::StripCarriage(szString).c_str()) < 0) + if (!szString.empty() && wprintf_s(L"%ws\n", strings::StripCarriage(szString).c_str()) < 0) return Failure(L"Cannot write parsed output", HRESULT_FROM_WIN32(ERROR_WRITE_FAULT)); } else @@ -147,7 +147,7 @@ HRESULT DoSmartView() const auto parser = cli::switchParser.atULONG(0); if (!parser || parser >= SmartViewParserTypeArray.size()) { - wprintf(L"SmartView: Invalid parser type.\n"); + wprintf_s(L"SmartView: Invalid parser type.\n"); return WC_H(E_INVALIDARG); } return smartviewfile::ParseFile( diff --git a/MrMapi/MMStore.cpp b/MrMapi/MMStore.cpp index bbe7c92b0..eb56f2dce 100644 --- a/MrMapi/MMStore.cpp +++ b/MrMapi/MMStore.cpp @@ -186,8 +186,8 @@ void PrintObjectProperties(const std::wstring& szObjType, _In_ LPMAPIPROP lpMAPI auto hRes = S_OK; if (!lpMAPIProp) return; - wprintf(output::g_szXMLHeader.c_str()); - wprintf(L"<%ws>\n", szObjType.c_str()); + wprintf_s(output::g_szXMLHeader.c_str()); + wprintf_s(L"<%ws>\n", szObjType.c_str()); LPSPropValue lpAllProps = nullptr; ULONG cValues = 0L; @@ -205,20 +205,20 @@ void PrintObjectProperties(const std::wstring& szObjType, _In_ LPMAPIPROP lpMAPI if (FAILED(hRes)) { - wprintf(L"\n", hRes); + wprintf_s(L"\n", hRes); } else if (lpAllProps) { - wprintf(L"\n"); + wprintf_s(L"\n"); output::outputProperties(output::dbgLevel::NoDebug, stdout, cValues, lpAllProps, lpMAPIProp, true); - wprintf(L"\n"); + wprintf_s(L"\n"); MAPIFreeBuffer(lpAllProps); } - wprintf(L"\n", szObjType.c_str()); + wprintf_s(L"\n", szObjType.c_str()); } void PrintStoreProperty(_In_ LPMAPISESSION lpMAPISession, ULONG ulIndex, ULONG ulPropTag) @@ -245,8 +245,8 @@ void PrintStoreTable(_In_ LPMAPISESSION lpMAPISession, ULONG ulPropTag) LPMAPITABLE lpStoreTable = nullptr; if (!lpMAPISession) return; - wprintf(output::g_szXMLHeader.c_str()); - wprintf(L"\n"); + wprintf_s(output::g_szXMLHeader.c_str()); + wprintf_s(L"\n"); WC_MAPI_S(lpMAPISession->GetMsgStoresTable(0, &lpStoreTable)); if (lpStoreTable) @@ -275,7 +275,7 @@ void PrintStoreTable(_In_ LPMAPISESSION lpMAPISession, ULONG ulPropTag) for (ULONG i = 0; i < lpRows->cRows; i++) { - wprintf(L"\n", iCurStore); + wprintf_s(L"\n", iCurStore); if (ulPropTag && lpRows->aRow[0].lpProps && PT_ERROR == PROP_TYPE(lpRows->aRow[0].lpProps->ulPropTag) && MAPI_E_NOT_FOUND == lpRows->aRow[0].lpProps->Value.err) @@ -293,7 +293,7 @@ void PrintStoreTable(_In_ LPMAPISESSION lpMAPISession, ULONG ulPropTag) false); } - wprintf(L"\n"); + wprintf_s(L"\n"); iCurStore++; } } @@ -302,7 +302,7 @@ void PrintStoreTable(_In_ LPMAPISESSION lpMAPISession, ULONG ulPropTag) } } - wprintf(L"\n"); + wprintf_s(L"\n"); if (lpStoreTable) lpStoreTable->Release(); } diff --git a/MrMapi/MrMAPI.cpp b/MrMapi/MrMAPI.cpp index 718eba99f..02520793e 100644 --- a/MrMapi/MrMAPI.cpp +++ b/MrMapi/MrMAPI.cpp @@ -42,7 +42,7 @@ bool PromptForAddInApproval( for (const auto& candidate : candidates) { - wprintf(L"Load add-in \"%ws\" (SHA-256: %ws)? [y/N] ", candidate.fileName.c_str(), candidate.sha256.c_str()); + wprintf_s(L"Load add-in \"%ws\" (SHA-256: %ws)? [y/N] ", candidate.fileName.c_str(), candidate.sha256.c_str()); fflush(stdout); WCHAR response[16] = {}; @@ -62,7 +62,7 @@ _Check_return_ LPMAPISESSION MrMAPILogonEx(const std::wstring& lpszProfile) LPMAPISESSION lpSession = nullptr; const auto hRes = WC_MAPI( MAPILogonEx(NULL, LPTSTR((lpszProfile.empty() ? nullptr : lpszProfile.c_str())), nullptr, ulFlags, &lpSession)); - if (FAILED(hRes)) wprintf(L"MAPILogonEx returned an error: 0x%08lx\n", hRes); + if (FAILED(hRes)) wprintf_s(L"MAPILogonEx returned an error: 0x%08lx\n", hRes); return lpSession; } @@ -95,7 +95,7 @@ bool LoadMAPIVersion(const std::wstring& lpszVersion) for (const auto& path : paths) { - wprintf(L"MAPI path: %ws\n", strings::wstringToLower(path).c_str()); + wprintf_s(L"MAPI path: %ws\n", strings::wstringToLower(path).c_str()); } return true; } @@ -193,7 +193,7 @@ int wmain(_In_ int argc, _In_count_(argc) wchar_t* argv[]) cli::ParseArgs(ProgOpts, cl, cli::g_options); if (mailboxRequested && !cli::switchMailbox.isSet()) { - wprintf(L"-Mailbox requires an SMTP address.\n"); + wprintf_s(L"-Mailbox requires an SMTP address.\n"); return 2; } @@ -201,13 +201,13 @@ int wmain(_In_ int argc, _In_count_(argc) wchar_t* argv[]) const auto mailboxError = cli::ValidateMailboxOptions(ProgOpts); if (!mailboxError.empty()) { - wprintf(L"%ws\n", mailboxError.c_str()); + wprintf_s(L"%ws\n", mailboxError.c_str()); return 2; } if (entryIDRequested && ProgOpts.mode == cli::cmdmodeHelp) { - wprintf(L"Invalid -EntryID command. Use -Help for syntax.\n"); + wprintf_s(L"Invalid -EntryID command. Use -Help for syntax.\n"); return 2; } @@ -262,7 +262,7 @@ int wmain(_In_ int argc, _In_count_(argc) wchar_t* argv[]) hRes = WC_MAPI(MAPIInitialize(nullptr)); if (FAILED(hRes)) { - wprintf(L"Error initializing MAPI: 0x%08lx\n", hRes); + wprintf_s(L"Error initializing MAPI: 0x%08lx\n", hRes); } else { @@ -295,14 +295,14 @@ int wmain(_In_ int argc, _In_count_(argc) wchar_t* argv[]) } if (FAILED(hRes)) - wprintf(L"Cannot open requested mailbox/folder: 0x%08lX. No fallback mailbox was used.\n", hRes); + wprintf_s(L"Cannot open requested mailbox/folder: 0x%08lX. No fallback mailbox was used.\n", hRes); } // If they need a folder get it and store at the same time from the folder id if (!cli::switchMailbox.isSet() && lpMAPISession && ProgOpts.flags & cli::OPT_NEEDFOLDER) { hRes = WC_H(HrMAPIOpenStoreAndFolder(lpMAPISession, cli::switchFolder[0], &lpMDB, &lpFolder)); - if (FAILED(hRes)) wprintf(L"HrMAPIOpenStoreAndFolder returned an error: 0x%08lx\n", hRes); + if (FAILED(hRes)) wprintf_s(L"HrMAPIOpenStoreAndFolder returned an error: 0x%08lx\n", hRes); } // If they passed a store index then open it @@ -313,14 +313,14 @@ int wmain(_In_ int argc, _In_count_(argc) wchar_t* argv[]) if (!cli::switchMailbox.isSet() && lpMAPISession && gotStoreIndex && !lpMDB) { lpMDB = OpenStore(lpMAPISession, ulStoreIndex, ProgOpts.mode == cli::cmdmodeEntryID); - if (!lpMDB) wprintf(L"OpenStore failed\n"); + if (!lpMDB) wprintf_s(L"OpenStore failed\n"); } if (!cli::switchMailbox.isSet() && lpMAPISession && ProgOpts.flags & cli::OPT_NEEDSTORE && !lpMDB) { // If they needed a store but didn't specify, get the default one lpMDB = OpenExchangeOrDefaultMessageStore(lpMAPISession); - if (!lpMDB) wprintf(L"OpenExchangeOrDefaultMessageStore failed.\n"); + if (!lpMDB) wprintf_s(L"OpenExchangeOrDefaultMessageStore failed.\n"); } if (!cli::switchMailbox.isSet() || SUCCEEDED(hRes)) @@ -329,7 +329,7 @@ int wmain(_In_ int argc, _In_count_(argc) wchar_t* argv[]) { case cli::cmdmodeEntryID: hRes = DoEntryID(lpMDB); - if (FAILED(hRes)) wprintf(L"EntryID property lookup failed: 0x%08lx\n", hRes); + if (FAILED(hRes)) wprintf_s(L"EntryID property lookup failed: 0x%08lx\n", hRes); break; case cli::cmdmodePropTag: DoPropTags(); diff --git a/MrMapi/mmcli.cpp b/MrMapi/mmcli.cpp index 0b4d9b309..70bd73a42 100644 --- a/MrMapi/mmcli.cpp +++ b/MrMapi/mmcli.cpp @@ -150,74 +150,74 @@ namespace cli void DisplayUsage(BOOL bFull) noexcept { - wprintf(L"MAPI data collection and parsing tool. Supports property tag lookup, error translation,\n"); - wprintf(L" smart view processing, rule tables, ACL tables, contents tables, and MAPI<->MIME conversion.\n"); + wprintf_s(L"MAPI data collection and parsing tool. Supports property tag lookup, error translation,\n"); + wprintf_s(L" smart view processing, rule tables, ACL tables, contents tables, and MAPI<->MIME conversion.\n"); if (bFull) { if (!g_lpMyAddins.empty()) { - wprintf(L"Addins Loaded:\n"); + wprintf_s(L"Addins Loaded:\n"); for (const auto& addIn : g_lpMyAddins) { - wprintf(L" %ws\n", addIn.szName); + wprintf_s(L" %ws\n", addIn.szName); } } - wprintf(L"MrMAPI currently knows:\n"); - wprintf(L"%6u property tags\n", static_cast(PropTagArray.size())); - wprintf(L"%6u dispids\n", static_cast(NameIDArray.size())); - wprintf(L"%6u types\n", static_cast(PropTypeArray.size())); - wprintf(L"%6u guids\n", static_cast(PropGuidArray.size())); - wprintf(L"%6lu errors\n", error::g_ulErrorArray); - wprintf(L"%6u smart view parsers\n", static_cast(SmartViewParserTypeArray.size()) - 1); - wprintf(L"\n"); + wprintf_s(L"MrMAPI currently knows:\n"); + wprintf_s(L"%6u property tags\n", static_cast(PropTagArray.size())); + wprintf_s(L"%6u dispids\n", static_cast(NameIDArray.size())); + wprintf_s(L"%6u types\n", static_cast(PropTypeArray.size())); + wprintf_s(L"%6u guids\n", static_cast(PropGuidArray.size())); + wprintf_s(L"%6lu errors\n", error::g_ulErrorArray); + wprintf_s(L"%6u smart view parsers\n", static_cast(SmartViewParserTypeArray.size()) - 1); + wprintf_s(L"\n"); } - wprintf(L"Usage:\n"); - wprintf(L" Add -Mailbox -Profile to a store/folder command.\n"); - wprintf(L" Primary addresses and verified SMTP aliases are supported.\n"); - wprintf(L" Uses that profile's Exchange session and existing permissions; never falls back to its own " - L"mailbox.\n"); - wprintf(L" MrMAPI -EntryID -Profile -Store \n"); - wprintf(L" MrMAPI -%ws\n", switchHelp.name()); - wprintf( + wprintf_s(L"Usage:\n"); + wprintf_s(L" Add -Mailbox -Profile to a store/folder command.\n"); + wprintf_s(L" Primary addresses and verified SMTP aliases are supported.\n"); + wprintf_s(L" Uses that profile's Exchange session and existing permissions; never falls back to its own " + L"mailbox.\n"); + wprintf_s(L" MrMAPI -EntryID -Profile -Store \n"); + wprintf_s(L" MrMAPI -%ws\n", switchHelp.name()); + wprintf_s( L" MrMAPI [-%ws] [-%ws] [-%ws] [-%ws ] |\n", switchSearch.name(), switchDispid.name(), switchDecimal.name(), switchType.name()); - wprintf(L" MrMAPI -%ws\n", switchGuid.name()); - wprintf(L" MrMAPI -%ws \n", switchError.name()); - wprintf( + wprintf_s(L" MrMAPI -%ws\n", switchGuid.name()); + wprintf_s(L" MrMAPI -%ws \n", switchError.name()); + wprintf_s( L" MrMAPI -%ws -%ws [-%ws] [-%ws ]\n", switchParser.name(), switchInput.name(), switchBinary.name(), switchOutput.name()); - wprintf( + wprintf_s( L" MrMAPI -%ws [-%ws] [-%ws] |\n", switchFlag.name(), switchDispid.name(), switchDecimal.name()); - wprintf(L" MrMAPI -%ws \n", switchFlag.name()); - wprintf( + wprintf_s(L" MrMAPI -%ws \n", switchFlag.name()); + wprintf_s( L" MrMAPI -%ws [-%ws ] [-%ws ]\n", switchRule.name(), switchProfile.name(), switchFolder.name()); - wprintf( + wprintf_s( L" MrMAPI -%ws [-%ws ] [-%ws ]\n", switchAcl.name(), switchProfile.name(), switchFolder.name()); - wprintf( + wprintf_s( L" MrMAPI -%ws | -%ws [-%ws ] [-%ws ] [-%ws ]\n", switchContents.name(), switchAssociatedContents.name(), switchProfile.name(), switchFolder.name(), switchOutput.name()); - wprintf( + wprintf_s( L" [-%ws ] [-%ws ] [-%ws] [-%ws] [-%ws ] [-%ws]\n", switchSubject.name(), switchMessageClass.name(), @@ -225,81 +225,81 @@ namespace cli switchList.name(), switchRecent.name(), switchSkip.name()); - wprintf( + wprintf_s( L" [-%ws ] [-%ws ] [-%ws]\n", switchFindProperty.name(), switchFindNamedProperty.name(), switchRecurse.name()); - wprintf( + wprintf_s( L" MrMAPI -%ws [-%ws ] [-%ws ]\n", switchChildFolders.name(), switchProfile.name(), switchFolder.name()); - wprintf( + wprintf_s( L" MrMAPI -%ws -%ws -%ws [-%ws]\n", switchXML.name(), switchInput.name(), switchOutput.name(), switchSkip.name()); - wprintf( + wprintf_s( L" MrMAPI -%ws [fid] [-%ws [mid]] [-%ws ]\n", switchFid.name(), switchMid.name(), switchProfile.name()); - wprintf( + wprintf_s( L" MrMAPI [|] -%ws [] [-%ws ]\n", switchStore.name(), switchProfile.name()); - wprintf( + wprintf_s( L" MrMAPI [|] -%ws [-%ws ]\n", switchFolder.name(), switchProfile.name()); - wprintf( + wprintf_s( L" MrMAPI -%ws -%ws [-%ws ]\n", switchSize.name(), switchFolder.name(), switchProfile.name()); - wprintf( + wprintf_s( L" MrMAPI -%ws | -%ws -%ws -%ws [-%ws ]\n", switchMAPI.name(), switchMIME.name(), switchInput.name(), switchOutput.name(), switchCCSFFlags.name()); - wprintf( + wprintf_s( L" [-%ws] [-%ws ] [-%ws ]\n", switchRFC822.name(), switchWrap.name(), switchEncoding.name()); - wprintf( + wprintf_s( L" [-%ws] [-%ws] [-%ws CodePage CharSetType CharSetApplyType]\n", switchAddressBook.name(), switchUnicode.name(), switchCharset.name()); - wprintf(L" MrMAPI -%ws -%ws \n", switchPST.name(), switchInput.name()); - wprintf( + wprintf_s(L" MrMAPI -%ws -%ws \n", switchPST.name(), switchInput.name()); + wprintf_s( L" MrMAPI -%ws [ [-%ws [-%ws]] -%ws ]\n", switchProfile.name(), switchProfileSection.name(), switchByteSwapped.name(), switchOutput.name()); - wprintf(L" MrMAPI -%ws [] [-%ws ]\n", switchReceiveFolder.name(), switchProfile.name()); - wprintf( + wprintf_s(L" MrMAPI -%ws [] [-%ws ]\n", switchReceiveFolder.name(), switchProfile.name()); + wprintf_s( L" MrMAPI -%ws -%ws [-%ws ]\n", switchSearchState.name(), switchFolder.name(), switchProfile.name()); - wprintf( + wprintf_s( L" MrMAPI -%ws [-%ws ] [-%ws ]\n", switchNamedProps.name(), switchProfile.name(), switchOutput.name()); - wprintf( + wprintf_s( L" MrMAPI -%ws [-%ws] [-%ws ]\n", switchAccounts.name(), switchIterate.name(), switchProfile.name()); - wprintf( + wprintf_s( L" MrMAPI -%ws -%ws [-%ws ] [-%ws ]\n", switchAccounts.name(), switchWizard.name(), @@ -308,275 +308,279 @@ namespace cli if (bFull) { - wprintf(L"\n Message by EntryID:\n"); - wprintf(L" -EntryID opens one message read-only in the explicitly selected profile and store.\n"); - wprintf(L" Hex must be contiguous pairs (1-8192 bytes), without 0x, spaces or separators.\n"); - wprintf(L" -Profile and -Store are required; no defaults.\n"); - wprintf(L" Specify one known property name or full typed hex tag (optional 0x prefix).\n"); - wprintf(L" Output is MrMAPI property XML on stdout, not a bare value. No file is written.\n"); - wprintf(L" Only -NoAddins, -Verbose, -Online and -Version are also accepted.\n"); - wprintf(L" Exit codes: 0 success/help, 2 invalid input, 1 MAPI/property failure.\n"); - wprintf(L" Example: MrMAPI -EntryID 00000000... -Profile \"Test\" -Store 0 PR_SUBJECT_W\n"); - wprintf(L"\n"); - wprintf(L"All switches may be shortened if the intended switch is unambiguous.\n"); - wprintf(L"For example, -T may be used instead of -%ws.\n", switchType.name()); + wprintf_s(L"\n Message by EntryID:\n"); + wprintf_s(L" -EntryID opens one message read-only in the explicitly selected profile and store.\n"); + wprintf_s(L" Hex must be contiguous pairs (1-8192 bytes), without 0x, spaces or separators.\n"); + wprintf_s(L" -Profile and -Store are required; no defaults.\n"); + wprintf_s(L" Specify one known property name or full typed hex tag (optional 0x prefix).\n"); + wprintf_s(L" Output is MrMAPI property XML on stdout, not a bare value. No file is written.\n"); + wprintf_s(L" Only -NoAddins, -Verbose, -Online and -Version are also accepted.\n"); + wprintf_s(L" Exit codes: 0 success/help, 2 invalid input, 1 MAPI/property failure.\n"); + wprintf_s(L" Example: MrMAPI -EntryID 00000000... -Profile \"Test\" -Store 0 PR_SUBJECT_W\n"); + wprintf_s(L"\n"); + wprintf_s(L"All switches may be shortened if the intended switch is unambiguous.\n"); + wprintf_s(L"For example, -T may be used instead of -%ws.\n", switchType.name()); } - wprintf(L"\n"); - wprintf(L" Help:\n"); - wprintf(L" -%ws Display expanded help.\n", switchHelp.name()); + wprintf_s(L"\n"); + wprintf_s(L" Help:\n"); + wprintf_s(L" -%ws Display expanded help.\n", switchHelp.name()); if (bFull) { - wprintf(L"\n"); - wprintf(L" Property Tag Lookup:\n"); - wprintf(L" -S (or -%ws) Perform substring search.\n", switchSearch.name()); - wprintf(L" With no parameters prints all known properties.\n"); - wprintf(L" -D (or -%ws) Search dispids.\n", switchDispid.name()); - wprintf(L" -N (or -%ws) Number is in decimal. Ignored for non-numbers.\n", switchDecimal.name()); - wprintf(L" -T (or -%ws) Print information on specified type.\n", switchType.name()); - wprintf(L" With no parameters prints list of known types.\n"); - wprintf(L" When combined with -S, restrict output to given type.\n"); - wprintf(L" -G (or -%ws) Display list of known guids.\n", switchGuid.name()); - wprintf(L"\n"); - wprintf(L" Flag Lookup:\n"); - wprintf(L" -Fl (or -%ws) Look up flags for specified property.\n", switchFlag.name()); - wprintf(L" May be combined with -D and -N switches, but all flag values must be in hex.\n"); - wprintf(L" -Fl (or -%ws) Look up flag name and output its value.\n", switchFlag.name()); - wprintf(L"\n"); - wprintf(L" Error Parsing:\n"); - wprintf(L" -E (or -%ws) Map an error code to its name and vice versa.\n", switchError.name()); - wprintf(L" May be combined with -S and -N switches.\n"); - wprintf(L"\n"); - wprintf(L" Smart View Parsing:\n"); - wprintf( + wprintf_s(L"\n"); + wprintf_s(L" Property Tag Lookup:\n"); + wprintf_s(L" -S (or -%ws) Perform substring search.\n", switchSearch.name()); + wprintf_s(L" With no parameters prints all known properties.\n"); + wprintf_s(L" -D (or -%ws) Search dispids.\n", switchDispid.name()); + wprintf_s(L" -N (or -%ws) Number is in decimal. Ignored for non-numbers.\n", switchDecimal.name()); + wprintf_s(L" -T (or -%ws) Print information on specified type.\n", switchType.name()); + wprintf_s(L" With no parameters prints list of known types.\n"); + wprintf_s(L" When combined with -S, restrict output to given type.\n"); + wprintf_s(L" -G (or -%ws) Display list of known guids.\n", switchGuid.name()); + wprintf_s(L"\n"); + wprintf_s(L" Flag Lookup:\n"); + wprintf_s(L" -Fl (or -%ws) Look up flags for specified property.\n", switchFlag.name()); + wprintf_s(L" May be combined with -D and -N switches, but all flag values must be in hex.\n"); + wprintf_s(L" -Fl (or -%ws) Look up flag name and output its value.\n", switchFlag.name()); + wprintf_s(L"\n"); + wprintf_s(L" Error Parsing:\n"); + wprintf_s(L" -E (or -%ws) Map an error code to its name and vice versa.\n", switchError.name()); + wprintf_s(L" May be combined with -S and -N switches.\n"); + wprintf_s(L"\n"); + wprintf_s(L" Smart View Parsing:\n"); + wprintf_s( L" -P (or -%ws) Parser type (number). See list below for supported parsers.\n", switchParser.name()); - wprintf(L" -B (or -%ws) Input file is binary. Default is hex encoded text.\n", switchBinary.name()); - wprintf(L" Empty input is parsed as an empty blob.\n"); - wprintf(L" Input failures return a nonzero exit code without replacing output.\n"); - wprintf(L" Input and output must identify different files.\n"); - wprintf(L"\n"); - wprintf(L" Rules Table:\n"); - wprintf(L" -R (or -%ws) Output rules table. Profile optional.\n", switchRule.name()); - wprintf(L"\n"); - wprintf(L" ACL Table:\n"); - wprintf(L" -A (or -%ws) Output ACL table. Profile optional.\n", switchAcl.name()); - wprintf(L"\n"); - wprintf(L" Contents Table:\n"); - wprintf( + wprintf_s(L" -B (or -%ws) Input file is binary. Default is hex encoded text.\n", switchBinary.name()); + wprintf_s(L" Empty input is parsed as an empty blob.\n"); + wprintf_s(L" Input failures return a nonzero exit code without replacing output.\n"); + wprintf_s(L" Input and output must identify different files.\n"); + wprintf_s(L"\n"); + wprintf_s(L" Rules Table:\n"); + wprintf_s(L" -R (or -%ws) Output rules table. Profile optional.\n", switchRule.name()); + wprintf_s(L"\n"); + wprintf_s(L" ACL Table:\n"); + wprintf_s(L" -A (or -%ws) Output ACL table. Profile optional.\n", switchAcl.name()); + wprintf_s(L"\n"); + wprintf_s(L" Contents Table:\n"); + wprintf_s( L" -C (or -%ws) Output contents table. May be combined with -H. Profile optional.\n", switchContents.name()); - wprintf( + wprintf_s( L" -H (or -%ws) Output associated contents table. May be combined with -C. Profile optional\n", switchAssociatedContents.name()); - wprintf(L" -Chi (or -%ws) Recurse into child folders of selected folder.\n", switchChildFolders.name()); - wprintf(L" -Su (or -%ws) Subject of messages to output.\n", switchSubject.name()); - wprintf(L" -Me (or -%ws) Message class of messages to output.\n", switchMessageClass.name()); - wprintf(L" -Ms (or -%ws) Output as .MSG instead of XML.\n", switchMSG.name()); - wprintf(L" -L (or -%ws) List details to screen and do not output files.\n", switchList.name()); - wprintf(L" -Res (or -%ws) Restrict output to the 'count' most recent messages.\n", switchRecent.name()); - wprintf( + wprintf_s(L" -Chi (or -%ws) Recurse into child folders of selected folder.\n", switchChildFolders.name()); + wprintf_s(L" -Su (or -%ws) Subject of messages to output.\n", switchSubject.name()); + wprintf_s(L" -Me (or -%ws) Message class of messages to output.\n", switchMessageClass.name()); + wprintf_s(L" -Ms (or -%ws) Output as .MSG instead of XML.\n", switchMSG.name()); + wprintf_s(L" -L (or -%ws) List details to screen and do not output files.\n", switchList.name()); + wprintf_s(L" -Res (or -%ws) Restrict output to the 'count' most recent messages.\n", switchRecent.name()); + wprintf_s( L" -FindP (or -%ws) Restrict output to messages which contain given properties.\n", switchFindProperty.name()); - wprintf( + wprintf_s( L" -FindN (or -%ws) Restrict output to messages which contain given named properties.\n", switchFindNamedProperty.name()); - wprintf(L" -Recur (or -%ws) Recurse into subfolders.\n", switchRecurse.name()); - wprintf(L"\n"); - wprintf(L" Child Folders:\n"); - wprintf(L" -Chi (or -%ws) List child folders of selected folder.\n", switchChildFolders.name()); - wprintf(L"\n"); - wprintf(L" MSG File Properties\n"); - wprintf(L" -X (or -%ws) Output properties of an MSG file as XML.\n", switchXML.name()); - wprintf(L"\n"); - wprintf(L" MID/FID Lookup\n"); - wprintf(L" -Fi (or -%ws) Folder ID (FID) to search for.\n", switchFid.name()); - wprintf(L" If -%ws is specified without a FID, search/display all folders\n", switchFid.name()); - wprintf(L" -Mid (or -%ws) Message ID (MID) to search for.\n", switchMid.name()); - wprintf( + wprintf_s(L" -Recur (or -%ws) Recurse into subfolders.\n", switchRecurse.name()); + wprintf_s(L"\n"); + wprintf_s(L" Child Folders:\n"); + wprintf_s(L" -Chi (or -%ws) List child folders of selected folder.\n", switchChildFolders.name()); + wprintf_s(L"\n"); + wprintf_s(L" MSG File Properties\n"); + wprintf_s(L" -X (or -%ws) Output properties of an MSG file as XML.\n", switchXML.name()); + wprintf_s(L"\n"); + wprintf_s(L" MID/FID Lookup\n"); + wprintf_s(L" -Fi (or -%ws) Folder ID (FID) to search for.\n", switchFid.name()); + wprintf_s(L" If -%ws is specified without a FID, search/display all folders\n", switchFid.name()); + wprintf_s(L" -Mid (or -%ws) Message ID (MID) to search for.\n", switchMid.name()); + wprintf_s( L" If -%ws is specified without a MID, display all messages in folders specified by the FID " "parameter.\n", switchMid.name()); - wprintf(L"\n"); - wprintf(L" Store Properties\n"); - wprintf(L" -St (or -%ws) Output properties of stores as XML.\n", switchStore.name()); - wprintf(L" If store number is specified, outputs properties of a single store.\n"); - wprintf(L" If a property is specified, outputs only that property.\n"); - wprintf(L"\n"); - wprintf(L" Folder Properties\n"); - wprintf(L" -F (or -%ws) Output properties of a folder as XML.\n", switchFolder.name()); - wprintf(L" If a property is specified, outputs only that property.\n"); - wprintf(L" -Size Output size of a folder and all subfolders.\n"); - wprintf(L" Use -%ws to specify which folder to scan.\n", switchFolder.name()); - wprintf(L" -SearchState Output search folder state.\n"); - wprintf(L" Use -%ws to specify which folder to scan.\n", switchFolder.name()); - wprintf(L"\n"); - wprintf(L" MAPI <-> MIME Conversion:\n"); - wprintf(L" -Ma (or -%ws) Convert an EML file to MAPI format (MSG file).\n", switchMAPI.name()); - wprintf(L" -Mi (or -%ws) Convert an MSG file to MIME format (EML file).\n", switchMIME.name()); - wprintf( + wprintf_s(L"\n"); + wprintf_s(L" Store Properties\n"); + wprintf_s(L" -St (or -%ws) Output properties of stores as XML.\n", switchStore.name()); + wprintf_s(L" If store number is specified, outputs properties of a single store.\n"); + wprintf_s(L" If a property is specified, outputs only that property.\n"); + wprintf_s(L"\n"); + wprintf_s(L" Folder Properties\n"); + wprintf_s(L" -F (or -%ws) Output properties of a folder as XML.\n", switchFolder.name()); + wprintf_s(L" If a property is specified, outputs only that property.\n"); + wprintf_s(L" -Size Output size of a folder and all subfolders.\n"); + wprintf_s(L" Use -%ws to specify which folder to scan.\n", switchFolder.name()); + wprintf_s(L" -SearchState Output search folder state.\n"); + wprintf_s(L" Use -%ws to specify which folder to scan.\n", switchFolder.name()); + wprintf_s(L"\n"); + wprintf_s(L" MAPI <-> MIME Conversion:\n"); + wprintf_s(L" -Ma (or -%ws) Convert an EML file to MAPI format (MSG file).\n", switchMAPI.name()); + wprintf_s(L" -Mi (or -%ws) Convert an MSG file to MIME format (EML file).\n", switchMIME.name()); + wprintf_s( L" -I (or -%ws) Indicates the input file for conversion, either a MIME-formatted EML file or an " L"MSG " "file.\n", switchInput.name()); - wprintf(L" -O (or -%ws) Indicates the output file for the conversion.\n", switchOutput.name()); - wprintf(L" -Cc (or -%ws) Indicates specific flags to pass to the converter.\n", switchCCSFFlags.name()); - wprintf(L" Available values (these may be OR'ed together):\n"); - wprintf(L" MIME -> MAPI:\n"); - wprintf(L" CCSF_SMTP: 0x02\n"); - wprintf(L" CCSF_INCLUDE_BCC: 0x20\n"); - wprintf(L" CCSF_USE_RTF: 0x80\n"); - wprintf(L" MAPI -> MIME:\n"); - wprintf(L" CCSF_NOHEADERS: 0x000004\n"); - wprintf(L" CCSF_USE_TNEF: 0x000010\n"); - wprintf(L" CCSF_8BITHEADERS: 0x000040\n"); - wprintf(L" CCSF_PLAIN_TEXT_ONLY: 0x001000\n"); - wprintf(L" CCSF_NO_MSGID: 0x004000\n"); - wprintf(L" CCSF_EMBEDDED_MESSAGE: 0x008000\n"); - wprintf(L" CCSF_PRESERVE_SOURCE: 0x040000\n"); - wprintf(L" CCSF_GLOBAL_MESSAGE: 0x200000\n"); - wprintf( + wprintf_s(L" -O (or -%ws) Indicates the output file for the conversion.\n", switchOutput.name()); + wprintf_s( + L" -Cc (or -%ws) Indicates specific flags to pass to the converter.\n", switchCCSFFlags.name()); + wprintf_s(L" Available values (these may be OR'ed together):\n"); + wprintf_s(L" MIME -> MAPI:\n"); + wprintf_s(L" CCSF_SMTP: 0x02\n"); + wprintf_s(L" CCSF_INCLUDE_BCC: 0x20\n"); + wprintf_s(L" CCSF_USE_RTF: 0x80\n"); + wprintf_s(L" MAPI -> MIME:\n"); + wprintf_s(L" CCSF_NOHEADERS: 0x000004\n"); + wprintf_s(L" CCSF_USE_TNEF: 0x000010\n"); + wprintf_s(L" CCSF_8BITHEADERS: 0x000040\n"); + wprintf_s(L" CCSF_PLAIN_TEXT_ONLY: 0x001000\n"); + wprintf_s(L" CCSF_NO_MSGID: 0x004000\n"); + wprintf_s(L" CCSF_EMBEDDED_MESSAGE: 0x008000\n"); + wprintf_s(L" CCSF_PRESERVE_SOURCE: 0x040000\n"); + wprintf_s(L" CCSF_GLOBAL_MESSAGE: 0x200000\n"); + wprintf_s( L" -Rf (or -%ws) (MAPI->MIME only) Indicates the EML should be generated in RFC822 format.\n", switchRFC822.name()); - wprintf(L" If not present, RFC1521 is used instead.\n"); - wprintf( + wprintf_s(L" If not present, RFC1521 is used instead.\n"); + wprintf_s( L" -W (or -%ws) (MAPI->MIME only) Indicates the maximum number of characters in each line in the\n", switchWrap.name()); - wprintf(L" generated EML. Default value is 74. A value of 0 indicates no wrapping.\n"); - wprintf( + wprintf_s(L" generated EML. Default value is 74. A value of 0 indicates no wrapping.\n"); + wprintf_s( L" -En (or -%ws) (MAPI->MIME only) Indicates the encoding type to use. Supported values are:\n", switchEncoding.name()); - wprintf(L" 1 - Base64\n"); - wprintf(L" 2 - UUENCODE\n"); - wprintf(L" 3 - Quoted-Printable\n"); - wprintf(L" 4 - 7bit (DEFAULT)\n"); - wprintf(L" 5 - 8bit\n"); - wprintf( + wprintf_s(L" 1 - Base64\n"); + wprintf_s(L" 2 - UUENCODE\n"); + wprintf_s(L" 3 - Quoted-Printable\n"); + wprintf_s(L" 4 - 7bit (DEFAULT)\n"); + wprintf_s(L" 5 - 8bit\n"); + wprintf_s( L" -Ad (or -%ws) Pass MAPI Address Book into converter. Profile optional.\n", switchAddressBook.name()); - wprintf( + wprintf_s( L" -U (or -%ws) (MIME->MAPI only) The resulting MSG file should be unicode.\n", switchUnicode.name()); - wprintf( + wprintf_s( L" -Ch (or -%ws) (MIME->MAPI only) Character set - three required parameters:\n", switchCharset.name()); - wprintf(L" CodePage - common values (others supported)\n"); - wprintf(L" 1252 - CP_USASCII - Indicates the USASCII character set, Windows code page " - "1252\n"); - wprintf(L" 1200 - CP_UNICODE - Indicates the Unicode character set, Windows code page " - "1200\n"); - wprintf(L" 50932 - CP_JAUTODETECT - Indicates Japanese auto-detect (50932)\n"); - wprintf(L" 50949 - CP_KAUTODETECT - Indicates Korean auto-detect (50949)\n"); - wprintf(L" 50221 - CP_ISO2022JPESC - Indicates the Internet character set ISO-2022-JP-ESC\n"); - wprintf(L" 50222 - CP_ISO2022JPSIO - Indicates the Internet character set ISO-2022-JP-SIO\n"); - wprintf(L" CharSetType - supported values (see CHARSETTYPE)\n"); - wprintf(L" 0 - CHARSET_BODY\n"); - wprintf(L" 1 - CHARSET_HEADER\n"); - wprintf(L" 2 - CHARSET_WEB\n"); - wprintf(L" CharSetApplyType - supported values (see CSETAPPLYTYPE)\n"); - wprintf(L" 0 - CSET_APPLY_UNTAGGED\n"); - wprintf(L" 1 - CSET_APPLY_ALL\n"); - wprintf(L" 2 - CSET_APPLY_TAG_ALL\n"); - wprintf(L"\n"); - wprintf(L" PST Analysis\n"); - wprintf(L" -PST Output statistics of a PST file.\n"); - wprintf(L" If a property is specified, outputs only that property.\n"); - wprintf(L" -I (or -%ws) PST file to be analyzed.\n", switchInput.name()); - wprintf(L"\n"); - wprintf(L" Profiles\n"); - wprintf(L" -Pr (or -%ws) Output list of profiles\n", switchProfile.name()); - wprintf(L" If a profile is specified, exports that profile.\n"); - wprintf(L" -ProfileSection If specified, output specific profile section.\n"); - wprintf( + wprintf_s(L" CodePage - common values (others supported)\n"); + wprintf_s(L" 1252 - CP_USASCII - Indicates the USASCII character set, Windows code page " + "1252\n"); + wprintf_s(L" 1200 - CP_UNICODE - Indicates the Unicode character set, Windows code page " + "1200\n"); + wprintf_s(L" 50932 - CP_JAUTODETECT - Indicates Japanese auto-detect (50932)\n"); + wprintf_s(L" 50949 - CP_KAUTODETECT - Indicates Korean auto-detect (50949)\n"); + wprintf_s( + L" 50221 - CP_ISO2022JPESC - Indicates the Internet character set ISO-2022-JP-ESC\n"); + wprintf_s( + L" 50222 - CP_ISO2022JPSIO - Indicates the Internet character set ISO-2022-JP-SIO\n"); + wprintf_s(L" CharSetType - supported values (see CHARSETTYPE)\n"); + wprintf_s(L" 0 - CHARSET_BODY\n"); + wprintf_s(L" 1 - CHARSET_HEADER\n"); + wprintf_s(L" 2 - CHARSET_WEB\n"); + wprintf_s(L" CharSetApplyType - supported values (see CSETAPPLYTYPE)\n"); + wprintf_s(L" 0 - CSET_APPLY_UNTAGGED\n"); + wprintf_s(L" 1 - CSET_APPLY_ALL\n"); + wprintf_s(L" 2 - CSET_APPLY_TAG_ALL\n"); + wprintf_s(L"\n"); + wprintf_s(L" PST Analysis\n"); + wprintf_s(L" -PST Output statistics of a PST file.\n"); + wprintf_s(L" If a property is specified, outputs only that property.\n"); + wprintf_s(L" -I (or -%ws) PST file to be analyzed.\n", switchInput.name()); + wprintf_s(L"\n"); + wprintf_s(L" Profiles\n"); + wprintf_s(L" -Pr (or -%ws) Output list of profiles\n", switchProfile.name()); + wprintf_s(L" If a profile is specified, exports that profile.\n"); + wprintf_s(L" -ProfileSection If specified, output specific profile section.\n"); + wprintf_s( L" -B (or -%ws) If specified, profile section guid is byte swapped.\n", switchByteSwapped.name()); - wprintf(L" -O (or -%ws) Indicates the output file for profile export.\n", switchOutput.name()); - wprintf(L" Required if a profile is specified.\n"); - wprintf(L"\n"); - wprintf(L" Receive Folder Table\n"); - wprintf(L" -%ws Displays Receive Folder Table for the specified store\n", switchReceiveFolder.name()); - wprintf(L"\n"); - wprintf(L" Universal Options:\n"); - wprintf(L" -I (or -%ws) Input file.\n", switchInput.name()); - wprintf(L" -O (or -%ws) Output file or directory.\n", switchOutput.name()); - wprintf( + wprintf_s(L" -O (or -%ws) Indicates the output file for profile export.\n", switchOutput.name()); + wprintf_s(L" Required if a profile is specified.\n"); + wprintf_s(L"\n"); + wprintf_s(L" Receive Folder Table\n"); + wprintf_s(L" -%ws Displays Receive Folder Table for the specified store\n", switchReceiveFolder.name()); + wprintf_s(L"\n"); + wprintf_s(L" Universal Options:\n"); + wprintf_s(L" -I (or -%ws) Input file.\n", switchInput.name()); + wprintf_s(L" -O (or -%ws) Output file or directory.\n", switchOutput.name()); + wprintf_s( L" -F (or -%ws) Folder to scan. Default is Inbox. See list below for supported folders.\n", switchFolder.name()); - wprintf(L" Folders may also be specified by path:\n"); - wprintf(L" \"Top of Information Store\\Calendar\"\n"); - wprintf(L" Path may be preceeded by entry IDs for special folders using @ notation:\n"); - wprintf(L" \"@PR_IPM_SUBTREE_ENTRYID\\Calendar\"\n"); - wprintf( + wprintf_s(L" Folders may also be specified by path:\n"); + wprintf_s(L" \"Top of Information Store\\Calendar\"\n"); + wprintf_s(L" Path may be preceeded by entry IDs for special folders using @ notation:\n"); + wprintf_s(L" \"@PR_IPM_SUBTREE_ENTRYID\\Calendar\"\n"); + wprintf_s( L" Path may further be preceeded by store number using # notation, which may either use a " "store number:\n"); - wprintf(L" \"#0\\@PR_IPM_SUBTREE_ENTRYID\\Calendar\"\n"); - wprintf(L" Or an entry ID:\n"); - wprintf(L" \"#00112233445566...778899AABBCC\\@PR_IPM_SUBTREE_ENTRYID\\Calendar\"\n"); - wprintf(L" MrMAPI's special folder constants may also be used:\n"); - wprintf(L" \"@12\\Calendar\"\n"); - wprintf(L" \"@1\"\n"); - wprintf(L" -Pr (or -%ws) Profile for MAPILogonEx.\n", switchProfile.name()); - wprintf( + wprintf_s(L" \"#0\\@PR_IPM_SUBTREE_ENTRYID\\Calendar\"\n"); + wprintf_s(L" Or an entry ID:\n"); + wprintf_s(L" \"#00112233445566...778899AABBCC\\@PR_IPM_SUBTREE_ENTRYID\\Calendar\"\n"); + wprintf_s(L" MrMAPI's special folder constants may also be used:\n"); + wprintf_s(L" \"@12\\Calendar\"\n"); + wprintf_s(L" \"@1\"\n"); + wprintf_s(L" -Pr (or -%ws) Profile for MAPILogonEx.\n", switchProfile.name()); + wprintf_s( L" -M (or -%ws) More properties. Tries harder to get stream properties. May take longer.\n", switchMoreProperties.name()); - wprintf(L" -Sk (or -%ws) Skip embedded message attachments on export.\n", switchSkip.name()); - wprintf(L" -No (or -%ws) No Addins. Don't load any add-ins.\n", switchNoAddins.name()); - wprintf( + wprintf_s(L" -Sk (or -%ws) Skip embedded message attachments on export.\n", switchSkip.name()); + wprintf_s(L" -No (or -%ws) No Addins. Don't load any add-ins.\n", switchNoAddins.name()); + wprintf_s( L" -%ws Prompt to approve add-ins not previously approved or denied.\n", switchApproveAddins.name()); - wprintf(L" Add-ins are disabled unless an add-in directory is configured in MFCMAPI Options.\n"); - wprintf(L" -On (or -%ws) Online mode. Bypass cached mode.\n", switchOnline.name()); - wprintf(L" -V (or -%ws) Verbose. Turn on all debug output.\n", switchVerbose.name()); - wprintf(L"\n"); - wprintf(L" MAPI Implementation Options:\n"); - wprintf(L" -%ws MAPI Version to load - supported values\n", switchVersion.name()); - wprintf(L" Supported values\n"); - wprintf(L" 0 - List all available MAPI binaries\n"); - wprintf(L" 1 - System MAPI\n"); - wprintf(L" 11 - Outlook 2003 (11)\n"); - wprintf(L" 12 - Outlook 2007 (12)\n"); - wprintf(L" 14 - Outlook 2010 (14)\n"); - wprintf(L" 15 - Outlook 2013 (15)\n"); - wprintf(L" 16 - Outlook 2016 (16)\n"); - wprintf(L" You can also pass a string, which will load the first MAPI whose path contains the " - "string.\n"); - wprintf(L"\n"); - wprintf(L"Smart View Parsers:\n"); + wprintf_s( + L" Add-ins are disabled unless an add-in directory is configured in MFCMAPI Options.\n"); + wprintf_s(L" -On (or -%ws) Online mode. Bypass cached mode.\n", switchOnline.name()); + wprintf_s(L" -V (or -%ws) Verbose. Turn on all debug output.\n", switchVerbose.name()); + wprintf_s(L"\n"); + wprintf_s(L" MAPI Implementation Options:\n"); + wprintf_s(L" -%ws MAPI Version to load - supported values\n", switchVersion.name()); + wprintf_s(L" Supported values\n"); + wprintf_s(L" 0 - List all available MAPI binaries\n"); + wprintf_s(L" 1 - System MAPI\n"); + wprintf_s(L" 11 - Outlook 2003 (11)\n"); + wprintf_s(L" 12 - Outlook 2007 (12)\n"); + wprintf_s(L" 14 - Outlook 2010 (14)\n"); + wprintf_s(L" 15 - Outlook 2013 (15)\n"); + wprintf_s(L" 16 - Outlook 2016 (16)\n"); + wprintf_s(L" You can also pass a string, which will load the first MAPI whose path contains the " + "string.\n"); + wprintf_s(L"\n"); + wprintf_s(L"Smart View Parsers:\n"); // Print smart view options for (ULONG i = 1; i < SmartViewParserTypeArray.size(); i++) { - wprintf(L" %2lu %ws\n", i, SmartViewParserTypeArray[i].lpszName); + wprintf_s(L" %2lu %ws\n", i, SmartViewParserTypeArray[i].lpszName); } - wprintf(L"\n"); - wprintf(L"Folders:\n"); + wprintf_s(L"\n"); + wprintf_s(L"Folders:\n"); // Print Folders for (ULONG i = 1; i < mapi::NUM_DEFAULT_PROPS; i++) { - wprintf(L" %2lu %ws\n", i, mapi::FolderNames[i]); + wprintf_s(L" %2lu %ws\n", i, mapi::FolderNames[i]); } - wprintf(L"\n"); - wprintf(L"Examples:\n"); - wprintf(L" MrMAPI PR_DISPLAY_NAME\n"); - wprintf(L"\n"); - wprintf(L" MrMAPI 0x3001001e\n"); - wprintf(L" MrMAPI 3001001e\n"); - wprintf(L" MrMAPI 3001\n"); - wprintf(L"\n"); - wprintf(L" MrMAPI -n 12289\n"); - wprintf(L"\n"); - wprintf(L" MrMAPI -t PT_LONG\n"); - wprintf(L" MrMAPI -t 3102\n"); - wprintf(L" MrMAPI -t\n"); - wprintf(L"\n"); - wprintf(L" MrMAPI -s display\n"); - wprintf(L" MrMAPI -s display -t PT_LONG\n"); - wprintf(L" MrMAPI -t 102 -s display\n"); - wprintf(L"\n"); - wprintf(L" MrMAPI -d dispidReminderTime\n"); - wprintf(L" MrMAPI -d 0x8502\n"); - wprintf(L" MrMAPI -d -s reminder\n"); - wprintf(L" MrMAPI -d -n 34050\n"); - wprintf(L"\n"); - wprintf(L" MrMAPI -p 17 -i webview.txt -o parsed.txt"); + wprintf_s(L"\n"); + wprintf_s(L"Examples:\n"); + wprintf_s(L" MrMAPI PR_DISPLAY_NAME\n"); + wprintf_s(L"\n"); + wprintf_s(L" MrMAPI 0x3001001e\n"); + wprintf_s(L" MrMAPI 3001001e\n"); + wprintf_s(L" MrMAPI 3001\n"); + wprintf_s(L"\n"); + wprintf_s(L" MrMAPI -n 12289\n"); + wprintf_s(L"\n"); + wprintf_s(L" MrMAPI -t PT_LONG\n"); + wprintf_s(L" MrMAPI -t 3102\n"); + wprintf_s(L" MrMAPI -t\n"); + wprintf_s(L"\n"); + wprintf_s(L" MrMAPI -s display\n"); + wprintf_s(L" MrMAPI -s display -t PT_LONG\n"); + wprintf_s(L" MrMAPI -t 102 -s display\n"); + wprintf_s(L"\n"); + wprintf_s(L" MrMAPI -d dispidReminderTime\n"); + wprintf_s(L" MrMAPI -d 0x8502\n"); + wprintf_s(L" MrMAPI -d -s reminder\n"); + wprintf_s(L" MrMAPI -d -n 34050\n"); + wprintf_s(L"\n"); + wprintf_s(L" MrMAPI -p 17 -i webview.txt -o parsed.txt"); } } @@ -638,7 +642,8 @@ namespace cli options.mode = valid ? cmdmodeEntryID : cmdmodeHelp; if (!valid) - wprintf(L"Invalid -EntryID request: supply hex, an explicit profile/store, and one typed property.\n"); + wprintf_s( + L"Invalid -EntryID request: supply hex, an explicit profile/store, and one typed property.\n"); return; } diff --git a/UI/Dialogs/Editors/Editor.h b/UI/Dialogs/Editors/Editor.h index ed9dcb1d5..0de6d4749 100644 --- a/UI/Dialogs/Editors/Editor.h +++ b/UI/Dialogs/Editors/Editor.h @@ -50,7 +50,7 @@ namespace dialog::editor void SetStringf(ULONG id, LPCWSTR szMsg, ...) const; #ifdef CHECKFORMATPARAMS #undef SetStringf -#define SetStringf(i, fmt, ...) SetStringf(i, fmt, __VA_ARGS__), wprintf(fmt, __VA_ARGS__) +#define SetStringf(i, fmt, ...) SetStringf(i, fmt, __VA_ARGS__), wprintf_s(fmt, __VA_ARGS__) #endif void LoadString(ULONG id, UINT uidMsg) const; diff --git a/core/mapi/processor/dumpStore.cpp b/core/mapi/processor/dumpStore.cpp index 9a7e4fb94..f93c8e845 100644 --- a/core/mapi/processor/dumpStore.cpp +++ b/core/mapi/processor/dumpStore.cpp @@ -238,7 +238,7 @@ namespace mapi::processor if (m_szFolderPath.empty()) return; if (m_bOutputList) { - wprintf(L"Subject, Message Class, Filename\n"); + wprintf_s(L"Subject, Message Class, Filename\n"); return; } @@ -290,16 +290,16 @@ namespace mapi::processor const auto lpMessageClass = PpropFindProp(lpSRow->lpProps, lpSRow->cValues, CHANGE_PROP_TYPE(PR_MESSAGE_CLASS, PT_UNSPECIFIED)); - wprintf(L"\"%ws\"", szSubj.c_str()); + wprintf_s(L"\"%ws\"", szSubj.c_str()); if (lpMessageClass) { if (PT_STRING8 == PROP_TYPE(lpMessageClass->ulPropTag)) { - wprintf(L",\"%hs\"", lpMessageClass->Value.lpszA ? lpMessageClass->Value.lpszA : ""); + wprintf_s(L",\"%hs\"", lpMessageClass->Value.lpszA ? lpMessageClass->Value.lpszA : ""); } else if (PT_UNICODE == PROP_TYPE(lpMessageClass->ulPropTag)) { - wprintf(L",\"%ws\"", lpMessageClass->Value.lpszW ? lpMessageClass->Value.lpszW : L""); + wprintf_s(L",\"%ws\"", lpMessageClass->Value.lpszW ? lpMessageClass->Value.lpszW : L""); } } @@ -307,7 +307,7 @@ namespace mapi::processor if (bOutputMSG) szExt = L".msg"; // STRING_OK auto szFileName = file::BuildFileNameAndPath(szExt, szSubj, szFolderPath, &recordKey); - wprintf(L",\"%ws\"\n", szFileName.c_str()); + wprintf_s(L",\"%ws\"\n", szFileName.c_str()); } bool dumpStore::DoContentsTablePerRowWork(_In_ const _SRow* lpSRow, ULONG ulCurRow) diff --git a/core/smartview/AdditionalRenEntryIDs.cpp b/core/smartview/AdditionalRenEntryIDs.cpp index 959af0ae3..19608715d 100644 --- a/core/smartview/AdditionalRenEntryIDs.cpp +++ b/core/smartview/AdditionalRenEntryIDs.cpp @@ -116,7 +116,7 @@ namespace smartview } // Now we parse for real - parser->rewind(); + parser->rewindToStart(); if (wPersistDataCount && wPersistDataCount < _MaxEntriesSmall) { diff --git a/core/smartview/ExtendedFlags.cpp b/core/smartview/ExtendedFlags.cpp index f008e236a..e616878b0 100644 --- a/core/smartview/ExtendedFlags.cpp +++ b/core/smartview/ExtendedFlags.cpp @@ -100,7 +100,7 @@ namespace smartview } // Now we parse for real - parser->rewind(); + parser->rewindToStart(); if (ulNumFlags && ulNumFlags < _MaxEntriesSmall) { diff --git a/core/smartview/PCL.cpp b/core/smartview/PCL.cpp index 5c9dcae4d..556ef18b3 100644 --- a/core/smartview/PCL.cpp +++ b/core/smartview/PCL.cpp @@ -38,7 +38,7 @@ namespace smartview } // Now we parse for real - parser->rewind(); + parser->rewindToStart(); if (cXID && cXID < _MaxEntriesSmall) { diff --git a/core/smartview/WebViewPersistStream.cpp b/core/smartview/WebViewPersistStream.cpp index 6ef751ee0..dced1a50d 100644 --- a/core/smartview/WebViewPersistStream.cpp +++ b/core/smartview/WebViewPersistStream.cpp @@ -72,7 +72,7 @@ namespace smartview } // Now we parse for real - parser->rewind(); + parser->rewindToStart(); if (cWebViews && cWebViews < _MaxEntriesSmall) { diff --git a/core/smartview/block/binaryParser.h b/core/smartview/block/binaryParser.h index 50c95ca3a..2dfb8d967 100644 --- a/core/smartview/block/binaryParser.h +++ b/core/smartview/block/binaryParser.h @@ -24,7 +24,7 @@ namespace smartview bool empty() const noexcept { return offset == size; } void advance(size_t cb) noexcept { offset += cb; } - void rewind() noexcept { offset = 0; } + void rewindToStart() noexcept { offset = 0; } size_t getOffset() const noexcept { return offset; } void setOffset(size_t _offset) noexcept { offset = _offset; } const BYTE* getAddress() const noexcept { return bin.data() + offset; } diff --git a/core/utility/output.cpp b/core/utility/output.cpp index 93c184705..831931608 100644 --- a/core/utility/output.cpp +++ b/core/utility/output.cpp @@ -188,7 +188,7 @@ namespace output } else { - wprintf(L"%ws", szMsg.c_str()); + wprintf_s(L"%ws", szMsg.c_str()); } // print to to our debug output log file diff --git a/core/utility/output.h b/core/utility/output.h index 3fee8c49a..ac325a24b 100644 --- a/core/utility/output.h +++ b/core/utility/output.h @@ -64,20 +64,20 @@ namespace output #ifdef CHECKFORMATPARAMS #undef Outputf #define Outputf(ulDbgLvl, fFile, bPrintThreadTime, szMsg, ...) \ - Outputf((wprintf(szMsg, __VA_ARGS__), ulDbgLvl), fFile, bPrintThreadTime, szMsg, __VA_ARGS__) + Outputf((wprintf_s(szMsg, __VA_ARGS__), ulDbgLvl), fFile, bPrintThreadTime, szMsg, __VA_ARGS__) #endif #define OutputToFile(fFile, szMsg) Output((output::dbgLevel::NoDebug), (fFile), true, (szMsg)) void __cdecl OutputToFilef(_In_opt_ FILE* fFile, LPCWSTR szMsg, ...); #ifdef CHECKFORMATPARAMS #undef OutputToFilef -#define OutputToFilef(fFile, szMsg, ...) OutputToFilef((wprintf(szMsg, __VA_ARGS__), fFile), szMsg, __VA_ARGS__) +#define OutputToFilef(fFile, szMsg, ...) OutputToFilef((wprintf_s(szMsg, __VA_ARGS__), fFile), szMsg, __VA_ARGS__) #endif void __cdecl DebugPrint(dbgLevel ulDbgLvl, LPCWSTR szMsg, ...); #ifdef CHECKFORMATPARAMS #undef DebugPrint -#define DebugPrint(ulDbgLvl, szMsg, ...) DebugPrint((wprintf(szMsg, __VA_ARGS__), ulDbgLvl), szMsg, __VA_ARGS__) +#define DebugPrint(ulDbgLvl, szMsg, ...) DebugPrint((wprintf_s(szMsg, __VA_ARGS__), ulDbgLvl), szMsg, __VA_ARGS__) #endif void __cdecl DebugPrint(dbgLevel ulDbgLvl, LPCWSTR szMsg, va_list argList); @@ -90,7 +90,7 @@ namespace output #ifdef CHECKFORMATPARAMS #undef DebugPrintEx #define DebugPrintEx(ulDbgLvl, szClass, szFunc, szMsg, ...) \ - DebugPrintEx((wprintf(szMsg, __VA_ARGS__), ulDbgLvl), szClass, szFunc, szMsg, __VA_ARGS__) + DebugPrintEx((wprintf_s(szMsg, __VA_ARGS__), ulDbgLvl), szClass, szFunc, szMsg, __VA_ARGS__) #endif // We'll only output this information in debug builds. diff --git a/core/utility/strings.h b/core/utility/strings.h index dc3a8f58a..35a210b40 100644 --- a/core/utility/strings.h +++ b/core/utility/strings.h @@ -13,8 +13,8 @@ namespace strings std::wstring format(LPCWSTR szMsg, ...); #ifdef CHECKFORMATPARAMS #undef format -// Yes, this is awkward, but it allows wprintf to be evaluated for format paramater checking without breaking namespaces. -#define format(fmt, ...) format((wprintf(fmt, __VA_ARGS__), fmt), __VA_ARGS__) +// Allows format parameter checking without breaking namespaces. +#define format(fmt, ...) format((wprintf_s(fmt, __VA_ARGS__), fmt), __VA_ARGS__) #endif std::wstring formatmessagesys(DWORD dwID); diff --git a/fuzz/fuzz.cpp b/fuzz/fuzz.cpp index 1367be2c5..e1c6a545e 100644 --- a/fuzz/fuzz.cpp +++ b/fuzz/fuzz.cpp @@ -31,7 +31,7 @@ void test(const SBinary hex) for (const auto parser : SmartViewParserTypeArray) { if (parser.type == parserType::NOPARSING) continue; - //wprintf(L"Testing %ws\r\n", addin::AddInStructTypeToString(parser.type).c_str()); + //wprintf_s(L"Testing %ws\r\n", addin::AddInStructTypeToString(parser.type).c_str()); const auto start = std::chrono::high_resolution_clock::now(); (void) smartview::InterpretBinary(hex, parser.type, nullptr); const auto end = std::chrono::high_resolution_clock::now(); @@ -40,12 +40,12 @@ void test(const SBinary hex) if (doLog) { - wprintf(L"Test %lld\r\n", testnum); - wprintf(L"%-40s %-15s %-15s\n", L"Parser Type", L"Total Time (ms)", L"Time per Test (ms)"); + wprintf_s(L"Test %lld\r\n", testnum); + wprintf_s(L"%-40s %-15s %-15s\n", L"Parser Type", L"Total Time (ms)", L"Time per Test (ms)"); for (const auto parser : SmartViewParserTypeArray) { if (parser.type == parserType::NOPARSING) continue; - wprintf( + wprintf_s( L"%-40ws %-15f %-15f\n", addin::AddInStructTypeToString(parser.type).c_str(), runtimes[static_cast(parser.type)].count(), @@ -63,7 +63,7 @@ FUZZ_EXPORT int __cdecl LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { std::call_once(_initFlag, EnsureInit); const SBinary input = {static_cast(size), (LPBYTE) (data)}; - //wprintf(L"Fuzzing: %ws\r\n", strings::BinToHexString(&input, true).c_str()); + //wprintf_s(L"Fuzzing: %ws\r\n", strings::BinToHexString(&input, true).c_str()); test(input); return 0; } From c90b1e1bf0262a2077e727b95d14c4aaadb35df3 Mon Sep 17 00:00:00 2001 From: Stephen Griffin Date: Sun, 25 Oct 2026 14:48:45 -0400 Subject: [PATCH 2/3] Replace live MAPI integration tests with mocked unit coverage Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- CONTRIBUTING.md | 1 + UnitTest/tests/compressedrtftest.cpp | 252 +++++++++------------------ 2 files changed, 86 insertions(+), 167 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0558d83c9..f32bdc5fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -74,6 +74,7 @@ The npm scripts automatically find MSBuild via vswhere, so no Developer Command * *Make sure to substitute your own name and topic in this command* * * Once you have a branch, make your changes and commit them to the local branch. * Run `npm run test` to verify your changes don't break existing tests. +* Native unit tests must run without installed Outlook/MAPI, profiles, or mailbox access. Mock MAPI entry points and provider interfaces; do not add live-MAPI integration tests to the unit-test project. * All submissions require a review and pull requests are how those happen. Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on pull requests. diff --git a/UnitTest/tests/compressedrtftest.cpp b/UnitTest/tests/compressedrtftest.cpp index 130c48c2f..f74a09495 100644 --- a/UnitTest/tests/compressedrtftest.cpp +++ b/UnitTest/tests/compressedrtftest.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include @@ -183,6 +182,15 @@ namespace compressedrtftest // Literal LZFu tokens followed by the end reference to dictionary offset 207 + 12. const std::wstring lzfu = L"1c0000000c0000004c5a4675236427fa007b5c727466312074106573747d0db0"; + std::vector MelaBytes(const std::vector& input) + { + const ULONG header[]{static_cast(input.size() + 12), static_cast(input.size()), 0x414C454D, 0}; + std::vector bytes(sizeof(header) + input.size()); + Assert::AreEqual(0, memcpy_s(bytes.data(), bytes.size(), header, sizeof(header))); + std::copy(input.begin(), input.end(), bytes.begin() + sizeof(header)); + return bytes; + } + class TestRtfProperty final : public IMAPIProp { public: @@ -268,172 +276,6 @@ namespace compressedrtftest ULONG m_refs{1}; }; - void RequireMapi() - { - const auto initialized = MAPIInitialize(nullptr); - Assert::IsTrue( - SUCCEEDED(initialized), L"Real decoder integration requires an installed matching-bitness MAPI runtime."); - MAPIUninitialize(); - } - - TEST_CLASS(compressedrtfintegrationtest) - { - public: - TEST_CLASS_INITIALIZE(initialize) { unittest::init(); } - TEST_METHOD_INITIALIZE(setup) - { - const auto hRes = CoInitializeEx(nullptr, COINIT_MULTITHREADED); - Assert::IsTrue(SUCCEEDED(hRes) || hRes == RPC_E_CHANGED_MODE); - m_uninitialize = SUCCEEDED(hRes); - const auto initialized = MAPIInitialize(nullptr); - m_mapiInitialized = SUCCEEDED(initialized); - Assert::IsTrue(m_mapiInitialized, L"These tests require matching-bitness installed MAPI."); - } - TEST_METHOD_CLEANUP(cleanup) - { - const auto removed = m_path.empty() || DeleteFileW(m_path.c_str()); - if (m_mapiInitialized) MAPIUninitialize(); - if (m_uninitialize) CoUninitialize(); - Assert::IsTrue(removed != FALSE, L"Could not remove the owned temporary MSG file."); - } - - TEST_METHOD(DecompressesMelaAndFormattedHex) - { - RequireMapi(); - std::vector output; - Assert::AreEqual( - S_OK, - mapi::DecompressRtfHex(L" 0x18 000000\r\n0c000000 4d454c41 00000000 7b5c7274663120746573747d", output)); - Assert::AreEqual(strings::HexStringToBin(L"7b5c7274663120746573747d"), output); - } - - TEST_METHOD(DecompressesLzfu) - { - RequireMapi(); - std::vector output; - Assert::AreEqual(S_OK, mapi::DecompressRtfHex(lzfu, output)); - Assert::AreEqual(strings::HexStringToBin(L"7b5c7274663120746573747d"), output); - } - - TEST_METHOD(PreservesEmbeddedNullAndHighBytes) - { - RequireMapi(); - std::vector output; - Assert::AreEqual(S_OK, mapi::DecompressRtfHex(L"10000000040000004d454c410000000000ff0080", output)); - Assert::AreEqual(std::vector({0, 0xff, 0, 0x80}), output); - } - - TEST_METHOD(RejectsDecodedLengthMismatch) - { - RequireMapi(); - auto hex = lzfu; - hex[9] = L'd'; - std::vector output{1}; - Assert::AreEqual(MAPI_E_CORRUPT_DATA, mapi::DecompressRtfHex(hex, output)); - Assert::IsTrue(output.empty()); - } - - TEST_METHOD(AcceptsEmptyMela) - { - RequireMapi(); - std::vector output{1}; - Assert::AreEqual(S_OK, mapi::DecompressRtfHex(L"0c000000000000004d454c4100000000", output)); - Assert::IsTrue(output.empty()); - } - - TEST_METHOD(CompressesAndRoundTripsExactBytes) - { - RequireMapi(); - for (const auto& input : - {strings::HexStringToBin(L"7b5c7274663120746573747d"), - std::vector{0, 0xff, 0, 0x80}, - std::vector{}, - std::vector(65536, 'a')}) - { - std::vector compressed{1}; - Assert::AreEqual(S_OK, mapi::CompressRtf(input, compressed)); - Assert::IsTrue(compressed.size() >= 16); - std::vector output{1}; - Assert::AreEqual( - S_OK, - mapi::DecompressRtfHex(strings::BinToHexString(compressed, false), output), - strings::format( - L"Input bytes: %zu; header: %ws", - input.size(), - strings::BinToHexString(compressed.data(), min(size_t{16}, compressed.size()), false).c_str()) - .c_str()); - Assert::AreEqual(input, output); - } - } - - TEST_METHOD(CompressesAndRoundTripsBeyondFormerRawSizeLimit) - { - RequireMapi(); - const std::vector input(17 * 1024 * 1024, 'a'); - std::vector compressed; - Assert::AreEqual(S_OK, mapi::CompressRtf(input, compressed)); - std::vector output; - Assert::AreEqual(S_OK, mapi::DecompressRtfHex(strings::BinToHexString(compressed, false), output)); - Assert::AreEqual(input, output); - } - - TEST_METHOD(CompressesBeyondFormerCompressedSizeLimit) - { - RequireMapi(); - std::vector input(4 * 1024 * 1024); - ULONG state = 1; - for (auto& byte : input) - { - state ^= state << 13; - state ^= state >> 17; - state ^= state << 5; - byte = static_cast(state); - } - - std::vector compressed{1}; - Assert::AreEqual(S_OK, mapi::CompressRtf(input, compressed)); - Assert::IsTrue(compressed.size() > 4 * 1024 * 1024); - std::vector output; - Assert::AreEqual(S_OK, mapi::DecompressRtf(compressed, output)); - Assert::AreEqual(input, output); - } - - TEST_METHOD(SavesMessageAndReadsExactBytesAfterReopening) - { - wchar_t directory[MAX_PATH]{}; - wchar_t path[MAX_PATH]{}; - const auto length = GetTempPathW(_countof(directory), directory); - Assert::IsTrue(length != 0 && length < _countof(directory)); - Assert::IsTrue(GetTempFileNameW(directory, L"rtf", 0, path) != 0); - m_path = path; - Microsoft::WRL::ComPtr message; - Microsoft::WRL::ComPtr storage; - Assert::AreEqual(S_OK, file::CreateNewMSG(m_path, true, message.GetAddressOf(), storage.GetAddressOf())); - const auto input = strings::HexStringToBin(L"7b5c72746631207065727369737465647d"); - std::vector compressed; - Assert::AreEqual(S_OK, mapi::CompressRtf(input, compressed)); - Assert::AreEqual(S_OK, mapi::SaveCompressedRtf(message.Get(), compressed)); - Assert::AreEqual(S_OK, storage->Commit(STGC_DEFAULT)); - message.Reset(); - storage.Reset(); - auto hRes = S_OK; - message.Attach(file::LoadMSGToMessage(m_path, &hRes)); - Assert::AreEqual(S_OK, hRes); - Assert::IsNotNull(message.Get()); - std::vector reopened; - Assert::AreEqual(S_OK, mapi::ReadCompressedRtf(message.Get(), reopened)); - Assert::AreEqual(compressed, reopened); - std::vector output; - Assert::AreEqual(S_OK, mapi::DecompressRtfHex(strings::BinToHexString(reopened, false), output)); - Assert::AreEqual(input, output); - } - - private: - bool m_uninitialize{}; - bool m_mapiInitialized{}; - std::wstring m_path; - }; - TEST_CLASS(compressedrtftest){public : TEST_CLASS_INITIALIZE(initialize){unittest::init(); } // namespace compressedrtftest TEST_METHOD(RejectsEmptyOddAndNonHexInputAndClearsOutput) @@ -510,6 +352,82 @@ TEST_CLASS(compressedrtfstreamtest) Assert::AreEqual(1UL, wrapCalls); } + TEST_METHOD(FormattedHexPassesExactMelaBytesToWrapper) + { + std::vector output; + Assert::AreEqual( + S_OK, + mapi::DecompressRtfHex(L" 0x18 000000\r\n0c000000 4d454c41 00000000 7b5c7274663120746573747d", output)); + Assert::AreEqual(strings::HexStringToBin(mela), wrappedInput); + Assert::AreEqual(wrappedOutput, output); + } + + TEST_METHOD(DecodedStreamPreservesEmbeddedNullAndHighBytes) + { + wrappedOutput = {0, 0xff, 0, 0x80}; + std::vector output; + Assert::AreEqual(S_OK, mapi::DecompressRtf(MelaBytes(wrappedOutput), output)); + Assert::AreEqual(wrappedOutput, output); + } + + TEST_METHOD(EmptyDecodedStreamAcceptsEmptyMela) + { + wrappedOutput.clear(); + std::vector output{1}; + Assert::AreEqual(S_OK, mapi::DecompressRtf(MelaBytes({}), output)); + Assert::IsTrue(output.empty()); + Assert::AreEqual(1UL, wrapCalls); + } + + TEST_METHOD(CompressionPassesExactBytesIncludingEmptyInputToWrapper) + { + for (const auto& input : + {strings::HexStringToBin(L"7b5c7274663120746573747d"), + std::vector{0, 0xff, 0, 0x80}, + std::vector{}, + std::vector(65536, 'a')}) + { + wrappedOutput = MelaBytes(input); + std::vector output{1}; + Assert::AreEqual(S_OK, mapi::CompressRtf(input, output)); + Assert::AreEqual(input, wrappedInput); + Assert::AreEqual(wrappedOutput, output); + } + } + + TEST_METHOD(ConversionStreamsBeyondFormerSizeLimits) + { + const std::vector input(17 * 1024 * 1024, 'a'); + wrappedOutput = MelaBytes(input); + std::vector compressed; + Assert::AreEqual(S_OK, mapi::CompressRtf(input, compressed)); + Assert::AreEqual(input, wrappedInput); + Assert::AreEqual(wrappedOutput, compressed); + Assert::IsTrue(compressed.size() > 4 * 1024 * 1024); + wrappedOutput = input; + std::vector output; + Assert::AreEqual(S_OK, mapi::DecompressRtf(compressed, output)); + Assert::AreEqual(input, output); + } + + TEST_METHOD(SavesAndReadsMockPropertyBeforeDecodingWrapperOutput) + { + TestRtfProperty prop; + const auto input = wrappedOutput; + wrappedOutput = MelaBytes(input); + std::vector compressed; + Assert::AreEqual(S_OK, mapi::CompressRtf(input, compressed)); + Assert::AreEqual(S_OK, mapi::SaveCompressedRtf(&prop, compressed)); + std::vector stored; + Assert::AreEqual(S_OK, mapi::ReadCompressedRtf(&prop, stored)); + Assert::AreEqual(compressed, stored); + wrappedOutput = input; + std::vector output; + Assert::AreEqual(S_OK, mapi::DecompressRtf(stored, output)); + Assert::AreEqual(input, output); + Assert::AreEqual(1UL, prop.saves); + } + TEST_METHOD(ReportsWrapperFailure) { wrapResult = E_FAIL; From b6ddd603ccf3b3a6bf5294176538813436ff0b9d Mon Sep 17 00:00:00 2001 From: Stephen Griffin Date: Sun, 25 Oct 2026 14:49:36 -0400 Subject: [PATCH 3/3] Remove unsolicited contributor documentation change Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- CONTRIBUTING.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f32bdc5fc..0558d83c9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -74,7 +74,6 @@ The npm scripts automatically find MSBuild via vswhere, so no Developer Command * *Make sure to substitute your own name and topic in this command* * * Once you have a branch, make your changes and commit them to the local branch. * Run `npm run test` to verify your changes don't break existing tests. -* Native unit tests must run without installed Outlook/MAPI, profiles, or mailbox access. Mock MAPI entry points and provider interfaces; do not add live-MAPI integration tests to the unit-test project. * All submissions require a review and pull requests are how those happen. Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on pull requests.