<commit_before>// Collection of useful MAPI functions
#include <StdAfx.h>
#include <MAPI/MAPIFunctions.h>
#include <core/utility/strings.h>
#include <MAPI/MAPIABFunctions.h>
#include <Interpret/InterpretProp.h>
#include <core/mapi/extraPropTags.h>
#include <core/mapi/mapiProgress.h>
#include <core/interpret/guid.h>
#include <core/mapi/cache/namedPropCache.h>
#include <Interpret/SmartView/SmartView.h>
#include <core/mapi/mapiMemory.h>
#include <core/utility/registry.h>
#include <IO/MFCOutput.h>
#include <core/utility/output.h>
#include <core/mapi/mapiFunctions.h>
#include <core/mapi/mapiOutput.h>

namespace mapi
{
	// I don't use MAPIOID.h, which is needed to deal with PR_ATTACH_TAG, but if I did, here's how to include it
	/*
	#include <mapiguid.h>
	#define USES_OID_TNEF
	#define USES_OID_OLE
	#define USES_OID_OLE1
	#define USES_OID_OLE1_STORAGE
	#define USES_OID_OLE2
	#define USES_OID_OLE2_STORAGE
	#define USES_OID_MAC_BINARY
	#define USES_OID_MIMETAG
	#define INITOID
	// Major hack to get MAPIOID to compile
	#define _MAC
	#include <MAPIOID.h>
	#undef _MAC
	*/

	LPUNKNOWN CallOpenEntry(
		_In_opt_ LPMDB lpMDB,
		_In_opt_ LPADRBOOK lpAB,
		_In_opt_ LPMAPICONTAINER lpContainer,
		_In_opt_ LPMAPISESSION lpMAPISession,
		ULONG cbEntryID,
		_In_opt_ LPENTRYID lpEntryID,
		_In_opt_ LPCIID lpInterface,
		ULONG ulFlags,
		_Out_opt_ ULONG* ulObjTypeRet) // optional - can be NULL
	{
		auto hRes = S_OK;
		ULONG ulObjType = 0;
		LPUNKNOWN lpUnk = nullptr;
		ULONG ulNoCacheFlags = 0;

		if (registry::forceMapiNoCache)
		{
			ulFlags |= MAPI_NO_CACHE;
		}

		// in case we need to retry without MAPI_NO_CACHE - do not add MAPI_NO_CACHE to ulFlags after this point
		if (MAPI_NO_CACHE & ulFlags) ulNoCacheFlags = ulFlags & ~MAPI_NO_CACHE;

		if (lpInterface && fIsSet(DBGGeneric))
		{
			auto szGuid = guid::GUIDToStringAndName(lpInterface);
			output::DebugPrint(DBGGeneric, L"CallOpenEntry: OpenEntry asking for %ws\n", szGuid.c_str());
		}

		if (lpMDB)
		{
			output::DebugPrint(DBGGeneric, L"CallOpenEntry: Calling OpenEntry on MDB with ulFlags = 0x%X\n", ulFlags);
			hRes = WC_MAPI(lpMDB->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, &ulObjType, &lpUnk));
			if (hRes == MAPI_E_UNKNOWN_FLAGS && ulNoCacheFlags)
			{
				output::DebugPrint(
					DBGGeneric,
					L"CallOpenEntry 2nd attempt: Calling OpenEntry on MDB with ulFlags = 0x%X\n",
					ulNoCacheFlags);
				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
				hRes = WC_MAPI(lpMDB->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulNoCacheFlags, &ulObjType, &lpUnk));
			}

			if (FAILED(hRes))
			{
				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
			}
		}

		if (lpAB && !lpUnk)
		{
			output::DebugPrint(DBGGeneric, L"CallOpenEntry: Calling OpenEntry on AB with ulFlags = 0x%X\n", ulFlags);
			hRes = WC_MAPI(lpAB->OpenEntry(
				cbEntryID,
				lpEntryID,
				nullptr, // no interface
				ulFlags,
				&ulObjType,
				&lpUnk));
			if (hRes == MAPI_E_UNKNOWN_FLAGS && ulNoCacheFlags)
			{
				output::DebugPrint(
					DBGGeneric,
					L"CallOpenEntry 2nd attempt: Calling OpenEntry on AB with ulFlags = 0x%X\n",
					ulNoCacheFlags);

				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
				hRes = WC_MAPI(lpAB->OpenEntry(
					cbEntryID,
					lpEntryID,
					nullptr, // no interface
					ulNoCacheFlags,
					&ulObjType,
					&lpUnk));
			}

			if (FAILED(hRes))
			{
				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
			}
		}

		if (lpContainer && !lpUnk)
		{
			output::DebugPrint(
				DBGGeneric, L"CallOpenEntry: Calling OpenEntry on Container with ulFlags = 0x%X\n", ulFlags);
			hRes = WC_MAPI(lpContainer->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, &ulObjType, &lpUnk));
			if (hRes == MAPI_E_UNKNOWN_FLAGS && ulNoCacheFlags)
			{
				output::DebugPrint(
					DBGGeneric,
					L"CallOpenEntry 2nd attempt: Calling OpenEntry on Container with ulFlags = 0x%X\n",
					ulNoCacheFlags);

				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
				hRes = WC_MAPI(
					lpContainer->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulNoCacheFlags, &ulObjType, &lpUnk));
			}

			if (FAILED(hRes))
			{
				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
			}
		}

		if (lpMAPISession && !lpUnk)
		{
			output::DebugPrint(
				DBGGeneric, L"CallOpenEntry: Calling OpenEntry on Session with ulFlags = 0x%X\n", ulFlags);
			hRes = WC_MAPI(lpMAPISession->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, &ulObjType, &lpUnk));
			if (hRes == MAPI_E_UNKNOWN_FLAGS && ulNoCacheFlags)
			{
				output::DebugPrint(
					DBGGeneric,
					L"CallOpenEntry 2nd attempt: Calling OpenEntry on Session with ulFlags = 0x%X\n",
					ulNoCacheFlags);

				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
				hRes = WC_MAPI(
					lpMAPISession->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulNoCacheFlags, &ulObjType, &lpUnk));
			}

			if (FAILED(hRes))
			{
				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
			}
		}

		if (lpUnk)
		{
			auto szFlags = smartview::InterpretNumberAsStringProp(ulObjType, PR_OBJECT_TYPE);
			output::DebugPrint(
				DBGGeneric, L"OnOpenEntryID: Got object of type 0x%08X = %ws\n", ulObjType, szFlags.c_str());
		}

		if (ulObjTypeRet) *ulObjTypeRet = ulObjType;

		return lpUnk;
	}

	// Concatenate two property arrays without duplicates
	_Check_return_ LPSPropTagArray
	ConcatSPropTagArrays(_In_ LPSPropTagArray lpArray1, _In_opt_ LPSPropTagArray lpArray2)
	{
		auto hRes = S_OK;

		// Add the sizes of the passed in arrays (0 if they were NULL)
		auto iNewArraySize = lpArray1 ? lpArray1->cValues : 0;

		if (lpArray2 && lpArray1)<commit_msg>Remove smartview from mapifunctions<commit_after>// Collection of useful MAPI functions
#include <StdAfx.h>
#include <MAPI/MAPIFunctions.h>
#include <core/utility/strings.h>
#include <MAPI/MAPIABFunctions.h>
#include <Interpret/InterpretProp.h>
#include <core/mapi/extraPropTags.h>
#include <core/mapi/mapiProgress.h>
#include <core/interpret/guid.h>
#include <core/mapi/cache/namedPropCache.h>
#include <core/mapi/mapiMemory.h>
#include <core/utility/registry.h>
#include <IO/MFCOutput.h>
#include <core/utility/output.h>
#include <core/mapi/mapiFunctions.h>
#include <core/mapi/mapiOutput.h>
#include <core/interpret/flags.h>

namespace mapi
{
	// I don't use MAPIOID.h, which is needed to deal with PR_ATTACH_TAG, but if I did, here's how to include it
	/*
	#include <mapiguid.h>
	#define USES_OID_TNEF
	#define USES_OID_OLE
	#define USES_OID_OLE1
	#define USES_OID_OLE1_STORAGE
	#define USES_OID_OLE2
	#define USES_OID_OLE2_STORAGE
	#define USES_OID_MAC_BINARY
	#define USES_OID_MIMETAG
	#define INITOID
	// Major hack to get MAPIOID to compile
	#define _MAC
	#include <MAPIOID.h>
	#undef _MAC
	*/

	LPUNKNOWN CallOpenEntry(
		_In_opt_ LPMDB lpMDB,
		_In_opt_ LPADRBOOK lpAB,
		_In_opt_ LPMAPICONTAINER lpContainer,
		_In_opt_ LPMAPISESSION lpMAPISession,
		ULONG cbEntryID,
		_In_opt_ LPENTRYID lpEntryID,
		_In_opt_ LPCIID lpInterface,
		ULONG ulFlags,
		_Out_opt_ ULONG* ulObjTypeRet) // optional - can be NULL
	{
		auto hRes = S_OK;
		ULONG ulObjType = 0;
		LPUNKNOWN lpUnk = nullptr;
		ULONG ulNoCacheFlags = 0;

		if (registry::forceMapiNoCache)
		{
			ulFlags |= MAPI_NO_CACHE;
		}

		// in case we need to retry without MAPI_NO_CACHE - do not add MAPI_NO_CACHE to ulFlags after this point
		if (MAPI_NO_CACHE & ulFlags) ulNoCacheFlags = ulFlags & ~MAPI_NO_CACHE;

		if (lpInterface && fIsSet(DBGGeneric))
		{
			auto szGuid = guid::GUIDToStringAndName(lpInterface);
			output::DebugPrint(DBGGeneric, L"CallOpenEntry: OpenEntry asking for %ws\n", szGuid.c_str());
		}

		if (lpMDB)
		{
			output::DebugPrint(DBGGeneric, L"CallOpenEntry: Calling OpenEntry on MDB with ulFlags = 0x%X\n", ulFlags);
			hRes = WC_MAPI(lpMDB->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, &ulObjType, &lpUnk));
			if (hRes == MAPI_E_UNKNOWN_FLAGS && ulNoCacheFlags)
			{
				output::DebugPrint(
					DBGGeneric,
					L"CallOpenEntry 2nd attempt: Calling OpenEntry on MDB with ulFlags = 0x%X\n",
					ulNoCacheFlags);
				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
				hRes = WC_MAPI(lpMDB->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulNoCacheFlags, &ulObjType, &lpUnk));
			}

			if (FAILED(hRes))
			{
				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
			}
		}

		if (lpAB && !lpUnk)
		{
			output::DebugPrint(DBGGeneric, L"CallOpenEntry: Calling OpenEntry on AB with ulFlags = 0x%X\n", ulFlags);
			hRes = WC_MAPI(lpAB->OpenEntry(
				cbEntryID,
				lpEntryID,
				nullptr, // no interface
				ulFlags,
				&ulObjType,
				&lpUnk));
			if (hRes == MAPI_E_UNKNOWN_FLAGS && ulNoCacheFlags)
			{
				output::DebugPrint(
					DBGGeneric,
					L"CallOpenEntry 2nd attempt: Calling OpenEntry on AB with ulFlags = 0x%X\n",
					ulNoCacheFlags);

				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
				hRes = WC_MAPI(lpAB->OpenEntry(
					cbEntryID,
					lpEntryID,
					nullptr, // no interface
					ulNoCacheFlags,
					&ulObjType,
					&lpUnk));
			}

			if (FAILED(hRes))
			{
				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
			}
		}

		if (lpContainer && !lpUnk)
		{
			output::DebugPrint(
				DBGGeneric, L"CallOpenEntry: Calling OpenEntry on Container with ulFlags = 0x%X\n", ulFlags);
			hRes = WC_MAPI(lpContainer->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, &ulObjType, &lpUnk));
			if (hRes == MAPI_E_UNKNOWN_FLAGS && ulNoCacheFlags)
			{
				output::DebugPrint(
					DBGGeneric,
					L"CallOpenEntry 2nd attempt: Calling OpenEntry on Container with ulFlags = 0x%X\n",
					ulNoCacheFlags);

				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
				hRes = WC_MAPI(
					lpContainer->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulNoCacheFlags, &ulObjType, &lpUnk));
			}

			if (FAILED(hRes))
			{
				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
			}
		}

		if (lpMAPISession && !lpUnk)
		{
			output::DebugPrint(
				DBGGeneric, L"CallOpenEntry: Calling OpenEntry on Session with ulFlags = 0x%X\n", ulFlags);
			hRes = WC_MAPI(lpMAPISession->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, &ulObjType, &lpUnk));
			if (hRes == MAPI_E_UNKNOWN_FLAGS && ulNoCacheFlags)
			{
				output::DebugPrint(
					DBGGeneric,
					L"CallOpenEntry 2nd attempt: Calling OpenEntry on Session with ulFlags = 0x%X\n",
					ulNoCacheFlags);

				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
				hRes = WC_MAPI(
					lpMAPISession->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulNoCacheFlags, &ulObjType, &lpUnk));
			}

			if (FAILED(hRes))
			{
				if (lpUnk) lpUnk->Release();
				lpUnk = nullptr;
			}
		}

		if (lpUnk)
		{
			auto szFlags = flags::InterpretFlags(PROP_ID(PR_OBJECT_TYPE), static_cast<LONG>(ulObjType));
			output::DebugPrint(
				DBGGeneric, L"OnOpenEntryID: Got object of type 0x%08X = %ws\n", ulObjType, szFlags.c_str());
		}

		if (ulObjTypeRet) *ulObjTypeRet = ulObjType;

		return lpUnk;
	}

	// Concatenate two property arrays without duplicates
	_Check_return_ LPSPropTagArray
	ConcatSPropTagArrays(_In_ LPSPropTagArray lpArray1, _In_opt_ LPSPropTagArray lpArray2)
	{
		auto hRes = S_OK;

		// Add the sizes of the passed in arrays (0 if they were NULL)
		auto iNewArraySize = lpArray1 ? lpArray1->cValues : 0;

		if (lpArray2 && lpArray1)
{'fraction_non_alphanumeric': 0.11506800286327845, 'fraction_numerical': 0.0051896921975662135, 'mean_word_length': 3.9021929824561403, 'pattern_counts': {'":': 0, '<': 40, '<?xml version=': 0, '>': 74, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4973237', 'n_tokens_mistral': 4977, 'n_tokens_neox': 4345, 'n_words': 942}