Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
c79b70d6
Commit
c79b70d6
authored
Apr 23, 2004
by
Jon Griffiths
Committed by
Alexandre Julliard
Apr 23, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement MAPI property & utility functions.
parent
11b26f05
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
1525 additions
and
61 deletions
+1525
-61
Makefile.in
dlls/mapi32/Makefile.in
+8
-1
mapi32.spec
dlls/mapi32/mapi32.spec
+42
-42
mapi32_main.c
dlls/mapi32/mapi32_main.c
+7
-18
prop.c
dlls/mapi32/prop.c
+927
-0
util.c
dlls/mapi32/util.c
+541
-0
No files found.
dlls/mapi32/Makefile.in
View file @
c79b70d6
...
...
@@ -3,8 +3,15 @@ TOPOBJDIR = ../..
SRCDIR
=
@srcdir@
VPATH
=
@srcdir@
MODULE
=
mapi32.dll
IMPORTS
=
shlwapi ole32 kernel32
EXTRALIBS
=
-luuid
$(LIBUNICODE)
C_SRCS
=
mapi32_main.c
C_SRCS
=
\
mapi32_main.c
\
prop.c
\
util.c
SUBDIRS
=
tests
@MAKE_DLL_RULES@
...
...
dlls/mapi32/mapi32.spec
View file @
c79b70d6
...
...
@@ -3,10 +3,10 @@
11 stdcall MAPILogonEx@20(long ptr ptr long ptr) MAPILogonEx
12 stdcall MAPIAllocateBuffer(long ptr)
13 stdcall MAPIAllocateBuffer@8(long ptr) MAPIAllocateBuffer
14 st
ub MAPIAllocateMore
15 st
ub MAPIAllocateMore@12
16 st
ub MAPIFreeBuffer
17 st
ub MAPIFreeBuffer@4
14 st
dcall MAPIAllocateMore(long ptr ptr)
15 st
dcall MAPIAllocateMore@12(long ptr ptr) MAPIAllocateMore
16 st
dcall MAPIFreeBuffer(ptr)
17 st
dcall MAPIFreeBuffer@4(ptr) MAPIFreeBuffer
18 stub MAPIAdminProfiles
19 stub MAPIAdminProfiles@8
20 stdcall MAPIInitialize(ptr)
...
...
@@ -22,18 +22,18 @@
30 stub MAPIOpenFormMgr@8
31 stub MAPIOpenLocalFormContainer
32 stub MAPIOpenLocalFormContainer@4
33 st
ub ScInitMapiUtil@4
33 st
dcall ScInitMapiUtil@4(long) ScInitMapiUtil
34 stdcall DeinitMapiUtil@0() DeinitMapiUtil
35 stub ScGenerateMuid@4
36 stub HrAllocAdviseSink@12
41 stub WrapProgress@20
42 st
ub HrThisThreadAdviseSink@8
42 st
dcall HrThisThreadAdviseSink@8(ptr ptr) HrThisThreadAdviseSink
43 stub ScBinFromHexBounded@12
44 stub FBinFromHex@8
45 stub HexFromBin@12
46 stub BuildDisplayTable@40
47 st
ub SwapPlong@8
48 st
ub SwapPword@8
47 st
dcall SwapPlong@8(ptr long) SwapPlong
48 st
dcall SwapPword@8(ptr long) SwapPword
49 stub MAPIInitIdle@4
50 stub MAPIDeinitIdle@0
51 stub InstallFilterHook@4
...
...
@@ -44,41 +44,41 @@
59 stub MAPIGetDefaultMalloc@0
60 stub CreateIProp@24
61 stub CreateTable@36
62 st
ub MNLS_lstrlenW@4
63 st
ub MNLS_lstrcmpW@8
64 st
ub MNLS_lstrcpyW@8
65 st
ub MNLS_CompareStringW@24
66 st
ub MNLS_MultiByteToWideChar@24
67 st
ub MNLS_WideCharToMultiByte@32
68 st
ub MNLS_IsBadStringPtrW@8
62 st
dcall MNLS_lstrlenW@4(wstr) MNLS_lstrlenW
63 st
dcall MNLS_lstrcmpW@8(wstr wstr) MNLS_lstrcmpW
64 st
dcall MNLS_lstrcpyW@8(ptr wstr) MNLS_lstrcpyW
65 st
dcall MNLS_CompareStringW@24(long wstr wstr) MNLS_CompareStringW
66 st
dcall MNLS_MultiByteToWideChar@24(long long str long ptr long) kernel32.MultiByteToWideChar
67 st
dcall MNLS_WideCharToMultiByte@32(long long wstr long ptr long ptr ptr) kernel32.WideCharToMultiByte
68 st
dcall MNLS_IsBadStringPtrW@8(ptr long) kernel32.IsBadStringPtrW
72 stub FEqualNames@8
73 stub WrapStoreEntryID@24
74 stub IsBadBoundedStringPtr@8
75 stub HrQueryAllRows@24
76 st
ub PropCopyMore@16
77 st
ub UlPropSize@4
78 st
ub FPropContainsProp@12
79 st
ub FPropCompareProp@12
80 st
ub LPropCompareProp@8
76 st
dcall PropCopyMore@16(ptr ptr ptr ptr) PropCopyMore
77 st
dcall UlPropSize@4(ptr) UlPropSize
78 st
dcall FPropContainsProp@12(ptr ptr long) FPropContainsProp
79 st
dcall FPropCompareProp@12(ptr long ptr) FPropCompareProp
80 st
dcall LPropCompareProp@8(ptr ptr) LPropCompareProp
81 stub HrAddColumns@16
82 stub HrAddColumnsEx@20
121 st
ub FtAddFt@16
121 st
dcall -ret64 FtAddFt@16(long long long long) MAPI32_FtAddFt
122 stub FtAdcFt@20
123 st
ub FtSubFt@16
124 st
ub FtMulDw@12
125 st
ub FtMulDwDw@8
126 st
ub FtNegFt@8
123 st
dcall -ret64 FtSubFt@16(long long long long) MAPI32_FtSubFt
124 st
dcall -ret64 FtMulDw@12(long long long) MAPI32_FtMulDw
125 st
dcall -ret64 FtMulDwDw@8(long long) MAPI32_FtMulDwDw
126 st
dcall -ret64 FtNegFt@8(long long) MAPI32_FtNegFt
127 stub FtDivFtBogus@20
128 st
ub UlAddRef@4
129 st
ub UlRelease@4
130 st
ub SzFindCh@8
131 st
ub SzFindLastCh@8
132 st
ub SzFindSz@8
128 st
dcall UlAddRef@4(ptr) UlAddRef
129 st
dcall UlRelease@4(ptr) UlRelease
130 st
dcall SzFindCh@8(str long) shlwapi.StrChrA
131 st
dcall SzFindLastCh@8(str str long) shlwapi.StrRChrA
132 st
dcall SzFindSz@8(str str) shlwapi.StrStrA
133 stub UFromSz@4
135 stub HrGetOneProp@12
136 stub HrSetOneProp@8
137 stub FPropExists@8
138 st
ub PpropFindProp@12
138 st
dcall PpropFindProp@12(ptr long long) PpropFindProp
139 stub FreePadrlist@4
140 stub FreeProws@4
141 stub HrSzFromEntryID@12
...
...
@@ -87,8 +87,8 @@
144 stub HrDecomposeEID@28
145 stub HrComposeMsgID@24
146 stub HrDecomposeMsgID@24
147 st
ub OpenStreamOnFile@24
148 st
ub OpenStreamOnFile
147 st
dcall OpenStreamOnFile@24(ptr ptr ptr ptr ptr ptr) OpenStreamOnFile
148 st
dcall OpenStreamOnFile(ptr ptr ptr ptr ptr ptr)
149 stub OpenTnefStream@28
150 stub OpenTnefStream
151 stub OpenTnefStreamEx@32
...
...
@@ -107,19 +107,19 @@
164 stub ScCountNotifications@12
165 stub ScCopyNotifications@16
166 stub ScRelocNotifications@20
170 st
ub ScCountProps@12
170 st
dcall ScCountProps@12(long ptr ptr) ScCountProps
171 stub ScCopyProps@16
172 stub ScRelocProps@20
173 st
ub LpValFindProp@12
173 st
dcall LpValFindProp@12(long long ptr) LpValFindProp
174 stub ScDupPropset@16
175 st
ub FBadRglpszA@8
176 st
ub FBadRglpszW@8
177 st
ub FBadRowSet@4
175 st
dcall FBadRglpszA@8(ptr long) FBadRglpszA
176 st
dcall FBadRglpszW@8(ptr long) FBadRglpszW
177 st
dcall FBadRowSet@4(ptr) FBadRowSet
178 stub FBadRglpNameID@8
179 st
ub FBadPropTag@4
180 st
ub FBadRow@4
181 st
ub FBadProp@4
182 st
ub FBadColumnSet@4
179 st
dcall FBadPropTag@4(long) FBadPropTag
180 st
dcall FBadRow@4(ptr) FBadRow
181 st
dcall FBadProp@4(ptr) FBadProp
182 st
dcall FBadColumnSet@4(ptr) FBadColumnSet
183 stub RTFSync@12
184 stub RTFSync
185 stub WrapCompressedRTFStream@12
...
...
dlls/mapi32/mapi32_main.c
View file @
c79b70d6
...
...
@@ -23,8 +23,8 @@
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "
mapi
.h"
#include "mapi
code
.h"
#include "
objbase
.h"
#include "mapi
x
.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
mapi
);
...
...
@@ -35,33 +35,22 @@ HRESULT WINAPI MAPIInitialize ( LPVOID lpMapiInit )
return
MAPI_E_NOT_INITIALIZED
;
}
HRESULT
WINAPI
MAPIAllocateBuffer
(
ULONG
cvSize
,
LPVOID
*
lppBuffer
)
{
ERR
(
"Stub
\n
"
);
*
lppBuffer
=
NULL
;
return
MAPI_E_NOT_INITIALIZED
;
}
ULONG
WINAPI
MAPILogon
(
ULONG
ulUIParam
,
LPSTR
lpszProfileName
,
LPSTR
lpszPassword
,
FLAGS
flFlags
,
ULONG
ulReserver
,
LPLHANDLE
lplhSession
)
{
ERR
(
"Stub
\n
"
);
return
MAPI_E_
FAILURE
;
return
MAPI_E_
LOGON_FAILED
;
}
HRESULT
WINAPI
MAPILogonEx
(
ULONG
ulUIParam
,
LPSTR
lpszProfileName
,
LPSTR
lpszPassword
,
FLAGS
flFlags
,
VOID
*
lppSession
)
HRESULT
WINAPI
MAPILogonEx
(
ULONG_PTR
ulUIParam
,
LPWSTR
lpszProfileName
,
LPWSTR
lpszPassword
,
ULONG
flFlags
,
LPMAPISESSION
*
lppSession
)
{
ERR
(
"Stub
\n
"
);
return
MAPI_E_LOGON_FAIL
URE
;
return
MAPI_E_LOGON_FAIL
ED
;
}
VOID
WINAPI
MAPIUninitialize
(
void
)
{
ERR
(
"Stub
\n
"
);
}
VOID
WINAPI
DeinitMapiUtil
(
void
)
{
ERR
(
"Stub
\n
"
);
}
dlls/mapi32/prop.c
0 → 100644
View file @
c79b70d6
/*
* Property functions
*
* Copyright 2004 Jon Griffiths
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winerror.h"
#include "winternl.h"
#include "objbase.h"
#include "shlwapi.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "mapival.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
mapi
);
BOOL
WINAPI
FBadRglpszA
(
LPSTR
*
,
ULONG
);
BOOL
WINAPI
FBadRglpszW
(
LPWSTR
*
,
ULONG
);
/* Internal: Check if a property value array is invalid */
static
inline
ULONG
PROP_BadArray
(
LPSPropValue
lpProp
,
size_t
elemSize
)
{
return
IsBadReadPtr
(
lpProp
->
Value
.
MVi
.
lpi
,
lpProp
->
Value
.
MVi
.
cValues
*
elemSize
);
}
/*************************************************************************
* PropCopyMore@16 (MAPI32.76)
*
* Copy a property value.
*
* PARAMS
* lpDest [O] Destination for the copied value
* lpSrc [I] Property value to copy to lpDest
* lpMore [I] Linked memory allocation function (pass MAPIAllocateMore())
* lpOrig [I] Original allocation to which memory will be linked
*
* RETURNS
* Success: S_OK. lpDest contains a deep copy of lpSrc.
* Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid,
* MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails.
*
* NOTES
* Any elements within the property returned should not be individually
* freed, as they will be freed when lpOrig is.
*/
SCODE
WINAPI
PropCopyMore
(
LPSPropValue
lpDest
,
LPSPropValue
lpSrc
,
ALLOCATEMORE
*
lpMore
,
LPVOID
lpOrig
)
{
ULONG
ulLen
,
i
;
SCODE
scode
=
S_OK
;
TRACE
(
"(%p,%p,%p,%p)
\n
"
,
lpDest
,
lpSrc
,
lpMore
,
lpOrig
);
if
(
!
lpDest
||
IsBadWritePtr
(
lpDest
,
sizeof
(
SPropValue
))
||
FBadProp
(
lpSrc
)
||
!
lpMore
)
return
MAPI_E_INVALID_PARAMETER
;
/* Shallow copy first, this is sufficient for properties without pointers */
*
lpDest
=
*
lpSrc
;
switch
(
PROP_TYPE
(
lpSrc
->
ulPropTag
))
{
case
PT_CLSID
:
scode
=
lpMore
(
sizeof
(
GUID
),
lpOrig
,
(
LPVOID
*
)
&
lpDest
->
Value
.
lpguid
);
if
(
SUCCEEDED
(
scode
))
memcpy
(
lpDest
->
Value
.
lpguid
,
lpSrc
->
Value
.
lpguid
,
sizeof
(
GUID
));
break
;
case
PT_STRING8
:
ulLen
=
lstrlenA
(
lpSrc
->
Value
.
lpszA
)
+
1u
;
scode
=
lpMore
(
ulLen
,
lpOrig
,
(
LPVOID
*
)
&
lpDest
->
Value
.
lpszA
);
if
(
SUCCEEDED
(
scode
))
memcpy
(
lpDest
->
Value
.
lpszA
,
lpSrc
->
Value
.
lpszA
,
ulLen
);
break
;
case
PT_UNICODE
:
ulLen
=
(
strlenW
(
lpSrc
->
Value
.
lpszW
)
+
1u
)
*
sizeof
(
WCHAR
);
scode
=
lpMore
(
ulLen
,
lpOrig
,
(
LPVOID
*
)
&
lpDest
->
Value
.
lpszW
);
if
(
SUCCEEDED
(
scode
))
memcpy
(
lpDest
->
Value
.
lpszW
,
lpSrc
->
Value
.
lpszW
,
ulLen
);
break
;
case
PT_BINARY
:
scode
=
lpMore
(
lpSrc
->
Value
.
bin
.
cb
,
lpOrig
,
(
LPVOID
*
)
&
lpDest
->
Value
.
bin
.
lpb
);
if
(
SUCCEEDED
(
scode
))
memcpy
(
lpDest
->
Value
.
bin
.
lpb
,
lpSrc
->
Value
.
bin
.
lpb
,
lpSrc
->
Value
.
bin
.
cb
);
break
;
default:
if
(
lpSrc
->
ulPropTag
&
MV_FLAG
)
{
ulLen
=
UlPropSize
(
lpSrc
);
if
(
PROP_TYPE
(
lpSrc
->
ulPropTag
)
==
PT_MV_STRING8
||
PROP_TYPE
(
lpSrc
->
ulPropTag
)
==
PT_MV_UNICODE
)
{
/* UlPropSize doesn't account for the string pointers */
ulLen
+=
lpSrc
->
Value
.
MVszA
.
cValues
*
sizeof
(
char
*
);
}
else
if
(
PROP_TYPE
(
lpSrc
->
ulPropTag
)
==
PT_MV_BINARY
)
{
/* UlPropSize doesn't account for the SBinary structs */
ulLen
+=
lpSrc
->
Value
.
MVbin
.
cValues
*
sizeof
(
SBinary
);
}
lpDest
->
Value
.
MVi
.
cValues
=
lpSrc
->
Value
.
MVi
.
cValues
;
scode
=
lpMore
(
ulLen
,
lpOrig
,
(
LPVOID
*
)
&
lpDest
->
Value
.
MVi
.
lpi
);
if
(
FAILED
(
scode
))
break
;
/* Note that we could allocate the memory for each value in a
* multi-value property seperately, however if an allocation failed
* we would be left with a bunch of allocated memory, which (while
* not really leaked) is unusable until lpOrig is freed. So for
* strings and binary arrays we make a single allocation for all
* of the data. This is consistent since individual elements can't
* be freed anyway.
*/
switch
(
PROP_TYPE
(
lpSrc
->
ulPropTag
))
{
case
PT_MV_STRING8
:
{
char
*
lpNextStr
=
(
char
*
)(
lpDest
->
Value
.
MVszA
.
lppszA
+
lpDest
->
Value
.
MVszA
.
cValues
);
for
(
i
=
0
;
i
<
lpSrc
->
Value
.
MVszA
.
cValues
;
i
++
)
{
ULONG
ulStrLen
=
lstrlenA
(
lpSrc
->
Value
.
MVszA
.
lppszA
[
i
])
+
1u
;
lpDest
->
Value
.
MVszA
.
lppszA
[
i
]
=
lpNextStr
;
memcpy
(
lpNextStr
,
lpSrc
->
Value
.
MVszA
.
lppszA
[
i
],
ulStrLen
);
lpNextStr
+=
ulStrLen
;
}
break
;
}
case
PT_MV_UNICODE
:
{
WCHAR
*
lpNextStr
=
(
WCHAR
*
)(
lpDest
->
Value
.
MVszW
.
lppszW
+
lpDest
->
Value
.
MVszW
.
cValues
);
for
(
i
=
0
;
i
<
lpSrc
->
Value
.
MVszW
.
cValues
;
i
++
)
{
ULONG
ulStrLen
=
strlenW
(
lpSrc
->
Value
.
MVszW
.
lppszW
[
i
])
+
1u
;
lpDest
->
Value
.
MVszW
.
lppszW
[
i
]
=
lpNextStr
;
memcpy
(
lpNextStr
,
lpSrc
->
Value
.
MVszA
.
lppszA
[
i
],
ulStrLen
*
sizeof
(
WCHAR
));
lpNextStr
+=
ulStrLen
;
}
break
;
}
case
PT_MV_BINARY
:
{
LPBYTE
lpNext
=
(
LPBYTE
)(
lpDest
->
Value
.
MVbin
.
lpbin
+
lpDest
->
Value
.
MVbin
.
cValues
);
for
(
i
=
0
;
i
<
lpSrc
->
Value
.
MVszW
.
cValues
;
i
++
)
{
lpDest
->
Value
.
MVbin
.
lpbin
[
i
].
cb
=
lpSrc
->
Value
.
MVbin
.
lpbin
[
i
].
cb
;
lpDest
->
Value
.
MVbin
.
lpbin
[
i
].
lpb
=
lpNext
;
memcpy
(
lpNext
,
lpSrc
->
Value
.
MVbin
.
lpbin
[
i
].
lpb
,
lpDest
->
Value
.
MVbin
.
lpbin
[
i
].
cb
);
lpNext
+=
lpDest
->
Value
.
MVbin
.
lpbin
[
i
].
cb
;
}
break
;
}
default:
/* No embedded pointers, just copy the data over */
memcpy
(
lpDest
->
Value
.
MVi
.
lpi
,
lpSrc
->
Value
.
MVi
.
lpi
,
ulLen
);
break
;
}
break
;
}
}
return
scode
;
}
/*************************************************************************
* UlPropSize@4 (MAPI32.77)
*
* Determine the size of a property in bytes.
*
* PARAMS
* lpProp [I] Property to determine the size of
*
* RETURNS
* Success: The size of the value in lpProp.
* Failure: 0, if a multi-value (array) property is invalid or the type of lpProp
* is unknown.
*
* NOTES
* - The size returned does not include the size of the SPropValue struct
* or the size of the array of pointers for multi-valued properties that
* contain pointers (such as PT_MV_STRING8 or PT-MV_UNICODE).
* - MSDN incorrectly states that this function returns MAPI_E_CALL_FAILED if
* lpProp is invalid. In reality no checking is performed and this function
* will crash if passed an invalid property, or return 0 if the property
* type is PT_OBJECT or is unknown.
*/
ULONG
WINAPI
UlPropSize
(
LPSPropValue
lpProp
)
{
ULONG
ulRet
=
1u
,
i
;
TRACE
(
"(%p)
\n
"
,
lpProp
);
switch
(
PROP_TYPE
(
lpProp
->
ulPropTag
))
{
case
PT_MV_I2
:
ulRet
=
lpProp
->
Value
.
MVi
.
cValues
;
case
PT_BOOLEAN
:
case
PT_I2
:
ulRet
*=
sizeof
(
USHORT
);
break
;
case
PT_MV_I4
:
ulRet
=
lpProp
->
Value
.
MVl
.
cValues
;
case
PT_ERROR
:
case
PT_I4
:
ulRet
*=
sizeof
(
LONG
);
break
;
case
PT_MV_I8
:
ulRet
=
lpProp
->
Value
.
MVli
.
cValues
;
case
PT_I8
:
ulRet
*=
sizeof
(
LONG64
);
break
;
case
PT_MV_R4
:
ulRet
=
lpProp
->
Value
.
MVflt
.
cValues
;
case
PT_R4
:
ulRet
*=
sizeof
(
float
);
break
;
case
PT_MV_APPTIME
:
case
PT_MV_R8
:
ulRet
=
lpProp
->
Value
.
MVdbl
.
cValues
;
case
PT_APPTIME
:
case
PT_R8
:
ulRet
*=
sizeof
(
double
);
break
;
case
PT_MV_CURRENCY
:
ulRet
=
lpProp
->
Value
.
MVcur
.
cValues
;
case
PT_CURRENCY
:
ulRet
*=
sizeof
(
CY
);
break
;
case
PT_MV_SYSTIME
:
ulRet
=
lpProp
->
Value
.
MVft
.
cValues
;
case
PT_SYSTIME
:
ulRet
*=
sizeof
(
FILETIME
);
break
;
case
PT_MV_CLSID
:
ulRet
=
lpProp
->
Value
.
MVguid
.
cValues
;
case
PT_CLSID
:
ulRet
*=
sizeof
(
GUID
);
break
;
case
PT_MV_STRING8
:
ulRet
=
0u
;
for
(
i
=
0
;
i
<
lpProp
->
Value
.
MVszA
.
cValues
;
i
++
)
ulRet
+=
(
lstrlenA
(
lpProp
->
Value
.
MVszA
.
lppszA
[
i
])
+
1u
);
break
;
case
PT_STRING8
:
ulRet
=
lstrlenA
(
lpProp
->
Value
.
lpszA
)
+
1u
;
break
;
case
PT_MV_UNICODE
:
ulRet
=
0u
;
for
(
i
=
0
;
i
<
lpProp
->
Value
.
MVszW
.
cValues
;
i
++
)
ulRet
+=
(
strlenW
(
lpProp
->
Value
.
MVszW
.
lppszW
[
i
])
+
1u
);
ulRet
*=
sizeof
(
WCHAR
);
break
;
case
PT_UNICODE
:
ulRet
=
(
lstrlenW
(
lpProp
->
Value
.
lpszW
)
+
1u
)
*
sizeof
(
WCHAR
);
break
;
case
PT_MV_BINARY
:
ulRet
=
0u
;
for
(
i
=
0
;
i
<
lpProp
->
Value
.
MVbin
.
cValues
;
i
++
)
ulRet
+=
lpProp
->
Value
.
MVbin
.
lpbin
[
i
].
cb
;
break
;
case
PT_BINARY
:
ulRet
=
lpProp
->
Value
.
bin
.
cb
;
break
;
break
;
case
PT_OBJECT
:
default:
ulRet
=
0u
;
break
;
}
return
ulRet
;
}
/*************************************************************************
* FPropContainsProp@12 (MAPI32.78)
*
* Find a property with a given property tag in a property array.
*
* PARAMS
* lpHaystack [I] Property to match to
* lpNeedle [I] Property to find in lpHaystack
* ulFuzzy [I] Flags controlling match type and strictness (FL_* flags from "mapidefs.h")
*
* RETURNS
* TRUE, if lpNeedle matches lpHaystack according to the criteria of ulFuzzy.
*
* NOTES
* Only property types of PT_STRING8 and PT_BINARY are handled by this function.
*/
BOOL
WINAPI
FPropContainsProp
(
LPSPropValue
lpHaystack
,
LPSPropValue
lpNeedle
,
ULONG
ulFuzzy
)
{
TRACE
(
"(%p,%p,0x%08lx)
\n
"
,
lpHaystack
,
lpNeedle
,
ulFuzzy
);
if
(
FBadProp
(
lpHaystack
)
||
FBadProp
(
lpNeedle
)
||
PROP_TYPE
(
lpHaystack
->
ulPropTag
)
!=
PROP_TYPE
(
lpNeedle
->
ulPropTag
))
return
FALSE
;
/* FIXME: Do later versions support Unicode as well? */
if
(
PROP_TYPE
(
lpHaystack
->
ulPropTag
)
==
PT_STRING8
)
{
DWORD
dwFlags
=
0
,
dwNeedleLen
,
dwHaystackLen
;
if
(
ulFuzzy
&
FL_IGNORECASE
)
dwFlags
|=
NORM_IGNORECASE
;
if
(
ulFuzzy
&
FL_IGNORENONSPACE
)
dwFlags
|=
NORM_IGNORENONSPACE
;
if
(
ulFuzzy
&
FL_LOOSE
)
dwFlags
|=
(
NORM_IGNORECASE
|
NORM_IGNORENONSPACE
|
NORM_IGNORESYMBOLS
);
dwNeedleLen
=
lstrlenA
(
lpNeedle
->
Value
.
lpszA
);
dwHaystackLen
=
lstrlenA
(
lpHaystack
->
Value
.
lpszA
);
if
((
ulFuzzy
&
(
FL_SUBSTRING
|
FL_PREFIX
))
==
FL_PREFIX
)
{
if
(
dwNeedleLen
<=
dwHaystackLen
&&
CompareStringA
(
LOCALE_USER_DEFAULT
,
dwFlags
,
lpHaystack
->
Value
.
lpszA
,
dwNeedleLen
,
lpNeedle
->
Value
.
lpszA
,
dwNeedleLen
)
==
CSTR_EQUAL
)
return
TRUE
;
/* needle is a prefix of haystack */
}
else
if
((
ulFuzzy
&
(
FL_SUBSTRING
|
FL_PREFIX
))
==
FL_SUBSTRING
)
{
LPSTR
(
WINAPI
*
pStrChrFn
)(
LPCSTR
,
WORD
)
=
StrChrA
;
LPSTR
lpStr
=
lpHaystack
->
Value
.
lpszA
;
if
(
dwFlags
&
NORM_IGNORECASE
)
pStrChrFn
=
StrChrIA
;
while
((
lpStr
=
pStrChrFn
(
lpStr
,
*
lpNeedle
->
Value
.
lpszA
))
!=
NULL
)
{
dwHaystackLen
-=
(
lpStr
-
lpHaystack
->
Value
.
lpszA
);
if
(
dwNeedleLen
<=
dwHaystackLen
&&
CompareStringA
(
LOCALE_USER_DEFAULT
,
dwFlags
,
lpStr
,
dwNeedleLen
,
lpNeedle
->
Value
.
lpszA
,
dwNeedleLen
)
==
CSTR_EQUAL
)
return
TRUE
;
/* needle is a substring of haystack */
lpStr
++
;
}
}
else
if
(
CompareStringA
(
LOCALE_USER_DEFAULT
,
dwFlags
,
lpHaystack
->
Value
.
lpszA
,
dwHaystackLen
,
lpNeedle
->
Value
.
lpszA
,
dwNeedleLen
)
==
CSTR_EQUAL
)
return
TRUE
;
/* full string match */
}
else
if
(
PROP_TYPE
(
lpHaystack
->
ulPropTag
)
==
PT_BINARY
)
{
if
((
ulFuzzy
&
(
FL_SUBSTRING
|
FL_PREFIX
))
==
FL_PREFIX
)
{
if
(
lpNeedle
->
Value
.
bin
.
cb
<=
lpHaystack
->
Value
.
bin
.
cb
&&
!
memcmp
(
lpNeedle
->
Value
.
bin
.
lpb
,
lpHaystack
->
Value
.
bin
.
lpb
,
lpNeedle
->
Value
.
bin
.
cb
))
return
TRUE
;
/* needle is a prefix of haystack */
}
else
if
((
ulFuzzy
&
(
FL_SUBSTRING
|
FL_PREFIX
))
==
FL_SUBSTRING
)
{
ULONG
ulLen
=
lpHaystack
->
Value
.
bin
.
cb
;
LPBYTE
lpb
=
lpHaystack
->
Value
.
bin
.
lpb
;
while
((
lpb
=
memchr
(
lpb
,
*
lpNeedle
->
Value
.
bin
.
lpb
,
ulLen
))
!=
NULL
)
{
ulLen
=
lpHaystack
->
Value
.
bin
.
cb
-
(
lpb
-
lpHaystack
->
Value
.
bin
.
lpb
);
if
(
lpNeedle
->
Value
.
bin
.
cb
<=
ulLen
&&
!
memcmp
(
lpNeedle
->
Value
.
bin
.
lpb
,
lpb
,
lpNeedle
->
Value
.
bin
.
cb
))
return
TRUE
;
/* needle is a substring of haystack */
lpb
++
;
}
}
else
if
(
!
LPropCompareProp
(
lpHaystack
,
lpNeedle
))
return
TRUE
;
/* needle is an exact match with haystack */
}
return
FALSE
;
}
/*************************************************************************
* FPropCompareProp@12 (MAPI32.79)
*
* Compare two properties.
*
* PARAMS
* lpPropLeft [I] Left hand property to compare to lpPropRight
* ulOp [I] Comparason operator (RELOP_* enum from "mapidefs.h")
* lpPropRight [I] Right hand property to compare to lpPropLeft
*
* RETURNS
* TRUE, if the comparason is true, FALSE otherwise.
*/
BOOL
WINAPI
FPropCompareProp
(
LPSPropValue
lpPropLeft
,
ULONG
ulOp
,
LPSPropValue
lpPropRight
)
{
LONG
iCmp
;
TRACE
(
"(%p,%ld,%p)
\n
"
,
lpPropLeft
,
ulOp
,
lpPropRight
);
if
(
ulOp
>
RELOP_RE
||
FBadProp
(
lpPropLeft
)
||
FBadProp
(
lpPropRight
))
return
FALSE
;
if
(
ulOp
==
RELOP_RE
)
{
FIXME
(
"Comparason operator RELOP_RE not yet implemented!
\n
"
);
return
FALSE
;
}
iCmp
=
LPropCompareProp
(
lpPropLeft
,
lpPropRight
);
switch
(
ulOp
)
{
case
RELOP_LT
:
return
iCmp
<
0
?
TRUE
:
FALSE
;
case
RELOP_LE
:
return
iCmp
<=
0
?
TRUE
:
FALSE
;
case
RELOP_GT
:
return
iCmp
>
0
?
TRUE
:
FALSE
;
case
RELOP_GE
:
return
iCmp
>=
0
?
TRUE
:
FALSE
;
case
RELOP_EQ
:
return
iCmp
==
0
?
TRUE
:
FALSE
;
case
RELOP_NE
:
return
iCmp
!=
0
?
TRUE
:
FALSE
;
}
return
FALSE
;
}
/*************************************************************************
* LPropCompareProp@8 (MAPI32.80)
*
* Compare two properties.
*
* PARAMS
* lpPropLeft [I] Left hand property to compare to lpPropRight
* lpPropRight [I] Right hand property to compare to lpPropLeft
*
* RETURNS
* An integer less than, equal to or greater than 0, indicating that
* lpszStr is less than, the same, or greater than lpszComp.
*/
LONG
WINAPI
LPropCompareProp
(
LPSPropValue
lpPropLeft
,
LPSPropValue
lpPropRight
)
{
LONG
iRet
;
TRACE
(
"(%p->0x%08lx,%p->0x%08lx)
\n
"
,
lpPropLeft
,
lpPropLeft
->
ulPropTag
,
lpPropRight
,
lpPropRight
->
ulPropTag
);
/* If the properties are not the same, sort by property type */
if
(
PROP_TYPE
(
lpPropLeft
->
ulPropTag
)
!=
PROP_TYPE
(
lpPropRight
->
ulPropTag
))
return
(
LONG
)
PROP_TYPE
(
lpPropLeft
->
ulPropTag
)
-
(
LONG
)
PROP_TYPE
(
lpPropRight
->
ulPropTag
);
switch
(
PROP_TYPE
(
lpPropLeft
->
ulPropTag
))
{
case
PT_UNSPECIFIED
:
case
PT_NULL
:
return
0
;
/* NULLs are equal */
case
PT_I2
:
return
lpPropLeft
->
Value
.
i
-
lpPropRight
->
Value
.
i
;
case
PT_I4
:
return
lpPropLeft
->
Value
.
l
-
lpPropRight
->
Value
.
l
;
case
PT_I8
:
if
(
lpPropLeft
->
Value
.
li
.
QuadPart
>
lpPropRight
->
Value
.
li
.
QuadPart
)
return
1
;
if
(
lpPropLeft
->
Value
.
li
.
QuadPart
==
lpPropRight
->
Value
.
li
.
QuadPart
)
return
0
;
return
-
1
;
case
PT_R4
:
if
(
lpPropLeft
->
Value
.
flt
>
lpPropRight
->
Value
.
flt
)
return
1
;
if
(
lpPropLeft
->
Value
.
flt
==
lpPropRight
->
Value
.
flt
)
return
0
;
return
-
1
;
case
PT_APPTIME
:
case
PT_R8
:
if
(
lpPropLeft
->
Value
.
dbl
>
lpPropRight
->
Value
.
dbl
)
return
1
;
if
(
lpPropLeft
->
Value
.
dbl
==
lpPropRight
->
Value
.
dbl
)
return
0
;
return
-
1
;
case
PT_CURRENCY
:
if
(
lpPropLeft
->
Value
.
cur
.
int64
>
lpPropRight
->
Value
.
cur
.
int64
)
return
1
;
if
(
lpPropLeft
->
Value
.
cur
.
int64
==
lpPropRight
->
Value
.
cur
.
int64
)
return
0
;
return
-
1
;
case
PT_SYSTIME
:
return
CompareFileTime
(
&
lpPropLeft
->
Value
.
ft
,
&
lpPropRight
->
Value
.
ft
);
case
PT_BOOLEAN
:
return
(
lpPropLeft
->
Value
.
b
?
1
:
0
)
-
(
lpPropRight
->
Value
.
b
?
1
:
0
);
case
PT_BINARY
:
if
(
lpPropLeft
->
Value
.
bin
.
cb
==
lpPropRight
->
Value
.
bin
.
cb
)
iRet
=
memcmp
(
lpPropLeft
->
Value
.
bin
.
lpb
,
lpPropRight
->
Value
.
bin
.
lpb
,
lpPropLeft
->
Value
.
bin
.
cb
);
else
{
iRet
=
memcmp
(
lpPropLeft
->
Value
.
bin
.
lpb
,
lpPropRight
->
Value
.
bin
.
lpb
,
min
(
lpPropLeft
->
Value
.
bin
.
cb
,
lpPropRight
->
Value
.
bin
.
cb
));
if
(
!
iRet
)
iRet
=
lpPropLeft
->
Value
.
bin
.
cb
-
lpPropRight
->
Value
.
bin
.
cb
;
}
return
iRet
;
case
PT_STRING8
:
return
lstrcmpA
(
lpPropLeft
->
Value
.
lpszA
,
lpPropRight
->
Value
.
lpszA
);
case
PT_UNICODE
:
return
strcmpW
(
lpPropLeft
->
Value
.
lpszW
,
lpPropRight
->
Value
.
lpszW
);
case
PT_ERROR
:
if
(
lpPropLeft
->
Value
.
err
>
lpPropRight
->
Value
.
err
)
return
1
;
if
(
lpPropLeft
->
Value
.
err
==
lpPropRight
->
Value
.
err
)
return
0
;
return
-
1
;
case
PT_CLSID
:
return
memcmp
(
lpPropLeft
->
Value
.
lpguid
,
lpPropRight
->
Value
.
lpguid
,
sizeof
(
GUID
));
}
FIXME
(
"Unhandled property type %ld"
,
PROP_TYPE
(
lpPropLeft
->
ulPropTag
));
return
0
;
}
/*************************************************************************
* PpropFindProp@12 (MAPI32.138)
*
* Find a property with a given property tag in a property array.
*
* PARAMS
* lpProps [I] Property array to search
* cValues [I] Number of properties in lpProps
* ulPropTag [I] Property tag to find
*
* RETURNS
* A pointer to the matching property, or NULL if none was found.
*
* NOTES
* if ulPropTag has a property type of PT_UNSPECIFIED, then only the property
* Ids need to match for a successful match to occur.
*/
LPSPropValue
WINAPI
PpropFindProp
(
LPSPropValue
lpProps
,
ULONG
cValues
,
ULONG
ulPropTag
)
{
TRACE
(
"(%p,%ld,%ld)
\n
"
,
lpProps
,
cValues
,
ulPropTag
);
if
(
lpProps
&&
cValues
)
{
ULONG
i
;
for
(
i
=
0
;
i
<
cValues
;
i
++
)
{
if
(
!
FBadPropTag
(
lpProps
[
i
].
ulPropTag
)
&&
(
lpProps
[
i
].
ulPropTag
==
ulPropTag
||
(
PROP_TYPE
(
ulPropTag
)
==
PT_UNSPECIFIED
&&
PROP_ID
(
lpProps
[
i
].
ulPropTag
)
==
PROP_ID
(
ulPropTag
))))
return
&
lpProps
[
i
];
}
}
return
NULL
;
}
/*************************************************************************
* ScCountProps@12 (MAPI32.170)
*
* Validate and determine the length of an array of properties.
*
* PARAMS
* iCount [I] Length of the lpProps array
* lpProps [I] Array of properties to validate/size
* pcBytes [O] If non-NULL, destination for the size of the property array
*
* RETURNS
* Success: S_OK. If pcBytes is non-NULL, it contains the size of the propery array.
* Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid or validation
* of the property array fails.
*/
SCODE
WINAPI
ScCountProps
(
INT
iCount
,
LPSPropValue
lpProps
,
ULONG
*
pcBytes
)
{
ULONG
i
,
ulCount
=
iCount
,
ulBytes
=
0
;
TRACE
(
"(%d,%p,%p)
\n
"
,
iCount
,
lpProps
,
pcBytes
);
if
(
iCount
<=
0
||
!
lpProps
||
IsBadReadPtr
(
lpProps
,
iCount
*
sizeof
(
SPropValue
)))
return
MAPI_E_INVALID_PARAMETER
;
for
(
i
=
0
;
i
<
ulCount
;
i
++
)
{
ULONG
ulPropSize
=
0
;
if
(
FBadProp
(
&
lpProps
[
i
])
||
lpProps
[
i
].
ulPropTag
==
PROP_ID_NULL
||
lpProps
[
i
].
ulPropTag
==
PROP_ID_INVALID
)
return
MAPI_E_INVALID_PARAMETER
;
if
(
PROP_TYPE
(
lpProps
[
i
].
ulPropTag
)
!=
PT_OBJECT
)
{
ulPropSize
=
UlPropSize
(
&
lpProps
[
i
]);
if
(
!
ulPropSize
)
return
MAPI_E_INVALID_PARAMETER
;
}
switch
(
PROP_TYPE
(
lpProps
[
i
].
ulPropTag
))
{
case
PT_STRING8
:
case
PT_UNICODE
:
case
PT_CLSID
:
case
PT_BINARY
:
case
PT_MV_I2
:
case
PT_MV_I4
:
case
PT_MV_I8
:
case
PT_MV_R4
:
case
PT_MV_R8
:
case
PT_MV_CURRENCY
:
case
PT_MV_SYSTIME
:
case
PT_MV_APPTIME
:
ulPropSize
+=
sizeof
(
SPropValue
);
break
;
case
PT_MV_CLSID
:
ulPropSize
+=
lpProps
[
i
].
Value
.
MVszA
.
cValues
*
sizeof
(
char
*
)
+
sizeof
(
SPropValue
);
break
;
case
PT_MV_STRING8
:
case
PT_MV_UNICODE
:
ulPropSize
+=
lpProps
[
i
].
Value
.
MVszA
.
cValues
*
sizeof
(
char
*
)
+
sizeof
(
SPropValue
);
break
;
case
PT_MV_BINARY
:
ulPropSize
+=
lpProps
[
i
].
Value
.
MVbin
.
cValues
*
sizeof
(
SBinary
)
+
sizeof
(
SPropValue
);
break
;
default:
ulPropSize
=
sizeof
(
SPropValue
);
break
;
}
ulBytes
+=
ulPropSize
;
}
if
(
pcBytes
)
*
pcBytes
=
ulBytes
;
return
S_OK
;
}
/*************************************************************************
* LpValFindProp@12 (MAPI32.173)
*
* Find a property with a given property id in a property array.
*
* PARAMS
* ulPropTag [I] Property tag containing property id to find
* cValues [I] Number of properties in lpProps
* lpProps [I] Property array to search
*
* RETURNS
* A pointer to the matching property, or NULL if none was found.
*
* NOTES
* This function matches only on the property id and does not care if the
* property types differ.
*/
LPSPropValue
WINAPI
LpValFindProp
(
ULONG
ulPropTag
,
ULONG
cValues
,
LPSPropValue
lpProps
)
{
TRACE
(
"(%ld,%ld,%p)
\n
"
,
ulPropTag
,
cValues
,
lpProps
);
if
(
lpProps
&&
cValues
)
{
ULONG
i
;
for
(
i
=
0
;
i
<
cValues
;
i
++
)
{
if
(
PROP_ID
(
ulPropTag
)
==
PROP_ID
(
lpProps
[
i
].
ulPropTag
))
return
&
lpProps
[
i
];
}
}
return
NULL
;
}
/*************************************************************************
* FBadRglpszA@8 (MAPI32.175)
*
* Determine if an array of strings is invalid
*
* PARAMS
* lppszStrs [I] Array of strings to check
* ulCount [I] Number of strings in lppszStrs
*
* RETURNS
* TRUE, if lppszStrs is invalid, FALSE otherwise.
*/
BOOL
WINAPI
FBadRglpszA
(
LPSTR
*
lppszStrs
,
ULONG
ulCount
)
{
ULONG
i
;
TRACE
(
"(%p,%ld)
\n
"
,
lppszStrs
,
ulCount
);
if
(
!
ulCount
)
return
FALSE
;
if
(
!
lppszStrs
||
IsBadReadPtr
(
lppszStrs
,
ulCount
*
sizeof
(
LPWSTR
)))
return
TRUE
;
for
(
i
=
0
;
i
<
ulCount
;
i
++
)
{
if
(
!
lppszStrs
[
i
]
||
IsBadStringPtrA
(
lppszStrs
[
i
],
-
1
))
return
TRUE
;
}
return
FALSE
;
}
/*************************************************************************
* FBadRglpszW@8 (MAPI32.176)
*
* See FBadRglpszA.
*/
BOOL
WINAPI
FBadRglpszW
(
LPWSTR
*
lppszStrs
,
ULONG
ulCount
)
{
ULONG
i
;
TRACE
(
"(%p,%ld)
\n
"
,
lppszStrs
,
ulCount
);
if
(
!
ulCount
)
return
FALSE
;
if
(
!
lppszStrs
||
IsBadReadPtr
(
lppszStrs
,
ulCount
*
sizeof
(
LPWSTR
)))
return
TRUE
;
for
(
i
=
0
;
i
<
ulCount
;
i
++
)
{
if
(
!
lppszStrs
[
i
]
||
IsBadStringPtrW
(
lppszStrs
[
i
],
-
1
))
return
TRUE
;
}
return
FALSE
;
}
/*************************************************************************
* FBadRowSet@4 (MAPI32.177)
*
* Determine if a row is invalid
*
* PARAMS
* lpRow [I] Row to check
*
* RETURNS
* TRUE, if lpRow is invalid, FALSE otherwise.
*/
BOOL
WINAPI
FBadRowSet
(
LPSRowSet
lpRowSet
)
{
ULONG
i
;
TRACE
(
"(%p)
\n
"
,
lpRowSet
);
if
(
!
lpRowSet
||
IsBadReadPtr
(
lpRowSet
,
CbSRowSet
(
lpRowSet
)))
return
TRUE
;
for
(
i
=
0
;
i
<
lpRowSet
->
cRows
;
i
++
)
{
if
(
FBadRow
(
&
lpRowSet
->
aRow
[
i
]))
return
TRUE
;
}
return
FALSE
;
}
/*************************************************************************
* FBadPropTag@4 (MAPI32.179)
*
* Determine if a property tag is invalid
*
* PARAMS
* ulPropTag [I] Property tag to check
*
* RETURNS
* TRUE, if ulPropTag is invalid, FALSE otherwise.
*/
ULONG
WINAPI
FBadPropTag
(
ULONG
ulPropTag
)
{
TRACE
(
"(0x%08lx)
\n
"
,
ulPropTag
);
switch
(
ulPropTag
&
(
~
MV_FLAG
&
PROP_TYPE_MASK
))
{
case
PT_UNSPECIFIED
:
case
PT_NULL
:
case
PT_I2
:
case
PT_LONG
:
case
PT_R4
:
case
PT_DOUBLE
:
case
PT_CURRENCY
:
case
PT_APPTIME
:
case
PT_ERROR
:
case
PT_BOOLEAN
:
case
PT_OBJECT
:
case
PT_I8
:
case
PT_STRING8
:
case
PT_UNICODE
:
case
PT_SYSTIME
:
case
PT_CLSID
:
case
PT_BINARY
:
return
FALSE
;
}
return
TRUE
;
}
/*************************************************************************
* FBadRow@4 (MAPI32.180)
*
* Determine if a row is invalid
*
* PARAMS
* lpRow [I] Row to check
*
* RETURNS
* TRUE, if lpRow is invalid, FALSE otherwise.
*/
ULONG
WINAPI
FBadRow
(
LPSRow
lpRow
)
{
ULONG
i
;
TRACE
(
"(%p)
\n
"
,
lpRow
);
if
(
!
lpRow
||
IsBadReadPtr
(
lpRow
,
sizeof
(
SRow
))
||
!
lpRow
->
lpProps
||
IsBadReadPtr
(
lpRow
->
lpProps
,
lpRow
->
cValues
*
sizeof
(
SPropValue
)))
return
TRUE
;
for
(
i
=
0
;
i
<
lpRow
->
cValues
;
i
++
)
{
if
(
FBadProp
(
&
lpRow
->
lpProps
[
i
]))
return
TRUE
;
}
return
FALSE
;
}
/*************************************************************************
* FBadProp@4 (MAPI32.181)
*
* Determine if a property is invalid
*
* PARAMS
* lpProp [I] Property to check
*
* RETURNS
* TRUE, if lpProp is invalid, FALSE otherwise.
*/
ULONG
WINAPI
FBadProp
(
LPSPropValue
lpProp
)
{
ULONG
i
;
if
(
!
lpProp
||
IsBadReadPtr
(
lpProp
,
sizeof
(
SPropValue
))
||
FBadPropTag
(
lpProp
->
ulPropTag
))
return
TRUE
;
switch
(
PROP_TYPE
(
lpProp
->
ulPropTag
))
{
/* Single value properties containing pointers */
case
PT_STRING8
:
if
(
!
lpProp
->
Value
.
lpszA
||
IsBadStringPtrA
(
lpProp
->
Value
.
lpszA
,
-
1
))
return
TRUE
;
break
;
case
PT_UNICODE
:
if
(
!
lpProp
->
Value
.
lpszW
||
IsBadStringPtrW
(
lpProp
->
Value
.
lpszW
,
-
1
))
return
TRUE
;
break
;
case
PT_BINARY
:
if
(
IsBadReadPtr
(
lpProp
->
Value
.
bin
.
lpb
,
lpProp
->
Value
.
bin
.
cb
))
return
TRUE
;
break
;
case
PT_CLSID
:
if
(
IsBadReadPtr
(
lpProp
->
Value
.
lpguid
,
sizeof
(
GUID
)))
return
TRUE
;
break
;
/* Multiple value properties (arrays) containing no pointers */
case
PT_MV_I2
:
return
PROP_BadArray
(
lpProp
,
sizeof
(
SHORT
));
case
PT_MV_LONG
:
return
PROP_BadArray
(
lpProp
,
sizeof
(
LONG
));
case
PT_MV_LONGLONG
:
return
PROP_BadArray
(
lpProp
,
sizeof
(
LONG64
));
case
PT_MV_FLOAT
:
return
PROP_BadArray
(
lpProp
,
sizeof
(
float
));
case
PT_MV_SYSTIME
:
return
PROP_BadArray
(
lpProp
,
sizeof
(
FILETIME
));
case
PT_MV_APPTIME
:
case
PT_MV_DOUBLE
:
return
PROP_BadArray
(
lpProp
,
sizeof
(
double
));
case
PT_MV_CURRENCY
:
return
PROP_BadArray
(
lpProp
,
sizeof
(
CY
));
case
PT_MV_CLSID
:
return
PROP_BadArray
(
lpProp
,
sizeof
(
GUID
));
/* Multiple value properties containing pointers */
case
PT_MV_STRING8
:
return
FBadRglpszA
(
lpProp
->
Value
.
MVszA
.
lppszA
,
lpProp
->
Value
.
MVszA
.
cValues
);
case
PT_MV_UNICODE
:
return
FBadRglpszW
(
lpProp
->
Value
.
MVszW
.
lppszW
,
lpProp
->
Value
.
MVszW
.
cValues
);
case
PT_MV_BINARY
:
if
(
PROP_BadArray
(
lpProp
,
sizeof
(
SBinary
)))
return
TRUE
;
for
(
i
=
0
;
i
<
lpProp
->
Value
.
MVszW
.
cValues
;
i
++
)
{
if
(
IsBadReadPtr
(
lpProp
->
Value
.
MVbin
.
lpbin
[
i
].
lpb
,
lpProp
->
Value
.
MVbin
.
lpbin
[
i
].
cb
))
return
TRUE
;
}
break
;
}
return
FALSE
;
}
/*************************************************************************
* FBadColumnSet@4 (MAPI32.182)
*
* Determine if an array of property tags is invalid
*
* PARAMS
* lpCols [I] Property tag array to check
*
* RETURNS
* TRUE, if lpCols is invalid, FALSE otherwise.
*/
ULONG
WINAPI
FBadColumnSet
(
LPSPropTagArray
lpCols
)
{
ULONG
ulRet
=
FALSE
,
i
;
TRACE
(
"(%p)
\n
"
,
lpCols
);
if
(
!
lpCols
||
IsBadReadPtr
(
lpCols
,
CbSPropTagArray
(
lpCols
)))
ulRet
=
TRUE
;
else
{
for
(
i
=
0
;
i
<
lpCols
->
cValues
;
i
++
)
{
if
((
lpCols
->
aulPropTag
[
i
]
&
PROP_TYPE_MASK
)
==
PT_ERROR
||
FBadPropTag
(
lpCols
->
aulPropTag
[
i
]))
{
ulRet
=
TRUE
;
break
;
}
}
}
TRACE
(
"Returning %s
\n
"
,
ulRet
?
"TRUE"
:
"FALSE"
);
return
ulRet
;
}
dlls/mapi32/util.c
0 → 100644
View file @
c79b70d6
/*
* MAPI Utility functions
*
* Copyright 2004 Jon Griffiths
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winerror.h"
#include "winternl.h"
#include "objbase.h"
#include "shlwapi.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "mapival.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
mapi
);
/**************************************************************************
* ScInitMapiUtil (MAPI32.33)
*
* Initialise Mapi utility functions.
*
* PARAMS
* ulReserved [I] Reserved, pass 0.
*
* RETURNS
* Success: S_OK. Mapi utility functions may be called.
* Failure: MAPI_E_INVALID_PARAMETER, if ulReserved is not 0.
*
* NOTES
* Your application does not need to call this function unless it does not
* call MAPIInitialize()/MAPIUninitialize().
*/
SCODE
WINAPI
ScInitMapiUtil
(
ULONG
ulReserved
)
{
FIXME
(
"(0x%08lx)stub!
\n
"
,
ulReserved
);
if
(
ulReserved
)
return
MAPI_E_INVALID_PARAMETER
;
return
S_OK
;
}
/**************************************************************************
* DeinitMapiUtil (MAPI32.34)
*
* Uninitialise Mapi utility functions.
*
* PARAMS
* None.
*
* RETURNS
* Nothing.
*
* NOTES
* Your application does not need to call this function unless it does not
* call MAPIInitialize()/MAPIUninitialize().
*/
VOID
WINAPI
DeinitMapiUtil
(
void
)
{
FIXME
(
"()stub!
\n
"
);
}
typedef
LPVOID
*
LPMAPIALLOCBUFFER
;
/**************************************************************************
* MAPIAllocateBuffer (MAPI32.12)
* MAPIAllocateBuffer@8 (MAPI32.13)
*
* Allocate a block of memory.
*
* PARAMS
* cbSize [I] Size of the block to allocate in bytes
* lppBuffer [O] Destination for pointer to allocated memory
*
* RETURNS
* Success: S_OK. *lppBuffer is filled with a pointer to a memory block of
* length cbSize bytes.
* Failure: MAPI_E_INVALID_PARAMETER, if lppBuffer is NULL.
* MAPI_E_NOT_ENOUGH_MEMORY, if the memory allocation fails.
*
* NOTES
* Memory allocated with this function should be freed with MAPIFreeBuffer().
* Further allocations of memory may be linked to the pointer returned using
* MAPIAllocateMore(). Linked allocations are freed when the initial pointer
* is feed.
*/
SCODE
WINAPI
MAPIAllocateBuffer
(
ULONG
cbSize
,
LPVOID
*
lppBuffer
)
{
LPMAPIALLOCBUFFER
lpBuff
;
TRACE
(
"(%ld,%p)
\n
"
,
cbSize
,
lppBuffer
);
if
(
!
lppBuffer
)
return
E_INVALIDARG
;
lpBuff
=
(
LPMAPIALLOCBUFFER
)
HeapAlloc
(
GetProcessHeap
(),
0
,
cbSize
+
sizeof
(
*
lpBuff
));
if
(
!
lpBuff
)
return
MAPI_E_NOT_ENOUGH_MEMORY
;
TRACE
(
"initial allocation:%p, returning %p
\n
"
,
lpBuff
,
lpBuff
+
1
);
*
lpBuff
++
=
NULL
;
*
lppBuffer
=
lpBuff
;
return
S_OK
;
}
/**************************************************************************
* MAPIAllocateMore (MAPI32.14)
* MAPIAllocateMore@12 (MAPI32.15)
*
* Allocate a block of memory linked to a previous allocation.
*
* PARAMS
* cbSize [I] Size of the block to allocate in bytes
* lpOrig [I] Initial allocation to link to, from MAPIAllocateBuffer()
* lppBuffer [O] Destination for pointer to allocated memory
*
* RETURNS
* Success: S_OK. *lppBuffer is filled with a pointer to a memory block of
* length cbSize bytes.
* Failure: MAPI_E_INVALID_PARAMETER, if lpOrig or lppBuffer is invalid.
* MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails.
*
* NOTES
* Memory allocated with this function and stored in *lppBuffer is freed
* when lpOrig is passed to MAPIFreeBuffer(). It should not be freed independently.
*/
SCODE
WINAPI
MAPIAllocateMore
(
ULONG
cbSize
,
LPVOID
lpOrig
,
LPVOID
*
lppBuffer
)
{
LPMAPIALLOCBUFFER
lpBuff
=
lpOrig
;
TRACE
(
"(%ld,%p,%p)
\n
"
,
cbSize
,
lpOrig
,
lppBuffer
);
if
(
!
lppBuffer
||
!
lpBuff
||
!--
lpBuff
)
return
E_INVALIDARG
;
/* Find the last allocation in the chain */
while
(
*
lpBuff
)
{
TRACE
(
"linked:%p->%p
\n
"
,
lpBuff
,
*
lpBuff
);
lpBuff
=
*
lpBuff
;
}
if
(
SUCCEEDED
(
MAPIAllocateBuffer
(
cbSize
,
lppBuffer
)))
{
*
lpBuff
=
((
LPMAPIALLOCBUFFER
)
*
lppBuffer
)
-
1
;
TRACE
(
"linking %p->%p
\n
"
,
lpBuff
,
*
lpBuff
);
}
return
*
lppBuffer
?
S_OK
:
MAPI_E_NOT_ENOUGH_MEMORY
;
}
/**************************************************************************
* MAPIFreeBuffer (MAPI32.16)
* MAPIFreeBuffer@4 (MAPI32.17)
*
* Free a block of memory and any linked allocations associated with it.
*
* PARAMS
* lpBuffer [I] Memory to free, returned from MAPIAllocateBuffer()
*
* RETURNS
* S_OK.
*/
ULONG
WINAPI
MAPIFreeBuffer
(
LPVOID
lpBuffer
)
{
LPMAPIALLOCBUFFER
lpBuff
=
lpBuffer
;
TRACE
(
"(%p)
\n
"
,
lpBuffer
);
if
(
lpBuff
&&
--
lpBuff
)
{
while
(
lpBuff
)
{
LPVOID
lpFree
=
lpBuff
;
lpBuff
=
*
lpBuff
;
TRACE
(
"linked:%p->%p, freeing %p
\n
"
,
lpFree
,
lpBuff
,
lpFree
);
HeapFree
(
GetProcessHeap
(),
0
,
lpFree
);
}
}
return
S_OK
;
}
/*************************************************************************
* HrThisThreadAdviseSink@8 (MAPI32.42)
*
* Ensure that an advise sink is only notified in its originating thread.
*
* PARAMS
* lpSink [I] IMAPIAdviseSink interface to be protected
* lppNewSink [I] Destination for wrapper IMAPIAdviseSink interface
*
* RETURNS
* Success: S_OK. *lppNewSink contains a new sink to use in place of lpSink.
* Failure: E_INVALIDARG, if any parameter is invalid.
*/
HRESULT
WINAPI
HrThisThreadAdviseSink
(
LPMAPIADVISESINK
lpSink
,
LPMAPIADVISESINK
*
lppNewSink
)
{
FIXME
(
"(%p,%p)semi-stub
\n
"
,
lpSink
,
lppNewSink
);
if
(
!
lpSink
||
!
lppNewSink
)
return
E_INVALIDARG
;
/* Don't wrap the sink for now, just copy it */
*
lppNewSink
=
lpSink
;
IMAPIAdviseSink_AddRef
(
lpSink
);
return
S_OK
;
}
/*************************************************************************
* SwapPlong@8 (MAPI32.47)
*
* Swap the bytes in a ULONG array.
*
* PARAMS
* lpData [O] Array to swap bytes in
* ulLen [I] Number of ULONG element to swap the bytes of
*
* RETURNS
* Nothing.
*/
VOID
WINAPI
SwapPlong
(
PULONG
lpData
,
ULONG
ulLen
)
{
ULONG
i
;
for
(
i
=
0
;
i
<
ulLen
;
i
++
)
lpData
[
i
]
=
RtlUlongByteSwap
(
lpData
[
i
]);
}
/*************************************************************************
* SwapPword@8 (MAPI32.48)
*
* Swap the bytes in a USHORT array.
*
* PARAMS
* lpData [O] Array to swap bytes in
* ulLen [I] Number of USHORT element to swap the bytes of
*
* RETURNS
* Nothing.
*/
VOID
WINAPI
SwapPword
(
PUSHORT
lpData
,
ULONG
ulLen
)
{
ULONG
i
;
for
(
i
=
0
;
i
<
ulLen
;
i
++
)
lpData
[
i
]
=
RtlUshortByteSwap
(
lpData
[
i
]);
}
/**************************************************************************
* MNLS_lstrlenW@4 (MAPI32.62)
*
* Calculate the length of a Unicode string.
*
* PARAMS
* lpszStr [I] String to calculate the length of
*
* RETURNS
* The length of lpszStr in Unicode characters.
*/
ULONG
WINAPI
MNLS_lstrlenW
(
LPCWSTR
lpszStr
)
{
TRACE
(
"(%s)
\n
"
,
debugstr_w
(
lpszStr
));
return
strlenW
(
lpszStr
);
}
/*************************************************************************
* MNLS_lstrcmpW@8 (MAPI32.63)
*
* Compare two Unicode strings.
*
* PARAMS
* lpszLeft [I] First string to compare
* lpszRight [I] Second string to compare
*
* RETURNS
* An integer less than, equal to or greater than 0, indicating that
* lpszLeft is less than, the same, or greater than lpszRight.
*/
INT
WINAPI
MNLS_lstrcmpW
(
LPCWSTR
lpszLeft
,
LPCWSTR
lpszRight
)
{
TRACE
(
"(%s,%s)
\n
"
,
debugstr_w
(
lpszLeft
),
debugstr_w
(
lpszRight
));
return
strcmpW
(
lpszLeft
,
lpszRight
);
}
/*************************************************************************
* MNLS_lstrcpyW@8 (MAPI32.64)
*
* Copy a Unicode string to another string.
*
* PARAMS
* lpszDest [O] Destination string
* lpszSrc [I] Source string
*
* RETURNS
* The length lpszDest in Unicode characters.
*/
ULONG
WINAPI
MNLS_lstrcpyW
(
LPWSTR
lpszDest
,
LPCWSTR
lpszSrc
)
{
ULONG
len
;
TRACE
(
"(%p,%s)
\n
"
,
lpszDest
,
debugstr_w
(
lpszSrc
));
len
=
(
strlenW
(
lpszSrc
)
+
1
)
*
sizeof
(
WCHAR
);
memcpy
(
lpszDest
,
lpszSrc
,
len
);
return
len
;
}
/*************************************************************************
* MNLS_CompareStringW@12 (MAPI32.65)
*
* Compare two Unicode strings.
*
* PARAMS
* dwCp [I] Copde page for the comparason
* lpszLeft [I] First string to compare
* lpszRight [I] Second string to compare
*
* RETURNS
* CSTR_LESS_THAN, CSTR_EQUAL or CSTR_GREATER_THAN, indicating that
* lpszLeft is less than, the same, or greater than lpszRight.
*/
INT
WINAPI
MNLS_CompareStringW
(
DWORD
dwCp
,
LPCWSTR
lpszLeft
,
LPCWSTR
lpszRight
)
{
INT
ret
;
TRACE
(
"0x%08lx,%s,%s
\n
"
,
dwCp
,
debugstr_w
(
lpszLeft
),
debugstr_w
(
lpszRight
));
ret
=
MNLS_lstrcmpW
(
lpszLeft
,
lpszRight
);
return
ret
<
0
?
CSTR_LESS_THAN
:
ret
?
CSTR_GREATER_THAN
:
CSTR_EQUAL
;
}
/**************************************************************************
* FtAddFt@16 (MAPI32.121)
*
* Add two FILETIME's together.
*
* PARAMS
* ftLeft [I] FILETIME to add to ftRight
* ftRight [I] FILETIME to add to ftLeft
*
* RETURNS
* The sum of ftLeft and ftRight
*/
LONGLONG
WINAPI
MAPI32_FtAddFt
(
FILETIME
ftLeft
,
FILETIME
ftRight
)
{
LONGLONG
*
pl
=
(
LONGLONG
*
)
&
ftLeft
,
*
pr
=
(
LONGLONG
*
)
&
ftRight
;
return
*
pl
+
*
pr
;
}
/**************************************************************************
* FtSubFt@16 (MAPI32.123)
*
* Subtract two FILETIME's together.
*
* PARAMS
* ftLeft [I] Initial FILETIME
* ftRight [I] FILETIME to subtract from ftLeft
*
* RETURNS
* The remainder after ftRight is subtracted from ftLeft.
*/
LONGLONG
WINAPI
MAPI32_FtSubFt
(
FILETIME
ftLeft
,
FILETIME
ftRight
)
{
LONGLONG
*
pl
=
(
LONGLONG
*
)
&
ftLeft
,
*
pr
=
(
LONGLONG
*
)
&
ftRight
;
return
*
pr
-
*
pl
;
}
/**************************************************************************
* FtMulDw@12 (MAPI32.124)
*
* Multiply a FILETIME by a DWORD.
*
* PARAMS
* dwLeft [I] DWORD to multiply with ftRight
* ftRight [I] FILETIME to multiply with dwLeft
*
* RETURNS
* The product of dwLeft and ftRight
*/
LONGLONG
WINAPI
MAPI32_FtMulDw
(
DWORD
dwLeft
,
FILETIME
ftRight
)
{
LONGLONG
*
pr
=
(
LONGLONG
*
)
&
ftRight
;
return
(
LONGLONG
)
dwLeft
*
(
*
pr
);
}
/**************************************************************************
* FtMulDwDw@8 (MAPI32.125)
*
* Multiply two DWORD, giving the result as a FILETIME.
*
* PARAMS
* dwLeft [I] DWORD to multiply with dwRight
* dwRight [I] DWORD to multiply with dwLeft
*
* RETURNS
* The product of ftMultiplier and ftMultiplicand as a FILETIME.
*/
LONGLONG
WINAPI
MAPI32_FtMulDwDw
(
DWORD
dwLeft
,
DWORD
dwRight
)
{
return
(
LONGLONG
)
dwLeft
*
(
LONGLONG
)
dwRight
;
}
/**************************************************************************
* FtNegFt@8 (MAPI32.126)
*
* Negate a FILETIME.
*
* PARAMS
* ft [I] FILETIME to negate
*
* RETURNS
* The negation of ft.
*/
LONGLONG
WINAPI
MAPI32_FtNegFt
(
FILETIME
ft
)
{
LONGLONG
*
p
=
(
LONGLONG
*
)
&
ft
;
return
-
*
p
;
}
/**************************************************************************
* UlAddRef@4 (MAPI32.128)
*
* Add a reference to an object.
*
* PARAMS
* lpUnk [I] Object to add a reference to.
*
* RETURNS
* The new reference count of the object, or 0 if lpUnk is NULL.
*
* NOTES
* See IUnknown_AddRef.
*/
ULONG
WINAPI
UlAddRef
(
void
*
lpUnk
)
{
TRACE
(
"(%p)
\n
"
,
lpUnk
);
if
(
!
lpUnk
)
return
0UL
;
return
IUnknown_AddRef
((
LPUNKNOWN
)
lpUnk
);
}
/**************************************************************************
* UlRelease@4 (MAPI32.129)
*
* Remove a reference from an object.
*
* PARAMS
* lpUnk [I] Object to remove reference from.
*
* RETURNS
* The new reference count of the object, or 0 if lpUnk is NULL. If lpUnk is
* non-NULL and this function returns 0, the object pointed to by lpUnk has
* been released.
*
* NOTES
* See IUnknown_Release.
*/
ULONG
WINAPI
UlRelease
(
void
*
lpUnk
)
{
TRACE
(
"(%p)
\n
"
,
lpUnk
);
if
(
!
lpUnk
)
return
0UL
;
return
IUnknown_Release
((
LPUNKNOWN
)
lpUnk
);
}
/*************************************************************************
* OpenStreamOnFile@24 (MAPI32.147)
*
* Create a stream on a file.
*
* PARAMS
* lpAlloc [I] Memory allocation function
* lpFree [I] Memory free function
* ulFlags [I] Flags controlling the opening process
* lpszPath [I] Path of file to create stream on
* lpszPrefix [I] Prefix of the temporary file name (if ulFlags includes SOF_UNIQUEFILENAME)
* lppStream [O] Destination for created stream
*
* RETURNS
* Success: S_OK. lppStream contains the new stream object
* Failure: E_INVALIDARG if any parameter is invalid, or an HRESULT error code
* describing the error.
*/
HRESULT
WINAPI
OpenStreamOnFile
(
LPALLOCATEBUFFER
lpAlloc
,
LPFREEBUFFER
lpFree
,
ULONG
ulFlags
,
LPWSTR
lpszPath
,
LPWSTR
lpszPrefix
,
LPSTREAM
*
lppStream
)
{
WCHAR
szBuff
[
MAX_PATH
];
DWORD
dwMode
=
STGM_READWRITE
,
dwAttributes
=
0
;
HRESULT
hRet
;
TRACE
(
"(%p,%p,0x%08lx,%s,%s,%p)
\n
"
,
lpAlloc
,
lpFree
,
ulFlags
,
debugstr_a
((
LPSTR
)
lpszPath
),
debugstr_a
((
LPSTR
)
lpszPrefix
),
lppStream
);
if
(
lppStream
)
*
lppStream
=
NULL
;
if
(
ulFlags
&
SOF_UNIQUEFILENAME
)
{
FIXME
(
"Should generate a temporary name
\n
"
);
return
E_INVALIDARG
;
}
if
(
!
lpszPath
||
!
lppStream
)
return
E_INVALIDARG
;
/* FIXME: Should probably munge mode and attributes, and should handle
* Unicode arguments (I assume MAPI_UNICODE is set in ulFlags if
* we are being passed Unicode strings; MSDN doesn't say).
* This implementation is just enough for Outlook97 to start.
*/
MultiByteToWideChar
(
CP_ACP
,
0
,
(
LPSTR
)
lpszPath
,
-
1
,
szBuff
,
MAX_PATH
);
hRet
=
SHCreateStreamOnFileEx
(
szBuff
,
dwMode
,
dwAttributes
,
TRUE
,
NULL
,
lppStream
);
return
hRet
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment