MAPI programming issue - outbox doesn't exist?

T

tsunamisama

Hi, I'm not sure where I need to post this question, but I guess this
Discussion Group is the closest match, so here goes:
(BTW: if anyone can suggest a better place to ask this question, it would be
greatly appreciated. Thanks)

I'm trying to write a very simple console app that I can call from within a
batch script that will send me a very simple email when [some event] happens.
I get as far as IMAPISession::OpenMsgStore. But after that, when I try to
call GetProps to retrieve the ENTRY ID of the outbox folder, it returns
MAPI_W_ERRORS_RETURNED, and my subsequent attempt to IMsgStore::OpenEntry on
the outbox folder fails with E_INVALIDARG. Before I get into the things I've
tried, please refer to the code below: (sorry for the length and inelegance -
I don't do much coding)


#include "stdafx.h"

//Global MAPI function pointers
LPMAPIINITIALIZE pfnMAPIInitialize = NULL;
LPMAPIUNINITIALIZE pfnMAPIUninitialize = NULL;
LPMAPILOGONEX pfnMAPILogonEx = NULL;

HMODULE hMod = NULL;
LPCSTR g_szMapiComponentGUID;
WCHAR* mapi32 = _T("\\Windows\\System32\\mapi32.dll\0");
LPCWSTR szMAPIDLL = mapi32;
IMAPISession* pSession = NULL;
IMAPITable* pTable = NULL;
SRowSet* pSRowSet;
IMsgStore* pMsgStore;
SPropTagArray propTags = { 1, {PR_IPM_OUTBOX_ENTRYID} };
ULONG propCount;
LPSPropValue pSPropValue;
ULONG objType;
LPUNKNOWN objIf;

void InitializeMapiFunctions()
{
//Load the DLL
hMod = LoadLibrary(szMAPIDLL);

//Initialize MAPI functions
pfnMAPIInitialize = (LPMAPIINITIALIZE) GetProcAddress(hMod,
"MAPIInitialize");
pfnMAPIUninitialize = (LPMAPIUNINITIALIZE) GetProcAddress(hMod,
"MAPIUninitialize");
pfnMAPILogonEx = (LPMAPILOGONEX) GetProcAddress(hMod, "MAPILogonEx");
}


int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = NULL;
InitializeMapiFunctions();

hr = (*pfnMAPIInitialize)(NULL);
if(hr == S_OK) printf("\n\nHey it worked!!!\n\n");

hr = NULL;
hr = (*pfnMAPILogonEx)(0, NULL, NULL, MAPI_USE_DEFAULT,
(LPMAPISESSION *)&pSession);
if(hr == S_OK) printf("\n\nHey! We're logged on!!!\n\n");
if(hr == MAPI_E_LOGON_FAILED)
printf("\n\nMAPI_E_LOGON_FAILED!!\n\n");
if(hr == MAPI_E_TIMEOUT) printf("\n\nHMAPI_E_TIMEOUT!!\n\n");
if(hr == MAPI_E_USER_CANCEL)
printf("\n\nMAPI_E_USER_CANCEL!!\n\n");

hr = NULL;
hr = pSession->GetMsgStoresTable(0, &pTable);
if(hr == S_OK) printf("\n\nGot the Message Store
table!!!!!\n\n");

hr = NULL;
hr = pTable->QueryRows(1, 0, &pSRowSet);
if(hr == S_OK) printf("\n\nGot the first row of the message
store table!!!\n\n");

hr = NULL;
hr = pSession->OpenMsgStore(0,

pSRowSet[0].aRow[0].lpProps[0].Value.bin.cb,

(ENTRYID*)pSRowSet[0].aRow[0].lpProps[0].Value.bin.lpb,

NULL,

MDB_WRITE,

&pMsgStore);
if(hr == S_OK) printf("Message store is
open!\n");

hr = NULL;

//The next function returns
MAPI_W_ERRORS_RETURNED when I pass in PR_IPM_OUTBOX_ENTRYID (via the propTags
struct defined at the top of this code). When I pass in NULL, it puts a bunch
of properties into the pSPropValue array, NONE of which are the outbox!

hr = pMsgStore->GetProps(&propTags/*NULL*/,
0, &propCount, &pSPropValue);

if(hr == S_OK) printf("\n\nGot the Entry ID
for the outbox folder!!!%d %d\n", propCount, pSPropValue->Value.bin.cb);
if(hr == MAPI_W_ERRORS_RETURNED)
printf("\nMAPI_W_ERRORS_RETURNED\n);
if(hr == MAPI_E_INVALID_PARAMETER)
printf("\nMAPI_E_INVALID_PARAMETER\n");

//As mentioned, pMsgStore->GetProps won't
give me the outbox property. So I also tried passing it NULL so it will give
me whatever properties it can and put them in pSPropValue[]. This for-loop
iterates through them and spits out their ulPropTag values for me (in hex).
for(int i = 0; i > (int) propCount; i++)
{
printf("%X
%d",pSPropValue.ulPropTag,i);

//This checks the ulPropTag
to see if it's the PR_VALID_FOLDER_MASK property. If so, it shows me that
mask.
if(((LONG)
pSPropValue.ulPropTag) == ((LONG) 903806979)) printf("
%X",pSPropValue.Value.l);

ENDL;
}

hr = NULL;

//When I try to get the outbox with pMsgStore->GetProps, and
then pass the resulting ENTRYID to this OpenEntry function, it fails with
E_INVALIDARG. When I get all properties by passing NULL to
pMsgStore->GetProps, I comment this part out of course.

hr = pMsgStore->OpenEntry((ULONG)pSPropValue[0]Value.bin.cb,

(LPENTRYID)pSPropValue[0]Value.bin.lpb,

NULL,

0,

&objType,

(LPUNKNOWN*)&objIf);
if(hr == S_OK) printf("\n\nOutbox is open for
business!!!\n\n");
if(hr == MAPI_E_NO_ACCESS) printf("\nMAPI_E_NO_ACCESS\n");

//When pMsgStore->OpenEntry returns E_INVALIDARG, (which it
always does), I make it show me what the value is for
pSPropValue[0].Value.bin.cb, and it's always some crazy garbage value. Which
I suppose explains the E_INVALIDARG error. :)

if(hr == E_INVALIDARG) printf("\nE_INVALIDARG
%d\n",pSPropValue[0].Value.bin.cb);

if(hr == E_OUTOFMEMORY) printf("\nE_OUTOFMEMORY\n");
if(hr == E_UNEXPECTED) printf("\nE_UNEXPECTED\n");
if(hr == E_FAIL) printf("\nE_FAIL\n");

(*pfnMAPIUninitialize)();

FreeLibrary(hMod);
return 0;
}


So... When I try to get the outbox prop with

hr = pMsgStore->GetProps(&propTags, 0, &propCount, &pSPropValue);

it completes with MAPI_W_ERRORS_RETURNED. As far as I can tell, the MSDN
tells me to treat this as a success. Fine. So I just go with it, and my
subsequent call to

hr = pMsgStore->OpenEntry((ULONG)pSPropValue[0]Value.bin.cb,

(LPENTRYID)pSPropValue[0]Value.bin.lpb,

NULL,

0,

&objType,

(LPUNKNOWN*)&objIf);

fails with E_INVALIDARG. So I added this

if(hr == E_INVALIDARG) printf("\nE_INVALIDARG
%d\n",pSPropValue[0].Value.bin.cb);

....to show just what is being passed in for pSPropValue[0].Value.bin.cb,
(which is supposed to be the count of bytes of pSPropValue[0]Value.bin.lpb,
the property's ENTRY_ID), and it turns out that it's some wacky number
"-2147221233". That explains the E_INVALIDARG error I suppose.

So the next thing I tried was to call pMsgStore->GetProps, this time passing
in NULL instead of propTags to see what all properties it actually puts into
pSPropValue[]

hr = pMsgStore->GetProps(NULL, 0, &propCount, &pSPropValue);

and then I iterate through everything that was put into pSPropValue[] to see
what they are

for(int i = 0; i > (int) propCount; i++)
{
printf("%X %d",pSPropValue.ulPropTag,i);
if(((LONG) pSPropValue.ulPropTag) == ((LONG) 903806979))
printf(" %X",pSPropValue.Value.l);
ENDL;
}

also in the above for-loop is a line that will check for the
PR_VALID_FOLDER_MASK property, and print that mask in hex. Here's what it
spits out:

E340102 0
E380003 1
FF90102 2
3001001E 3
34160102 4
7C040102 5
7C06101E 6
7C070102 7
7C0C0003 8
7C0D0014 9
7C11000B 10
7C130003 11
FF70003 12
FFA0102 13
FFB0102 14
FFE0003 15
FFF0102 16
300B0102 17
340D0003 18
340E0003 19
340F0003 20
34140102 21
35DF0003 22 FF
35E00102 23
66200102 24
66210102 25
66240102 26
66300102 27
66310102 28
6632000B 29
65E40003 30

For the PR_IPM_OUTBOX_ENTRYID property, the high order 16 bits is supposed
to be 35E2. As you can see, it's not in the above list. :( The only 'special'
properties in the list that I can recognize are:

35DF0003 (PR_VALID_FOLDER_MASK)
35E00102 (PR_IPM_SUBTREE_ENTRYID)

No outbox. Not to mention the fact that there's no inbox, drafts, etc... And
here's the kicker: You'll notice that the PR_VALID_FOLDER_MASK was found and
it's mask was displayed as FF

35DF0003 22 FF

The FF mask means that all folders exist and are valid! As defined in
mapidefs.h:

excerpt from mapidefs.h:
/* Flag bits for PR_VALID_FOLDER_MASK */

#define FOLDER_IPM_SUBTREE_VALID ((ULONG)
0x00000001)
#define FOLDER_IPM_INBOX_VALID
((ULONG) 0x00000002)
#define FOLDER_IPM_OUTBOX_VALID
((ULONG) 0x00000004)
#define FOLDER_IPM_WASTEBASKET_VALID ((ULONG) 0x00000008)
#define FOLDER_IPM_SENTMAIL_VALID
((ULONG) 0x00000010)
#define FOLDER_VIEWS_VALID
((ULONG) 0x00000020)
#define FOLDER_COMMON_VIEWS_VALID
((ULONG) 0x00000040)
#define FOLDER_FINDER_VALID
((ULONG) 0x00000080)

but when I try to IMsgStore::GetProps for the outbox, it fails. And when I
look at the entire list of properties, the outbox isn't there! I've tried
this with Outlook (2007) open and closed. From within Outlook, I've tried
setting the permissions on my Mailbox as well as Outbox to "Owner" for both
Default and Anonymous. I only have one profile on this system, the default
profile; (it uses Exchange if that means anything).

Sorry for the looooong post. I'm at the end of my rope here!

Thanks
-Daniel
 
S

SvenC

Hi tsunamisama.
Hi, I'm not sure where I need to post this question, but I guess this
Discussion Group is the closest match, so here goes:
(BTW: if anyone can suggest a better place to ask this question, it would
be
greatly appreciated. Thanks)

This might be better: microsoft.public.platformsdk.mapi
I'm trying to write a very simple console app that I can call from within
a
batch script that will send me a very simple email when [some event]
happens.
I get as far as IMAPISession::OpenMsgStore. But after that, when I try to
call GetProps to retrieve the ENTRY ID of the outbox folder, it returns
MAPI_W_ERRORS_RETURNED, and my subsequent attempt to IMsgStore::OpenEntry
on
the outbox folder fails with E_INVALIDARG. Before I get into the things
I've
tried, please refer to the code below: (sorry for the length and
inelegance -
I don't do much coding)

Please use MFCMAPI to check the content of your message store and see if
it contains the outbox entryid.

http://mfcmapi.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=21390

You find the executable and source code of mfcmapi, so you find lots of
sample code as well.
 
D

Dmitry Streblechenko

How many stores d oyou have in the profile? Why do you assume the very first
store will be the default one?
PF stores for example do not have the Outbox folder.

--
Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
-
tsunamisama said:
Hi, I'm not sure where I need to post this question, but I guess this
Discussion Group is the closest match, so here goes:
(BTW: if anyone can suggest a better place to ask this question, it would
be
greatly appreciated. Thanks)

I'm trying to write a very simple console app that I can call from within
a
batch script that will send me a very simple email when [some event]
happens.
I get as far as IMAPISession::OpenMsgStore. But after that, when I try to
call GetProps to retrieve the ENTRY ID of the outbox folder, it returns
MAPI_W_ERRORS_RETURNED, and my subsequent attempt to IMsgStore::OpenEntry
on
the outbox folder fails with E_INVALIDARG. Before I get into the things
I've
tried, please refer to the code below: (sorry for the length and
inelegance -
I don't do much coding)


#include "stdafx.h"

//Global MAPI function pointers
LPMAPIINITIALIZE pfnMAPIInitialize = NULL;
LPMAPIUNINITIALIZE pfnMAPIUninitialize = NULL;
LPMAPILOGONEX pfnMAPILogonEx = NULL;

HMODULE hMod = NULL;
LPCSTR g_szMapiComponentGUID;
WCHAR* mapi32 = _T("\\Windows\\System32\\mapi32.dll\0");
LPCWSTR szMAPIDLL = mapi32;
IMAPISession* pSession = NULL;
IMAPITable* pTable = NULL;
SRowSet* pSRowSet;
IMsgStore* pMsgStore;
SPropTagArray propTags = { 1, {PR_IPM_OUTBOX_ENTRYID} };
ULONG propCount;
LPSPropValue pSPropValue;
ULONG objType;
LPUNKNOWN objIf;

void InitializeMapiFunctions()
{
//Load the DLL
hMod = LoadLibrary(szMAPIDLL);

//Initialize MAPI functions
pfnMAPIInitialize = (LPMAPIINITIALIZE) GetProcAddress(hMod,
"MAPIInitialize");
pfnMAPIUninitialize = (LPMAPIUNINITIALIZE) GetProcAddress(hMod,
"MAPIUninitialize");
pfnMAPILogonEx = (LPMAPILOGONEX) GetProcAddress(hMod, "MAPILogonEx");
}


int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = NULL;
InitializeMapiFunctions();

hr = (*pfnMAPIInitialize)(NULL);
if(hr == S_OK) printf("\n\nHey it worked!!!\n\n");

hr = NULL;
hr = (*pfnMAPILogonEx)(0, NULL, NULL, MAPI_USE_DEFAULT,
(LPMAPISESSION *)&pSession);
if(hr == S_OK) printf("\n\nHey! We're logged on!!!\n\n");
if(hr == MAPI_E_LOGON_FAILED)
printf("\n\nMAPI_E_LOGON_FAILED!!\n\n");
if(hr == MAPI_E_TIMEOUT)
printf("\n\nHMAPI_E_TIMEOUT!!\n\n");
if(hr == MAPI_E_USER_CANCEL)
printf("\n\nMAPI_E_USER_CANCEL!!\n\n");

hr = NULL;
hr = pSession->GetMsgStoresTable(0, &pTable);
if(hr == S_OK) printf("\n\nGot the Message Store
table!!!!!\n\n");

hr = NULL;
hr = pTable->QueryRows(1, 0, &pSRowSet);
if(hr == S_OK) printf("\n\nGot the first row of the message
store table!!!\n\n");

hr = NULL;
hr = pSession->OpenMsgStore(0,

pSRowSet[0].aRow[0].lpProps[0].Value.bin.cb,

(ENTRYID*)pSRowSet[0].aRow[0].lpProps[0].Value.bin.lpb,

NULL,

MDB_WRITE,

&pMsgStore);
if(hr == S_OK) printf("Message store is
open!\n");

hr = NULL;

//The next function returns
MAPI_W_ERRORS_RETURNED when I pass in PR_IPM_OUTBOX_ENTRYID (via the
propTags
struct defined at the top of this code). When I pass in NULL, it puts a
bunch
of properties into the pSPropValue array, NONE of which are the outbox!

hr = pMsgStore->GetProps(&propTags/*NULL*/,
0, &propCount, &pSPropValue);

if(hr == S_OK) printf("\n\nGot the Entry ID
for the outbox folder!!!%d %d\n", propCount, pSPropValue->Value.bin.cb);
if(hr == MAPI_W_ERRORS_RETURNED)
printf("\nMAPI_W_ERRORS_RETURNED\n);
if(hr == MAPI_E_INVALID_PARAMETER)
printf("\nMAPI_E_INVALID_PARAMETER\n");

//As mentioned, pMsgStore->GetProps won't
give me the outbox property. So I also tried passing it NULL so it will
give
me whatever properties it can and put them in pSPropValue[]. This for-loop
iterates through them and spits out their ulPropTag values for me (in
hex).
for(int i = 0; i > (int) propCount; i++)
{
printf("%X
%d",pSPropValue.ulPropTag,i);

//This checks the ulPropTag
to see if it's the PR_VALID_FOLDER_MASK property. If so, it shows me that
mask.
if(((LONG)
pSPropValue.ulPropTag) == ((LONG) 903806979)) printf("
%X",pSPropValue.Value.l);

ENDL;
}

hr = NULL;

//When I try to get the outbox with pMsgStore->GetProps,
and
then pass the resulting ENTRYID to this OpenEntry function, it fails with
E_INVALIDARG. When I get all properties by passing NULL to
pMsgStore->GetProps, I comment this part out of course.

hr =
pMsgStore->OpenEntry((ULONG)pSPropValue[0]Value.bin.cb,

(LPENTRYID)pSPropValue[0]Value.bin.lpb,

NULL,

0,

&objType,

(LPUNKNOWN*)&objIf);
if(hr == S_OK) printf("\n\nOutbox is open for
business!!!\n\n");
if(hr == MAPI_E_NO_ACCESS) printf("\nMAPI_E_NO_ACCESS\n");

//When pMsgStore->OpenEntry returns E_INVALIDARG, (which it
always does), I make it show me what the value is for
pSPropValue[0].Value.bin.cb, and it's always some crazy garbage value.
Which
I suppose explains the E_INVALIDARG error. :)

if(hr == E_INVALIDARG) printf("\nE_INVALIDARG
%d\n",pSPropValue[0].Value.bin.cb);

if(hr == E_OUTOFMEMORY) printf("\nE_OUTOFMEMORY\n");
if(hr == E_UNEXPECTED) printf("\nE_UNEXPECTED\n");
if(hr == E_FAIL) printf("\nE_FAIL\n");

(*pfnMAPIUninitialize)();

FreeLibrary(hMod);
return 0;
}


So... When I try to get the outbox prop with

hr = pMsgStore->GetProps(&propTags, 0, &propCount, &pSPropValue);

it completes with MAPI_W_ERRORS_RETURNED. As far as I can tell, the MSDN
tells me to treat this as a success. Fine. So I just go with it, and my
subsequent call to

hr = pMsgStore->OpenEntry((ULONG)pSPropValue[0]Value.bin.cb,

(LPENTRYID)pSPropValue[0]Value.bin.lpb,

NULL,

0,

&objType,

(LPUNKNOWN*)&objIf);

fails with E_INVALIDARG. So I added this

if(hr == E_INVALIDARG) printf("\nE_INVALIDARG
%d\n",pSPropValue[0].Value.bin.cb);

...to show just what is being passed in for pSPropValue[0].Value.bin.cb,
(which is supposed to be the count of bytes of
pSPropValue[0]Value.bin.lpb,
the property's ENTRY_ID), and it turns out that it's some wacky number
"-2147221233". That explains the E_INVALIDARG error I suppose.

So the next thing I tried was to call pMsgStore->GetProps, this time
passing
in NULL instead of propTags to see what all properties it actually puts
into
pSPropValue[]

hr = pMsgStore->GetProps(NULL, 0, &propCount, &pSPropValue);

and then I iterate through everything that was put into pSPropValue[] to
see
what they are

for(int i = 0; i > (int) propCount; i++)
{
printf("%X %d",pSPropValue.ulPropTag,i);
if(((LONG) pSPropValue.ulPropTag) == ((LONG) 903806979))
printf(" %X",pSPropValue.Value.l);
ENDL;
}

also in the above for-loop is a line that will check for the
PR_VALID_FOLDER_MASK property, and print that mask in hex. Here's what it
spits out:

E340102 0
E380003 1
FF90102 2
3001001E 3
34160102 4
7C040102 5
7C06101E 6
7C070102 7
7C0C0003 8
7C0D0014 9
7C11000B 10
7C130003 11
FF70003 12
FFA0102 13
FFB0102 14
FFE0003 15
FFF0102 16
300B0102 17
340D0003 18
340E0003 19
340F0003 20
34140102 21
35DF0003 22 FF
35E00102 23
66200102 24
66210102 25
66240102 26
66300102 27
66310102 28
6632000B 29
65E40003 30

For the PR_IPM_OUTBOX_ENTRYID property, the high order 16 bits is supposed
to be 35E2. As you can see, it's not in the above list. :( The only
'special'
properties in the list that I can recognize are:

35DF0003 (PR_VALID_FOLDER_MASK)
35E00102 (PR_IPM_SUBTREE_ENTRYID)

No outbox. Not to mention the fact that there's no inbox, drafts, etc...
And
here's the kicker: You'll notice that the PR_VALID_FOLDER_MASK was found
and
it's mask was displayed as FF

35DF0003 22 FF

The FF mask means that all folders exist and are valid! As defined in
mapidefs.h:

excerpt from mapidefs.h:
/* Flag bits for PR_VALID_FOLDER_MASK */

#define FOLDER_IPM_SUBTREE_VALID ((ULONG)
0x00000001)
#define FOLDER_IPM_INBOX_VALID
((ULONG) 0x00000002)
#define FOLDER_IPM_OUTBOX_VALID
((ULONG) 0x00000004)
#define FOLDER_IPM_WASTEBASKET_VALID ((ULONG)
0x00000008)
#define FOLDER_IPM_SENTMAIL_VALID
((ULONG) 0x00000010)
#define FOLDER_VIEWS_VALID
((ULONG) 0x00000020)
#define FOLDER_COMMON_VIEWS_VALID
((ULONG) 0x00000040)
#define FOLDER_FINDER_VALID
((ULONG) 0x00000080)

but when I try to IMsgStore::GetProps for the outbox, it fails. And when I
look at the entire list of properties, the outbox isn't there! I've tried
this with Outlook (2007) open and closed. From within Outlook, I've tried
setting the permissions on my Mailbox as well as Outbox to "Owner" for
both
Default and Anonymous. I only have one profile on this system, the default
profile; (it uses Exchange if that means anything).

Sorry for the looooong post. I'm at the end of my rope here!

Thanks
-Daniel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top