Only stop writing a volume label if we found a non writable fat
[wine.git] / dlls / mapi32 / util.c
blobbf683e0205a113002f68e692b06fff7050497b96
1 /*
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
21 #include <stdarg.h>
23 #define COBJMACROS
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winuser.h"
30 #include "winerror.h"
31 #include "winternl.h"
32 #include "objbase.h"
33 #include "shlwapi.h"
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36 #include "mapival.h"
37 #include "xcmc.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(mapi);
41 static const BYTE digitsToHex[] = {
42 0,1,2,3,4,5,6,7,8,9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,10,11,12,13,14,15,
43 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
44 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,10,11,12,13,
45 14,15 };
47 /**************************************************************************
48 * ScInitMapiUtil (MAPI32.33)
50 * Initialise Mapi utility functions.
52 * PARAMS
53 * ulReserved [I] Reserved, pass 0.
55 * RETURNS
56 * Success: S_OK. Mapi utility functions may be called.
57 * Failure: MAPI_E_INVALID_PARAMETER, if ulReserved is not 0.
59 * NOTES
60 * Your application does not need to call this function unless it does not
61 * call MAPIInitialize()/MAPIUninitialize().
63 SCODE WINAPI ScInitMapiUtil(ULONG ulReserved)
65 FIXME("(0x%08lx)stub!\n", ulReserved);
66 if (ulReserved)
67 return MAPI_E_INVALID_PARAMETER;
68 return S_OK;
71 /**************************************************************************
72 * DeinitMapiUtil (MAPI32.34)
74 * Uninitialise Mapi utility functions.
76 * PARAMS
77 * None.
79 * RETURNS
80 * Nothing.
82 * NOTES
83 * Your application does not need to call this function unless it does not
84 * call MAPIInitialize()/MAPIUninitialize().
86 VOID WINAPI DeinitMapiUtil(void)
88 FIXME("()stub!\n");
91 typedef LPVOID *LPMAPIALLOCBUFFER;
93 /**************************************************************************
94 * MAPIAllocateBuffer (MAPI32.12)
95 * MAPIAllocateBuffer@8 (MAPI32.13)
97 * Allocate a block of memory.
99 * PARAMS
100 * cbSize [I] Size of the block to allocate in bytes
101 * lppBuffer [O] Destination for pointer to allocated memory
103 * RETURNS
104 * Success: S_OK. *lppBuffer is filled with a pointer to a memory block of
105 * length cbSize bytes.
106 * Failure: MAPI_E_INVALID_PARAMETER, if lppBuffer is NULL.
107 * MAPI_E_NOT_ENOUGH_MEMORY, if the memory allocation fails.
109 * NOTES
110 * Memory allocated with this function should be freed with MAPIFreeBuffer().
111 * Further allocations of memory may be linked to the pointer returned using
112 * MAPIAllocateMore(). Linked allocations are freed when the initial pointer
113 * is feed.
115 SCODE WINAPI MAPIAllocateBuffer(ULONG cbSize, LPVOID *lppBuffer)
117 LPMAPIALLOCBUFFER lpBuff;
119 TRACE("(%ld,%p)\n", cbSize, lppBuffer);
121 if (!lppBuffer)
122 return E_INVALIDARG;
124 lpBuff = (LPMAPIALLOCBUFFER)HeapAlloc(GetProcessHeap(), 0, cbSize + sizeof(*lpBuff));
125 if (!lpBuff)
126 return MAPI_E_NOT_ENOUGH_MEMORY;
128 TRACE("initial allocation:%p, returning %p\n", lpBuff, lpBuff + 1);
129 *lpBuff++ = NULL;
130 *lppBuffer = lpBuff;
131 return S_OK;
134 /**************************************************************************
135 * MAPIAllocateMore (MAPI32.14)
136 * MAPIAllocateMore@12 (MAPI32.15)
138 * Allocate a block of memory linked to a previous allocation.
140 * PARAMS
141 * cbSize [I] Size of the block to allocate in bytes
142 * lpOrig [I] Initial allocation to link to, from MAPIAllocateBuffer()
143 * lppBuffer [O] Destination for pointer to allocated memory
145 * RETURNS
146 * Success: S_OK. *lppBuffer is filled with a pointer to a memory block of
147 * length cbSize bytes.
148 * Failure: MAPI_E_INVALID_PARAMETER, if lpOrig or lppBuffer is invalid.
149 * MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails.
151 * NOTES
152 * Memory allocated with this function and stored in *lppBuffer is freed
153 * when lpOrig is passed to MAPIFreeBuffer(). It should not be freed independently.
155 SCODE WINAPI MAPIAllocateMore(ULONG cbSize, LPVOID lpOrig, LPVOID *lppBuffer)
157 LPMAPIALLOCBUFFER lpBuff = lpOrig;
159 TRACE("(%ld,%p,%p)\n", cbSize, lpOrig, lppBuffer);
161 if (!lppBuffer || !lpBuff || !--lpBuff)
162 return E_INVALIDARG;
164 /* Find the last allocation in the chain */
165 while (*lpBuff)
167 TRACE("linked:%p->%p\n", lpBuff, *lpBuff);
168 lpBuff = *lpBuff;
171 if (SUCCEEDED(MAPIAllocateBuffer(cbSize, lppBuffer)))
173 *lpBuff = ((LPMAPIALLOCBUFFER)*lppBuffer) - 1;
174 TRACE("linking %p->%p\n", lpBuff, *lpBuff);
176 return *lppBuffer ? S_OK : MAPI_E_NOT_ENOUGH_MEMORY;
179 /**************************************************************************
180 * MAPIFreeBuffer (MAPI32.16)
181 * MAPIFreeBuffer@4 (MAPI32.17)
183 * Free a block of memory and any linked allocations associated with it.
185 * PARAMS
186 * lpBuffer [I] Memory to free, returned from MAPIAllocateBuffer()
188 * RETURNS
189 * S_OK.
191 ULONG WINAPI MAPIFreeBuffer(LPVOID lpBuffer)
193 LPMAPIALLOCBUFFER lpBuff = lpBuffer;
195 TRACE("(%p)\n", lpBuffer);
197 if (lpBuff && --lpBuff)
199 while (lpBuff)
201 LPVOID lpFree = lpBuff;
203 lpBuff = *lpBuff;
205 TRACE("linked:%p->%p, freeing %p\n", lpFree, lpBuff, lpFree);
206 HeapFree(GetProcessHeap(), 0, lpFree);
209 return S_OK;
212 /**************************************************************************
213 * WrapProgress@20 (MAPI32.41)
215 HRESULT WINAPI WrapProgress(PVOID unk1, PVOID unk2, PVOID unk3, PVOID unk4, PVOID unk5)
217 /* Native does not implement this function */
218 return MAPI_E_NO_SUPPORT;
221 /*************************************************************************
222 * HrThisThreadAdviseSink@8 (MAPI32.42)
224 * Ensure that an advise sink is only notified in its originating thread.
226 * PARAMS
227 * lpSink [I] IMAPIAdviseSink interface to be protected
228 * lppNewSink [I] Destination for wrapper IMAPIAdviseSink interface
230 * RETURNS
231 * Success: S_OK. *lppNewSink contains a new sink to use in place of lpSink.
232 * Failure: E_INVALIDARG, if any parameter is invalid.
234 HRESULT WINAPI HrThisThreadAdviseSink(LPMAPIADVISESINK lpSink, LPMAPIADVISESINK* lppNewSink)
236 FIXME("(%p,%p)semi-stub\n", lpSink, lppNewSink);
238 if (!lpSink || !lppNewSink)
239 return E_INVALIDARG;
241 /* Don't wrap the sink for now, just copy it */
242 *lppNewSink = lpSink;
243 IMAPIAdviseSink_AddRef(lpSink);
244 return S_OK;
247 /*************************************************************************
248 * FBinFromHex (MAPI32.44)
250 * Create an array of binary data from a string.
252 * PARAMS
253 * lpszHex [I] String to convert to binary data
254 * lpOut [O] Destination for resulting binary data
256 * RETURNS
257 * Success: TRUE. lpOut contains the decoded binary data.
258 * Failure: FALSE, if lpszHex does not represent a binary string.
260 * NOTES
261 * - lpOut must be at least half the length of lpszHex in bytes.
262 * - Although the Mapi headers prototype this function as both
263 * Ascii and Unicode, there is only one (Ascii) implementation. This
264 * means that lpszHex is treated as an Ascii string (i.e. a single NUL
265 * character in the byte stream terminates the string).
267 BOOL WINAPI FBinFromHex(LPWSTR lpszHex, LPBYTE lpOut)
269 LPSTR lpStr = (LPSTR)lpszHex;
271 TRACE("(%p,%p)\n", lpszHex, lpOut);
273 while (*lpStr)
275 if (lpStr[0] < '0' || lpStr[0] > 'f' || digitsToHex[lpStr[0] - '0'] == 0xff ||
276 lpStr[1] < '0' || lpStr[1] > 'f' || digitsToHex[lpStr[1] - '0'] == 0xff)
277 return FALSE;
279 *lpOut++ = (digitsToHex[lpStr[0] - '0'] << 4) | digitsToHex[lpStr[1] - '0'];
280 lpStr += 2;
282 return TRUE;
285 /*************************************************************************
286 * HexFromBin (MAPI32.45)
288 * Create a string from an array of binary data.
290 * PARAMS
291 * lpHex [I] Binary data to convert to string
292 * iCount [I] Length of lpHex in bytes
293 * lpszOut [O] Destination for resulting hex string
295 * RETURNS
296 * Nothing.
298 * NOTES
299 * - lpszOut must be at least 2 * iCount + 1 bytes characters long.
300 * - Although the Mapi headers prototype this function as both
301 * Ascii and Unicode, there is only one (Ascii) implementation. This
302 * means that the resulting string is not properly NUL terminated
303 * if the caller expects it to be a Unicode string.
305 void WINAPI HexFromBin(LPBYTE lpHex, int iCount, LPWSTR lpszOut)
307 static const char hexDigits[] = { "0123456789ABCDEF" };
308 LPSTR lpStr = (LPSTR)lpszOut;
310 TRACE("(%p,%d,%p)\n", lpHex, iCount, lpszOut);
312 while (iCount-- > 0)
314 *lpStr++ = hexDigits[*lpHex >> 4];
315 *lpStr++ = hexDigits[*lpHex & 0xf];
316 lpHex++;
318 *lpStr = '\0';
321 /*************************************************************************
322 * SwapPlong@8 (MAPI32.47)
324 * Swap the bytes in a ULONG array.
326 * PARAMS
327 * lpData [O] Array to swap bytes in
328 * ulLen [I] Number of ULONG element to swap the bytes of
330 * RETURNS
331 * Nothing.
333 VOID WINAPI SwapPlong(PULONG lpData, ULONG ulLen)
335 ULONG i;
337 for (i = 0; i < ulLen; i++)
338 lpData[i] = RtlUlongByteSwap(lpData[i]);
341 /*************************************************************************
342 * SwapPword@8 (MAPI32.48)
344 * Swap the bytes in a USHORT array.
346 * PARAMS
347 * lpData [O] Array to swap bytes in
348 * ulLen [I] Number of USHORT element to swap the bytes of
350 * RETURNS
351 * Nothing.
353 VOID WINAPI SwapPword(PUSHORT lpData, ULONG ulLen)
355 ULONG i;
357 for (i = 0; i < ulLen; i++)
358 lpData[i] = RtlUshortByteSwap(lpData[i]);
361 /**************************************************************************
362 * MNLS_lstrlenW@4 (MAPI32.62)
364 * Calculate the length of a Unicode string.
366 * PARAMS
367 * lpszStr [I] String to calculate the length of
369 * RETURNS
370 * The length of lpszStr in Unicode characters.
372 ULONG WINAPI MNLS_lstrlenW(LPCWSTR lpszStr)
374 TRACE("(%s)\n", debugstr_w(lpszStr));
375 return strlenW(lpszStr);
378 /*************************************************************************
379 * MNLS_lstrcmpW@8 (MAPI32.63)
381 * Compare two Unicode strings.
383 * PARAMS
384 * lpszLeft [I] First string to compare
385 * lpszRight [I] Second string to compare
387 * RETURNS
388 * An integer less than, equal to or greater than 0, indicating that
389 * lpszLeft is less than, the same, or greater than lpszRight.
391 INT WINAPI MNLS_lstrcmpW(LPCWSTR lpszLeft, LPCWSTR lpszRight)
393 TRACE("(%s,%s)\n", debugstr_w(lpszLeft), debugstr_w(lpszRight));
394 return strcmpW(lpszLeft, lpszRight);
397 /*************************************************************************
398 * MNLS_lstrcpyW@8 (MAPI32.64)
400 * Copy a Unicode string to another string.
402 * PARAMS
403 * lpszDest [O] Destination string
404 * lpszSrc [I] Source string
406 * RETURNS
407 * The length lpszDest in Unicode characters.
409 ULONG WINAPI MNLS_lstrcpyW(LPWSTR lpszDest, LPCWSTR lpszSrc)
411 ULONG len;
413 TRACE("(%p,%s)\n", lpszDest, debugstr_w(lpszSrc));
414 len = (strlenW(lpszSrc) + 1) * sizeof(WCHAR);
415 memcpy(lpszDest, lpszSrc, len);
416 return len;
419 /*************************************************************************
420 * MNLS_CompareStringW@12 (MAPI32.65)
422 * Compare two Unicode strings.
424 * PARAMS
425 * dwCp [I] Code page for the comparison
426 * lpszLeft [I] First string to compare
427 * lpszRight [I] Second string to compare
429 * RETURNS
430 * CSTR_LESS_THAN, CSTR_EQUAL or CSTR_GREATER_THAN, indicating that
431 * lpszLeft is less than, the same, or greater than lpszRight.
433 INT WINAPI MNLS_CompareStringW(DWORD dwCp, LPCWSTR lpszLeft, LPCWSTR lpszRight)
435 INT ret;
437 TRACE("0x%08lx,%s,%s\n", dwCp, debugstr_w(lpszLeft), debugstr_w(lpszRight));
438 ret = MNLS_lstrcmpW(lpszLeft, lpszRight);
439 return ret < 0 ? CSTR_LESS_THAN : ret ? CSTR_GREATER_THAN : CSTR_EQUAL;
442 /**************************************************************************
443 * FEqualNames@8 (MAPI32.72)
445 * Compare two Mapi names.
447 * PARAMS
448 * lpName1 [I] First name to compare to lpName2
449 * lpName2 [I] Second name to compare to lpName1
451 * RETURNS
452 * TRUE, if the names are the same,
453 * FALSE, Otherwise.
455 BOOL WINAPI FEqualNames(LPMAPINAMEID lpName1, LPMAPINAMEID lpName2)
457 TRACE("(%p,%p)\n", lpName1, lpName2);
459 if (!lpName1 || !lpName2 ||
460 !IsEqualGUID(lpName1->lpguid, lpName2->lpguid) ||
461 lpName1->ulKind != lpName2->ulKind)
462 return FALSE;
464 if (lpName1->ulKind == MNID_STRING)
465 return !strcmpW(lpName1->Kind.lpwstrName, lpName2->Kind.lpwstrName);
467 return lpName1->Kind.lID == lpName2->Kind.lID ? TRUE : FALSE;
470 /**************************************************************************
471 * IsBadBoundedStringPtr@8 (MAPI32.71)
473 * Determine if a string pointer is valid.
475 * PARAMS
476 * lpszStr [I] String to check
477 * ulLen [I] Maximum length of lpszStr
479 * RETURNS
480 * TRUE, if lpszStr is invalid or longer than ulLen,
481 * FALSE, otherwise.
483 BOOL WINAPI IsBadBoundedStringPtr(LPCSTR lpszStr, ULONG ulLen)
485 if (!lpszStr || IsBadStringPtrA(lpszStr, -1) || strlen(lpszStr) >= ulLen)
486 return TRUE;
487 return FALSE;
490 /**************************************************************************
491 * FtAddFt@16 (MAPI32.121)
493 * Add two FILETIME's together.
495 * PARAMS
496 * ftLeft [I] FILETIME to add to ftRight
497 * ftRight [I] FILETIME to add to ftLeft
499 * RETURNS
500 * The sum of ftLeft and ftRight
502 LONGLONG WINAPI MAPI32_FtAddFt(FILETIME ftLeft, FILETIME ftRight)
504 LONGLONG *pl = (LONGLONG*)&ftLeft, *pr = (LONGLONG*)&ftRight;
506 return *pl + *pr;
509 /**************************************************************************
510 * FtSubFt@16 (MAPI32.123)
512 * Subtract two FILETIME's together.
514 * PARAMS
515 * ftLeft [I] Initial FILETIME
516 * ftRight [I] FILETIME to subtract from ftLeft
518 * RETURNS
519 * The remainder after ftRight is subtracted from ftLeft.
521 LONGLONG WINAPI MAPI32_FtSubFt(FILETIME ftLeft, FILETIME ftRight)
523 LONGLONG *pl = (LONGLONG*)&ftLeft, *pr = (LONGLONG*)&ftRight;
525 return *pr - *pl;
528 /**************************************************************************
529 * FtMulDw@12 (MAPI32.124)
531 * Multiply a FILETIME by a DWORD.
533 * PARAMS
534 * dwLeft [I] DWORD to multiply with ftRight
535 * ftRight [I] FILETIME to multiply with dwLeft
537 * RETURNS
538 * The product of dwLeft and ftRight
540 LONGLONG WINAPI MAPI32_FtMulDw(DWORD dwLeft, FILETIME ftRight)
542 LONGLONG *pr = (LONGLONG*)&ftRight;
544 return (LONGLONG)dwLeft * (*pr);
547 /**************************************************************************
548 * FtMulDwDw@8 (MAPI32.125)
550 * Multiply two DWORD, giving the result as a FILETIME.
552 * PARAMS
553 * dwLeft [I] DWORD to multiply with dwRight
554 * dwRight [I] DWORD to multiply with dwLeft
556 * RETURNS
557 * The product of ftMultiplier and ftMultiplicand as a FILETIME.
559 LONGLONG WINAPI MAPI32_FtMulDwDw(DWORD dwLeft, DWORD dwRight)
561 return (LONGLONG)dwLeft * (LONGLONG)dwRight;
564 /**************************************************************************
565 * FtNegFt@8 (MAPI32.126)
567 * Negate a FILETIME.
569 * PARAMS
570 * ft [I] FILETIME to negate
572 * RETURNS
573 * The negation of ft.
575 LONGLONG WINAPI MAPI32_FtNegFt(FILETIME ft)
577 LONGLONG *p = (LONGLONG*)&ft;
579 return - *p;
582 /**************************************************************************
583 * UlAddRef@4 (MAPI32.128)
585 * Add a reference to an object.
587 * PARAMS
588 * lpUnk [I] Object to add a reference to.
590 * RETURNS
591 * The new reference count of the object, or 0 if lpUnk is NULL.
593 * NOTES
594 * See IUnknown_AddRef.
596 ULONG WINAPI UlAddRef(void *lpUnk)
598 TRACE("(%p)\n", lpUnk);
600 if (!lpUnk)
601 return 0UL;
602 return IUnknown_AddRef((LPUNKNOWN)lpUnk);
605 /**************************************************************************
606 * UlRelease@4 (MAPI32.129)
608 * Remove a reference from an object.
610 * PARAMS
611 * lpUnk [I] Object to remove reference from.
613 * RETURNS
614 * The new reference count of the object, or 0 if lpUnk is NULL. If lpUnk is
615 * non-NULL and this function returns 0, the object pointed to by lpUnk has
616 * been released.
618 * NOTES
619 * See IUnknown_Release.
621 ULONG WINAPI UlRelease(void *lpUnk)
623 TRACE("(%p)\n", lpUnk);
625 if (!lpUnk)
626 return 0UL;
627 return IUnknown_Release((LPUNKNOWN)lpUnk);
630 /**************************************************************************
631 * UFromSz@4 (MAPI32.133)
633 * Read an integer from a string
635 * PARAMS
636 * lpszStr [I] String to read the integer from.
638 * RETURNS
639 * Success: The integer read from lpszStr.
640 * Failure: 0, if the first character in lpszStr is not 0-9.
642 * NOTES
643 * This function does not accept whitespace and stops at the first non-digit
644 * character.
646 UINT WINAPI UFromSz(LPCSTR lpszStr)
648 ULONG ulRet = 0;
650 TRACE("(%s)\n", debugstr_a(lpszStr));
652 if (lpszStr)
654 while (*lpszStr >= '0' && *lpszStr <= '9')
656 ulRet = ulRet * 10 + (*lpszStr - '0');
657 lpszStr = CharNextA(lpszStr);
660 return ulRet;
663 /*************************************************************************
664 * OpenStreamOnFile@24 (MAPI32.147)
666 * Create a stream on a file.
668 * PARAMS
669 * lpAlloc [I] Memory allocation function
670 * lpFree [I] Memory free function
671 * ulFlags [I] Flags controlling the opening process
672 * lpszPath [I] Path of file to create stream on
673 * lpszPrefix [I] Prefix of the temporary file name (if ulFlags includes SOF_UNIQUEFILENAME)
674 * lppStream [O] Destination for created stream
676 * RETURNS
677 * Success: S_OK. lppStream contains the new stream object
678 * Failure: E_INVALIDARG if any parameter is invalid, or an HRESULT error code
679 * describing the error.
681 HRESULT WINAPI OpenStreamOnFile(LPALLOCATEBUFFER lpAlloc, LPFREEBUFFER lpFree,
682 ULONG ulFlags, LPWSTR lpszPath, LPWSTR lpszPrefix,
683 LPSTREAM *lppStream)
685 WCHAR szBuff[MAX_PATH];
686 DWORD dwMode = STGM_READWRITE, dwAttributes = 0;
687 HRESULT hRet;
689 TRACE("(%p,%p,0x%08lx,%s,%s,%p)\n", lpAlloc, lpFree, ulFlags,
690 debugstr_a((LPSTR)lpszPath), debugstr_a((LPSTR)lpszPrefix), lppStream);
692 if (lppStream)
693 *lppStream = NULL;
695 if (ulFlags & SOF_UNIQUEFILENAME)
697 FIXME("Should generate a temporary name\n");
698 return E_INVALIDARG;
701 if (!lpszPath || !lppStream)
702 return E_INVALIDARG;
704 /* FIXME: Should probably munge mode and attributes, and should handle
705 * Unicode arguments (I assume MAPI_UNICODE is set in ulFlags if
706 * we are being passed Unicode strings; MSDN doesn't say).
707 * This implementation is just enough for Outlook97 to start.
709 MultiByteToWideChar(CP_ACP, 0, (LPSTR)lpszPath, -1, szBuff, MAX_PATH);
710 hRet = SHCreateStreamOnFileEx(szBuff, dwMode, dwAttributes, TRUE,
711 NULL, lppStream);
712 return hRet;
715 /*************************************************************************
716 * UlFromSzHex@4 (MAPI32.155)
718 * Read an integer from a hexadecimal string.
720 * PARAMS
721 * lpSzHex [I] String containing the hexadecimal number to read
723 * RETURNS
724 * Success: The number represented by lpszHex.
725 * Failure: 0, if lpszHex does not contain a hex string.
727 * NOTES
728 * This function does not accept whitespace and stops at the first non-hex
729 * character.
731 ULONG WINAPI UlFromSzHex(LPCWSTR lpszHex)
733 LPSTR lpStr = (LPSTR)lpszHex;
734 ULONG ulRet = 0;
736 TRACE("(%s)\n", debugstr_a(lpStr));
738 while (*lpStr)
740 if (lpStr[0] < '0' || lpStr[0] > 'f' || digitsToHex[lpStr[0] - '0'] == 0xff ||
741 lpStr[1] < '0' || lpStr[1] > 'f' || digitsToHex[lpStr[1] - '0'] == 0xff)
742 break;
744 ulRet = ulRet * 16 + ((digitsToHex[lpStr[0] - '0'] << 4) | digitsToHex[lpStr[1] - '0']);
745 lpStr += 2;
747 return ulRet;
750 /************************************************************************
751 * FBadEntryList@4 (MAPI32.190)
753 * Determine is an entry list is invalid.
755 * PARAMS
756 * lpEntryList [I] List to check
758 * RETURNS
759 * TRUE, if lpEntryList is invalid,
760 * FALSE, otherwise.
762 BOOL WINAPI FBadEntryList(LPENTRYLIST lpEntryList)
764 ULONG i;
766 if (IsBadReadPtr(lpEntryList, sizeof(*lpEntryList)) ||
767 IsBadReadPtr(lpEntryList->lpbin,
768 lpEntryList->cValues * sizeof(*lpEntryList->lpbin)))
769 return TRUE;
771 for (i = 0; i < lpEntryList->cValues; i++)
772 if(IsBadReadPtr(lpEntryList->lpbin[i].lpb, lpEntryList->lpbin[i].cb))
773 return TRUE;
775 return FALSE;
778 /*************************************************************************
779 * CbOfEncoded@4 (MAPI32.207)
781 * Return the length of an encoded string.
783 * PARAMS
784 * lpSzEnc [I] Encoded string to get the length of.
786 * RETURNS
787 * The length of the encoded string in bytes.
789 ULONG WINAPI CbOfEncoded(LPCSTR lpszEnc)
791 ULONG ulRet = 0;
793 TRACE("(%s)\n", debugstr_a(lpszEnc));
795 if (lpszEnc)
796 ulRet = (((strlen(lpszEnc) | 3) >> 2) + 1) * 3;
797 return ulRet;
800 /*************************************************************************
801 * cmc_query_configuration (MAPI32.235)
803 * Retrieves the configuration information for the installed CMC
805 * PARAMS
806 * session [I] MAPI session handle
807 * item [I] Enumerated variable that identifies which
808 * configuration information is being requested
809 * reference [O] Buffer where configuration information is written
810 * config_extensions[I/O] Path of file to create stream on
812 * RETURNS
813 * A CMD define
815 CMC_return_code WINAPI cmc_query_configuration(
816 CMC_session_id session,
817 CMC_enum item,
818 CMC_buffer reference,
819 CMC_extension *config_extensions)
821 FIXME("stub");
822 return CMC_E_NOT_SUPPORTED;