OOUSER.C
/*********************************************************************** 
 * 
 *  OOUSER.C 
 * 
 *  Sample AB One Off Mail User object 
 *  This file contains the code for implementing the Sample AB 
 *  One Off Mail user. 
 * 
 *  This is the object that is opened in response to the entryID that is 
 *  supplied by this provider in the one-off table (see GetOneOffTable() in 
 *  ABP.C).  All this object does is supply a display table and any default 
 *  values for properties that might need to be there.  One important property 
 *  that this object exports is it's PR_TEMPLATEID (see how this object and 
 *  the implementation in OOTID.C work together). 
 * 
 *  Copyright 1992-1995 Microsoft Corporation.  All Rights Reserved. 
 * 
 ***********************************************************************/ 
 
#include "abp.h" 
#include "sampabp.rh" 
 
/* 
 *  Display table control structures for the OneOff property sheet. 
 */ 
 
/* 
 *  This is the edit control on the one-off pane. 
 */ 
static DTBLEDIT editOOUserDisplayName = 
{ 
    sizeof(DTBLEDIT), 
    0, 
    MAX_DISPLAY_NAME, 
    PR_DISPLAY_NAME_A 
}; 
 
/* 
 *  This edit control is for the server name edit box. 
 */ 
static DTBLEDIT editOOUserServer = 
{ 
    sizeof(DTBLEDIT), 
    0, 
    MAX_SERVER_NAME, 
    PR_SERVER_NAME 
}; 
 
/* 
 *  This is the edit control associated with the Share field. 
 */ 
static DTBLEDIT editOOUserShare = 
{ 
    sizeof(DTBLEDIT), 
    0, 
    MAX_SHARE_NAME, 
    PR_SHARE_NAME 
}; 
 
/* 
 *  This is the edit control associated with the path. 
 */ 
static DTBLEDIT editOOUserPath = 
{ 
    sizeof(DTBLEDIT), 
    0, 
    MAX_PATH, 
    PR_PATH_NAME 
}; 
 
/* 
 *  General Property Page definition 
 */ 
static DTCTL rgdtctlOOUserGeneral[] = 
{ 
    /* general property page */ 
    /* 
     *  Although this control is not absolutely required, 
     *  we suggest filling it in.  This non-requirement 
     *  will probibly change before we actually ship! 
     */ 
    {DTCT_PAGE, 0, NULL, 0, NULL, 0, &dtblpage}, 
 
    /* display name static control and edit control */ 
    /* 
     *  Note that this edit control is editable and required 
     */ 
    {DTCT_LABEL, 0, NULL, 0, NULL, 
        IDC_STATIC_CONTROL, &dtbllabel}, 
    {DTCT_EDIT, DT_EDITABLE|DT_REQUIRED, NULL, 0, szNoFilter, 
        IDC_OOUSER_DISPLAY_NAME, &editOOUserDisplayName}, 
 
    /* group box */ 
    {DTCT_GROUPBOX, 0, NULL, 0, NULL, 
        IDC_STATIC_CONTROL, &dtblgroupbox}, 
    /* 
     *  The following three label/edit pairs make up the 
     *  calculated email address (see OOTID.C's SaveChanges() method). 
     */ 
    /* server static control and edit control */ 
     
    {DTCT_LABEL, 0, NULL, 0, NULL, 
        IDC_STATIC_CONTROL, &dtbllabel}, 
    {DTCT_EDIT, DT_EDITABLE | DT_REQUIRED, NULL, 0, szFileNameFilter, 
        IDC_OOUSER_SERVER, &editOOUserServer}, 
 
    /* share static control and edit control */ 
    {DTCT_LABEL, 0, NULL, 0, NULL, 
        IDC_STATIC_CONTROL, &dtbllabel}, 
    {DTCT_EDIT, DT_EDITABLE | DT_REQUIRED, NULL, 0, szFileNameFilter, 
        IDC_OOUSER_SHARE, &editOOUserShare}, 
 
    /* path static control and edit control */ 
    {DTCT_LABEL, 0, NULL, 0, NULL, 
        IDC_STATIC_CONTROL, &dtbllabel}, 
    {DTCT_EDIT, DT_EDITABLE, NULL, 0, szNoFilter, 
        IDC_OOUSER_PATH, &editOOUserPath}, 
}; 
 
/* 
 *  The OneOff property sheet definition.  This is an array of 
 *  property sheet pages that gets passed to BuildDisplayTable(). 
 */ 
static DTPAGE rgdtpage[] = 
{ 
    { 
        sizeof(rgdtctlOOUserGeneral) / sizeof(DTCTL), 
        (LPTSTR) MAKEINTRESOURCE(OOUserGeneralPage), 
        "", 
        rgdtctlOOUserGeneral 
    }, 
}; 
 
 
 
 
/* 
 *  Declaration of IMailUser object implementation 
 */ 
#undef  INTERFACE 
#define INTERFACE   struct _ABOOUSER 
 
#undef  MAPIMETHOD_ 
#define MAPIMETHOD_(type, method)   MAPIMETHOD_DECLARE(type, method, ABOOUSER_) 
        MAPI_IUNKNOWN_METHODS(IMPL) 
        MAPI_IMAPIPROP_METHODS(IMPL) 
        MAPI_IMAILUSER_METHODS(IMPL) 
#undef  MAPIMETHOD_ 
#define MAPIMETHOD_(type, method)   MAPIMETHOD_TYPEDEF(type, method, ABOOUSER_) 
        MAPI_IUNKNOWN_METHODS(IMPL) 
        MAPI_IMAPIPROP_METHODS(IMPL) 
        MAPI_IMAILUSER_METHODS(IMPL) 
#undef  MAPIMETHOD_ 
#define MAPIMETHOD_(type, method)   STDMETHOD_(type, method) 
 
DECLARE_MAPI_INTERFACE(ABOOUSER_) 
{ 
    MAPI_IUNKNOWN_METHODS(IMPL) 
    MAPI_IMAPIPROP_METHODS(IMPL) 
    MAPI_IMAILUSER_METHODS(IMPL) 
}; 
 
/* 
 *  Structure behind the 'this' 
 */ 
 
typedef struct _ABOOUSER 
{ 
    const ABOOUSER_Vtbl FAR * lpVtbl; 
 
    SAB_Wrapped; 
 
} ABOOUSER, *LPABOOUSER; 
 
 
#define ABOOUSER_ValidateObject(Method, pThis)      \ 
{                                                   \ 
    HRESULT hResult;                                \ 
    if (IsBadReadPtr(pThis, sizeof(ABOOUSER)))      \ 
    {                                               \ 
        hResult = ResultFromScode(E_INVALIDARG);    \ 
        DebugTraceResult(ABOOUSER##_##Method, hResult); \ 
        return hResult;                             \ 
    }                                               \ 
                                                    \ 
    if (pThis->lpVtbl != &vtblABOOUSER)             \ 
    {                                               \ 
        hResult = ResultFromScode(E_INVALIDARG);    \ 
        DebugTraceResult(ABOOUSER##_##Method, hResult); \ 
        return hResult;                             \ 
    }                                               \ 
} 
 
/* 
 *  ABOOUser vtbl is set up here. 
 */ 
static const ABOOUSER_Vtbl vtblABOOUSER = 
{ 
    (ABOOUSER_QueryInterface_METHOD *)  ABU_QueryInterface, 
    (ABOOUSER_AddRef_METHOD *)          WRAP_AddRef, 
    (ABOOUSER_Release_METHOD *)         WRAP_Release, 
    (ABOOUSER_GetLastError_METHOD *)    WRAP_GetLastError, 
    (ABOOUSER_SaveChanges_METHOD *)     WRAP_SaveChanges, 
    (ABOOUSER_GetProps_METHOD *)        WRAP_GetProps, 
    (ABOOUSER_GetPropList_METHOD *)     WRAP_GetPropList, 
    ABOOUSER_OpenProperty, 
    (ABOOUSER_SetProps_METHOD *)        WRAP_SetProps, 
    (ABOOUSER_DeleteProps_METHOD *)     WRAP_DeleteProps, 
    (ABOOUSER_CopyTo_METHOD *)          WRAP_CopyTo, 
    (ABOOUSER_CopyProps_METHOD *)       WRAP_CopyProps, 
    (ABOOUSER_GetNamesFromIDs_METHOD *) WRAP_GetNamesFromIDs, 
    (ABOOUSER_GetIDsFromNames_METHOD *) WRAP_GetIDsFromNames, 
}; 
 
enum {  ivaloousrPR_DISPLAY_TYPE = 0, 
        ivaloousrPR_ADDRTYPE_A, 
        ivaloousrPR_TEMPLATEID, 
        cvaloousrMax }; 
 
SizedSPropTagArray( cvaloousrMax, tagaABOOUSERAccess) = 
{ 
      cvaloousrMax 
    , { PR_DISPLAY_TYPE 
      , PR_ADDRTYPE_A 
      , PR_TEMPLATEID 
      } 
}; 
 
ULONG   rgulABOOUSERAccess[cvaloousrMax] = 
{ 
      IPROP_READONLY | IPROP_CLEAN  /* PR_DISPLAY_TYPE */ 
    , IPROP_READONLY | IPROP_CLEAN  /* PR_ADDRTYPE_A */ 
    , IPROP_READONLY | IPROP_CLEAN  /* PR_TEMPLATEID */ 
}; 
 
/************************************************************************* 
 * 
 -  NewSampOOUser 
 - 
 *  Creates the IMailUser associated with a one off mail user. 
 * 
 * 
 */ 
HRESULT 
HrNewSampOOUser(LPMAILUSER *        lppMAPIPropEntry, 
                ULONG *             lpulObjType, 
                ULONG               cbEntryID, 
                LPENTRYID           lpEntryID, 
                LPABLOGON           lpABPLogon, 
                LPCIID              lpInterface, 
                HINSTANCE           hLibrary, 
                LPALLOCATEBUFFER    lpAllocBuff, 
                LPALLOCATEMORE      lpAllocMore, 
                LPFREEBUFFER        lpFreeBuff, 
                LPMALLOC            lpMalloc ) 
{ 
    LPABOOUSER lpABOOUser = NULL; 
    SCODE sc; 
    HRESULT hr = hrSuccess; 
    LPPROPDATA lpPropData = NULL; 
    SPropValue spv[4]; 
 
    /*  Do I support this interface?? */ 
    if (lpInterface) 
    { 
        if (memcmp(lpInterface, &IID_IMailUser, sizeof(IID)) && 
            memcmp(lpInterface, &IID_IMAPIProp, sizeof(IID)) && 
            memcmp(lpInterface, &IID_IUnknown, sizeof(IID))) 
        { 
            DebugTraceSc(HrNewSampOOUser, MAPI_E_INTERFACE_NOT_SUPPORTED); 
            return ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED); 
        } 
    } 
 
    /* 
     *  Allocate space for the ABOOUser structure 
     */ 
    sc = lpAllocBuff(sizeof(ABOOUSER), (LPVOID *) &lpABOOUser); 
 
    if (FAILED(sc)) 
    { 
        hr = ResultFromScode(sc); 
        goto err; 
    } 
 
    lpABOOUser->lpVtbl = &vtblABOOUSER; 
    lpABOOUser->lcInit = 1; 
    lpABOOUser->hResult = hrSuccess; 
    lpABOOUser->idsLastError = 0; 
    lpABOOUser->hLibrary = hLibrary; 
    lpABOOUser->lpAllocBuff = lpAllocBuff; 
    lpABOOUser->lpAllocMore = lpAllocMore; 
    lpABOOUser->lpFreeBuff = lpFreeBuff; 
    lpABOOUser->lpMalloc = lpMalloc; 
    lpABOOUser->lpABLogon = lpABPLogon; 
 
    /* 
     *  Create property storage object. 
     */ 
 
    sc = CreateIProp( 
        (LPIID) &IID_IMAPIPropData, 
        lpAllocBuff, 
        lpAllocMore, 
        lpFreeBuff, 
        lpMalloc, 
        &lpPropData); 
 
    if (FAILED(sc)) 
    { 
        hr = ResultFromScode(sc); 
        goto err; 
    } 
 
    /* 
     *  Set up the initial set of properties 
     */ 
 
    spv[0].ulPropTag = PR_DISPLAY_TYPE; 
    spv[0].Value.l = DT_MAILUSER; 
 
    spv[1].ulPropTag = PR_OBJECT_TYPE; 
    spv[1].Value.l = MAPI_MAILUSER; 
 
    /* 
     *  Note that we're using our entryID for our templateID. 
     *  This is a really simple way to implement templateIDs. 
     *  (See OOTID.C) 
     */ 
    spv[2].ulPropTag = PR_TEMPLATEID; 
    spv[2].Value.bin.cb = sizeof(OOUSR_ENTRYID); 
    spv[2].Value.bin.lpb = (LPBYTE) lpEntryID; 
 
    spv[3].ulPropTag = PR_ADDRTYPE; 
    spv[3].Value.lpszA = lpszEMT; 
 
    /* 
     *   Set the default properties 
     */ 
    hr = lpPropData->lpVtbl->SetProps( 
        lpPropData, 
        sizeof(spv) / sizeof(SPropValue), 
        spv, 
        NULL); 
 
    if (HR_FAILED(hr)) 
    { 
        goto err; 
    } 
 
    /* 
    *   We mark these properties READONLY so that they can't be changed by 
    *   the client. 
    */ 
    (void) lpPropData->lpVtbl->HrSetPropAccess(lpPropData, 
                                (LPSPropTagArray) &tagaABOOUSERAccess, 
                                rgulABOOUSERAccess); 
 
    (void) lpPropData->lpVtbl->HrSetObjAccess(lpPropData, IPROP_READWRITE); 
 
    lpABOOUser->lpPropData = (LPMAPIPROP) lpPropData; 
 
    InitializeCriticalSection(&lpABOOUser->cs); 
 
    /*  We must AddRef the lpABPLogon object since we will be using it 
     */ 
    lpABPLogon->lpVtbl->AddRef(lpABPLogon); 
 
    *lppMAPIPropEntry = (LPVOID) lpABOOUser; 
    *lpulObjType = MAPI_MAILUSER; 
 
out: 
 
    DebugTraceResult(HrNewSampOOUser, hr); 
    return hr; 
 
err: 
 
    if (lpPropData) 
        lpPropData->lpVtbl->Release(lpPropData); 
 
    lpFreeBuff( lpABOOUser ); 
 
    goto out; 
} 
 
 
/************************************************************************* 
 * 
 -  ABOOUSER_OpenProperty 
 - 
 * 
 *  This is how we get the display table associated with this one-off's 
 *  details screen. 
 */ 
STDMETHODIMP 
ABOOUSER_OpenProperty( 
    LPABOOUSER lpABOOUser, 
    ULONG ulPropTag, 
    LPCIID lpiid, 
    ULONG ulInterfaceOptions, 
    ULONG ulFlags, 
    LPUNKNOWN * lppUnk) 
{ 
 
    /* 
     *  Since the default is that we do not support opening this 
     *  object, we can initialize our hResult here. 
     */ 
    HRESULT hResult = ResultFromScode(MAPI_E_NO_SUPPORT); 
 
    ABOOUSER_ValidateObject(OpenProperty, lpABOOUser); 
 
    Validate_IMAPIProp_OpenProperty(lpABOOUser, ulPropTag, lpiid, 
                            ulInterfaceOptions, ulFlags, lppUnk); 
 
 
    if (ulInterfaceOptions & ~MAPI_UNICODE ) 
    { 
        /* 
         *  Only UNICODE flag should be set for any of the objects that might 
         *  be returned from this object. 
         */ 
        hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS); 
        goto ret; 
    } 
     
    if ( ulInterfaceOptions & MAPI_UNICODE ) 
    { 
        hResult = ResultFromScode( MAPI_E_BAD_CHARWIDTH ); 
        goto ret; 
    } 
     
 
     
    if (ulFlags & MAPI_CREATE) 
    { 
        /* 
         *  Don't support creating any sub-objects 
         */ 
        hResult = ResultFromScode(E_ACCESSDENIED); 
        goto ret; 
    } 
     
     
    /*  Check to see if I need a display table*/ 
 
    if (ulPropTag == PR_DETAILS_TABLE) 
    { 
        /* Looking for the display table */ 
        /* Check to see if they're expecting a table interface*/ 
 
        if (memcmp(lpiid, &IID_IMAPITable, sizeof(IID))) 
        { 
            /* 
             *  This provider will only export a table interface for 
             *  PR_DETAILS_TABLE 
             */ 
            hResult = ResultFromScode(E_NOINTERFACE); 
            goto ret; 
        } 
 
        /* Create a display table */ 
 
        hResult = BuildDisplayTable( 
            lpABOOUser->lpAllocBuff, 
            lpABOOUser->lpAllocMore, 
            lpABOOUser->lpFreeBuff, 
            lpABOOUser->lpMalloc, 
            lpABOOUser->hLibrary, 
            sizeof(rgdtpage) / sizeof(DTPAGE), 
            rgdtpage, 
            0, 
            (LPMAPITABLE *) lppUnk, 
            NULL); 
 
        if (HR_FAILED(hResult)) 
        { 
            goto ret; 
        } 
 
        /* 
         * We're succeeding. Ensure our hResult is set properly (i.e. mask warnings) 
         */ 
 
        hResult = hrSuccess; 
    } 
 
ret: 
    DebugTraceResult(ABOOUSER_OpenProperty, hResult); 
    return hResult; 
}