0
votes

I´m trying to develop a custom address book provider for outlook. Using MFCMAPI to browse the store I found that the PR_PST_PATH property for the .pst file of the outlook default profile is reachable through IProviderAdmin-Interface.

So I tried the following piece of mapi-code:

// Get ProfileAdmin
LPPROFADMIN lpProfileAdmin = NULL;
hRes = MAPIAdminProfiles(0, &lpProfileAdmin);
if (FAILED(hRes) || lpProfileAdmin == NULL) {
    hRes = MAPI_E_UNCONFIGURED;
    return hRes;
}

// Get ProfileTable and filter default profile
LPMAPITABLE lpProfileTable = NULL;
hRes = lpProfileAdmin->GetProfileTable(0, &lpProfileTable);
if (FAILED(hRes) || lpProfileTable == NULL) {
    hRes = MAPI_E_UNCONFIGURED;
    return hRes;
}

SPropValue spvDefaultProfile;
spvDefaultProfile.ulPropTag = PR_DEFAULT_PROFILE;
spvDefaultProfile.Value.b = TRUE;

SRestriction srProfile;
srProfile.rt = RES_PROPERTY;
srProfile.res.resProperty.relop = RELOP_EQ;
srProfile.res.resProperty.ulPropTag = PR_DEFAULT_PROFILE;
srProfile.res.resProperty.lpProp = &spvDefaultProfile;

hRes = lpProfileTable->Restrict(&srProfile, TBL_BATCH);
hRes = lpProfileTable->FindRow(&srProfile, BOOKMARK_BEGINNING, 0);

LPSRowSet lpRowSet = NULL;
hRes = lpProfileTable->QueryRows(1, 0, &lpRowSet);
if (FAILED(hRes) || lpRowSet == NULL) {
    hRes = MAPI_E_UNCONFIGURED;
    return hRes;
}

bstr_t profileName((const char *)lpRowSet->aRow[0].lpProps[0].Value.lpszA);
lpzProfileName = (LPTSTR)profileName;

// Get ServiceAdmin
LPSERVICEADMIN lpServiceAdmin = NULL;
hRes = lpProfileAdmin->AdminServices(lpzProfileName, NULL, NULL, MAPI_UNICODE, &lpServiceAdmin);
if (FAILED(hRes) || lpServiceAdmin == NULL) {
    hRes = MAPI_E_UNCONFIGURED;
    return hRes;
}

// Get ServiceTable and filter default store
LPMAPITABLE lpServiceTable = NULL;
hRes = lpServiceAdmin->GetMsgServiceTable(0, &lpServiceTable);
if (FAILED(hRes) || lpServiceTable == NULL) {
    hRes = MAPI_E_UNCONFIGURED;
    return hRes;
}

SRestriction srService;
srService.rt = RES_BITMASK;
srService.res.resBitMask.ulPropTag = PR_RESOURCE_FLAGS;
srService.res.resBitMask.relBMR = BMR_EQZ;
srService.res.resBitMask.ulMask = SERVICE_DEFAULT_STORE;

hRes = lpServiceTable->Restrict(&srService, TBL_BATCH);
hRes = lpServiceTable->FindRow(&srService, BOOKMARK_BEGINNING, 0);

lpRowSet = NULL;
hRes = lpServiceTable->QueryRows(1, 0, &lpRowSet);
if (FAILED(hRes) || lpRowSet == NULL) {
    hRes = MAPI_E_UNCONFIGURED;
    return hRes;
}

// Get UID Property for default store
LPSPropValue pValServiceUid = PpropFindProp(lpRowSet->aRow[0].lpProps, lpRowSet->aRow[0].cValues, PR_SERVICE_UID);
if (pValServiceUid == NULL) {
    hRes = MAPI_E_UNCONFIGURED;
    return hRes;
}

// Get ProfileSection for UID
LPPROFSECT lpProfileSect = NULL;
hRes = lpServiceAdmin->OpenProfileSection((LPMAPIUID)pValServiceUid->Value.bin.lpb, NULL, MAPI_FORCE_ACCESS, &lpProfileSect);  
if (FAILED(hRes) || lpProfileSect == NULL) {
    hRes = MAPI_E_UNCONFIGURED;
    return hRes;
}

// Get UID of IProviderAdmin
LPSPropValue pValProviderUid = NULL;
hRes = HrGetOneProp(lpProfileSect, PR_STORE_PROVIDERS, &pValProviderUid);
if (FAILED(hRes) || pValProviderUid == NULL) {
    hRes = MAPI_E_UNCONFIGURED;
    return hRes;
}

LPPROVIDERADMIN lpProviderAdmin = NULL;
hRes = lpServiceAdmin->AdminProviders((LPMAPIUID)pValProviderUid->Value.bin.lpb, 0, &lpProviderAdmin);
if (FAILED(hRes) || lpProviderAdmin == NULL) {
    hRes = MAPI_E_UNCONFIGURED;
    return hRes;
}

LPMAPITABLE lpProviderTable = NULL;
hRes = lpProviderAdmin->GetProviderTable(0, &lpProviderTable);
if (FAILED(hRes) || lpProviderTable == NULL) {
    hRes = MAPI_E_UNCONFIGURED;
    return hRes;
}

But the call to

lpServiceAdmin->AdminProviders(...)

fails with a return value of E_INVALIDARGS.

So, what I´m doing wrong? And what is the correct way to get the PR_PST_PATH property?

Regards

Joachim

1

1 Answers

0
votes

Confirm the pValProviderUid matches what you see in MFCMAPI.