Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
70281427
Commit
70281427
authored
Jul 15, 2018
by
Michael Stefaniuc
Committed by
Alexandre Julliard
Jul 16, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dmusic: Sync up the dmobject.[ch] files.
Signed-off-by:
Michael Stefaniuc
<
mstefani@winehq.org
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
73b782c9
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
1855 additions
and
0 deletions
+1855
-0
dmobject.c
dlls/dmband/dmobject.c
+212
-0
dmobject.h
dlls/dmband/dmobject.h
+53
-0
dmobject.c
dlls/dmcompos/dmobject.c
+212
-0
dmobject.h
dlls/dmcompos/dmobject.h
+53
-0
dmobject.c
dlls/dmloader/dmobject.c
+212
-0
dmobject.h
dlls/dmloader/dmobject.h
+53
-0
dmobject.c
dlls/dmscript/dmobject.c
+212
-0
dmobject.h
dlls/dmscript/dmobject.h
+53
-0
dmobject.c
dlls/dmstyle/dmobject.c
+212
-0
dmobject.h
dlls/dmstyle/dmobject.h
+53
-0
dmobject.c
dlls/dmusic/dmobject.c
+212
-0
dmobject.h
dlls/dmusic/dmobject.h
+53
-0
dmobject.c
dlls/dswave/dmobject.c
+212
-0
dmobject.h
dlls/dswave/dmobject.h
+53
-0
No files found.
dlls/dmband/dmobject.c
View file @
70281427
...
...
@@ -21,12 +21,152 @@
*/
#define COBJMACROS
#include <assert.h>
#include "objbase.h"
#include "dmusici.h"
#include "dmusicf.h"
#include "dmobject.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dmobj
);
WINE_DECLARE_DEBUG_CHANNEL
(
dmfile
);
/* RIFF format parsing */
#define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
static
inline
const
char
*
debugstr_fourcc
(
DWORD
fourcc
)
{
if
(
!
fourcc
)
return
"''"
;
return
wine_dbg_sprintf
(
"'%c%c%c%c'"
,
(
char
)(
fourcc
),
(
char
)(
fourcc
>>
8
),
(
char
)(
fourcc
>>
16
),
(
char
)(
fourcc
>>
24
));
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
{
const
char
*
type
=
""
;
if
(
!
chunk
)
return
"(null)"
;
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
type
=
wine_dbg_sprintf
(
"type %s, "
,
debugstr_fourcc
(
chunk
->
type
));
return
wine_dbg_sprintf
(
"%s chunk, %ssize %u"
,
debugstr_fourcc
(
chunk
->
id
),
type
,
chunk
->
size
);
}
static
HRESULT
stream_read
(
IStream
*
stream
,
void
*
data
,
ULONG
size
)
{
ULONG
read
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
data
,
size
,
&
read
);
if
(
FAILED
(
hr
))
TRACE_
(
dmfile
)(
"IStream_Read failed: %08x
\n
"
,
hr
);
else
if
(
!
read
&&
read
<
size
)
{
/* All or nothing: Handle a partial read due to end of stream as an error */
TRACE_
(
dmfile
)(
"Short read: %u < %u
\n
"
,
read
,
size
);
return
E_FAIL
;
}
return
hr
;
}
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
static
const
LARGE_INTEGER
zero
;
ULONGLONG
ck_end
=
0
,
p_end
=
0
;
HRESULT
hr
;
hr
=
IStream_Seek
(
stream
,
zero
,
STREAM_SEEK_CUR
,
&
chunk
->
offset
);
if
(
FAILED
(
hr
))
return
hr
;
assert
(
!
(
chunk
->
offset
.
QuadPart
&
1
));
if
(
chunk
->
parent
)
{
p_end
=
chunk
->
parent
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
((
chunk
->
parent
->
size
+
1
)
&
~
1
);
if
(
chunk
->
offset
.
QuadPart
==
p_end
)
return
S_FALSE
;
ck_end
=
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk header in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
hr
=
stream_read
(
stream
,
chunk
,
CHUNK_HDR_SIZE
);
if
(
hr
!=
S_OK
)
return
hr
;
if
(
chunk
->
parent
)
{
ck_end
+=
(
chunk
->
size
+
1
)
&
~
1
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk data in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
if
(
chunk
->
id
==
FOURCC_LIST
||
chunk
->
id
==
FOURCC_RIFF
)
{
hr
=
stream_read
(
stream
,
&
chunk
->
type
,
sizeof
(
FOURCC
));
if
(
hr
!=
S_OK
)
return
hr
!=
S_FALSE
?
hr
:
E_FAIL
;
}
TRACE_
(
dmfile
)(
"Returning %s
\n
"
,
debugstr_chunk
(
chunk
));
return
S_OK
;
}
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
end
;
end
.
QuadPart
=
(
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
chunk
->
size
+
1
)
&
~
(
ULONGLONG
)
1
;
return
IStream_Seek
(
stream
,
end
,
STREAM_SEEK_SET
,
NULL
);
}
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
HRESULT
hr
;
if
(
chunk
->
id
)
{
hr
=
stream_skip_chunk
(
stream
,
chunk
);
if
(
FAILED
(
hr
))
return
hr
;
}
return
stream_get_chunk
(
stream
,
chunk
);
}
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
{
if
(
chunk
->
size
!=
size
)
{
WARN_
(
dmfile
)(
"Chunk %s (size %u, offset %s) doesn't contains the expected data size %u
\n
"
,
debugstr_fourcc
(
chunk
->
id
),
chunk
->
size
,
wine_dbgstr_longlong
(
chunk
->
offset
.
QuadPart
),
size
);
return
E_FAIL
;
}
return
stream_read
(
stream
,
data
,
size
);
}
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
{
ULONG
len
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
str
,
min
(
chunk
->
size
,
size
),
&
len
);
if
(
FAILED
(
hr
))
return
hr
;
/* Don't assume the string is properly zero terminated */
str
[
min
(
len
,
size
-
1
)]
=
0
;
if
(
len
<
chunk
->
size
)
return
S_FALSE
;
return
S_OK
;
}
/* Generic IDirectMusicObject methods */
static
inline
struct
dmobject
*
impl_from_IDirectMusicObject
(
IDirectMusicObject
*
iface
)
...
...
@@ -110,6 +250,78 @@ HRESULT WINAPI dmobj_IDirectMusicObject_SetDescriptor(IDirectMusicObject *iface,
return
ret
;
}
/* Helper for IDirectMusicObject::ParseDescriptor */
static
inline
void
info_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
info
,
DMUS_OBJECTDESC
*
desc
)
{
struct
chunk_entry
chunk
=
{.
parent
=
info
};
char
name
[
DMUS_MAX_NAME
];
ULONG
len
;
HRESULT
hr
=
E_FAIL
;
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
))
hr
=
IStream_Read
(
stream
,
name
,
min
(
chunk
.
size
,
sizeof
(
name
)),
&
len
);
if
(
SUCCEEDED
(
hr
))
{
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
name
,
len
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
));
desc
->
wszName
[
min
(
len
,
sizeof
(
desc
->
wszName
)
-
1
)]
=
0
;
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
}
static
inline
void
unfo_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
unfo
,
DMUS_OBJECTDESC
*
desc
,
BOOL
inam
)
{
struct
chunk_entry
chunk
=
{.
parent
=
unfo
};
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
DMUS_FOURCC_UNAM_CHUNK
||
(
inam
&&
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
)))
if
(
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
{
struct
chunk_entry
chunk
=
{.
parent
=
riff
};
HRESULT
hr
;
TRACE
(
"Looking for %#x in %p: %s
\n
"
,
supported
,
stream
,
debugstr_chunk
(
riff
));
desc
->
dwValidData
=
0
;
desc
->
dwSize
=
sizeof
(
*
desc
);
while
((
hr
=
stream_next_chunk
(
stream
,
&
chunk
))
==
S_OK
)
{
switch
(
chunk
.
id
)
{
case
DMUS_FOURCC_GUID_CHUNK
:
if
((
supported
&
DMUS_OBJ_OBJECT
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
guidObject
,
sizeof
(
desc
->
guidObject
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_OBJECT
;
break
;
case
DMUS_FOURCC_CATEGORY_CHUNK
:
if
((
supported
&
DMUS_OBJ_CATEGORY
)
&&
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszCategory
,
sizeof
(
desc
->
wszCategory
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_CATEGORY
;
break
;
case
DMUS_FOURCC_VERSION_CHUNK
:
if
((
supported
&
DMUS_OBJ_VERSION
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
vVersion
,
sizeof
(
desc
->
vVersion
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_VERSION
;
break
;
case
FOURCC_LIST
:
if
(
chunk
.
type
==
DMUS_FOURCC_UNFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME
))
unfo_get_name
(
stream
,
&
chunk
,
desc
,
supported
&
DMUS_OBJ_NAME_INAM
);
else
if
(
chunk
.
type
==
DMUS_FOURCC_INFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME_INFO
))
info_get_name
(
stream
,
&
chunk
,
desc
);
break
;
}
}
TRACE
(
"Found %#x
\n
"
,
desc
->
dwValidData
);
return
hr
;
}
/* Generic IPersistStream methods */
static
inline
struct
dmobject
*
impl_from_IPersistStream
(
IPersistStream
*
iface
)
{
...
...
dlls/dmband/dmobject.h
View file @
70281427
...
...
@@ -19,6 +19,51 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/debug.h"
/* RIFF stream parsing */
struct
chunk_entry
;
struct
chunk_entry
{
FOURCC
id
;
DWORD
size
;
FOURCC
type
;
/* valid only for LIST and RIFF chunks */
ULARGE_INTEGER
offset
;
/* chunk offset from start of stream */
const
struct
chunk_entry
*
parent
;
/* enclosing RIFF or LIST chunk */
};
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
DECLSPEC_HIDDEN
;
static
inline
HRESULT
stream_reset_chunk_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
+
sizeof
(
FOURCC
)
+
sizeof
(
DWORD
);
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
offset
.
QuadPart
+=
sizeof
(
FOURCC
);
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
static
inline
HRESULT
stream_reset_chunk_start
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
;
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
/* IDirectMusicObject base object */
struct
dmobject
{
IDirectMusicObject
IDirectMusicObject_iface
;
IPersistStream
IPersistStream_iface
;
...
...
@@ -38,6 +83,14 @@ HRESULT WINAPI dmobj_IDirectMusicObject_GetDescriptor(IDirectMusicObject *iface,
HRESULT
WINAPI
dmobj_IDirectMusicObject_SetDescriptor
(
IDirectMusicObject
*
iface
,
DMUS_OBJECTDESC
*
desc
)
DECLSPEC_HIDDEN
;
/* Helper for IDirectMusicObject::ParseDescriptor */
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
DECLSPEC_HIDDEN
;
/* Additional supported flags for dmobj_parsedescriptor.
DMUS_OBJ_NAME is 'UNAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INAM 0x1000
/* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000
/* 'INAM' chunk in INFO list */
/* Generic IPersistStream methods */
HRESULT
WINAPI
dmobj_IPersistStream_QueryInterface
(
IPersistStream
*
iface
,
REFIID
riid
,
void
**
ret_iface
)
DECLSPEC_HIDDEN
;
...
...
dlls/dmcompos/dmobject.c
View file @
70281427
...
...
@@ -21,12 +21,152 @@
*/
#define COBJMACROS
#include <assert.h>
#include "objbase.h"
#include "dmusici.h"
#include "dmusicf.h"
#include "dmobject.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dmobj
);
WINE_DECLARE_DEBUG_CHANNEL
(
dmfile
);
/* RIFF format parsing */
#define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
static
inline
const
char
*
debugstr_fourcc
(
DWORD
fourcc
)
{
if
(
!
fourcc
)
return
"''"
;
return
wine_dbg_sprintf
(
"'%c%c%c%c'"
,
(
char
)(
fourcc
),
(
char
)(
fourcc
>>
8
),
(
char
)(
fourcc
>>
16
),
(
char
)(
fourcc
>>
24
));
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
{
const
char
*
type
=
""
;
if
(
!
chunk
)
return
"(null)"
;
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
type
=
wine_dbg_sprintf
(
"type %s, "
,
debugstr_fourcc
(
chunk
->
type
));
return
wine_dbg_sprintf
(
"%s chunk, %ssize %u"
,
debugstr_fourcc
(
chunk
->
id
),
type
,
chunk
->
size
);
}
static
HRESULT
stream_read
(
IStream
*
stream
,
void
*
data
,
ULONG
size
)
{
ULONG
read
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
data
,
size
,
&
read
);
if
(
FAILED
(
hr
))
TRACE_
(
dmfile
)(
"IStream_Read failed: %08x
\n
"
,
hr
);
else
if
(
!
read
&&
read
<
size
)
{
/* All or nothing: Handle a partial read due to end of stream as an error */
TRACE_
(
dmfile
)(
"Short read: %u < %u
\n
"
,
read
,
size
);
return
E_FAIL
;
}
return
hr
;
}
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
static
const
LARGE_INTEGER
zero
;
ULONGLONG
ck_end
=
0
,
p_end
=
0
;
HRESULT
hr
;
hr
=
IStream_Seek
(
stream
,
zero
,
STREAM_SEEK_CUR
,
&
chunk
->
offset
);
if
(
FAILED
(
hr
))
return
hr
;
assert
(
!
(
chunk
->
offset
.
QuadPart
&
1
));
if
(
chunk
->
parent
)
{
p_end
=
chunk
->
parent
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
((
chunk
->
parent
->
size
+
1
)
&
~
1
);
if
(
chunk
->
offset
.
QuadPart
==
p_end
)
return
S_FALSE
;
ck_end
=
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk header in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
hr
=
stream_read
(
stream
,
chunk
,
CHUNK_HDR_SIZE
);
if
(
hr
!=
S_OK
)
return
hr
;
if
(
chunk
->
parent
)
{
ck_end
+=
(
chunk
->
size
+
1
)
&
~
1
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk data in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
if
(
chunk
->
id
==
FOURCC_LIST
||
chunk
->
id
==
FOURCC_RIFF
)
{
hr
=
stream_read
(
stream
,
&
chunk
->
type
,
sizeof
(
FOURCC
));
if
(
hr
!=
S_OK
)
return
hr
!=
S_FALSE
?
hr
:
E_FAIL
;
}
TRACE_
(
dmfile
)(
"Returning %s
\n
"
,
debugstr_chunk
(
chunk
));
return
S_OK
;
}
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
end
;
end
.
QuadPart
=
(
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
chunk
->
size
+
1
)
&
~
(
ULONGLONG
)
1
;
return
IStream_Seek
(
stream
,
end
,
STREAM_SEEK_SET
,
NULL
);
}
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
HRESULT
hr
;
if
(
chunk
->
id
)
{
hr
=
stream_skip_chunk
(
stream
,
chunk
);
if
(
FAILED
(
hr
))
return
hr
;
}
return
stream_get_chunk
(
stream
,
chunk
);
}
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
{
if
(
chunk
->
size
!=
size
)
{
WARN_
(
dmfile
)(
"Chunk %s (size %u, offset %s) doesn't contains the expected data size %u
\n
"
,
debugstr_fourcc
(
chunk
->
id
),
chunk
->
size
,
wine_dbgstr_longlong
(
chunk
->
offset
.
QuadPart
),
size
);
return
E_FAIL
;
}
return
stream_read
(
stream
,
data
,
size
);
}
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
{
ULONG
len
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
str
,
min
(
chunk
->
size
,
size
),
&
len
);
if
(
FAILED
(
hr
))
return
hr
;
/* Don't assume the string is properly zero terminated */
str
[
min
(
len
,
size
-
1
)]
=
0
;
if
(
len
<
chunk
->
size
)
return
S_FALSE
;
return
S_OK
;
}
/* Generic IDirectMusicObject methods */
static
inline
struct
dmobject
*
impl_from_IDirectMusicObject
(
IDirectMusicObject
*
iface
)
...
...
@@ -110,6 +250,78 @@ HRESULT WINAPI dmobj_IDirectMusicObject_SetDescriptor(IDirectMusicObject *iface,
return
ret
;
}
/* Helper for IDirectMusicObject::ParseDescriptor */
static
inline
void
info_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
info
,
DMUS_OBJECTDESC
*
desc
)
{
struct
chunk_entry
chunk
=
{.
parent
=
info
};
char
name
[
DMUS_MAX_NAME
];
ULONG
len
;
HRESULT
hr
=
E_FAIL
;
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
))
hr
=
IStream_Read
(
stream
,
name
,
min
(
chunk
.
size
,
sizeof
(
name
)),
&
len
);
if
(
SUCCEEDED
(
hr
))
{
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
name
,
len
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
));
desc
->
wszName
[
min
(
len
,
sizeof
(
desc
->
wszName
)
-
1
)]
=
0
;
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
}
static
inline
void
unfo_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
unfo
,
DMUS_OBJECTDESC
*
desc
,
BOOL
inam
)
{
struct
chunk_entry
chunk
=
{.
parent
=
unfo
};
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
DMUS_FOURCC_UNAM_CHUNK
||
(
inam
&&
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
)))
if
(
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
{
struct
chunk_entry
chunk
=
{.
parent
=
riff
};
HRESULT
hr
;
TRACE
(
"Looking for %#x in %p: %s
\n
"
,
supported
,
stream
,
debugstr_chunk
(
riff
));
desc
->
dwValidData
=
0
;
desc
->
dwSize
=
sizeof
(
*
desc
);
while
((
hr
=
stream_next_chunk
(
stream
,
&
chunk
))
==
S_OK
)
{
switch
(
chunk
.
id
)
{
case
DMUS_FOURCC_GUID_CHUNK
:
if
((
supported
&
DMUS_OBJ_OBJECT
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
guidObject
,
sizeof
(
desc
->
guidObject
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_OBJECT
;
break
;
case
DMUS_FOURCC_CATEGORY_CHUNK
:
if
((
supported
&
DMUS_OBJ_CATEGORY
)
&&
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszCategory
,
sizeof
(
desc
->
wszCategory
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_CATEGORY
;
break
;
case
DMUS_FOURCC_VERSION_CHUNK
:
if
((
supported
&
DMUS_OBJ_VERSION
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
vVersion
,
sizeof
(
desc
->
vVersion
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_VERSION
;
break
;
case
FOURCC_LIST
:
if
(
chunk
.
type
==
DMUS_FOURCC_UNFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME
))
unfo_get_name
(
stream
,
&
chunk
,
desc
,
supported
&
DMUS_OBJ_NAME_INAM
);
else
if
(
chunk
.
type
==
DMUS_FOURCC_INFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME_INFO
))
info_get_name
(
stream
,
&
chunk
,
desc
);
break
;
}
}
TRACE
(
"Found %#x
\n
"
,
desc
->
dwValidData
);
return
hr
;
}
/* Generic IPersistStream methods */
static
inline
struct
dmobject
*
impl_from_IPersistStream
(
IPersistStream
*
iface
)
{
...
...
dlls/dmcompos/dmobject.h
View file @
70281427
...
...
@@ -19,6 +19,51 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/debug.h"
/* RIFF stream parsing */
struct
chunk_entry
;
struct
chunk_entry
{
FOURCC
id
;
DWORD
size
;
FOURCC
type
;
/* valid only for LIST and RIFF chunks */
ULARGE_INTEGER
offset
;
/* chunk offset from start of stream */
const
struct
chunk_entry
*
parent
;
/* enclosing RIFF or LIST chunk */
};
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
DECLSPEC_HIDDEN
;
static
inline
HRESULT
stream_reset_chunk_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
+
sizeof
(
FOURCC
)
+
sizeof
(
DWORD
);
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
offset
.
QuadPart
+=
sizeof
(
FOURCC
);
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
static
inline
HRESULT
stream_reset_chunk_start
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
;
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
/* IDirectMusicObject base object */
struct
dmobject
{
IDirectMusicObject
IDirectMusicObject_iface
;
IPersistStream
IPersistStream_iface
;
...
...
@@ -38,6 +83,14 @@ HRESULT WINAPI dmobj_IDirectMusicObject_GetDescriptor(IDirectMusicObject *iface,
HRESULT
WINAPI
dmobj_IDirectMusicObject_SetDescriptor
(
IDirectMusicObject
*
iface
,
DMUS_OBJECTDESC
*
desc
)
DECLSPEC_HIDDEN
;
/* Helper for IDirectMusicObject::ParseDescriptor */
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
DECLSPEC_HIDDEN
;
/* Additional supported flags for dmobj_parsedescriptor.
DMUS_OBJ_NAME is 'UNAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INAM 0x1000
/* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000
/* 'INAM' chunk in INFO list */
/* Generic IPersistStream methods */
HRESULT
WINAPI
dmobj_IPersistStream_QueryInterface
(
IPersistStream
*
iface
,
REFIID
riid
,
void
**
ret_iface
)
DECLSPEC_HIDDEN
;
...
...
dlls/dmloader/dmobject.c
View file @
70281427
...
...
@@ -21,12 +21,152 @@
*/
#define COBJMACROS
#include <assert.h>
#include "objbase.h"
#include "dmusici.h"
#include "dmusicf.h"
#include "dmobject.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dmobj
);
WINE_DECLARE_DEBUG_CHANNEL
(
dmfile
);
/* RIFF format parsing */
#define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
static
inline
const
char
*
debugstr_fourcc
(
DWORD
fourcc
)
{
if
(
!
fourcc
)
return
"''"
;
return
wine_dbg_sprintf
(
"'%c%c%c%c'"
,
(
char
)(
fourcc
),
(
char
)(
fourcc
>>
8
),
(
char
)(
fourcc
>>
16
),
(
char
)(
fourcc
>>
24
));
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
{
const
char
*
type
=
""
;
if
(
!
chunk
)
return
"(null)"
;
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
type
=
wine_dbg_sprintf
(
"type %s, "
,
debugstr_fourcc
(
chunk
->
type
));
return
wine_dbg_sprintf
(
"%s chunk, %ssize %u"
,
debugstr_fourcc
(
chunk
->
id
),
type
,
chunk
->
size
);
}
static
HRESULT
stream_read
(
IStream
*
stream
,
void
*
data
,
ULONG
size
)
{
ULONG
read
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
data
,
size
,
&
read
);
if
(
FAILED
(
hr
))
TRACE_
(
dmfile
)(
"IStream_Read failed: %08x
\n
"
,
hr
);
else
if
(
!
read
&&
read
<
size
)
{
/* All or nothing: Handle a partial read due to end of stream as an error */
TRACE_
(
dmfile
)(
"Short read: %u < %u
\n
"
,
read
,
size
);
return
E_FAIL
;
}
return
hr
;
}
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
static
const
LARGE_INTEGER
zero
;
ULONGLONG
ck_end
=
0
,
p_end
=
0
;
HRESULT
hr
;
hr
=
IStream_Seek
(
stream
,
zero
,
STREAM_SEEK_CUR
,
&
chunk
->
offset
);
if
(
FAILED
(
hr
))
return
hr
;
assert
(
!
(
chunk
->
offset
.
QuadPart
&
1
));
if
(
chunk
->
parent
)
{
p_end
=
chunk
->
parent
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
((
chunk
->
parent
->
size
+
1
)
&
~
1
);
if
(
chunk
->
offset
.
QuadPart
==
p_end
)
return
S_FALSE
;
ck_end
=
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk header in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
hr
=
stream_read
(
stream
,
chunk
,
CHUNK_HDR_SIZE
);
if
(
hr
!=
S_OK
)
return
hr
;
if
(
chunk
->
parent
)
{
ck_end
+=
(
chunk
->
size
+
1
)
&
~
1
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk data in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
if
(
chunk
->
id
==
FOURCC_LIST
||
chunk
->
id
==
FOURCC_RIFF
)
{
hr
=
stream_read
(
stream
,
&
chunk
->
type
,
sizeof
(
FOURCC
));
if
(
hr
!=
S_OK
)
return
hr
!=
S_FALSE
?
hr
:
E_FAIL
;
}
TRACE_
(
dmfile
)(
"Returning %s
\n
"
,
debugstr_chunk
(
chunk
));
return
S_OK
;
}
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
end
;
end
.
QuadPart
=
(
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
chunk
->
size
+
1
)
&
~
(
ULONGLONG
)
1
;
return
IStream_Seek
(
stream
,
end
,
STREAM_SEEK_SET
,
NULL
);
}
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
HRESULT
hr
;
if
(
chunk
->
id
)
{
hr
=
stream_skip_chunk
(
stream
,
chunk
);
if
(
FAILED
(
hr
))
return
hr
;
}
return
stream_get_chunk
(
stream
,
chunk
);
}
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
{
if
(
chunk
->
size
!=
size
)
{
WARN_
(
dmfile
)(
"Chunk %s (size %u, offset %s) doesn't contains the expected data size %u
\n
"
,
debugstr_fourcc
(
chunk
->
id
),
chunk
->
size
,
wine_dbgstr_longlong
(
chunk
->
offset
.
QuadPart
),
size
);
return
E_FAIL
;
}
return
stream_read
(
stream
,
data
,
size
);
}
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
{
ULONG
len
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
str
,
min
(
chunk
->
size
,
size
),
&
len
);
if
(
FAILED
(
hr
))
return
hr
;
/* Don't assume the string is properly zero terminated */
str
[
min
(
len
,
size
-
1
)]
=
0
;
if
(
len
<
chunk
->
size
)
return
S_FALSE
;
return
S_OK
;
}
/* Generic IDirectMusicObject methods */
static
inline
struct
dmobject
*
impl_from_IDirectMusicObject
(
IDirectMusicObject
*
iface
)
...
...
@@ -110,6 +250,78 @@ HRESULT WINAPI dmobj_IDirectMusicObject_SetDescriptor(IDirectMusicObject *iface,
return
ret
;
}
/* Helper for IDirectMusicObject::ParseDescriptor */
static
inline
void
info_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
info
,
DMUS_OBJECTDESC
*
desc
)
{
struct
chunk_entry
chunk
=
{.
parent
=
info
};
char
name
[
DMUS_MAX_NAME
];
ULONG
len
;
HRESULT
hr
=
E_FAIL
;
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
))
hr
=
IStream_Read
(
stream
,
name
,
min
(
chunk
.
size
,
sizeof
(
name
)),
&
len
);
if
(
SUCCEEDED
(
hr
))
{
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
name
,
len
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
));
desc
->
wszName
[
min
(
len
,
sizeof
(
desc
->
wszName
)
-
1
)]
=
0
;
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
}
static
inline
void
unfo_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
unfo
,
DMUS_OBJECTDESC
*
desc
,
BOOL
inam
)
{
struct
chunk_entry
chunk
=
{.
parent
=
unfo
};
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
DMUS_FOURCC_UNAM_CHUNK
||
(
inam
&&
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
)))
if
(
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
{
struct
chunk_entry
chunk
=
{.
parent
=
riff
};
HRESULT
hr
;
TRACE
(
"Looking for %#x in %p: %s
\n
"
,
supported
,
stream
,
debugstr_chunk
(
riff
));
desc
->
dwValidData
=
0
;
desc
->
dwSize
=
sizeof
(
*
desc
);
while
((
hr
=
stream_next_chunk
(
stream
,
&
chunk
))
==
S_OK
)
{
switch
(
chunk
.
id
)
{
case
DMUS_FOURCC_GUID_CHUNK
:
if
((
supported
&
DMUS_OBJ_OBJECT
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
guidObject
,
sizeof
(
desc
->
guidObject
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_OBJECT
;
break
;
case
DMUS_FOURCC_CATEGORY_CHUNK
:
if
((
supported
&
DMUS_OBJ_CATEGORY
)
&&
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszCategory
,
sizeof
(
desc
->
wszCategory
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_CATEGORY
;
break
;
case
DMUS_FOURCC_VERSION_CHUNK
:
if
((
supported
&
DMUS_OBJ_VERSION
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
vVersion
,
sizeof
(
desc
->
vVersion
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_VERSION
;
break
;
case
FOURCC_LIST
:
if
(
chunk
.
type
==
DMUS_FOURCC_UNFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME
))
unfo_get_name
(
stream
,
&
chunk
,
desc
,
supported
&
DMUS_OBJ_NAME_INAM
);
else
if
(
chunk
.
type
==
DMUS_FOURCC_INFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME_INFO
))
info_get_name
(
stream
,
&
chunk
,
desc
);
break
;
}
}
TRACE
(
"Found %#x
\n
"
,
desc
->
dwValidData
);
return
hr
;
}
/* Generic IPersistStream methods */
static
inline
struct
dmobject
*
impl_from_IPersistStream
(
IPersistStream
*
iface
)
{
...
...
dlls/dmloader/dmobject.h
View file @
70281427
...
...
@@ -19,6 +19,51 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/debug.h"
/* RIFF stream parsing */
struct
chunk_entry
;
struct
chunk_entry
{
FOURCC
id
;
DWORD
size
;
FOURCC
type
;
/* valid only for LIST and RIFF chunks */
ULARGE_INTEGER
offset
;
/* chunk offset from start of stream */
const
struct
chunk_entry
*
parent
;
/* enclosing RIFF or LIST chunk */
};
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
DECLSPEC_HIDDEN
;
static
inline
HRESULT
stream_reset_chunk_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
+
sizeof
(
FOURCC
)
+
sizeof
(
DWORD
);
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
offset
.
QuadPart
+=
sizeof
(
FOURCC
);
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
static
inline
HRESULT
stream_reset_chunk_start
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
;
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
/* IDirectMusicObject base object */
struct
dmobject
{
IDirectMusicObject
IDirectMusicObject_iface
;
IPersistStream
IPersistStream_iface
;
...
...
@@ -38,6 +83,14 @@ HRESULT WINAPI dmobj_IDirectMusicObject_GetDescriptor(IDirectMusicObject *iface,
HRESULT
WINAPI
dmobj_IDirectMusicObject_SetDescriptor
(
IDirectMusicObject
*
iface
,
DMUS_OBJECTDESC
*
desc
)
DECLSPEC_HIDDEN
;
/* Helper for IDirectMusicObject::ParseDescriptor */
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
DECLSPEC_HIDDEN
;
/* Additional supported flags for dmobj_parsedescriptor.
DMUS_OBJ_NAME is 'UNAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INAM 0x1000
/* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000
/* 'INAM' chunk in INFO list */
/* Generic IPersistStream methods */
HRESULT
WINAPI
dmobj_IPersistStream_QueryInterface
(
IPersistStream
*
iface
,
REFIID
riid
,
void
**
ret_iface
)
DECLSPEC_HIDDEN
;
...
...
dlls/dmscript/dmobject.c
View file @
70281427
...
...
@@ -21,12 +21,152 @@
*/
#define COBJMACROS
#include <assert.h>
#include "objbase.h"
#include "dmusici.h"
#include "dmusicf.h"
#include "dmobject.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dmobj
);
WINE_DECLARE_DEBUG_CHANNEL
(
dmfile
);
/* RIFF format parsing */
#define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
static
inline
const
char
*
debugstr_fourcc
(
DWORD
fourcc
)
{
if
(
!
fourcc
)
return
"''"
;
return
wine_dbg_sprintf
(
"'%c%c%c%c'"
,
(
char
)(
fourcc
),
(
char
)(
fourcc
>>
8
),
(
char
)(
fourcc
>>
16
),
(
char
)(
fourcc
>>
24
));
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
{
const
char
*
type
=
""
;
if
(
!
chunk
)
return
"(null)"
;
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
type
=
wine_dbg_sprintf
(
"type %s, "
,
debugstr_fourcc
(
chunk
->
type
));
return
wine_dbg_sprintf
(
"%s chunk, %ssize %u"
,
debugstr_fourcc
(
chunk
->
id
),
type
,
chunk
->
size
);
}
static
HRESULT
stream_read
(
IStream
*
stream
,
void
*
data
,
ULONG
size
)
{
ULONG
read
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
data
,
size
,
&
read
);
if
(
FAILED
(
hr
))
TRACE_
(
dmfile
)(
"IStream_Read failed: %08x
\n
"
,
hr
);
else
if
(
!
read
&&
read
<
size
)
{
/* All or nothing: Handle a partial read due to end of stream as an error */
TRACE_
(
dmfile
)(
"Short read: %u < %u
\n
"
,
read
,
size
);
return
E_FAIL
;
}
return
hr
;
}
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
static
const
LARGE_INTEGER
zero
;
ULONGLONG
ck_end
=
0
,
p_end
=
0
;
HRESULT
hr
;
hr
=
IStream_Seek
(
stream
,
zero
,
STREAM_SEEK_CUR
,
&
chunk
->
offset
);
if
(
FAILED
(
hr
))
return
hr
;
assert
(
!
(
chunk
->
offset
.
QuadPart
&
1
));
if
(
chunk
->
parent
)
{
p_end
=
chunk
->
parent
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
((
chunk
->
parent
->
size
+
1
)
&
~
1
);
if
(
chunk
->
offset
.
QuadPart
==
p_end
)
return
S_FALSE
;
ck_end
=
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk header in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
hr
=
stream_read
(
stream
,
chunk
,
CHUNK_HDR_SIZE
);
if
(
hr
!=
S_OK
)
return
hr
;
if
(
chunk
->
parent
)
{
ck_end
+=
(
chunk
->
size
+
1
)
&
~
1
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk data in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
if
(
chunk
->
id
==
FOURCC_LIST
||
chunk
->
id
==
FOURCC_RIFF
)
{
hr
=
stream_read
(
stream
,
&
chunk
->
type
,
sizeof
(
FOURCC
));
if
(
hr
!=
S_OK
)
return
hr
!=
S_FALSE
?
hr
:
E_FAIL
;
}
TRACE_
(
dmfile
)(
"Returning %s
\n
"
,
debugstr_chunk
(
chunk
));
return
S_OK
;
}
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
end
;
end
.
QuadPart
=
(
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
chunk
->
size
+
1
)
&
~
(
ULONGLONG
)
1
;
return
IStream_Seek
(
stream
,
end
,
STREAM_SEEK_SET
,
NULL
);
}
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
HRESULT
hr
;
if
(
chunk
->
id
)
{
hr
=
stream_skip_chunk
(
stream
,
chunk
);
if
(
FAILED
(
hr
))
return
hr
;
}
return
stream_get_chunk
(
stream
,
chunk
);
}
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
{
if
(
chunk
->
size
!=
size
)
{
WARN_
(
dmfile
)(
"Chunk %s (size %u, offset %s) doesn't contains the expected data size %u
\n
"
,
debugstr_fourcc
(
chunk
->
id
),
chunk
->
size
,
wine_dbgstr_longlong
(
chunk
->
offset
.
QuadPart
),
size
);
return
E_FAIL
;
}
return
stream_read
(
stream
,
data
,
size
);
}
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
{
ULONG
len
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
str
,
min
(
chunk
->
size
,
size
),
&
len
);
if
(
FAILED
(
hr
))
return
hr
;
/* Don't assume the string is properly zero terminated */
str
[
min
(
len
,
size
-
1
)]
=
0
;
if
(
len
<
chunk
->
size
)
return
S_FALSE
;
return
S_OK
;
}
/* Generic IDirectMusicObject methods */
static
inline
struct
dmobject
*
impl_from_IDirectMusicObject
(
IDirectMusicObject
*
iface
)
...
...
@@ -110,6 +250,78 @@ HRESULT WINAPI dmobj_IDirectMusicObject_SetDescriptor(IDirectMusicObject *iface,
return
ret
;
}
/* Helper for IDirectMusicObject::ParseDescriptor */
static
inline
void
info_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
info
,
DMUS_OBJECTDESC
*
desc
)
{
struct
chunk_entry
chunk
=
{.
parent
=
info
};
char
name
[
DMUS_MAX_NAME
];
ULONG
len
;
HRESULT
hr
=
E_FAIL
;
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
))
hr
=
IStream_Read
(
stream
,
name
,
min
(
chunk
.
size
,
sizeof
(
name
)),
&
len
);
if
(
SUCCEEDED
(
hr
))
{
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
name
,
len
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
));
desc
->
wszName
[
min
(
len
,
sizeof
(
desc
->
wszName
)
-
1
)]
=
0
;
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
}
static
inline
void
unfo_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
unfo
,
DMUS_OBJECTDESC
*
desc
,
BOOL
inam
)
{
struct
chunk_entry
chunk
=
{.
parent
=
unfo
};
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
DMUS_FOURCC_UNAM_CHUNK
||
(
inam
&&
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
)))
if
(
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
{
struct
chunk_entry
chunk
=
{.
parent
=
riff
};
HRESULT
hr
;
TRACE
(
"Looking for %#x in %p: %s
\n
"
,
supported
,
stream
,
debugstr_chunk
(
riff
));
desc
->
dwValidData
=
0
;
desc
->
dwSize
=
sizeof
(
*
desc
);
while
((
hr
=
stream_next_chunk
(
stream
,
&
chunk
))
==
S_OK
)
{
switch
(
chunk
.
id
)
{
case
DMUS_FOURCC_GUID_CHUNK
:
if
((
supported
&
DMUS_OBJ_OBJECT
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
guidObject
,
sizeof
(
desc
->
guidObject
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_OBJECT
;
break
;
case
DMUS_FOURCC_CATEGORY_CHUNK
:
if
((
supported
&
DMUS_OBJ_CATEGORY
)
&&
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszCategory
,
sizeof
(
desc
->
wszCategory
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_CATEGORY
;
break
;
case
DMUS_FOURCC_VERSION_CHUNK
:
if
((
supported
&
DMUS_OBJ_VERSION
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
vVersion
,
sizeof
(
desc
->
vVersion
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_VERSION
;
break
;
case
FOURCC_LIST
:
if
(
chunk
.
type
==
DMUS_FOURCC_UNFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME
))
unfo_get_name
(
stream
,
&
chunk
,
desc
,
supported
&
DMUS_OBJ_NAME_INAM
);
else
if
(
chunk
.
type
==
DMUS_FOURCC_INFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME_INFO
))
info_get_name
(
stream
,
&
chunk
,
desc
);
break
;
}
}
TRACE
(
"Found %#x
\n
"
,
desc
->
dwValidData
);
return
hr
;
}
/* Generic IPersistStream methods */
static
inline
struct
dmobject
*
impl_from_IPersistStream
(
IPersistStream
*
iface
)
{
...
...
dlls/dmscript/dmobject.h
View file @
70281427
...
...
@@ -19,6 +19,51 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/debug.h"
/* RIFF stream parsing */
struct
chunk_entry
;
struct
chunk_entry
{
FOURCC
id
;
DWORD
size
;
FOURCC
type
;
/* valid only for LIST and RIFF chunks */
ULARGE_INTEGER
offset
;
/* chunk offset from start of stream */
const
struct
chunk_entry
*
parent
;
/* enclosing RIFF or LIST chunk */
};
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
DECLSPEC_HIDDEN
;
static
inline
HRESULT
stream_reset_chunk_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
+
sizeof
(
FOURCC
)
+
sizeof
(
DWORD
);
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
offset
.
QuadPart
+=
sizeof
(
FOURCC
);
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
static
inline
HRESULT
stream_reset_chunk_start
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
;
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
/* IDirectMusicObject base object */
struct
dmobject
{
IDirectMusicObject
IDirectMusicObject_iface
;
IPersistStream
IPersistStream_iface
;
...
...
@@ -38,6 +83,14 @@ HRESULT WINAPI dmobj_IDirectMusicObject_GetDescriptor(IDirectMusicObject *iface,
HRESULT
WINAPI
dmobj_IDirectMusicObject_SetDescriptor
(
IDirectMusicObject
*
iface
,
DMUS_OBJECTDESC
*
desc
)
DECLSPEC_HIDDEN
;
/* Helper for IDirectMusicObject::ParseDescriptor */
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
DECLSPEC_HIDDEN
;
/* Additional supported flags for dmobj_parsedescriptor.
DMUS_OBJ_NAME is 'UNAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INAM 0x1000
/* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000
/* 'INAM' chunk in INFO list */
/* Generic IPersistStream methods */
HRESULT
WINAPI
dmobj_IPersistStream_QueryInterface
(
IPersistStream
*
iface
,
REFIID
riid
,
void
**
ret_iface
)
DECLSPEC_HIDDEN
;
...
...
dlls/dmstyle/dmobject.c
View file @
70281427
...
...
@@ -21,12 +21,152 @@
*/
#define COBJMACROS
#include <assert.h>
#include "objbase.h"
#include "dmusici.h"
#include "dmusicf.h"
#include "dmobject.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dmobj
);
WINE_DECLARE_DEBUG_CHANNEL
(
dmfile
);
/* RIFF format parsing */
#define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
static
inline
const
char
*
debugstr_fourcc
(
DWORD
fourcc
)
{
if
(
!
fourcc
)
return
"''"
;
return
wine_dbg_sprintf
(
"'%c%c%c%c'"
,
(
char
)(
fourcc
),
(
char
)(
fourcc
>>
8
),
(
char
)(
fourcc
>>
16
),
(
char
)(
fourcc
>>
24
));
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
{
const
char
*
type
=
""
;
if
(
!
chunk
)
return
"(null)"
;
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
type
=
wine_dbg_sprintf
(
"type %s, "
,
debugstr_fourcc
(
chunk
->
type
));
return
wine_dbg_sprintf
(
"%s chunk, %ssize %u"
,
debugstr_fourcc
(
chunk
->
id
),
type
,
chunk
->
size
);
}
static
HRESULT
stream_read
(
IStream
*
stream
,
void
*
data
,
ULONG
size
)
{
ULONG
read
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
data
,
size
,
&
read
);
if
(
FAILED
(
hr
))
TRACE_
(
dmfile
)(
"IStream_Read failed: %08x
\n
"
,
hr
);
else
if
(
!
read
&&
read
<
size
)
{
/* All or nothing: Handle a partial read due to end of stream as an error */
TRACE_
(
dmfile
)(
"Short read: %u < %u
\n
"
,
read
,
size
);
return
E_FAIL
;
}
return
hr
;
}
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
static
const
LARGE_INTEGER
zero
;
ULONGLONG
ck_end
=
0
,
p_end
=
0
;
HRESULT
hr
;
hr
=
IStream_Seek
(
stream
,
zero
,
STREAM_SEEK_CUR
,
&
chunk
->
offset
);
if
(
FAILED
(
hr
))
return
hr
;
assert
(
!
(
chunk
->
offset
.
QuadPart
&
1
));
if
(
chunk
->
parent
)
{
p_end
=
chunk
->
parent
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
((
chunk
->
parent
->
size
+
1
)
&
~
1
);
if
(
chunk
->
offset
.
QuadPart
==
p_end
)
return
S_FALSE
;
ck_end
=
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk header in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
hr
=
stream_read
(
stream
,
chunk
,
CHUNK_HDR_SIZE
);
if
(
hr
!=
S_OK
)
return
hr
;
if
(
chunk
->
parent
)
{
ck_end
+=
(
chunk
->
size
+
1
)
&
~
1
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk data in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
if
(
chunk
->
id
==
FOURCC_LIST
||
chunk
->
id
==
FOURCC_RIFF
)
{
hr
=
stream_read
(
stream
,
&
chunk
->
type
,
sizeof
(
FOURCC
));
if
(
hr
!=
S_OK
)
return
hr
!=
S_FALSE
?
hr
:
E_FAIL
;
}
TRACE_
(
dmfile
)(
"Returning %s
\n
"
,
debugstr_chunk
(
chunk
));
return
S_OK
;
}
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
end
;
end
.
QuadPart
=
(
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
chunk
->
size
+
1
)
&
~
(
ULONGLONG
)
1
;
return
IStream_Seek
(
stream
,
end
,
STREAM_SEEK_SET
,
NULL
);
}
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
HRESULT
hr
;
if
(
chunk
->
id
)
{
hr
=
stream_skip_chunk
(
stream
,
chunk
);
if
(
FAILED
(
hr
))
return
hr
;
}
return
stream_get_chunk
(
stream
,
chunk
);
}
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
{
if
(
chunk
->
size
!=
size
)
{
WARN_
(
dmfile
)(
"Chunk %s (size %u, offset %s) doesn't contains the expected data size %u
\n
"
,
debugstr_fourcc
(
chunk
->
id
),
chunk
->
size
,
wine_dbgstr_longlong
(
chunk
->
offset
.
QuadPart
),
size
);
return
E_FAIL
;
}
return
stream_read
(
stream
,
data
,
size
);
}
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
{
ULONG
len
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
str
,
min
(
chunk
->
size
,
size
),
&
len
);
if
(
FAILED
(
hr
))
return
hr
;
/* Don't assume the string is properly zero terminated */
str
[
min
(
len
,
size
-
1
)]
=
0
;
if
(
len
<
chunk
->
size
)
return
S_FALSE
;
return
S_OK
;
}
/* Generic IDirectMusicObject methods */
static
inline
struct
dmobject
*
impl_from_IDirectMusicObject
(
IDirectMusicObject
*
iface
)
...
...
@@ -110,6 +250,78 @@ HRESULT WINAPI dmobj_IDirectMusicObject_SetDescriptor(IDirectMusicObject *iface,
return
ret
;
}
/* Helper for IDirectMusicObject::ParseDescriptor */
static
inline
void
info_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
info
,
DMUS_OBJECTDESC
*
desc
)
{
struct
chunk_entry
chunk
=
{.
parent
=
info
};
char
name
[
DMUS_MAX_NAME
];
ULONG
len
;
HRESULT
hr
=
E_FAIL
;
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
))
hr
=
IStream_Read
(
stream
,
name
,
min
(
chunk
.
size
,
sizeof
(
name
)),
&
len
);
if
(
SUCCEEDED
(
hr
))
{
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
name
,
len
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
));
desc
->
wszName
[
min
(
len
,
sizeof
(
desc
->
wszName
)
-
1
)]
=
0
;
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
}
static
inline
void
unfo_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
unfo
,
DMUS_OBJECTDESC
*
desc
,
BOOL
inam
)
{
struct
chunk_entry
chunk
=
{.
parent
=
unfo
};
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
DMUS_FOURCC_UNAM_CHUNK
||
(
inam
&&
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
)))
if
(
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
{
struct
chunk_entry
chunk
=
{.
parent
=
riff
};
HRESULT
hr
;
TRACE
(
"Looking for %#x in %p: %s
\n
"
,
supported
,
stream
,
debugstr_chunk
(
riff
));
desc
->
dwValidData
=
0
;
desc
->
dwSize
=
sizeof
(
*
desc
);
while
((
hr
=
stream_next_chunk
(
stream
,
&
chunk
))
==
S_OK
)
{
switch
(
chunk
.
id
)
{
case
DMUS_FOURCC_GUID_CHUNK
:
if
((
supported
&
DMUS_OBJ_OBJECT
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
guidObject
,
sizeof
(
desc
->
guidObject
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_OBJECT
;
break
;
case
DMUS_FOURCC_CATEGORY_CHUNK
:
if
((
supported
&
DMUS_OBJ_CATEGORY
)
&&
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszCategory
,
sizeof
(
desc
->
wszCategory
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_CATEGORY
;
break
;
case
DMUS_FOURCC_VERSION_CHUNK
:
if
((
supported
&
DMUS_OBJ_VERSION
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
vVersion
,
sizeof
(
desc
->
vVersion
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_VERSION
;
break
;
case
FOURCC_LIST
:
if
(
chunk
.
type
==
DMUS_FOURCC_UNFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME
))
unfo_get_name
(
stream
,
&
chunk
,
desc
,
supported
&
DMUS_OBJ_NAME_INAM
);
else
if
(
chunk
.
type
==
DMUS_FOURCC_INFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME_INFO
))
info_get_name
(
stream
,
&
chunk
,
desc
);
break
;
}
}
TRACE
(
"Found %#x
\n
"
,
desc
->
dwValidData
);
return
hr
;
}
/* Generic IPersistStream methods */
static
inline
struct
dmobject
*
impl_from_IPersistStream
(
IPersistStream
*
iface
)
{
...
...
dlls/dmstyle/dmobject.h
View file @
70281427
...
...
@@ -19,6 +19,51 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/debug.h"
/* RIFF stream parsing */
struct
chunk_entry
;
struct
chunk_entry
{
FOURCC
id
;
DWORD
size
;
FOURCC
type
;
/* valid only for LIST and RIFF chunks */
ULARGE_INTEGER
offset
;
/* chunk offset from start of stream */
const
struct
chunk_entry
*
parent
;
/* enclosing RIFF or LIST chunk */
};
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
DECLSPEC_HIDDEN
;
static
inline
HRESULT
stream_reset_chunk_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
+
sizeof
(
FOURCC
)
+
sizeof
(
DWORD
);
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
offset
.
QuadPart
+=
sizeof
(
FOURCC
);
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
static
inline
HRESULT
stream_reset_chunk_start
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
;
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
/* IDirectMusicObject base object */
struct
dmobject
{
IDirectMusicObject
IDirectMusicObject_iface
;
IPersistStream
IPersistStream_iface
;
...
...
@@ -38,6 +83,14 @@ HRESULT WINAPI dmobj_IDirectMusicObject_GetDescriptor(IDirectMusicObject *iface,
HRESULT
WINAPI
dmobj_IDirectMusicObject_SetDescriptor
(
IDirectMusicObject
*
iface
,
DMUS_OBJECTDESC
*
desc
)
DECLSPEC_HIDDEN
;
/* Helper for IDirectMusicObject::ParseDescriptor */
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
DECLSPEC_HIDDEN
;
/* Additional supported flags for dmobj_parsedescriptor.
DMUS_OBJ_NAME is 'UNAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INAM 0x1000
/* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000
/* 'INAM' chunk in INFO list */
/* Generic IPersistStream methods */
HRESULT
WINAPI
dmobj_IPersistStream_QueryInterface
(
IPersistStream
*
iface
,
REFIID
riid
,
void
**
ret_iface
)
DECLSPEC_HIDDEN
;
...
...
dlls/dmusic/dmobject.c
View file @
70281427
...
...
@@ -21,12 +21,152 @@
*/
#define COBJMACROS
#include <assert.h>
#include "objbase.h"
#include "dmusici.h"
#include "dmusicf.h"
#include "dmobject.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dmobj
);
WINE_DECLARE_DEBUG_CHANNEL
(
dmfile
);
/* RIFF format parsing */
#define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
static
inline
const
char
*
debugstr_fourcc
(
DWORD
fourcc
)
{
if
(
!
fourcc
)
return
"''"
;
return
wine_dbg_sprintf
(
"'%c%c%c%c'"
,
(
char
)(
fourcc
),
(
char
)(
fourcc
>>
8
),
(
char
)(
fourcc
>>
16
),
(
char
)(
fourcc
>>
24
));
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
{
const
char
*
type
=
""
;
if
(
!
chunk
)
return
"(null)"
;
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
type
=
wine_dbg_sprintf
(
"type %s, "
,
debugstr_fourcc
(
chunk
->
type
));
return
wine_dbg_sprintf
(
"%s chunk, %ssize %u"
,
debugstr_fourcc
(
chunk
->
id
),
type
,
chunk
->
size
);
}
static
HRESULT
stream_read
(
IStream
*
stream
,
void
*
data
,
ULONG
size
)
{
ULONG
read
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
data
,
size
,
&
read
);
if
(
FAILED
(
hr
))
TRACE_
(
dmfile
)(
"IStream_Read failed: %08x
\n
"
,
hr
);
else
if
(
!
read
&&
read
<
size
)
{
/* All or nothing: Handle a partial read due to end of stream as an error */
TRACE_
(
dmfile
)(
"Short read: %u < %u
\n
"
,
read
,
size
);
return
E_FAIL
;
}
return
hr
;
}
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
static
const
LARGE_INTEGER
zero
;
ULONGLONG
ck_end
=
0
,
p_end
=
0
;
HRESULT
hr
;
hr
=
IStream_Seek
(
stream
,
zero
,
STREAM_SEEK_CUR
,
&
chunk
->
offset
);
if
(
FAILED
(
hr
))
return
hr
;
assert
(
!
(
chunk
->
offset
.
QuadPart
&
1
));
if
(
chunk
->
parent
)
{
p_end
=
chunk
->
parent
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
((
chunk
->
parent
->
size
+
1
)
&
~
1
);
if
(
chunk
->
offset
.
QuadPart
==
p_end
)
return
S_FALSE
;
ck_end
=
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk header in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
hr
=
stream_read
(
stream
,
chunk
,
CHUNK_HDR_SIZE
);
if
(
hr
!=
S_OK
)
return
hr
;
if
(
chunk
->
parent
)
{
ck_end
+=
(
chunk
->
size
+
1
)
&
~
1
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk data in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
if
(
chunk
->
id
==
FOURCC_LIST
||
chunk
->
id
==
FOURCC_RIFF
)
{
hr
=
stream_read
(
stream
,
&
chunk
->
type
,
sizeof
(
FOURCC
));
if
(
hr
!=
S_OK
)
return
hr
!=
S_FALSE
?
hr
:
E_FAIL
;
}
TRACE_
(
dmfile
)(
"Returning %s
\n
"
,
debugstr_chunk
(
chunk
));
return
S_OK
;
}
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
end
;
end
.
QuadPart
=
(
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
chunk
->
size
+
1
)
&
~
(
ULONGLONG
)
1
;
return
IStream_Seek
(
stream
,
end
,
STREAM_SEEK_SET
,
NULL
);
}
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
HRESULT
hr
;
if
(
chunk
->
id
)
{
hr
=
stream_skip_chunk
(
stream
,
chunk
);
if
(
FAILED
(
hr
))
return
hr
;
}
return
stream_get_chunk
(
stream
,
chunk
);
}
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
{
if
(
chunk
->
size
!=
size
)
{
WARN_
(
dmfile
)(
"Chunk %s (size %u, offset %s) doesn't contains the expected data size %u
\n
"
,
debugstr_fourcc
(
chunk
->
id
),
chunk
->
size
,
wine_dbgstr_longlong
(
chunk
->
offset
.
QuadPart
),
size
);
return
E_FAIL
;
}
return
stream_read
(
stream
,
data
,
size
);
}
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
{
ULONG
len
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
str
,
min
(
chunk
->
size
,
size
),
&
len
);
if
(
FAILED
(
hr
))
return
hr
;
/* Don't assume the string is properly zero terminated */
str
[
min
(
len
,
size
-
1
)]
=
0
;
if
(
len
<
chunk
->
size
)
return
S_FALSE
;
return
S_OK
;
}
/* Generic IDirectMusicObject methods */
static
inline
struct
dmobject
*
impl_from_IDirectMusicObject
(
IDirectMusicObject
*
iface
)
...
...
@@ -110,6 +250,78 @@ HRESULT WINAPI dmobj_IDirectMusicObject_SetDescriptor(IDirectMusicObject *iface,
return
ret
;
}
/* Helper for IDirectMusicObject::ParseDescriptor */
static
inline
void
info_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
info
,
DMUS_OBJECTDESC
*
desc
)
{
struct
chunk_entry
chunk
=
{.
parent
=
info
};
char
name
[
DMUS_MAX_NAME
];
ULONG
len
;
HRESULT
hr
=
E_FAIL
;
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
))
hr
=
IStream_Read
(
stream
,
name
,
min
(
chunk
.
size
,
sizeof
(
name
)),
&
len
);
if
(
SUCCEEDED
(
hr
))
{
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
name
,
len
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
));
desc
->
wszName
[
min
(
len
,
sizeof
(
desc
->
wszName
)
-
1
)]
=
0
;
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
}
static
inline
void
unfo_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
unfo
,
DMUS_OBJECTDESC
*
desc
,
BOOL
inam
)
{
struct
chunk_entry
chunk
=
{.
parent
=
unfo
};
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
DMUS_FOURCC_UNAM_CHUNK
||
(
inam
&&
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
)))
if
(
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
{
struct
chunk_entry
chunk
=
{.
parent
=
riff
};
HRESULT
hr
;
TRACE
(
"Looking for %#x in %p: %s
\n
"
,
supported
,
stream
,
debugstr_chunk
(
riff
));
desc
->
dwValidData
=
0
;
desc
->
dwSize
=
sizeof
(
*
desc
);
while
((
hr
=
stream_next_chunk
(
stream
,
&
chunk
))
==
S_OK
)
{
switch
(
chunk
.
id
)
{
case
DMUS_FOURCC_GUID_CHUNK
:
if
((
supported
&
DMUS_OBJ_OBJECT
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
guidObject
,
sizeof
(
desc
->
guidObject
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_OBJECT
;
break
;
case
DMUS_FOURCC_CATEGORY_CHUNK
:
if
((
supported
&
DMUS_OBJ_CATEGORY
)
&&
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszCategory
,
sizeof
(
desc
->
wszCategory
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_CATEGORY
;
break
;
case
DMUS_FOURCC_VERSION_CHUNK
:
if
((
supported
&
DMUS_OBJ_VERSION
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
vVersion
,
sizeof
(
desc
->
vVersion
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_VERSION
;
break
;
case
FOURCC_LIST
:
if
(
chunk
.
type
==
DMUS_FOURCC_UNFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME
))
unfo_get_name
(
stream
,
&
chunk
,
desc
,
supported
&
DMUS_OBJ_NAME_INAM
);
else
if
(
chunk
.
type
==
DMUS_FOURCC_INFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME_INFO
))
info_get_name
(
stream
,
&
chunk
,
desc
);
break
;
}
}
TRACE
(
"Found %#x
\n
"
,
desc
->
dwValidData
);
return
hr
;
}
/* Generic IPersistStream methods */
static
inline
struct
dmobject
*
impl_from_IPersistStream
(
IPersistStream
*
iface
)
{
...
...
dlls/dmusic/dmobject.h
View file @
70281427
...
...
@@ -19,6 +19,51 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/debug.h"
/* RIFF stream parsing */
struct
chunk_entry
;
struct
chunk_entry
{
FOURCC
id
;
DWORD
size
;
FOURCC
type
;
/* valid only for LIST and RIFF chunks */
ULARGE_INTEGER
offset
;
/* chunk offset from start of stream */
const
struct
chunk_entry
*
parent
;
/* enclosing RIFF or LIST chunk */
};
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
DECLSPEC_HIDDEN
;
static
inline
HRESULT
stream_reset_chunk_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
+
sizeof
(
FOURCC
)
+
sizeof
(
DWORD
);
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
offset
.
QuadPart
+=
sizeof
(
FOURCC
);
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
static
inline
HRESULT
stream_reset_chunk_start
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
;
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
/* IDirectMusicObject base object */
struct
dmobject
{
IDirectMusicObject
IDirectMusicObject_iface
;
IPersistStream
IPersistStream_iface
;
...
...
@@ -38,6 +83,14 @@ HRESULT WINAPI dmobj_IDirectMusicObject_GetDescriptor(IDirectMusicObject *iface,
HRESULT
WINAPI
dmobj_IDirectMusicObject_SetDescriptor
(
IDirectMusicObject
*
iface
,
DMUS_OBJECTDESC
*
desc
)
DECLSPEC_HIDDEN
;
/* Helper for IDirectMusicObject::ParseDescriptor */
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
DECLSPEC_HIDDEN
;
/* Additional supported flags for dmobj_parsedescriptor.
DMUS_OBJ_NAME is 'UNAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INAM 0x1000
/* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000
/* 'INAM' chunk in INFO list */
/* Generic IPersistStream methods */
HRESULT
WINAPI
dmobj_IPersistStream_QueryInterface
(
IPersistStream
*
iface
,
REFIID
riid
,
void
**
ret_iface
)
DECLSPEC_HIDDEN
;
...
...
dlls/dswave/dmobject.c
View file @
70281427
...
...
@@ -21,12 +21,152 @@
*/
#define COBJMACROS
#include <assert.h>
#include "objbase.h"
#include "dmusici.h"
#include "dmusicf.h"
#include "dmobject.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dmobj
);
WINE_DECLARE_DEBUG_CHANNEL
(
dmfile
);
/* RIFF format parsing */
#define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
static
inline
const
char
*
debugstr_fourcc
(
DWORD
fourcc
)
{
if
(
!
fourcc
)
return
"''"
;
return
wine_dbg_sprintf
(
"'%c%c%c%c'"
,
(
char
)(
fourcc
),
(
char
)(
fourcc
>>
8
),
(
char
)(
fourcc
>>
16
),
(
char
)(
fourcc
>>
24
));
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
{
const
char
*
type
=
""
;
if
(
!
chunk
)
return
"(null)"
;
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
type
=
wine_dbg_sprintf
(
"type %s, "
,
debugstr_fourcc
(
chunk
->
type
));
return
wine_dbg_sprintf
(
"%s chunk, %ssize %u"
,
debugstr_fourcc
(
chunk
->
id
),
type
,
chunk
->
size
);
}
static
HRESULT
stream_read
(
IStream
*
stream
,
void
*
data
,
ULONG
size
)
{
ULONG
read
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
data
,
size
,
&
read
);
if
(
FAILED
(
hr
))
TRACE_
(
dmfile
)(
"IStream_Read failed: %08x
\n
"
,
hr
);
else
if
(
!
read
&&
read
<
size
)
{
/* All or nothing: Handle a partial read due to end of stream as an error */
TRACE_
(
dmfile
)(
"Short read: %u < %u
\n
"
,
read
,
size
);
return
E_FAIL
;
}
return
hr
;
}
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
static
const
LARGE_INTEGER
zero
;
ULONGLONG
ck_end
=
0
,
p_end
=
0
;
HRESULT
hr
;
hr
=
IStream_Seek
(
stream
,
zero
,
STREAM_SEEK_CUR
,
&
chunk
->
offset
);
if
(
FAILED
(
hr
))
return
hr
;
assert
(
!
(
chunk
->
offset
.
QuadPart
&
1
));
if
(
chunk
->
parent
)
{
p_end
=
chunk
->
parent
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
((
chunk
->
parent
->
size
+
1
)
&
~
1
);
if
(
chunk
->
offset
.
QuadPart
==
p_end
)
return
S_FALSE
;
ck_end
=
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk header in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
hr
=
stream_read
(
stream
,
chunk
,
CHUNK_HDR_SIZE
);
if
(
hr
!=
S_OK
)
return
hr
;
if
(
chunk
->
parent
)
{
ck_end
+=
(
chunk
->
size
+
1
)
&
~
1
;
if
(
ck_end
>
p_end
)
{
WARN_
(
dmfile
)(
"No space for sub-chunk data in parent chunk: ends at offset %s > %s
\n
"
,
wine_dbgstr_longlong
(
ck_end
),
wine_dbgstr_longlong
(
p_end
));
return
E_FAIL
;
}
}
if
(
chunk
->
id
==
FOURCC_LIST
||
chunk
->
id
==
FOURCC_RIFF
)
{
hr
=
stream_read
(
stream
,
&
chunk
->
type
,
sizeof
(
FOURCC
));
if
(
hr
!=
S_OK
)
return
hr
!=
S_FALSE
?
hr
:
E_FAIL
;
}
TRACE_
(
dmfile
)(
"Returning %s
\n
"
,
debugstr_chunk
(
chunk
));
return
S_OK
;
}
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
end
;
end
.
QuadPart
=
(
chunk
->
offset
.
QuadPart
+
CHUNK_HDR_SIZE
+
chunk
->
size
+
1
)
&
~
(
ULONGLONG
)
1
;
return
IStream_Seek
(
stream
,
end
,
STREAM_SEEK_SET
,
NULL
);
}
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
{
HRESULT
hr
;
if
(
chunk
->
id
)
{
hr
=
stream_skip_chunk
(
stream
,
chunk
);
if
(
FAILED
(
hr
))
return
hr
;
}
return
stream_get_chunk
(
stream
,
chunk
);
}
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
{
if
(
chunk
->
size
!=
size
)
{
WARN_
(
dmfile
)(
"Chunk %s (size %u, offset %s) doesn't contains the expected data size %u
\n
"
,
debugstr_fourcc
(
chunk
->
id
),
chunk
->
size
,
wine_dbgstr_longlong
(
chunk
->
offset
.
QuadPart
),
size
);
return
E_FAIL
;
}
return
stream_read
(
stream
,
data
,
size
);
}
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
{
ULONG
len
;
HRESULT
hr
;
hr
=
IStream_Read
(
stream
,
str
,
min
(
chunk
->
size
,
size
),
&
len
);
if
(
FAILED
(
hr
))
return
hr
;
/* Don't assume the string is properly zero terminated */
str
[
min
(
len
,
size
-
1
)]
=
0
;
if
(
len
<
chunk
->
size
)
return
S_FALSE
;
return
S_OK
;
}
/* Generic IDirectMusicObject methods */
static
inline
struct
dmobject
*
impl_from_IDirectMusicObject
(
IDirectMusicObject
*
iface
)
...
...
@@ -110,6 +250,78 @@ HRESULT WINAPI dmobj_IDirectMusicObject_SetDescriptor(IDirectMusicObject *iface,
return
ret
;
}
/* Helper for IDirectMusicObject::ParseDescriptor */
static
inline
void
info_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
info
,
DMUS_OBJECTDESC
*
desc
)
{
struct
chunk_entry
chunk
=
{.
parent
=
info
};
char
name
[
DMUS_MAX_NAME
];
ULONG
len
;
HRESULT
hr
=
E_FAIL
;
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
))
hr
=
IStream_Read
(
stream
,
name
,
min
(
chunk
.
size
,
sizeof
(
name
)),
&
len
);
if
(
SUCCEEDED
(
hr
))
{
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
name
,
len
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
));
desc
->
wszName
[
min
(
len
,
sizeof
(
desc
->
wszName
)
-
1
)]
=
0
;
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
}
static
inline
void
unfo_get_name
(
IStream
*
stream
,
const
struct
chunk_entry
*
unfo
,
DMUS_OBJECTDESC
*
desc
,
BOOL
inam
)
{
struct
chunk_entry
chunk
=
{.
parent
=
unfo
};
while
(
stream_next_chunk
(
stream
,
&
chunk
)
==
S_OK
)
if
(
chunk
.
id
==
DMUS_FOURCC_UNAM_CHUNK
||
(
inam
&&
chunk
.
id
==
mmioFOURCC
(
'I'
,
'N'
,
'A'
,
'M'
)))
if
(
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszName
,
sizeof
(
desc
->
wszName
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_NAME
;
}
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
{
struct
chunk_entry
chunk
=
{.
parent
=
riff
};
HRESULT
hr
;
TRACE
(
"Looking for %#x in %p: %s
\n
"
,
supported
,
stream
,
debugstr_chunk
(
riff
));
desc
->
dwValidData
=
0
;
desc
->
dwSize
=
sizeof
(
*
desc
);
while
((
hr
=
stream_next_chunk
(
stream
,
&
chunk
))
==
S_OK
)
{
switch
(
chunk
.
id
)
{
case
DMUS_FOURCC_GUID_CHUNK
:
if
((
supported
&
DMUS_OBJ_OBJECT
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
guidObject
,
sizeof
(
desc
->
guidObject
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_OBJECT
;
break
;
case
DMUS_FOURCC_CATEGORY_CHUNK
:
if
((
supported
&
DMUS_OBJ_CATEGORY
)
&&
stream_chunk_get_wstr
(
stream
,
&
chunk
,
desc
->
wszCategory
,
sizeof
(
desc
->
wszCategory
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_CATEGORY
;
break
;
case
DMUS_FOURCC_VERSION_CHUNK
:
if
((
supported
&
DMUS_OBJ_VERSION
)
&&
stream_chunk_get_data
(
stream
,
&
chunk
,
&
desc
->
vVersion
,
sizeof
(
desc
->
vVersion
))
==
S_OK
)
desc
->
dwValidData
|=
DMUS_OBJ_VERSION
;
break
;
case
FOURCC_LIST
:
if
(
chunk
.
type
==
DMUS_FOURCC_UNFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME
))
unfo_get_name
(
stream
,
&
chunk
,
desc
,
supported
&
DMUS_OBJ_NAME_INAM
);
else
if
(
chunk
.
type
==
DMUS_FOURCC_INFO_LIST
&&
(
supported
&
DMUS_OBJ_NAME_INFO
))
info_get_name
(
stream
,
&
chunk
,
desc
);
break
;
}
}
TRACE
(
"Found %#x
\n
"
,
desc
->
dwValidData
);
return
hr
;
}
/* Generic IPersistStream methods */
static
inline
struct
dmobject
*
impl_from_IPersistStream
(
IPersistStream
*
iface
)
{
...
...
dlls/dswave/dmobject.h
View file @
70281427
...
...
@@ -19,6 +19,51 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/debug.h"
/* RIFF stream parsing */
struct
chunk_entry
;
struct
chunk_entry
{
FOURCC
id
;
DWORD
size
;
FOURCC
type
;
/* valid only for LIST and RIFF chunks */
ULARGE_INTEGER
offset
;
/* chunk offset from start of stream */
const
struct
chunk_entry
*
parent
;
/* enclosing RIFF or LIST chunk */
};
HRESULT
stream_get_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_next_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_skip_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
void
*
data
,
ULONG
size
)
DECLSPEC_HIDDEN
;
HRESULT
stream_chunk_get_wstr
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
,
WCHAR
*
str
,
ULONG
size
)
DECLSPEC_HIDDEN
;
static
inline
HRESULT
stream_reset_chunk_data
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
+
sizeof
(
FOURCC
)
+
sizeof
(
DWORD
);
if
(
chunk
->
id
==
FOURCC_RIFF
||
chunk
->
id
==
FOURCC_LIST
)
offset
.
QuadPart
+=
sizeof
(
FOURCC
);
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
static
inline
HRESULT
stream_reset_chunk_start
(
IStream
*
stream
,
const
struct
chunk_entry
*
chunk
)
{
LARGE_INTEGER
offset
;
offset
.
QuadPart
=
chunk
->
offset
.
QuadPart
;
return
IStream_Seek
(
stream
,
offset
,
STREAM_SEEK_SET
,
NULL
);
}
const
char
*
debugstr_chunk
(
const
struct
chunk_entry
*
chunk
)
DECLSPEC_HIDDEN
;
/* IDirectMusicObject base object */
struct
dmobject
{
IDirectMusicObject
IDirectMusicObject_iface
;
IPersistStream
IPersistStream_iface
;
...
...
@@ -38,6 +83,14 @@ HRESULT WINAPI dmobj_IDirectMusicObject_GetDescriptor(IDirectMusicObject *iface,
HRESULT
WINAPI
dmobj_IDirectMusicObject_SetDescriptor
(
IDirectMusicObject
*
iface
,
DMUS_OBJECTDESC
*
desc
)
DECLSPEC_HIDDEN
;
/* Helper for IDirectMusicObject::ParseDescriptor */
HRESULT
dmobj_parsedescriptor
(
IStream
*
stream
,
const
struct
chunk_entry
*
riff
,
DMUS_OBJECTDESC
*
desc
,
DWORD
supported
)
DECLSPEC_HIDDEN
;
/* Additional supported flags for dmobj_parsedescriptor.
DMUS_OBJ_NAME is 'UNAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INAM 0x1000
/* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000
/* 'INAM' chunk in INFO list */
/* Generic IPersistStream methods */
HRESULT
WINAPI
dmobj_IPersistStream_QueryInterface
(
IPersistStream
*
iface
,
REFIID
riid
,
void
**
ret_iface
)
DECLSPEC_HIDDEN
;
...
...
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