Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

425 lines
12 KiB

  1. //
  2. // SMAPI16.CPP - Simple MAPI implementation, 16bit Version
  3. //
  4. #include "pch.hxx"
  5. #include <mapi.h>
  6. #include <note.h>
  7. #include <mimeutil.h>
  8. #include <resource.h>
  9. #include <ipab.h>
  10. #include <error.h>
  11. ASSERTDATA
  12. #define WriteVar2File( hf, v ) _lwrite( (hf), &(v), sizeof(v) );
  13. #define ReadVarFromFile( hf, v ) _lread( (hf), &(v), sizeof(v) );
  14. static const char s_cszMailMsgCmd[] = "msimn.exe /mailmsg:%s";
  15. inline void WriteStr2File( HFILE hFile, LPCSTR cszText )
  16. {
  17. UINT uText = ( cszText == NULL ) ? 0 : lstrlen( cszText ) + 1;
  18. _lwrite( hFile, &uText, sizeof( uText ) );
  19. if ( uText > 0 )
  20. _lwrite( hFile, cszText, uText );
  21. }
  22. inline void WriteMRD2File( HFILE hFile, lpMapiRecipDesc lpMRD )
  23. {
  24. WriteVar2File( hFile, lpMRD->ulReserved );
  25. WriteVar2File( hFile, lpMRD->ulRecipClass );
  26. WriteStr2File( hFile, lpMRD->lpszName );
  27. WriteStr2File( hFile, lpMRD->lpszAddress );
  28. WriteVar2File( hFile, lpMRD->ulEIDSize );
  29. _lwrite( hFile, lpMRD->lpEntryID, lpMRD->ulEIDSize );
  30. }
  31. inline LPSTR ReadStrFromFile( HFILE hFile )
  32. {
  33. UINT uText;
  34. LPSTR szText;
  35. ReadVarFromFile( hFile, uText );
  36. if ( uText > 0 )
  37. {
  38. szText = (LPSTR)malloc( uText );
  39. _lread( hFile, szText, uText );
  40. }
  41. else
  42. szText = NULL;
  43. return( szText );
  44. }
  45. inline lpMapiRecipDesc ReadMRDFromFile( HFILE hFile )
  46. {
  47. lpMapiRecipDesc lpMRD = new MapiRecipDesc;
  48. ReadVarFromFile( hFile, lpMRD->ulReserved );
  49. ReadVarFromFile( hFile, lpMRD->ulRecipClass );
  50. lpMRD->lpszName = ReadStrFromFile( hFile );
  51. lpMRD->lpszAddress = ReadStrFromFile( hFile );
  52. ReadVarFromFile( hFile, lpMRD->ulEIDSize );
  53. if ( lpMRD->ulEIDSize > 0 )
  54. {
  55. lpMRD->lpEntryID = malloc( lpMRD->ulEIDSize );
  56. _lread( hFile, lpMRD->lpEntryID, lpMRD->ulEIDSize );
  57. }
  58. else
  59. lpMRD->lpEntryID = NULL;
  60. return( lpMRD );
  61. }
  62. inline lpMapiFileDesc ReadMFDFromFile( HFILE hFile )
  63. {
  64. lpMapiFileDesc lpMFD = new MapiFileDesc;
  65. ReadVarFromFile( hFile, lpMFD->ulReserved );
  66. ReadVarFromFile( hFile, lpMFD->flFlags );
  67. ReadVarFromFile( hFile, lpMFD->nPosition );
  68. lpMFD->lpszPathName = ReadStrFromFile( hFile );
  69. lpMFD->lpszFileName = ReadStrFromFile( hFile );
  70. lpMFD->lpFileType = NULL;
  71. return( lpMFD );
  72. }
  73. #define FreeMemSafe( lp ) \
  74. if ( (lp) != NULL ) \
  75. { \
  76. free( lp ); \
  77. lp = NULL; \
  78. }
  79. inline void FreeMRDSafe( lpMapiRecipDesc &lpMRD )
  80. {
  81. if ( lpMRD != NULL )
  82. {
  83. FreeMemSafe( lpMRD->lpszName );
  84. FreeMemSafe( lpMRD->lpszAddress );
  85. FreeMemSafe( lpMRD->lpEntryID );
  86. free( lpMRD );
  87. lpMRD = NULL;
  88. }
  89. }
  90. inline void FreeMFDSafe( lpMapiFileDesc &lpMFD )
  91. {
  92. if ( lpMFD != NULL )
  93. {
  94. FreeMemSafe( lpMFD->lpszPathName );
  95. FreeMemSafe( lpMFD->lpszFileName );
  96. free( lpMFD );
  97. lpMFD = NULL;
  98. }
  99. }
  100. ///////////////////////////////////////////////////////////////////////
  101. //
  102. // MAPISendMail
  103. //
  104. ///////////////////////////////////////////////////////////////////////
  105. EXTERN_C ULONG STDAPICALLTYPE
  106. MAPISENDMAIL(
  107. LHANDLE lhSession, // ignored
  108. ULONG ulUIParam,
  109. lpMapiMessage lpMessage,
  110. FLAGS flFlags,
  111. ULONG ulReserved
  112. )
  113. {
  114. // validate parameters
  115. if ( NULL == lpMessage || IsBadReadPtr( lpMessage, sizeof( MapiMessage ) ) )
  116. return MAPI_E_INVALID_MESSAGE;
  117. // $BUGBUG - We do not support sendmail without UI yet. This is a big
  118. // hole that we need to fix.
  119. if (!(flFlags & MAPI_DIALOG))
  120. return MAPI_E_NOT_SUPPORTED;
  121. // Create Temporary File Storage
  122. //
  123. char szTmpDir[_MAX_PATH], szTmpFile[_MAX_PATH];
  124. OFSTRUCT of;
  125. HFILE hTmp;
  126. if ( GetTempPath( _MAX_PATH, szTmpDir ) == 0 )
  127. return( MAPI_E_FAILURE );
  128. if ( GetTempFileName( szTmpDir, "msm", 0, szTmpFile ) == 0 )
  129. return( MAPI_E_FAILURE );
  130. hTmp = OpenFile( szTmpFile, &of, OF_CREATE | OF_WRITE );
  131. if ( hTmp == HFILE_ERROR )
  132. return( MAPI_E_FAILURE );
  133. // lhSession is intentionally ignored because it is impossible to support it
  134. WriteVar2File( hTmp, lhSession );
  135. WriteVar2File( hTmp, ulUIParam );
  136. WriteVar2File( hTmp, flFlags );
  137. WriteVar2File( hTmp, ulReserved );
  138. // Write lpMapiMessage into Temporary File
  139. //
  140. int i;
  141. WriteVar2File( hTmp, lpMessage->ulReserved );
  142. WriteStr2File( hTmp, lpMessage->lpszSubject );
  143. WriteStr2File( hTmp, lpMessage->lpszNoteText );
  144. WriteStr2File( hTmp, lpMessage->lpszMessageType );
  145. WriteStr2File( hTmp, lpMessage->lpszDateReceived );
  146. WriteStr2File( hTmp, lpMessage->lpszConversationID );
  147. WriteVar2File( hTmp, lpMessage->flFlags );
  148. WriteVar2File( hTmp, lpMessage->lpOriginator );
  149. if ( lpMessage->lpOriginator != NULL )
  150. WriteMRD2File( hTmp, lpMessage->lpOriginator );
  151. WriteVar2File( hTmp, lpMessage->nRecipCount );
  152. for ( i = 0; i < lpMessage->nRecipCount; i++ )
  153. WriteMRD2File( hTmp, lpMessage->lpRecips+i );
  154. WriteVar2File( hTmp, lpMessage->nFileCount );
  155. for ( i = 0; i < lpMessage->nFileCount; i++ )
  156. {
  157. lpMapiFileDesc lpMFD = lpMessage->lpFiles+i;
  158. WriteVar2File( hTmp, lpMFD->ulReserved );
  159. WriteVar2File( hTmp, lpMFD->flFlags );
  160. WriteVar2File( hTmp, lpMFD->nPosition );
  161. WriteStr2File( hTmp, lpMFD->lpszPathName );
  162. WriteStr2File( hTmp, lpMFD->lpszFileName );
  163. Assert( lpMFD->lpFileType == NULL );
  164. }
  165. #ifdef DEBUG
  166. WriteStr2File( hTmp, szTmpFile );
  167. #endif
  168. if ( hTmp != NULL && hTmp != HFILE_ERROR )
  169. _lclose( hTmp );
  170. // Execute MSIMN.EXE
  171. //
  172. char szFmt[256], szCmd[256];
  173. LPSTR szLastDirSep = NULL;
  174. if ( GetModuleFileName( g_hInst, szFmt, sizeof( szFmt ) ) == 0 )
  175. return( MAPI_E_FAILURE );
  176. for ( LPSTR szPtr = szFmt; *szPtr != '\0'; szPtr = AnsiNext( szPtr ) )
  177. if ( *szPtr == '\\' )
  178. szLastDirSep = szPtr;
  179. if ( szLastDirSep == NULL )
  180. return( MAPI_E_FAILURE );
  181. StrCpyN( szLastDirSep+1, s_cszMailMsgCmd, ARRAYSIZE(szFmt)-(szLastDirSep-szFmt)-1);
  182. wnsprintf( szCmd, ARRAYSIZE(szCmd), szFmt, szTmpFile );
  183. return( ( WinExec( szCmd, SW_SHOW ) < 32 ) ? MAPI_E_FAILURE : SUCCESS_SUCCESS );
  184. }
  185. HRESULT HandleMailMsg( LPSTR szCmd )
  186. {
  187. OFSTRUCT of;
  188. HFILE hTmp;
  189. ULONG ulRet = MAPI_E_FAILURE;
  190. NCINFO nci = { 0 };
  191. LPMIMEMESSAGE pMsg = NULL;
  192. LPSTREAM pStream = NULL;
  193. LPMIMEADDRESSTABLE pAddrTable = NULL;
  194. HRESULT hr;
  195. LPSTR szText = NULL;
  196. lpMapiRecipDesc lpMRD = NULL;
  197. lpMapiFileDesc lpMFD = NULL;
  198. ULONG ulTmp;
  199. BOOL fBody = FALSE;
  200. // Open Tmp File
  201. //
  202. LPSTR szSpace = strchr( szCmd, ' ' );
  203. if ( szSpace != NULL )
  204. *szSpace = '\0';
  205. hTmp = OpenFile( szCmd, &of, OF_READ );
  206. if ( hTmp == HFILE_ERROR )
  207. goto error;
  208. LHANDLE lhSession;
  209. ULONG ulUIParam;
  210. FLAGS flFlags;
  211. ULONG ulReserved;
  212. ReadVarFromFile( hTmp, lhSession );
  213. ReadVarFromFile( hTmp, ulUIParam );
  214. ReadVarFromFile( hTmp, flFlags );
  215. ReadVarFromFile( hTmp, ulReserved );
  216. hr = HrCreateMessage( &pMsg );
  217. if ( FAILED( hr ) )
  218. goto error;
  219. nci.ntNote = ntSendNote;
  220. nci.dwFlags = NCF_SENDIMMEDIATE | NCF_MODAL;
  221. nci.pMsg = pMsg;
  222. nci.hwndOwner = (HWND)ulUIParam;
  223. ReadVarFromFile( hTmp, ulTmp );
  224. // set the subject on the message
  225. szText = ReadStrFromFile( hTmp );
  226. if ( szText != NULL )
  227. {
  228. hr = MimeOleSetBodyPropA( pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT),
  229. NOFLAGS, szText );
  230. if ( FAILED( hr ) )
  231. goto error;
  232. FreeMemSafe( szText );
  233. }
  234. // set the body on the message
  235. szText = ReadStrFromFile( hTmp );
  236. if ( szText != NULL )
  237. {
  238. if ( szText[0] != '\0' )
  239. {
  240. fBody = TRUE;
  241. hr = MimeOleCreateVirtualStream( &pStream );
  242. if ( FAILED( hr ) )
  243. goto error;
  244. hr = pStream->Write( szText, lstrlen( szText ), NULL );
  245. if ( FAILED( hr ) )
  246. goto error;
  247. hr = pMsg->SetTextBody( TXT_PLAIN, IET_DECODED, NULL, pStream, NULL );
  248. if ( FAILED( hr ) )
  249. goto error;
  250. }
  251. FreeMemSafe( szText );
  252. }
  253. // ignore lpMessage->lpszMessageType
  254. szText = ReadStrFromFile( hTmp );
  255. FreeMemSafe( szText );
  256. // ignore lpMessage->lpszDateReceived
  257. szText = ReadStrFromFile( hTmp );
  258. FreeMemSafe( szText );
  259. // ignore lpMessage->lpszConversationID
  260. szText = ReadStrFromFile( hTmp );
  261. FreeMemSafe( szText );
  262. // ignore lpMessage->flFlags
  263. ReadVarFromFile( hTmp, ulTmp );
  264. // ignore lpMessage->lpOriginator
  265. lpMRD = ReadMRDFromFile( hTmp );
  266. FreeMRDSafe( lpMRD );
  267. // set the recipients on the message
  268. ReadVarFromFile( hTmp, ulTmp );
  269. if ( ulTmp > 0 )
  270. {
  271. hr = pMsg->GetAddressTable( &pAddrTable );
  272. if ( FAILED( hr ) )
  273. goto error;
  274. for ( ULONG i = 0; i < ulTmp; i++ )
  275. {
  276. lpMRD = ReadMRDFromFile( hTmp );
  277. hr = pAddrTable->Append( MapiRecipToMimeOle( lpMRD->ulRecipClass ),
  278. IET_DECODED,
  279. lpMRD->lpszName, lpMRD->lpszAddress, NULL );
  280. if ( FAILED( hr ) )
  281. goto error;
  282. FreeMRDSafe( lpMRD );
  283. }
  284. }
  285. // set the attachments on the message
  286. ReadVarFromFile( hTmp, ulTmp );
  287. if ( ulTmp > 0 )
  288. {
  289. lpMFD = ReadMFDFromFile( hTmp );
  290. // special case: no body & one .HTM file - inline the HTML
  291. if ( fBody && ulTmp == 1 &&
  292. ( ( lpMFD->flFlags & ( MAPI_OLE | MAPI_OLE_STATIC ) ) == 0 ) &&
  293. FIsHTMLFile( lpMFD->lpszPathName ) )
  294. {
  295. Assert( pStream == NULL );
  296. hr = CreateStreamOnHFile( lpMFD->lpszPathName,
  297. GENERIC_READ,
  298. FILE_SHARE_READ,
  299. NULL,
  300. OPEN_EXISTING,
  301. FILE_ATTRIBUTE_NORMAL,
  302. NULL,
  303. &pStream );
  304. if ( FAILED( hr ) )
  305. goto error;
  306. hr = pMsg->SetTextBody( TXT_HTML, IET_DECODED, NULL, pStream, NULL );
  307. if ( FAILED( hr ) )
  308. goto error;
  309. nci.ntNote = ntWebPage;
  310. }
  311. else
  312. {
  313. for ( ULONG i = 0; i < ulTmp; i++ )
  314. {
  315. if ( i > 0 )
  316. {
  317. FreeMFDSafe( lpMFD );
  318. lpMFD = ReadMFDFromFile( hTmp );
  319. }
  320. // $BUGBUG - should we error this out, or send anyway?
  321. if ( lpMFD->flFlags & MAPI_OLE )
  322. continue;
  323. if ( lpMFD->lpszPathName != NULL && lpMFD->lpszPathName[0] != '\0' )
  324. {
  325. hr = pMsg->AttachFile( lpMFD->lpszPathName, NULL, NULL );
  326. if ( FAILED( hr ) )
  327. goto error;
  328. }
  329. }
  330. FreeMFDSafe( lpMFD );
  331. }
  332. }
  333. #ifdef DEBUG
  334. {
  335. LPSTR szTmpFile = ReadStrFromFile( hTmp );
  336. free( szTmpFile );
  337. }
  338. #endif
  339. // this is redundant, but need to close file before opening Note window
  340. if ( hTmp != NULL && hTmp != HFILE_ERROR )
  341. {
  342. _lclose( hTmp );
  343. hTmp = NULL;
  344. }
  345. if ( Initialize_RunDLL( TRUE ) )
  346. {
  347. hr = HrCreateNote( &nci );
  348. if ( SUCCEEDED( hr ) )
  349. ulRet = SUCCESS_SUCCESS;
  350. Uninitialize_RunDLL();
  351. }
  352. error:
  353. if ( hTmp != NULL && hTmp != HFILE_ERROR )
  354. _lclose( hTmp );
  355. OpenFile( szCmd, &of, OF_DELETE );
  356. FreeMemSafe( szText );
  357. FreeMRDSafe( lpMRD );
  358. FreeMFDSafe( lpMFD );
  359. if ( pMsg )
  360. pMsg->Release();
  361. if ( pAddrTable )
  362. pAddrTable->Release();
  363. if ( pStream )
  364. pStream->Release();
  365. if ( FAILED( ulRet ) )
  366. AthMessageBoxW( GetDesktopWindow(),
  367. MAKEINTRESOURCEW( idsAthenaMail ),
  368. MAKEINTRESOURCEW( idsMailRundllFailed ),
  369. 0,
  370. MB_ICONEXCLAMATION | MB_OK );
  371. return( ulRet );
  372. }