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
bb5056ea
Commit
bb5056ea
authored
Jan 27, 2017
by
Jacek Caban
Committed by
Alexandre Julliard
Jan 30, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
inetcomm: Moved sub_stream_t implementation before MimeBody implementation.
Signed-off-by:
Jacek Caban
<
jacek@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
a8ab3107
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
1142 additions
and
1145 deletions
+1142
-1145
mimeole.c
dlls/inetcomm/mimeole.c
+1142
-1145
No files found.
dlls/inetcomm/mimeole.c
View file @
bb5056ea
...
...
@@ -166,1550 +166,1547 @@ typedef struct MimeBody
BODYOFFSETS
body_offsets
;
}
MimeBody
;
static
inline
MimeBody
*
impl_from_IMimeBody
(
IMimeBody
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
MimeBody
,
IMimeBody_iface
);
}
typedef
struct
propschema
typedef
struct
{
I
MimePropertySchema
IMimePropertySchema
_iface
;
I
Stream
IStream
_iface
;
LONG
ref
;
}
propschema
;
IStream
*
base
;
ULARGE_INTEGER
pos
,
start
,
length
;
}
sub_stream_t
;
static
inline
propschema
*
impl_from_IMimePropertySchema
(
IMimePropertySchema
*
iface
)
static
inline
sub_stream_t
*
impl_from_IStream
(
IStream
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
propschema
,
IMimePropertySchema
_iface
);
return
CONTAINING_RECORD
(
iface
,
sub_stream_t
,
IStream
_iface
);
}
static
LPSTR
strdupA
(
LPCSTR
str
)
static
HRESULT
WINAPI
sub_stream_QueryInterface
(
IStream
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
char
*
ret
;
int
len
=
strlen
(
str
);
ret
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
+
1
);
memcpy
(
ret
,
str
,
len
+
1
);
return
ret
;
sub_stream_t
*
This
=
impl_from_IStream
(
iface
);
TRACE
(
"(%p)->(%s, %p)
\n
"
,
This
,
debugstr_guid
(
riid
),
ppv
);
*
ppv
=
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
)
||
IsEqualIID
(
riid
,
&
IID_ISequentialStream
)
||
IsEqualIID
(
riid
,
&
IID_IStream
))
{
IStream_AddRef
(
iface
);
*
ppv
=
iface
;
return
S_OK
;
}
return
E_NOINTERFACE
;
}
#define PARSER_BUF_SIZE 1024
static
ULONG
WINAPI
sub_stream_AddRef
(
IStream
*
iface
)
{
sub_stream_t
*
This
=
impl_from_IStream
(
iface
);
LONG
ref
=
InterlockedIncrement
(
&
This
->
ref
);
/*****************************************************
* copy_headers_to_buf [internal]
*
* Copies the headers into a '\0' terminated memory block and leave
* the stream's current position set to after the blank line.
*/
static
HRESULT
copy_headers_to_buf
(
IStream
*
stm
,
char
**
ptr
)
TRACE
(
"(%p) ref=%d
\n
"
,
This
,
ref
);
return
ref
;
}
static
ULONG
WINAPI
sub_stream_Release
(
IStream
*
iface
)
{
char
*
buf
=
NULL
;
DWORD
size
=
PARSER_BUF_SIZE
,
offset
=
0
,
last_end
=
0
;
HRESULT
hr
;
BOOL
done
=
FALSE
;
sub_stream_t
*
This
=
impl_from_IStream
(
iface
);
LONG
ref
=
InterlockedDecrement
(
&
This
->
ref
);
*
ptr
=
NULL
;
TRACE
(
"(%p) ref=%d
\n
"
,
This
,
ref
)
;
do
if
(
!
ref
)
{
char
*
end
;
DWORD
read
;
IStream_Release
(
This
->
base
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
}
return
ref
;
}
if
(
!
buf
)
buf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
+
1
);
else
{
size
*=
2
;
buf
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
buf
,
size
+
1
);
}
if
(
!
buf
)
{
hr
=
E_OUTOFMEMORY
;
goto
fail
;
}
static
HRESULT
WINAPI
sub_stream_Read
(
IStream
*
iface
,
void
*
pv
,
ULONG
cb
,
ULONG
*
pcbRead
)
{
sub_stream_t
*
This
=
impl_from_IStream
(
iface
);
HRESULT
hr
;
ULARGE_INTEGER
base_pos
;
LARGE_INTEGER
tmp_pos
;
hr
=
IStream_Read
(
stm
,
buf
+
offset
,
size
-
offset
,
&
read
);
if
(
FAILED
(
hr
))
goto
fail
;
TRACE
(
"(%p, %d, %p)
\n
"
,
pv
,
cb
,
pcbRead
);
offset
+=
read
;
buf
[
offset
]
=
'\0'
;
tmp_pos
.
QuadPart
=
0
;
IStream_Seek
(
This
->
base
,
tmp_pos
,
STREAM_SEEK_CUR
,
&
base_pos
);
tmp_pos
.
QuadPart
=
This
->
pos
.
QuadPart
+
This
->
start
.
QuadPart
;
IStream_Seek
(
This
->
base
,
tmp_pos
,
STREAM_SEEK_SET
,
NULL
);
if
(
read
==
0
)
done
=
TRUE
;
if
(
This
->
pos
.
QuadPart
+
cb
>
This
->
length
.
QuadPart
)
cb
=
This
->
length
.
QuadPart
-
This
->
pos
.
QuadPart
;
while
(
!
done
&&
(
end
=
strstr
(
buf
+
last_end
,
"
\r\n
"
)))
{
DWORD
new_end
=
end
-
buf
+
2
;
if
(
new_end
-
last_end
==
2
)
{
LARGE_INTEGER
off
;
off
.
QuadPart
=
new_end
;
IStream_Seek
(
stm
,
off
,
STREAM_SEEK_SET
,
NULL
);
buf
[
new_end
]
=
'\0'
;
done
=
TRUE
;
}
else
last_end
=
new_end
;
}
}
while
(
!
done
);
hr
=
IStream_Read
(
This
->
base
,
pv
,
cb
,
pcbRead
);
*
ptr
=
buf
;
return
S_OK
;
This
->
pos
.
QuadPart
+=
*
pcbRead
;
tmp_pos
.
QuadPart
=
base_pos
.
QuadPart
;
IStream_Seek
(
This
->
base
,
tmp_pos
,
STREAM_SEEK_SET
,
NULL
);
fail:
HeapFree
(
GetProcessHeap
(),
0
,
buf
);
return
hr
;
}
static
header_t
*
read_prop
(
MimeBody
*
body
,
char
**
ptr
)
static
HRESULT
WINAPI
sub_stream_Write
(
IStream
*
iface
,
const
void
*
pv
,
ULONG
cb
,
ULONG
*
pcbWritten
)
{
char
*
colon
=
strchr
(
*
ptr
,
':'
);
const
property_t
*
prop
;
header_t
*
ret
;
FIXME
(
"stub
\n
"
);
return
E_NOTIMPL
;
}
if
(
!
colon
)
return
NULL
;
static
HRESULT
WINAPI
sub_stream_Seek
(
IStream
*
iface
,
LARGE_INTEGER
dlibMove
,
DWORD
dwOrigin
,
ULARGE_INTEGER
*
plibNewPosition
)
{
sub_stream_t
*
This
=
impl_from_IStream
(
iface
);
LARGE_INTEGER
new_pos
;
*
colon
=
'\0'
;
TRACE
(
"(%08x.%08x, %x, %p)
\n
"
,
dlibMove
.
u
.
HighPart
,
dlibMove
.
u
.
LowPart
,
dwOrigin
,
plibNewPosition
)
;
for
(
prop
=
default_props
;
prop
->
name
;
prop
++
)
switch
(
dwOrigin
)
{
if
(
!
lstrcmpiA
(
*
ptr
,
prop
->
name
))
{
TRACE
(
"%s: found match with default property id %d
\n
"
,
*
ptr
,
prop
->
id
);
break
;
}
case
STREAM_SEEK_SET
:
new_pos
=
dlibMove
;
break
;
case
STREAM_SEEK_CUR
:
new_pos
.
QuadPart
=
This
->
pos
.
QuadPart
+
dlibMove
.
QuadPart
;
break
;
case
STREAM_SEEK_END
:
new_pos
.
QuadPart
=
This
->
length
.
QuadPart
+
dlibMove
.
QuadPart
;
break
;
default:
return
STG_E_INVALIDFUNCTION
;
}
if
(
!
prop
->
name
)
{
property_list_entry_t
*
prop_entry
;
LIST_FOR_EACH_ENTRY
(
prop_entry
,
&
body
->
new_props
,
property_list_entry_t
,
entry
)
{
if
(
!
lstrcmpiA
(
*
ptr
,
prop_entry
->
prop
.
name
))
{
TRACE
(
"%s: found match with already added new property id %d
\n
"
,
*
ptr
,
prop_entry
->
prop
.
id
);
prop
=
&
prop_entry
->
prop
;
break
;
}
}
if
(
!
prop
->
name
)
{
prop_entry
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
prop_entry
));
prop_entry
->
prop
.
name
=
strdupA
(
*
ptr
);
prop_entry
->
prop
.
id
=
body
->
next_prop_id
++
;
prop_entry
->
prop
.
flags
=
0
;
prop_entry
->
prop
.
default_vt
=
VT_LPSTR
;
list_add_tail
(
&
body
->
new_props
,
&
prop_entry
->
entry
);
prop
=
&
prop_entry
->
prop
;
TRACE
(
"%s: allocating new prop id %d
\n
"
,
*
ptr
,
prop_entry
->
prop
.
id
);
}
}
if
(
new_pos
.
QuadPart
<
0
)
new_pos
.
QuadPart
=
0
;
else
if
(
new_pos
.
QuadPart
>
This
->
length
.
QuadPart
)
new_pos
.
QuadPart
=
This
->
length
.
QuadPart
;
ret
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
ret
));
ret
->
prop
=
prop
;
PropVariantInit
(
&
ret
->
value
);
list_init
(
&
ret
->
params
);
*
ptr
=
colon
+
1
;
This
->
pos
.
QuadPart
=
new_pos
.
QuadPart
;
return
ret
;
if
(
plibNewPosition
)
*
plibNewPosition
=
This
->
pos
;
return
S_OK
;
}
static
void
unfold_header
(
char
*
header
,
int
len
)
static
HRESULT
WINAPI
sub_stream_SetSize
(
IStream
*
iface
,
ULARGE_INTEGER
libNewSize
)
{
char
*
start
=
header
,
*
cp
=
header
;
do
{
while
(
*
cp
==
' '
||
*
cp
==
'\t'
)
{
cp
++
;
len
--
;
}
if
(
cp
!=
start
)
memmove
(
start
,
cp
,
len
+
1
);
cp
=
strstr
(
start
,
"
\r\n
"
);
len
-=
(
cp
-
start
);
start
=
cp
;
*
start
=
' '
;
start
++
;
len
--
;
cp
+=
2
;
}
while
(
*
cp
==
' '
||
*
cp
==
'\t'
);
*
(
start
-
1
)
=
'\0'
;
FIXME
(
"stub
\n
"
);
return
E_NOTIMPL
;
}
static
char
*
unquote_string
(
const
char
*
str
)
static
HRESULT
WINAPI
sub_stream_CopyTo
(
IStream
*
iface
,
IStream
*
pstm
,
ULARGE_INTEGER
cb
,
ULARGE_INTEGER
*
pcbRead
,
ULARGE_INTEGER
*
pcbWritten
)
{
BOOL
quoted
=
FALSE
;
char
*
ret
,
*
cp
;
HRESULT
hr
=
S_OK
;
BYTE
tmpBuffer
[
128
];
ULONG
bytesRead
,
bytesWritten
,
copySize
;
ULARGE_INTEGER
totalBytesRead
;
ULARGE_INTEGER
totalBytesWritten
;
while
(
*
str
==
' '
||
*
str
==
'\t'
)
str
++
;
TRACE
(
"(%p)->(%p, %d, %p, %p)
\n
"
,
iface
,
pstm
,
cb
.
u
.
LowPart
,
pcbRead
,
pcbWritten
)
;
if
(
*
str
==
'"'
)
totalBytesRead
.
QuadPart
=
0
;
totalBytesWritten
.
QuadPart
=
0
;
while
(
cb
.
QuadPart
>
0
)
{
quoted
=
TRUE
;
str
++
;
}
ret
=
strdupA
(
str
);
for
(
cp
=
ret
;
*
cp
;
cp
++
)
{
if
(
*
cp
==
'\\'
)
memmove
(
cp
,
cp
+
1
,
strlen
(
cp
+
1
)
+
1
);
else
if
(
*
cp
==
'"'
)
{
if
(
!
quoted
)
{
WARN
(
"quote in unquoted string
\n
"
);
}
else
{
*
cp
=
'\0'
;
break
;
}
}
}
return
ret
;
}
if
(
cb
.
QuadPart
>=
sizeof
(
tmpBuffer
)
)
copySize
=
sizeof
(
tmpBuffer
);
else
copySize
=
cb
.
u
.
LowPart
;
static
void
add_param
(
header_t
*
header
,
const
char
*
p
)
{
const
char
*
key
=
p
,
*
value
,
*
cp
=
p
;
param_t
*
param
;
char
*
name
;
hr
=
IStream_Read
(
iface
,
tmpBuffer
,
copySize
,
&
bytesRead
);
if
(
FAILED
(
hr
))
break
;
TRACE
(
"got param %s
\n
"
,
p
)
;
totalBytesRead
.
QuadPart
+=
bytesRead
;
while
(
*
key
==
' '
||
*
key
==
'\t'
)
key
++
;
if
(
bytesRead
)
{
hr
=
IStream_Write
(
pstm
,
tmpBuffer
,
bytesRead
,
&
bytesWritten
);
if
(
FAILED
(
hr
))
break
;
totalBytesWritten
.
QuadPart
+=
bytesWritten
;
}
cp
=
strchr
(
key
,
'='
);
if
(
!
cp
)
{
WARN
(
"malformed parameter - skipping
\n
"
);
return
;
if
(
bytesRead
!=
copySize
)
cb
.
QuadPart
=
0
;
else
cb
.
QuadPart
-=
bytesRead
;
}
name
=
HeapAlloc
(
GetProcessHeap
(),
0
,
cp
-
key
+
1
);
memcpy
(
name
,
key
,
cp
-
key
);
name
[
cp
-
key
]
=
'\0'
;
value
=
cp
+
1
;
if
(
pcbRead
)
pcbRead
->
QuadPart
=
totalBytesRead
.
QuadPart
;
if
(
pcbWritten
)
pcbWritten
->
QuadPart
=
totalBytesWritten
.
QuadPart
;
param
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
param
));
param
->
name
=
name
;
param
->
value
=
unquote_string
(
value
);
list_add_tail
(
&
header
->
params
,
&
param
->
entry
);
return
hr
;
}
static
void
split_params
(
header_t
*
header
,
char
*
value
)
static
HRESULT
WINAPI
sub_stream_Commit
(
IStream
*
iface
,
DWORD
grfCommitFlags
)
{
char
*
cp
=
value
,
*
start
=
value
;
BOOL
in_quotes
=
FALSE
,
done_value
=
FALSE
;
while
(
*
cp
)
{
if
(
!
in_quotes
&&
*
cp
==
';'
)
{
*
cp
=
'\0'
;
if
(
done_value
)
add_param
(
header
,
start
);
done_value
=
TRUE
;
start
=
cp
+
1
;
}
else
if
(
*
cp
==
'"'
)
in_quotes
=
!
in_quotes
;
cp
++
;
}
if
(
done_value
)
add_param
(
header
,
start
);
FIXME
(
"stub
\n
"
);
return
E_NOTIMPL
;
}
static
void
read_value
(
header_t
*
header
,
char
**
cur
)
static
HRESULT
WINAPI
sub_stream_Revert
(
IStream
*
iface
)
{
char
*
end
=
*
cur
,
*
value
;
DWORD
len
;
do
{
end
=
strstr
(
end
,
"
\r\n
"
);
end
+=
2
;
}
while
(
*
end
==
' '
||
*
end
==
'\t'
);
len
=
end
-
*
cur
;
value
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
+
1
);
memcpy
(
value
,
*
cur
,
len
);
value
[
len
]
=
'\0'
;
unfold_header
(
value
,
len
);
TRACE
(
"value %s
\n
"
,
debugstr_a
(
value
));
if
(
header
->
prop
->
flags
&
MPF_HASPARAMS
)
{
split_params
(
header
,
value
);
TRACE
(
"value w/o params %s
\n
"
,
debugstr_a
(
value
));
}
header
->
value
.
vt
=
VT_LPSTR
;
header
->
value
.
u
.
pszVal
=
value
;
FIXME
(
"stub
\n
"
);
return
E_NOTIMPL
;
}
*
cur
=
end
;
static
HRESULT
WINAPI
sub_stream_LockRegion
(
IStream
*
iface
,
ULARGE_INTEGER
libOffset
,
ULARGE_INTEGER
cb
,
DWORD
dwLockType
)
{
FIXME
(
"stub
\n
"
);
return
E_NOTIMPL
;
}
static
void
init_content_type
(
MimeBody
*
body
,
header_t
*
header
)
static
HRESULT
WINAPI
sub_stream_UnlockRegion
(
IStream
*
iface
,
ULARGE_INTEGER
libOffset
,
ULARGE_INTEGER
cb
,
DWORD
dwLockType
)
{
char
*
slash
;
DWORD
len
;
FIXME
(
"stub
\n
"
);
return
E_NOTIMPL
;
}
if
(
header
->
prop
->
id
!=
PID_HDR_CNTTYPE
)
{
ERR
(
"called with header %s
\n
"
,
header
->
prop
->
name
);
return
;
}
static
HRESULT
WINAPI
sub_stream_Stat
(
IStream
*
iface
,
STATSTG
*
pstatstg
,
DWORD
grfStatFlag
)
{
sub_stream_t
*
This
=
impl_from_IStream
(
iface
);
FIXME
(
"(%p)->(%p, %08x)
\n
"
,
This
,
pstatstg
,
grfStatFlag
);
memset
(
pstatstg
,
0
,
sizeof
(
*
pstatstg
));
pstatstg
->
cbSize
=
This
->
length
;
return
S_OK
;
}
slash
=
strchr
(
header
->
value
.
u
.
pszVal
,
'/'
);
if
(
!
slash
)
{
WARN
(
"malformed context type value
\n
"
);
return
;
}
len
=
slash
-
header
->
value
.
u
.
pszVal
;
body
->
content_pri_type
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
+
1
);
memcpy
(
body
->
content_pri_type
,
header
->
value
.
u
.
pszVal
,
len
);
body
->
content_pri_type
[
len
]
=
'\0'
;
body
->
content_sub_type
=
strdupA
(
slash
+
1
);
static
HRESULT
WINAPI
sub_stream_Clone
(
IStream
*
iface
,
IStream
**
ppstm
)
{
FIXME
(
"stub
\n
"
);
return
E_NOTIMPL
;
}
static
HRESULT
parse_headers
(
MimeBody
*
body
,
IStream
*
stm
)
static
struct
IStreamVtbl
sub_stream_vtbl
=
{
char
*
header_buf
,
*
cur_header_ptr
;
HRESULT
hr
;
header_t
*
header
;
sub_stream_QueryInterface
,
sub_stream_AddRef
,
sub_stream_Release
,
sub_stream_Read
,
sub_stream_Write
,
sub_stream_Seek
,
sub_stream_SetSize
,
sub_stream_CopyTo
,
sub_stream_Commit
,
sub_stream_Revert
,
sub_stream_LockRegion
,
sub_stream_UnlockRegion
,
sub_stream_Stat
,
sub_stream_Clone
};
hr
=
copy_headers_to_buf
(
stm
,
&
header_buf
);
if
(
FAILED
(
hr
))
return
hr
;
static
HRESULT
create_sub_stream
(
IStream
*
stream
,
ULARGE_INTEGER
start
,
ULARGE_INTEGER
length
,
IStream
**
out
)
{
sub_stream_t
*
This
;
cur_header_ptr
=
header_buf
;
while
((
header
=
read_prop
(
body
,
&
cur_header_ptr
)))
{
read_value
(
header
,
&
cur_header_ptr
);
list_add_tail
(
&
body
->
headers
,
&
header
->
entry
);
*
out
=
NULL
;
This
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
This
));
if
(
!
This
)
return
E_OUTOFMEMORY
;
if
(
header
->
prop
->
id
==
PID_HDR_CNTTYPE
)
init_content_type
(
body
,
header
);
}
This
->
IStream_iface
.
lpVtbl
=
&
sub_stream_vtbl
;
This
->
ref
=
1
;
This
->
start
=
start
;
This
->
length
=
length
;
This
->
pos
.
QuadPart
=
0
;
IStream_AddRef
(
stream
);
This
->
base
=
stream
;
HeapFree
(
GetProcessHeap
(),
0
,
header_buf
)
;
return
hr
;
*
out
=
&
This
->
IStream_iface
;
return
S_OK
;
}
static
void
empty_param_list
(
struct
list
*
list
)
static
inline
MimeBody
*
impl_from_IMimeBody
(
IMimeBody
*
iface
)
{
param_t
*
param
,
*
cursor2
;
LIST_FOR_EACH_ENTRY_SAFE
(
param
,
cursor2
,
list
,
param_t
,
entry
)
{
list_remove
(
&
param
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
param
->
name
);
HeapFree
(
GetProcessHeap
(),
0
,
param
->
value
);
HeapFree
(
GetProcessHeap
(),
0
,
param
);
}
return
CONTAINING_RECORD
(
iface
,
MimeBody
,
IMimeBody_iface
);
}
static
void
empty_header_list
(
struct
list
*
list
)
typedef
struct
propschema
{
header_t
*
header
,
*
cursor2
;
LIST_FOR_EACH_ENTRY_SAFE
(
header
,
cursor2
,
list
,
header_t
,
entry
)
{
list_remove
(
&
header
->
entry
);
PropVariantClear
(
&
header
->
value
);
empty_param_list
(
&
header
->
params
);
HeapFree
(
GetProcessHeap
(),
0
,
header
);
}
}
IMimePropertySchema
IMimePropertySchema_iface
;
LONG
ref
;
}
propschema
;
static
void
empty_new_prop_list
(
struct
list
*
list
)
static
inline
propschema
*
impl_from_IMimePropertySchema
(
IMimePropertySchema
*
iface
)
{
property_list_entry_t
*
prop
,
*
cursor2
;
LIST_FOR_EACH_ENTRY_SAFE
(
prop
,
cursor2
,
list
,
property_list_entry_t
,
entry
)
{
list_remove
(
&
prop
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
(
char
*
)
prop
->
prop
.
name
);
HeapFree
(
GetProcessHeap
(),
0
,
prop
);
}
return
CONTAINING_RECORD
(
iface
,
propschema
,
IMimePropertySchema_iface
);
}
static
void
release_data
(
REFIID
riid
,
void
*
data
)
static
LPSTR
strdupA
(
LPCSTR
str
)
{
if
(
!
data
)
return
;
if
(
IsEqualIID
(
riid
,
&
IID_IStream
))
IStream_Release
((
IStream
*
)
data
);
else
FIXME
(
"Unhandled data format %s
\n
"
,
debugstr_guid
(
riid
));
char
*
ret
;
int
len
=
strlen
(
str
);
ret
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
+
1
);
memcpy
(
ret
,
str
,
len
+
1
);
return
ret
;
}
static
HRESULT
find_prop
(
MimeBody
*
body
,
const
char
*
name
,
header_t
**
prop
)
#define PARSER_BUF_SIZE 1024
/*****************************************************
* copy_headers_to_buf [internal]
*
* Copies the headers into a '\0' terminated memory block and leave
* the stream's current position set to after the blank line.
*/
static
HRESULT
copy_headers_to_buf
(
IStream
*
stm
,
char
**
ptr
)
{
header_t
*
header
;
char
*
buf
=
NULL
;
DWORD
size
=
PARSER_BUF_SIZE
,
offset
=
0
,
last_end
=
0
;
HRESULT
hr
;
BOOL
done
=
FALSE
;
*
p
rop
=
NULL
;
*
p
tr
=
NULL
;
LIST_FOR_EACH_ENTRY
(
header
,
&
body
->
headers
,
header_t
,
entry
)
do
{
if
(
ISPIDSTR
(
name
))
char
*
end
;
DWORD
read
;
if
(
!
buf
)
buf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
+
1
);
else
{
if
(
STRTOPID
(
name
)
==
header
->
prop
->
id
)
{
*
prop
=
header
;
return
S_OK
;
}
size
*=
2
;
buf
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
buf
,
size
+
1
);
}
else
if
(
!
lstrcmpiA
(
name
,
header
->
prop
->
name
)
)
if
(
!
buf
)
{
*
prop
=
header
;
return
S_OK
;
hr
=
E_OUTOFMEMORY
;
goto
fail
;
}
}
return
MIME_E_NOT_FOUND
;
}
hr
=
IStream_Read
(
stm
,
buf
+
offset
,
size
-
offset
,
&
read
)
;
if
(
FAILED
(
hr
))
goto
fail
;
static
const
property_t
*
find_default_prop
(
const
char
*
name
)
{
const
property_t
*
prop_def
=
NULL
;
offset
+=
read
;
buf
[
offset
]
=
'\0'
;
for
(
prop_def
=
default_props
;
prop_def
->
name
;
prop_def
++
)
{
if
(
ISPIDSTR
(
name
))
if
(
read
==
0
)
done
=
TRUE
;
while
(
!
done
&&
(
end
=
strstr
(
buf
+
last_end
,
"
\r\n
"
)
))
{
if
(
STRTOPID
(
name
)
==
prop_def
->
id
)
DWORD
new_end
=
end
-
buf
+
2
;
if
(
new_end
-
last_end
==
2
)
{
break
;
LARGE_INTEGER
off
;
off
.
QuadPart
=
new_end
;
IStream_Seek
(
stm
,
off
,
STREAM_SEEK_SET
,
NULL
);
buf
[
new_end
]
=
'\0'
;
done
=
TRUE
;
}
else
last_end
=
new_end
;
}
else
if
(
!
lstrcmpiA
(
name
,
prop_def
->
name
))
{
break
;
}
}
}
while
(
!
done
);
if
(
prop_def
->
id
)
TRACE
(
"%s: found match with default property id %d
\n
"
,
prop_def
->
name
,
prop_def
->
id
);
else
prop_def
=
NULL
;
*
ptr
=
buf
;
return
S_OK
;
return
prop_def
;
fail:
HeapFree
(
GetProcessHeap
(),
0
,
buf
);
return
hr
;
}
static
HRESULT
WINAPI
MimeBody_QueryInterface
(
IMimeBody
*
iface
,
REFIID
riid
,
void
**
ppvObject
)
static
header_t
*
read_prop
(
MimeBody
*
body
,
char
**
ptr
)
{
TRACE
(
"(%p)->(%s, %p)
\n
"
,
iface
,
debugstr_guid
(
riid
),
ppvObject
);
char
*
colon
=
strchr
(
*
ptr
,
':'
);
const
property_t
*
prop
;
header_t
*
ret
;
*
ppvObject
=
NULL
;
if
(
!
colon
)
return
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
)
||
IsEqualIID
(
riid
,
&
IID_IPersist
)
||
IsEqualIID
(
riid
,
&
IID_IPersistStreamInit
)
||
IsEqualIID
(
riid
,
&
IID_IMimePropertySet
)
||
IsEqualIID
(
riid
,
&
IID_IMimeBody
))
*
colon
=
'\0'
;
for
(
prop
=
default_props
;
prop
->
name
;
prop
++
)
{
*
ppvObject
=
iface
;
if
(
!
lstrcmpiA
(
*
ptr
,
prop
->
name
))
{
TRACE
(
"%s: found match with default property id %d
\n
"
,
*
ptr
,
prop
->
id
);
break
;
}
}
if
(
*
ppvObject
)
if
(
!
prop
->
name
)
{
IUnknown_AddRef
((
IUnknown
*
)
*
ppvObject
);
return
S_OK
;
property_list_entry_t
*
prop_entry
;
LIST_FOR_EACH_ENTRY
(
prop_entry
,
&
body
->
new_props
,
property_list_entry_t
,
entry
)
{
if
(
!
lstrcmpiA
(
*
ptr
,
prop_entry
->
prop
.
name
))
{
TRACE
(
"%s: found match with already added new property id %d
\n
"
,
*
ptr
,
prop_entry
->
prop
.
id
);
prop
=
&
prop_entry
->
prop
;
break
;
}
}
if
(
!
prop
->
name
)
{
prop_entry
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
prop_entry
));
prop_entry
->
prop
.
name
=
strdupA
(
*
ptr
);
prop_entry
->
prop
.
id
=
body
->
next_prop_id
++
;
prop_entry
->
prop
.
flags
=
0
;
prop_entry
->
prop
.
default_vt
=
VT_LPSTR
;
list_add_tail
(
&
body
->
new_props
,
&
prop_entry
->
entry
);
prop
=
&
prop_entry
->
prop
;
TRACE
(
"%s: allocating new prop id %d
\n
"
,
*
ptr
,
prop_entry
->
prop
.
id
);
}
}
FIXME
(
"no interface for %s
\n
"
,
debugstr_guid
(
riid
));
return
E_NOINTERFACE
;
ret
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
ret
));
ret
->
prop
=
prop
;
PropVariantInit
(
&
ret
->
value
);
list_init
(
&
ret
->
params
);
*
ptr
=
colon
+
1
;
return
ret
;
}
static
ULONG
WINAPI
MimeBody_AddRef
(
IMimeBody
*
iface
)
static
void
unfold_header
(
char
*
header
,
int
len
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
LONG
ref
=
InterlockedIncrement
(
&
This
->
ref
);
char
*
start
=
header
,
*
cp
=
header
;
TRACE
(
"(%p) ref=%d
\n
"
,
This
,
ref
);
do
{
while
(
*
cp
==
' '
||
*
cp
==
'\t'
)
{
cp
++
;
len
--
;
}
if
(
cp
!=
start
)
memmove
(
start
,
cp
,
len
+
1
);
return
ref
;
cp
=
strstr
(
start
,
"
\r\n
"
);
len
-=
(
cp
-
start
);
start
=
cp
;
*
start
=
' '
;
start
++
;
len
--
;
cp
+=
2
;
}
while
(
*
cp
==
' '
||
*
cp
==
'\t'
);
*
(
start
-
1
)
=
'\0'
;
}
static
ULONG
WINAPI
MimeBody_Release
(
IMimeBody
*
iface
)
static
char
*
unquote_string
(
const
char
*
str
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
)
;
LONG
ref
=
InterlockedDecrement
(
&
This
->
ref
)
;
BOOL
quoted
=
FALSE
;
char
*
ret
,
*
cp
;
TRACE
(
"(%p) ref=%d
\n
"
,
This
,
ref
)
;
while
(
*
str
==
' '
||
*
str
==
'\t'
)
str
++
;
if
(
!
ref
)
if
(
*
str
==
'"'
)
{
empty_header_list
(
&
This
->
headers
);
empty_new_prop_list
(
&
This
->
new_props
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
content_pri_type
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
content_sub_type
);
release_data
(
&
This
->
data_iid
,
This
->
data
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
quoted
=
TRUE
;
str
++
;
}
return
ref
;
ret
=
strdupA
(
str
);
for
(
cp
=
ret
;
*
cp
;
cp
++
)
{
if
(
*
cp
==
'\\'
)
memmove
(
cp
,
cp
+
1
,
strlen
(
cp
+
1
)
+
1
);
else
if
(
*
cp
==
'"'
)
{
if
(
!
quoted
)
{
WARN
(
"quote in unquoted string
\n
"
);
}
else
{
*
cp
=
'\0'
;
break
;
}
}
}
return
ret
;
}
static
HRESULT
WINAPI
MimeBody_GetClassID
(
IMimeBody
*
iface
,
CLSID
*
pClassID
)
static
void
add_param
(
header_t
*
header
,
const
char
*
p
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%p) stub
\n
"
,
This
,
pClassID
);
return
E_NOTIMPL
;
}
const
char
*
key
=
p
,
*
value
,
*
cp
=
p
;
param_t
*
param
;
char
*
name
;
TRACE
(
"got param %s
\n
"
,
p
);
static
HRESULT
WINAPI
MimeBody_IsDirty
(
IMimeBody
*
iface
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->() stub
\n
"
,
This
);
return
E_NOTIMPL
;
}
while
(
*
key
==
' '
||
*
key
==
'\t'
)
key
++
;
static
HRESULT
WINAPI
MimeBody_Load
(
IMimeBody
*
iface
,
IStream
*
pStm
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
TRACE
(
"(%p)->(%p)
\n
"
,
This
,
pStm
);
return
parse_headers
(
This
,
pStm
)
;
}
cp
=
strchr
(
key
,
'='
);
if
(
!
cp
)
{
WARN
(
"malformed parameter - skipping
\n
"
);
return
;
}
static
HRESULT
WINAPI
MimeBody_Save
(
IMimeBody
*
iface
,
IStream
*
pStm
,
BOOL
fClearDirty
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%p, %d)
\n
"
,
This
,
pStm
,
fClearDirty
);
return
E_NOTIMPL
;
}
name
=
HeapAlloc
(
GetProcessHeap
(),
0
,
cp
-
key
+
1
);
memcpy
(
name
,
key
,
cp
-
key
);
name
[
cp
-
key
]
=
'\0'
;
static
HRESULT
WINAPI
MimeBody_GetSizeMax
(
IMimeBody
*
iface
,
ULARGE_INTEGER
*
pcbSize
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%p) stub
\n
"
,
This
,
pcbSize
);
return
E_NOTIMPL
;
}
value
=
cp
+
1
;
static
HRESULT
WINAPI
MimeBody_InitNew
(
IMimeBody
*
iface
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
TRACE
(
"(%p)->()
\n
"
,
This
);
return
S_OK
;
param
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
param
));
param
->
name
=
name
;
param
->
value
=
unquote_string
(
value
);
list_add_tail
(
&
header
->
params
,
&
param
->
entry
);
}
static
HRESULT
WINAPI
MimeBody_GetPropInfo
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
LPMIMEPROPINFO
pInfo
)
static
void
split_params
(
header_t
*
header
,
char
*
value
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
header_t
*
header
;
HRESULT
hr
;
DWORD
supported
=
PIM_PROPID
|
PIM_VTDEFAULT
;
TRACE
(
"(%p)->(%s, %p) semi-stub
\n
"
,
This
,
debugstr_a
(
pszName
),
pInfo
);
if
(
!
pszName
||
!
pInfo
)
return
E_INVALIDARG
;
TRACE
(
"mask 0x%04x
\n
"
,
pInfo
->
dwMask
);
if
(
pInfo
->
dwMask
&
~
supported
)
FIXME
(
"Unsupported mask flags 0x%04x
\n
"
,
pInfo
->
dwMask
&
~
supported
);
char
*
cp
=
value
,
*
start
=
value
;
BOOL
in_quotes
=
FALSE
,
done_value
=
FALSE
;
hr
=
find_prop
(
This
,
pszName
,
&
header
);
if
(
hr
==
S_OK
)
while
(
*
cp
)
{
if
(
pInfo
->
dwMask
&
PIM_CHARSET
)
pInfo
->
hCharset
=
0
;
if
(
pInfo
->
dwMask
&
PIM_FLAGS
)
pInfo
->
dwFlags
=
0x00000000
;
if
(
pInfo
->
dwMask
&
PIM_ROWNUMBER
)
pInfo
->
dwRowNumber
=
0
;
if
(
pInfo
->
dwMask
&
PIM_ENCODINGTYPE
)
pInfo
->
ietEncoding
=
0
;
if
(
pInfo
->
dwMask
&
PIM_VALUES
)
pInfo
->
cValues
=
0
;
if
(
pInfo
->
dwMask
&
PIM_PROPID
)
pInfo
->
dwPropId
=
header
->
prop
->
id
;
if
(
pInfo
->
dwMask
&
PIM_VTDEFAULT
)
pInfo
->
vtDefault
=
header
->
prop
->
default_vt
;
if
(
pInfo
->
dwMask
&
PIM_VTCURRENT
)
pInfo
->
vtCurrent
=
0
;
if
(
!
in_quotes
&&
*
cp
==
';'
)
{
*
cp
=
'\0'
;
if
(
done_value
)
add_param
(
header
,
start
);
done_value
=
TRUE
;
start
=
cp
+
1
;
}
else
if
(
*
cp
==
'"'
)
in_quotes
=
!
in_quotes
;
cp
++
;
}
return
hr
;
if
(
done_value
)
add_param
(
header
,
start
);
}
static
HRESULT
WINAPI
MimeBody_SetPropInfo
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
LPCMIMEPROPINFO
pInfo
)
static
void
read_value
(
header_t
*
header
,
char
**
cur
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%s, %p) stub
\n
"
,
This
,
debugstr_a
(
pszName
),
pInfo
);
return
E_NOTIMPL
;
}
char
*
end
=
*
cur
,
*
value
;
DWORD
len
;
static
HRESULT
WINAPI
MimeBody_GetProp
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
DWORD
dwFlags
,
LPPROPVARIANT
pValue
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
header_t
*
header
;
HRESULT
hr
;
do
{
end
=
strstr
(
end
,
"
\r\n
"
);
end
+=
2
;
}
while
(
*
end
==
' '
||
*
end
==
'\t'
);
TRACE
(
"(%p)->(%s, 0x%x, %p)
\n
"
,
This
,
debugstr_a
(
pszName
),
dwFlags
,
pValue
);
len
=
end
-
*
cur
;
value
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
+
1
);
memcpy
(
value
,
*
cur
,
len
);
value
[
len
]
=
'\0'
;
if
(
!
pszName
||
!
pValue
)
return
E_INVALIDARG
;
unfold_header
(
value
,
len
);
TRACE
(
"value %s
\n
"
,
debugstr_a
(
value
))
;
if
(
!
ISPIDSTR
(
pszName
)
&&
!
lstrcmpiA
(
pszName
,
"att:pri-content-type"
)
)
if
(
header
->
prop
->
flags
&
MPF_HASPARAMS
)
{
PropVariantClear
(
pValue
);
pValue
->
vt
=
VT_LPSTR
;
pValue
->
u
.
pszVal
=
strdupA
(
This
->
content_pri_type
);
return
S_OK
;
split_params
(
header
,
value
);
TRACE
(
"value w/o params %s
\n
"
,
debugstr_a
(
value
));
}
hr
=
find_prop
(
This
,
pszName
,
&
header
);
if
(
hr
==
S_OK
)
{
TRACE
(
"type %d->%d
\n
"
,
header
->
value
.
vt
,
pValue
->
vt
);
hr
=
PropVariantChangeType
(
pValue
,
&
header
->
value
,
0
,
pValue
->
vt
);
if
(
FAILED
(
hr
))
FIXME
(
"Conversion not currently supported (%d->%d)
\n
"
,
header
->
value
.
vt
,
pValue
->
vt
);
}
header
->
value
.
vt
=
VT_LPSTR
;
header
->
value
.
u
.
pszVal
=
value
;
return
hr
;
*
cur
=
end
;
}
static
HRESULT
WINAPI
MimeBody_SetProp
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
DWORD
dwFlags
,
LPCPROPVARIANT
pValue
)
static
void
init_content_type
(
MimeBody
*
body
,
header_t
*
header
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
header_t
*
header
;
HRESULT
hr
;
TRACE
(
"(%p)->(%s, 0x%x, %p)
\n
"
,
This
,
debugstr_a
(
pszName
),
dwFlags
,
pValue
);
if
(
!
pszName
||
!
pValue
)
return
E_INVALIDARG
;
char
*
slash
;
DWORD
len
;
hr
=
find_prop
(
This
,
pszName
,
&
header
);
if
(
hr
!=
S_OK
)
if
(
header
->
prop
->
id
!=
PID_HDR_CNTTYPE
)
{
property_list_entry_t
*
prop_entry
;
const
property_t
*
prop
=
NULL
;
LIST_FOR_EACH_ENTRY
(
prop_entry
,
&
This
->
new_props
,
property_list_entry_t
,
entry
)
{
if
(
ISPIDSTR
(
pszName
))
{
if
(
STRTOPID
(
pszName
)
==
prop_entry
->
prop
.
id
)
{
TRACE
(
"Found match with already added new property id %d
\n
"
,
prop_entry
->
prop
.
id
);
prop
=
&
prop_entry
->
prop
;
break
;
}
}
else
if
(
!
lstrcmpiA
(
pszName
,
prop_entry
->
prop
.
name
))
{
TRACE
(
"Found match with already added new property id %d
\n
"
,
prop_entry
->
prop
.
id
);
prop
=
&
prop_entry
->
prop
;
break
;
}
}
header
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
header
));
if
(
!
header
)
return
E_OUTOFMEMORY
;
if
(
!
prop
)
{
const
property_t
*
prop_def
=
NULL
;
prop_entry
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
prop_entry
));
if
(
!
prop_entry
)
{
HeapFree
(
GetProcessHeap
(),
0
,
header
);
return
E_OUTOFMEMORY
;
}
prop_def
=
find_default_prop
(
pszName
);
if
(
prop_def
)
{
prop_entry
->
prop
.
name
=
strdupA
(
prop_def
->
name
);
prop_entry
->
prop
.
id
=
prop_def
->
id
;
}
else
{
if
(
ISPIDSTR
(
pszName
))
{
HeapFree
(
GetProcessHeap
(),
0
,
prop_entry
);
HeapFree
(
GetProcessHeap
(),
0
,
header
);
return
MIME_E_NOT_FOUND
;
}
prop_entry
->
prop
.
name
=
strdupA
(
pszName
);
prop_entry
->
prop
.
id
=
This
->
next_prop_id
++
;
}
prop_entry
->
prop
.
flags
=
0
;
prop_entry
->
prop
.
default_vt
=
pValue
->
vt
;
list_add_tail
(
&
This
->
new_props
,
&
prop_entry
->
entry
);
prop
=
&
prop_entry
->
prop
;
TRACE
(
"Allocating new prop id %d
\n
"
,
prop_entry
->
prop
.
id
);
}
header
->
prop
=
prop
;
PropVariantInit
(
&
header
->
value
);
list_init
(
&
header
->
params
);
list_add_tail
(
&
This
->
headers
,
&
header
->
entry
);
ERR
(
"called with header %s
\n
"
,
header
->
prop
->
name
);
return
;
}
PropVariantCopy
(
&
header
->
value
,
pValue
);
return
S_OK
;
}
static
HRESULT
WINAPI
MimeBody_AppendProp
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
DWORD
dwFlags
,
LPPROPVARIANT
pValue
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%s, 0x%x, %p) stub
\n
"
,
This
,
debugstr_a
(
pszName
),
dwFlags
,
pValue
);
return
E_NOTIMPL
;
slash
=
strchr
(
header
->
value
.
u
.
pszVal
,
'/'
);
if
(
!
slash
)
{
WARN
(
"malformed context type value
\n
"
);
return
;
}
len
=
slash
-
header
->
value
.
u
.
pszVal
;
body
->
content_pri_type
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
+
1
);
memcpy
(
body
->
content_pri_type
,
header
->
value
.
u
.
pszVal
,
len
);
body
->
content_pri_type
[
len
]
=
'\0'
;
body
->
content_sub_type
=
strdupA
(
slash
+
1
);
}
static
HRESULT
WINAPI
MimeBody_DeleteProp
(
IMimeBody
*
iface
,
LPCSTR
pszName
)
static
HRESULT
parse_headers
(
MimeBody
*
body
,
IStream
*
stm
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
)
;
header_t
*
curso
r
;
BOOL
found
;
char
*
header_buf
,
*
cur_header_ptr
;
HRESULT
h
r
;
header_t
*
header
;
TRACE
(
"(%p)->(%s) stub
\n
"
,
This
,
debugstr_a
(
pszName
));
hr
=
copy_headers_to_buf
(
stm
,
&
header_buf
);
if
(
FAILED
(
hr
))
return
hr
;
LIST_FOR_EACH_ENTRY
(
cursor
,
&
This
->
headers
,
header_t
,
entry
)
cur_header_ptr
=
header_buf
;
while
((
header
=
read_prop
(
body
,
&
cur_header_ptr
)))
{
if
(
ISPIDSTR
(
pszName
))
found
=
STRTOPID
(
pszName
)
==
cursor
->
prop
->
id
;
else
found
=
!
lstrcmpiA
(
pszName
,
cursor
->
prop
->
name
);
read_value
(
header
,
&
cur_header_ptr
);
list_add_tail
(
&
body
->
headers
,
&
header
->
entry
);
if
(
found
)
{
list_remove
(
&
cursor
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
cursor
);
return
S_OK
;
}
if
(
header
->
prop
->
id
==
PID_HDR_CNTTYPE
)
init_content_type
(
body
,
header
);
}
return
MIME_E_NOT_FOUND
;
HeapFree
(
GetProcessHeap
(),
0
,
header_buf
);
return
hr
;
}
static
HRESULT
WINAPI
MimeBody_CopyProps
(
IMimeBody
*
iface
,
ULONG
cNames
,
LPCSTR
*
prgszName
,
IMimePropertySet
*
pPropertySet
)
static
void
empty_param_list
(
struct
list
*
list
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%d, %p, %p) stub
\n
"
,
This
,
cNames
,
prgszName
,
pPropertySet
);
return
E_NOTIMPL
;
param_t
*
param
,
*
cursor2
;
LIST_FOR_EACH_ENTRY_SAFE
(
param
,
cursor2
,
list
,
param_t
,
entry
)
{
list_remove
(
&
param
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
param
->
name
);
HeapFree
(
GetProcessHeap
(),
0
,
param
->
value
);
HeapFree
(
GetProcessHeap
(),
0
,
param
);
}
}
static
HRESULT
WINAPI
MimeBody_MoveProps
(
IMimeBody
*
iface
,
ULONG
cNames
,
LPCSTR
*
prgszName
,
IMimePropertySet
*
pPropertySet
)
static
void
empty_header_list
(
struct
list
*
list
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%d, %p, %p) stub
\n
"
,
This
,
cNames
,
prgszName
,
pPropertySet
);
return
E_NOTIMPL
;
header_t
*
header
,
*
cursor2
;
LIST_FOR_EACH_ENTRY_SAFE
(
header
,
cursor2
,
list
,
header_t
,
entry
)
{
list_remove
(
&
header
->
entry
);
PropVariantClear
(
&
header
->
value
);
empty_param_list
(
&
header
->
params
);
HeapFree
(
GetProcessHeap
(),
0
,
header
);
}
}
static
HRESULT
WINAPI
MimeBody_DeleteExcept
(
IMimeBody
*
iface
,
ULONG
cNames
,
LPCSTR
*
prgszName
)
static
void
empty_new_prop_list
(
struct
list
*
list
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%d, %p) stub
\n
"
,
This
,
cNames
,
prgszName
);
return
E_NOTIMPL
;
property_list_entry_t
*
prop
,
*
cursor2
;
LIST_FOR_EACH_ENTRY_SAFE
(
prop
,
cursor2
,
list
,
property_list_entry_t
,
entry
)
{
list_remove
(
&
prop
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
(
char
*
)
prop
->
prop
.
name
);
HeapFree
(
GetProcessHeap
(),
0
,
prop
);
}
}
static
HRESULT
WINAPI
MimeBody_QueryProp
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
LPCSTR
pszCriteria
,
boolean
fSubString
,
boolean
fCaseSensitive
)
static
void
release_data
(
REFIID
riid
,
void
*
data
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%s, %s, %d, %d) stub
\n
"
,
This
,
debugstr_a
(
pszName
),
debugstr_a
(
pszCriteria
),
fSubString
,
fCaseSensitive
);
return
E_NOTIMPL
;
if
(
!
data
)
return
;
if
(
IsEqualIID
(
riid
,
&
IID_IStream
))
IStream_Release
((
IStream
*
)
data
);
else
FIXME
(
"Unhandled data format %s
\n
"
,
debugstr_guid
(
riid
));
}
static
HRESULT
WINAPI
MimeBody_GetCharset
(
IMimeBody
*
iface
,
LPHCHARSET
phCharset
)
static
HRESULT
find_prop
(
MimeBody
*
body
,
const
char
*
name
,
header_t
**
prop
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%p) stub
\n
"
,
This
,
phCharset
);
*
phCharset
=
NULL
;
return
S_OK
;
header_t
*
header
;
*
prop
=
NULL
;
LIST_FOR_EACH_ENTRY
(
header
,
&
body
->
headers
,
header_t
,
entry
)
{
if
(
ISPIDSTR
(
name
))
{
if
(
STRTOPID
(
name
)
==
header
->
prop
->
id
)
{
*
prop
=
header
;
return
S_OK
;
}
}
else
if
(
!
lstrcmpiA
(
name
,
header
->
prop
->
name
))
{
*
prop
=
header
;
return
S_OK
;
}
}
return
MIME_E_NOT_FOUND
;
}
static
HRESULT
WINAPI
MimeBody_SetCharset
(
IMimeBody
*
iface
,
HCHARSET
hCharset
,
CSETAPPLYTYPE
applytype
)
static
const
property_t
*
find_default_prop
(
const
char
*
name
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%p, %d) stub
\n
"
,
This
,
hCharset
,
applytype
);
return
E_NOTIMPL
;
const
property_t
*
prop_def
=
NULL
;
for
(
prop_def
=
default_props
;
prop_def
->
name
;
prop_def
++
)
{
if
(
ISPIDSTR
(
name
))
{
if
(
STRTOPID
(
name
)
==
prop_def
->
id
)
{
break
;
}
}
else
if
(
!
lstrcmpiA
(
name
,
prop_def
->
name
))
{
break
;
}
}
if
(
prop_def
->
id
)
TRACE
(
"%s: found match with default property id %d
\n
"
,
prop_def
->
name
,
prop_def
->
id
);
else
prop_def
=
NULL
;
return
prop_def
;
}
static
HRESULT
WINAPI
MimeBody_GetParameters
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
ULONG
*
pcParams
,
LPMIMEPARAMINFO
*
pprgParam
)
static
HRESULT
WINAPI
MimeBody_QueryInterface
(
IMimeBody
*
iface
,
REFIID
riid
,
void
**
ppvObject
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
HRESULT
hr
;
header_t
*
header
;
TRACE
(
"(%p)->(%s, %p, %p)
\n
"
,
iface
,
debugstr_a
(
pszName
),
pcParams
,
pprgParam
);
TRACE
(
"(%p)->(%s, %p)
\n
"
,
iface
,
debugstr_guid
(
riid
),
ppvObject
);
*
pprgParam
=
NULL
;
*
pcParams
=
0
;
*
ppvObject
=
NULL
;
hr
=
find_prop
(
This
,
pszName
,
&
header
);
if
(
hr
!=
S_OK
)
return
hr
;
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
)
||
IsEqualIID
(
riid
,
&
IID_IPersist
)
||
IsEqualIID
(
riid
,
&
IID_IPersistStreamInit
)
||
IsEqualIID
(
riid
,
&
IID_IMimePropertySet
)
||
IsEqualIID
(
riid
,
&
IID_IMimeBody
))
{
*
ppvObject
=
iface
;
}
*
pcParams
=
list_count
(
&
header
->
params
);
if
(
*
pcParams
)
if
(
*
ppvObject
)
{
I
MimeAllocator
*
alloc
;
param_t
*
param
;
MIMEPARAMINFO
*
info
;
I
Unknown_AddRef
((
IUnknown
*
)
*
ppvObject
)
;
return
S_OK
;
}
MimeOleGetAllocator
(
&
alloc
);
FIXME
(
"no interface for %s
\n
"
,
debugstr_guid
(
riid
));
return
E_NOINTERFACE
;
}
*
pprgParam
=
info
=
IMimeAllocator_Alloc
(
alloc
,
*
pcParams
*
sizeof
(
**
pprgParam
));
LIST_FOR_EACH_ENTRY
(
param
,
&
header
->
params
,
param_t
,
entry
)
{
int
len
;
static
ULONG
WINAPI
MimeBody_AddRef
(
IMimeBody
*
iface
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
LONG
ref
=
InterlockedIncrement
(
&
This
->
ref
)
;
len
=
strlen
(
param
->
name
)
+
1
;
info
->
pszName
=
IMimeAllocator_Alloc
(
alloc
,
len
);
memcpy
(
info
->
pszName
,
param
->
name
,
len
);
len
=
strlen
(
param
->
value
)
+
1
;
info
->
pszData
=
IMimeAllocator_Alloc
(
alloc
,
len
);
memcpy
(
info
->
pszData
,
param
->
value
,
len
);
info
++
;
}
IMimeAllocator_Release
(
alloc
);
}
return
S_OK
;
TRACE
(
"(%p) ref=%d
\n
"
,
This
,
ref
);
return
ref
;
}
static
HRESULT
WINAPI
MimeBody_IsContentType
(
IMimeBody
*
iface
,
LPCSTR
pszPriType
,
LPCSTR
pszSubType
)
static
ULONG
WINAPI
MimeBody_Release
(
IMimeBody
*
iface
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
LONG
ref
=
InterlockedDecrement
(
&
This
->
ref
);
TRACE
(
"(%p)->(%s, %s)
\n
"
,
This
,
debugstr_a
(
pszPriType
),
debugstr_a
(
pszSubType
));
if
(
pszPriType
)
{
const
char
*
pri
=
This
->
content_pri_type
;
if
(
!
pri
)
pri
=
"text"
;
if
(
lstrcmpiA
(
pri
,
pszPriType
))
return
S_FALSE
;
}
TRACE
(
"(%p) ref=%d
\n
"
,
This
,
ref
);
if
(
pszSubType
)
if
(
!
ref
)
{
const
char
*
sub
=
This
->
content_sub_type
;
if
(
!
sub
)
sub
=
"plain"
;
if
(
lstrcmpiA
(
sub
,
pszSubType
))
return
S_FALSE
;
empty_header_list
(
&
This
->
headers
);
empty_new_prop_list
(
&
This
->
new_props
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
content_pri_type
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
content_sub_type
);
release_data
(
&
This
->
data_iid
,
This
->
data
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
}
return
S_OK
;
return
ref
;
}
static
HRESULT
WINAPI
MimeBody_BindToObject
(
IMimeBody
*
iface
,
REFIID
riid
,
void
**
ppvObject
)
static
HRESULT
WINAPI
MimeBody_GetClassID
(
IMimeBody
*
iface
,
CLSID
*
pClassID
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%
s, %p) stub
\n
"
,
This
,
debugstr_guid
(
riid
),
ppvObject
);
FIXME
(
"(%p)->(%
p) stub
\n
"
,
This
,
pClassID
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
MimeBody_Clone
(
IMimeBody
*
iface
,
IMimePropertySet
**
ppPropertySet
)
static
HRESULT
WINAPI
MimeBody_IsDirty
(
IMimeBody
*
iface
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(
%p) stub
\n
"
,
This
,
ppPropertySet
);
FIXME
(
"(%p)->(
) stub
\n
"
,
This
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
MimeBody_SetOption
(
IMimeBody
*
iface
,
const
TYPEDID
oid
,
LPCPROPVARIANT
pValue
)
static
HRESULT
WINAPI
MimeBody_Load
(
IMimeBody
*
iface
,
IStream
*
pStm
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
HRESULT
hr
=
E_NOTIMPL
;
TRACE
(
"(%p)->(%08x, %p)
\n
"
,
This
,
oid
,
pValue
);
if
(
pValue
->
vt
!=
TYPEDID_TYPE
(
oid
))
{
WARN
(
"Called with vartype %04x and oid %08x
\n
"
,
pValue
->
vt
,
oid
);
return
E_INVALIDARG
;
}
switch
(
oid
)
{
case
OID_SECURITY_HWND_OWNER
:
FIXME
(
"OID_SECURITY_HWND_OWNER (value %08x): ignoring
\n
"
,
pValue
->
u
.
ulVal
);
hr
=
S_OK
;
break
;
case
OID_TRANSMIT_BODY_ENCODING
:
FIXME
(
"OID_TRANSMIT_BODY_ENCODING (value %08x): ignoring
\n
"
,
pValue
->
u
.
ulVal
);
hr
=
S_OK
;
break
;
default:
FIXME
(
"Unhandled oid %08x
\n
"
,
oid
);
}
return
hr
;
TRACE
(
"(%p)->(%p)
\n
"
,
This
,
pStm
);
return
parse_headers
(
This
,
pStm
);
}
static
HRESULT
WINAPI
MimeBody_GetOption
(
IMimeBody
*
iface
,
const
TYPEDID
oid
,
LPPROPVARIANT
pValue
)
static
HRESULT
WINAPI
MimeBody_Save
(
IMimeBody
*
iface
,
IStream
*
pStm
,
BOOL
fClearDirty
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%
08x, %p): stub
\n
"
,
This
,
oid
,
pValue
);
FIXME
(
"(%p)->(%
p, %d)
\n
"
,
This
,
pStm
,
fClearDirty
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
MimeBody_EnumProps
(
IMimeBody
*
iface
,
DWORD
dwFlags
,
IMimeEnumProperties
**
ppEnum
)
static
HRESULT
WINAPI
MimeBody_GetSizeMax
(
IMimeBody
*
iface
,
ULARGE_INTEGER
*
pcbSize
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(
0x%x, %p) stub
\n
"
,
This
,
dwFlags
,
ppEnum
);
FIXME
(
"(%p)->(
%p) stub
\n
"
,
This
,
pcbSize
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
MimeBody_IsType
(
IMimeBody
*
iface
,
IMSGBODYTYPE
bodytype
)
static
HRESULT
WINAPI
MimeBody_InitNew
(
IMimeBody
*
iface
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
TRACE
(
"(%p)->(%d)
\n
"
,
This
,
bodytype
);
switch
(
bodytype
)
{
case
IBT_EMPTY
:
return
This
->
data
?
S_FALSE
:
S_OK
;
default:
FIXME
(
"Unimplemented bodytype %d - returning S_OK
\n
"
,
bodytype
);
}
TRACE
(
"(%p)->()
\n
"
,
This
);
return
S_OK
;
}
static
HRESULT
WINAPI
MimeBody_SetDisplayName
(
IMimeBody
*
iface
,
LPCSTR
pszDisplay
)
static
HRESULT
WINAPI
MimeBody_GetPropInfo
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
LPMIMEPROPINFO
pInfo
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%s) stub
\n
"
,
This
,
debugstr_a
(
pszDisplay
));
return
E_NOTIMPL
;
header_t
*
header
;
HRESULT
hr
;
DWORD
supported
=
PIM_PROPID
|
PIM_VTDEFAULT
;
TRACE
(
"(%p)->(%s, %p) semi-stub
\n
"
,
This
,
debugstr_a
(
pszName
),
pInfo
);
if
(
!
pszName
||
!
pInfo
)
return
E_INVALIDARG
;
TRACE
(
"mask 0x%04x
\n
"
,
pInfo
->
dwMask
);
if
(
pInfo
->
dwMask
&
~
supported
)
FIXME
(
"Unsupported mask flags 0x%04x
\n
"
,
pInfo
->
dwMask
&
~
supported
);
hr
=
find_prop
(
This
,
pszName
,
&
header
);
if
(
hr
==
S_OK
)
{
if
(
pInfo
->
dwMask
&
PIM_CHARSET
)
pInfo
->
hCharset
=
0
;
if
(
pInfo
->
dwMask
&
PIM_FLAGS
)
pInfo
->
dwFlags
=
0x00000000
;
if
(
pInfo
->
dwMask
&
PIM_ROWNUMBER
)
pInfo
->
dwRowNumber
=
0
;
if
(
pInfo
->
dwMask
&
PIM_ENCODINGTYPE
)
pInfo
->
ietEncoding
=
0
;
if
(
pInfo
->
dwMask
&
PIM_VALUES
)
pInfo
->
cValues
=
0
;
if
(
pInfo
->
dwMask
&
PIM_PROPID
)
pInfo
->
dwPropId
=
header
->
prop
->
id
;
if
(
pInfo
->
dwMask
&
PIM_VTDEFAULT
)
pInfo
->
vtDefault
=
header
->
prop
->
default_vt
;
if
(
pInfo
->
dwMask
&
PIM_VTCURRENT
)
pInfo
->
vtCurrent
=
0
;
}
return
hr
;
}
static
HRESULT
WINAPI
MimeBody_GetDisplayName
(
IMimeBody
*
iface
,
LPSTR
*
ppszDisplay
)
static
HRESULT
WINAPI
MimeBody_SetPropInfo
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
LPCMIMEPROPINFO
pInfo
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%
p) stub
\n
"
,
This
,
ppszDisplay
);
FIXME
(
"(%p)->(%
s, %p) stub
\n
"
,
This
,
debugstr_a
(
pszName
),
pInfo
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
MimeBody_GetOffsets
(
IMimeBody
*
iface
,
LPBODYOFFSETS
pOffsets
)
static
HRESULT
WINAPI
MimeBody_GetProp
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
DWORD
dwFlags
,
LPPROPVARIANT
pValue
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
TRACE
(
"(%p)->(%p)
\n
"
,
This
,
pOffsets
);
header_t
*
header
;
HRESULT
hr
;
*
pOffsets
=
This
->
body_offsets
;
TRACE
(
"(%p)->(%s, 0x%x, %p)
\n
"
,
This
,
debugstr_a
(
pszName
),
dwFlags
,
pValue
)
;
if
(
This
->
body_offsets
.
cbBodyEnd
==
0
)
return
MIME_E_NO_DATA
;
return
S_OK
;
}
if
(
!
pszName
||
!
pValue
)
return
E_INVALIDARG
;
static
HRESULT
WINAPI
MimeBody_GetCurrentEncoding
(
IMimeBody
*
iface
,
ENCODINGTYPE
*
pietEncoding
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
if
(
!
ISPIDSTR
(
pszName
)
&&
!
lstrcmpiA
(
pszName
,
"att:pri-content-type"
))
{
PropVariantClear
(
pValue
);
pValue
->
vt
=
VT_LPSTR
;
pValue
->
u
.
pszVal
=
strdupA
(
This
->
content_pri_type
);
return
S_OK
;
}
TRACE
(
"(%p)->(%p)
\n
"
,
This
,
pietEncoding
);
hr
=
find_prop
(
This
,
pszName
,
&
header
);
if
(
hr
==
S_OK
)
{
TRACE
(
"type %d->%d
\n
"
,
header
->
value
.
vt
,
pValue
->
vt
);
*
pietEncoding
=
This
->
encoding
;
return
S_OK
;
hr
=
PropVariantChangeType
(
pValue
,
&
header
->
value
,
0
,
pValue
->
vt
);
if
(
FAILED
(
hr
))
FIXME
(
"Conversion not currently supported (%d->%d)
\n
"
,
header
->
value
.
vt
,
pValue
->
vt
);
}
return
hr
;
}
static
HRESULT
WINAPI
MimeBody_SetCurrentEncoding
(
IMimeBody
*
iface
,
ENCODINGTYPE
ietEncoding
)
static
HRESULT
WINAPI
MimeBody_SetProp
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
DWORD
dwFlags
,
LPCPROPVARIANT
pValue
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
header_t
*
header
;
HRESULT
hr
;
TRACE
(
"(%p)->(%s, 0x%x, %p)
\n
"
,
This
,
debugstr_a
(
pszName
),
dwFlags
,
pValue
);
if
(
!
pszName
||
!
pValue
)
return
E_INVALIDARG
;
hr
=
find_prop
(
This
,
pszName
,
&
header
);
if
(
hr
!=
S_OK
)
{
property_list_entry_t
*
prop_entry
;
const
property_t
*
prop
=
NULL
;
LIST_FOR_EACH_ENTRY
(
prop_entry
,
&
This
->
new_props
,
property_list_entry_t
,
entry
)
{
if
(
ISPIDSTR
(
pszName
))
{
if
(
STRTOPID
(
pszName
)
==
prop_entry
->
prop
.
id
)
{
TRACE
(
"Found match with already added new property id %d
\n
"
,
prop_entry
->
prop
.
id
);
prop
=
&
prop_entry
->
prop
;
break
;
}
}
else
if
(
!
lstrcmpiA
(
pszName
,
prop_entry
->
prop
.
name
))
{
TRACE
(
"Found match with already added new property id %d
\n
"
,
prop_entry
->
prop
.
id
);
prop
=
&
prop_entry
->
prop
;
break
;
}
}
header
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
header
));
if
(
!
header
)
return
E_OUTOFMEMORY
;
if
(
!
prop
)
{
const
property_t
*
prop_def
=
NULL
;
prop_entry
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
prop_entry
));
if
(
!
prop_entry
)
{
HeapFree
(
GetProcessHeap
(),
0
,
header
);
return
E_OUTOFMEMORY
;
}
prop_def
=
find_default_prop
(
pszName
);
if
(
prop_def
)
{
prop_entry
->
prop
.
name
=
strdupA
(
prop_def
->
name
);
prop_entry
->
prop
.
id
=
prop_def
->
id
;
}
else
{
if
(
ISPIDSTR
(
pszName
))
{
HeapFree
(
GetProcessHeap
(),
0
,
prop_entry
);
HeapFree
(
GetProcessHeap
(),
0
,
header
);
return
MIME_E_NOT_FOUND
;
}
prop_entry
->
prop
.
name
=
strdupA
(
pszName
);
prop_entry
->
prop
.
id
=
This
->
next_prop_id
++
;
}
prop_entry
->
prop
.
flags
=
0
;
prop_entry
->
prop
.
default_vt
=
pValue
->
vt
;
list_add_tail
(
&
This
->
new_props
,
&
prop_entry
->
entry
);
prop
=
&
prop_entry
->
prop
;
TRACE
(
"Allocating new prop id %d
\n
"
,
prop_entry
->
prop
.
id
);
}
TRACE
(
"(%p)->(%d)
\n
"
,
This
,
ietEncoding
);
header
->
prop
=
prop
;
PropVariantInit
(
&
header
->
value
);
list_init
(
&
header
->
params
);
list_add_tail
(
&
This
->
headers
,
&
header
->
entry
);
}
This
->
encoding
=
ietEncoding
;
return
S_OK
;
}
PropVariantCopy
(
&
header
->
value
,
pValue
);
static
HRESULT
WINAPI
MimeBody_GetEstimatedSize
(
IMimeBody
*
iface
,
ENCODINGTYPE
ietEncoding
,
ULONG
*
pcbSize
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%d, %p) stub
\n
"
,
This
,
ietEncoding
,
pcbSize
);
return
E_NOTIMPL
;
return
S_OK
;
}
static
HRESULT
WINAPI
MimeBody_GetDataHere
(
IMimeBody
*
iface
,
ENCODINGTYPE
ietEncoding
,
IStream
*
pStream
)
static
HRESULT
WINAPI
MimeBody_AppendProp
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
DWORD
dwFlags
,
LPPROPVARIANT
pValue
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%
d, %p) stub
\n
"
,
This
,
ietEncoding
,
pStream
);
FIXME
(
"(%p)->(%
s, 0x%x, %p) stub
\n
"
,
This
,
debugstr_a
(
pszName
),
dwFlags
,
pValue
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
MimeBody_GetData
(
IMimeBody
*
iface
,
ENCODINGTYPE
ietEncoding
,
IStream
**
ppStream
)
static
HRESULT
WINAPI
MimeBody_DeleteProp
(
IMimeBody
*
iface
,
LPCSTR
pszName
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%d, %p). Ignoring encoding type.
\n
"
,
This
,
ietEncoding
,
ppStream
);
*
ppStream
=
This
->
data
;
IStream_AddRef
(
*
ppStream
);
return
S_OK
;
}
header_t
*
cursor
;
BOOL
found
;
static
HRESULT
WINAPI
MimeBody_SetData
(
IMimeBody
*
iface
,
ENCODINGTYPE
ietEncoding
,
LPCSTR
pszPriType
,
LPCSTR
pszSubType
,
REFIID
riid
,
LPVOID
pvObject
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
TRACE
(
"(%p)->(%d, %s, %s, %s %p)
\n
"
,
This
,
ietEncoding
,
debugstr_a
(
pszPriType
),
debugstr_a
(
pszSubType
),
debugstr_guid
(
riid
),
pvObject
);
TRACE
(
"(%p)->(%s) stub
\n
"
,
This
,
debugstr_a
(
pszName
));
if
(
IsEqualIID
(
riid
,
&
IID_IStream
))
IStream_AddRef
((
IStream
*
)
pvObject
);
else
LIST_FOR_EACH_ENTRY
(
cursor
,
&
This
->
headers
,
header_t
,
entry
)
{
FIXME
(
"Unhandled object type %s
\n
"
,
debugstr_guid
(
riid
));
return
E_INVALIDARG
;
}
if
(
This
->
data
)
FIXME
(
"release old data
\n
"
);
This
->
data_iid
=
*
riid
;
This
->
data
=
pvObject
;
IMimeBody_SetCurrentEncoding
(
iface
,
ietEncoding
);
if
(
ISPIDSTR
(
pszName
))
found
=
STRTOPID
(
pszName
)
==
cursor
->
prop
->
id
;
else
found
=
!
lstrcmpiA
(
pszName
,
cursor
->
prop
->
name
);
/* FIXME: Update the content type.
If pszPriType == NULL use 'application'
If pszSubType == NULL use 'octet-stream' */
if
(
found
)
{
list_remove
(
&
cursor
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
cursor
);
return
S_OK
;
}
}
return
S_OK
;
return
MIME_E_NOT_FOUND
;
}
static
HRESULT
WINAPI
MimeBody_EmptyData
(
IMimeBody
*
iface
)
static
HRESULT
WINAPI
MimeBody_CopyProps
(
IMimeBody
*
iface
,
ULONG
cNames
,
LPCSTR
*
prgszName
,
IMimePropertySet
*
pPropertySet
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(
) stub
\n
"
,
This
);
FIXME
(
"(%p)->(
%d, %p, %p) stub
\n
"
,
This
,
cNames
,
prgszName
,
pPropertySet
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
MimeBody_CopyTo
(
IMimeBody
*
iface
,
IMimeBody
*
pBody
)
static
HRESULT
WINAPI
MimeBody_MoveProps
(
IMimeBody
*
iface
,
ULONG
cNames
,
LPCSTR
*
prgszName
,
IMimePropertySet
*
pPropertySet
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%
p) stub
\n
"
,
This
,
pBody
);
FIXME
(
"(%p)->(%
d, %p, %p) stub
\n
"
,
This
,
cNames
,
prgszName
,
pPropertySet
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
MimeBody_GetTransmitInfo
(
IMimeBody
*
iface
,
LPTRANSMITINFO
pTransmitInfo
)
static
HRESULT
WINAPI
MimeBody_DeleteExcept
(
IMimeBody
*
iface
,
ULONG
cNames
,
LPCSTR
*
prgszName
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%
p) stub
\n
"
,
This
,
pTransmitInfo
);
FIXME
(
"(%p)->(%
d, %p) stub
\n
"
,
This
,
cNames
,
prgszName
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
MimeBody_SaveToFile
(
IMimeBody
*
iface
,
ENCODINGTYPE
ietEncoding
,
LPCSTR
pszFilePath
)
static
HRESULT
WINAPI
MimeBody_QueryProp
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
LPCSTR
pszCriteria
,
boolean
fSubString
,
boolean
fCaseSensitive
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%
d, %s) stub
\n
"
,
This
,
ietEncoding
,
debugstr_a
(
pszFilePath
)
);
FIXME
(
"(%p)->(%
s, %s, %d, %d) stub
\n
"
,
This
,
debugstr_a
(
pszName
),
debugstr_a
(
pszCriteria
),
fSubString
,
fCaseSensitive
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
MimeBody_Get
Handle
(
IMimeBody
*
iface
,
LPHBODY
phBody
)
static
HRESULT
WINAPI
MimeBody_Get
Charset
(
IMimeBody
*
iface
,
LPHCHARSET
phCharset
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
TRACE
(
"(%p)->(%p)
\n
"
,
iface
,
phBody
);
if
(
!
phBody
)
return
E_INVALIDARG
;
*
phBody
=
This
->
handle
;
return
This
->
handle
?
S_OK
:
MIME_E_NO_DATA
;
FIXME
(
"(%p)->(%p) stub
\n
"
,
This
,
phCharset
);
*
phCharset
=
NULL
;
return
S_OK
;
}
static
IMimeBodyVtbl
body_vtbl
=
static
HRESULT
WINAPI
MimeBody_SetCharset
(
IMimeBody
*
iface
,
HCHARSET
hCharset
,
CSETAPPLYTYPE
applytype
)
{
MimeBody_QueryInterface
,
MimeBody_AddRef
,
MimeBody_Release
,
MimeBody_GetClassID
,
MimeBody_IsDirty
,
MimeBody_Load
,
MimeBody_Save
,
MimeBody_GetSizeMax
,
MimeBody_InitNew
,
MimeBody_GetPropInfo
,
MimeBody_SetPropInfo
,
MimeBody_GetProp
,
MimeBody_SetProp
,
MimeBody_AppendProp
,
MimeBody_DeleteProp
,
MimeBody_CopyProps
,
MimeBody_MoveProps
,
MimeBody_DeleteExcept
,
MimeBody_QueryProp
,
MimeBody_GetCharset
,
MimeBody_SetCharset
,
MimeBody_GetParameters
,
MimeBody_IsContentType
,
MimeBody_BindToObject
,
MimeBody_Clone
,
MimeBody_SetOption
,
MimeBody_GetOption
,
MimeBody_EnumProps
,
MimeBody_IsType
,
MimeBody_SetDisplayName
,
MimeBody_GetDisplayName
,
MimeBody_GetOffsets
,
MimeBody_GetCurrentEncoding
,
MimeBody_SetCurrentEncoding
,
MimeBody_GetEstimatedSize
,
MimeBody_GetDataHere
,
MimeBody_GetData
,
MimeBody_SetData
,
MimeBody_EmptyData
,
MimeBody_CopyTo
,
MimeBody_GetTransmitInfo
,
MimeBody_SaveToFile
,
MimeBody_GetHandle
};
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%p, %d) stub
\n
"
,
This
,
hCharset
,
applytype
);
return
E_NOTIMPL
;
}
static
HRESULT
MimeBody_set_offsets
(
MimeBody
*
body
,
const
BODYOFFSETS
*
offsets
)
static
HRESULT
WINAPI
MimeBody_GetParameters
(
IMimeBody
*
iface
,
LPCSTR
pszName
,
ULONG
*
pcParams
,
LPMIMEPARAMINFO
*
pprgParam
)
{
TRACE
(
"setting offsets to %d, %d, %d, %d
\n
"
,
offsets
->
cbBoundaryStart
,
offsets
->
cbHeaderStart
,
offsets
->
cbBodyStart
,
offsets
->
cbBodyEnd
);
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
HRESULT
hr
;
header_t
*
header
;
body
->
body_offsets
=
*
offsets
;
return
S_OK
;
}
TRACE
(
"(%p)->(%s, %p, %p)
\n
"
,
iface
,
debugstr_a
(
pszName
),
pcParams
,
pprgParam
);
#define FIRST_CUSTOM_PROP_ID 0x100
*
pprgParam
=
NULL
;
*
pcParams
=
0
;
static
MimeBody
*
mimebody_create
(
void
)
{
MimeBody
*
This
;
BODYOFFSETS
body_offsets
;
hr
=
find_prop
(
This
,
pszName
,
&
header
);
if
(
hr
!=
S_OK
)
return
hr
;
This
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
This
));
if
(
!
This
)
return
NULL
;
*
pcParams
=
list_count
(
&
header
->
params
);
if
(
*
pcParams
)
{
IMimeAllocator
*
alloc
;
param_t
*
param
;
MIMEPARAMINFO
*
info
;
This
->
IMimeBody_iface
.
lpVtbl
=
&
body_vtbl
;
This
->
ref
=
1
;
This
->
handle
=
NULL
;
list_init
(
&
This
->
headers
);
list_init
(
&
This
->
new_props
);
This
->
next_prop_id
=
FIRST_CUSTOM_PROP_ID
;
This
->
content_pri_type
=
NULL
;
This
->
content_sub_type
=
NULL
;
This
->
encoding
=
IET_7BIT
;
This
->
data
=
NULL
;
This
->
data_iid
=
IID_NULL
;
MimeOleGetAllocator
(
&
alloc
);
body_offsets
.
cbBoundaryStart
=
body_offsets
.
cbHeaderStart
=
0
;
body_offsets
.
cbBodyStart
=
body_offsets
.
cbBodyEnd
=
0
;
MimeBody_set_offsets
(
This
,
&
body_offsets
);
*
pprgParam
=
info
=
IMimeAllocator_Alloc
(
alloc
,
*
pcParams
*
sizeof
(
**
pprgParam
));
LIST_FOR_EACH_ENTRY
(
param
,
&
header
->
params
,
param_t
,
entry
)
{
int
len
;
return
This
;
len
=
strlen
(
param
->
name
)
+
1
;
info
->
pszName
=
IMimeAllocator_Alloc
(
alloc
,
len
);
memcpy
(
info
->
pszName
,
param
->
name
,
len
);
len
=
strlen
(
param
->
value
)
+
1
;
info
->
pszData
=
IMimeAllocator_Alloc
(
alloc
,
len
);
memcpy
(
info
->
pszData
,
param
->
value
,
len
);
info
++
;
}
IMimeAllocator_Release
(
alloc
);
}
return
S_OK
;
}
HRESULT
MimeBody_create
(
IUnknown
*
outer
,
void
**
ppv
)
static
HRESULT
WINAPI
MimeBody_IsContentType
(
IMimeBody
*
iface
,
LPCSTR
pszPriType
,
LPCSTR
pszSubType
)
{
MimeBody
*
mb
;
if
(
outer
)
return
CLASS_E_NOAGGREGATION
;
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
if
((
mb
=
mimebody_create
()))
TRACE
(
"(%p)->(%s, %s)
\n
"
,
This
,
debugstr_a
(
pszPriType
),
debugstr_a
(
pszSubType
));
if
(
pszPriType
)
{
*
ppv
=
&
mb
->
IMimeBody_iface
;
return
S_OK
;
const
char
*
pri
=
This
->
content_pri_type
;
if
(
!
pri
)
pri
=
"text"
;
if
(
lstrcmpiA
(
pri
,
pszPriType
))
return
S_FALSE
;
}
else
if
(
pszSubType
)
{
*
ppv
=
NULL
;
return
E_OUTOFMEMORY
;
const
char
*
sub
=
This
->
content_sub_type
;
if
(
!
sub
)
sub
=
"plain"
;
if
(
lstrcmpiA
(
sub
,
pszSubType
))
return
S_FALSE
;
}
}
return
S_OK
;
}
typedef
struct
static
HRESULT
WINAPI
MimeBody_BindToObject
(
IMimeBody
*
iface
,
REFIID
riid
,
void
**
ppvObject
)
{
IStream
IStream_iface
;
LONG
ref
;
IStream
*
base
;
ULARGE_INTEGER
pos
,
start
,
length
;
}
sub_stream_t
;
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%s, %p) stub
\n
"
,
This
,
debugstr_guid
(
riid
),
ppvObject
);
return
E_NOTIMPL
;
}
static
inline
sub_stream_t
*
impl_from_IStream
(
IStream
*
iface
)
static
HRESULT
WINAPI
MimeBody_Clone
(
IMimeBody
*
iface
,
IMimePropertySet
**
ppPropertySet
)
{
return
CONTAINING_RECORD
(
iface
,
sub_stream_t
,
IStream_iface
);
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%p) stub
\n
"
,
This
,
ppPropertySet
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
sub_stream_QueryInterface
(
IStream
*
iface
,
REFIID
riid
,
void
**
ppv
)
static
HRESULT
WINAPI
MimeBody_SetOption
(
IMimeBody
*
iface
,
const
TYPEDID
oid
,
LPCPROPVARIANT
pValue
)
{
sub_stream_t
*
This
=
impl_from_IStream
(
iface
);
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
HRESULT
hr
=
E_NOTIMPL
;
TRACE
(
"(%p)->(%08x, %p)
\n
"
,
This
,
oid
,
pValue
);
TRACE
(
"(%p)->(%s, %p)
\n
"
,
This
,
debugstr_guid
(
riid
),
ppv
);
*
ppv
=
NULL
;
if
(
pValue
->
vt
!=
TYPEDID_TYPE
(
oid
))
{
WARN
(
"Called with vartype %04x and oid %08x
\n
"
,
pValue
->
vt
,
oid
);
return
E_INVALIDARG
;
}
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
)
||
IsEqualIID
(
riid
,
&
IID_ISequentialStream
)
||
IsEqualIID
(
riid
,
&
IID_IStream
))
switch
(
oid
)
{
IStream_AddRef
(
iface
);
*
ppv
=
iface
;
return
S_OK
;
case
OID_SECURITY_HWND_OWNER
:
FIXME
(
"OID_SECURITY_HWND_OWNER (value %08x): ignoring
\n
"
,
pValue
->
u
.
ulVal
);
hr
=
S_OK
;
break
;
case
OID_TRANSMIT_BODY_ENCODING
:
FIXME
(
"OID_TRANSMIT_BODY_ENCODING (value %08x): ignoring
\n
"
,
pValue
->
u
.
ulVal
);
hr
=
S_OK
;
break
;
default:
FIXME
(
"Unhandled oid %08x
\n
"
,
oid
);
}
return
E_NOINTERFACE
;
return
hr
;
}
static
ULONG
WINAPI
sub_stream_AddRef
(
IStream
*
iface
)
static
HRESULT
WINAPI
MimeBody_GetOption
(
IMimeBody
*
iface
,
const
TYPEDID
oid
,
LPPROPVARIANT
pValue
)
{
sub_stream_t
*
This
=
impl_from_IStream
(
iface
);
LONG
ref
=
InterlockedIncrement
(
&
This
->
ref
);
TRACE
(
"(%p) ref=%d
\n
"
,
This
,
ref
);
return
ref
;
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%08x, %p): stub
\n
"
,
This
,
oid
,
pValue
);
return
E_NOTIMPL
;
}
static
ULONG
WINAPI
sub_stream_Release
(
IStream
*
iface
)
static
HRESULT
WINAPI
MimeBody_EnumProps
(
IMimeBody
*
iface
,
DWORD
dwFlags
,
IMimeEnumProperties
**
ppEnum
)
{
sub_stream_t
*
This
=
impl_from_IStream
(
iface
);
LONG
ref
=
InterlockedDecrement
(
&
This
->
ref
);
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(0x%x, %p) stub
\n
"
,
This
,
dwFlags
,
ppEnum
);
return
E_NOTIMPL
;
}
TRACE
(
"(%p) ref=%d
\n
"
,
This
,
ref
);
static
HRESULT
WINAPI
MimeBody_IsType
(
IMimeBody
*
iface
,
IMSGBODYTYPE
bodytype
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
if
(
!
ref
)
TRACE
(
"(%p)->(%d)
\n
"
,
This
,
bodytype
);
switch
(
bodytype
)
{
IStream_Release
(
This
->
base
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
case
IBT_EMPTY
:
return
This
->
data
?
S_FALSE
:
S_OK
;
default:
FIXME
(
"Unimplemented bodytype %d - returning S_OK
\n
"
,
bodytype
);
}
return
ref
;
return
S_OK
;
}
static
HRESULT
WINAPI
sub_stream_Read
(
IStream
*
iface
,
void
*
pv
,
ULONG
cb
,
ULONG
*
pcbRead
)
static
HRESULT
WINAPI
MimeBody_SetDisplayName
(
IMimeBody
*
iface
,
LPCSTR
pszDisplay
)
{
sub_stream_t
*
This
=
impl_from_IStream
(
iface
);
HRESULT
hr
;
ULARGE_INTEGER
base_pos
;
LARGE_INTEGER
tmp_pos
;
TRACE
(
"(%p, %d, %p)
\n
"
,
pv
,
cb
,
pcbRead
);
tmp_pos
.
QuadPart
=
0
;
IStream_Seek
(
This
->
base
,
tmp_pos
,
STREAM_SEEK_CUR
,
&
base_pos
);
tmp_pos
.
QuadPart
=
This
->
pos
.
QuadPart
+
This
->
start
.
QuadPart
;
IStream_Seek
(
This
->
base
,
tmp_pos
,
STREAM_SEEK_SET
,
NULL
);
if
(
This
->
pos
.
QuadPart
+
cb
>
This
->
length
.
QuadPart
)
cb
=
This
->
length
.
QuadPart
-
This
->
pos
.
QuadPart
;
hr
=
IStream_Read
(
This
->
base
,
pv
,
cb
,
pcbRead
);
This
->
pos
.
QuadPart
+=
*
pcbRead
;
tmp_pos
.
QuadPart
=
base_pos
.
QuadPart
;
IStream_Seek
(
This
->
base
,
tmp_pos
,
STREAM_SEEK_SET
,
NULL
);
return
hr
;
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%s) stub
\n
"
,
This
,
debugstr_a
(
pszDisplay
));
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
sub_stream_Write
(
IStream
*
iface
,
const
void
*
pv
,
ULONG
cb
,
ULONG
*
pcbWritten
)
static
HRESULT
WINAPI
MimeBody_GetDisplayName
(
IMimeBody
*
iface
,
LPSTR
*
ppszDisplay
)
{
FIXME
(
"stub
\n
"
);
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%p) stub
\n
"
,
This
,
ppszDisplay
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
sub_stream_Seek
(
IStream
*
iface
,
LARGE_INTEGER
dlibMove
,
DWORD
dwOrigin
,
ULARGE_INTEGER
*
plibNewPosition
)
static
HRESULT
WINAPI
MimeBody_GetOffsets
(
IMimeBody
*
iface
,
LPBODYOFFSETS
pOffsets
)
{
sub_stream_t
*
This
=
impl_from_IStream
(
iface
);
LARGE_INTEGER
new_pos
;
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
TRACE
(
"(%p)->(%p)
\n
"
,
This
,
pOffsets
)
;
TRACE
(
"(%08x.%08x, %x, %p)
\n
"
,
dlibMove
.
u
.
HighPart
,
dlibMove
.
u
.
LowPart
,
dwOrigin
,
plibNewPosition
)
;
*
pOffsets
=
This
->
body_offsets
;
switch
(
dwOrigin
)
{
case
STREAM_SEEK_SET
:
new_pos
=
dlibMove
;
break
;
case
STREAM_SEEK_CUR
:
new_pos
.
QuadPart
=
This
->
pos
.
QuadPart
+
dlibMove
.
QuadPart
;
break
;
case
STREAM_SEEK_END
:
new_pos
.
QuadPart
=
This
->
length
.
QuadPart
+
dlibMove
.
QuadPart
;
break
;
default:
return
STG_E_INVALIDFUNCTION
;
}
if
(
This
->
body_offsets
.
cbBodyEnd
==
0
)
return
MIME_E_NO_DATA
;
return
S_OK
;
}
if
(
new_pos
.
QuadPart
<
0
)
new_pos
.
QuadPart
=
0
;
else
if
(
new_pos
.
QuadPart
>
This
->
length
.
QuadPart
)
new_pos
.
QuadPart
=
This
->
length
.
QuadPart
;
static
HRESULT
WINAPI
MimeBody_GetCurrentEncoding
(
IMimeBody
*
iface
,
ENCODINGTYPE
*
pietEncoding
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
T
his
->
pos
.
QuadPart
=
new_pos
.
QuadPart
;
T
RACE
(
"(%p)->(%p)
\n
"
,
This
,
pietEncoding
)
;
if
(
plibNewPosition
)
*
plibNewPosition
=
This
->
pos
;
*
pietEncoding
=
This
->
encoding
;
return
S_OK
;
}
static
HRESULT
WINAPI
sub_stream_SetSize
(
IStream
*
iface
,
ULARGE_INTEGER
libNewSize
)
static
HRESULT
WINAPI
MimeBody_SetCurrentEncoding
(
IMimeBody
*
iface
,
ENCODINGTYPE
ietEncoding
)
{
FIXME
(
"stub
\n
"
);
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
TRACE
(
"(%p)->(%d)
\n
"
,
This
,
ietEncoding
);
This
->
encoding
=
ietEncoding
;
return
S_OK
;
}
static
HRESULT
WINAPI
MimeBody_GetEstimatedSize
(
IMimeBody
*
iface
,
ENCODINGTYPE
ietEncoding
,
ULONG
*
pcbSize
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%d, %p) stub
\n
"
,
This
,
ietEncoding
,
pcbSize
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
sub_stream_CopyTo
(
IStream
*
iface
,
IStream
*
pstm
,
ULARGE_INTEGER
cb
,
ULARGE_INTEGER
*
pcbRead
,
ULARGE_INTEGER
*
pcbWritten
)
static
HRESULT
WINAPI
MimeBody_GetDataHere
(
IMimeBody
*
iface
,
ENCODINGTYPE
ietEncoding
,
IStream
*
pStream
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%d, %p) stub
\n
"
,
This
,
ietEncoding
,
pStream
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
MimeBody_GetData
(
IMimeBody
*
iface
,
ENCODINGTYPE
ietEncoding
,
IStream
**
ppStream
)
{
HRESULT
hr
=
S_OK
;
BYTE
tmpBuffer
[
128
];
ULONG
bytesRead
,
bytesWritten
,
copySize
;
ULARGE_INTEGER
totalBytesRead
;
ULARGE_INTEGER
totalBytesWritten
;
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%d, %p). Ignoring encoding type.
\n
"
,
This
,
ietEncoding
,
ppStream
);
TRACE
(
"(%p)->(%p, %d, %p, %p)
\n
"
,
iface
,
pstm
,
cb
.
u
.
LowPart
,
pcbRead
,
pcbWritten
);
*
ppStream
=
This
->
data
;
IStream_AddRef
(
*
ppStream
);
return
S_OK
;
}
totalBytesRead
.
QuadPart
=
0
;
totalBytesWritten
.
QuadPart
=
0
;
static
HRESULT
WINAPI
MimeBody_SetData
(
IMimeBody
*
iface
,
ENCODINGTYPE
ietEncoding
,
LPCSTR
pszPriType
,
LPCSTR
pszSubType
,
REFIID
riid
,
LPVOID
pvObject
)
{
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
TRACE
(
"(%p)->(%d, %s, %s, %s %p)
\n
"
,
This
,
ietEncoding
,
debugstr_a
(
pszPriType
),
debugstr_a
(
pszSubType
),
debugstr_guid
(
riid
),
pvObject
);
while
(
cb
.
QuadPart
>
0
)
if
(
IsEqualIID
(
riid
,
&
IID_IStream
))
IStream_AddRef
((
IStream
*
)
pvObject
);
else
{
if
(
cb
.
QuadPart
>=
sizeof
(
tmpBuffer
)
)
copySize
=
sizeof
(
tmpBuffer
);
else
copySize
=
cb
.
u
.
LowPart
;
hr
=
IStream_Read
(
iface
,
tmpBuffer
,
copySize
,
&
bytesRead
);
if
(
FAILED
(
hr
))
break
;
FIXME
(
"Unhandled object type %s
\n
"
,
debugstr_guid
(
riid
));
return
E_INVALIDARG
;
}
totalBytesRead
.
QuadPart
+=
bytesRead
;
if
(
This
->
data
)
FIXME
(
"release old data
\n
"
);
if
(
bytesRead
)
{
hr
=
IStream_Write
(
pstm
,
tmpBuffer
,
bytesRead
,
&
bytesWritten
);
if
(
FAILED
(
hr
))
break
;
totalBytesWritten
.
QuadPart
+=
bytesWritten
;
}
This
->
data_iid
=
*
riid
;
This
->
data
=
pvObject
;
if
(
bytesRead
!=
copySize
)
cb
.
QuadPart
=
0
;
else
cb
.
QuadPart
-=
bytesRead
;
}
IMimeBody_SetCurrentEncoding
(
iface
,
ietEncoding
);
if
(
pcbRead
)
pcbRead
->
QuadPart
=
totalBytesRead
.
QuadPart
;
if
(
pcbWritten
)
pcbWritten
->
QuadPart
=
totalBytesWritten
.
QuadPart
;
/* FIXME: Update the content type.
If pszPriType == NULL use 'application'
If pszSubType == NULL use 'octet-stream' */
return
hr
;
return
S_OK
;
}
static
HRESULT
WINAPI
sub_stream_Commit
(
IStream
*
iface
,
DWORD
grfCommitFlags
)
static
HRESULT
WINAPI
MimeBody_EmptyData
(
IMimeBody
*
iface
)
{
FIXME
(
"stub
\n
"
);
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->() stub
\n
"
,
This
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
sub_stream_Revert
(
IStream
*
iface
)
static
HRESULT
WINAPI
MimeBody_CopyTo
(
IMimeBody
*
iface
,
IMimeBody
*
pBody
)
{
FIXME
(
"stub
\n
"
);
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%p) stub
\n
"
,
This
,
pBody
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
sub_stream_LockRegion
(
IStream
*
iface
,
ULARGE_INTEGER
libOffset
,
ULARGE_INTEGER
cb
,
DWORD
dwLockType
)
static
HRESULT
WINAPI
MimeBody_GetTransmitInfo
(
IMimeBody
*
iface
,
LPTRANSMITINFO
pTransmitInfo
)
{
FIXME
(
"stub
\n
"
);
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%p) stub
\n
"
,
This
,
pTransmitInfo
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
sub_stream_UnlockRegion
(
IStream
*
iface
,
ULARGE_INTEGER
libOffset
,
ULARGE_INTEGER
cb
,
DWORD
dwLockType
)
static
HRESULT
WINAPI
MimeBody_SaveToFile
(
IMimeBody
*
iface
,
ENCODINGTYPE
ietEncoding
,
LPCSTR
pszFilePath
)
{
FIXME
(
"stub
\n
"
);
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
FIXME
(
"(%p)->(%d, %s) stub
\n
"
,
This
,
ietEncoding
,
debugstr_a
(
pszFilePath
));
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
sub_stream_Stat
(
IStream
*
iface
,
STATSTG
*
pstatstg
,
DWORD
grfStatFlag
)
static
HRESULT
WINAPI
MimeBody_GetHandle
(
IMimeBody
*
iface
,
LPHBODY
phBody
)
{
sub_stream_t
*
This
=
impl_from_IStream
(
iface
);
FIXME
(
"(%p)->(%p, %08x)
\n
"
,
This
,
pstatstg
,
grfStatFlag
);
memset
(
pstatstg
,
0
,
sizeof
(
*
pstatstg
));
pstatstg
->
cbSize
=
This
->
length
;
return
S_OK
;
}
MimeBody
*
This
=
impl_from_IMimeBody
(
iface
);
TRACE
(
"(%p)->(%p)
\n
"
,
iface
,
phBody
);
static
HRESULT
WINAPI
sub_stream_Clone
(
IStream
*
iface
,
IStream
**
ppstm
)
{
FIXME
(
"stub
\n
"
);
return
E_NOTIMPL
;
if
(
!
phBody
)
return
E_INVALIDARG
;
*
phBody
=
This
->
handle
;
return
This
->
handle
?
S_OK
:
MIME_E_NO_DATA
;
}
static
struct
IStreamVtbl
sub_stream
_vtbl
=
static
IMimeBodyVtbl
body
_vtbl
=
{
sub_stream_QueryInterface
,
sub_stream_AddRef
,
sub_stream_Release
,
sub_stream_Read
,
sub_stream_Write
,
sub_stream_Seek
,
sub_stream_SetSize
,
sub_stream_CopyTo
,
sub_stream_Commit
,
sub_stream_Revert
,
sub_stream_LockRegion
,
sub_stream_UnlockRegion
,
sub_stream_Stat
,
sub_stream_Clone
MimeBody_QueryInterface
,
MimeBody_AddRef
,
MimeBody_Release
,
MimeBody_GetClassID
,
MimeBody_IsDirty
,
MimeBody_Load
,
MimeBody_Save
,
MimeBody_GetSizeMax
,
MimeBody_InitNew
,
MimeBody_GetPropInfo
,
MimeBody_SetPropInfo
,
MimeBody_GetProp
,
MimeBody_SetProp
,
MimeBody_AppendProp
,
MimeBody_DeleteProp
,
MimeBody_CopyProps
,
MimeBody_MoveProps
,
MimeBody_DeleteExcept
,
MimeBody_QueryProp
,
MimeBody_GetCharset
,
MimeBody_SetCharset
,
MimeBody_GetParameters
,
MimeBody_IsContentType
,
MimeBody_BindToObject
,
MimeBody_Clone
,
MimeBody_SetOption
,
MimeBody_GetOption
,
MimeBody_EnumProps
,
MimeBody_IsType
,
MimeBody_SetDisplayName
,
MimeBody_GetDisplayName
,
MimeBody_GetOffsets
,
MimeBody_GetCurrentEncoding
,
MimeBody_SetCurrentEncoding
,
MimeBody_GetEstimatedSize
,
MimeBody_GetDataHere
,
MimeBody_GetData
,
MimeBody_SetData
,
MimeBody_EmptyData
,
MimeBody_CopyTo
,
MimeBody_GetTransmitInfo
,
MimeBody_SaveToFile
,
MimeBody_GetHandle
};
static
HRESULT
create_sub_stream
(
IStream
*
stream
,
ULARGE_INTEGER
start
,
ULARGE_INTEGER
length
,
IStream
**
out
)
static
HRESULT
MimeBody_set_offsets
(
MimeBody
*
body
,
const
BODYOFFSETS
*
offsets
)
{
sub_stream_t
*
This
;
TRACE
(
"setting offsets to %d, %d, %d, %d
\n
"
,
offsets
->
cbBoundaryStart
,
offsets
->
cbHeaderStart
,
offsets
->
cbBodyStart
,
offsets
->
cbBodyEnd
);
body
->
body_offsets
=
*
offsets
;
return
S_OK
;
}
#define FIRST_CUSTOM_PROP_ID 0x100
static
MimeBody
*
mimebody_create
(
void
)
{
MimeBody
*
This
;
BODYOFFSETS
body_offsets
;
*
out
=
NULL
;
This
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
This
));
if
(
!
This
)
return
E_OUTOFMEMORY
;
if
(
!
This
)
return
NULL
;
This
->
I
Stream_iface
.
lpVtbl
=
&
sub_stream
_vtbl
;
This
->
I
MimeBody_iface
.
lpVtbl
=
&
body
_vtbl
;
This
->
ref
=
1
;
This
->
start
=
start
;
This
->
length
=
length
;
This
->
pos
.
QuadPart
=
0
;
IStream_AddRef
(
stream
);
This
->
base
=
stream
;
This
->
handle
=
NULL
;
list_init
(
&
This
->
headers
);
list_init
(
&
This
->
new_props
);
This
->
next_prop_id
=
FIRST_CUSTOM_PROP_ID
;
This
->
content_pri_type
=
NULL
;
This
->
content_sub_type
=
NULL
;
This
->
encoding
=
IET_7BIT
;
This
->
data
=
NULL
;
This
->
data_iid
=
IID_NULL
;
*
out
=
&
This
->
IStream_iface
;
return
S_OK
;
body_offsets
.
cbBoundaryStart
=
body_offsets
.
cbHeaderStart
=
0
;
body_offsets
.
cbBodyStart
=
body_offsets
.
cbBodyEnd
=
0
;
MimeBody_set_offsets
(
This
,
&
body_offsets
);
return
This
;
}
HRESULT
MimeBody_create
(
IUnknown
*
outer
,
void
**
ppv
)
{
MimeBody
*
mb
;
if
(
outer
)
return
CLASS_E_NOAGGREGATION
;
if
((
mb
=
mimebody_create
()))
{
*
ppv
=
&
mb
->
IMimeBody_iface
;
return
S_OK
;
}
else
{
*
ppv
=
NULL
;
return
E_OUTOFMEMORY
;
}
}
typedef
struct
body_t
{
...
...
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