mapiutil.cpp 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  1. /*
  2. * Copyright 2005 - 2016 Zarafa and its licensors
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Affero General Public License, version 3,
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Affero General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Affero General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. */
  17. #include <kopano/platform.h>
  18. #include <memory>
  19. #include <new>
  20. #include <cstdlib>
  21. #include <cmath> // for pow()
  22. #include "m4l.mapiutil.h"
  23. #include "m4l.mapidefs.h"
  24. #include "m4l.mapix.h"
  25. #include "m4l.debug.h"
  26. #include <mapi.h>
  27. #include <mapix.h>
  28. #include <mapiutil.h>
  29. #include <mapidefs.h>
  30. #include <kopano/ECDebug.h>
  31. #include <kopano/ECTags.h>
  32. #include <kopano/memory.hpp>
  33. #include <kopano/stringutil.h>
  34. #include <kopano/Util.h>
  35. #include "ECMemStream.h"
  36. #include <kopano/mapiguidext.h>
  37. #include "rtf.h"
  38. #include <kopano/charset/convstring.h>
  39. using namespace KCHL;
  40. ULONG __stdcall UlRelease(LPVOID lpUnknown)
  41. {
  42. TRACE_MAPILIB(TRACE_ENTRY, "UlRelease", "");
  43. if(lpUnknown)
  44. return ((IUnknown *)lpUnknown)->Release();
  45. else
  46. return 0;
  47. }
  48. void __stdcall DeinitMapiUtil(void)
  49. {
  50. TRACE_MAPILIB(TRACE_ENTRY, "DeInitMAPIUtil", "");
  51. TRACE_MAPILIB(TRACE_RETURN, "DeInitMAPIUtil", "");
  52. }
  53. SPropValue * __stdcall PpropFindProp(SPropValue *lpPropArray, ULONG cValues,
  54. ULONG ulPropTag)
  55. {
  56. return const_cast<SPropValue *>(PCpropFindProp(lpPropArray, cValues, ulPropTag));
  57. }
  58. const SPropValue * __stdcall PCpropFindProp(const SPropValue *lpPropArray,
  59. ULONG cValues, ULONG ulPropTag)
  60. {
  61. TRACE_MAPILIB1(TRACE_ENTRY, "PpropFindProp", "%08x", ulPropTag);
  62. const SPropValue *lpValue = NULL;
  63. if (lpPropArray == NULL)
  64. goto exit;
  65. for (ULONG i = 0; i<cValues; ++i) {
  66. if ((lpPropArray[i].ulPropTag == ulPropTag) ||
  67. (PROP_TYPE(ulPropTag) == PT_UNSPECIFIED && PROP_ID(lpPropArray[i].ulPropTag) == PROP_ID(ulPropTag))) {
  68. lpValue = &lpPropArray[i];
  69. break;
  70. }
  71. }
  72. exit:
  73. TRACE_MAPILIB2(TRACE_RETURN, "PpropFindProp", "%s: %08x", (lpValue ? "SUCCESS" : "FAILED"), ulPropTag);
  74. return lpValue;
  75. }
  76. // Find a property with a given property Id in a property array. NOTE: doesn't care about prop type!
  77. LPSPropValue __stdcall LpValFindProp(ULONG ulPropTag, ULONG cValues, LPSPropValue lpProps)
  78. {
  79. TRACE_MAPILIB1(TRACE_ENTRY, "LpValFindProp", "%08x", ulPropTag);
  80. LPSPropValue lpValue = NULL;
  81. if (lpProps == NULL)
  82. goto exit;
  83. for (ULONG i = 0; i < cValues; ++i) {
  84. if(PROP_ID(lpProps[i].ulPropTag) == PROP_ID(ulPropTag)) {
  85. lpValue = &lpProps[i];
  86. break;
  87. }
  88. }
  89. exit:
  90. TRACE_MAPILIB2(TRACE_RETURN, "LpValFindProp", "%s: %08x", (lpValue ? "SUCCESS" : "FAILED"), ulPropTag);
  91. return lpValue;
  92. }
  93. SCODE __stdcall PropCopyMore( LPSPropValue lpSPropValueDest, LPSPropValue lpSPropValueSrc, ALLOCATEMORE * lpfAllocMore, LPVOID lpvObject)
  94. {
  95. HRESULT hr = hrSuccess;
  96. TRACE_MAPILIB1(TRACE_ENTRY, "PropCopyMore", "%s", PropNameFromPropArray(1, lpSPropValueSrc).c_str());
  97. hr = Util::HrCopyProperty(lpSPropValueDest, lpSPropValueSrc, lpvObject, lpfAllocMore);
  98. TRACE_MAPILIB2(TRACE_RETURN, "PropCopyMore", "%s: %s", GetMAPIErrorDescription(hr).c_str(), PropNameFromPropArray(1, lpSPropValueDest).c_str());
  99. return hr;
  100. }
  101. HRESULT __stdcall WrapStoreEntryID(ULONG ulFlags, LPTSTR lpszDLLName, ULONG cbOrigEntry,
  102. LPENTRYID lpOrigEntry, ULONG *lpcbWrappedEntry, LPENTRYID *lppWrappedEntry) {
  103. TRACE_MAPILIB(TRACE_ENTRY, "WrapStoreEntryID", "");
  104. HRESULT hr = hrSuccess;
  105. ULONG cbDLLName = 0;
  106. ULONG cbPad = 0;
  107. std::string strDLLName = convstring(lpszDLLName, ulFlags);
  108. if (lpszDLLName == NULL || lpOrigEntry == NULL || lpcbWrappedEntry == NULL || lppWrappedEntry == NULL || cbOrigEntry <= (4+sizeof(GUID)) ) {
  109. hr = MAPI_E_INVALID_PARAMETER;
  110. goto exit;
  111. }
  112. // The format of a wrapped entryid is:
  113. // - flags (4)
  114. // - static guid (16) (see m4l.common.h)
  115. // - 2 bytes unknown data
  116. // - then the dll name + termination char + padding to 32 bits
  117. // - then the entry id
  118. cbDLLName = strDLLName.size() + 1;
  119. cbPad = (4 - ((4+sizeof(GUID)+2+cbDLLName) & 0x03)) & 0x03;
  120. *lpcbWrappedEntry = 4+sizeof(GUID)+2+cbDLLName+cbPad+cbOrigEntry;
  121. hr = MAPIAllocateBuffer(*lpcbWrappedEntry, (void**)lppWrappedEntry);
  122. if (hr != hrSuccess)
  123. goto exit;
  124. memset(*lppWrappedEntry, 0, *lpcbWrappedEntry);
  125. memcpy((*lppWrappedEntry)->ab, &muidStoreWrap, sizeof(GUID));
  126. strcpy(((char*)*lppWrappedEntry)+4+sizeof(GUID)+2, strDLLName.c_str());
  127. memcpy(((BYTE*)*lppWrappedEntry)+4+sizeof(GUID)+2+cbDLLName+cbPad, lpOrigEntry, cbOrigEntry);
  128. exit:
  129. TRACE_MAPILIB1(TRACE_ENTRY, "WrapStoreEntryID", "0x%08x", hr);
  130. return hr;
  131. }
  132. void __stdcall FreeProws(LPSRowSet lpRows) {
  133. TRACE_MAPILIB(TRACE_ENTRY, "FreeProws", "");
  134. unsigned int i;
  135. if(lpRows == NULL)
  136. return;
  137. for (i = 0; i < lpRows->cRows; ++i)
  138. MAPIFreeBuffer(lpRows->aRow[i].lpProps);
  139. MAPIFreeBuffer(lpRows);
  140. TRACE_MAPILIB(TRACE_RETURN, "FreeProws", "");
  141. }
  142. void __stdcall FreePadrlist(LPADRLIST lpAdrlist) {
  143. TRACE_MAPILIB(TRACE_ENTRY, "FreePadrlist", "");
  144. // it's the same in mapi4linux
  145. FreeProws((LPSRowSet) lpAdrlist);
  146. TRACE_MAPILIB(TRACE_RETURN, "FreePadrlist", "");
  147. }
  148. // M4LMAPIAdviseSink is in mapidefs.cpp
  149. HRESULT __stdcall HrAllocAdviseSink(LPNOTIFCALLBACK lpFunction, void *lpContext, LPMAPIADVISESINK *lppSink)
  150. {
  151. TRACE_MAPILIB(TRACE_ENTRY, "HrAllocAdviseSink", "");
  152. HRESULT hr = hrSuccess;
  153. IMAPIAdviseSink *lpSink = NULL;
  154. lpSink = new(std::nothrow) M4LMAPIAdviseSink(lpFunction, lpContext);
  155. if (!lpSink) {
  156. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  157. goto exit;
  158. }
  159. lpSink->AddRef();
  160. *lppSink = lpSink;
  161. exit:
  162. TRACE_MAPILIB1(TRACE_RETURN, "HrAllocAdviseSink", "0x%08x", hr);
  163. return hr;
  164. }
  165. // Linux always has multithreaded advise sinks
  166. HRESULT __stdcall HrThisThreadAdviseSink(LPMAPIADVISESINK lpAdviseSink, LPMAPIADVISESINK *lppAdviseSink) {
  167. TRACE_MAPILIB(TRACE_ENTRY, "HrThisThreadAdviseSink", "");
  168. *lppAdviseSink = lpAdviseSink;
  169. lpAdviseSink->AddRef();
  170. TRACE_MAPILIB1(TRACE_RETURN, "HrThisThreadAdviseSink", "0x%08x", hrSuccess);
  171. return hrSuccess;
  172. }
  173. // rtf funcions
  174. // This is called when a user calls Commit() on a wrapped (uncompressed) RTF Stream
  175. static HRESULT RTFCommitFunc(IStream *lpUncompressedStream, void *lpData)
  176. {
  177. HRESULT hr = hrSuccess;
  178. auto lpCompressedStream = static_cast<IStream *>(lpData);
  179. STATSTG sStatStg;
  180. std::unique_ptr<char[]> lpUncompressed;
  181. char *lpReadPtr = NULL;
  182. ULONG ulRead = 0;
  183. ULONG ulWritten = 0;
  184. unsigned int ulCompressedSize;
  185. char *lpCompressed = NULL;
  186. ULARGE_INTEGER zero = {{0,0}};
  187. LARGE_INTEGER front = {{0,0}};
  188. hr = lpUncompressedStream->Stat(&sStatStg, STATFLAG_NONAME);
  189. if(hr != hrSuccess)
  190. goto exit;
  191. lpUncompressed.reset(new(std::nothrow) char[sStatStg.cbSize.LowPart]);
  192. if(lpUncompressed == NULL) {
  193. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  194. goto exit;
  195. }
  196. lpReadPtr = lpUncompressed.get();
  197. while(1) {
  198. hr = lpUncompressedStream->Read(lpReadPtr, 1024, &ulRead);
  199. if(hr != hrSuccess || ulRead == 0)
  200. break;
  201. lpReadPtr += ulRead;
  202. }
  203. // We now have the complete uncompressed data in lpUncompressed
  204. if (rtf_compress(&lpCompressed, &ulCompressedSize, lpUncompressed.get(), sStatStg.cbSize.LowPart) != 0) {
  205. hr = MAPI_E_CALL_FAILED;
  206. goto exit;
  207. }
  208. // lpCompressed is the compressed RTF stream, write it to lpCompressedStream
  209. lpReadPtr = lpCompressed;
  210. lpCompressedStream->SetSize(zero);
  211. lpCompressedStream->Seek(front,SEEK_SET,NULL);
  212. while(ulCompressedSize) {
  213. hr = lpCompressedStream->Write(lpReadPtr, ulCompressedSize > 16384 ? 16384 : ulCompressedSize, &ulWritten);
  214. if(hr != hrSuccess)
  215. break;
  216. lpReadPtr += ulWritten;
  217. ulCompressedSize -= ulWritten;
  218. }
  219. exit:
  220. free(lpCompressed);
  221. return hr;
  222. }
  223. HRESULT __stdcall WrapCompressedRTFStream(LPSTREAM lpCompressedRTFStream, ULONG ulFlags, LPSTREAM * lppUncompressedStream) {
  224. // This functions doesn't really wrap the stream, but decodes the
  225. // compressed stream, and writes the uncompressed data to the
  226. // Uncompressed stream. This is usually not a problem, as the whole
  227. // stream is read out in one go anyway.
  228. //
  229. // Also, not much streaming is done on the input data, the function
  230. // therefore is quite memory-hungry.
  231. STATSTG sStatStg;
  232. HRESULT hr = hrSuccess;
  233. std::unique_ptr<char[]> lpCompressed, lpUncompressed;
  234. char *lpReadPtr = NULL;
  235. ULONG ulRead = 0;
  236. object_ptr<ECMemStream> lpUncompressedStream;
  237. ULONG ulUncompressedLen = 0;
  238. hr = lpCompressedRTFStream->Stat(&sStatStg, STATFLAG_NONAME);
  239. if(hr != hrSuccess)
  240. return hr;
  241. if(sStatStg.cbSize.LowPart > 0) {
  242. lpCompressed.reset(new(std::nothrow) char[sStatStg.cbSize.LowPart]);
  243. if (lpCompressed == nullptr)
  244. return MAPI_E_NOT_ENOUGH_MEMORY;
  245. // Read in the whole compressed data buffer
  246. lpReadPtr = lpCompressed.get();
  247. while(1) {
  248. hr = lpCompressedRTFStream->Read(lpReadPtr, 1024, &ulRead);
  249. if(hr != hrSuccess)
  250. return hr;
  251. if(ulRead == 0)
  252. break;
  253. lpReadPtr += ulRead;
  254. }
  255. ulUncompressedLen = rtf_get_uncompressed_length(lpCompressed.get(), sStatStg.cbSize.LowPart);
  256. lpUncompressed.reset(new(std::nothrow) char[ulUncompressedLen]);
  257. if (lpUncompressed == nullptr)
  258. return MAPI_E_NOT_ENOUGH_MEMORY;
  259. if (rtf_decompress(lpUncompressed.get(), lpCompressed.get(), sStatStg.cbSize.LowPart) != 0)
  260. return MAPI_E_INVALID_PARAMETER;
  261. // We now have the uncompressed data, create a stream and write the uncompressed data into it
  262. }
  263. hr = ECMemStream::Create(lpUncompressed.get(), ulUncompressedLen,
  264. STGM_WRITE | STGM_TRANSACTED, RTFCommitFunc,
  265. nullptr /* no cleanup */,
  266. lpCompressedRTFStream, &~lpUncompressedStream);
  267. if(hr != hrSuccess)
  268. return hr;
  269. return lpUncompressedStream->QueryInterface(IID_IStream,
  270. reinterpret_cast<void **>(lppUncompressedStream));
  271. }
  272. // RTFSync is not much use even in windows, so we don't implement it
  273. HRESULT __stdcall RTFSync(LPMESSAGE lpMessage, ULONG ulFlags, BOOL * lpfMessageUpdated) {
  274. TRACE_MAPILIB(TRACE_ENTRY, "RTFSync", "");
  275. HRESULT hr = MAPI_E_NO_SUPPORT;
  276. TRACE_MAPILIB1(TRACE_RETURN, "RTFSync", "0x%08x", hr);
  277. return hr;
  278. }
  279. //--- php-ext used functions
  280. HRESULT __stdcall HrQueryAllRows(LPMAPITABLE lpTable,
  281. const SPropTagArray *lpPropTags, LPSRestriction lpRestriction,
  282. const SSortOrderSet *lpSortOrderSet, LONG crowsMax, LPSRowSet *lppRows)
  283. {
  284. TRACE_MAPILIB1(TRACE_ENTRY, "HrQueryAllRows", "%s", PropNameFromPropTagArray(lpPropTags).c_str());
  285. HRESULT hr = hrSuccess;
  286. hr = lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
  287. if (hr != hrSuccess)
  288. goto exit;
  289. if (lpPropTags) {
  290. hr = lpTable->SetColumns(lpPropTags, TBL_BATCH);
  291. if (hr != hrSuccess)
  292. goto exit;
  293. }
  294. if (lpRestriction) {
  295. hr = lpTable->Restrict(lpRestriction, TBL_BATCH);
  296. if (hr != hrSuccess)
  297. goto exit;
  298. }
  299. if (lpSortOrderSet) {
  300. hr = lpTable->SortTable(lpSortOrderSet, TBL_BATCH);
  301. if (hr != hrSuccess)
  302. goto exit;
  303. }
  304. if (crowsMax == 0)
  305. crowsMax = 0x7FFFFFFF;
  306. hr = lpTable->QueryRows(crowsMax, 0, lppRows);
  307. exit:
  308. TRACE_MAPILIB1(TRACE_RETURN, "HrQueryAllRows", "0x%08x", hr);
  309. return hr;
  310. }
  311. HRESULT __stdcall HrGetOneProp(IMAPIProp *lpProp, ULONG ulPropTag, LPSPropValue *lppPropVal) {
  312. TRACE_MAPILIB1(TRACE_ENTRY, "HrGetOneProp", "%08x", ulPropTag);
  313. HRESULT hr = hrSuccess;
  314. SizedSPropTagArray(1, sPropTag) = { 1, { ulPropTag } };
  315. ULONG cValues = 0;
  316. memory_ptr<SPropValue> lpPropVal;
  317. hr = lpProp->GetProps(sPropTag, 0, &cValues, &~lpPropVal);
  318. if(HR_FAILED(hr))
  319. goto exit;
  320. if(cValues != 1 || lpPropVal->ulPropTag != ulPropTag) {
  321. hr = MAPI_E_NOT_FOUND;
  322. goto exit;
  323. }
  324. *lppPropVal = lpPropVal.release();
  325. exit:
  326. TRACE_MAPILIB1(TRACE_RETURN, "HrGetOneProp", "0x%08x", hr);
  327. return hr;
  328. }
  329. HRESULT __stdcall HrSetOneProp(LPMAPIPROP lpMapiProp, const SPropValue *lpProp)
  330. {
  331. TRACE_MAPILIB1(TRACE_ENTRY, "HrSetOneProp", "%s", PropNameFromPropArray(1, lpProp).c_str());
  332. HRESULT hr = hrSuccess;
  333. hr = lpMapiProp->SetProps(1, lpProp, NULL);
  334. // convert ProblemArray into HRESULT error?
  335. TRACE_MAPILIB1(TRACE_RETURN, "HrSetOneProp", "0x%08x", hr);
  336. return hr;
  337. }
  338. BOOL __stdcall FPropExists(LPMAPIPROP lpMapiProp, ULONG ulPropTag)
  339. {
  340. TRACE_MAPILIB1(TRACE_ENTRY, "FPropExists", "%08x", ulPropTag);
  341. HRESULT hr = hrSuccess;
  342. memory_ptr<SPropValue> lpPropVal = NULL;
  343. hr = HrGetOneProp(lpMapiProp, ulPropTag, &~lpPropVal);
  344. TRACE_MAPILIB1(TRACE_RETURN, "FPropExists", "0x%08x", hr);
  345. return (hr == hrSuccess);
  346. }
  347. /* Actually not part of MAPI */
  348. HRESULT __stdcall CreateStreamOnHGlobal(void *hGlobal, BOOL fDeleteOnRelease, IStream **lppStream)
  349. {
  350. HRESULT hr = hrSuccess;
  351. object_ptr<ECMemStream> lpStream;
  352. if (hGlobal != nullptr || fDeleteOnRelease != TRUE)
  353. return MAPI_E_INVALID_PARAMETER;
  354. hr = ECMemStream::Create(nullptr, 0, STGM_WRITE, nullptr, nullptr, nullptr, &~lpStream); // NULLs: no callbacks and custom data
  355. if(hr != hrSuccess)
  356. return hr;
  357. return lpStream->QueryInterface(IID_IStream, reinterpret_cast<void **>(lppStream));
  358. }
  359. HRESULT __stdcall OpenStreamOnFile(LPALLOCATEBUFFER lpAllocateBuffer, LPFREEBUFFER lpFreeBuffer, ULONG ulFlags,
  360. LPTSTR lpszFileName, LPTSTR lpszPrefix, LPSTREAM *lppStream)
  361. {
  362. TRACE_MAPILIB(TRACE_ENTRY, "OpenStreamOnFile", "");
  363. HRESULT hr = MAPI_E_NOT_FOUND;
  364. TRACE_MAPILIB1(TRACE_RETURN, "OpenStreamOnFile", "0x%08x", hr);
  365. return hr;
  366. }
  367. HRESULT __stdcall BuildDisplayTable(LPALLOCATEBUFFER lpAllocateBuffer, LPALLOCATEMORE lpAllocateMore,
  368. LPFREEBUFFER lpFreeBuffer, LPMALLOC lpMalloc,
  369. HINSTANCE hInstance, UINT cPages,
  370. LPDTPAGE lpPage, ULONG ulFlags,
  371. LPMAPITABLE * lppTable, LPTABLEDATA * lppTblData)
  372. {
  373. TRACE_MAPILIB(TRACE_ENTRY, "BuildDisplayTable", "");
  374. HRESULT hr = MAPI_E_NO_SUPPORT;
  375. TRACE_MAPILIB1(TRACE_RETURN, "BuildDisplayTable", "0x%08x", hr);
  376. return hr;
  377. }
  378. #pragma pack(push, 1)
  379. struct CONVERSATION_INDEX {
  380. char ulReserved1;
  381. char ftTime[5];
  382. GUID guid;
  383. };
  384. #pragma pack(pop)
  385. HRESULT __stdcall ScCreateConversationIndex (ULONG cbParent,
  386. LPBYTE lpbParent,
  387. ULONG *lpcbConvIndex,
  388. LPBYTE *lppbConvIndex)
  389. {
  390. HRESULT hr;
  391. TRACE_MAPILIB1(TRACE_ENTRY, "ScCreateConversationIndex", "%s", lpbParent ? bin2hex(cbParent, lpbParent).c_str() : "<null>");
  392. ULONG cbConvIndex = 0;
  393. BYTE *pbConvIndex = NULL;
  394. if(cbParent == 0) {
  395. FILETIME ft;
  396. if ((hr = MAPIAllocateBuffer(sizeof(CONVERSATION_INDEX), (void **)&pbConvIndex)) != hrSuccess)
  397. return hr;
  398. cbConvIndex = sizeof(CONVERSATION_INDEX);
  399. auto ci = reinterpret_cast<CONVERSATION_INDEX *>(pbConvIndex);
  400. ci->ulReserved1 = 1;
  401. UnixTimeToFileTime(time(NULL), &ft);
  402. memcpy(ci->ftTime, &ft, 5);
  403. CoCreateGuid(&ci->guid);
  404. } else {
  405. FILETIME now;
  406. FILETIME parent;
  407. FILETIME diff;
  408. if ((hr = MAPIAllocateBuffer(cbParent + 5, (void **)&pbConvIndex)) != hrSuccess)
  409. return hr;
  410. cbConvIndex = cbParent+5;
  411. memcpy(pbConvIndex, lpbParent, cbParent);
  412. memset(&parent, 0, sizeof(FILETIME));
  413. memcpy(&parent, ((CONVERSATION_INDEX*)lpbParent)->ftTime, 5);
  414. UnixTimeToFileTime(time(NULL), &now);
  415. diff = FtSubFt(now, parent);
  416. memcpy(pbConvIndex + sizeof(CONVERSATION_INDEX), &diff, 5);
  417. }
  418. *lppbConvIndex = pbConvIndex;
  419. *lpcbConvIndex = cbConvIndex;
  420. TRACE_MAPILIB1(TRACE_RETURN, "ScCreateConversationIndex", "%s", bin2hex(cbConvIndex, pbConvIndex).c_str());
  421. return hrSuccess;
  422. }
  423. SCODE __stdcall ScDupPropset( int cprop, LPSPropValue rgprop, LPALLOCATEBUFFER lpAllocateBuffer, LPSPropValue *prgprop )
  424. {
  425. TRACE_MAPILIB(TRACE_ENTRY, "ScDupPropset", "");
  426. HRESULT hr = hrSuccess;
  427. LPSPropValue lpDst = NULL;
  428. ULONG ulSize = 0;
  429. hr = ScCountProps(cprop, rgprop, &ulSize);
  430. if(hr != hrSuccess)
  431. goto exit;
  432. hr = lpAllocateBuffer(ulSize, (void **)&lpDst);
  433. if(hr != hrSuccess)
  434. goto exit;
  435. hr = ScCopyProps(cprop, rgprop, lpDst, NULL);
  436. if(hr != hrSuccess)
  437. goto exit;
  438. *prgprop = lpDst;
  439. exit:
  440. TRACE_MAPILIB1(TRACE_RETURN, "ScDupPropset", "0x%08x", hr);
  441. return hr;
  442. }
  443. SCODE __stdcall ScRelocProps(int cprop, LPSPropValue rgprop, LPVOID pvBaseOld, LPVOID pvBaseNew, ULONG *pcb)
  444. {
  445. TRACE_MAPILIB(TRACE_ENTRY, "ScRelocProps", "");
  446. TRACE_MAPILIB1(TRACE_RETURN, "ScRelocProps", "0x%08x", S_FALSE);
  447. return S_FALSE;
  448. }
  449. ULONG __stdcall CbOfEncoded(LPCSTR lpszEnc)
  450. {
  451. TRACE_MAPILIB(TRACE_ENTRY, "CbOfEncoded", "");
  452. ULONG ulRet = 0;
  453. if (lpszEnc)
  454. ulRet = (((strlen(lpszEnc) | 3) >> 2) + 1) * 3;
  455. TRACE_MAPILIB(TRACE_RETURN, "CbOfEncoded", "");
  456. return ulRet;
  457. }
  458. ULONG __stdcall CchOfEncoding(LPCSTR lpszEnd)
  459. {
  460. TRACE_MAPILIB(TRACE_ENTRY, "CchOfEncoding", "");
  461. TRACE_MAPILIB(TRACE_RETURN, "CchOfEncoding", "");
  462. return 0;
  463. }
  464. SCODE __stdcall ScCopyProps( int cprop, LPSPropValue rgprop, LPVOID pvDst, ULONG *pcb )
  465. {
  466. TRACE_MAPILIB1(TRACE_ENTRY, "ScCopyProps", "%s", PropNameFromPropArray(cprop, rgprop).c_str());
  467. auto lpHeap = static_cast<BYTE *>(pvDst) + sizeof(SPropValue) * cprop;
  468. LPSPropValue lpProp = (LPSPropValue)pvDst;
  469. for (int i = 0 ; i < cprop; ++i) {
  470. lpProp[i] = rgprop[i];
  471. switch(PROP_TYPE(rgprop[i].ulPropTag)) {
  472. case PT_ERROR:
  473. lpProp[i].Value.err = rgprop[i].Value.err;
  474. break;
  475. case PT_NULL:
  476. case PT_OBJECT:
  477. lpProp[i].Value.x = rgprop[i].Value.x;
  478. break;
  479. case PT_BOOLEAN:
  480. lpProp[i].Value.b = rgprop[i].Value.b;
  481. break;
  482. case PT_SHORT:
  483. lpProp[i].Value.i = rgprop[i].Value.i;
  484. break;
  485. case PT_MV_SHORT:
  486. for (ULONG j = 0; j < rgprop[i].Value.MVi.cValues; ++j)
  487. lpProp[i].Value.MVi.lpi[j] = rgprop[i].Value.MVi.lpi[j];
  488. break;
  489. case PT_LONG:
  490. lpProp[i].Value.l = rgprop[i].Value.l;
  491. break;
  492. case PT_MV_LONG:
  493. for (ULONG j = 0; j < rgprop[i].Value.MVl.cValues; ++j)
  494. lpProp[i].Value.MVl.lpl[j] = rgprop[i].Value.MVl.lpl[j];
  495. break;
  496. case PT_LONGLONG:
  497. memcpy(&lpProp[i].Value.li, &rgprop[i].Value.li, sizeof(rgprop[i].Value.li));
  498. break;
  499. case PT_MV_LONGLONG:
  500. for (ULONG j = 0; j < rgprop[i].Value.MVli.cValues; ++j)
  501. memcpy(&lpProp[i].Value.MVli.lpli[j], &rgprop[i].Value.MVli.lpli[j], sizeof(rgprop[i].Value.MVli.lpli[j]));
  502. break;
  503. case PT_FLOAT:
  504. lpProp[i].Value.flt = rgprop[i].Value.flt;
  505. break;
  506. case PT_MV_FLOAT:
  507. for (ULONG j = 0; j < rgprop[i].Value.MVflt.cValues; ++j)
  508. lpProp[i].Value.MVflt.lpflt[j] = rgprop[i].Value.MVflt.lpflt[j];
  509. break;
  510. case PT_DOUBLE:
  511. lpProp[i].Value.dbl = rgprop[i].Value.dbl;
  512. break;
  513. case PT_MV_DOUBLE:
  514. for (ULONG j = 0; j < rgprop[i].Value.MVdbl.cValues; ++j)
  515. lpProp[i].Value.MVdbl.lpdbl[j] = rgprop[i].Value.MVdbl.lpdbl[j];
  516. break;
  517. case PT_CURRENCY:
  518. memcpy(&lpProp[i].Value.cur, &rgprop[i].Value.cur, sizeof(rgprop[i].Value.cur));
  519. break;
  520. case PT_MV_CURRENCY:
  521. for (ULONG j = 0; j < rgprop[i].Value.MVcur.cValues; ++j)
  522. memcpy(&lpProp[i].Value.MVcur.lpcur[j], &rgprop[i].Value.MVcur.lpcur[j], sizeof(rgprop[i].Value.MVcur.lpcur[j]));
  523. break;
  524. case PT_SYSTIME:
  525. memcpy(&lpProp[i].Value.ft, &rgprop[i].Value.ft, sizeof(rgprop[i].Value.ft));
  526. break;
  527. case PT_MV_SYSTIME:
  528. for (ULONG j = 0; j < rgprop[i].Value.MVft.cValues; ++j)
  529. memcpy(&lpProp[i].Value.MVft.lpft[j], &rgprop[i].Value.MVft.lpft[j], sizeof(rgprop[i].Value.MVft.lpft[j]));
  530. break;
  531. case PT_APPTIME:
  532. lpProp[i].Value.at = rgprop[i].Value.at;
  533. break;
  534. case PT_MV_APPTIME:
  535. for (ULONG j = 0; j < rgprop[i].Value.MVat.cValues; ++j)
  536. lpProp[i].Value.MVat.lpat[j] = rgprop[i].Value.MVat.lpat[j];
  537. break;
  538. case PT_CLSID:
  539. memcpy(lpHeap, rgprop[i].Value.lpguid, sizeof(GUID));
  540. lpProp[i].Value.lpguid = (LPGUID)lpHeap;
  541. lpHeap += sizeof(GUID);
  542. break;
  543. case PT_MV_CLSID:
  544. memcpy(lpHeap, rgprop[i].Value.MVguid.lpguid, sizeof(GUID) * rgprop[i].Value.MVguid.cValues);
  545. lpProp[i].Value.MVguid.lpguid = (LPGUID)lpHeap;
  546. lpHeap += sizeof(GUID) * rgprop[i].Value.MVguid.cValues;
  547. break;
  548. #define COPY_STRING8(__heap, __target, __source) \
  549. { \
  550. strcpy((char *)(__heap), (__source)); \
  551. (__target) = (char *)(__heap); \
  552. (__heap) += strlen((__source)) + 1; \
  553. }
  554. case PT_STRING8:
  555. COPY_STRING8(lpHeap, lpProp[i].Value.lpszA, rgprop[i].Value.lpszA);
  556. break;
  557. case PT_MV_STRING8:
  558. for (ULONG j = 0; j < rgprop[i].Value.MVszA.cValues; ++j)
  559. COPY_STRING8(lpHeap, lpProp[i].Value.MVszA.lppszA[j], rgprop[i].Value.MVszA.lppszA[j]);
  560. break;
  561. #define COPY_BINARY(__heap, __target, __source) \
  562. { \
  563. memcpy((__heap), (__source).lpb, (__source).cb);\
  564. (__target).lpb = (__heap); \
  565. (__target).cb = (__source).cb; \
  566. (__heap) += (__source).cb; \
  567. }
  568. case PT_BINARY:
  569. COPY_BINARY(lpHeap, lpProp[i].Value.bin, rgprop[i].Value.bin);
  570. break;
  571. case PT_MV_BINARY:
  572. for (ULONG j = 0; j < rgprop[i].Value.MVbin.cValues; ++j)
  573. COPY_BINARY(lpHeap, lpProp[i].Value.MVbin.lpbin[j], rgprop[i].Value.MVbin.lpbin[j]);
  574. break;
  575. #define COPY_UNICODE(__heap, __target, __source) \
  576. { \
  577. (__target) = lstrcpyW((WCHAR *)(__heap), (__source)); \
  578. (__heap) += (lstrlenW((__source)) + 1) * sizeof(WCHAR); \
  579. }
  580. case PT_UNICODE:
  581. COPY_UNICODE(lpHeap, lpProp[i].Value.lpszW, rgprop[i].Value.lpszW);
  582. break;
  583. case PT_MV_UNICODE:
  584. for (ULONG j = 0; j < rgprop[i].Value.MVszW.cValues; ++j)
  585. COPY_UNICODE(lpHeap, lpProp[i].Value.MVszW.lppszW[j], rgprop[i].Value.MVszW.lppszW[j]);
  586. break;
  587. default:
  588. break;
  589. }
  590. }
  591. if(pcb)
  592. *pcb = lpHeap - (BYTE *)pvDst;
  593. TRACE_MAPILIB1(TRACE_RETURN, "ScCopyProps", "%s", PropNameFromPropArray(cprop, (LPSPropValue)pvDst).c_str());
  594. return S_OK;
  595. }
  596. SCODE __stdcall ScCountProps(int cValues, LPSPropValue lpPropArray, ULONG *lpcb)
  597. {
  598. SCODE sc = S_OK;
  599. ULONG ulSize = 0;
  600. for (int i = 0; i < cValues; ++i) {
  601. ulSize += sizeof(SPropValue);
  602. switch(PROP_TYPE(lpPropArray[i].ulPropTag)) {
  603. case PROP_ID_NULL:
  604. case PROP_ID_INVALID:
  605. sc = MAPI_E_INVALID_PARAMETER;
  606. break;
  607. case PT_STRING8:
  608. ulSize += strlen(lpPropArray[i].Value.lpszA)+1;
  609. break;
  610. case PT_MV_STRING8:
  611. ulSize += sizeof(LPTSTR) * lpPropArray[i].Value.MVszA.cValues;
  612. for (unsigned int j = 0; j < lpPropArray[i].Value.MVszA.cValues; ++j)
  613. ulSize += strlen(lpPropArray[i].Value.MVszA.lppszA[j])+1;
  614. break;
  615. case PT_BINARY:
  616. ulSize += lpPropArray[i].Value.bin.cb;
  617. break;
  618. case PT_MV_BINARY:
  619. ulSize += sizeof(SBinary) * lpPropArray[i].Value.MVbin.cValues;
  620. for (unsigned int j = 0; j < lpPropArray[i].Value.MVbin.cValues; ++j)
  621. ulSize += lpPropArray[i].Value.MVbin.lpbin[j].cb;
  622. break;
  623. case PT_UNICODE:
  624. ulSize += (lstrlenW(lpPropArray[i].Value.lpszW) + 1) * sizeof(WCHAR);
  625. break;
  626. case PT_MV_UNICODE:
  627. ulSize += sizeof(LPWSTR) * lpPropArray[i].Value.MVszW.cValues;
  628. for (unsigned int j = 0; j < lpPropArray[i].Value.MVszW.cValues; ++j)
  629. ulSize += (lstrlenW(lpPropArray[i].Value.MVszW.lppszW[j]) + 1) * sizeof(WCHAR);
  630. break;
  631. case PT_CLSID:
  632. ulSize += sizeof(GUID);
  633. break;
  634. case PT_MV_CLSID:
  635. ulSize += (lpPropArray[i].Value.MVguid.cValues * sizeof(GUID));
  636. break;
  637. default:
  638. break;
  639. }
  640. }
  641. if (lpcb)
  642. *lpcb = ulSize;
  643. TRACE_MAPILIB1(TRACE_RETURN, "ScCountProps", "%d", ulSize);
  644. return sc;
  645. }
  646. SCODE __stdcall ScInitMapiUtil(ULONG ulFlags)
  647. {
  648. TRACE_MAPILIB(TRACE_ENTRY, "ScInitMAPIUtil", "");
  649. TRACE_MAPILIB1(TRACE_RETURN, "ScInitMAPIUtil", "0x%08x", S_OK);
  650. return S_OK;
  651. }
  652. BOOL __stdcall FBinFromHex(LPTSTR sz, LPBYTE pb)
  653. {
  654. TRACE_MAPILIB1(TRACE_ENTRY, "FBinFromHex", "%s", sz);
  655. ULONG len;
  656. memory_ptr<BYTE> lpBin;
  657. Util::hex2bin((char *)sz, strlen((char *)sz), &len, &~lpBin);
  658. memcpy(pb, lpBin, len);
  659. TRACE_MAPILIB1(TRACE_RETURN, "FBinFromHex", "%s", sz);
  660. return true;
  661. }
  662. void __stdcall HexFromBin(LPBYTE pb, int cb, LPTSTR sz)
  663. {
  664. std::string hex = bin2hex(cb, pb);
  665. TRACE_MAPILIB1(TRACE_ENTRY, "HexFromBin", "%s", hex.c_str());
  666. strcpy((char *)sz, hex.c_str());
  667. TRACE_MAPILIB1(TRACE_RETURN, "HexFromBin", "%s", sz);
  668. }
  669. // @todo according to MSDN, this function also supports Unicode strings
  670. // but I don't see how that's easy possible
  671. LPTSTR __stdcall SzFindCh(LPCTSTR lpsz, USHORT ch)
  672. {
  673. TRACE_MAPILIB(TRACE_ENTRY, "SzFindCh", "");
  674. LPTSTR lpszFind = (LPTSTR)strchr((char*)lpsz, ch);
  675. TRACE_MAPILIB(TRACE_RETURN, "SzFindCh", "");
  676. return lpszFind;
  677. }
  678. int __stdcall MNLS_CompareStringW(LCID Locale, DWORD dwCmpFlags, LPCWSTR lpString1, int cchCount1, LPCWSTR lpString2, int cchCount2)
  679. {
  680. TRACE_MAPILIB4(TRACE_ENTRY, "MNLS_CompareStringW", "%d %S, %d %S", cchCount1, lpString1, cchCount2, lpString2);
  681. // FIXME: we're ignoring Locale, dwCmpFlags, cchCount1 and cchCount2
  682. int ulCmp = wcscmp((LPWSTR)lpString1, (LPWSTR)lpString2);
  683. TRACE_MAPILIB1(TRACE_RETURN, "MNLS_CompareStringW", "%d", ulCmp);
  684. return ulCmp;
  685. }
  686. int __stdcall MNLS_lstrlenW(LPCWSTR lpString)
  687. {
  688. TRACE_MAPILIB1(TRACE_ENTRY, "MNLS_lstrlenW", "%S", lpString);
  689. int ulLen = lstrlenW(lpString);
  690. TRACE_MAPILIB2(TRACE_RETURN, "MNLS_lstrlenW", "%S: %d", lpString, ulLen);
  691. return ulLen;
  692. }
  693. int __stdcall MNLS_lstrlen(LPCSTR lpString)
  694. {
  695. TRACE_MAPILIB1(TRACE_ENTRY, "MNLS_lstrlen", "%S", lpString);
  696. int ulLen = lstrlenW((LPCWSTR)lpString);
  697. TRACE_MAPILIB2(TRACE_RETURN, "MNLS_lstrlen", "%S: %d", lpString, ulLen);
  698. return ulLen;
  699. }
  700. int __stdcall MNLS_lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
  701. {
  702. TRACE_MAPILIB2(TRACE_ENTRY, "lstrcmpW", "%S, %S", lpString1, lpString2);
  703. int ulCmp = lstrcmpW(lpString1, lpString2);
  704. TRACE_MAPILIB3(TRACE_RETURN, "lstrcmpW", "%S, %S: %d", lpString1, lpString2, ulCmp);
  705. return ulCmp;
  706. }
  707. LPWSTR __stdcall MNLS_lstrcpyW(LPWSTR lpString1, LPCWSTR lpString2)
  708. {
  709. TRACE_MAPILIB1(TRACE_ENTRY, "MNLS_lstrcpyW", "%S", lpString2);
  710. LPWSTR str = lstrcpyW(lpString1, lpString2);
  711. TRACE_MAPILIB(TRACE_RETURN, "MNLS_lstrcpyW", "");
  712. return str;
  713. }
  714. FILETIME __stdcall FtAddFt( FILETIME Addend1, FILETIME Addend2 )
  715. {
  716. TRACE_MAPILIB4(TRACE_ENTRY, "FtAddFt", "(%u,%u) (%u,%u)", Addend1.dwHighDateTime, Addend1.dwLowDateTime, Addend2.dwHighDateTime, Addend2.dwLowDateTime);
  717. FILETIME ft;
  718. unsigned long long l = ((unsigned long long)Addend1.dwHighDateTime << 32) + Addend1.dwLowDateTime;
  719. l += ((unsigned long long)Addend2.dwHighDateTime << 32) + Addend2.dwLowDateTime;
  720. ft.dwHighDateTime = l >> 32;
  721. ft.dwLowDateTime = l & 0xffffffff;
  722. TRACE_MAPILIB2(TRACE_RETURN, "FtAddFt", "(%u,%u)", ft.dwHighDateTime, ft.dwLowDateTime);
  723. return ft;
  724. }
  725. FILETIME __stdcall FtSubFt( FILETIME Minuend, FILETIME Subtrahend )
  726. {
  727. TRACE_MAPILIB4(TRACE_ENTRY, "FtSubFt", "(%u,%u) (%u,%u)", Minuend.dwHighDateTime, Minuend.dwLowDateTime, Subtrahend.dwHighDateTime, Subtrahend.dwLowDateTime);
  728. FILETIME ft;
  729. unsigned long long l = ((unsigned long long)Minuend.dwHighDateTime << 32) + Minuend.dwLowDateTime;
  730. l -= ((unsigned long long)Subtrahend.dwHighDateTime << 32) + Subtrahend.dwLowDateTime;
  731. ft.dwHighDateTime = l >> 32;
  732. ft.dwLowDateTime = l & 0xffffffff;
  733. TRACE_MAPILIB2(TRACE_RETURN, "FtSubFt", "(%u,%u)", ft.dwHighDateTime, ft.dwLowDateTime);
  734. return ft;
  735. }
  736. FILETIME __stdcall FtDivFtBogus(FILETIME f, FILETIME f2, DWORD n)
  737. {
  738. TRACE_MAPILIB5(TRACE_ENTRY, "FtDivFtBogus", "(%u, %u), (%u, %u), %u", f.dwHighDateTime, f.dwLowDateTime, f2.dwHighDateTime, f2.dwLowDateTime, n);
  739. // Obtained by experiment: this function does (f*f2) >> (n+64)
  740. // Since we don't have a good int64 * int64, we do our own addition_plus_bitshift
  741. // which discards the lowest 64 bits on the fly.
  742. unsigned long long shift = 0;
  743. unsigned long long ret = (unsigned long long)f.dwHighDateTime * f2.dwHighDateTime;
  744. ret += ((unsigned long long)f.dwLowDateTime * f2.dwHighDateTime) >> 32;
  745. ret += ((unsigned long long)f.dwHighDateTime * f2.dwLowDateTime) >> 32;
  746. // The remainder may give us a few more, use the top 32 bits of the remainder.
  747. shift += (((unsigned long long)f.dwLowDateTime * f2.dwHighDateTime) & 0xFFFFFFFF);
  748. shift += (((unsigned long long)f.dwHighDateTime * f2.dwLowDateTime) & 0xFFFFFFFF);
  749. shift += ((unsigned long long)f.dwLowDateTime * f2.dwLowDateTime) >> 32;
  750. ret += shift >> 32;
  751. ret >>= n;
  752. FILETIME ft;
  753. ft.dwHighDateTime = ret >> 32;
  754. ft.dwLowDateTime = ret & 0xFFFFFFFF;
  755. TRACE_MAPILIB2(TRACE_RETURN, "FtDivFtBogus", "(%u %u)", ft.dwHighDateTime, ft.dwLowDateTime);
  756. return ft;
  757. }
  758. FILETIME __stdcall FtMulDw(DWORD ftMultiplier, FILETIME ftMultiplicand)
  759. {
  760. TRACE_MAPILIB3(TRACE_ENTRY, "FtMulDw", "%d x (%d, %d)", ftMultiplier, ftMultiplicand.dwHighDateTime, ftMultiplicand.dwLowDateTime);
  761. FILETIME ft;
  762. unsigned long long t = ((unsigned long long)ftMultiplicand.dwHighDateTime << 32) + (ftMultiplicand.dwLowDateTime & 0xffffffff);
  763. t *= ftMultiplier;
  764. ft.dwHighDateTime = t >> 32;
  765. ft.dwLowDateTime = t & 0xFFFFFFFF;
  766. TRACE_MAPILIB2(TRACE_RETURN, "FtMulDw", "%(%d, %d)", ft.dwHighDateTime, ft.dwLowDateTime);
  767. return ft;
  768. }
  769. LONG __stdcall MAPIInitIdle( LPVOID lpvReserved )
  770. {
  771. TRACE_MAPILIB(TRACE_ENTRY, "MAPIInitIdle", "");
  772. TRACE_MAPILIB(TRACE_RETURN, "MAPIInitIdle", "");
  773. return 0;
  774. }
  775. void __stdcall MAPIDeinitIdle(void)
  776. {
  777. TRACE_MAPILIB(TRACE_ENTRY, "MAPIDeinitIdle", "");
  778. TRACE_MAPILIB(TRACE_RETURN, "MAPIDeinitIdle", "");
  779. }
  780. void __stdcall DeregisterIdleRoutine( FTG ftg )
  781. {
  782. TRACE_MAPILIB(TRACE_ENTRY, "DeregisterIdleRoutine", "");
  783. TRACE_MAPILIB(TRACE_RETURN, "DeregisterIdleRoutine", "");
  784. }
  785. void __stdcall EnableIdleRoutine( FTG ftg, BOOL fEnable )
  786. {
  787. TRACE_MAPILIB(TRACE_ENTRY, "EnableIdleRoutine", "");
  788. TRACE_MAPILIB(TRACE_RETURN, "EnableIdleRoutine", "");
  789. }
  790. void __stdcall ChangeIdleRoutine(FTG ftg, PFNIDLE pfnIdle, LPVOID pvIdleParam, short priIdle, ULONG csecIdle, USHORT iroIdle, USHORT ircIdle)
  791. {
  792. TRACE_MAPILIB(TRACE_ENTRY, "ChangeIdleRoutine", "");
  793. TRACE_MAPILIB(TRACE_RETURN, "ChangeIdleRoutine", "");
  794. }
  795. FTG __stdcall FtgRegisterIdleRoutine(PFNIDLE pfnIdle, LPVOID pvIdleParam, short priIdle, ULONG csecIdle, USHORT iroIdle)
  796. {
  797. TRACE_MAPILIB(TRACE_ENTRY, "FtgRegisterIdleRoutine", "");
  798. FTG f = NULL;
  799. TRACE_MAPILIB(TRACE_RETURN, "FtgRegisterIdleRoutine", "");
  800. return f;
  801. }
  802. const WORD kwBaseOffset = 0xAC00; // Hangul char range (AC00-D7AF)
  803. LPWSTR __stdcall EncodeID(ULONG cbEID, LPENTRYID rgbID, LPWSTR *lpWString)
  804. {
  805. TRACE_MAPILIB(TRACE_ENTRY, "EncodeID", "");
  806. ULONG i = 0;
  807. LPWSTR pwzDst = NULL;
  808. LPBYTE pbSrc = NULL;
  809. LPWSTR pwzIDEncoded = NULL;
  810. // rgbID is the item Entry ID or the attachment ID
  811. // cbID is the size in bytes of rgbID
  812. // Allocate memory for pwzIDEncoded
  813. pwzIDEncoded = new WCHAR[cbEID+1];
  814. if (!pwzIDEncoded)
  815. goto exit;
  816. for (i = 0, pbSrc = (LPBYTE)rgbID, pwzDst = pwzIDEncoded;
  817. i < cbEID; ++i, ++pbSrc, ++pwzDst)
  818. *pwzDst = (WCHAR) (*pbSrc + kwBaseOffset);
  819. // Ensure NULL terminated
  820. *pwzDst = L'\0';
  821. exit:
  822. // pwzIDEncoded now contains the entry ID encoded.
  823. TRACE_MAPILIB1(TRACE_RETURN, "EncodeID", "%s", (pwzIDEncoded ? "SUCCESS" : "FAILED"));
  824. return pwzIDEncoded;
  825. }
  826. void __stdcall FDecodeID(LPCSTR lpwEncoded, LPENTRYID *lpDecoded, ULONG *cbEncoded)
  827. {
  828. TRACE_MAPILIB(TRACE_ENTRY, "FDecodeID", "");
  829. TRACE_MAPILIB(TRACE_RETURN, "FDecodeID", "");
  830. // ?
  831. }
  832. BOOL __stdcall FBadRglpszA(const TCHAR *, ULONG cStrings)
  833. {
  834. TRACE_MAPILIB(TRACE_ENTRY, "FBadRglpszA", "");
  835. TRACE_MAPILIB(TRACE_RETURN, "FBadRglpszA", "");
  836. return FALSE;
  837. }
  838. BOOL __stdcall FBadRglpszW(const wchar_t *, ULONG cStrings)
  839. {
  840. TRACE_MAPILIB(TRACE_ENTRY, "FBadRglpszW", "");
  841. TRACE_MAPILIB(TRACE_RETURN, "FBadRglpszW", "");
  842. return FALSE;
  843. }
  844. BOOL __stdcall FBadRowSet(const SRowSet *)
  845. {
  846. TRACE_MAPILIB(TRACE_ENTRY, "FBadRowSet", "");
  847. TRACE_MAPILIB(TRACE_RETURN, "FBadRowSet", "");
  848. return FALSE;
  849. }
  850. BOOL __stdcall FBadRglpNameID(LPMAPINAMEID *lppNameId, ULONG cNames)
  851. {
  852. TRACE_MAPILIB(TRACE_ENTRY, "FBadRglpNameID", "");
  853. TRACE_MAPILIB(TRACE_RETURN, "FBadRglpNameID", "");
  854. return FALSE;
  855. }
  856. ULONG __stdcall FBadPropTag(ULONG ulPropTag)
  857. {
  858. TRACE_MAPILIB(TRACE_ENTRY, "FBadPropTag", "");
  859. TRACE_MAPILIB(TRACE_RETURN, "FBadPropTag", "");
  860. return FALSE;
  861. }
  862. ULONG __stdcall FBadRow(const SRow *)
  863. {
  864. TRACE_MAPILIB(TRACE_ENTRY, "FBadRow", "");
  865. TRACE_MAPILIB(TRACE_RETURN, "FBadRow", "");
  866. return FALSE;
  867. }
  868. ULONG __stdcall FBadProp(const SPropValue *)
  869. {
  870. TRACE_MAPILIB(TRACE_ENTRY, "FBadProp", "");
  871. TRACE_MAPILIB(TRACE_RETURN, "FBadProp", "");
  872. return FALSE;
  873. }
  874. ULONG __stdcall FBadColumnSet(const SPropTagArray *lpptaCols)
  875. {
  876. TRACE_MAPILIB(TRACE_ENTRY, "FBadColumnSet", "");
  877. TRACE_MAPILIB(TRACE_RETURN, "FBadColumnSet", "");
  878. return FALSE;
  879. }
  880. ULONG __stdcall FBadSortOrderSet(const SSortOrderSet *)
  881. {
  882. TRACE_MAPILIB(TRACE_ENTRY, "FBadSortOrderSet", "");
  883. TRACE_MAPILIB(TRACE_RETURN, "FBadSortOrderSet", "");
  884. return FALSE;
  885. }
  886. BOOL __stdcall FBadEntryList(const SBinaryArray *lpEntryList)
  887. {
  888. TRACE_MAPILIB(TRACE_ENTRY, "FBadEntryList", "");
  889. TRACE_MAPILIB(TRACE_RETURN, "FBadEntryList", "");
  890. return FALSE;
  891. }
  892. ULONG __stdcall FBadRestriction(const SRestriction *)
  893. {
  894. TRACE_MAPILIB(TRACE_ENTRY, "FBadRestriction", "");
  895. TRACE_MAPILIB(TRACE_RETURN, "FBadRestriction", "");
  896. return FALSE;
  897. }
  898. HRESULT GetConnectionProperties(LPSPropValue lpServer, LPSPropValue lpUsername, ULONG *lpcValues, LPSPropValue *lppProps)
  899. {
  900. HRESULT hr = hrSuccess;
  901. memory_ptr<SPropValue> lpProps;
  902. char *szUsername;
  903. std::string strServerPath;
  904. ULONG cProps = 0;
  905. if (lpServer == nullptr || lpUsername == nullptr)
  906. return MAPI_E_UNCONFIGURED;
  907. hr = MAPIAllocateBuffer(sizeof(SPropValue) * 5, &~lpProps);
  908. if (hr != hrSuccess)
  909. return hr;
  910. if (m4l_lpConfig->GetSetting("server_address")[0])
  911. strServerPath = (std::string)"https://" + m4l_lpConfig->GetSetting("server_address") + ":" + m4l_lpConfig->GetSetting("ssl_port") + "/";
  912. else
  913. strServerPath = (std::string)"https://" + lpServer->Value.lpszA + ":" + m4l_lpConfig->GetSetting("ssl_port") + "/";
  914. szUsername = lpUsername->Value.lpszA;
  915. if(strrchr(szUsername, '='))
  916. szUsername = strrchr(szUsername, '=')+1;
  917. lpProps[cProps].ulPropTag = PR_EC_PATH;
  918. if ((hr = MAPIAllocateMore(strServerPath.size() + 1, lpProps, (void**)&lpProps[cProps].Value.lpszA)) != hrSuccess)
  919. return hr;
  920. memcpy(lpProps[cProps++].Value.lpszA, strServerPath.c_str(),strServerPath.size() + 1);
  921. lpProps[cProps].ulPropTag = PR_EC_USERNAME_A;
  922. if ((hr = MAPIAllocateMore(strlen(szUsername) + 1, lpProps, (void**)&lpProps[cProps].Value.lpszA)) != hrSuccess)
  923. return hr;
  924. memcpy(lpProps[cProps++].Value.lpszA, szUsername, strlen(szUsername) + 1);
  925. lpProps[cProps].ulPropTag = PR_EC_USERPASSWORD_A;
  926. if ((hr = MAPIAllocateMore(1, lpProps, (void**)&lpProps[cProps].Value.lpszA)) != hrSuccess)
  927. return hr;
  928. memcpy(lpProps[cProps++].Value.lpszA, "", 1);
  929. lpProps[cProps].ulPropTag = PR_EC_SSLKEY_FILE;
  930. if ((hr = MAPIAllocateMore(strlen(m4l_lpConfig->GetSetting("ssl_key_file")) + 1, lpProps, (void**)&lpProps[cProps].Value.lpszA)) != hrSuccess)
  931. return hr;
  932. memcpy(lpProps[cProps++].Value.lpszA, m4l_lpConfig->GetSetting("ssl_key_file"), strlen(m4l_lpConfig->GetSetting("ssl_key_file")) + 1);
  933. lpProps[cProps].ulPropTag = PR_EC_SSLKEY_PASS;
  934. if ((hr = MAPIAllocateMore(strlen(m4l_lpConfig->GetSetting("ssl_key_pass")) + 1, lpProps, (void**)&lpProps[cProps].Value.lpszA)) != hrSuccess)
  935. return hr;
  936. memcpy(lpProps[cProps++].Value.lpszA, m4l_lpConfig->GetSetting("ssl_key_pass"), strlen(m4l_lpConfig->GetSetting("ssl_key_pass")) + 1);
  937. *lpcValues = cProps;
  938. *lppProps = lpProps.release();
  939. return hrSuccess;
  940. }