IFOLDER.C
// --ifolder.c------------------------------------------------------------------ 
//  
//  Module containing MAPI utility functions for folders. 
//  
// Copyright (C) Microsoft Corp. 1986-1996.  All Rights Reserved. 
// ----------------------------------------------------------------------------- 
 
#include "edk.h" 
 
#include "ifolder.chk" 
 
typedef struct { 
    ULONG   cbRootFolderA; 
    LPSTR   lpszRootFolderA; 
    ULONG   cbRootFolderW; 
    LPWSTR  lpszRootFolderW; 
    ULONG   ulPropTag; 
} ROOT_LOOKUP; 
 
#define RLENTRY(str,ul) {sizeof(str), str, sizeof(L##str), L##str, ul} 
 
static const ROOT_LOOKUP rgRootLookup[] = { 
    RLENTRY( "@PR_IPM_SUBTREE_ENTRYID",              PR_IPM_SUBTREE_ENTRYID), 
    RLENTRY( "@PR_IPM_OUTBOX_ENTRYID",               PR_IPM_OUTBOX_ENTRYID), 
    RLENTRY( "@PR_IPM_WASTEBASKET_ENTRYID",          PR_IPM_WASTEBASKET_ENTRYID), 
    RLENTRY( "@PR_IPM_SENTMAIL_ENTRYID",             PR_IPM_SENTMAIL_ENTRYID), 
    RLENTRY( "@PR_IPM_PUBLIC_FOLDERS_ENTRYID",       PR_IPM_PUBLIC_FOLDERS_ENTRYID), 
    RLENTRY( "@PR_IPM_FAVORITES_ENTRYID",            PR_IPM_FAVORITES_ENTRYID), 
    RLENTRY( "@PR_NON_IPM_SUBTREE_ENTRYID",          PR_NON_IPM_SUBTREE_ENTRYID), 
    RLENTRY( "@PR_GW_MTSIN_ENTRYID",                 PR_GW_MTSIN_ENTRYID), 
    RLENTRY( "@PR_GW_MTSOUT_ENTRYID",                PR_GW_MTSOUT_ENTRYID), 
    RLENTRY( "@PR_VIEWS_ENTRYID",                    PR_VIEWS_ENTRYID), 
    RLENTRY( "@PR_DEFAULT_VIEW_ENTRYID",             PR_DEFAULT_VIEW_ENTRYID), 
    RLENTRY( "@PR_COMMON_VIEWS_ENTRYID",             PR_COMMON_VIEWS_ENTRYID), 
    RLENTRY( "@PR_FINDER_ENTRYID",                   PR_FINDER_ENTRYID), 
    RLENTRY( "@PR_HEADER_FOLDER_ENTRYID",            PR_HEADER_FOLDER_ENTRYID), 
    RLENTRY( "@PR_SCHEDULE_FOLDER_ENTRYID",          PR_SCHEDULE_FOLDER_ENTRYID), 
    RLENTRY( "@PR_IPM_DAF_ENTRYID",                  PR_IPM_DAF_ENTRYID), 
    RLENTRY( "@PR_EFORMS_REGISTRY_ENTRYID",          PR_EFORMS_REGISTRY_ENTRYID), 
    RLENTRY( "@PR_SPLUS_FREE_BUSY_ENTRYID",          PR_SPLUS_FREE_BUSY_ENTRYID), 
    RLENTRY( "@PR_OFFLINE_ADDRBOOK_ENTRYID",         PR_OFFLINE_ADDRBOOK_ENTRYID), 
    RLENTRY( "@PR_EFORMS_FOR_LOCALE_ENTRYID",        PR_EFORMS_FOR_LOCALE_ENTRYID), 
    RLENTRY( "@PR_FREE_BUSY_FOR_LOCAL_SITE_ENTRYID", PR_FREE_BUSY_FOR_LOCAL_SITE_ENTRYID), 
    RLENTRY( "@PR_ADDRBOOK_FOR_LOCAL_SITE_ENTRYID",  PR_ADDRBOOK_FOR_LOCAL_SITE_ENTRYID), 
}; 
 
static const ULONG ulRootLookupCount = ARRAY_CNT(rgRootLookup); 
 
//$--_HrLookupRootFolder@------------------------------------------------------ 
//  Compare folder name to known root folder ENTRYID strings.  Return ENTRYID, 
//  if matched. 
// ----------------------------------------------------------------------------- 
static HRESULT _HrLookupRootFolderW( 
    IN  LPMDB lpMdb,                // pointer to open message store 
    IN  LPCWSTR lpszRootFolder,     // root folder name only (no separators) 
    OUT ULONG *lpcbeid,             // size of entryid 
    OUT LPENTRYID *lppeid)          // pointer to entryid 
{ 
    HRESULT      hr           = NOERROR; 
 
    DEBUGPRIVATE( "HrMAPIFindRootFolderW()"); 
 
    hr = CHK_HrMAPIFindRootFolderW( lpMdb, lpszRootFolder, lpcbeid, lppeid); 
    if( FAILED( hr)) 
        RETURN( hr); 
 
    *lpcbeid = 0L; 
    *lppeid  = NULL; 
 
    // Since there are no ENTRYID properties for "Inbox"... 
    if( _wcsicmp( lpszRootFolder, L"@PR_IPM_INBOX_ENTRYID") == 0) 
    { 
        hr = MAPICALL( lpMdb)->GetReceiveFolder( lpMdb, 
            NULL,       // default message class ("IPM") 
            MAPI_UNICODE, 
            lpcbeid, 
            lppeid, 
            NULL); 
        if( FAILED( hr)) 
        { 
            if( hr == MAPI_E_NOT_FOUND) 
                hr = HR_LOG( EDK_E_NOT_FOUND); 
            else 
                hr = HR_LOG( E_FAIL); 
 
            goto cleanup; 
        } 
    } 
    else 
    { 
        ULONG cbRootFolder = 0L; 
        ULONG i            = 0L; 
 
        // Calculate length of folder name to speed up search somewhat 
        cbRootFolder = cbStrLenW( lpszRootFolder); 
 
        for( i = 0L; i < ulRootLookupCount; i++) 
        { 
            if( cbRootFolder == rgRootLookup[i].cbRootFolderW && 
                _wcsicmp( rgRootLookup[i].lpszRootFolderW, lpszRootFolder) == 0 ) 
            { 
                SPropTagArray rgPropTag    = { 1, { rgRootLookup[i].ulPropTag}}; 
                LPSPropValue  lpPropValue  = NULL; 
                ULONG         cValues      = 0L; 
 
                // Get the outbox entry ID property.  
                hr = MAPICALL(lpMdb)->GetProps( lpMdb, 
                    &rgPropTag, 
                    MAPI_UNICODE, 
                    &cValues, 
                    &lpPropValue); 
                if( FAILED( hr)) 
                { 
                    hr = HR_LOG(E_FAIL); 
                    goto cleanup; 
                } 
         
                if( hr == MAPI_W_ERRORS_RETURNED) 
                { 
                    if( lpPropValue && lpPropValue->Value.ul == MAPI_E_NOT_FOUND) 
                        hr = HR_LOG( MAPI_E_NOT_FOUND); 
                    else 
                        hr = HR_LOG( E_FAIL); 
 
                    goto cleanup; 
                } 
         
                ASSERTERROR(cValues != 0, "ZERO properties returned"); 
                ASSERTERROR(lpPropValue != NULL, "NULL lpPropValue variable"); 
         
                // Check to make sure we got the right property. 
                if (lpPropValue->ulPropTag == rgRootLookup[i].ulPropTag) 
                { 
                    *lpcbeid = lpPropValue->Value.bin.cb; 
     
                    hr = MAPIAllocateBuffer( *lpcbeid, (PVOID*)lppeid); 
                    if( SUCCEEDED( hr)) 
                    { 
                        CopyMemory( *lppeid, lpPropValue->Value.bin.lpb, *lpcbeid); 
                    } 
                    else 
                    { 
                        hr = HR_LOG( E_OUTOFMEMORY); 
                    } 
                } 
                else 
                { 
                    hr = HR_LOG(E_FAIL); 
                } 
 
                MAPIFREEBUFFER( lpPropValue); 
                goto cleanup; 
            } 
        }  
 
        // Not a recognized root folder 
        hr = HR_LOG( EDK_E_NOT_FOUND); 
    } 
 
cleanup: 
    RETURN( hr); 
} 
 
static HRESULT _HrLookupRootFolderA( 
    IN  LPMDB lpMdb,                // pointer to open message store 
    IN  LPCSTR lpszRootFolder,      // root folder name only (no separators) 
    OUT ULONG *lpcbeid,             // size of entryid 
    OUT LPENTRYID *lppeid)          // pointer to entryid 
{ 
    HRESULT      hr           = NOERROR; 
 
    DEBUGPUBLIC( "HrMAPIFindRootFolderA()"); 
 
    hr = CHK_HrMAPIFindRootFolderA( lpMdb, lpszRootFolder, lpcbeid, lppeid); 
    if( FAILED( hr)) 
        RETURN( hr); 
 
    *lpcbeid = 0L; 
    *lppeid  = NULL; 
 
    // Since there are no ENTRYID properties for "Inbox"... 
    if( _strcmpi( lpszRootFolder, "@PR_IPM_INBOX_ENTRYID") == 0) 
    { 
        hr = MAPICALL( lpMdb)->GetReceiveFolder( lpMdb, 
            NULL,       // default message class ("IPM") 
            0L, 
            lpcbeid, 
            lppeid, 
            NULL); 
        if( FAILED( hr)) 
        { 
            if( hr == MAPI_E_NOT_FOUND) 
                hr = HR_LOG( EDK_E_NOT_FOUND); 
            else 
                hr = HR_LOG( E_FAIL); 
 
            goto cleanup; 
        } 
    } 
    else 
    { 
        ULONG cbRootFolder = 0L; 
        ULONG i            = 0L; 
 
        // Calculate length of folder name to speed up search somewhat 
        cbRootFolder = cbStrLenA( lpszRootFolder); 
 
        for( i = 0L; i < ulRootLookupCount; i++) 
        { 
            if( cbRootFolder == rgRootLookup[i].cbRootFolderA && 
                _strcmpi( rgRootLookup[i].lpszRootFolderA, lpszRootFolder) == 0 ) 
            { 
                SPropTagArray rgPropTag    = { 1, { rgRootLookup[i].ulPropTag}}; 
                LPSPropValue  lpPropValue  = NULL; 
                ULONG         cValues      = 0L; 
 
                // Get the outbox entry ID property.  
                hr = MAPICALL(lpMdb)->GetProps( lpMdb, 
                    &rgPropTag, 
                    0L, 
                    &cValues, 
                    &lpPropValue); 
                if( FAILED( hr)) 
                { 
                    hr = HR_LOG(E_FAIL); 
                    goto cleanup; 
                } 
         
                if( hr == MAPI_W_ERRORS_RETURNED) 
                { 
                    if( lpPropValue && lpPropValue->Value.ul == MAPI_E_NOT_FOUND) 
                        hr = HR_LOG( MAPI_E_NOT_FOUND); 
                    else 
                        hr = HR_LOG( E_FAIL); 
 
                    goto cleanup; 
                } 
         
                ASSERTERROR(cValues != 0, "ZERO properties returned"); 
                ASSERTERROR(lpPropValue != NULL, "NULL lpPropValue variable"); 
         
                // Check to make sure we got the right property. 
                if (lpPropValue->ulPropTag == rgRootLookup[i].ulPropTag) 
                { 
                    *lpcbeid = lpPropValue->Value.bin.cb; 
     
                    hr = MAPIAllocateBuffer( *lpcbeid, (PVOID*)lppeid); 
                    if( SUCCEEDED( hr)) 
                    { 
                        CopyMemory( *lppeid, lpPropValue->Value.bin.lpb, *lpcbeid); 
                    } 
                    else 
                    { 
                        hr = HR_LOG( E_OUTOFMEMORY); 
                    } 
                } 
                else 
                { 
                    hr = HR_LOG(E_FAIL); 
                } 
 
                MAPIFREEBUFFER( lpPropValue); 
                goto cleanup; 
            } 
        }  
 
        // Not a recognized root folder 
        hr = HR_LOG( EDK_E_NOT_FOUND); 
    } 
 
cleanup: 
    RETURN( hr); 
} 
 
//$--HrMAPIFindFolder@----------------------------------------------------- 
//  Search folder for entry ID of child folder by name. 
// ----------------------------------------------------------------------------- 
HRESULT HrMAPIFindFolderW(         // RETURNS: return code 
    IN LPMAPIFOLDER lpFolder,           // pointer to folder 
    IN LPCWSTR lpszName,                // name of folder to find 
    OUT ULONG *lpcbeid,                 // pointer to count of bytes in entry ID 
    OUT LPENTRYID *lppeid)              // pointer to entry ID pointer 
{ 
    HRESULThr           = NOERROR; 
LPMAPITABLElpTable      = NULL; 
LPSRowSetlpRow        = NULL; 
    LPSPropValue    lpRowProp    = NULL; 
    ULONG           i            = 0L; 
 
    static const enum { IDISPNAME, IENTRYID }; 
    static const SizedSPropTagArray( 2, rgColProps) = { 2, { PR_DISPLAY_NAME_W, PR_ENTRYID}}; 
     
DEBUGPUBLIC( "HrMAPIFindFolderW()"); 
 
    hr = CHK_HrMAPIFindFolderW( lpFolder, lpszName, lpcbeid, lppeid); 
    if (FAILED(hr)) 
        RETURN(hr); 
 
    // Avoid dereferencing a NULL in retail builds 
    if( !lpcbeid || !lppeid) 
    { 
        hr = HR_LOG( E_INVALIDARG); 
        goto cleanup; 
    } 
 
    *lpcbeid = 0; 
    *lppeid  = NULL; 
 
    if( !lpFolder) 
    { 
        hr = HR_LOG( E_FAIL); 
        goto cleanup; 
    } 
 
hr = MAPICALL( lpFolder)->GetHierarchyTable( lpFolder, 
        MAPI_UNICODE | MAPI_DEFERRED_ERRORS, &lpTable); 
if (FAILED(hr)) 
    { 
        hr = HR_LOG( E_FAIL); 
goto cleanup; 
    } 
 
    hr = HrQueryAllRows( lpTable, (LPSPropTagArray)&rgColProps, NULL, NULL, 0L, &lpRow); 
if( FAILED( hr)) 
    { 
        if( hr == MAPI_E_NOT_FOUND) 
            hr = HR_LOG( EDK_E_NOT_FOUND); 
        else 
            hr = HR_LOG( E_FAIL); 
 
        goto cleanup; 
    } 
 
    ASSERTERROR( lpRow != NULL, "NULL lpRow returned from QueryRows!"); 
     
    // Search rows for the folder in question 
    for(i = 0; i < lpRow->cRows; i++) 
    { 
        ASSERTERROR( 
            lpRow->aRow[i].cValues > 0, 
            "Row is empty of properties."); 
 
        lpRowProp = lpRow->aRow[i].lpProps; 
 
        ASSERTERROR( 
            lpRowProp[IENTRYID].ulPropTag == PR_ENTRYID, 
            "Row does not contain entry id"); 
        ASSERTERROR( 
            lpRowProp[IDISPNAME].ulPropTag == PR_DISPLAY_NAME_A, 
            "Row does not contain display name"); 
 
        if(_wcsicmp(lpRowProp[IDISPNAME].Value.lpszW, lpszName) == 0) 
        { 
            *lpcbeid = lpRowProp[IENTRYID].Value.bin.cb; 
 
            hr = MAPIAllocateBuffer(*lpcbeid, (PVOID*)lppeid); 
            if(FAILED(hr)) 
            { 
                hr = HR_LOG(E_OUTOFMEMORY); 
                goto cleanup; 
            } 
 
            // Copy entry ID 
            CopyMemory( *lppeid, lpRowProp[IENTRYID].Value.bin.lpb, *lpcbeid); 
            goto cleanup; 
        } 
 
    }  // for 
 
    hr = HR_LOG( EDK_E_NOT_FOUND); 
 
cleanup: 
FREEPROWS(lpRow); 
ULRELEASE(lpTable); 
 
    RETURN(hr); 
} 
 
HRESULT HrMAPIFindFolderA(         // RETURNS: return code 
    IN LPMAPIFOLDER lpFolder,           // pointer to folder 
    IN LPCSTR  lpszName,                // name of folder to find 
    OUT ULONG *lpcbeid,                 // pointer to count of bytes in entry ID 
    OUT LPENTRYID *lppeid)              // pointer to entry ID pointer 
{ 
    HRESULThr           = NOERROR; 
LPMAPITABLElpTable      = NULL; 
LPSRowSetlpRow        = NULL; 
    LPSPropValue    lpRowProp    = NULL; 
    ULONG           i            = 0L; 
 
    static const enum { IDISPNAME, IENTRYID }; 
    static SizedSPropTagArray( 2, rgColProps) = { 2, { PR_DISPLAY_NAME_A, PR_ENTRYID}}; 
     
DEBUGPUBLIC( "HrMAPIFindFolderA()"); 
 
    hr = CHK_HrMAPIFindFolderA( lpFolder, lpszName, lpcbeid, lppeid); 
    if (FAILED(hr)) 
        RETURN(hr); 
 
    // Avoid dereferencing a NULL in retail builds 
    if( !lpcbeid || !lppeid) 
    { 
        hr = HR_LOG( E_INVALIDARG); 
        goto cleanup; 
    } 
 
    *lpcbeid = 0; 
    *lppeid  = NULL; 
 
    if( !lpFolder) 
    { 
        hr = HR_LOG( E_INVALIDARG); 
        goto cleanup; 
    } 
 
hr = MAPICALL( lpFolder)->GetHierarchyTable( lpFolder, 
        MAPI_DEFERRED_ERRORS, &lpTable); 
if (FAILED(hr)) 
    { 
        hr = HR_LOG( E_FAIL); 
goto cleanup; 
    } 
 
    hr = HrQueryAllRows( lpTable, (LPSPropTagArray)&rgColProps, NULL, NULL, 0L, &lpRow); 
if( FAILED( hr)) 
    { 
        if( hr == MAPI_E_NOT_FOUND) 
            hr = HR_LOG( EDK_E_NOT_FOUND); 
        else 
            hr = HR_LOG( E_FAIL); 
 
        goto cleanup; 
    } 
 
    ASSERTERROR( lpRow != NULL, "NULL lpRow returned from QueryRows!"); 
     
    // Search rows for the folder in question 
    for(i = 0; i < lpRow->cRows; i++) 
    { 
        ASSERTERROR( 
            lpRow->aRow[i].cValues > 0, 
            "Row is empty of properties."); 
 
        lpRowProp = lpRow->aRow[i].lpProps; 
 
        ASSERTERROR( 
            lpRowProp[IENTRYID].ulPropTag == PR_ENTRYID, 
            "Row does not contain entry id"); 
        ASSERTERROR( 
            lpRowProp[IDISPNAME].ulPropTag == PR_DISPLAY_NAME_A, 
            "Row does not contain display name"); 
 
        if(_strcmpi(lpRowProp[IDISPNAME].Value.lpszA, lpszName) == 0) 
        { 
            *lpcbeid = lpRowProp[IENTRYID].Value.bin.cb; 
 
            hr = MAPIAllocateBuffer(*lpcbeid, (PVOID*)lppeid); 
            if(FAILED(hr)) 
            { 
                hr = HR_LOG(E_OUTOFMEMORY); 
                goto cleanup; 
            } 
 
            // Copy entry ID 
            CopyMemory( *lppeid, lpRowProp[IENTRYID].Value.bin.lpb, *lpcbeid); 
            goto cleanup; 
        } 
 
    }  // for 
 
    hr = HR_LOG( EDK_E_NOT_FOUND); 
 
cleanup: 
FREEPROWS(lpRow); 
ULRELEASE(lpTable); 
 
    RETURN(hr); 
} 
 
//$--HrMAPIFindSubfolderEx@--------------------------------------------------------- 
//  Finds an arbitrarily nested folder in the indicated folder given it's  
//  path name. 
//------------------------------------------------------------------------------ 
HRESULT HrMAPIFindSubfolderExW( 
    IN LPMAPIFOLDER lpRootFolder,       // open root folder 
    IN WCHAR chSep,                     // folder path separator character 
    IN LPCWSTR lpszFolderPath,          // folder path 
    OUT ULONG *lpcbeid,                 // pointer to count of bytes in entry ID 
    OUT LPENTRYID *lppeid)              // pointer to entry ID pointer 
{ 
    HRESULT         hr              = NOERROR; 
    LPMAPIFOLDER    lpParentFolder  = lpRootFolder; 
    LPMAPIFOLDER    lpChildFolder   = NULL; 
ULONG           cbeid           = 0L; 
    LPENTRYID       lpeid           = NULL; 
    LPWSTR         *lppszFolderList = NULL; 
    WCHAR           rgchSep[2]      = L"\\"; 
    ULONG           ulFolderCount   = 0L; 
ULONGulObjType    = 0L; 
    ULONG           i               = 0L; 
 
    DEBUGPUBLIC( "HrMAPIFindSubfolderExW()"); 
 
    hr = CHK_HrMAPIFindSubfolderExW( 
        lpRootFolder, chSep, lpszFolderPath, lpcbeid, lppeid); 
    if( FAILED( hr)) 
        RETURN( hr); 
 
    if( !lpcbeid || !lppeid) 
    { 
        hr = HR_LOG( E_INVALIDARG); 
        goto cleanup; 
    } 
 
    // Set the user defined separator character 
    rgchSep[0] = chSep; 
 
    hr = HrStrTokAllW( lpszFolderPath, rgchSep, &ulFolderCount, &lppszFolderList); 
    if( FAILED( hr)) 
        goto cleanup; 
 
    for(i = 0L; i < ulFolderCount; i++) 
    { 
        // Free entryid before re-use. 
        MAPIFREEBUFFER( lpeid); 
 
        hr = HrMAPIFindFolderW( lpParentFolder, lppszFolderList[i], &cbeid, &lpeid);  
        if( FAILED( hr)) 
            goto cleanup; 
         
        // Only OpenEntry if needed for next tier of folder path. 
        if( lppszFolderList[i+1] != NULL) 
        { 
            hr = MAPICALL( lpParentFolder)->OpenEntry( lpParentFolder, 
                cbeid, 
                lpeid, 
                NULL, 
                MAPI_DEFERRED_ERRORS, 
                &ulObjType, 
                (LPUNKNOWN*)&lpChildFolder); 
            if( FAILED( hr) || ulObjType != MAPI_FOLDER) 
            { 
                MAPIFREEBUFFER( lpeid); 
 
                hr = HR_LOG( E_FAIL); 
                goto cleanup; 
            } 
        } 
 
        // No longer need the parent folder 
        // (Don't release the folder that was passed!) 
        if( i > 0L) 
            ULRELEASE( lpParentFolder); 
         
        lpParentFolder = lpChildFolder; 
        lpChildFolder  = NULL; 
    } 
 
    // Success! 
    *lpcbeid = cbeid; 
    *lppeid  = lpeid; 
 
cleanup: 
    MAPIFREEBUFFER( lppszFolderList); 
 
    RETURN( hr); 
} 
 
HRESULT HrMAPIFindSubfolderExA( 
    IN LPMAPIFOLDER lpRootFolder,       // open root folder 
    IN CHAR chSep,                      // folder path separator character 
    IN LPCSTR lpszFolderPath,           // folder path 
    OUT ULONG *lpcbeid,                 // pointer to count of bytes in entry ID 
    OUT LPENTRYID *lppeid)              // pointer to entry ID pointer 
{ 
    HRESULT         hr              = NOERROR; 
    LPMAPIFOLDER    lpParentFolder  = lpRootFolder; 
    LPMAPIFOLDER    lpChildFolder   = NULL; 
ULONG           cbeid           = 0L; 
    LPENTRYID       lpeid           = NULL; 
    LPSTR          *lppszFolderList = NULL; 
    CHAR            rgchSep[2]      = "\\"; 
    ULONG           ulFolderCount   = 0L; 
ULONGulObjType    = 0L; 
    ULONG           i               = 0L; 
 
    DEBUGPUBLIC( "HrMAPIFindSubfolderExA()"); 
 
    hr = CHK_HrMAPIFindSubfolderExA( 
        lpRootFolder, chSep, lpszFolderPath, lpcbeid, lppeid); 
    if( FAILED( hr)) 
        RETURN( hr); 
 
    if( !lpcbeid || !lppeid) 
    { 
        hr = HR_LOG( E_INVALIDARG); 
        goto cleanup; 
    } 
 
    // Set the user defined separator character 
    rgchSep[0] = chSep; 
 
    hr = HrStrTokAllA( lpszFolderPath, rgchSep, &ulFolderCount, &lppszFolderList); 
    if( FAILED( hr)) 
        goto cleanup; 
 
    for(i = 0L; i < ulFolderCount; i++) 
    { 
        // Free entryid before re-use. 
        MAPIFREEBUFFER( lpeid); 
 
        hr = HrMAPIFindFolderA( lpParentFolder, lppszFolderList[i], &cbeid, &lpeid);  
        if( FAILED( hr)) 
            goto cleanup; 
         
        // Only OpenEntry if needed for next tier of folder path. 
        if( lppszFolderList[i+1] != NULL) 
        { 
            hr = MAPICALL( lpParentFolder)->OpenEntry( lpParentFolder, 
                cbeid, 
                lpeid, 
                NULL, 
                MAPI_DEFERRED_ERRORS, 
                &ulObjType, 
                (LPUNKNOWN*)&lpChildFolder); 
            if( FAILED( hr) || ulObjType != MAPI_FOLDER) 
            { 
                MAPIFREEBUFFER( lpeid); 
 
                hr = HR_LOG( E_FAIL); 
                goto cleanup; 
            } 
        } 
 
        // No longer need the parent folder 
        // (Don't release the folder that was passed!) 
        if( i > 0L) 
            ULRELEASE( lpParentFolder); 
         
        lpParentFolder = lpChildFolder; 
        lpChildFolder  = NULL; 
    } 
 
    // Success! 
    *lpcbeid = cbeid; 
    *lppeid  = lpeid; 
 
cleanup: 
    MAPIFREEBUFFER( lppszFolderList); 
 
    RETURN( hr); 
} 
     
//$--HrMAPIFindFolderEx@----------------------------------------------- 
//  Finds an arbitrarily nested folder in the indicated store given it's  
//  path name. 
//------------------------------------------------------------------------------ 
HRESULT HrMAPIFindFolderExW( 
    IN LPMDB lpMdb,                     // Open message store 
    IN WCHAR  chSep,                    // folder path separator character 
    IN LPCWSTR lpszFolderPath,          // folder path 
    OUT ULONG *lpcbeid,                 // pointer to count of bytes in entry ID 
    OUT LPENTRYID *lppeid)              // pointer to entry ID pointer 
{ 
    HRESULT      hr              = NOERROR; 
    LPMAPIFOLDER lpRootFolder    = NULL; 
    const WCHAR *cpPath          = lpszFolderPath; 
    ULONG        cbeid           = 0L; 
    LPENTRYID    lpeid           = NULL; 
 
    DEBUGPUBLIC("HrMAPIFindFolderExW()"); 
             
    hr = CHK_HrMAPIFindFolderExW( 
        lpMdb, chSep, lpszFolderPath, lpcbeid, lppeid); 
    if( FAILED(hr)) 
        RETURN(hr); 
 
    // Avoid dereferencing a NULL in retail builds 
    if( !lpcbeid || !lppeid) 
    { 
        hr = HR_LOG( E_INVALIDARG); 
        goto cleanup; 
    } 
 
    *lpcbeid = 0L; 
    *lppeid  = NULL; 
 
    if( !lpMdb) 
    { 
        hr = HR_LOG( E_FAIL); 
        goto cleanup; 
    } 
 
    // Move forward past any initial path separators 
    while( *cpPath && *cpPath == chSep) cpPath++; 
 
    // Check for literal property name 
    if( *cpPath == L'@') 
    { 
        WCHAR  szRootFolder[MAX_PATH + 1] = {0}; 
        WCHAR *cpFolder        = szRootFolder; 
 
        // Copy root folder to string buffer 
        while( *cpPath && *cpPath != chSep) *cpFolder++ = *cpPath++; 
     
        *cpFolder = 0; 
     
        hr = _HrLookupRootFolderW( lpMdb, szRootFolder, &cbeid, &lpeid); 
        if( hr == EDK_E_NOT_FOUND) 
        {   // Folder was unrecognized!  Try opening the REAL root folder, 
            // and pass the FULL path to HrMAPIFindSubfolderEx(). 
     
            cpPath = lpszFolderPath; 
            cbeid  = 0L;      // force REAL root folder 
            lpeid  = NULL; 
        } 
        else if( FAILED( hr)) 
            goto cleanup; 
        else 
        {   // Folder found! If path continues, open the returned ENTRYID 
            // and pass the REMAINING path to HrMAPIFindSubfolderEx(). 
     
            // Skip past next separators, if necessary 
            while( *cpPath && *cpPath == chSep) cpPath++; 
        } 
    } 
 
    if( *cpPath) 
    {   // The path continues! 
 
        ULONG ulObjType = 0; 
 
        hr = MAPICALL( lpMdb)->OpenEntry( lpMdb, 
            cbeid, 
            lpeid, 
            NULL, 
            MAPI_BEST_ACCESS | MAPI_DEFERRED_ERRORS, 
            &ulObjType, 
            (LPUNKNOWN*)&lpRootFolder); 
        if( FAILED( hr)) 
            goto cleanup; 
 
        if( ulObjType != MAPI_FOLDER) 
        { 
            hr = HR_LOG( E_FAIL); 
            goto cleanup; 
        } 
 
        // Free before re-use 
        MAPIFREEBUFFER( lpeid); 
 
        // Find the subfolder in question 
        hr = HrMAPIFindSubfolderExW( 
            lpRootFolder, chSep, cpPath, &cbeid, &lpeid); 
        if(FAILED(hr)) 
            goto cleanup; 
    } 
 
    // Success! 
    *lpcbeid = cbeid; 
    *lppeid  = lpeid; 
 
cleanup: 
    ULRELEASE(lpRootFolder); 
 
    RETURN(hr); 
} 
 
HRESULT HrMAPIFindFolderExA( 
    IN LPMDB lpMdb,                     // Open message store 
    IN CHAR  chSep,                     // folder path separator character 
    IN LPCSTR lpszFolderPath,           // folder path 
    OUT ULONG *lpcbeid,                 // pointer to count of bytes in entry ID 
    OUT LPENTRYID *lppeid)              // pointer to entry ID pointer 
{ 
    HRESULT      hr              = NOERROR; 
    LPMAPIFOLDER lpRootFolder    = NULL; 
    const CHAR  *cpPath          = lpszFolderPath; 
    ULONG        cbeid           = 0L; 
    LPENTRYID    lpeid           = NULL; 
 
    DEBUGPUBLIC("HrMAPIFindFolderExA()"); 
             
    hr = CHK_HrMAPIFindFolderExA( 
        lpMdb, chSep, lpszFolderPath, lpcbeid, lppeid); 
    if( FAILED(hr)) 
        RETURN(hr); 
 
    // Avoid dereferencing a NULL in retail builds 
    if( !lpcbeid || !lppeid) 
    { 
        hr = HR_LOG( E_INVALIDARG); 
        goto cleanup; 
    } 
 
    *lpcbeid = 0L; 
    *lppeid  = NULL; 
 
    if( !lpMdb) 
    { 
        hr = HR_LOG( E_FAIL); 
        goto cleanup; 
    } 
 
    // Move forward past any initial path separators 
    while( *cpPath && *cpPath == chSep) cpPath++; 
 
    // Check for literal property name 
    if( *cpPath == '@') 
    { 
        CHAR  szRootFolder[MAX_PATH + 1] = {0}; 
        CHAR *cpFolder        = szRootFolder; 
     
        // Copy root folder to string buffer 
        while( *cpPath && *cpPath != chSep) *cpFolder++ = *cpPath++; 
     
        *cpFolder = 0; 
     
        hr = _HrLookupRootFolderA( lpMdb, szRootFolder, &cbeid, &lpeid); 
        if( hr == EDK_E_NOT_FOUND) 
        {   // Folder was unrecognized!  Try opening the REAL root folder, 
            // and pass the FULL path to HrMAPIFindSubfolderEx(). 
     
            cpPath = lpszFolderPath; 
            cbeid  = 0L;      // force REAL root folder 
            lpeid  = NULL; 
        } 
        else if( FAILED( hr)) 
            goto cleanup; 
        else 
        {   // Folder found! If path continues, open the returned ENTRYID 
            // and pass the REMAINING path to HrMAPIFindSubfolderEx(). 
     
            // Skip past next separators, if necessary 
            while( *cpPath && *cpPath == chSep) cpPath++; 
        } 
    } 
     
    if( *cpPath) 
    {   // The path continues! 
 
        ULONG ulObjType = 0; 
 
        hr = MAPICALL( lpMdb)->OpenEntry( lpMdb, 
            cbeid, 
            lpeid, 
            NULL, 
            MAPI_BEST_ACCESS | MAPI_DEFERRED_ERRORS, 
            &ulObjType, 
            (LPUNKNOWN*)&lpRootFolder); 
        if( FAILED( hr)) 
            goto cleanup; 
 
        if( ulObjType != MAPI_FOLDER) 
        { 
            hr = HR_LOG( E_FAIL); 
            goto cleanup; 
        } 
 
        // Free before re-use 
        MAPIFREEBUFFER( lpeid); 
 
        // Find the subfolder in question 
        hr = HrMAPIFindSubfolderExA( 
            lpRootFolder, chSep, cpPath, &cbeid, &lpeid); 
        if(FAILED(hr)) 
            goto cleanup; 
    } 
 
    // Success! 
    *lpcbeid = cbeid; 
    *lppeid  = lpeid; 
 
cleanup: 
    ULRELEASE(lpRootFolder); 
 
    RETURN(hr); 
} 
 
//$--HrMAPIOpenFolderEx@----------------------------------------------- 
//  Opens an arbitrarily nested folder in the indicated store given it's  
//  path name. 
//------------------------------------------------------------------------------ 
HRESULT HrMAPIOpenFolderExW( 
    IN LPMDB lpMdb,                     // Open message store 
    IN WCHAR chSep,                     // folder path separator character 
    IN LPCWSTR lpszFolderPath,          // folder path 
    OUT LPMAPIFOLDER * lppFolder)       // pointer to folder opened 
{ 
    HRESULT   hr        = NOERROR; 
    LPENTRYID lpeid     = NULL; 
    ULONG     cbeid     = 0; 
    ULONG     ulObjType = 0; 
 
    DEBUGPUBLIC( "HrMAPIOpenFolderExW()"); 
             
    hr = CHK_HrMAPIOpenFolderExW( 
        lpMdb, chSep, lpszFolderPath, lppFolder); 
    if(FAILED(hr)) 
        RETURN(hr); 
 
    if( !lppFolder) 
    { 
        hr = HR_LOG( E_INVALIDARG); 
        goto cleanup; 
    } 
 
    *lppFolder = NULL; 
 
    hr = HrMAPIFindFolderExW( 
        lpMdb, chSep, lpszFolderPath, 
        &cbeid, &lpeid); 
    if(FAILED(hr)) 
        goto cleanup; 
 
    hr = MAPICALL( lpMdb)->OpenEntry( lpMdb, 
        cbeid, 
        lpeid, 
        NULL, 
MAPI_BEST_ACCESS | MAPI_DEFERRED_ERRORS, 
        &ulObjType, 
        (LPUNKNOWN*)lppFolder); 
    if( FAILED( hr) || ulObjType != MAPI_FOLDER) 
    { 
        hr = HR_LOG(E_FAIL); 
        goto cleanup; 
    } 
 
    ASSERT_IUNKNOWN_PTR( *lppFolder, "INVALID *lppFolder pointer"); 
 
cleanup: 
    MAPIFREEBUFFER(lpeid); 
 
    RETURN(hr); 
} 
 
HRESULT HrMAPIOpenFolderExA( 
    IN LPMDB lpMdb,                     // Open message store 
    IN CHAR chSep,                      // folder path separator character 
    IN LPCSTR lpszFolderPath,           // folder path 
    OUT LPMAPIFOLDER * lppFolder)       // pointer to folder opened 
{ 
    HRESULT   hr        = NOERROR; 
    LPENTRYID lpeid     = NULL; 
    ULONG     cbeid     = 0; 
    ULONG     ulObjType = 0; 
 
    DEBUGPUBLIC( "HrMAPIOpenFolderExA()"); 
             
    hr = CHK_HrMAPIOpenFolderExA( 
        lpMdb, chSep, lpszFolderPath, lppFolder); 
    if(FAILED(hr)) 
        RETURN(hr); 
 
    if( !lppFolder) 
    { 
        hr = HR_LOG( E_INVALIDARG); 
        goto cleanup; 
    } 
 
    *lppFolder = NULL; 
 
    hr = HrMAPIFindFolderExA( 
        lpMdb, chSep, lpszFolderPath, 
        &cbeid, &lpeid); 
    if(FAILED(hr)) 
        goto cleanup; 
 
    hr = MAPICALL(lpMdb)->OpenEntry( lpMdb, 
        cbeid, 
        lpeid, 
        NULL, 
        MAPI_BEST_ACCESS | MAPI_DEFERRED_ERRORS, 
        &ulObjType, 
        (LPUNKNOWN*)lppFolder); 
    if( FAILED( hr) || ulObjType != MAPI_FOLDER) 
    { 
        hr = HR_LOG(E_FAIL); 
        goto cleanup; 
    } 
 
    ASSERT_IUNKNOWN_PTR(*lppFolder, "INVALID *lppFolder pointer"); 
 
cleanup: 
    MAPIFREEBUFFER(lpeid); 
 
    RETURN(hr); 
} 
 
//$--HrMAPIOpenSubfolderEx@--------------------------------------------------- 
//  Opens an aribtrarily nested folder in the indicated folder given 
//  its path name.  
//------------------------------------------------------------------------ 
HRESULT HrMAPIOpenSubfolderExW( 
    IN LPMAPIFOLDER lpRootFolder,       // open root folder 
    IN WCHAR chSep,                     // character used as path separator 
    IN LPCWSTR lpszFolderPath,          // folder path 
    OUT LPMAPIFOLDER *lppFolder)        // pointer to open child folder 
{ 
    HRESULT   hr        = NOERROR; 
    LPENTRYID lpeid     = NULL; 
    ULONG     cbeid     = 0; 
    ULONG     ulObjType = 0; 
 
    DEBUGPUBLIC( "HrMAPIOpenSubfolderExW()"); 
             
    hr = CHK_HrMAPIOpenSubfolderExW( 
        lpRootFolder, chSep, lpszFolderPath, lppFolder); 
    if(FAILED(hr)) 
        RETURN(hr); 
 
    if( !lppFolder) 
    { 
        hr = HR_LOG( E_INVALIDARG); 
        goto cleanup; 
    } 
 
    *lppFolder = NULL; 
 
    hr = HrMAPIFindSubfolderExW( 
        lpRootFolder, chSep, lpszFolderPath, 
        &cbeid, &lpeid); 
    if(FAILED(hr)) 
        goto cleanup; 
 
    hr = MAPICALL( lpRootFolder)->OpenEntry( lpRootFolder, 
        cbeid, 
        lpeid, 
        NULL, 
        MAPI_BEST_ACCESS | MAPI_DEFERRED_ERRORS, 
        &ulObjType, 
        (LPUNKNOWN*)lppFolder); 
    if( FAILED( hr) || ulObjType != MAPI_FOLDER) 
    { 
        hr = HR_LOG(E_FAIL); 
        goto cleanup; 
    } 
 
    ASSERT_IUNKNOWN_PTR( *lppFolder, "INVALID Folder!"); 
 
cleanup: 
    MAPIFREEBUFFER(lpeid); 
 
    RETURN(hr); 
} 
 
HRESULT HrMAPIOpenSubfolderExA( 
    IN LPMAPIFOLDER lpRootFolder,       // open root folder 
    IN CHAR chSep,                      // character used as path separator 
    IN LPCSTR lpszFolderPath,           // folder path 
    OUT LPMAPIFOLDER *lppFolder)        // pointer to open child folder 
{ 
    HRESULT   hr        = NOERROR; 
    LPENTRYID lpeid     = NULL; 
    ULONG     cbeid     = 0; 
    ULONG     ulObjType = 0; 
 
    DEBUGPUBLIC( "HrMAPIOpenSubfolderExA()"); 
             
    hr = CHK_HrMAPIOpenSubfolderExA( 
        lpRootFolder, chSep, lpszFolderPath, lppFolder); 
    if(FAILED(hr)) 
        RETURN(hr); 
 
    if( !lppFolder) 
    { 
        hr = HR_LOG( E_INVALIDARG); 
        goto cleanup; 
    } 
 
    *lppFolder = NULL; 
 
    hr = HrMAPIFindSubfolderExA( 
        lpRootFolder, chSep, lpszFolderPath, 
        &cbeid, &lpeid); 
    if(FAILED(hr)) 
        goto cleanup; 
 
    hr = MAPICALL( lpRootFolder)->OpenEntry( lpRootFolder, 
        cbeid, 
        lpeid, 
        NULL, 
        MAPI_BEST_ACCESS | MAPI_DEFERRED_ERRORS, 
        &ulObjType, 
        (LPUNKNOWN*)lppFolder); 
    if( FAILED( hr) || ulObjType != MAPI_FOLDER) 
    { 
        hr = HR_LOG(E_FAIL); 
        goto cleanup; 
    } 
 
    ASSERT_IUNKNOWN_PTR( *lppFolder, "INVALID Folder!"); 
 
cleanup: 
    MAPIFREEBUFFER(lpeid); 
 
    RETURN(hr); 
} 
 
//$--HrOpenExchangePublicFolders----------------------------------------------- 
//  Opens the root of the public folder heirarchy. 
//------------------------------------------------------------------------ 
HRESULT HrOpenExchangePublicFolders( 
    IN LPMDB lpPubStore,                // pointer to public message store 
    OUT LPMAPIFOLDER *lppRootFolder)    // return ptr to public folder root 
{ 
    HRESULT       hr           = NOERROR; 
    ULONG         cValues      = 0L; 
    LPSPropValue  lpPropValue  = NULL; 
    SPropTagArray rgPropTag    = { 1, { PR_IPM_PUBLIC_FOLDERS_ENTRYID } }; 
    ULONG         ulObjType    = 0L; 
    LPMAPIFOLDER  lpRootFolder = NULL; 
     
    DEBUGPUBLIC( "HrOpenExchangePublicFolders()"); 
 
    hr = CHK_HrOpenExchangePublicFolders( lpPubStore, lppRootFolder); 
    if( FAILED( hr)) 
        RETURN( hr); 
 
    // Avoid dereferencing a NULL in retail builds 
    if( !lpPubStore) 
    { 
        hr = HR_LOG( E_INVALIDARG); 
        goto cleanup; 
    } 
 
    // Get the outbox entry ID property.  
    hr = MAPICALL(lpPubStore)->GetProps( lpPubStore, 
        &rgPropTag, 
        fMapiUnicode, 
        &cValues, 
        &lpPropValue); 
    if( FAILED( hr)) 
    { 
        lpPropValue = NULL; 
 
        hr = HR_LOG(E_FAIL); 
        goto cleanup; 
    } 
 
    if( hr == 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; 
    } 
 
    ASSERTERROR(cValues != 0, "ZERO cValues variable"); 
 
    ASSERTERROR(lpPropValue != NULL, "NULL lpPropValue variable"); 
 
    // Check to make sure we got the right property. 
    if (lpPropValue->ulPropTag != PR_IPM_PUBLIC_FOLDERS_ENTRYID) 
    { 
        hr = HR_LOG(E_FAIL); 
        goto cleanup; 
    } 
 
    hr = MAPICALL( lpPubStore)->OpenEntry( lpPubStore, 
        lpPropValue->Value.bin.cb, 
        (LPENTRYID)lpPropValue->Value.bin.lpb, 
        NULL, 
        MAPI_BEST_ACCESS | MAPI_DEFERRED_ERRORS, 
        &ulObjType, 
        (LPUNKNOWN*)&lpRootFolder); 
    if( FAILED( hr) || ulObjType != MAPI_FOLDER) 
        goto cleanup; 
 
    *lppRootFolder = lpRootFolder; 
 
cleanup: 
 
    MAPIFREEBUFFER(lpPropValue); 
 
    RETURN(hr); 
}