2 * MAPI Utility functions
4 * Copyright 2004 Jon Griffiths
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(mapi);
41 /**************************************************************************
42 * ScInitMapiUtil (MAPI32.33)
44 * Initialise Mapi utility functions.
47 * ulReserved [I] Reserved, pass 0.
50 * Success: S_OK. Mapi utility functions may be called.
51 * Failure: MAPI_E_INVALID_PARAMETER, if ulReserved is not 0.
54 * Your application does not need to call this function unless it does not
55 * call MAPIInitialize()/MAPIUninitialize().
57 SCODE WINAPI ScInitMapiUtil(ULONG ulReserved)
59 FIXME("(0x%08lx)stub!\n", ulReserved);
61 return MAPI_E_INVALID_PARAMETER;
65 /**************************************************************************
66 * DeinitMapiUtil (MAPI32.34)
68 * Uninitialise Mapi utility functions.
77 * Your application does not need to call this function unless it does not
78 * call MAPIInitialize()/MAPIUninitialize().
80 VOID WINAPI DeinitMapiUtil(void)
85 typedef LPVOID *LPMAPIALLOCBUFFER;
87 /**************************************************************************
88 * MAPIAllocateBuffer (MAPI32.12)
89 * MAPIAllocateBuffer@8 (MAPI32.13)
91 * Allocate a block of memory.
94 * cbSize [I] Size of the block to allocate in bytes
95 * lppBuffer [O] Destination for pointer to allocated memory
98 * Success: S_OK. *lppBuffer is filled with a pointer to a memory block of
99 * length cbSize bytes.
100 * Failure: MAPI_E_INVALID_PARAMETER, if lppBuffer is NULL.
101 * MAPI_E_NOT_ENOUGH_MEMORY, if the memory allocation fails.
104 * Memory allocated with this function should be freed with MAPIFreeBuffer().
105 * Further allocations of memory may be linked to the pointer returned using
106 * MAPIAllocateMore(). Linked allocations are freed when the initial pointer
109 SCODE WINAPI MAPIAllocateBuffer(ULONG cbSize, LPVOID *lppBuffer)
111 LPMAPIALLOCBUFFER lpBuff;
113 TRACE("(%ld,%p)\n", cbSize, lppBuffer);
118 lpBuff = (LPMAPIALLOCBUFFER)HeapAlloc(GetProcessHeap(), 0, cbSize + sizeof(*lpBuff));
120 return MAPI_E_NOT_ENOUGH_MEMORY;
122 TRACE("initial allocation:%p, returning %p\n", lpBuff, lpBuff + 1);
128 /**************************************************************************
129 * MAPIAllocateMore (MAPI32.14)
130 * MAPIAllocateMore@12 (MAPI32.15)
132 * Allocate a block of memory linked to a previous allocation.
135 * cbSize [I] Size of the block to allocate in bytes
136 * lpOrig [I] Initial allocation to link to, from MAPIAllocateBuffer()
137 * lppBuffer [O] Destination for pointer to allocated memory
140 * Success: S_OK. *lppBuffer is filled with a pointer to a memory block of
141 * length cbSize bytes.
142 * Failure: MAPI_E_INVALID_PARAMETER, if lpOrig or lppBuffer is invalid.
143 * MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails.
146 * Memory allocated with this function and stored in *lppBuffer is freed
147 * when lpOrig is passed to MAPIFreeBuffer(). It should not be freed independently.
149 SCODE WINAPI MAPIAllocateMore(ULONG cbSize, LPVOID lpOrig, LPVOID *lppBuffer)
151 LPMAPIALLOCBUFFER lpBuff = lpOrig;
153 TRACE("(%ld,%p,%p)\n", cbSize, lpOrig, lppBuffer);
155 if (!lppBuffer || !lpBuff || !--lpBuff)
158 /* Find the last allocation in the chain */
161 TRACE("linked:%p->%p\n", lpBuff, *lpBuff);
165 if (SUCCEEDED(MAPIAllocateBuffer(cbSize, lppBuffer)))
167 *lpBuff = ((LPMAPIALLOCBUFFER)*lppBuffer) - 1;
168 TRACE("linking %p->%p\n", lpBuff, *lpBuff);
170 return *lppBuffer ? S_OK : MAPI_E_NOT_ENOUGH_MEMORY;
173 /**************************************************************************
174 * MAPIFreeBuffer (MAPI32.16)
175 * MAPIFreeBuffer@4 (MAPI32.17)
177 * Free a block of memory and any linked allocations associated with it.
180 * lpBuffer [I] Memory to free, returned from MAPIAllocateBuffer()
185 ULONG WINAPI MAPIFreeBuffer(LPVOID lpBuffer)
187 LPMAPIALLOCBUFFER lpBuff = lpBuffer;
189 TRACE("(%p)\n", lpBuffer);
191 if (lpBuff && --lpBuff)
195 LPVOID lpFree = lpBuff;
199 TRACE("linked:%p->%p, freeing %p\n", lpFree, lpBuff, lpFree);
200 HeapFree(GetProcessHeap(), 0, lpFree);
206 /*************************************************************************
207 * HrThisThreadAdviseSink@8 (MAPI32.42)
209 * Ensure that an advise sink is only notified in its originating thread.
212 * lpSink [I] IMAPIAdviseSink interface to be protected
213 * lppNewSink [I] Destination for wrapper IMAPIAdviseSink interface
216 * Success: S_OK. *lppNewSink contains a new sink to use in place of lpSink.
217 * Failure: E_INVALIDARG, if any parameter is invalid.
219 HRESULT WINAPI HrThisThreadAdviseSink(LPMAPIADVISESINK lpSink, LPMAPIADVISESINK* lppNewSink)
221 FIXME("(%p,%p)semi-stub\n", lpSink, lppNewSink);
223 if (!lpSink || !lppNewSink)
226 /* Don't wrap the sink for now, just copy it */
227 *lppNewSink = lpSink;
228 IMAPIAdviseSink_AddRef(lpSink);
232 /*************************************************************************
233 * FBinFromHex (MAPI32.44)
235 * Create an array of binary data from a string.
238 * lpszHex [I] String to convert to binary data
239 * lpOut [O] Destination for resulting binary data
242 * Success: TRUE. lpOut contains the decoded binary data.
243 * Failure: FALSE, if lpszHex does not represent a binary string.
246 * - lpOut must be at least half the length of lpszHex in bytes.
247 * - Although the Mapi headers prototype this function as both
248 * Ascii and Unicode, there is only one (Ascii) implementation. This
249 * means that lpszHex is treated as an Ascii string (i.e. a single NUL
250 * character in the byte stream terminates the string).
252 BOOL WINAPI FBinFromHex(LPWSTR lpszHex, LPBYTE lpOut)
254 static const BYTE digitsToHex[] = {
255 0,1,2,3,4,5,6,7,8,9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,10,11,12,13,14,15,
256 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
257 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,10,11,12,13,
259 LPSTR lpStr = (LPSTR)lpszHex;
261 TRACE("(%p,%p)\n", lpszHex, lpOut);
265 if (lpStr[0] < '0' || lpStr[0] > 'f' || digitsToHex[lpStr[0] - '0'] == 0xff ||
266 lpStr[1] < '0' || lpStr[1] > 'f' || digitsToHex[lpStr[1] - '0'] == 0xff)
269 *lpOut++ = (digitsToHex[lpStr[0] - '0'] << 4) | digitsToHex[lpStr[1] - '0'];
275 /*************************************************************************
276 * HexFromBin (MAPI32.45)
278 * Create a string from an array of binary data.
281 * lpHex [I] Binary data to convert to string
282 * iCount [I] Length of lpHex in bytes
283 * lpszOut [O] Destination for resulting hex string
289 * - lpszOut must be at least 2 * iCount + 1 bytes characters long.
290 * - Although the Mapi headers prototype this function as both
291 * Ascii and Unicode, there is only one (Ascii) implementation. This
292 * means that the resulting string is not properly NUL terminated
293 * if the caller expects it to be a Unicode string.
295 void WINAPI HexFromBin(LPBYTE lpHex, int iCount, LPWSTR lpszOut)
297 static const char hexDigits[] = { "0123456789ABCDEF" };
298 LPSTR lpStr = (LPSTR)lpszOut;
300 TRACE("(%p,%d,%p)\n", lpHex, iCount, lpszOut);
304 *lpStr++ = hexDigits[*lpHex >> 4];
305 *lpStr++ = hexDigits[*lpHex & 0xf];
311 /*************************************************************************
312 * SwapPlong@8 (MAPI32.47)
314 * Swap the bytes in a ULONG array.
317 * lpData [O] Array to swap bytes in
318 * ulLen [I] Number of ULONG element to swap the bytes of
323 VOID WINAPI SwapPlong(PULONG lpData, ULONG ulLen)
327 for (i = 0; i < ulLen; i++)
328 lpData[i] = RtlUlongByteSwap(lpData[i]);
331 /*************************************************************************
332 * SwapPword@8 (MAPI32.48)
334 * Swap the bytes in a USHORT array.
337 * lpData [O] Array to swap bytes in
338 * ulLen [I] Number of USHORT element to swap the bytes of
343 VOID WINAPI SwapPword(PUSHORT lpData, ULONG ulLen)
347 for (i = 0; i < ulLen; i++)
348 lpData[i] = RtlUshortByteSwap(lpData[i]);
351 /**************************************************************************
352 * MNLS_lstrlenW@4 (MAPI32.62)
354 * Calculate the length of a Unicode string.
357 * lpszStr [I] String to calculate the length of
360 * The length of lpszStr in Unicode characters.
362 ULONG WINAPI MNLS_lstrlenW(LPCWSTR lpszStr)
364 TRACE("(%s)\n", debugstr_w(lpszStr));
365 return strlenW(lpszStr);
368 /*************************************************************************
369 * MNLS_lstrcmpW@8 (MAPI32.63)
371 * Compare two Unicode strings.
374 * lpszLeft [I] First string to compare
375 * lpszRight [I] Second string to compare
378 * An integer less than, equal to or greater than 0, indicating that
379 * lpszLeft is less than, the same, or greater than lpszRight.
381 INT WINAPI MNLS_lstrcmpW(LPCWSTR lpszLeft, LPCWSTR lpszRight)
383 TRACE("(%s,%s)\n", debugstr_w(lpszLeft), debugstr_w(lpszRight));
384 return strcmpW(lpszLeft, lpszRight);
387 /*************************************************************************
388 * MNLS_lstrcpyW@8 (MAPI32.64)
390 * Copy a Unicode string to another string.
393 * lpszDest [O] Destination string
394 * lpszSrc [I] Source string
397 * The length lpszDest in Unicode characters.
399 ULONG WINAPI MNLS_lstrcpyW(LPWSTR lpszDest, LPCWSTR lpszSrc)
403 TRACE("(%p,%s)\n", lpszDest, debugstr_w(lpszSrc));
404 len = (strlenW(lpszSrc) + 1) * sizeof(WCHAR);
405 memcpy(lpszDest, lpszSrc, len);
409 /*************************************************************************
410 * MNLS_CompareStringW@12 (MAPI32.65)
412 * Compare two Unicode strings.
415 * dwCp [I] Code page for the comparison
416 * lpszLeft [I] First string to compare
417 * lpszRight [I] Second string to compare
420 * CSTR_LESS_THAN, CSTR_EQUAL or CSTR_GREATER_THAN, indicating that
421 * lpszLeft is less than, the same, or greater than lpszRight.
423 INT WINAPI MNLS_CompareStringW(DWORD dwCp, LPCWSTR lpszLeft, LPCWSTR lpszRight)
427 TRACE("0x%08lx,%s,%s\n", dwCp, debugstr_w(lpszLeft), debugstr_w(lpszRight));
428 ret = MNLS_lstrcmpW(lpszLeft, lpszRight);
429 return ret < 0 ? CSTR_LESS_THAN : ret ? CSTR_GREATER_THAN : CSTR_EQUAL;
432 /**************************************************************************
433 * FEqualNames@8 (MAPI32.72)
435 * Compare two Mapi names.
438 * lpName1 [I] First name to compare to lpName2
439 * lpName2 [I] Second name to compare to lpName1
442 * TRUE, if the names are the same,
445 BOOL WINAPI FEqualNames(LPMAPINAMEID lpName1, LPMAPINAMEID lpName2)
447 TRACE("(%p,%p)\n", lpName1, lpName2);
449 if (!lpName1 || !lpName2 ||
450 !IsEqualGUID(lpName1->lpguid, lpName2->lpguid) ||
451 lpName1->ulKind != lpName2->ulKind)
454 if (lpName1->ulKind == MNID_STRING)
455 return !strcmpW(lpName1->Kind.lpwstrName, lpName2->Kind.lpwstrName);
457 return lpName1->Kind.lID == lpName2->Kind.lID ? TRUE : FALSE;
460 /**************************************************************************
461 * FtAddFt@16 (MAPI32.121)
463 * Add two FILETIME's together.
466 * ftLeft [I] FILETIME to add to ftRight
467 * ftRight [I] FILETIME to add to ftLeft
470 * The sum of ftLeft and ftRight
472 LONGLONG WINAPI MAPI32_FtAddFt(FILETIME ftLeft, FILETIME ftRight)
474 LONGLONG *pl = (LONGLONG*)&ftLeft, *pr = (LONGLONG*)&ftRight;
479 /**************************************************************************
480 * FtSubFt@16 (MAPI32.123)
482 * Subtract two FILETIME's together.
485 * ftLeft [I] Initial FILETIME
486 * ftRight [I] FILETIME to subtract from ftLeft
489 * The remainder after ftRight is subtracted from ftLeft.
491 LONGLONG WINAPI MAPI32_FtSubFt(FILETIME ftLeft, FILETIME ftRight)
493 LONGLONG *pl = (LONGLONG*)&ftLeft, *pr = (LONGLONG*)&ftRight;
498 /**************************************************************************
499 * FtMulDw@12 (MAPI32.124)
501 * Multiply a FILETIME by a DWORD.
504 * dwLeft [I] DWORD to multiply with ftRight
505 * ftRight [I] FILETIME to multiply with dwLeft
508 * The product of dwLeft and ftRight
510 LONGLONG WINAPI MAPI32_FtMulDw(DWORD dwLeft, FILETIME ftRight)
512 LONGLONG *pr = (LONGLONG*)&ftRight;
514 return (LONGLONG)dwLeft * (*pr);
517 /**************************************************************************
518 * FtMulDwDw@8 (MAPI32.125)
520 * Multiply two DWORD, giving the result as a FILETIME.
523 * dwLeft [I] DWORD to multiply with dwRight
524 * dwRight [I] DWORD to multiply with dwLeft
527 * The product of ftMultiplier and ftMultiplicand as a FILETIME.
529 LONGLONG WINAPI MAPI32_FtMulDwDw(DWORD dwLeft, DWORD dwRight)
531 return (LONGLONG)dwLeft * (LONGLONG)dwRight;
534 /**************************************************************************
535 * FtNegFt@8 (MAPI32.126)
540 * ft [I] FILETIME to negate
543 * The negation of ft.
545 LONGLONG WINAPI MAPI32_FtNegFt(FILETIME ft)
547 LONGLONG *p = (LONGLONG*)&ft;
552 /**************************************************************************
553 * UlAddRef@4 (MAPI32.128)
555 * Add a reference to an object.
558 * lpUnk [I] Object to add a reference to.
561 * The new reference count of the object, or 0 if lpUnk is NULL.
564 * See IUnknown_AddRef.
566 ULONG WINAPI UlAddRef(void *lpUnk)
568 TRACE("(%p)\n", lpUnk);
572 return IUnknown_AddRef((LPUNKNOWN)lpUnk);
575 /**************************************************************************
576 * UlRelease@4 (MAPI32.129)
578 * Remove a reference from an object.
581 * lpUnk [I] Object to remove reference from.
584 * The new reference count of the object, or 0 if lpUnk is NULL. If lpUnk is
585 * non-NULL and this function returns 0, the object pointed to by lpUnk has
589 * See IUnknown_Release.
591 ULONG WINAPI UlRelease(void *lpUnk)
593 TRACE("(%p)\n", lpUnk);
597 return IUnknown_Release((LPUNKNOWN)lpUnk);
600 /*************************************************************************
601 * OpenStreamOnFile@24 (MAPI32.147)
603 * Create a stream on a file.
606 * lpAlloc [I] Memory allocation function
607 * lpFree [I] Memory free function
608 * ulFlags [I] Flags controlling the opening process
609 * lpszPath [I] Path of file to create stream on
610 * lpszPrefix [I] Prefix of the temporary file name (if ulFlags includes SOF_UNIQUEFILENAME)
611 * lppStream [O] Destination for created stream
614 * Success: S_OK. lppStream contains the new stream object
615 * Failure: E_INVALIDARG if any parameter is invalid, or an HRESULT error code
616 * describing the error.
618 HRESULT WINAPI OpenStreamOnFile(LPALLOCATEBUFFER lpAlloc, LPFREEBUFFER lpFree,
619 ULONG ulFlags, LPWSTR lpszPath, LPWSTR lpszPrefix,
622 WCHAR szBuff[MAX_PATH];
623 DWORD dwMode = STGM_READWRITE, dwAttributes = 0;
626 TRACE("(%p,%p,0x%08lx,%s,%s,%p)\n", lpAlloc, lpFree, ulFlags,
627 debugstr_a((LPSTR)lpszPath), debugstr_a((LPSTR)lpszPrefix), lppStream);
632 if (ulFlags & SOF_UNIQUEFILENAME)
634 FIXME("Should generate a temporary name\n");
638 if (!lpszPath || !lppStream)
641 /* FIXME: Should probably munge mode and attributes, and should handle
642 * Unicode arguments (I assume MAPI_UNICODE is set in ulFlags if
643 * we are being passed Unicode strings; MSDN doesn't say).
644 * This implementation is just enough for Outlook97 to start.
646 MultiByteToWideChar(CP_ACP, 0, (LPSTR)lpszPath, -1, szBuff, MAX_PATH);
647 hRet = SHCreateStreamOnFileEx(szBuff, dwMode, dwAttributes, TRUE,
653 /*************************************************************************
654 * cmc_query_configuration (MAPI32.235)
656 * Retrieves the configuration information for the installed CMC
659 * session [I] MAPI session handle
660 * item [I] Enumerated variable that identifies which
661 * configuration information is being requested
662 * reference [O] Buffer where configuration information is written
663 * config_extensions[I/O] Path of file to create stream on
668 CMC_return_code WINAPI cmc_query_configuration(
669 CMC_session_id session,
671 CMC_buffer reference,
672 CMC_extension *config_extensions)
675 return CMC_E_NOT_SUPPORTED;