// --edkmapi.c------------------------------------------------------------------
//
// Module containing MAPI utility functions.
//
// Copyright (C) Microsoft Corp. 1986-1996. All Rights Reserved.
// -----------------------------------------------------------------------------
#include "edk.h"
#include "edkmapi.chk"
//$--HrMAPIGetFirstSRowSet-------------------------------------------------------
// Gets the first SRowSet from a table
// -----------------------------------------------------------------------------
HRESULT HrMAPIGetFirstSRowSet( // RETURNS: return code
IN LPMAPITABLE lpTable, // pointer to table address variable
IN ULONG cRows, // count of number of rows in SRowSet
IN LPSPropTagArray rgPropTags, // array of property tags
OUT LPSRowSet FAR *lppRows) // pointer to address variable for
// SRowSet
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
DEBUGPUBLIC("HrMAPIGetFirstSRowSet()\n");
hr = CHK_HrMAPIGetFirstSRowSet(
lpTable,
cRows,
rgPropTags,
lppRows);
if(FAILED(hr))
RETURN(hr);
*lppRows = NULL;
// Set the columns to return
hrT = MAPICALL(lpTable)->SetColumns(lpTable, rgPropTags, (ULONG)0);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Go to the beginning of the table
hrT = MAPICALL(lpTable)->SeekRow(lpTable, BOOKMARK_BEGINNING, 0, NULL);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Get the next SRowSet
hrT = MAPICALL(lpTable)->QueryRows(
lpTable,
cRows,
(ULONG)0,
lppRows);
if(SUCCEEDED(hrT) && ((*lppRows) != NULL) && ((*lppRows)->cRows == 0))
{
FREEPROWS(*lppRows);
hrT = EDK_E_NOT_FOUND;
}
if(FAILED(hrT) || ((*lppRows) == NULL))
{
if (hrT != EDK_E_NOT_FOUND)
{
hr = HR_LOG(E_FAIL);
}
else
{
hr = HR_LOG(EDK_E_END_OF_FILE);
}
}
cleanup:
RETURN(hr);
}
//$--HrMAPIGetNextSRowSet--------------------------------------------------------
// Gets the next SRowSet from a table
// -----------------------------------------------------------------------------
HRESULT HrMAPIGetNextSRowSet( // RETURNS: return code
IN LPMAPITABLE lpTable, // pointer to table
IN ULONG cRows, // count of number of rows in SRowSet
IN LPSPropTagArray rgPropTags, // array of property tags
OUT LPSRowSet FAR *lppRows) // pointer to address variable for
// SRowSet
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
DEBUGPUBLIC("HrMAPIGetNextSRowSet()\n");
hr = CHK_HrMAPIGetNextSRowSet(
lpTable,
cRows,
rgPropTags,
lppRows);
if(FAILED(hr))
RETURN(hr);
*lppRows = NULL;
// Set the columns to return
hrT = MAPICALL(lpTable)->SetColumns(lpTable, rgPropTags, (ULONG)0);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Get the next SRowSet
hrT = MAPICALL(lpTable)->QueryRows(
lpTable,
cRows,
(ULONG)0,
lppRows);
if(SUCCEEDED(hrT) && ((*lppRows) != NULL) && ((*lppRows)->cRows == 0))
{
FREEPROWS(*lppRows);
hrT = EDK_E_NOT_FOUND;
}
if(FAILED(hrT) || ((*lppRows) == NULL))
{
if (hrT != EDK_E_NOT_FOUND)
{
hr = HR_LOG(E_FAIL);
}
else
{
hr = HR_LOG(EDK_E_END_OF_FILE);
}
}
cleanup:
RETURN(hr);
}
//$--HrMAPICreateEntryList-------------------------------------------------------
// Creates an ENTRYLIST.
// -----------------------------------------------------------------------------
HRESULT HrMAPICreateEntryList( // RETURNS: return code
IN ULONG cbeid, // count of bytes in Entry ID
IN LPENTRYID lpeid, // pointer to Entry ID
OUT LPENTRYLIST FAR *lppEntryList) // pointer to address variable of Entry
// list
{
HRESULT hr = NOERROR;
SCODE sc = 0;
LPVOID lpvSBinaryArray = NULL;
LPVOID lpvSBinary = NULL;
LPVOID lpv = NULL;
DEBUGPUBLIC("HrMAPICreateEntryList()\n");
hr = CHK_HrMAPICreateEntryList(
cbeid,
lpeid,
lppEntryList);
if(FAILED(hr))
RETURN(hr);
*lppEntryList = NULL;
sc = MAPIAllocateBuffer(cbeid, &lpv);
if(FAILED(sc))
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
// Copy entry ID
CopyMemory(lpv, lpeid, cbeid);
sc = MAPIAllocateBuffer(sizeof(SBinary), &lpvSBinary);
if(FAILED(sc))
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
// Initialize SBinary structure
ZeroMemory(lpvSBinary, sizeof(SBinary));
((LPSBinary)lpvSBinary)->cb = cbeid;
((LPSBinary)lpvSBinary)->lpb = (LPBYTE)lpv;
sc = MAPIAllocateBuffer(sizeof(SBinaryArray), &lpvSBinaryArray);
if(FAILED(sc))
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
// Initialize SBinaryArray structure
ZeroMemory(lpvSBinaryArray, sizeof(SBinaryArray));
((SBinaryArray *)lpvSBinaryArray)->cValues = 1;
((SBinaryArray *)lpvSBinaryArray)->lpbin = (LPSBinary)lpvSBinary;
*lppEntryList = (LPENTRYLIST)lpvSBinaryArray;
cleanup:
if(FAILED(hr))
{
MAPIFREEBUFFER(lpv);
MAPIFREEBUFFER(lpvSBinary);
MAPIFREEBUFFER(lpvSBinaryArray);
}
RETURN(hr);
}
//$--HrMAPIAppendEntryList-------------------------------------------------------
// Appends to an ENTRYLIST.
// -----------------------------------------------------------------------------
HRESULT HrMAPIAppendEntryList( // RETURNS: return code
IN ULONG cbeid, // count of bytes in Entry ID
IN LPENTRYID lpeid, // pointer to Entry ID
OUT LPENTRYLIST FAR lpEntryList) // pointer to address variable of Entry
// list
{
HRESULT hr = NOERROR;
SCODE sc = 0;
LPVOID lpvSBinary = NULL;
LPVOID lpv = NULL;
ULONG cValues = 0;
ULONG cSBinary = 0;
ULONG i = 0;
DEBUGPUBLIC("HrMAPIAppendEntryList()\n");
hr = CHK_HrMAPIAppendEntryList(
cbeid,
lpeid,
lpEntryList);
if(FAILED(hr))
RETURN(hr);
sc = MAPIAllocateBuffer(cbeid, &lpv);
if(FAILED(sc))
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
// Copy Entry ID
CopyMemory(lpv, lpeid, cbeid);
cValues = lpEntryList->cValues;
cSBinary = sizeof(SBinary) * (cValues + 1);
sc = MAPIAllocateBuffer(cSBinary, &lpvSBinary);
if(FAILED(sc))
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
// Initialize SBinary structure
ZeroMemory(lpvSBinary, cSBinary);
#define BINLIST ((LPSBinary)lpvSBinary)
// Copy values from old SBinary list to new SBinary list
for(i = 0; i < cValues; i++)
{
BINLIST[i].cb = lpEntryList->lpbin[i].cb;
BINLIST[i].lpb = lpEntryList->lpbin[i].lpb;
}
// Add new entry to the end of the list
BINLIST[cValues].cb = cbeid;
BINLIST[cValues].lpb = (LPBYTE)lpv;
// Free old SBinary list
MAPIFREEBUFFER(lpEntryList->lpbin);
// Increment number of cValues
cValues++;
// Update Entry list
lpEntryList->cValues = cValues;
lpEntryList->lpbin = BINLIST;
#undef BINLIST
cleanup:
if(FAILED(hr))
{
MAPIFREEBUFFER(lpv);
MAPIFREEBUFFER(lpvSBinary);
}
RETURN(hr);
}
//$--HrMAPIDestroyEntryList---------------------------------------------------------
// Frees an ENTRYLIST.
// -----------------------------------------------------------------------------
HRESULT HrMAPIDestroyEntryList( // RETURNS: return code
IN OUT LPENTRYLIST FAR *lppEntryList)// pointer to address variable of Entry
// list
{
HRESULT hr = NOERROR;
ULONG i = 0;
LPENTRYLIST lpEntryList = NULL;
DEBUGPUBLIC("HrMAPIDestroyEntryList()\n");
hr = CHK_HrMAPIDestroyEntryList(
lppEntryList);
if(FAILED(hr))
RETURN(hr);
if(lppEntryList != NULL)
{
lpEntryList = *lppEntryList;
if(lpEntryList != NULL)
{
if(lpEntryList->lpbin != NULL)
{
// Free values in SBinary list
for(i = 0; i < lpEntryList->cValues; i++)
{
MAPIFREEBUFFER(lpEntryList->lpbin[i].lpb);
}
// Free SBinary list
MAPIFREEBUFFER(lpEntryList->lpbin);
}
lpEntryList->cValues = 0;
// Free SBinary array
MAPIFREEBUFFER(lpEntryList);
*lppEntryList = NULL;
}
}
RETURN(hr);
}
//$--HrMAPIWriteStreamToFile----------------------------------------------------
// Write stream to a file given a file handle.
// -----------------------------------------------------------------------------
HRESULT HrMAPIWriteStreamToFile( // RETURNS: return code
IN LPSTREAM lpStream, // Pointer to stream
OUT HANDLE hFile) // Handle to file
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
ULONG cBytesRead = 0;
DWORD cBytesWritten = 0;
BYTE byteBuffer[128] = {0};
BOOL fWriteOk = FALSE;
DEBUGPUBLIC("HrMAPIWriteStreamToFile()\n");
hr = CHK_HrMAPIWriteStreamToFile(
lpStream,
hFile);
if(FAILED(hr))
RETURN(hr);
for(;;)
{
hrT = OLECALL(lpStream)->Read(
lpStream,
byteBuffer,
sizeof(byteBuffer),
&cBytesRead);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
break;
}
if (cBytesRead == 0)
{
hr = NOERROR;
break ;
}
fWriteOk = WriteFile(
hFile,
byteBuffer,
cBytesRead,
&cBytesWritten,
NULL);
if(fWriteOk == FALSE)
{
hr = HR_LOG(E_FAIL);
break;
}
if(cBytesWritten != cBytesRead)
{
hr = HR_LOG(MAPI_E_NOT_ENOUGH_DISK);
break;
}
}
RETURN(hr);
}
//$--HrMAPIWriteFileToStream----------------------------------------------------
// Write file to a stream given a stream pointer.
// -----------------------------------------------------------------------------
HRESULT HrMAPIWriteFileToStream( // RETURNS: return code
IN HANDLE hFile, // Handle to file
OUT LPSTREAM lpStream) // Pointer to stream
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
DWORD cBytesRead = 0;
ULONG cBytesWritten = 0;
BYTE byteBuffer[128] = {0};
BOOL fReadOk = FALSE;
DEBUGPUBLIC("HrMAPIWriteFileToStream()\n");
hr = CHK_HrMAPIWriteFileToStream(
hFile,
lpStream);
if(FAILED(hr))
RETURN(hr);
for(;;)
{
fReadOk = ReadFile(
hFile,
byteBuffer,
sizeof(byteBuffer),
&cBytesRead,
NULL);
if(fReadOk == FALSE)
{
hr = HR_LOG(E_FAIL);
break;
}
if(cBytesRead == 0)
{
hr = NOERROR;
break;
}
hrT = OLECALL(lpStream)->Write(
lpStream,
byteBuffer,
cBytesRead,
&cBytesWritten);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
break;
}
if(cBytesWritten != cBytesRead)
{
hr = HR_LOG(MAPI_E_NOT_ENOUGH_DISK);
break;
}
}
RETURN(hr);
}
//$--HrMAPIWriteAttachmentToFile-----------------------------------------------
// Write the identified message attachment to a file.
// -----------------------------------------------------------------------------
HRESULT HrMAPIWriteAttachmentToFile( // RETURNS: return code
IN LPMESSAGE lpMessage, // message containing the attachments
IN ULONG iAttach, // attachment identifier
OUT HANDLE hFile) // handle to file
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
LPATTACH lpAttach = NULL;
LPSTREAM lpAttStream = NULL;
DEBUGPUBLIC("HrMAPIWriteAttachmentToFile()\n");
hr = CHK_HrMAPIWriteAttachmentToFile(
lpMessage,
iAttach,
hFile);
if(FAILED(hr))
RETURN(hr);
//
// Open the attachment.
//
hrT = MAPICALL(lpMessage)->OpenAttach(
lpMessage,
iAttach,
NULL,
MAPI_DEFERRED_ERRORS,
&lpAttach);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
ASSERTERROR(lpAttach != NULL, "NULL lpAttach variable");
//
// Get a stream interface on the attachment
//
hrT = MAPICALL(lpAttach)->OpenProperty(
lpAttach,
PR_ATTACH_DATA_BIN,
(LPIID)&IID_IStream,
STGM_READ | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
MAPI_DEFERRED_ERRORS,
(LPUNKNOWN *)&lpAttStream);
if(FAILED(hrT))
{
if(hrT == MAPI_E_NOT_FOUND)
{
hr = HR_LOG(MAPI_E_NOT_FOUND);
}
else
{
hr = HR_LOG(E_FAIL);
}
goto cleanup;
}
//
// Copy the attachment into a file.
//
hrT = HrMAPIWriteStreamToFile(lpAttStream, hFile);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
cleanup:
if(lpAttStream != NULL)
OLECALL(lpAttStream)->Release(lpAttStream);
if(lpAttach != NULL)
MAPICALL(lpAttach)->Release(lpAttach);
RETURN(hr);
}
//$--HrMAPIGotoSRow--------------------------------------------------------------
// Goto the specified SRow in an SRowSet.
//------------------------------------------------------------------------------
HRESULT HrMAPIGotoSRow( // RETURNS: return code
IN LPSRowSet FAR lpRows, // pointer to SRowSet
IN ULONG ulRow, // index of SRow in SRowSet
OUT LPSRow *lppRow) // pointer to SRow
{
HRESULT hr = NOERROR;
DEBUGPUBLIC("HrMAPIGotoSRow()\n");
hr = CHK_HrMAPIGotoSRow(
lpRows,
ulRow,
lppRow);
if(FAILED(hr))
RETURN(hr);
*lppRow = NULL;
if(ulRow < lpRows->cRows)
{
*lppRow = &(lpRows->aRow[ulRow]);
}
else
{
hr = HR_LOG(EDK_E_NOT_FOUND);
}
RETURN(hr);
}
//$--HrMAPIGotoFirstSRow---------------------------------------------------------
// Goto the first SRow in an SRowSet.
//------------------------------------------------------------------------------
HRESULT HrMAPIGotoFirstSRow( // RETURNS: return code
IN LPSRowSet FAR lpRows, // pointer to SRowSet
OUT ULONG *lpulRow, // index of SRow in SRowSet
OUT LPSRow *lppRow) // pointer to SRow
{
HRESULT hr = NOERROR;
DEBUGPUBLIC("HrMAPIGotoFirstSRow()\n");
hr = CHK_HrMAPIGotoFirstSRow(
lpRows,
lpulRow,
lppRow);
if(FAILED(hr))
RETURN(hr);
*lpulRow = 0;
hr = HrMAPIGotoSRow(
lpRows,
0,
lppRow);
RETURN(hr);
}
//$--HrMAPIGotoNextSRow----------------------------------------------------------
// Goto the next SRow in an SRowSet.
//------------------------------------------------------------------------------
HRESULT HrMAPIGotoNextSRow( // RETURNS: return code
IN LPSRowSet FAR lpRows, // pointer to SRowSet
IN OUT ULONG *lpulRow, // index of SRow in SRowSet
OUT LPSRow *lppRow) // pointer to SRow
{
HRESULT hr = NOERROR;
ULONG ulRow = 0;
DEBUGPUBLIC("HrMAPIGotoNextSRow()\n");
hr = CHK_HrMAPIGotoNextSRow(
lpRows,
lpulRow,
lppRow);
if(FAILED(hr))
RETURN(hr);
ulRow = *lpulRow;
ulRow++;
*lpulRow = ulRow;
hr = HrMAPIGotoSRow(
lpRows,
ulRow,
lppRow);
RETURN(hr);
}
//$--HrMAPIWriteStreamToMemory----------------------------------------------------
// Reads a given number of bytes from a stream to a block of memory.
// -----------------------------------------------------------------------------
HRESULT HrMAPIWriteStreamToMemory( // RETURNS: return code
IN LPSTREAM lpStream, // pointer to stream
IN ULONG cBytes, // count of bytes in memory
IN LPBYTE lpbBytes, // pointer to memory
OUT ULONG *lpcBytesRead) // count of bytes read from stream
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
DEBUGPUBLIC("HrMAPIWriteStreamToMemory()\n");
hr = CHK_HrMAPIWriteStreamToMemory(
lpStream,
cBytes,
lpbBytes,
lpcBytesRead);
if(FAILED(hr))
RETURN(hr);
*lpcBytesRead = 0;
// Read from the stream
hrT = OLECALL(lpStream)->Read(
lpStream,
lpbBytes,
cBytes,
lpcBytesRead);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
cleanup:
RETURN(hr);
}
//$--HrMAPIWriteMemoryToStream---------------------------------------------------
// Writes a given number of bytes from a block of memory to a stream
// -----------------------------------------------------------------------------
HRESULT HrMAPIWriteMemoryToStream( // RETURNS: return code
IN LPSTREAM lpStream, // pointer to stream
IN ULONG cBytes, // count of bytes in memory
IN LPBYTE lpbBytes, // pointer to memory
OUT ULONG *lpcBytesWritten) // count of bytes written from stream
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
DEBUGPUBLIC("HrMAPIWriteMemoryToStream()\n");
hr = CHK_HrMAPIWriteMemoryToStream(
lpStream,
cBytes,
lpbBytes,
lpcBytesWritten);
if(FAILED(hr))
RETURN(hr);
*lpcBytesWritten = 0;
// Write a block to the stream
hrT = OLECALL(lpStream)->Write(
lpStream,
lpbBytes,
cBytes,
lpcBytesWritten);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
if((*lpcBytesWritten) < cBytes)
{
hr = HR_LOG(MAPI_E_NOT_ENOUGH_DISK);
goto cleanup;
}
cleanup:
RETURN(hr);
}
//$--HrMAPISetStreamSize---------------------------------------------------------
// Sets the size of the given stream.
// -----------------------------------------------------------------------------
HRESULT HrMAPISetStreamSize( // RETURNS: return code
IN LPSTREAM lpStream, // pointer to stream
IN ULONG cBytes) // count of bytes in stream
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
ULARGE_INTEGER ll = {0};
DEBUGPUBLIC("HrMAPISetStreamSize()\n");
hr = CHK_HrMAPISetStreamSize(
lpStream,
cBytes);
if(FAILED(hr))
RETURN(hr);
ll.LowPart = cBytes;
ll.HighPart = 0;
hrT = OLECALL(lpStream)->SetSize(lpStream, ll);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
cleanup:
RETURN(hr);
}