1 /*
2 * MAPI Utility functions
3 *
4 * Copyright 2004 Jon Griffiths
5 *
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.
10 *
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.
15 *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winreg.h"
30 #include "winuser.h"
31 #include "winerror.h"
32 #include "winternl.h"
33 #include "objbase.h"
34 #include "shlwapi.h"
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
37 #include "mapival.h"
38 #include "xcmc.h"
39 #include "msi.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(mapi);
42
43 static const BYTE digitsToHex[] = {
44 0,1,2,3,4,5,6,7,8,9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,10,11,12,13,14,15,
45 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
46 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,10,11,12,13,
47 14,15 };
48
49 /**************************************************************************
50 * ScInitMapiUtil (MAPI32.33)
51 *
52 * Initialise Mapi utility functions.
53 *
54 * PARAMS
55 * ulReserved [I] Reserved, pass 0.
56 *
57 * RETURNS
58 * Success: S_OK. Mapi utility functions may be called.
59 * Failure: MAPI_E_INVALID_PARAMETER, if ulReserved is not 0.
60 *
61 * NOTES
62 * Your application does not need to call this function unless it does not
63 * call MAPIInitialize()/MAPIUninitialize().
64 */
65 SCODE WINAPI ScInitMapiUtil(ULONG ulReserved)
66 {
67 FIXME("(0x%08x)stub!\n", ulReserved);
68 if (ulReserved)
69 return MAPI_E_INVALID_PARAMETER;
70 return S_OK;
71 }
72
73 /**************************************************************************
74 * DeinitMapiUtil (MAPI32.34)
75 *
76 * Uninitialise Mapi utility functions.
77 *
78 * PARAMS
79 * None.
80 *
81 * RETURNS
82 * Nothing.
83 *
84 * NOTES
85 * Your application does not need to call this function unless it does not
86 * call MAPIInitialize()/MAPIUninitialize().
87 */
88 VOID WINAPI DeinitMapiUtil(void)
89 {
90 FIXME("()stub!\n");
91 }
92
93 typedef LPVOID *LPMAPIALLOCBUFFER;
94
95 /**************************************************************************
96 * MAPIAllocateBuffer (MAPI32.12)
97 * MAPIAllocateBuffer@8 (MAPI32.13)
98 *
99 * Allocate a block of memory.
100 *
101 * PARAMS
102 * cbSize [I] Size of the block to allocate in bytes
103 * lppBuffer [O] Destination for pointer to allocated memory
104 *
105 * RETURNS
106 * Success: S_OK. *lppBuffer is filled with a pointer to a memory block of
107 * length cbSize bytes.
108 * Failure: MAPI_E_INVALID_PARAMETER, if lppBuffer is NULL.
109 * MAPI_E_NOT_ENOUGH_MEMORY, if the memory allocation fails.
110 *
111 * NOTES
112 * Memory allocated with this function should be freed with MAPIFreeBuffer().
113 * Further allocations of memory may be linked to the pointer returned using
114 * MAPIAllocateMore(). Linked allocations are freed when the initial pointer
115 * is feed.
116 */
117 SCODE WINAPI MAPIAllocateBuffer(ULONG cbSize, LPVOID *lppBuffer)
118 {
119 LPMAPIALLOCBUFFER lpBuff;
120
121 TRACE("(%d,%p)\n", cbSize, lppBuffer);
122
123 if (!lppBuffer)
124 return E_INVALIDARG;
125
126 lpBuff = HeapAlloc(GetProcessHeap(), 0, cbSize + sizeof(*lpBuff));
127 if (!lpBuff)
128 return MAPI_E_NOT_ENOUGH_MEMORY;
129
130 TRACE("initial allocation:%p, returning %p\n", lpBuff, lpBuff + 1);
131 *lpBuff++ = NULL;
132 *lppBuffer = lpBuff;
133 return S_OK;
134 }
135
136 /**************************************************************************
137 * MAPIAllocateMore (MAPI32.14)
138 * MAPIAllocateMore@12 (MAPI32.15)
139 *
140 * Allocate a block of memory linked to a previous allocation.
141 *
142 * PARAMS
143 * cbSize [I] Size of the block to allocate in bytes
144 * lpOrig [I] Initial allocation to link to, from MAPIAllocateBuffer()
145 * lppBuffer [O] Destination for pointer to allocated memory
146 *
147 * RETURNS
148 * Success: S_OK. *lppBuffer is filled with a pointer to a memory block of
149 * length cbSize bytes.
150 * Failure: MAPI_E_INVALID_PARAMETER, if lpOrig or lppBuffer is invalid.
151 * MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails.
152 *
153 * NOTES
154 * Memory allocated with this function and stored in *lppBuffer is freed
155 * when lpOrig is passed to MAPIFreeBuffer(). It should not be freed independently.
156 */
157 SCODE WINAPI MAPIAllocateMore(ULONG cbSize, LPVOID lpOrig, LPVOID *lppBuffer)
158 {
159 LPMAPIALLOCBUFFER lpBuff = lpOrig;
160
161 TRACE("(%d,%p,%p)\n", cbSize, lpOrig, lppBuffer);
162
163 if (!lppBuffer || !lpBuff || !--lpBuff)
164 return E_INVALIDARG;
165
166 /* Find the last allocation in the chain */
167 while (*lpBuff)
168 {
169 TRACE("linked:%p->%p\n", lpBuff, *lpBuff);
170 lpBuff = *lpBuff;
171 }
172
173 if (SUCCEEDED(MAPIAllocateBuffer(cbSize, lppBuffer)))
174 {
175 *lpBuff = ((LPMAPIALLOCBUFFER)*lppBuffer) - 1;
176 TRACE("linking %p->%p\n", lpBuff, *lpBuff);
177 }
178 return *lppBuffer ? S_OK : MAPI_E_NOT_ENOUGH_MEMORY;
179 }
180
181 /**************************************************************************
182 * MAPIFreeBuffer (MAPI32.16)
183 * MAPIFreeBuffer@4 (MAPI32.17)
184 *
185 * Free a block of memory and any linked allocations associated with it.
186 *
187 * PARAMS
188 * lpBuffer [I] Memory to free, returned from MAPIAllocateBuffer()
189 *
190 * RETURNS
191 * S_OK.
192 */
193 ULONG WINAPI MAPIFreeBuffer(LPVOID lpBuffer)
194 {
195 LPMAPIALLOCBUFFER lpBuff = lpBuffer;
196
197 TRACE("(%p)\n", lpBuffer);
198
199 if (lpBuff && --lpBuff)
200 {
201 while (lpBuff)
202 {
203 LPVOID lpFree = lpBuff;
204
205 lpBuff = *lpBuff;
206
207 TRACE("linked:%p->%p, freeing %p\n", lpFree, lpBuff, lpFree);
208 HeapFree(GetProcessHeap(), 0, lpFree);
209 }
210 }
211 return S_OK;
212 }
213
214 /**************************************************************************
215 * WrapProgress@20 (MAPI32.41)
216 */
217 HRESULT WINAPI WrapProgress(PVOID unk1, PVOID unk2, PVOID unk3, PVOID unk4, PVOID unk5)
218 {
219 /* Native does not implement this function */
220 return MAPI_E_NO_SUPPORT;
221 }
222
223 /*************************************************************************
224 * HrThisThreadAdviseSink@8 (MAPI32.42)
225 *
226 * Ensure that an advise sink is only notified in its originating thread.
227 *
228 * PARAMS
229 * lpSink [I] IMAPIAdviseSink interface to be protected
230 * lppNewSink [I] Destination for wrapper IMAPIAdviseSink interface
231 *
232 * RETURNS
233 * Success: S_OK. *lppNewSink contains a new sink to use in place of lpSink.
234 * Failure: E_INVALIDARG, if any parameter is invalid.
235 */
236 HRESULT WINAPI HrThisThreadAdviseSink(LPMAPIADVISESINK lpSink, LPMAPIADVISESINK* lppNewSink)
237 {
238 FIXME("(%p,%p)semi-stub\n", lpSink, lppNewSink);
239
240 if (!lpSink || !lppNewSink)
241 return E_INVALIDARG;
242
243 /* Don't wrap the sink for now, just copy it */
244 *lppNewSink = lpSink;
245 IMAPIAdviseSink_AddRef(lpSink);
246 return S_OK;
247 }
248
249 /*************************************************************************
250 * FBinFromHex (MAPI32.44)
251 *
252 * Create an array of binary data from a string.
253 *
254 * PARAMS
255 * lpszHex [I] String to convert to binary data
256 * lpOut [O] Destination for resulting binary data
257 *
258 * RETURNS
259 * Success: TRUE. lpOut contains the decoded binary data.
260 * Failure: FALSE, if lpszHex does not represent a binary string.
261 *
262 * NOTES
263 * - lpOut must be at least half the length of lpszHex in bytes.
264 * - Although the Mapi headers prototype this function as both
265 * Ascii and Unicode, there is only one (Ascii) implementation. This
266 * means that lpszHex is treated as an Ascii string (i.e. a single NUL
267 * character in the byte stream terminates the string).
268 */
269 BOOL WINAPI FBinFromHex(LPWSTR lpszHex, LPBYTE lpOut)
270 {
271 LPSTR lpStr = (LPSTR)lpszHex;
272
273 TRACE("(%p,%p)\n", lpszHex, lpOut);
274
275 while (*lpStr)
276 {
277 if (lpStr[0] < '' || lpStr[0] > 'f' || digitsToHex[lpStr[0] - ''] == 0xff ||
278 lpStr[1] < '' || lpStr[1] > 'f' || digitsToHex[lpStr[1] - ''] == 0xff)
279 return FALSE;
280
281 *lpOut++ = (digitsToHex[lpStr[0] - ''] << 4) | digitsToHex[lpStr[1] - ''];
282 lpStr += 2;
283 }
284 return TRUE;
285 }
286
287 /*************************************************************************
288 * HexFromBin (MAPI32.45)
289 *
290 * Create a string from an array of binary data.
291 *
292 * PARAMS
293 * lpHex [I] Binary data to convert to string
294 * iCount [I] Length of lpHex in bytes
295 * lpszOut [O] Destination for resulting hex string
296 *
297 * RETURNS
298 * Nothing.
299 *
300 * NOTES
301 * - lpszOut must be at least 2 * iCount + 1 bytes characters long.
302 * - Although the Mapi headers prototype this function as both
303 * Ascii and Unicode, there is only one (Ascii) implementation. This
304 * means that the resulting string is not properly NUL terminated
305 * if the caller expects it to be a Unicode string.
306 */
307 void WINAPI HexFromBin(LPBYTE lpHex, int iCount, LPWSTR lpszOut)
308 {
309 static const char hexDigits[] = { "0123456789ABCDEF" };
310 LPSTR lpStr = (LPSTR)lpszOut;
311
312 TRACE("(%p,%d,%p)\n", lpHex, iCount, lpszOut);
313
314 while (iCount-- > 0)
315 {
316 *lpStr++ = hexDigits[*lpHex >> 4];
317 *lpStr++ = hexDigits[*lpHex & 0xf];
318 lpHex++;
319 }
320 *lpStr = '\0';
321 }
322
323 /*************************************************************************
324 * SwapPlong@8 (MAPI32.47)
325 *
326 * Swap the bytes in a ULONG array.
327 *
328 * PARAMS
329 * lpData [O] Array to swap bytes in
330 * ulLen [I] Number of ULONG element to swap the bytes of
331 *
332 * RETURNS
333 * Nothing.
334 */
335 VOID WINAPI SwapPlong(PULONG lpData, ULONG ulLen)
336 {
337 ULONG i;
338
339 for (i = 0; i < ulLen; i++)
340 lpData[i] = RtlUlongByteSwap(lpData[i]);
341 }
342
343 /*************************************************************************
344 * SwapPword@8 (MAPI32.48)
345 *
346 * Swap the bytes in a USHORT array.
347 *
348 * PARAMS
349 * lpData [O] Array to swap bytes in
350 * ulLen [I] Number of USHORT element to swap the bytes of
351 *
352 * RETURNS
353 * Nothing.
354 */
355 VOID WINAPI SwapPword(PUSHORT lpData, ULONG ulLen)
356 {
357 ULONG i;
358
359 for (i = 0; i < ulLen; i++)
360 lpData[i] = RtlUshortByteSwap(lpData[i]);
361 }
362
363 /**************************************************************************
364 * MNLS_lstrlenW@4 (MAPI32.62)
365 *
366 * Calculate the length of a Unicode string.
367 *
368 * PARAMS
369 * lpszStr [I] String to calculate the length of
370 *
371 * RETURNS
372 * The length of lpszStr in Unicode characters.
373 */
374 ULONG WINAPI MNLS_lstrlenW(LPCWSTR lpszStr)
375 {
376 TRACE("(%s)\n", debugstr_w(lpszStr));
377 return strlenW(lpszStr);
378 }
379
380 /*************************************************************************
381 * MNLS_lstrcmpW@8 (MAPI32.63)
382 *
383 * Compare two Unicode strings.
384 *
385 * PARAMS
386 * lpszLeft [I] First string to compare
387 * lpszRight [I] Second string to compare
388 *
389 * RETURNS
390 * An integer less than, equal to or greater than 0, indicating that
391 * lpszLeft is less than, the same, or greater than lpszRight.
392 */
393 INT WINAPI MNLS_lstrcmpW(LPCWSTR lpszLeft, LPCWSTR lpszRight)
394 {
395 TRACE("(%s,%s)\n", debugstr_w(lpszLeft), debugstr_w(lpszRight));
396 return strcmpW(lpszLeft, lpszRight);
397 }
398
399 /*************************************************************************
400 * MNLS_lstrcpyW@8 (MAPI32.64)
401 *
402 * Copy a Unicode string to another string.
403 *
404 * PARAMS
405 * lpszDest [O] Destination string
406 * lpszSrc [I] Source string
407 *
408 * RETURNS
409 * The length lpszDest in Unicode characters.
410 */
411 ULONG WINAPI MNLS_lstrcpyW(LPWSTR lpszDest, LPCWSTR lpszSrc)
412 {
413 ULONG len;
414
415 TRACE("(%p,%s)\n", lpszDest, debugstr_w(lpszSrc));
416 len = (strlenW(lpszSrc) + 1) * sizeof(WCHAR);
417 memcpy(lpszDest, lpszSrc, len);
418 return len;
419 }
420
421 /*************************************************************************
422 * MNLS_CompareStringW@12 (MAPI32.65)
423 *
424 * Compare two Unicode strings.
425 *
426 * PARAMS
427 * dwCp [I] Code page for the comparison
428 * lpszLeft [I] First string to compare
429 * lpszRight [I] Second string to compare
430 *
431 * RETURNS
432 * CSTR_LESS_THAN, CSTR_EQUAL or CSTR_GREATER_THAN, indicating that
433 * lpszLeft is less than, the same, or greater than lpszRight.
434 */
435 INT WINAPI MNLS_CompareStringW(DWORD dwCp, LPCWSTR lpszLeft, LPCWSTR lpszRight)
436 {
437 INT ret;
438
439 TRACE("0x%08x,%s,%s\n", dwCp, debugstr_w(lpszLeft), debugstr_w(lpszRight));
440 ret = MNLS_lstrcmpW(lpszLeft, lpszRight);
441 return ret < 0 ? CSTR_LESS_THAN : ret ? CSTR_GREATER_THAN : CSTR_EQUAL;
442 }
443
444 /**************************************************************************
445 * FEqualNames@8 (MAPI32.72)
446 *
447 * Compare two Mapi names.
448 *
449 * PARAMS
450 * lpName1 [I] First name to compare to lpName2
451 * lpName2 [I] Second name to compare to lpName1
452 *
453 * RETURNS
454 * TRUE, if the names are the same,
455 * FALSE, Otherwise.
456 */
457 BOOL WINAPI FEqualNames(LPMAPINAMEID lpName1, LPMAPINAMEID lpName2)
458 {
459 TRACE("(%p,%p)\n", lpName1, lpName2);
460
461 if (!lpName1 || !lpName2 ||
462 !IsEqualGUID(lpName1->lpguid, lpName2->lpguid) ||
463 lpName1->ulKind != lpName2->ulKind)
464 return FALSE;
465
466 if (lpName1->ulKind == MNID_STRING)
467 return !strcmpW(lpName1->Kind.lpwstrName, lpName2->Kind.lpwstrName);
468
469 return lpName1->Kind.lID == lpName2->Kind.lID ? TRUE : FALSE;
470 }
471
472 /**************************************************************************
473 * IsBadBoundedStringPtr@8 (MAPI32.71)
474 *
475 * Determine if a string pointer is valid.
476 *
477 * PARAMS
478 * lpszStr [I] String to check
479 * ulLen [I] Maximum length of lpszStr
480 *
481 * RETURNS
482 * TRUE, if lpszStr is invalid or longer than ulLen,
483 * FALSE, otherwise.
484 */
485 BOOL WINAPI IsBadBoundedStringPtr(LPCSTR lpszStr, ULONG ulLen)
486 {
487 if (!lpszStr || IsBadStringPtrA(lpszStr, -1) || strlen(lpszStr) >= ulLen)
488 return TRUE;
489 return FALSE;
490 }
491
492 /**************************************************************************
493 * FtAddFt@16 (MAPI32.121)
494 *
495 * Add two FILETIME's together.
496 *
497 * PARAMS
498 * ftLeft [I] FILETIME to add to ftRight
499 * ftRight [I] FILETIME to add to ftLeft
500 *
501 * RETURNS
502 * The sum of ftLeft and ftRight
503 */
504 LONGLONG WINAPI MAPI32_FtAddFt(FILETIME ftLeft, FILETIME ftRight)
505 {
506 LONGLONG *pl = (LONGLONG*)&ftLeft, *pr = (LONGLONG*)&ftRight;
507
508 return *pl + *pr;
509 }
510
511 /**************************************************************************
512 * FtSubFt@16 (MAPI32.123)
513 *
514 * Subtract two FILETIME's together.
515 *
516 * PARAMS
517 * ftLeft [I] Initial FILETIME
518 * ftRight [I] FILETIME to subtract from ftLeft
519 *
520 * RETURNS
521 * The remainder after ftRight is subtracted from ftLeft.
522 */
523 LONGLONG WINAPI MAPI32_FtSubFt(FILETIME ftLeft, FILETIME ftRight)
524 {
525 LONGLONG *pl = (LONGLONG*)&ftLeft, *pr = (LONGLONG*)&ftRight;
526
527 return *pr - *pl;
528 }
529
530 /**************************************************************************
531 * FtMulDw@12 (MAPI32.124)
532 *
533 * Multiply a FILETIME by a DWORD.
534 *
535 * PARAMS
536 * dwLeft [I] DWORD to multiply with ftRight
537 * ftRight [I] FILETIME to multiply with dwLeft
538 *
539 * RETURNS
540 * The product of dwLeft and ftRight
541 */
542 LONGLONG WINAPI MAPI32_FtMulDw(DWORD dwLeft, FILETIME ftRight)
543 {
544 LONGLONG *pr = (LONGLONG*)&ftRight;
545
546 return (LONGLONG)dwLeft * (*pr);
547 }
548
549 /**************************************************************************
550 * FtMulDwDw@8 (MAPI32.125)
551 *
552 * Multiply two DWORD, giving the result as a FILETIME.
553 *
554 * PARAMS
555 * dwLeft [I] DWORD to multiply with dwRight
556 * dwRight [I] DWORD to multiply with dwLeft
557 *
558 * RETURNS
559 * The product of ftMultiplier and ftMultiplicand as a FILETIME.
560 */
561 LONGLONG WINAPI MAPI32_FtMulDwDw(DWORD dwLeft, DWORD dwRight)
562 {
563 return (LONGLONG)dwLeft * (LONGLONG)dwRight;
564 }
565
566 /**************************************************************************
567 * FtNegFt@8 (MAPI32.126)
568 *
569 * Negate a FILETIME.
570 *
571 * PARAMS
572 * ft [I] FILETIME to negate
573 *
574 * RETURNS
575 * The negation of ft.
576 */
577 LONGLONG WINAPI MAPI32_FtNegFt(FILETIME ft)
578 {
579 LONGLONG *p = (LONGLONG*)&ft;
580
581 return - *p;
582 }
583
584 /**************************************************************************
585 * UlAddRef@4 (MAPI32.128)
586 *
587 * Add a reference to an object.
588 *
589 * PARAMS
590 * lpUnk [I] Object to add a reference to.
591 *
592 * RETURNS
593 * The new reference count of the object, or 0 if lpUnk is NULL.
594 *
595 * NOTES
596 * See IUnknown_AddRef.
597 */
598 ULONG WINAPI UlAddRef(void *lpUnk)
599 {
600 TRACE("(%p)\n", lpUnk);
601
602 if (!lpUnk)
603 return 0UL;
604 return IUnknown_AddRef((LPUNKNOWN)lpUnk);
605 }
606
607 /**************************************************************************
608 * UlRelease@4 (MAPI32.129)
609 *
610 * Remove a reference from an object.
611 *
612 * PARAMS
613 * lpUnk [I] Object to remove reference from.
614 *
615 * RETURNS
616 * The new reference count of the object, or 0 if lpUnk is NULL. If lpUnk is
617 * non-NULL and this function returns 0, the object pointed to by lpUnk has
618 * been released.
619 *
620 * NOTES
621 * See IUnknown_Release.
622 */
623 ULONG WINAPI UlRelease(void *lpUnk)
624 {
625 TRACE("(%p)\n", lpUnk);
626
627 if (!lpUnk)
628 return 0UL;
629 return IUnknown_Release((LPUNKNOWN)lpUnk);
630 }
631
632 /**************************************************************************
633 * UFromSz@4 (MAPI32.133)
634 *
635 * Read an integer from a string
636 *
637 * PARAMS
638 * lpszStr [I] String to read the integer from.
639 *
640 * RETURNS
641 * Success: The integer read from lpszStr.
642 * Failure: 0, if the first character in lpszStr is not 0-9.
643 *
644 * NOTES
645 * This function does not accept whitespace and stops at the first non-digit
646 * character.
647 */
648 UINT WINAPI UFromSz(LPCSTR lpszStr)
649 {
650 ULONG ulRet = 0;
651
652 TRACE("(%s)\n", debugstr_a(lpszStr));
653
654 if (lpszStr)
655 {
656 while (*lpszStr >= '' && *lpszStr <= '9')
657 {
658 ulRet = ulRet * 10 + (*lpszStr - '');
659 lpszStr++;
660 }
661 }
662 return ulRet;
663 }
664
665 /*************************************************************************
666 * OpenStreamOnFile@24 (MAPI32.147)
667 *
668 * Create a stream on a file.
669 *
670 * PARAMS
671 * lpAlloc [I] Memory allocation function
672 * lpFree [I] Memory free function
673 * ulFlags [I] Flags controlling the opening process
674 * lpszPath [I] Path of file to create stream on
675 * lpszPrefix [I] Prefix of the temporary file name (if ulFlags includes SOF_UNIQUEFILENAME)
676 * lppStream [O] Destination for created stream
677 *
678 * RETURNS
679 * Success: S_OK. lppStream contains the new stream object
680 * Failure: E_INVALIDARG if any parameter is invalid, or an HRESULT error code
681 * describing the error.
682 */
683 HRESULT WINAPI OpenStreamOnFile(LPALLOCATEBUFFER lpAlloc, LPFREEBUFFER lpFree,
684 ULONG ulFlags, LPWSTR lpszPath, LPWSTR lpszPrefix,
685 LPSTREAM *lppStream)
686 {
687 WCHAR szBuff[MAX_PATH];
688 DWORD dwMode = STGM_READWRITE, dwAttributes = 0;
689 HRESULT hRet;
690
691 TRACE("(%p,%p,0x%08x,%s,%s,%p)\n", lpAlloc, lpFree, ulFlags,
692 debugstr_a((LPSTR)lpszPath), debugstr_a((LPSTR)lpszPrefix), lppStream);
693
694 if (lppStream)
695 *lppStream = NULL;
696
697 if (ulFlags & SOF_UNIQUEFILENAME)
698 {
699 FIXME("Should generate a temporary name\n");
700 return E_INVALIDARG;
701 }
702
703 if (!lpszPath || !lppStream)
704 return E_INVALIDARG;
705
706 /* FIXME: Should probably munge mode and attributes, and should handle
707 * Unicode arguments (I assume MAPI_UNICODE is set in ulFlags if
708 * we are being passed Unicode strings; MSDN doesn't say).
709 * This implementation is just enough for Outlook97 to start.
710 */
711 MultiByteToWideChar(CP_ACP, 0, (LPSTR)lpszPath, -1, szBuff, MAX_PATH);
712 hRet = SHCreateStreamOnFileEx(szBuff, dwMode, dwAttributes, TRUE,
713 NULL, lppStream);
714 return hRet;
715 }
716
717 /*************************************************************************
718 * UlFromSzHex@4 (MAPI32.155)
719 *
720 * Read an integer from a hexadecimal string.
721 *
722 * PARAMS
723 * lpSzHex [I] String containing the hexadecimal number to read
724 *
725 * RETURNS
726 * Success: The number represented by lpszHex.
727 * Failure: 0, if lpszHex does not contain a hex string.
728 *
729 * NOTES
730 * This function does not accept whitespace and stops at the first non-hex
731 * character.
732 */
733 ULONG WINAPI UlFromSzHex(LPCWSTR lpszHex)
734 {
735 LPCSTR lpStr = (LPCSTR)lpszHex;
736 ULONG ulRet = 0;
737
738 TRACE("(%s)\n", debugstr_a(lpStr));
739
740 while (*lpStr)
741 {
742 if (lpStr[0] < '' || lpStr[0] > 'f' || digitsToHex[lpStr[0] - ''] == 0xff ||
743 lpStr[1] < '' || lpStr[1] > 'f' || digitsToHex[lpStr[1] - ''] == 0xff)
744 break;
745
746 ulRet = ulRet * 16 + ((digitsToHex[lpStr[0] - ''] << 4) | digitsToHex[lpStr[1] - '']);
747 lpStr += 2;
748 }
749 return ulRet;
750 }
751
752 /************************************************************************
753 * FBadEntryList@4 (MAPI32.190)
754 *
755 * Determine is an entry list is invalid.
756 *
757 * PARAMS
758 * lpEntryList [I] List to check
759 *
760 * RETURNS
761 * TRUE, if lpEntryList is invalid,
762 * FALSE, otherwise.
763 */
764 BOOL WINAPI FBadEntryList(LPENTRYLIST lpEntryList)
765 {
766 ULONG i;
767
768 if (IsBadReadPtr(lpEntryList, sizeof(*lpEntryList)) ||
769 IsBadReadPtr(lpEntryList->lpbin,
770 lpEntryList->cValues * sizeof(*lpEntryList->lpbin)))
771 return TRUE;
772
773 for (i = 0; i < lpEntryList->cValues; i++)
774 if(IsBadReadPtr(lpEntryList->lpbin[i].lpb, lpEntryList->lpbin[i].cb))
775 return TRUE;
776
777 return FALSE;
778 }
779
780 /*************************************************************************
781 * CbOfEncoded@4 (MAPI32.207)
782 *
783 * Return the length of an encoded string.
784 *
785 * PARAMS
786 * lpSzEnc [I] Encoded string to get the length of.
787 *
788 * RETURNS
789 * The length of the encoded string in bytes.
790 */
791 ULONG WINAPI CbOfEncoded(LPCSTR lpszEnc)
792 {
793 ULONG ulRet = 0;
794
795 TRACE("(%s)\n", debugstr_a(lpszEnc));
796
797 if (lpszEnc)
798 ulRet = (((strlen(lpszEnc) | 3) >> 2) + 1) * 3;
799 return ulRet;
800 }
801
802 /*************************************************************************
803 * cmc_query_configuration (MAPI32.235)
804 *
805 * Retrieves the configuration information for the installed CMC
806 *
807 * PARAMS
808 * session [I] MAPI session handle
809 * item [I] Enumerated variable that identifies which
810 * configuration information is being requested
811 * reference [O] Buffer where configuration information is written
812 * config_extensions[I/O] Path of file to create stream on
813 *
814 * RETURNS
815 * A CMD define
816 */
817 CMC_return_code WINAPI cmc_query_configuration(
818 CMC_session_id session,
819 CMC_enum item,
820 CMC_buffer reference,
821 CMC_extension *config_extensions)
822 {
823 FIXME("stub\n");
824 return CMC_E_NOT_SUPPORTED;
825 }
826
827 /**************************************************************************
828 * FGetComponentPath (MAPI32.254)
829 * FGetComponentPath@20 (MAPI32.255)
830 *
831 * Return the installed component path, usually to the private mapi32.dll.
832 *
833 * PARAMS
834 * component [I] Component ID
835 * qualifier [I] Application LCID
836 * dll_path [O] returned component path
837 * dll_path_length [I] component path length
838 * install [I] install mode
839 *
840 * RETURNS
841 * Success: TRUE.
842 * Failure: FALSE.
843 *
844 * NOTES
845 * Previously documented in Q229700 "How to locate the correct path
846 * to the Mapisvc.inf file in Microsoft Outlook".
847 */
848 BOOL WINAPI FGetComponentPath(LPCSTR component, LPCSTR qualifier, LPSTR dll_path,
849 DWORD dll_path_length, BOOL install)
850 {
851 BOOL ret = FALSE;
852 HMODULE hmsi;
853
854 TRACE("%s %s %p %u %d\n", component, qualifier, dll_path, dll_path_length, install);
855
856 dll_path[0] = 0;
857
858 hmsi = LoadLibraryA("msi.dll");
859 if (hmsi)
860 {
861 FARPROC pMsiProvideQualifiedComponentA = GetProcAddress(hmsi, "MsiProvideQualifiedComponentA");
862
863 if (pMsiProvideQualifiedComponentA)
864 {
865 static const char * const fmt[] = { "%d\\NT", "%d\\95", "%d" };
866 char lcid_ver[20];
867 UINT i;
868
869 for (i = 0; i < sizeof(fmt)/sizeof(fmt[0]); i++)
870 {
871 /* FIXME: what's the correct behaviour here? */
872 if (!qualifier || qualifier == lcid_ver)
873 {
874 sprintf(lcid_ver, fmt[i], GetUserDefaultUILanguage());
875 qualifier = lcid_ver;
876 }
877
878 if (pMsiProvideQualifiedComponentA(component, qualifier,
879 install ? INSTALLMODE_DEFAULT : INSTALLMODE_EXISTING,
880 dll_path, &dll_path_length) == ERROR_SUCCESS)
881 {
882 ret = TRUE;
883 break;
884 }
885
886 if (qualifier != lcid_ver) break;
887 }
888 }
889 FreeLibrary(hmsi);
890 }
891 return ret;
892 }
893
894 /**************************************************************************
895 * HrQueryAllRows (MAPI32.75)
896 */
897 HRESULT WINAPI HrQueryAllRows(LPMAPITABLE lpTable, LPSPropTagArray lpPropTags,
898 LPSRestriction lpRestriction, LPSSortOrderSet lpSortOrderSet,
899 LONG crowsMax, LPSRowSet *lppRows)
900 {
901 FIXME("(%p, %p, %p, %p, %d, %p): stub\n", lpTable, lpPropTags, lpRestriction, lpSortOrderSet, crowsMax, lppRows);
902 *lppRows = NULL;
903 return MAPI_E_CALL_FAILED;
904 }
905
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.