2 * MAPI Utility functions
4 * Copyright 2004 Jon Griffiths
5 * Copyright 2009 Owen Rudge for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(mapi
);
44 static const BYTE digitsToHex
[] = {
45 0,1,2,3,4,5,6,7,8,9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,10,11,12,13,14,15,
46 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
47 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,10,11,12,13,
50 MAPI_FUNCTIONS mapiFunctions
;
52 /**************************************************************************
53 * ScInitMapiUtil (MAPI32.33)
55 * Initialise Mapi utility functions.
58 * ulReserved [I] Reserved, pass 0.
61 * Success: S_OK. Mapi utility functions may be called.
62 * Failure: MAPI_E_INVALID_PARAMETER, if ulReserved is not 0.
65 * Your application does not need to call this function unless it does not
66 * call MAPIInitialize()/MAPIUninitialize().
68 SCODE WINAPI
ScInitMapiUtil(ULONG ulReserved
)
70 if (mapiFunctions
.ScInitMapiUtil
)
71 return mapiFunctions
.ScInitMapiUtil(ulReserved
);
73 FIXME("(0x%08x)stub!\n", ulReserved
);
75 return MAPI_E_INVALID_PARAMETER
;
79 /**************************************************************************
80 * DeinitMapiUtil (MAPI32.34)
82 * Uninitialise Mapi utility functions.
91 * Your application does not need to call this function unless it does not
92 * call MAPIInitialize()/MAPIUninitialize().
94 VOID WINAPI
DeinitMapiUtil(void)
96 if (mapiFunctions
.DeinitMapiUtil
)
97 mapiFunctions
.DeinitMapiUtil();
102 typedef LPVOID
*LPMAPIALLOCBUFFER
;
104 /**************************************************************************
105 * MAPIAllocateBuffer (MAPI32.12)
106 * MAPIAllocateBuffer@8 (MAPI32.13)
108 * Allocate a block of memory.
111 * cbSize [I] Size of the block to allocate in bytes
112 * lppBuffer [O] Destination for pointer to allocated memory
115 * Success: S_OK. *lppBuffer is filled with a pointer to a memory block of
116 * length cbSize bytes.
117 * Failure: MAPI_E_INVALID_PARAMETER, if lppBuffer is NULL.
118 * MAPI_E_NOT_ENOUGH_MEMORY, if the memory allocation fails.
121 * Memory allocated with this function should be freed with MAPIFreeBuffer().
122 * Further allocations of memory may be linked to the pointer returned using
123 * MAPIAllocateMore(). Linked allocations are freed when the initial pointer
126 SCODE WINAPI
MAPIAllocateBuffer(ULONG cbSize
, LPVOID
*lppBuffer
)
128 LPMAPIALLOCBUFFER lpBuff
;
130 TRACE("(%d,%p)\n", cbSize
, lppBuffer
);
132 if (mapiFunctions
.MAPIAllocateBuffer
)
133 return mapiFunctions
.MAPIAllocateBuffer(cbSize
, lppBuffer
);
138 lpBuff
= HeapAlloc(GetProcessHeap(), 0, cbSize
+ sizeof(*lpBuff
));
140 return MAPI_E_NOT_ENOUGH_MEMORY
;
142 TRACE("initial allocation:%p, returning %p\n", lpBuff
, lpBuff
+ 1);
148 /**************************************************************************
149 * MAPIAllocateMore (MAPI32.14)
150 * MAPIAllocateMore@12 (MAPI32.15)
152 * Allocate a block of memory linked to a previous allocation.
155 * cbSize [I] Size of the block to allocate in bytes
156 * lpOrig [I] Initial allocation to link to, from MAPIAllocateBuffer()
157 * lppBuffer [O] Destination for pointer to allocated memory
160 * Success: S_OK. *lppBuffer is filled with a pointer to a memory block of
161 * length cbSize bytes.
162 * Failure: MAPI_E_INVALID_PARAMETER, if lpOrig or lppBuffer is invalid.
163 * MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails.
166 * Memory allocated with this function and stored in *lppBuffer is freed
167 * when lpOrig is passed to MAPIFreeBuffer(). It should not be freed independently.
169 SCODE WINAPI
MAPIAllocateMore(ULONG cbSize
, LPVOID lpOrig
, LPVOID
*lppBuffer
)
171 LPMAPIALLOCBUFFER lpBuff
= lpOrig
;
173 TRACE("(%d,%p,%p)\n", cbSize
, lpOrig
, lppBuffer
);
175 if (mapiFunctions
.MAPIAllocateMore
)
176 return mapiFunctions
.MAPIAllocateMore(cbSize
, lpOrig
, lppBuffer
);
178 if (!lppBuffer
|| !lpBuff
|| !--lpBuff
)
181 /* Find the last allocation in the chain */
184 TRACE("linked:%p->%p\n", lpBuff
, *lpBuff
);
188 if (SUCCEEDED(MAPIAllocateBuffer(cbSize
, lppBuffer
)))
190 *lpBuff
= ((LPMAPIALLOCBUFFER
)*lppBuffer
) - 1;
191 TRACE("linking %p->%p\n", lpBuff
, *lpBuff
);
193 return *lppBuffer
? S_OK
: MAPI_E_NOT_ENOUGH_MEMORY
;
196 /**************************************************************************
197 * MAPIFreeBuffer (MAPI32.16)
198 * MAPIFreeBuffer@4 (MAPI32.17)
200 * Free a block of memory and any linked allocations associated with it.
203 * lpBuffer [I] Memory to free, returned from MAPIAllocateBuffer()
208 ULONG WINAPI
MAPIFreeBuffer(LPVOID lpBuffer
)
210 LPMAPIALLOCBUFFER lpBuff
= lpBuffer
;
212 TRACE("(%p)\n", lpBuffer
);
214 if (mapiFunctions
.MAPIFreeBuffer
)
215 return mapiFunctions
.MAPIFreeBuffer(lpBuffer
);
217 if (lpBuff
&& --lpBuff
)
221 LPVOID lpFree
= lpBuff
;
225 TRACE("linked:%p->%p, freeing %p\n", lpFree
, lpBuff
, lpFree
);
226 HeapFree(GetProcessHeap(), 0, lpFree
);
232 /**************************************************************************
233 * WrapProgress@20 (MAPI32.41)
235 HRESULT WINAPI
WrapProgress(PVOID unk1
, PVOID unk2
, PVOID unk3
, PVOID unk4
, PVOID unk5
)
237 /* Native does not implement this function */
238 return MAPI_E_NO_SUPPORT
;
241 /*************************************************************************
242 * HrThisThreadAdviseSink@8 (MAPI32.42)
244 * Ensure that an advise sink is only notified in its originating thread.
247 * lpSink [I] IMAPIAdviseSink interface to be protected
248 * lppNewSink [I] Destination for wrapper IMAPIAdviseSink interface
251 * Success: S_OK. *lppNewSink contains a new sink to use in place of lpSink.
252 * Failure: E_INVALIDARG, if any parameter is invalid.
254 HRESULT WINAPI
HrThisThreadAdviseSink(LPMAPIADVISESINK lpSink
, LPMAPIADVISESINK
* lppNewSink
)
256 if (mapiFunctions
.HrThisThreadAdviseSink
)
257 return mapiFunctions
.HrThisThreadAdviseSink(lpSink
, lppNewSink
);
259 FIXME("(%p,%p)semi-stub\n", lpSink
, lppNewSink
);
261 if (!lpSink
|| !lppNewSink
)
264 /* Don't wrap the sink for now, just copy it */
265 *lppNewSink
= lpSink
;
266 IMAPIAdviseSink_AddRef(lpSink
);
270 /*************************************************************************
271 * FBinFromHex (MAPI32.44)
273 * Create an array of binary data from a string.
276 * lpszHex [I] String to convert to binary data
277 * lpOut [O] Destination for resulting binary data
280 * Success: TRUE. lpOut contains the decoded binary data.
281 * Failure: FALSE, if lpszHex does not represent a binary string.
284 * - lpOut must be at least half the length of lpszHex in bytes.
285 * - Although the Mapi headers prototype this function as both
286 * Ascii and Unicode, there is only one (Ascii) implementation. This
287 * means that lpszHex is treated as an Ascii string (i.e. a single NUL
288 * character in the byte stream terminates the string).
290 BOOL WINAPI
FBinFromHex(LPWSTR lpszHex
, LPBYTE lpOut
)
292 LPSTR lpStr
= (LPSTR
)lpszHex
;
294 TRACE("(%p,%p)\n", lpszHex
, lpOut
);
298 if (lpStr
[0] < '0' || lpStr
[0] > 'f' || digitsToHex
[lpStr
[0] - '0'] == 0xff ||
299 lpStr
[1] < '0' || lpStr
[1] > 'f' || digitsToHex
[lpStr
[1] - '0'] == 0xff)
302 *lpOut
++ = (digitsToHex
[lpStr
[0] - '0'] << 4) | digitsToHex
[lpStr
[1] - '0'];
308 /*************************************************************************
309 * HexFromBin (MAPI32.45)
311 * Create a string from an array of binary data.
314 * lpHex [I] Binary data to convert to string
315 * iCount [I] Length of lpHex in bytes
316 * lpszOut [O] Destination for resulting hex string
322 * - lpszOut must be at least 2 * iCount + 1 bytes characters long.
323 * - Although the Mapi headers prototype this function as both
324 * Ascii and Unicode, there is only one (Ascii) implementation. This
325 * means that the resulting string is not properly NUL terminated
326 * if the caller expects it to be a Unicode string.
328 void WINAPI
HexFromBin(LPBYTE lpHex
, int iCount
, LPWSTR lpszOut
)
330 static const char hexDigits
[] = { "0123456789ABCDEF" };
331 LPSTR lpStr
= (LPSTR
)lpszOut
;
333 TRACE("(%p,%d,%p)\n", lpHex
, iCount
, lpszOut
);
337 *lpStr
++ = hexDigits
[*lpHex
>> 4];
338 *lpStr
++ = hexDigits
[*lpHex
& 0xf];
344 /*************************************************************************
345 * SwapPlong@8 (MAPI32.47)
347 * Swap the bytes in a ULONG array.
350 * lpData [O] Array to swap bytes in
351 * ulLen [I] Number of ULONG element to swap the bytes of
356 VOID WINAPI
SwapPlong(PULONG lpData
, ULONG ulLen
)
360 for (i
= 0; i
< ulLen
; i
++)
361 lpData
[i
] = RtlUlongByteSwap(lpData
[i
]);
364 /*************************************************************************
365 * SwapPword@8 (MAPI32.48)
367 * Swap the bytes in a USHORT array.
370 * lpData [O] Array to swap bytes in
371 * ulLen [I] Number of USHORT element to swap the bytes of
376 VOID WINAPI
SwapPword(PUSHORT lpData
, ULONG ulLen
)
380 for (i
= 0; i
< ulLen
; i
++)
381 lpData
[i
] = RtlUshortByteSwap(lpData
[i
]);
384 /**************************************************************************
385 * MNLS_lstrlenW@4 (MAPI32.62)
387 * Calculate the length of a Unicode string.
390 * lpszStr [I] String to calculate the length of
393 * The length of lpszStr in Unicode characters.
395 ULONG WINAPI
MNLS_lstrlenW(LPCWSTR lpszStr
)
397 TRACE("(%s)\n", debugstr_w(lpszStr
));
398 return strlenW(lpszStr
);
401 /*************************************************************************
402 * MNLS_lstrcmpW@8 (MAPI32.63)
404 * Compare two Unicode strings.
407 * lpszLeft [I] First string to compare
408 * lpszRight [I] Second string to compare
411 * An integer less than, equal to or greater than 0, indicating that
412 * lpszLeft is less than, the same, or greater than lpszRight.
414 INT WINAPI
MNLS_lstrcmpW(LPCWSTR lpszLeft
, LPCWSTR lpszRight
)
416 TRACE("(%s,%s)\n", debugstr_w(lpszLeft
), debugstr_w(lpszRight
));
417 return strcmpW(lpszLeft
, lpszRight
);
420 /*************************************************************************
421 * MNLS_lstrcpyW@8 (MAPI32.64)
423 * Copy a Unicode string to another string.
426 * lpszDest [O] Destination string
427 * lpszSrc [I] Source string
430 * The length lpszDest in Unicode characters.
432 ULONG WINAPI
MNLS_lstrcpyW(LPWSTR lpszDest
, LPCWSTR lpszSrc
)
436 TRACE("(%p,%s)\n", lpszDest
, debugstr_w(lpszSrc
));
437 len
= (strlenW(lpszSrc
) + 1) * sizeof(WCHAR
);
438 memcpy(lpszDest
, lpszSrc
, len
);
442 /*************************************************************************
443 * MNLS_CompareStringW@12 (MAPI32.65)
445 * Compare two Unicode strings.
448 * dwCp [I] Code page for the comparison
449 * lpszLeft [I] First string to compare
450 * lpszRight [I] Second string to compare
453 * CSTR_LESS_THAN, CSTR_EQUAL or CSTR_GREATER_THAN, indicating that
454 * lpszLeft is less than, the same, or greater than lpszRight.
456 INT WINAPI
MNLS_CompareStringW(DWORD dwCp
, LPCWSTR lpszLeft
, LPCWSTR lpszRight
)
460 TRACE("0x%08x,%s,%s\n", dwCp
, debugstr_w(lpszLeft
), debugstr_w(lpszRight
));
461 ret
= MNLS_lstrcmpW(lpszLeft
, lpszRight
);
462 return ret
< 0 ? CSTR_LESS_THAN
: ret
? CSTR_GREATER_THAN
: CSTR_EQUAL
;
465 /**************************************************************************
466 * FEqualNames@8 (MAPI32.72)
468 * Compare two Mapi names.
471 * lpName1 [I] First name to compare to lpName2
472 * lpName2 [I] Second name to compare to lpName1
475 * TRUE, if the names are the same,
478 BOOL WINAPI
FEqualNames(LPMAPINAMEID lpName1
, LPMAPINAMEID lpName2
)
480 TRACE("(%p,%p)\n", lpName1
, lpName2
);
482 if (!lpName1
|| !lpName2
||
483 !IsEqualGUID(lpName1
->lpguid
, lpName2
->lpguid
) ||
484 lpName1
->ulKind
!= lpName2
->ulKind
)
487 if (lpName1
->ulKind
== MNID_STRING
)
488 return !strcmpW(lpName1
->Kind
.lpwstrName
, lpName2
->Kind
.lpwstrName
);
490 return lpName1
->Kind
.lID
== lpName2
->Kind
.lID
;
493 /**************************************************************************
494 * IsBadBoundedStringPtr@8 (MAPI32.71)
496 * Determine if a string pointer is valid.
499 * lpszStr [I] String to check
500 * ulLen [I] Maximum length of lpszStr
503 * TRUE, if lpszStr is invalid or longer than ulLen,
506 BOOL WINAPI
IsBadBoundedStringPtr(LPCSTR lpszStr
, ULONG ulLen
)
508 if (!lpszStr
|| IsBadStringPtrA(lpszStr
, -1) || strlen(lpszStr
) >= ulLen
)
513 /**************************************************************************
514 * FtAddFt@16 (MAPI32.121)
516 * Add two FILETIME's together.
519 * ftLeft [I] FILETIME to add to ftRight
520 * ftRight [I] FILETIME to add to ftLeft
523 * The sum of ftLeft and ftRight
525 LONGLONG WINAPI
MAPI32_FtAddFt(FILETIME ftLeft
, FILETIME ftRight
)
527 LONGLONG
*pl
= (LONGLONG
*)&ftLeft
, *pr
= (LONGLONG
*)&ftRight
;
532 /**************************************************************************
533 * FtSubFt@16 (MAPI32.123)
535 * Subtract two FILETIME's together.
538 * ftLeft [I] Initial FILETIME
539 * ftRight [I] FILETIME to subtract from ftLeft
542 * The remainder after ftRight is subtracted from ftLeft.
544 LONGLONG WINAPI
MAPI32_FtSubFt(FILETIME ftLeft
, FILETIME ftRight
)
546 LONGLONG
*pl
= (LONGLONG
*)&ftLeft
, *pr
= (LONGLONG
*)&ftRight
;
551 /**************************************************************************
552 * FtMulDw@12 (MAPI32.124)
554 * Multiply a FILETIME by a DWORD.
557 * dwLeft [I] DWORD to multiply with ftRight
558 * ftRight [I] FILETIME to multiply with dwLeft
561 * The product of dwLeft and ftRight
563 LONGLONG WINAPI
MAPI32_FtMulDw(DWORD dwLeft
, FILETIME ftRight
)
565 LONGLONG
*pr
= (LONGLONG
*)&ftRight
;
567 return (LONGLONG
)dwLeft
* (*pr
);
570 /**************************************************************************
571 * FtMulDwDw@8 (MAPI32.125)
573 * Multiply two DWORD, giving the result as a FILETIME.
576 * dwLeft [I] DWORD to multiply with dwRight
577 * dwRight [I] DWORD to multiply with dwLeft
580 * The product of ftMultiplier and ftMultiplicand as a FILETIME.
582 LONGLONG WINAPI
MAPI32_FtMulDwDw(DWORD dwLeft
, DWORD dwRight
)
584 return (LONGLONG
)dwLeft
* (LONGLONG
)dwRight
;
587 /**************************************************************************
588 * FtNegFt@8 (MAPI32.126)
593 * ft [I] FILETIME to negate
596 * The negation of ft.
598 LONGLONG WINAPI
MAPI32_FtNegFt(FILETIME ft
)
600 LONGLONG
*p
= (LONGLONG
*)&ft
;
605 /**************************************************************************
606 * UlAddRef@4 (MAPI32.128)
608 * Add a reference to an object.
611 * lpUnk [I] Object to add a reference to.
614 * The new reference count of the object, or 0 if lpUnk is NULL.
617 * See IUnknown_AddRef.
619 ULONG WINAPI
UlAddRef(void *lpUnk
)
621 TRACE("(%p)\n", lpUnk
);
625 return IUnknown_AddRef((LPUNKNOWN
)lpUnk
);
628 /**************************************************************************
629 * UlRelease@4 (MAPI32.129)
631 * Remove a reference from an object.
634 * lpUnk [I] Object to remove reference from.
637 * The new reference count of the object, or 0 if lpUnk is NULL. If lpUnk is
638 * non-NULL and this function returns 0, the object pointed to by lpUnk has
642 * See IUnknown_Release.
644 ULONG WINAPI
UlRelease(void *lpUnk
)
646 TRACE("(%p)\n", lpUnk
);
650 return IUnknown_Release((LPUNKNOWN
)lpUnk
);
653 /**************************************************************************
654 * UFromSz@4 (MAPI32.133)
656 * Read an integer from a string
659 * lpszStr [I] String to read the integer from.
662 * Success: The integer read from lpszStr.
663 * Failure: 0, if the first character in lpszStr is not 0-9.
666 * This function does not accept whitespace and stops at the first non-digit
669 UINT WINAPI
UFromSz(LPCSTR lpszStr
)
673 TRACE("(%s)\n", debugstr_a(lpszStr
));
677 while (*lpszStr
>= '0' && *lpszStr
<= '9')
679 ulRet
= ulRet
* 10 + (*lpszStr
- '0');
686 /*************************************************************************
687 * OpenStreamOnFile@24 (MAPI32.147)
689 * Create a stream on a file.
692 * lpAlloc [I] Memory allocation function
693 * lpFree [I] Memory free function
694 * ulFlags [I] Flags controlling the opening process
695 * lpszPath [I] Path of file to create stream on
696 * lpszPrefix [I] Prefix of the temporary file name (if ulFlags includes SOF_UNIQUEFILENAME)
697 * lppStream [O] Destination for created stream
700 * Success: S_OK. lppStream contains the new stream object
701 * Failure: E_INVALIDARG if any parameter is invalid, or an HRESULT error code
702 * describing the error.
704 HRESULT WINAPI
OpenStreamOnFile(LPALLOCATEBUFFER lpAlloc
, LPFREEBUFFER lpFree
,
705 ULONG ulFlags
, LPWSTR lpszPath
, LPWSTR lpszPrefix
,
708 WCHAR szBuff
[MAX_PATH
];
709 DWORD dwMode
= STGM_READWRITE
, dwAttributes
= 0;
712 TRACE("(%p,%p,0x%08x,%s,%s,%p)\n", lpAlloc
, lpFree
, ulFlags
,
713 debugstr_a((LPSTR
)lpszPath
), debugstr_a((LPSTR
)lpszPrefix
), lppStream
);
715 if (mapiFunctions
.OpenStreamOnFile
)
716 return mapiFunctions
.OpenStreamOnFile(lpAlloc
, lpFree
, ulFlags
, lpszPath
, lpszPrefix
, lppStream
);
721 if (ulFlags
& SOF_UNIQUEFILENAME
)
723 FIXME("Should generate a temporary name\n");
727 if (!lpszPath
|| !lppStream
)
730 /* FIXME: Should probably munge mode and attributes, and should handle
731 * Unicode arguments (I assume MAPI_UNICODE is set in ulFlags if
732 * we are being passed Unicode strings; MSDN doesn't say).
733 * This implementation is just enough for Outlook97 to start.
735 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)lpszPath
, -1, szBuff
, MAX_PATH
);
736 hRet
= SHCreateStreamOnFileEx(szBuff
, dwMode
, dwAttributes
, TRUE
,
741 /*************************************************************************
742 * UlFromSzHex@4 (MAPI32.155)
744 * Read an integer from a hexadecimal string.
747 * lpSzHex [I] String containing the hexadecimal number to read
750 * Success: The number represented by lpszHex.
751 * Failure: 0, if lpszHex does not contain a hex string.
754 * This function does not accept whitespace and stops at the first non-hex
757 ULONG WINAPI
UlFromSzHex(LPCWSTR lpszHex
)
759 LPCSTR lpStr
= (LPCSTR
)lpszHex
;
762 TRACE("(%s)\n", debugstr_a(lpStr
));
766 if (lpStr
[0] < '0' || lpStr
[0] > 'f' || digitsToHex
[lpStr
[0] - '0'] == 0xff ||
767 lpStr
[1] < '0' || lpStr
[1] > 'f' || digitsToHex
[lpStr
[1] - '0'] == 0xff)
770 ulRet
= ulRet
* 16 + ((digitsToHex
[lpStr
[0] - '0'] << 4) | digitsToHex
[lpStr
[1] - '0']);
776 /************************************************************************
777 * FBadEntryList@4 (MAPI32.190)
779 * Determine is an entry list is invalid.
782 * lpEntryList [I] List to check
785 * TRUE, if lpEntryList is invalid,
788 BOOL WINAPI
FBadEntryList(LPENTRYLIST lpEntryList
)
792 if (IsBadReadPtr(lpEntryList
, sizeof(*lpEntryList
)) ||
793 IsBadReadPtr(lpEntryList
->lpbin
,
794 lpEntryList
->cValues
* sizeof(*lpEntryList
->lpbin
)))
797 for (i
= 0; i
< lpEntryList
->cValues
; i
++)
798 if(IsBadReadPtr(lpEntryList
->lpbin
[i
].lpb
, lpEntryList
->lpbin
[i
].cb
))
804 /*************************************************************************
805 * CbOfEncoded@4 (MAPI32.207)
807 * Return the length of an encoded string.
810 * lpSzEnc [I] Encoded string to get the length of.
813 * The length of the encoded string in bytes.
815 ULONG WINAPI
CbOfEncoded(LPCSTR lpszEnc
)
819 TRACE("(%s)\n", debugstr_a(lpszEnc
));
822 ulRet
= (((strlen(lpszEnc
) | 3) >> 2) + 1) * 3;
826 /*************************************************************************
827 * cmc_query_configuration (MAPI32.235)
829 * Retrieves the configuration information for the installed CMC
832 * session [I] MAPI session handle
833 * item [I] Enumerated variable that identifies which
834 * configuration information is being requested
835 * reference [O] Buffer where configuration information is written
836 * config_extensions[I/O] Path of file to create stream on
841 CMC_return_code WINAPI
cmc_query_configuration(
842 CMC_session_id session
,
844 CMC_buffer reference
,
845 CMC_extension
*config_extensions
)
848 return CMC_E_NOT_SUPPORTED
;
851 /**************************************************************************
852 * FGetComponentPath (MAPI32.254)
853 * FGetComponentPath@20 (MAPI32.255)
855 * Return the installed component path, usually to the private mapi32.dll.
858 * component [I] Component ID
859 * qualifier [I] Application LCID
860 * dll_path [O] returned component path
861 * dll_path_length [I] component path length
862 * install [I] install mode
869 * Previously documented in Q229700 "How to locate the correct path
870 * to the Mapisvc.inf file in Microsoft Outlook".
872 BOOL WINAPI
FGetComponentPath(LPCSTR component
, LPCSTR qualifier
, LPSTR dll_path
,
873 DWORD dll_path_length
, BOOL install
)
878 TRACE("%s %s %p %u %d\n", component
, qualifier
, dll_path
, dll_path_length
, install
);
880 if (mapiFunctions
.FGetComponentPath
)
881 return mapiFunctions
.FGetComponentPath(component
, qualifier
, dll_path
, dll_path_length
, install
);
885 hmsi
= LoadLibraryA("msi.dll");
888 UINT (WINAPI
*pMsiProvideQualifiedComponentA
)(LPCSTR
, LPCSTR
, DWORD
, LPSTR
, LPDWORD
);
890 pMsiProvideQualifiedComponentA
= (void *)GetProcAddress(hmsi
, "MsiProvideQualifiedComponentA");
891 if (pMsiProvideQualifiedComponentA
)
893 static const char * const fmt
[] = { "%d\\NT", "%d\\95", "%d" };
897 for (i
= 0; i
< sizeof(fmt
)/sizeof(fmt
[0]); i
++)
899 /* FIXME: what's the correct behaviour here? */
900 if (!qualifier
|| qualifier
== lcid_ver
)
902 sprintf(lcid_ver
, fmt
[i
], GetUserDefaultUILanguage());
903 qualifier
= lcid_ver
;
906 if (pMsiProvideQualifiedComponentA(component
, qualifier
,
907 install
? INSTALLMODE_DEFAULT
: INSTALLMODE_EXISTING
,
908 dll_path
, &dll_path_length
) == ERROR_SUCCESS
)
914 if (qualifier
!= lcid_ver
) break;
922 /**************************************************************************
923 * HrQueryAllRows (MAPI32.75)
925 HRESULT WINAPI
HrQueryAllRows(LPMAPITABLE lpTable
, LPSPropTagArray lpPropTags
,
926 LPSRestriction lpRestriction
, LPSSortOrderSet lpSortOrderSet
,
927 LONG crowsMax
, LPSRowSet
*lppRows
)
929 if (mapiFunctions
.HrQueryAllRows
)
930 return mapiFunctions
.HrQueryAllRows(lpTable
, lpPropTags
, lpRestriction
, lpSortOrderSet
, crowsMax
, lppRows
);
932 FIXME("(%p, %p, %p, %p, %d, %p): stub\n", lpTable
, lpPropTags
, lpRestriction
, lpSortOrderSet
, crowsMax
, lppRows
);
934 return MAPI_E_CALL_FAILED
;
937 /**************************************************************************
938 * WrapCompressedRTFStream (MAPI32.186)
940 HRESULT WINAPI
WrapCompressedRTFStream(LPSTREAM compressed
, ULONG flags
, LPSTREAM
*uncompressed
)
942 if (mapiFunctions
.WrapCompressedRTFStream
)
943 return mapiFunctions
.WrapCompressedRTFStream(compressed
, flags
, uncompressed
);
945 FIXME("(%p, 0x%08x, %p): stub\n", compressed
, flags
, uncompressed
);
946 return MAPI_E_NO_SUPPORT
;
949 static HMODULE mapi_provider
;
950 static HMODULE mapi_ex_provider
;
952 /**************************************************************************
955 * Attempts to load a MAPI provider from the specified registry key.
957 * Returns a handle to the loaded module in `mapi_provider' if successful.
959 static void load_mapi_provider(HKEY hkeyMail
, LPCWSTR valueName
, HMODULE
*mapi_provider
)
961 static const WCHAR mapi32_dll
[] = {'m','a','p','i','3','2','.','d','l','l',0 };
963 DWORD dwType
, dwLen
= 0;
966 /* Check if we have a value set for DLLPath */
967 if ((RegQueryValueExW(hkeyMail
, valueName
, NULL
, &dwType
, NULL
, &dwLen
) == ERROR_SUCCESS
) &&
968 ((dwType
== REG_SZ
) || (dwType
== REG_EXPAND_SZ
)) && (dwLen
> 0))
970 dllPath
= HeapAlloc(GetProcessHeap(), 0, dwLen
);
974 RegQueryValueExW(hkeyMail
, valueName
, NULL
, NULL
, (LPBYTE
)dllPath
, &dwLen
);
976 /* Check that this value doesn't refer to mapi32.dll (eg, as Outlook does) */
977 if (lstrcmpiW(dllPath
, mapi32_dll
) != 0)
979 if (dwType
== REG_EXPAND_SZ
)
982 LPWSTR dllPathExpanded
;
984 /* Expand the path if necessary */
985 dwExpandLen
= ExpandEnvironmentStringsW(dllPath
, NULL
, 0);
986 dllPathExpanded
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * dwExpandLen
+ 1);
990 ExpandEnvironmentStringsW(dllPath
, dllPathExpanded
, dwExpandLen
+ 1);
992 HeapFree(GetProcessHeap(), 0, dllPath
);
993 dllPath
= dllPathExpanded
;
998 TRACE("loading %s\n", debugstr_w(dllPath
));
999 *mapi_provider
= LoadLibraryW(dllPath
);
1002 HeapFree(GetProcessHeap(), 0, dllPath
);
1007 /**************************************************************************
1008 * load_mapi_providers
1010 * Scans the registry for MAPI providers and attempts to load a Simple and
1011 * Extended MAPI library.
1013 * Returns TRUE if at least one library loaded, FALSE otherwise.
1015 void load_mapi_providers(void)
1017 static const WCHAR regkey_mail
[] = {
1018 'S','o','f','t','w','a','r','e','\\','C','l','i','e','n','t','s','\\',
1019 'M','a','i','l',0 };
1021 static const WCHAR regkey_dllpath
[] = {'D','L','L','P','a','t','h',0 };
1022 static const WCHAR regkey_dllpath_ex
[] = {'D','L','L','P','a','t','h','E','x',0 };
1023 static const WCHAR regkey_backslash
[] = { '\\', 0 };
1026 DWORD dwType
, dwLen
= 0;
1027 LPWSTR appName
= NULL
, appKey
= NULL
;
1031 /* Open the Mail key */
1032 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, regkey_mail
, 0, KEY_READ
, &hkeyMail
) != ERROR_SUCCESS
)
1035 /* Check if we have a default value set, and the length of it */
1036 if ((RegQueryValueExW(hkeyMail
, NULL
, NULL
, &dwType
, NULL
, &dwLen
) != ERROR_SUCCESS
) ||
1037 !((dwType
== REG_SZ
) || (dwType
== REG_EXPAND_SZ
)) || (dwLen
== 0))
1040 appName
= HeapAlloc(GetProcessHeap(), 0, dwLen
);
1045 /* Get the value, and get the path to the app key */
1046 RegQueryValueExW(hkeyMail
, NULL
, NULL
, NULL
, (LPBYTE
)appName
, &dwLen
);
1048 TRACE("appName: %s\n", debugstr_w(appName
));
1050 appKey
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * (lstrlenW(regkey_mail
) +
1051 lstrlenW(regkey_backslash
) + lstrlenW(appName
) + 1));
1056 lstrcpyW(appKey
, regkey_mail
);
1057 lstrcatW(appKey
, regkey_backslash
);
1058 lstrcatW(appKey
, appName
);
1060 RegCloseKey(hkeyMail
);
1062 TRACE("appKey: %s\n", debugstr_w(appKey
));
1064 /* Open the app's key */
1065 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, appKey
, 0, KEY_READ
, &hkeyMail
) != ERROR_SUCCESS
)
1068 /* Try to load the providers */
1069 load_mapi_provider(hkeyMail
, regkey_dllpath
, &mapi_provider
);
1070 load_mapi_provider(hkeyMail
, regkey_dllpath_ex
, &mapi_ex_provider
);
1072 /* Now try to load our function pointers */
1073 ZeroMemory(&mapiFunctions
, sizeof(mapiFunctions
));
1075 /* Simple MAPI functions */
1078 mapiFunctions
.MAPIAddress
= (void*) GetProcAddress(mapi_provider
, "MAPIAddress");
1079 mapiFunctions
.MAPIDeleteMail
= (void*) GetProcAddress(mapi_provider
, "MAPIDeleteMail");
1080 mapiFunctions
.MAPIDetails
= (void*) GetProcAddress(mapi_provider
, "MAPIDetails");
1081 mapiFunctions
.MAPIFindNext
= (void*) GetProcAddress(mapi_provider
, "MAPIFindNext");
1082 mapiFunctions
.MAPILogoff
= (void*) GetProcAddress(mapi_provider
, "MAPILogoff");
1083 mapiFunctions
.MAPILogon
= (void*) GetProcAddress(mapi_provider
, "MAPILogon");
1084 mapiFunctions
.MAPIReadMail
= (void*) GetProcAddress(mapi_provider
, "MAPIReadMail");
1085 mapiFunctions
.MAPIResolveName
= (void*) GetProcAddress(mapi_provider
, "MAPIResolveName");
1086 mapiFunctions
.MAPISaveMail
= (void*) GetProcAddress(mapi_provider
, "MAPISaveMail");
1087 mapiFunctions
.MAPISendDocuments
= (void*) GetProcAddress(mapi_provider
, "MAPISendDocuments");
1088 mapiFunctions
.MAPISendMail
= (void*) GetProcAddress(mapi_provider
, "MAPISendMail");
1089 mapiFunctions
.MAPISendMailW
= (void*) GetProcAddress(mapi_provider
, "MAPISendMailW");
1092 /* Extended MAPI functions */
1093 if (mapi_ex_provider
)
1095 mapiFunctions
.MAPIInitialize
= (void*) GetProcAddress(mapi_ex_provider
, "MAPIInitialize");
1096 mapiFunctions
.MAPILogonEx
= (void*) GetProcAddress(mapi_ex_provider
, "MAPILogonEx");
1097 mapiFunctions
.MAPIUninitialize
= (void*) GetProcAddress(mapi_ex_provider
, "MAPIUninitialize");
1099 mapiFunctions
.DeinitMapiUtil
= (void*) GetProcAddress(mapi_ex_provider
, "DeinitMapiUtil@0");
1100 mapiFunctions
.DllCanUnloadNow
= (void*) GetProcAddress(mapi_ex_provider
, "DllCanUnloadNow");
1101 mapiFunctions
.DllGetClassObject
= (void*) GetProcAddress(mapi_ex_provider
, "DllGetClassObject");
1102 mapiFunctions
.FGetComponentPath
= (void*) GetProcAddress(mapi_ex_provider
, "FGetComponentPath");
1103 mapiFunctions
.HrThisThreadAdviseSink
= (void*) GetProcAddress(mapi_ex_provider
, "HrThisThreadAdviseSink@8");
1104 mapiFunctions
.HrQueryAllRows
= (void*) GetProcAddress(mapi_ex_provider
, "HrQueryAllRows@24");
1105 mapiFunctions
.MAPIAdminProfiles
= (void*) GetProcAddress(mapi_ex_provider
, "MAPIAdminProfiles");
1106 mapiFunctions
.MAPIAllocateBuffer
= (void*) GetProcAddress(mapi_ex_provider
, "MAPIAllocateBuffer");
1107 mapiFunctions
.MAPIAllocateMore
= (void*) GetProcAddress(mapi_ex_provider
, "MAPIAllocateMore");
1108 mapiFunctions
.MAPIFreeBuffer
= (void*) GetProcAddress(mapi_ex_provider
, "MAPIFreeBuffer");
1109 mapiFunctions
.MAPIGetDefaultMalloc
= (void*) GetProcAddress(mapi_ex_provider
, "MAPIGetDefaultMalloc@0");
1110 mapiFunctions
.MAPIOpenLocalFormContainer
= (void *) GetProcAddress(mapi_ex_provider
, "MAPIOpenLocalFormContainer");
1111 mapiFunctions
.OpenStreamOnFile
= (void*) GetProcAddress(mapi_ex_provider
, "OpenStreamOnFile@24");
1112 mapiFunctions
.ScInitMapiUtil
= (void*) GetProcAddress(mapi_ex_provider
, "ScInitMapiUtil@4");
1113 mapiFunctions
.WrapCompressedRTFStream
= (void*) GetProcAddress(mapi_ex_provider
, "WrapCompressedRTFStream@12");
1117 RegCloseKey(hkeyMail
);
1118 HeapFree(GetProcessHeap(), 0, appKey
);
1119 HeapFree(GetProcessHeap(), 0, appName
);
1122 /**************************************************************************
1123 * unload_mapi_providers
1125 * Unloads any loaded MAPI libraries.
1127 void unload_mapi_providers(void)
1131 FreeLibrary(mapi_provider
);
1132 FreeLibrary(mapi_ex_provider
);