// --iprop.c--------------------------------------------------------------------
//
// Module containing MAPI utility functions for properties.
//
// Copyright (C) Microsoft Corp. 1986-1996. All Rights Reserved.
// -----------------------------------------------------------------------------
#include "edk.h"
#include "iprop.chk"
//$--HrMAPIOpenCachedProp--------------------------------------------------------
//
// DESCRIPTION: Create a new (local) IPropData object in which the original object
// properties are cached. The local cached can be created for
// reading (for use with GetProp calls) for for writing (for use with
// SetProp calls). The purpose of this function and HrMAPICloseCachedProp
// is to reduce the number of remote procedure calls made by code
// which performs many GetProp or SetProp calls on an object.
//
// INPUT: lpObj -- property object to cache
// lpPropList -- list of properties to cache (for reading)
// defaults to all properties if NULL.
// ulFlags -- read OR write access flag (EDK_CACHE_READ
// or EDK_CACHE_WRITE)
//
// OUTPUT: lppCachedObj -- cached property object
//
// RETURNS: HRESULT -- NOERROR if successful,
// E_INVALIDARG if bad input
// E_FAIL otherwise.
//
// NOTE: This function creates a cached object for reading only
// or for writing only. It does not support and object
// for both reading and writing.
//
// -----------------------------------------------------------------------------
HRESULT HrMAPIOpenCachedProp( // RETURNS: return code
IN LPMAPIPROP lpObj, // source object
IN LPSPropTagArray lpPropList, // list of properties to cache
IN ULONG ulFlags, // open for reading only or for writing only
OUT LPPROPDATA FAR * lppCachedObj) // cached version of source object
{
HRESULT hr = NOERROR;
LPSPropProblemArray lpProblems = NULL;
LPSPropValue lpPropVals = NULL;
ULONG ulPropCount= 0; // number of properties
DEBUGPUBLIC("HrMAPIOpenCachedProp()\n");
hr = CHK_HrMAPIOpenCachedProp(
lpObj,
lpPropList,
ulFlags,
lppCachedObj);
if(FAILED(hr))
RETURN(hr);
*lppCachedObj = NULL;
//
// Call CreateIProp() to create a new IPropData object.
// Since IPropData inherits from IMAPIProp, we can use it as our
// IMAPIProp cache pointer.
//
hr = CreateIProp(
&IID_IMAPIPropData, // interface type
MAPIAllocateBuffer,// allocation routine
MAPIAllocateMore, // allocate more routine
MAPIFreeBuffer, // deallocation routine
0, // reserved
lppCachedObj); // address of pointer to new IPropData object
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// If we are creating the cache for reading, then
// we must populate the new object with properties.
// Otherwise, we pass an "empty" object back to the user
// for property writing.
if ( ulFlags == EDK_CACHE_READ )
{
// Get properties from remote object and set these same properties
// on the local object.
hr = MAPICALL(lpObj)->GetProps(
lpObj, // for C to C++ vtbl resolution
lpPropList, // Get all properties
fMapiUnicode, // flags
&ulPropCount, // number of properties retrieved
&lpPropVals); // property values structure pointer
// handle errors
// If there is an error, release the cached object
if ( FAILED(hr) || (hr == MAPI_W_ERRORS_RETURNED) )
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
hr = MAPICALL(*lppCachedObj)->SetProps(*lppCachedObj,
ulPropCount,
lpPropVals,
&lpProblems);
// handle errors
if ( FAILED(hr) )
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Check to see if there were any problems setting the
// properties
if ( lpProblems != NULL )
{
// We have an error
hr = HR_LOG(E_FAIL);
goto cleanup;
}
} // end if creating cache for reading
// We have been successful.
cleanup:
// Handle error case
if ( FAILED(hr) )
{
ULRELEASE(*lppCachedObj);
}
// Free MAPI buffers
MAPIFREEBUFFER(lpProblems);
MAPIFREEBUFFER(lpPropVals);
RETURN(hr);
}
//$--HrMAPICloseCachedProp-------------------------------------------------------
//
// DESCRIPTION: If object was created as a write cache,
// copy properties in local cached object
// back to original remote object.
//
// INPUT: lpCachedObj -- cached property object
// lpOriginalObj -- original property object
// ulFlags -- read cache or write cache flag (EDK_CACHE_READ
// or EDK_CACHE_WRITE)
//
// OUTPUT: lppProblems -- set to the property problem array returned
// by if there were problems setting properties on the original
// object
//
// NOTES: lppProblems: It may be set, even though overall call
// is successful. This is because all of the SetProps have been "deferred" on the
// original object until this call, the user will need to evaluate
// the contents of the lppProblems buffer pointer based on which
// properties he/or she actually tried to set.
//
// RETURNS: HRESULT -- NOERROR if successful,
// E_INVALIDARG if bad input
// E_FAIL otherwise
//
// lppProblems will only be valid if return code
// is NOERROR.
//
// -----------------------------------------------------------------------------
HRESULT HrMAPICloseCachedProp( // RETURNS: return code
IN LPPROPDATA lpCachedObj, // cached property object
IN LPMAPIPROP lpOriginalObj, // original object
IN ULONG ulFlags, // cache type (EDK_CACHE_READ or EDK_CACHE_WRITE)
OUT LPSPropProblemArray FAR * lppProblems) // pointer to property problems array if problems setting properties
{
HRESULT hr = NOERROR;
ULONG ulPropCount = 0; // number of properties
LPSPropValue lpPropVals = NULL; // property values
DEBUGPUBLIC("HrMAPICloseCachedProp()\n");
hr = CHK_HrMAPICloseCachedProp(
lpCachedObj,
lpOriginalObj,
ulFlags,
lppProblems);
if(FAILED(hr))
RETURN(hr);
*lppProblems = NULL; // initialize output
// If the cache was opened for writing, copy all of the
// properties from the cached object back to the original
// object.
if ( ulFlags == EDK_CACHE_WRITE )
{
// Get properties from local object and set these same properties
// on the remote object. CopyTo() is not sufficient, because it
// won't copy read-only properties.
hr = MAPICALL(lpCachedObj)->GetProps(
lpCachedObj, // for C to C++ vtbl resolution
NULL, // get all properties
fMapiUnicode, // flags
&ulPropCount, // number of properties retrieved
&lpPropVals); // property values structure pointer
// handle errors
if ( FAILED(hr) || (hr == MAPI_W_ERRORS_RETURNED) )
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Set all properties retrieved in the remote object
hr = MAPICALL(lpOriginalObj)->SetProps(lpOriginalObj,
ulPropCount,
lpPropVals,
lppProblems);
// handle errors
if ( FAILED(hr) )
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
} // end if cache created for writing
// The user will need to evaluate why the set property
// call has failed (if *lppProblems has been set
// by the SetProps call) based on what properties (if any)
// they have set in the cached object.
// Overall, we have been successful.
cleanup:
// Free MAPI buffers
MAPIFREEBUFFER(lpPropVals);
RETURN(hr);
}
//$--HrMAPIGetPropString---------------------------------------------------------
// Get a string property.
// -----------------------------------------------------------------------------
HRESULT HrMAPIGetPropString( // RETURNS: return code
IN LPMAPIPROP lpObj, // pointer to object
IN ULONG ulPropTag, // property tag
OUT ULONG *lpcbProp, // count of bytes in property
OUT LPVOID *lppvProp) // pointer to property address variable
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
ULONG cValues = 0;
LPSPropValue lpPropValue = NULL;
ULONG cbProp = 0;
SCODE sc = 0;
SizedSPropTagArray(1, rgPropTag) =
{
1,
{
0
}
};
DEBUGPUBLIC("HrMAPIGetPropString()\n");
hr = CHK_HrMAPIGetPropString(
lpObj,
ulPropTag,
lpcbProp,
lppvProp);
if(FAILED(hr))
RETURN(hr);
*lpcbProp = 0;
*lppvProp = NULL;
rgPropTag.cValues = 1;
rgPropTag.aulPropTag[0] = ulPropTag;
hrT = MAPICALL(lpObj)->GetProps(
lpObj,
(LPSPropTagArray)&rgPropTag,
fMapiUnicode,
&cValues,
&lpPropValue);
if(hrT == MAPI_W_ERRORS_RETURNED)
{
if((lpPropValue != NULL) && (lpPropValue->Value.ul == MAPI_E_NOT_FOUND))
{
hr = HR_LOG(MAPI_E_NOT_FOUND);
}
else
{
hr = HR_LOG(E_FAIL);
}
goto cleanup;
}
if(FAILED(hrT))
{
lpPropValue = NULL;
hr = HR_LOG(E_FAIL);
goto cleanup;
}
ASSERTERROR(cValues != 0, "ZERO cValues variable");
ASSERTERROR(lpPropValue != NULL, "NULL lpPropValue variable");
if(PROP_TYPE(ulPropTag) == PT_STRING8)
{
cbProp = ((lpPropValue->Value.lpszA == NULL) ?
sizeof(CHAR) :
cbStrLenA(lpPropValue->Value.lpszA));
}
else
{
cbProp = ((lpPropValue->Value.lpszW == NULL) ?
sizeof(WCHAR) :
cbStrLenW(lpPropValue->Value.lpszW));
}
sc = MAPIAllocateBuffer(cbProp, lppvProp);
if(FAILED(sc))
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
ASSERTERROR(*lppvProp != NULL, "NULL *lppvProp pointer");
if(PROP_TYPE(ulPropTag) == PT_STRING8)
{
memcpy(*lppvProp, lpPropValue->Value.lpszA, cbProp);
}
else
{
memcpy(*lppvProp, lpPropValue->Value.lpszW, cbProp);
}
*lpcbProp = cbProp;
cleanup:
MAPIFREEBUFFER(lpPropValue);
RETURN(hr);
}
//$--HrMAPISetPropString---------------------------------------------------------
// Set a string property.
// -----------------------------------------------------------------------------
HRESULT HrMAPISetPropString( // RETURNS: return code
IN LPMAPIPROP lpObj, // pointer to object
IN ULONG ulPropTag, // property tag
IN LPVOID lpvProp) // pointer to property
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
ULONG cValues = 1;
SPropValue PropValue = {0};
DEBUGPUBLIC("HrMAPISetPropString()\n");
hr = CHK_HrMAPISetPropString(
lpObj,
ulPropTag,
lpvProp);
if(FAILED(hr))
RETURN(hr);
// Initialize SPropValue structure
memset(&PropValue, 0, sizeof(PropValue));
PropValue.ulPropTag = ulPropTag;
if(PROP_TYPE(ulPropTag) == PT_STRING8)
{
PropValue.Value.lpszA = (LPSTR)lpvProp;
}
else
{
PropValue.Value.lpszW = (LPWSTR)lpvProp;
}
hrT = MAPICALL(lpObj)->SetProps(
lpObj,
cValues,
&PropValue,
NULL);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
}
RETURN(hr);
}
//$--HrMAPIGetPropBinary---------------------------------------------------------
// Get a binary property.
// -----------------------------------------------------------------------------
HRESULT HrMAPIGetPropBinary( // RETURNS: return code
IN LPMAPIPROP lpObj, // pointer to object
IN ULONG ulPropTag, // property tag
OUT ULONG *lpcbProp, // count of bytes in property
OUT LPVOID *lppvProp) // pointer to property address variable
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
ULONG cValues = 0;
LPSPropValue lpPropValue = NULL;
ULONG cbProp = 0;
SCODE sc = 0;
SizedSPropTagArray(1, rgPropTag) =
{
1,
{
0
}
};
DEBUGPUBLIC("HrMAPIGetPropBinary()\n");
hr = CHK_HrMAPIGetPropBinary(
lpObj,
ulPropTag,
lpcbProp,
lppvProp);
if(FAILED(hr))
RETURN(hr);
*lpcbProp = 0L;
*lppvProp = NULL;
rgPropTag.cValues = 1;
rgPropTag.aulPropTag[0] = ulPropTag;
hrT = MAPICALL(lpObj)->GetProps(
lpObj,
(LPSPropTagArray)&rgPropTag,
fMapiUnicode,
&cValues,
&lpPropValue);
if(hrT == MAPI_W_ERRORS_RETURNED)
{
if((lpPropValue != NULL) && (lpPropValue->Value.ul == MAPI_E_NOT_FOUND))
{
hr = HR_LOG(MAPI_E_NOT_FOUND);
}
else
{
hr = HR_LOG(E_FAIL);
}
goto cleanup;
}
if(FAILED(hrT))
{
lpPropValue = NULL;
hr = HR_LOG(E_FAIL);
goto cleanup;
}
ASSERTERROR(cValues != 0, "ZERO cValues variable");
ASSERTERROR(lpPropValue != NULL, "NULL lpPropValue variable");
cbProp = lpPropValue->Value.bin.cb;
sc = MAPIAllocateBuffer(cbProp, lppvProp);
if(FAILED(sc))
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
ASSERTERROR(*lppvProp != NULL, "NULL *lppvProp pointer");
// Copy property value
memcpy(*lppvProp, lpPropValue->Value.bin.lpb, cbProp);
*lpcbProp = cbProp;
cleanup:
MAPIFREEBUFFER(lpPropValue);
RETURN(hr);
}
//$--HrMAPISetPropBinary---------------------------------------------------------
// Set a binary property.
// -----------------------------------------------------------------------------
HRESULT HrMAPISetPropBinary( // RETURNS: return code
IN LPMAPIPROP lpObj, // pointer to object
IN ULONG ulPropTag, // property tag
IN ULONG cbProp, // count of bytes in property
IN LPVOID lpvProp) // pointer to property
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
ULONG cValues = 1;
SPropValue PropValue = {0};
DEBUGPUBLIC("HrMAPISetPropBinary()\n");
hr = CHK_HrMAPISetPropBinary(
lpObj,
ulPropTag,
cbProp,
lpvProp);
if(FAILED(hr))
RETURN(hr);
// Initialize SPropValue structure
memset(&PropValue, 0, sizeof(PropValue));
PropValue.ulPropTag = ulPropTag;
PropValue.Value.bin.cb = cbProp;
PropValue.Value.bin.lpb = (LPBYTE)lpvProp;
hrT = MAPICALL(lpObj)->SetProps(
lpObj,
cValues,
&PropValue,
NULL);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
}
RETURN(hr);
}
//$--HrMAPIGetPropBoolean--------------------------------------------------------
// Get a boolean property.
// -----------------------------------------------------------------------------
HRESULT HrMAPIGetPropBoolean( // RETURNS: return code
IN LPMAPIPROP lpObj, // pointer to object
IN ULONG ulPropTag, // property tag
OUT BOOL *lpfProp) // pointer to property variable
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
ULONG cValues = 0;
LPSPropValue lpPropValue = NULL;
SCODE sc = 0;
SizedSPropTagArray(1, rgPropTag) =
{
1,
{
0
}
};
DEBUGPUBLIC("HrMAPIGetPropBoolean()\n");
hr = CHK_HrMAPIGetPropBoolean(
lpObj,
ulPropTag,
lpfProp);
if(FAILED(hr))
RETURN(hr);
*lpfProp = FALSE;
rgPropTag.cValues = 1;
rgPropTag.aulPropTag[0] = ulPropTag;
hrT = MAPICALL(lpObj)->GetProps(
lpObj,
(LPSPropTagArray)&rgPropTag,
fMapiUnicode,
&cValues,
&lpPropValue);
if(hrT == MAPI_W_ERRORS_RETURNED)
{
if((lpPropValue != NULL) && (lpPropValue->Value.ul == MAPI_E_NOT_FOUND))
{
hr = HR_LOG(MAPI_E_NOT_FOUND);
}
else
{
hr = HR_LOG(E_FAIL);
}
goto cleanup;
}
if(FAILED(hrT))
{
lpPropValue = NULL;
hr = HR_LOG(E_FAIL);
goto cleanup;
}
ASSERTERROR(cValues != 0, "ZERO cValues variable");
ASSERTERROR(lpPropValue != NULL, "NULL lpPropValue variable");
*lpfProp = (BOOL)(lpPropValue->Value.b);
cleanup:
MAPIFREEBUFFER(lpPropValue);
RETURN(hr);
}
//$--HrMAPISetPropBoolean--------------------------------------------------------
// Set a boolean property.
// -----------------------------------------------------------------------------
HRESULT HrMAPISetPropBoolean( // RETURNS: return code
IN LPMAPIPROP lpObj, // pointer to object
IN ULONG ulPropTag, // property tag
IN BOOL fProp) // property
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
ULONG cValues = 1;
SPropValue PropValue = {0};
DEBUGPUBLIC("HrMAPISetPropBoolean()\n");
hr = CHK_HrMAPISetPropBoolean(
lpObj,
ulPropTag,
fProp);
if(FAILED(hr))
RETURN(hr);
// Initialize SPropValue structure
ZeroMemory(&PropValue, sizeof(PropValue));
PropValue.ulPropTag = ulPropTag;
PropValue.Value.b = fProp;
hrT = MAPICALL(lpObj)->SetProps(
lpObj,
cValues,
&PropValue,
NULL);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
}
RETURN(hr);
}
//$--HrMAPIGetPropLong-----------------------------------------------------------
// Get a long property.
// -----------------------------------------------------------------------------
HRESULT HrMAPIGetPropLong( // RETURNS: return code
IN LPMAPIPROP lpObj, // pointer to object
IN ULONG ulPropTag, // property tag
OUT ULONG *lpulProp) // pointer to property variable
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
ULONG cValues = 0;
LPSPropValue lpPropValue = NULL;
SCODE sc = 0;
SizedSPropTagArray(1, rgPropTag) =
{
1,
{
0
}
};
DEBUGPUBLIC("HrMAPIGetPropLong()\n");
hr = CHK_HrMAPIGetPropLong(
lpObj,
ulPropTag,
lpulProp);
if(FAILED(hr))
RETURN(hr);
*lpulProp = 0;
rgPropTag.cValues = 1;
rgPropTag.aulPropTag[0] = ulPropTag;
hrT = MAPICALL(lpObj)->GetProps(
lpObj,
(LPSPropTagArray)&rgPropTag,
fMapiUnicode,
&cValues,
&lpPropValue);
if(hrT == MAPI_W_ERRORS_RETURNED)
{
if((lpPropValue != NULL) && (lpPropValue->Value.ul == MAPI_E_NOT_FOUND))
{
hr = HR_LOG(MAPI_E_NOT_FOUND);
}
else
{
hr = HR_LOG(E_FAIL);
}
goto cleanup;
}
if(FAILED(hrT))
{
lpPropValue = NULL;
hr = HR_LOG(E_FAIL);
goto cleanup;
}
ASSERTERROR(cValues != 0, "ZERO cValues variable");
ASSERTERROR(lpPropValue != NULL, "NULL lpPropValue variable");
*lpulProp = lpPropValue->Value.ul;
cleanup:
MAPIFREEBUFFER(lpPropValue);
RETURN(hr);
}
//$--HrMAPISetPropLong-----------------------------------------------------------
// Set a long property.
// -----------------------------------------------------------------------------
HRESULT HrMAPISetPropLong( // RETURNS: return code
IN LPMAPIPROP lpObj, // pointer to object
IN ULONG ulPropTag, // property tag
IN ULONG ulProp) // property
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
ULONG cValues = 1;
SPropValue PropValue = {0};
DEBUGPUBLIC("HrMAPISetPropLong()\n");
hr = CHK_HrMAPISetPropLong(
lpObj,
ulPropTag,
ulProp);
if(FAILED(hr))
RETURN(hr);
// Initialize SPropValue structure
ZeroMemory(&PropValue, sizeof(PropValue));
PropValue.ulPropTag = ulPropTag;
PropValue.Value.ul = ulProp;
hrT = MAPICALL(lpObj)->SetProps(
lpObj,
cValues,
&PropValue,
NULL);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
}
RETURN(hr);
}
//$--HrMAPIGetPropSystime--------------------------------------------------------
// Get a systime property.
// -----------------------------------------------------------------------------
HRESULT HrMAPIGetPropSystime( // RETURNS: return code
IN LPMAPIPROP lpObj, // pointer to object
IN ULONG ulPropTag, // property tag
OUT LPFILETIME lpSystime) // pointer to property variable
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
ULONG cValues = 0;
LPSPropValue lpPropValue = NULL;
SCODE sc = 0;
SizedSPropTagArray(1, rgPropTag) =
{
1,
{
0
}
};
DEBUGPUBLIC("HrMAPIGetPropSystime()\n");
hr = CHK_HrMAPIGetPropSystime(
lpObj,
ulPropTag,
lpSystime);
if(FAILED(hr))
RETURN(hr);
// Initialize FILETIME structure
ZeroMemory(lpSystime, sizeof(FILETIME));
rgPropTag.cValues = 1;
rgPropTag.aulPropTag[0] = ulPropTag;
hrT = MAPICALL(lpObj)->GetProps(
lpObj,
(LPSPropTagArray)&rgPropTag,
fMapiUnicode,
&cValues,
&lpPropValue);
if(hrT == MAPI_W_ERRORS_RETURNED)
{
if((lpPropValue != NULL) && (lpPropValue->Value.ul == MAPI_E_NOT_FOUND))
{
hr = HR_LOG(MAPI_E_NOT_FOUND);
}
else
{
hr = HR_LOG(E_FAIL);
}
goto cleanup;
}
if(FAILED(hrT))
{
lpPropValue = NULL;
hr = HR_LOG(E_FAIL);
goto cleanup;
}
ASSERTERROR(cValues != 0, "ZERO cValues variable");
ASSERTERROR(lpPropValue != NULL, "NULL lpPropValue variable");
lpSystime->dwLowDateTime = lpPropValue->Value.ft.dwLowDateTime;
lpSystime->dwHighDateTime = lpPropValue->Value.ft.dwHighDateTime;
cleanup:
MAPIFREEBUFFER(lpPropValue);
RETURN(hr);
}
//$--HrMAPISetPropSystime--------------------------------------------------------
// Set a systime property.
// -----------------------------------------------------------------------------
HRESULT HrMAPISetPropSystime( // RETURNS: return code
IN LPMAPIPROP lpObj, // pointer to object
IN ULONG ulPropTag, // property tag
IN LPFILETIME lpSystime) // pointer to property
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
ULONG cValues = 1;
SPropValue PropValue = {0};
DEBUGPUBLIC("HrMAPISetPropSystime()\n");
hr = CHK_HrMAPISetPropSystime(
lpObj,
ulPropTag,
lpSystime);
if(FAILED(hr))
RETURN(hr);
// Initialize SPropValue structure
ZeroMemory(&PropValue, sizeof(PropValue));
PropValue.ulPropTag = ulPropTag;
PropValue.Value.ft.dwLowDateTime = lpSystime->dwLowDateTime;
PropValue.Value.ft.dwHighDateTime = lpSystime->dwHighDateTime;
hrT = MAPICALL(lpObj)->SetProps(
lpObj,
cValues,
&PropValue,
NULL);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
}
RETURN(hr);
}
//$--HrMAPIGetPropToFile---------------------------------------------------------
// Get a property and put in a given file.
// -----------------------------------------------------------------------------
HRESULT HrMAPIGetPropToFile( // RETURNS: return code
IN LPMAPIPROP lpObj, // pointer to object
IN ULONG ulPropTag, // property tag
IN LPSTR lpszFilename, // pointer to destination file name
OUT ULONG *lpcbProp) // pointer to count of bytes address
// variable
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
SCODE sc = 0;
LPSTREAM lpStream = NULL;
HANDLE hFile = NULL;
ULONG ulBytesRead = 0;
LPBYTE lpbBlock = NULL;
DWORD dwBytesWritten = 0;
DEBUGPUBLIC("HrMAPIGetPropToFile()\n");
hr = CHK_HrMAPIGetPropToFile(
lpObj,
ulPropTag,
lpszFilename,
lpcbProp);
if(FAILED(hr))
RETURN(hr);
// Open a stream on the property
hrT = MAPICALL(lpObj)->OpenProperty(
lpObj,
ulPropTag,
(LPIID)&IID_IStream,
STGM_READ,
MAPI_DEFERRED_ERRORS,
(LPUNKNOWN *)&lpStream);
if(FAILED(hrT))
{
// Streams are not supported by provider
if((hrT == MAPI_E_NO_SUPPORT) || (hrT == MAPI_E_INTERFACE_NOT_SUPPORTED))
{
ULONG PropType = 0;
lpStream = NULL;
MODULE_WARNING1("Streams are not supported by provider [%08lx]",hrT);
PropType = PROP_TYPE(ulPropTag);
// Read property into memory
switch(PropType)
{
case PT_BINARY:
hr = HrMAPIGetPropBinary(
lpObj,
ulPropTag,
&ulBytesRead,
(void **)&lpbBlock);
break;
default:
hr = HrMAPIGetPropString(
lpObj,
ulPropTag,
&ulBytesRead,
(void **)&lpbBlock);
}
}
else
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
if(FAILED(hr))
{
goto cleanup;
}
}
hFile = CreateFile(
lpszFilename,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Copy propery value to the file
if(lpStream != NULL)
{
sc = MAPIAllocateBuffer(EDK_CBTRANSFER, (void **)&lpbBlock);
// An error occured allocating the block buffer
if(FAILED(sc))
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
for (;;)
{
// Read a block from the stream
hrT = OLECALL(lpStream)->Read(
lpStream,
lpbBlock,
EDK_CBTRANSFER,
&ulBytesRead);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
if(ulBytesRead == 0L)
break;
// Write the block to the file
hr = _HrWriteFile(hFile, ulBytesRead, lpbBlock);
if(FAILED(hr))
{
goto cleanup;
}
}
}
else
{
// Write the block to the file
hr = _HrWriteFile(hFile, ulBytesRead, lpbBlock);
if(FAILED(hr))
{
goto cleanup;
}
}
cleanup:
// Close the file
if(hFile != NULL)
{
if(CloseHandle(hFile) == FALSE)
{
hr = HR_LOG(E_FAIL);
}
}
// Release the stream
ULOLERELEASE(lpStream);
MAPIFREEBUFFER(lpbBlock);
RETURN(hr);
}
//$--HrMAPISetPropFromFile-------------------------------------------------------
// Set a property from a given file.
// -----------------------------------------------------------------------------
HRESULT HrMAPISetPropFromFile( // RETURNS: return code
IN LPMAPIPROP lpObj, // pointer to object
IN ULONG ulPropTag, // property tag
IN LPSTR lpszFilename, // pointer to source file name
OUT ULONG *lpcbProp) // pointer to count of bytes address
// variable
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
SCODE sc = 0;
LPSTREAM lpStream = NULL;
HFILE hFile = HFILE_ERROR;
OFSTRUCT ofStruct = {0};
DWORD dwBytesRead = 0;
LPBYTE lpbBlock = NULL;
ULONG ulBytesWritten = 0;
ULARGE_INTEGER ll = {0,0};
ULONG ulFileSize = 0;
BYTE bLastByte = 0xFF;
ULONG cbProp = 0;
DEBUGPUBLIC("HrMAPISetPropFromFile()\n");
hr = CHK_HrMAPISetPropFromFile(
lpObj,
ulPropTag,
lpszFilename,
lpcbProp);
if(FAILED(hr))
RETURN(hr);
*lpcbProp = 0;
// Open a stream on the property
hrT = MAPICALL(lpObj)->OpenProperty(
lpObj,
ulPropTag,
(LPIID)&IID_IStream,
STGM_DIRECT | STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
MAPI_CREATE | MAPI_MODIFY | MAPI_DEFERRED_ERRORS,
(LPUNKNOWN *)&lpStream);
if(FAILED(hrT))
{
// Streams are not supported by provider
if((hrT == MAPI_E_NO_SUPPORT) || (hrT == MAPI_E_INTERFACE_NOT_SUPPORTED))
{
lpStream = NULL;
}
else
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
}
hFile = OpenFile(
lpszFilename,
&ofStruct,
OF_READ);
if(hFile == HFILE_ERROR)
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Get file size
if((ulFileSize = GetFileSize((HANDLE)hFile, NULL)) == (DWORD)HFILE_ERROR)
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
if(PROP_TYPE(ulPropTag) == PT_UNICODE)
{
if((ulFileSize % sizeof(wchar_t)) != 0)
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
}
cbProp = ulFileSize;
// Copy propery value to the file
if(lpStream != NULL)
{
// Allocate memory for the block buffer
sc = MAPIAllocateBuffer(EDK_CBTRANSFER, (void **)&lpbBlock);
// An error occured allocating the block buffer
if(FAILED(sc))
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
ll.LowPart = ulFileSize;
ll.HighPart = 0L;
hrT = OLECALL(lpStream)->SetSize(lpStream, ll);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
for (;;)
{
BOOL fStatus;
// Read a block from the file
fStatus = ReadFile(
(HANDLE)hFile,
lpbBlock,
EDK_CBTRANSFER,
&dwBytesRead,
NULL);
if(fStatus == FALSE)
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
if(dwBytesRead == 0L)
break;
bLastByte = lpbBlock[dwBytesRead - 1L];
// Write a block to the stream
hrT = OLECALL(lpStream)->Write(
lpStream,
lpbBlock,
dwBytesRead,
&ulBytesWritten);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
if(ulBytesWritten < dwBytesRead)
{
hr = HR_LOG(MAPI_E_NOT_ENOUGH_DISK);
goto cleanup;
}
}
if((PROP_TYPE(ulPropTag) == PT_STRING8) ||
(PROP_TYPE(ulPropTag) == PT_UNICODE))
{
// NULL terminate if not already
if(bLastByte != 0)
{
// Initialize with enough zeroes for a NULL character
ZeroMemory(lpbBlock, sizeof(wchar_t));
if(PROP_TYPE(ulPropTag) == PT_UNICODE)
{
dwBytesRead = sizeof(wchar_t);
}
else
{
dwBytesRead = 1L;
}
ulBytesWritten = 0L;
// Write a block to the stream
hrT = OLECALL(lpStream)->Write(
lpStream,
lpbBlock,
dwBytesRead,
&ulBytesWritten);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
if(ulBytesWritten < dwBytesRead)
{
hr = HR_LOG(MAPI_E_NOT_ENOUGH_DISK);
goto cleanup;
}
cbProp += ulBytesWritten;
}
}
}
else
{
BOOL fStatus = FALSE;
ULONG PropType = 0;
// Allocate the memory for the property value
sc = MAPIAllocateBuffer(
ulFileSize + 2 * sizeof(wchar_t),
(void **)&lpbBlock);
// An error occured allocating the block buffer
if(FAILED(sc))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Read the property value into memory
fStatus = ReadFile(
(HANDLE)hFile,
lpbBlock,
ulFileSize,
&dwBytesRead,
NULL);
if(fStatus == FALSE)
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Check if the entire file was read
if(dwBytesRead != ulFileSize)
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
if((PROP_TYPE(ulPropTag) == PT_STRING8) ||
(PROP_TYPE(ulPropTag) == PT_UNICODE))
{
// NULL terminate if not already
bLastByte = lpbBlock[dwBytesRead - 1L];
if(bLastByte != 0)
{
if(PROP_TYPE(ulPropTag) == PT_UNICODE)
{
((wchar_t *)lpbBlock)[dwBytesRead/sizeof(wchar_t)] = '\0';
ulFileSize += sizeof(wchar_t);
}
else
{
lpbBlock[dwBytesRead] = 0;
ulFileSize++;
}
cbProp = ulFileSize;
}
}
PropType = PROP_TYPE(ulPropTag);
// Set property
switch(PropType)
{
case PT_BINARY:
hr = HrMAPISetPropBinary(
lpObj,
ulPropTag,
ulFileSize,
&lpbBlock);
break;
default:
hr = HrMAPISetPropString(
lpObj,
ulPropTag,
&lpbBlock);
}
}
cleanup:
// Close the file
if(hFile != HFILE_ERROR)
{
if(CloseHandle((HANDLE)hFile) == FALSE)
{
hr = HR_LOG(E_FAIL);
}
}
// Release the stream
ULOLERELEASE(lpStream);
MAPIFREEBUFFER(lpbBlock);
if(SUCCEEDED(hr))
{
*lpcbProp = cbProp;
}
RETURN(hr);
}
//$--HrMAPIOpenStreamOnProperty-------------------------------------------------
// Open a stream on a given property.
// -----------------------------------------------------------------------------
HRESULT HrMAPIOpenStreamOnProperty( // RETURNS: return code
IN LPMAPIPROP lpObj, // pointer to object
IN ULONG ulPropTag, // property tag
IN ULONG ulFlags, // flags (MAPI_CREATE and/or MAPI_MODIFY)
OUT LPSTREAM *lppStream) // pointer to stream address variable
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
LPSTREAM lpStream = NULL;
ULONG ulStgmFlags = STGM_READ;
DEBUGPUBLIC("HrMAPIOpenStreamOnProperty()\n");
hr = CHK_HrMAPIOpenStreamOnProperty(
lpObj,
ulPropTag,
ulFlags,
lppStream);
if(FAILED(hr))
RETURN(hr);
*lppStream = NULL;
if(ulFlags & MAPI_CREATE)
{
ulStgmFlags |= STGM_CREATE;
}
if(ulFlags & MAPI_MODIFY)
{
ulStgmFlags |= STGM_WRITE;
}
hrT = MAPICALL(lpObj)->OpenProperty(
lpObj,
ulPropTag,
(LPIID)&IID_IStream,
STGM_DIRECT | STGM_SHARE_EXCLUSIVE | ulStgmFlags,
MAPI_DEFERRED_ERRORS | ulFlags,
(LPUNKNOWN *)&lpStream);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
*lppStream = lpStream;
cleanup:
RETURN(hr);
}
//$--HrMAPIAppendSPropValues-----------------------------------------------------
// Append one set of SPropValue's to another.
// -----------------------------------------------------------------------------
HRESULT HrMAPIAppendSPropValues( // RETURNS: return code
IN ULONG cHeadProps, // count of property values in head
IN LPSPropValue lpHeadProps, // pointer to property values in
// head
IN ULONG cTailProps, // count of property values in tail
IN LPSPropValue lpTailProps, // pointer to property values in
// tail
OUT ULONG *lpcNewProps, // pointer to count of property
// values
OUT LPSPropValue *lppNewProps) // pointer to property values
{
HRESULT hr = NOERROR;
SCODE sc = 0;
ULONG cNewProps = 0;
LPSPropValue lpTmpProps = NULL;
LPSPropValue lpNewProps = NULL;
ULONG cBytes = 0;
ULONG i = 0;
ULONG j = 0;
DEBUGPUBLIC("HrMAPIAppendSPropValues()\n");
hr = CHK_HrMAPIAppendSPropValues(
cHeadProps,
lpHeadProps,
cTailProps,
lpTailProps,
lpcNewProps,
lppNewProps);
if(FAILED(hr))
RETURN(hr);
*lpcNewProps = 0;
*lppNewProps = NULL;
cNewProps = cHeadProps + cTailProps;
cBytes = CbSPropValue(cNewProps);
sc = MAPIAllocateBuffer(cBytes, (void **)&lpTmpProps);
if(FAILED(sc))
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
// Copy existing property values
for(i = 0; i < cHeadProps; i++)
{
lpTmpProps[i] = lpHeadProps[i];
}
for(i = cHeadProps, j = 0; i < cNewProps; i++, j++)
{
lpTmpProps[i] = lpTailProps[j];
}
sc = ScDupPropset(
cNewProps,
lpTmpProps,
MAPIAllocateBuffer,
&lpNewProps);
if(FAILED(sc))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
*lpcNewProps = cNewProps;
*lppNewProps = lpNewProps;
cleanup:
MAPIFREEBUFFER(lpTmpProps);
RETURN(hr);
}
//$--HrMAPIMoveOneProp-----------------------------------------------------------
// Move one property from a source object to a destination object.
// -----------------------------------------------------------------------------
HRESULT HrMAPIMoveOneProp( // RETURNS: return code
IN LPMAPIPROP lpSrcObj, // pointer to source object
IN ULONG ulSrcPropTag, // source property tag
IN ULONG ulDstPropTag, // destination property tag
IN BOOL IsMust, // TRUE if a required property
IN BOOL IsReplace, // TRUE if existing destination
// property can be replaced
IN OUT LPMAPIPROP lpDstObj) // pointer to destination object
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
SCODE sc = 0;
ULONG cProps = 0;
LPSPropValue lpProps = NULL;
SizedSPropTagArray(1, rgPropTag) = { 1, 0 };
DEBUGPUBLIC("HrMAPIMoveOneProp()\n");
hr = CHK_HrMAPIMoveOneProp(
lpSrcObj,
ulSrcPropTag,
ulDstPropTag,
IsMust,
IsReplace,
lpDstObj);
if(FAILED(hr))
RETURN(hr);
if(PROP_TYPE(ulSrcPropTag) != PROP_TYPE(ulDstPropTag))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
if((IsReplace == FALSE) && FPropExists(lpDstObj, ulDstPropTag))
{
MODULE_WARNING("Destination property exists and not overwritten.");
goto cleanup;
}
rgPropTag.cValues = 1;
rgPropTag.aulPropTag[0] = ulSrcPropTag;
hrT = MAPICALL(lpSrcObj)->GetProps(
lpSrcObj,
(LPSPropTagArray)&rgPropTag,
fMapiUnicode,
&cProps,
&lpProps);
if(hrT == MAPI_W_ERRORS_RETURNED)
{
hrT = lpProps->Value.ul;
if(hrT != MAPI_E_NOT_FOUND)
{
hr = HR_LOG(E_FAIL);
}
else if(IsMust == TRUE)
{
hr = HR_LOG(MAPI_E_NOT_FOUND);
}
goto cleanup;
}
if(FAILED(hrT))
{
lpProps = NULL;
hr = HR_LOG(E_FAIL);
goto cleanup;
}
ASSERTERROR(cProps != 0, "ZERO cProps variable");
ASSERTERROR(lpProps != NULL, "NULL lpProps variable");
lpProps->ulPropTag = ulDstPropTag;
hrT = MAPICALL(lpDstObj)->SetProps(
lpDstObj,
cProps,
lpProps,
NULL);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
cleanup:
MAPIFREEBUFFER(lpProps);
RETURN(hr);
}