SMHMDB.C
/* 
 *  S M H M D B . C 
 * 
 *  Sample mail handling hook 
 *  Store Tables 
 * 
 *  Copyright 1992-95 Microsoft Corporation.  All Rights Reserved. 
 */ 
 
#include "_pch.h" 
 
 
/* 
 *  sptStoTbl 
 * 
 *  The store table column set and enum 
 */ 
enum { ipNull, ipEid, ipDispNm, ipRsrcFlags, cpStoTblMax }; 
static const SizedSPropTagArray (cpStoTblMax, sptStoTbl) = 
{ 
    cpStoTblMax, 
    { 
        PR_NULL, 
        PR_ENTRYID, 
        PR_DISPLAY_NAME_A, 
        PR_RESOURCE_FLAGS 
    } 
}; 
 
 
/* 
 *  HrInitStoresTable() 
 * 
 *  Purpose: 
 * 
 *      Inits the stores table stucture and adds a reference to the SMH 
 *      parent object.  This is done by getting the message stores table 
 *      from the MAPI session and querying all rows (up to cStoMax) and 
 *      mapping the return to an LPSTOTABLE structure. 
 * 
 *  Arguments: 
 * 
 *      lpsmh           the SMH parent object 
 *      lpsess          the MAPI session that this SMH instance belongs to 
 * 
 *  Returns: 
 * 
 *      (HRESULT) 
 */ 
HRESULT 
HrInitStoresTable (LPSMH lpsmh, LPMAPISESSION lpsess) 
{ 
    HRESULT hr; 
    LPMAPITABLE lptbl; 
    LPSRowSet lprws = NULL; 
    LPSTOTABLE lpstotbl; 
    UINT i; 
 
    Assert (lpsmh->lpstotbl == NULL); 
    hr = lpsess->lpVtbl->GetMsgStoresTable (lpsess, 0, &lptbl); 
    if (!HR_FAILED (hr)) 
    { 
        hr = lptbl->lpVtbl->SetColumns (lptbl, (LPSPropTagArray)&sptStoTbl, 0); 
        if (!HR_FAILED (hr)) 
        { 
            hr = lptbl->lpVtbl->QueryRows (lptbl, cStoMax, 0, &lprws); 
            if (!HR_FAILED (hr)) 
            { 
                /*  Zero fill the initial property in all rows. 
                 *  This has the nice side effect of NULL'ing the 
                 *  lpmdb member of the structure 
                 */ 
                lpstotbl = (LPSTOTABLE)lprws; 
                for (i = 0; i < lpstotbl->cSto; i++) 
                    memset (&lpstotbl->aSto[i].lpstoe->valPad, 
                        0, sizeof(SPropValue)); 
 
                lpsmh->lpstotbl = lpstotbl; 
            } 
        } 
        UlRelease (lptbl); 
    } 
 
    DebugTraceResult (HrInitStoresTable(), hr); 
    return hr; 
} 
 
 
/* 
 *  ReleaseStoresTable() 
 * 
 *  Purpose: 
 * 
 *      Releases all resources owned by the store table and disconnects 
 *      the SMH parent from the table. 
 * 
 *  Arguments: 
 * 
 *      lpsmh       the SMH parent object 
 */ 
VOID 
ReleaseStoresTable (LPSMH lpsmh) 
{ 
    LPSTOTABLE lpstotbl = lpsmh->lpstotbl; 
    UINT i; 
 
    if (lpstotbl) 
    { 
        for (i = 0; i < lpstotbl->cSto; i++) 
        { 
            UlRelease (lpstotbl->aSto[i].lpstoe->lpmdb); 
            (*lpsmh->lpfnFree) (lpstotbl->aSto[i].lpProps); 
        } 
        (*lpsmh->lpfnFree) (lpstotbl); 
        lpsmh->lpstotbl = NULL; 
    } 
    return; 
} 
 
 
/* 
 *  HrOpenStoEntry() 
 * 
 *  Purpose: 
 * 
 *      Opens the store associated with a stoenty in the stores table. 
 * 
 *      IMPORTANT: the caller does not end up owning the store reference 
 *      and should NOT call Release() on the store unless they also call 
 *      AddRef().  The referece is owned by the stores table and is 
 *      released upon the tables destruction. 
 * 
 *  Arguments: 
 * 
 *      lpsess          the MAPI session object 
 *      lpsto           the STO structure for the MDB to open 
 *      lppmdb  [OUT]   contains the LPMDB iff the call succeeds 
 * 
 *  Returns: 
 * 
 *      (HRESULT) 
 */ 
HRESULT 
HrOpenStoEntry (LPMAPISESSION lpsess, LPSTO lpsto, LPMDB FAR * lppmdb) 
{ 
    HRESULT hr = hrSuccess; 
    LPMDB lpmdb = NULL; 
 
    if (!lpsto->lpstoe->lpmdb) 
    { 
        hr = lpsess->lpVtbl->OpenMsgStore (lpsess, 
                                0, 
                                lpsto->lpProps[ipEid].Value.bin.cb, 
                                (LPENTRYID)lpsto->lpProps[ipEid].Value.bin.lpb, 
                                NULL, 
                                MDB_WRITE | MDB_NO_DIALOG | MDB_NO_MAIL, 
                                &lpmdb); 
        if (!HR_FAILED (hr)) 
            lpsto->lpstoe->lpmdb = lpmdb; 
         
        *lppmdb = lpmdb; 
    } 
    else 
    { 
        *lppmdb = lpsto->lpstoe->lpmdb; 
    } 
 
    DebugTraceResult (HrOpenStoEntry(), hr); 
    return hr; 
} 
 
 
/* 
 *  HrOpenMdbFromEid() 
 * 
 *  Purpose: 
 * 
 *      Opens a message store by entryid.  The entryid is looked up in 
 *      the stores table to find the proper STOENTRY.  If no entry is 
 *      found, then the store is not opened.  If one is found, then the 
 *      MDB is retrieved from the STOENTRY.  If it has not yet been opened, 
 *      the MDB is opened at this time and stored (no pun intended). 
 * 
 *      IMPORTANT: the caller does not end up owning the store reference 
 *      and should NOT call Release() on the store unless they also call 
 *      AddRef().  The referece is owned by the stores table and is 
 *      released upon the tables destruction. 
 * 
 *  Arguments: 
 * 
 *      lpsmh           the SMH parent object 
 *      cbeid           size of the stores entryid 
 *      lpeid           the entryid to be opened 
 *      lppmdb  [OUT]   contains the LPMDB iff the call succeeds 
 * 
 *  Returns: 
 * 
 *      (HRESULT) 
 */ 
HRESULT 
HrOpenMdbFromEid (LPSMH lpsmh, ULONG cbeid, LPENTRYID lpeid, LPMDB FAR * lppmdb) 
{ 
    HRESULT hr = ResultFromScode (MAPI_E_NOT_FOUND); 
    LPSTOTABLE lpstotbl = lpsmh->lpstotbl; 
    UINT i; 
 
    if (lpstotbl) 
    { 
        for (i = 0; i < lpstotbl->cSto; i++) 
        { 
            if ((cbeid == lpstotbl->aSto[i].lpProps[ipEid].Value.bin.cb) && 
                !memcmp (lpeid, lpstotbl->aSto[i].lpProps[ipEid].Value.bin.lpb, (UINT)cbeid)) 
            { 
                if (lpstotbl->aSto[i].lpstoe->lpmdb) 
                { 
                    *lppmdb = lpstotbl->aSto[i].lpstoe->lpmdb; 
                    hr = hrSuccess; 
                } 
                else 
                    hr = HrOpenStoEntry (lpsmh->lpsess, &lpstotbl->aSto[i], lppmdb); 
 
                break; 
            } 
        } 
    } 
 
    if (HR_FAILED (hr)) 
        *lppmdb = NULL; 
 
    DebugTraceResult (HrOpenMdbFromEid(), hr); 
    return hr; 
} 
 
 
/* 
 *  HrOpenMdbFromName() 
 * 
 *  Purpose: 
 * 
 *      Opens a message store by PR_DISPLAY_NAME value.  The name is 
 *      looked up in the stores table to find the proper STOENTRY.  If no 
 *      entry is found, then the store is not opened.  If one is found, 
 *      then the MDB is retrieved from the STOENTRY.  If it has not yet 
 *      been opened, the MDB is opened at this time and stored (no pun 
 *      intended). 
 * 
 *      IMPORTANT: the caller does not end up owning the store reference 
 *      and should NOT call Release() on the store unless they also call 
 *      AddRef().  The referece is owned by the stores table and is 
 *      released upon the tables destruction. 
 * 
 *  Arguments: 
 * 
 *      lpsmh           the SMH parent object 
 *      lpszName        the name of the store to open 
 *      lppmdb  [OUT]   contains the LPMDB iff the call succeeds 
 * 
 *  Returns: 
 * 
 *      (HRESULT) 
 */ 
HRESULT 
HrOpenMdbFromName (LPSMH lpsmh, LPTSTR lpszName, LPMDB FAR * lppmdb) 
{ 
    HRESULT hr = ResultFromScode (MAPI_E_NOT_FOUND); 
    LPSTOTABLE lpstotbl = lpsmh->lpstotbl; 
    UINT i; 
 
    if (lpstotbl) 
    { 
        for (i = 0; i < lpstotbl->cSto; i++) 
        { 
            if (!lstrcmpi (lpszName, lpstotbl->aSto[i].lpProps[ipDispNm].Value.LPSZ)) 
            { 
                if (lpstotbl->aSto[i].lpstoe->lpmdb) 
                { 
                    *lppmdb = lpstotbl->aSto[i].lpstoe->lpmdb; 
                    hr = hrSuccess; 
                } 
                else 
                    hr = HrOpenStoEntry (lpsmh->lpsess, &lpstotbl->aSto[i], lppmdb); 
 
                break; 
            } 
        } 
    } 
 
    if (HR_FAILED (hr)) 
        *lppmdb = NULL; 
 
    DebugTraceResult (HrOpenMdbFromEid(), hr); 
    return hr; 
}