/* This is sample C code showing how we implemented IDSMAIL in a C environment. We used Borland C, but Visual C should be about the same. This code does not contain all the IDS functions, but will give someone with a good C background a place to start. Ron Phillips Monarch Bay Software */ // The three invokes void IDSInvokeMethod(DISPID dwDispID, WORD MethodType, VARTYPE vtReturnCode, VARIANT* excep, BYTE PramType, void* Pram) { HRESULT hr; DISPPARAMS dparams; UINT uArgErr; EXCEPINFO pxexcepinfo; VARIANTARG vtArg; VARIANT VarRet; _fmemset(&pxexcepinfo,0,sizeof(EXCEPINFO)); if(Pram!=NULL) { dparams.cNamedArgs = 0; dparams.rgdispidNamedArgs = NULL; VariantInit(&vtArg); dparams.rgvarg = &vtArg; dparams.cArgs = 1; switch (PramType) { case VTS_BSTR: { dparams.rgvarg[0].vt = VT_BSTR; dparams.rgvarg[0].u.bstrVal = SysAllocString(Pram); break; } case VTS_I2: case VTS_BOOL: { int *x=(int *)Pram; dparams.rgvarg[0].vt = VT_I2; dparams.rgvarg[0].u.iVal =(int) *x; break; } default: ErrorOut(YES,"Unknown invoke param"); return; } } else { dparams.rgvarg = NULL; // no arguments dparams.rgdispidNamedArgs = NULL; // no arguments dparams.cArgs = 0; dparams.cNamedArgs = 0; } VariantInit(&VarRet); VarRet.vt=VT_EMPTY; hr = g_lpDispatch->lpVtbl->Invoke( g_lpDispatch, // pseudo this_ pointer dwDispID, // dispid of method name &IID_NULL, // reserved must always be null LOCALE_USER_DEFAULT,// locale info for alternate language support DISPATCH_METHOD, // context flags for invocation &dparams, // parameter description block pointer &VarRet, // variant representing return code &pxexcepinfo, // exception info if DISP_E_EXCEPTION is returned &uArgErr // argument index if type mismatch or argument not found error occurs to a parameter ); if ( FAILED(hr) ) { IDSHandleError(hr,&pxexcepinfo); IDSError=1; return; } VariantClear(&vtArg); switch (vtReturnCode) { case VT_EMPTY: break; case VT_I2: *(short*)excep = VarRet.u.iVal; break; case VT_I4: *(long*)excep = VarRet.u.lVal; break; case VT_BSTR: { excep->u.bstrVal = SysAllocString(VarRet.u.bstrVal); excep->vt = VarRet.vt; SysFreeString(VarRet.u.bstrVal); } break; case VT_BOOL: *(BOOL*)excep = (VarRet.u.bool != 0); break; case VT_VARIANT: *(VARIANTARG*)excep = VarRet; break; default: ErrorOut(YES,"Unknown Get type"); break; } VariantClear(&VarRet); } void IDSInvokeSet(DISPID dwDispID, WORD MethodType, VARTYPE vtReturnCode, void* excep, BYTE PramType, void* Pram) { DISPID dispidNamed; HRESULT hr; DISPPARAMS dparams; UINT uArgErr; EXCEPINFO pxexcepinfo; VARIANTARG vtArg; _fmemset(&pxexcepinfo,0,sizeof(EXCEPINFO)); dispidNamed = DISPID_PROPERTYPUT; dparams.cNamedArgs = 1; dparams.rgdispidNamedArgs = &dispidNamed; VariantInit(&vtArg); dparams.rgvarg = &vtArg; dparams.cArgs = 1; switch (PramType) { case VTS_BSTR: { dparams.rgvarg[0].vt = VT_BSTR; dparams.rgvarg[0].u.bstrVal = SysAllocString(Pram); break; } case VTS_I2: case VTS_BOOL: { int *x=(int *)Pram; dparams.rgvarg[0].vt = VT_I2; dparams.rgvarg[0].u.iVal =(int) *x; break; } case VTS_I4: { long int *x=(long int *)Pram; dparams.rgvarg[0].vt = VT_I4; dparams.rgvarg[0].u.lVal =(long int) *x; break; } default: ErrorOut(YES,"Unknown invoke param (set)"); return; } hr = g_lpDispatch->lpVtbl->Invoke( g_lpDispatch, // pseudo this_ pointer dwDispID, // dispid of method name &IID_NULL, // reserved must always be null LOCALE_USER_DEFAULT,// locale info for alternate language support DISPATCH_PROPERTYPUT, // context flags for invocation &dparams, // parameter description block pointer NULL, // variant representing return code &pxexcepinfo, // exception info if DISP_E_EXCEPTION is returned &uArgErr // argument index if type mismatch or argument not found error occurs to a parameter ); if ( FAILED(hr) ) { IDSHandleError(hr,&pxexcepinfo); IDSError=1; return; } VariantClear(&vtArg); } void IDSInvokeGet(DISPID dwDispID, WORD MethodType, VARTYPE vtReturnCode, void* excep, BYTE PramType, void* Pram) { HRESULT hr; DISPPARAMS dparams; UINT uArgErr; EXCEPINFO pxexcepinfo; VARIANT VarRet; _fmemset(&pxexcepinfo,0,sizeof(EXCEPINFO)); dparams.rgvarg = NULL; // no arguments dparams.rgdispidNamedArgs = NULL; // no arguments dparams.cArgs = 0; dparams.cNamedArgs = 0; VariantInit(&VarRet); hr = g_lpDispatch->lpVtbl->Invoke( g_lpDispatch, // pseudo this_ pointer dwDispID, // dispid of method name &IID_NULL, // reserved must always be null 0,// locale info for alternate language support DISPATCH_PROPERTYGET, // context flags for invocation &dparams, // parameter description block pointer &VarRet, // variant representing return code &pxexcepinfo, // exception info if DISP_E_EXCEPTION is returned &uArgErr // argument index if type mismatch or argument not found error occurs to a parameter ); if ( FAILED(hr) ) { IDSHandleError(hr,&pxexcepinfo); IDSError=1; return; } switch (vtReturnCode) { case VT_I2: *(short*)excep = VarRet.u.iVal; break; case VT_I4: *(long*)excep = VarRet.u.lVal; break; case VT_BSTR: { int nLen = SysStringLen(VarRet.u.bstrVal); char* psz = farmalloc(nLen); _fmemcpy(psz, VarRet.u.bstrVal, nLen); SysFreeString(VarRet.u.bstrVal); } break; case VT_BOOL: *(BOOL*)excep = (VarRet.u.bool != 0); break; case VT_VARIANT: *(VARIANTARG*)excep = VarRet; break; default: ErrorOut(YES,"Unknown Get type"); break; } VariantClear(&VarRet); } /////////////////////////////////////////////////////////// // some sample functions (Not all, but enough to illustrate how it works) void IDSSetNativeSystem(void) { IDSFunctionNR=1; IDSInvokeMethod(0x60030060L, DISPATCH_METHOD, VT_EMPTY, NULL, NULL, NULL); } void IDSLoadMessageHeaders(void) { IDSFunctionNR=2; IDSInvokeMethod(0x600300a8L, DISPATCH_METHOD, VT_EMPTY, NULL, NULL, NULL); } void IDSSetErrorDisplay(int Value) { int newValue; BYTE parms = VTS_BOOL; newValue=Value; if(newValue==1) newValue=-1; IDSFunctionNR=4; IDSInvokeSet(0x68030058L, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, &newValue); } BOOL IDSGetUnreadOnly(void) { VARIANT result; IDSFunctionNR=11; IDSInvokeGet(0x680300bcL, DISPATCH_PROPERTYGET, VT_VARIANT, (void*)&result, NULL, NULL); if( result.u.iVal!=0) result.u.iVal = 1; return result.u.iVal; } BOOL IDSGetSuppressAttachments(void) { VARIANT result; IDSFunctionNR=12; IDSInvokeGet(0x680300d0L, DISPATCH_PROPERTYGET, VT_VARIANT, (void*)&result, NULL, NULL); if( result.u.iVal!=0) result.u.iVal = 1; return result.u.iVal; } void IDSSend(void) { IDSFunctionNR=16; IDSInvokeMethod(0x60030034L, DISPATCH_METHOD, VT_EMPTY, NULL, NULL, NULL); } void IDSAddRecipientBcc(char * theRecipient) { BYTE parms = VTS_BSTR; IDSFunctionNR=28; IDSInvokeMethod(0x6003002cL, DISPATCH_METHOD, VT_EMPTY, NULL, parms, theRecipient); } void IDSGetRecipientDelimiter(char *ret) { VARIANT result; IDSFunctionNR=110; IDSInvokeGet(0x68030148L, DISPATCH_PROPERTYGET, VT_VARIANT, (void*)&result, NULL,NULL); lstrcpy(ret,result.u.bstrVal); SysFreeString(result.u.bstrVal); } void IDSGetMessage(char *ret,int buffsize) { int nLen; VARIANT result; IDSFunctionNR=37; IDSInvokeGet(0x6803004cL, DISPATCH_PROPERTYGET, VT_VARIANT, (void*)&result, NULL, NULL); nLen = SysStringLen(result.u.bstrVal); nLen++; if(nLenpfnDeferredFillIn) (*pExInfo->pfnDeferredFillIn)(pExInfo); lstrcpy(szSource, "Unknown"); if (NULL!=pExInfo->bstrSource) { lstrcpy(szSource, pExInfo->bstrSource); } if (NULL!=pExInfo->bstrDescription) { pszFmt=(LPTSTR)malloc(CCHSTRINGMAX*sizeof(char)); pszMsg=(LPTSTR)malloc((CCHSTRINGMAX+lstrlen(szSource) +lstrlen(pExInfo->bstrDescription))*sizeof(char)); if (0==pExInfo->wCode) { //Formatting for SCODE errors lstrcpy(pszFmt, "F %d, Error %lX: %s"); wsprintf(pszMsg, pszFmt, IDSFunctionNR, (long)pExInfo->scode , (LPTSTR)pExInfo->bstrDescription); } else { //Formatting for wCode errors lstrcpy(pszFmt, "F=%d, Error %u: %s"); wsprintf(pszMsg, pszFmt, IDSFunctionNR, (UINT)pExInfo->wCode , (LPTSTR)pExInfo->bstrDescription); } free(pszFmt); } else { pszMsg=(LPTSTR)malloc(CCHSTRINGMAX*sizeof(char)); lstrcpy(pszMsg,"An error occurred in IDSMail."); } // uStyle=MB_OK | MB_ICONEXCLAMATION; // uStyle |=(NULL!=pExInfo->bstrHelpFile) ? MB_OKCANCEL : 0; ErrorOut(NO,pszMsg); if (NULL!=pszMsg) free(pszMsg); SysFreeString(pExInfo->bstrDescription); SysFreeString(pExInfo->bstrHelpFile); return; } // and an example putting it all together int GetMail (int MsgID,LPMAILMSG lpMsg,LONG lFlags) { IDSSetMessageIndex(MsgID-1); IDSLoadMessage(); IDSGetMessageItemString(IDSM_ITM_FROM,lpMsg->szFrom); IDSGetMessageItemString(IDSM_ITM_SUBJECT,lpMsg->szSubject); IDSGetMessageItemString(IDSM_ITM_DATE_SENT,lpMsg->szDateSent); IDSGetMessageItemString(IDSM_ITM_STATE,lpMsg->szState); IDSGetMessageItemString(IDSM_ITM_ATTACHMENT,lpMsg->szAttachmentPath); IDSGetMessageItemString(IDSM_ITM_ATTACHMENT_NAME,lpMsg->szAttachmentName); IDSGetMessageItemString(IDSM_ITM_CC,lpMsg->szCC); IDSGetMessageText(lpMsg->szNoteText,4000); return TRUE; }