Beispiel #1
0
void ImageController::Replace(const std::wstring& sNewImage)
{
	::DeleteFile(m_sImageZipFile.c_str());

	std::string sCheckSum = CStdStringA(CMD5Checksum::GetMD5(CStdString(sNewImage).c_str()));
	
	std::wstring sCheckSumFile = sNewImage + L".checksum";
	std::ofstream oFile(CStdStringA(sCheckSumFile), std::ios::out | std::ios::trunc);

	oFile << sCheckSum;
	oFile.close();

	ZipWrapper zw(m_sImageZipFile);
	zw.AddFileToZip(sNewImage);
	zw.AddFileToZip(sCheckSumFile);
}
void CompoundFileStore::AddNewFile( const std::string& sUniqueName, const std::tstring& sFile )
{
    CIndexedStorage* pStorage = GetRootStorage();

    CIndexedStorage* pInnerStorage = pStorage->OpenStorage( sUniqueName.c_str() );
    if( pInnerStorage )
    {
        pInnerStorage->Release();
        throw std::exception("cannot add file as ID already exists");
    }

    pInnerStorage = pStorage->CreateStorage( sUniqueName.c_str() );
    CIndexedStream* pInnerStream = pInnerStorage->CreateStream( "FileData" );
    BSTR bPW = NULL;
    HRESULT hr = pInnerStream->CopyFromFile( sFile.c_str(), bPW );

    pInnerStorage->Release();
    pInnerStream->Release();


    if( FAILED(hr) )
    {
        _com_error err(hr);
        throw std::exception(CStdStringA(err.ErrorMessage()));
    }

    m_mUniqueNameToFiles[sUniqueName] = sFile;

}
void CompoundFileStore::StoreFile( const std::string& sUniqueName )
{
    std::tstring sFile = m_mUniqueNameToFiles[sUniqueName];
    if( sFile.empty() )
    {
        throw std::exception("ID is empty - cannot store file");
    }

    if((_taccess(sFile.c_str() ,00) == -1 ) || (_taccess(sFile.c_str() ,02) == -1))
    {
        throw std::exception("Cannot access local copy of file - cannot store.");
    }

    CIndexedStorage* pStorage = GetRootStorage();

    CIndexedStorage* pInnerStorage = pStorage->OpenStorage( sUniqueName.c_str() );
    if( !pInnerStorage )
    {
        throw std::exception("no stream in store for ID - cannot store.");
    }

    CIndexedStream* pInnerStream = pInnerStorage->OpenStream( "FileData" );
    BSTR bPW = NULL;
    HRESULT hr = pInnerStream->CopyFromFile( sFile.c_str(), bPW );

    pInnerStorage->Release();
    pInnerStream->Release();

    if( FAILED(hr) )
    {
        _com_error err(hr);
        throw std::exception(CStdStringA(err.ErrorMessage()));
    }

}
std::tstring CompoundFileStore::GetFile( const std::string& sUniqueName )
{
    if( m_mUniqueNameToFiles[sUniqueName] != _T("") )
        return m_mUniqueNameToFiles[sUniqueName];

    TCHAR sTempDir[MAX_PATH];
    TCHAR sTempFileName[MAX_PATH];
    GetTempPath(MAX_PATH, sTempDir);
    GetTempFileName(sTempDir, _T("W3T"), 0, sTempFileName);

    CIndexedStorage* pStorage = GetRootStorage();

    CIndexedStorage* pInnerStorage = pStorage->OpenStorage( sUniqueName.c_str() , STGM_DIRECT|STGM_READ|STGM_SHARE_EXCLUSIVE);
    if( !pInnerStorage )
        return _T("");

    CIndexedStream* pInnerStream = pInnerStorage->OpenStream( "FileData" ,STGM_DIRECT|STGM_READ|STGM_SHARE_EXCLUSIVE);
    CComBSTR bPW = NULL;
    HRESULT hr = pInnerStream->WriteToFile(sTempFileName, bPW, false);

    pInnerStream->Release();
    pInnerStorage->Release();

    if( FAILED(hr) )
    {
        _com_error err(hr);
        throw std::exception(CStdStringA(err.ErrorMessage()));
    }

    m_mUniqueNameToFiles[sUniqueName] = sTempFileName;

    return sTempFileName;
}
Beispiel #5
0
DOCSObjects::IProfilePtr DMTests_Helper::GetProfile(long lDocNum)
{
	_variant_t vIndex;
	vIndex.vt	= VT_I4;
	vIndex.lVal	= lDocNum;

	DOCSObjects::IProfilePtr pProfile = m_pLibrary->GetProfile(vIndex);
	if(pProfile == NULL)
	{
		CStdString sMsg;
		sMsg.Format(_T("Failed to retrieve profile for document %d"), lDocNum);
		throw std::exception(CStdStringA(sMsg));
	}
	return pProfile;
}
void TestCompareModule::TestAutomationOfWdfCreation()
{
	OptionGuard opGuard("DocFormat");
	Workshare::OptionApi::SetInt(L"DocFormat", -1); // WDF
	std::map<CStdString, CStdString> pairedDocuments = HelperClass::GetOriginalModifiedDocuments(TEST_FOLDER, HelperClass::WORD, HelperClass::WORD);

	assertMessage(!pairedDocuments.empty(), _T("Please provide sample .doc files with required naming convention to create Wdf file"));

	for each(std::pair<CStdString, CStdString>iterator in pairedDocuments)
	{
		Gen::CFilePath original(iterator.first);
		Gen::CFilePath modified(iterator.second);

		CStdString sOutfile = TEST_RESULTS_OUTPUT_FOLDER
			+ original.GetFileNameNoExtension() + _T("__")
			+ modified.GetFileNameNoExtension() + _T(".wdf");
		if (::CGeneral::FileExists(sOutfile.c_str()))
			::DeleteFile(sOutfile.c_str());

		CStdString sCommandLine = _T("\"") + HelperClass::GetInstallPath() + _T("DeltaVw.exe\"");
		sCommandLine += _T(" /original=\"") + iterator.first + _T("\"");
		sCommandLine += _T(" /modified=\"") + iterator.second + _T("\"");
		sCommandLine += _T(" /outfile=\"") + sOutfile + _T("\"");
		sCommandLine += _T(" /V /S");

		PROCESS_INFORMATION pi = {0};
		STARTUPINFO si = {0};
		si.cb = sizeof(STARTUPINFO);
		si.wShowWindow = SW_SHOW;
		si.dwFlags = STARTF_USESHOWWINDOW;

		BOOL bRet = ::CreateProcess(NULL, sCommandLine.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
		if (!bRet)
		{
			::CloseHandle(pi.hProcess);
			sCommandLine.ReleaseBuffer();
			throw std::exception("CreateProcess failed to start DeltaView (" + CStdStringA(sCommandLine) + ")");
		}
		// Wait for the file to be created and then perform the test
		DWORD dwExitCode = WaitForSingleObject(pi.hProcess, INFINITE); 
		::CloseHandle(pi.hProcess);
		::CloseHandle(pi.hThread);

		assertFileExistsMessage(sOutfile, _T("Unable to create the Wdf file!"));
		assertMessage(ValidWorkshareDeltaFile(sOutfile), _T("Did not manage to create a valid Workshare DeltaFile"));
	}
Beispiel #7
0
bool RTFobj::CanUseEMF() const	
{ 
	// dataclass is excel.sheet && embedded && result is pict
	if ( (theObjResult == 0) || (m_iObjType != otEmb && m_iObjType != otAutlink))
		return false;

	if (theRTFPCDataClass && theRTFPCDataClass->GetContent().Find(_T("Excel.Sheet")) >= 0)
		return true;

	// sometimes word 2003 puts nothing in ObjClass, so we pixk up the hex version from ObjData
	if (CStdStringA(theObjData.GetData()).Find("457863656c2e5368656574") > 0)	// 01050000010000000e000000457863656c2e53686565742e3800
		return true;

	if (theRTFPCDataClass && theRTFPCDataClass->GetContent().Find(_T("Msxml2.SAXXMLReader")) >= 0)
		return true;

	return false;
}
CIndexedStorage* CompoundFileStore::GetRootStorage()
{
    if( m_pRootStorage == NULL )
    {
        if( m_sFileName.empty() )
            return NULL;

        if( ::_taccess( m_sFileName.c_str(), 00 ) != 0 )
        {
            CreateNewStore();
        }

        CSimpleCompoundFile simpleCompoundFile;
        try
        {
            m_pRootStorage = simpleCompoundFile.Open( m_sFileName.c_str() );
        }
        catch(_com_error& e)
        {
            CStdString sMsg;
            sMsg.Format(_T("Failed to open compound file %s : (0x%x) %s "), m_sFileName.c_str(), e.Error(), e.ErrorMessage());
            LOG_WS_ERROR(sMsg.c_str());
            m_pRootStorage = NULL;
            throw e;
        }
        catch(...)
        {
            CStdString sMsg;
            sMsg.Format(_T("Failed to open compound file %s : Unexpected exception"), m_sFileName.c_str());
            LOG_WS_ERROR(sMsg.c_str());
            m_pRootStorage = NULL;
            throw std::exception(CStdStringA(sMsg.c_str()));
        }
    }

    return m_pRootStorage;
}
Beispiel #9
0
void DMTests_Helper::SaveDocument(const CStdString& sDocumentName, const CStdString& sAppID, CStdString& sTestDocID)
{

	USES_CONVERSION;

	try
	{
		DOCSObjects::IApplicationPtr    pApp( __uuidof( DOCSObjects::Application ));

		pApp->PutDefParentWindow( 0 );

		DOCSObjects::ILibrariesPtr pLibs	= pApp->GetLibraries();
		DOCSObjects::ILibraryPtr pLib		= pApp->GetCurrentLibrary();
		DOCSObjects::IDOCSFormsPtr pForms	= pLib->GetForms();
		DOCSObjects::IProfilePtr pBaseProf	= NULL;
		DOCSObjects::IDOCSFormPtr  pForm	= NULL;

		int	 iCount		= pForms->GetCount();
		bool bFoundProf	= FALSE;
		_variant_t vtIndex;
		vtIndex.vt = VT_I4;

		for (vtIndex.lVal = 1; (vtIndex.lVal <= iCount) && (!bFoundProf); vtIndex.lVal++)
		{
			pForm = pForms->GetItem(vtIndex);

			if (pForm->GetType() & DOCSObjects::FT_DEFAULT_PROFILE)
			{
				pBaseProf       = pLib->CreateProfile(pForm->GetName());
				bFoundProf      = TRUE;
			}
		}

		if (pBaseProf == NULL)
		{
			pBaseProf = pLib->CreateProfile( _bstr_t( _T("LAWPROF") ));
		}

		DOCSObjects::IColumnsPtr pCols = pBaseProf->GetColumns();

		DOCSObjects::IColumnPtr pCol = pCols->GetItem( _variant_t( _T("APP_ID") ));
		pCol->PutValue( _variant_t( T2CW(sAppID.c_str()) ) );

		pCol = pCols->GetItem( _variant_t( _T("DOCNAME") ));
		pCol->PutValue( _variant_t( sDocumentName.c_str() ) );

		pCol = pCols->GetItem( _variant_t( _T("TYPE_ID") ));
		pCol->PutValue( _variant_t( L"MEMO"));

		pCol = pCols->GetItem( L"AUTHOR_ID");
		pCol->PutValue(L"pair");

		pCol = pCols->GetItem(L"TYPIST_ID");
		pCol->PutValue(L"pair");

		pCol = pCols->GetItem(L"CLIENT_ID");
		pCol->PutValue(L"TEST");

		pCol = pCols->GetItem(L"MATTER_ID");
		pCol->PutValue(L"TEST");


		VARIANT_BOOL vb = pBaseProf->Save( DOCSObjects::OF_NORMAL );

		if(vb == VARIANT_FALSE)
		{
			throw std::exception("Profile save document failed");
		}

		DOCSObjects::IVersionPtr pVer = pBaseProf->GetCurrentVersion();

		CStdString sDest = pVer->GetFilePath();
		bool bSuccess = false;
		if (sAppID.CompareNoCase(_T("ACROBAT")) == 0)
		{
			bSuccess = (CopyFile(TEST_PDF_FILE,sDest.c_str(),false)!=0);
		}
		else
		{
			bSuccess = (CopyFile(TEST_DOC_FILE,sDest.c_str(),false)!=0);
		}
		if(!bSuccess)
		{
			throw std::exception("Copy of test file failed");
		}

		m_lDocNum = pBaseProf->GetDocNumber();

		BSTR bsLibName = pLib->GetName();
		CStdString sLibName(bsLibName);
		SysFreeString(bsLibName);

		sTestDocID.Format(_T("PowerDocs://%s/%d/1"),sLibName.c_str(),m_lDocNum);

		pVer->UploadFile( NULL );
		pVer->UnlockVersion( DOCSObjects::OF_NORMAL );

		pBaseProf->ReleaseDoc();

		m_vDocIDs.push_back(sTestDocID);
	}
	catch(_com_error& e)
	{
		CStdString sMsg;
		sMsg.Format(_T("Save document failed : %s"), (const TCHAR*)e.Description());
		throw std::exception(CStdStringA(sMsg));
	}
}
bool GameJoltAPI::SendRequest( CStdString &output, CStdString url )
{

	// The private key must be set to send a request.
	if ( m_GamePrivateKey == _T("") )
	{
		m_ErrorMessage += _T("(You must put in your game's private key before you can use any of the API functions.)");
		return false;
	}

	////////////////////////////////////
	// Let's form the URL first.

	url = GJAPI_ROOT + GJAPI_VERSION + url;
	CStdString signature( md5( CStdStringA( _T("http://") + GJAPI_SERVER + url + m_GamePrivateKey ) ) );
	url += _T("&signature=") + signature;

	// Now let's build the request.
	BOOL ret = FALSE;
	HINTERNET hSession = NULL;
	HINTERNET hConnect = NULL;
	HINTERNET hRequest = NULL;

	hSession = WinHttpOpen
	(
		L"Game Jolt API Construct/1.0", 
		WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
		WINHTTP_NO_PROXY_NAME, 
		WINHTTP_NO_PROXY_BYPASS, 
		0
	);

	if ( hSession )
		hConnect = WinHttpConnect
		( 
			hSession, 
			CStdStringW( GJAPI_SERVER ),
			INTERNET_DEFAULT_PORT, 
			0
		);
	else
		m_ErrorMessage += _T("(Could not open HTTP session.)");

	if ( hConnect )
		hRequest = WinHttpOpenRequest
		( 
			hConnect,
			L"GET",
			CStdStringW( url ),
			NULL,
			WINHTTP_NO_REFERER,
			WINHTTP_DEFAULT_ACCEPT_TYPES,
			WINHTTP_FLAG_REFRESH
		);
	else
		m_ErrorMessage += _T("(Could not connect to the HTTP session.)");

	if ( hRequest ) 
		ret = WinHttpSendRequest
		( 
			hRequest,
			WINHTTP_NO_ADDITIONAL_HEADERS,
			0,
			WINHTTP_NO_REQUEST_DATA,
			0,
			0,
			0
		);
	else
		m_ErrorMessage += _T("(Could not set up the HTTP request.)");

	if ( ret )
		ret = WinHttpReceiveResponse( hRequest, NULL );
	else
		m_ErrorMessage += _T("(Could not send the HTTP request.)");

	DWORD bufferSize = 0;
	DWORD outputDownloaded = 0;
	LPSTR outputBuffer = 0;

	// Keep checking for data until there is nothing left.
	if ( ret )
	{
		do 
		{

			// Check for available data.
			bufferSize = 0;
			WinHttpQueryDataAvailable( hRequest, &bufferSize );

			// Allocate space for the buffer.
			outputBuffer = new char[bufferSize + 1];
			if ( outputBuffer )
			{
				// Read the data.
				ZeroMemory( outputBuffer, bufferSize + 1 );

				if ( WinHttpReadData( hRequest, (LPVOID)outputBuffer, bufferSize, &outputDownloaded ) )
					output += outputBuffer;

				// Free the memory allocated to the buffer.
				delete [] outputBuffer;
			}

		} while( bufferSize > 0 );
	}
	else
		m_ErrorMessage += _T("(Did not get a response from the server.)");

	if ( hRequest ) WinHttpCloseHandle( hRequest );
    if ( hConnect ) WinHttpCloseHandle( hConnect );
    if ( hSession ) WinHttpCloseHandle( hSession );

	return true;

}
bool GameJoltAPI::PopulateTrophyInfo()
{

	CStdString output;
	CStdString gameIDString;
	vector<map<CStdString, CStdString>> parsedOutput;
	vector<map<CStdString, CStdString>>::iterator it;
	map<CStdString, CStdString> trophyInfo;
	bool ret = true;
	int trophyID = 0;

	// Game ID must be set.
	if ( m_GameID <= 0 )
	{
		m_ErrorMessage += _T("(The game ID must be set.)");
		return false;
	}

	// Username must be set.
	if ( m_Username == _T("") )
	{
		m_ErrorMessage += _T("(The username must be set.)");
		return false;
	}

	// User token must be set.
	if ( m_UserToken == _T("") )
	{
		m_ErrorMessage += _T("(The user token must be set.)");
		return false;
	}

	// We must format the Game ID to a string.
	gameIDString.Format( _T("%d"), m_GameID );

	// Send the request.
	ret = SendRequest( output, _T("/trophies/?game_id=") + gameIDString + _T("&username="******"&user_token=") + EncodeURL( m_UserToken ) );

	if ( !ret )
	{
		m_ErrorMessage += _T("(Could not populate the trophy information.)");
		return false;
	}

	// Parse the output.
	ret = ParseOutputString( output, parsedOutput );

	if ( !ret )
	{
		m_ErrorMessage += _T("(Could not populate the trophy information.)");
		return false;
	}

	for ( it = parsedOutput.begin(); it != parsedOutput.end(); it++ )
	{
		trophyInfo = (*it);
		trophyID = atoi( CStdStringA( trophyInfo["id"] ) );
		m_Trophies[trophyID] = Trophy();
		m_Trophies[trophyID].Initialize( this, trophyInfo );
	}

	m_TrophiesPopulated = true;

	return true;

}
Beispiel #12
0
bool PrintManager::ShowPrintRevisionReportDialog(SAFEARRAY** ReportSelection, std::vector<CStdString>& VecElements, LONG_PTR& lPrinterHandle)
{
	lPrinterHandle = 0;
	BOOL bShowDialog = TRUE; 
	_bstr_t bstrOutputFilePathName = _T("");
	LONG lCopies = 1; 
	BOOL bCollate= FALSE;

	StrTerField tFields;
	GetTerFields(this->m_hWnd, &tFields);
	int iTotalPages = tFields.TotalPagesW;

	// show print dialog
	CWSPrintRevisionReportDlg dlgPrint(VecElements, FALSE);

	if(!bShowDialog)
	{
		dlgPrint.GetDefaults();
	}

	dlgPrint.BlackAndWhite(Workshare::OptionApi::GetBool(L"PrintBWOnly"));
	dlgPrint.m_pd.nCopies = (WORD)lCopies;

	if(bCollate)
	{
		dlgPrint.m_pd.Flags |= PD_COLLATE;
	}

	INT_PTR iDlgResponse = IDOK;

	if(bShowDialog)
	{
		iDlgResponse = dlgPrint.DoModal();
	}

	if(iDlgResponse == IDOK)
	{	
		if(CreateSelectedResponsesSafeArray(dlgPrint.GetSelectedElements(), ReportSelection) == false)
		{
			throw std::exception( " CreateSelectedResponsesSafeArray failed");
		}
		m_NoOfCopies = dlgPrint.GetCopies();
		// inform TER of the current printer selection
		PRINTDLG pdlg=dlgPrint.m_pd;
		if(pdlg.hDevNames) 
		{
			InformTerOfCurrentPrinterSelection(dlgPrint);
		}

		Workshare::OptionApi::SetBool(L"PrintBWOnly", (bool)(dlgPrint.BlackAndWhite()));
	
		SetBlackAndWhitePrinting( Workshare::OptionApi::GetBool(L"PrintBWOnly") );

		HDC hdcPrinterHandle = TerStartPrintJob(m_hWnd, _bstr_t(bstrOutputFilePathName), CStdStringA(dlgPrint.GetDocumentNameToPrint()));
		lPrinterHandle = (long)hdcPrinterHandle;

		// Get the current orientation
		m_SaveOrient = GetOrientation();

		if(pdlg.hDevNames && m_SaveOrient!=m_NewOrient && m_iCurSectOrient!=m_NewOrient)
		{
			TerSetSectOrient(this->m_hWnd, m_iCurSectOrient, TRUE);
		}

		//down to here
	}
	else
	{
		return false;
	}

	return true;
}
Beispiel #13
0
DWORD GetLongPathName (CStdStringW strShortPath, CStdStringW &strLongPath)
{
	int iFound = strShortPath.ReverseFind (L'\\');

	if (iFound > 1)
	{
		// recurse to peel off components
		//
		if (GetLongPathName(strShortPath.Left (iFound), strLongPath) > 0)
		{
			strLongPath += L'\\';
				
				if (strShortPath.Right(1) != L"\\")
				{
					HANDLE hFind;

					if (g_bIsNT)
					{
						WIN32_FIND_DATAW findData;
						
						// append the long component name to the path
						//
						if (INVALID_HANDLE_VALUE != (hFind = ::FindFirstFileW (strShortPath, &findData)))
						{
							strLongPath += findData.cFileName;
							::FindClose (hFind);
						}
						else
						{
							// if FindFirstFile fails, return the error code
							//
							strLongPath.Empty();
							return 0;
						}
					}
					else
					{
						WIN32_FIND_DATAA findData;
						
						// append the long component name to the path
						//
						if (INVALID_HANDLE_VALUE != (hFind = ::FindFirstFileA (CStdStringA (strShortPath), &findData)))
						{
							strLongPath += findData.cFileName;
							::FindClose (hFind);
						}
						else
						{
							// if FindFirstFile fails, return the error code
							//
							strLongPath.Empty();
							return 0;
						}
					}
				}
		}
	}
	else
	{
		strLongPath = strShortPath;
	}
	
	return strLongPath.GetLength();
}
Beispiel #14
0
std::tstring Workshare::Mail::Mapi::FormatMessageId(LPSPropValue pEntryId, LPSPropValue pSearchKey, LPSPropValue pInternetId)
{
#define BUFFER_SIZE    (8 * 1024)
    //DS & WVR : no need to do any unicode conversion, hex chars are always ASCII
	char szMessageId[BUFFER_SIZE] = {0};
	char* pszMessageId = szMessageId;
	int iCurrentSize = 0;
	if(pEntryId)
	{
		if ((pEntryId->Value.bin.cb * 2) >= BUFFER_SIZE)
		{
			throw Workshare::Exception(_T("Buffer size for MessageId too small."));
		}
		HexFromBin(pEntryId->Value.bin.lpb, pEntryId->Value.bin.cb, (LPTSTR)pszMessageId);  //Read the documentation, HexFromBin accepts LPTSTRs but is lying.
		pszMessageId += pEntryId->Value.bin.cb * 2;
		iCurrentSize += pEntryId->Value.bin.cb * 2;
	}
	*pszMessageId = ';';
	pszMessageId++;
	if(pSearchKey)
	{
		if (iCurrentSize + (pSearchKey->Value.bin.cb * 2) >= BUFFER_SIZE)
		{
			throw Workshare::Exception(_T("Buffer size for MessageId too small."));
		}
		HexFromBin(pSearchKey->Value.bin.lpb, pSearchKey->Value.bin.cb, (LPTSTR)pszMessageId);
		pszMessageId += pSearchKey->Value.bin.cb * 2;
		iCurrentSize += pSearchKey->Value.bin.cb * 2;
	}
	*pszMessageId = ';';
	pszMessageId++;
#ifdef UNICODE
    if(0 != pInternetId && 0 != pInternetId->Value.lpszW)
    {
        LPTSTR lpStr = pInternetId->Value.lpszW;
#else
    if(0 != pInternetId && 0 != pInternetId->Value.lpszA)
    {
        LPTSTR lpStr = pInternetId->Value.lpszA;
#endif
		if (iCurrentSize + (CStdStringA(lpStr).length()) >= BUFFER_SIZE)
		{
			throw Workshare::Exception(_T("Buffer size for MessageId too small."));
		}
		strcpy(pszMessageId, CStdStringA(lpStr));
   }
	else
		*pszMessageId = 0;

	return CStdString(szMessageId);
}

void Workshare::Mail::Mapi::ParseMessageId(const std::tstring& sMessageId, std::tstring& sEntryId, std::tstring& sSearchKey, std::tstring& sInternetId)
{
   if(sMessageId.empty())
      throw Workshare::ArgumentException(_T("sMessageId"), _T("The email Message ID was not specified."));

   size_t pos = sMessageId.find(_T(';'));
   if(-1 == pos)
      throw Workshare::ArgumentException(_T("sMessageId"), _T("Invalid message ID (should be in format EntryId;SearchKey[;InternetId])"));

   sEntryId = sMessageId.substr(0, pos);
   std::tstring sSearchKeyAndInternetId = sMessageId.substr(pos + 1);
   pos = sSearchKeyAndInternetId.find(_T(';'));
   if(-1 != pos)
   {
      sSearchKey = sSearchKeyAndInternetId.substr(0, pos);
      sInternetId = sSearchKeyAndInternetId.substr(pos + 1);
   }
   else
   {
      sSearchKey = sSearchKeyAndInternetId;
      sInternetId = _T("");
   }
}

std::tstring Workshare::Mail::Mapi::GetSearchKeyFromMessageId(const std::tstring& messageId)
{
   std::tstring entryId;
   std::tstring searchKey;
   std::tstring internetId;
   Workshare::Mail::Mapi::ParseMessageId(messageId, entryId, searchKey, internetId);
   if(searchKey.empty())
      throw Workshare::Exception(_T("The message ID does not include a valid search key."));

   return searchKey;
}