EDKMAPI.C
// --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); 
}