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
70970429
Commit
70970429
authored
Jun 19, 2023
by
Rémi Bernon
Committed by
Alexandre Julliard
Aug 23, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mf/scheme_handler: Split file scheme handler to scheme_handler.c.
parent
fd3d0113
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
484 additions
and
448 deletions
+484
-448
Makefile.in
dlls/mf/Makefile.in
+1
-0
main.c
dlls/mf/main.c
+0
-448
mf_private.h
dlls/mf/mf_private.h
+2
-0
scheme_handler.c
dlls/mf/scheme_handler.c
+481
-0
No files found.
dlls/mf/Makefile.in
View file @
70970429
...
...
@@ -13,6 +13,7 @@ C_SRCS = \
quality.c
\
samplegrabber.c
\
sar.c
\
scheme_handler.c
\
session.c
\
topology.c
\
topology_loader.c
...
...
dlls/mf/main.c
View file @
70970429
...
...
@@ -548,454 +548,6 @@ static const IClassFactoryVtbl class_factory_vtbl =
class_factory_LockServer
,
};
struct
file_scheme_handler_result
{
struct
list
entry
;
IMFAsyncResult
*
result
;
MF_OBJECT_TYPE
obj_type
;
IUnknown
*
object
;
};
struct
file_scheme_handler
{
IMFSchemeHandler
IMFSchemeHandler_iface
;
IMFAsyncCallback
IMFAsyncCallback_iface
;
LONG
refcount
;
IMFSourceResolver
*
resolver
;
struct
list
results
;
CRITICAL_SECTION
cs
;
};
static
struct
file_scheme_handler
*
impl_from_IMFSchemeHandler
(
IMFSchemeHandler
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
file_scheme_handler
,
IMFSchemeHandler_iface
);
}
static
struct
file_scheme_handler
*
impl_from_IMFAsyncCallback
(
IMFAsyncCallback
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
file_scheme_handler
,
IMFAsyncCallback_iface
);
}
static
HRESULT
WINAPI
file_scheme_handler_QueryInterface
(
IMFSchemeHandler
*
iface
,
REFIID
riid
,
void
**
obj
)
{
TRACE
(
"%p, %s, %p.
\n
"
,
iface
,
debugstr_guid
(
riid
),
obj
);
if
(
IsEqualIID
(
riid
,
&
IID_IMFSchemeHandler
)
||
IsEqualIID
(
riid
,
&
IID_IUnknown
))
{
*
obj
=
iface
;
IMFSchemeHandler_AddRef
(
iface
);
return
S_OK
;
}
WARN
(
"Unsupported %s.
\n
"
,
debugstr_guid
(
riid
));
*
obj
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
file_scheme_handler_AddRef
(
IMFSchemeHandler
*
iface
)
{
struct
file_scheme_handler
*
handler
=
impl_from_IMFSchemeHandler
(
iface
);
ULONG
refcount
=
InterlockedIncrement
(
&
handler
->
refcount
);
TRACE
(
"%p, refcount %lu.
\n
"
,
handler
,
refcount
);
return
refcount
;
}
static
ULONG
WINAPI
file_scheme_handler_Release
(
IMFSchemeHandler
*
iface
)
{
struct
file_scheme_handler
*
handler
=
impl_from_IMFSchemeHandler
(
iface
);
ULONG
refcount
=
InterlockedDecrement
(
&
handler
->
refcount
);
struct
file_scheme_handler_result
*
result
,
*
next
;
TRACE
(
"%p, refcount %lu.
\n
"
,
iface
,
refcount
);
if
(
!
refcount
)
{
LIST_FOR_EACH_ENTRY_SAFE
(
result
,
next
,
&
handler
->
results
,
struct
file_scheme_handler_result
,
entry
)
{
list_remove
(
&
result
->
entry
);
IMFAsyncResult_Release
(
result
->
result
);
if
(
result
->
object
)
IUnknown_Release
(
result
->
object
);
free
(
result
);
}
DeleteCriticalSection
(
&
handler
->
cs
);
if
(
handler
->
resolver
)
IMFSourceResolver_Release
(
handler
->
resolver
);
free
(
handler
);
}
return
refcount
;
}
struct
create_object_context
{
IUnknown
IUnknown_iface
;
LONG
refcount
;
IPropertyStore
*
props
;
WCHAR
*
url
;
DWORD
flags
;
};
static
struct
create_object_context
*
impl_from_IUnknown
(
IUnknown
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
create_object_context
,
IUnknown_iface
);
}
static
HRESULT
WINAPI
create_object_context_QueryInterface
(
IUnknown
*
iface
,
REFIID
riid
,
void
**
obj
)
{
TRACE
(
"%p, %s, %p.
\n
"
,
iface
,
debugstr_guid
(
riid
),
obj
);
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
))
{
*
obj
=
iface
;
IUnknown_AddRef
(
iface
);
return
S_OK
;
}
WARN
(
"Unsupported %s.
\n
"
,
debugstr_guid
(
riid
));
*
obj
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
create_object_context_AddRef
(
IUnknown
*
iface
)
{
struct
create_object_context
*
context
=
impl_from_IUnknown
(
iface
);
ULONG
refcount
=
InterlockedIncrement
(
&
context
->
refcount
);
TRACE
(
"%p, refcount %lu.
\n
"
,
iface
,
refcount
);
return
refcount
;
}
static
ULONG
WINAPI
create_object_context_Release
(
IUnknown
*
iface
)
{
struct
create_object_context
*
context
=
impl_from_IUnknown
(
iface
);
ULONG
refcount
=
InterlockedDecrement
(
&
context
->
refcount
);
TRACE
(
"%p, refcount %lu.
\n
"
,
iface
,
refcount
);
if
(
!
refcount
)
{
if
(
context
->
props
)
IPropertyStore_Release
(
context
->
props
);
free
(
context
->
url
);
free
(
context
);
}
return
refcount
;
}
static
const
IUnknownVtbl
create_object_context_vtbl
=
{
create_object_context_QueryInterface
,
create_object_context_AddRef
,
create_object_context_Release
,
};
static
HRESULT
WINAPI
file_scheme_handler_BeginCreateObject
(
IMFSchemeHandler
*
iface
,
const
WCHAR
*
url
,
DWORD
flags
,
IPropertyStore
*
props
,
IUnknown
**
cancel_cookie
,
IMFAsyncCallback
*
callback
,
IUnknown
*
state
)
{
struct
file_scheme_handler
*
handler
=
impl_from_IMFSchemeHandler
(
iface
);
struct
create_object_context
*
context
;
IMFAsyncResult
*
caller
,
*
item
;
HRESULT
hr
;
TRACE
(
"%p, %s, %#lx, %p, %p, %p, %p.
\n
"
,
iface
,
debugstr_w
(
url
),
flags
,
props
,
cancel_cookie
,
callback
,
state
);
if
(
cancel_cookie
)
*
cancel_cookie
=
NULL
;
if
(
FAILED
(
hr
=
MFCreateAsyncResult
(
NULL
,
callback
,
state
,
&
caller
)))
return
hr
;
if
(
!
(
context
=
malloc
(
sizeof
(
*
context
))))
{
IMFAsyncResult_Release
(
caller
);
return
E_OUTOFMEMORY
;
}
context
->
IUnknown_iface
.
lpVtbl
=
&
create_object_context_vtbl
;
context
->
refcount
=
1
;
context
->
props
=
props
;
if
(
context
->
props
)
IPropertyStore_AddRef
(
context
->
props
);
context
->
flags
=
flags
;
context
->
url
=
wcsdup
(
url
);
if
(
!
context
->
url
)
{
IMFAsyncResult_Release
(
caller
);
IUnknown_Release
(
&
context
->
IUnknown_iface
);
return
E_OUTOFMEMORY
;
}
hr
=
MFCreateAsyncResult
(
&
context
->
IUnknown_iface
,
&
handler
->
IMFAsyncCallback_iface
,
(
IUnknown
*
)
caller
,
&
item
);
IUnknown_Release
(
&
context
->
IUnknown_iface
);
if
(
SUCCEEDED
(
hr
))
{
if
(
SUCCEEDED
(
hr
=
MFPutWorkItemEx
(
MFASYNC_CALLBACK_QUEUE_IO
,
item
)))
{
if
(
cancel_cookie
)
{
*
cancel_cookie
=
(
IUnknown
*
)
caller
;
IUnknown_AddRef
(
*
cancel_cookie
);
}
}
IMFAsyncResult_Release
(
item
);
}
IMFAsyncResult_Release
(
caller
);
return
hr
;
}
static
HRESULT
WINAPI
file_scheme_handler_EndCreateObject
(
IMFSchemeHandler
*
iface
,
IMFAsyncResult
*
result
,
MF_OBJECT_TYPE
*
obj_type
,
IUnknown
**
object
)
{
struct
file_scheme_handler
*
handler
=
impl_from_IMFSchemeHandler
(
iface
);
struct
file_scheme_handler_result
*
found
=
NULL
,
*
cur
;
HRESULT
hr
;
TRACE
(
"%p, %p, %p, %p.
\n
"
,
iface
,
result
,
obj_type
,
object
);
EnterCriticalSection
(
&
handler
->
cs
);
LIST_FOR_EACH_ENTRY
(
cur
,
&
handler
->
results
,
struct
file_scheme_handler_result
,
entry
)
{
if
(
result
==
cur
->
result
)
{
list_remove
(
&
cur
->
entry
);
found
=
cur
;
break
;
}
}
LeaveCriticalSection
(
&
handler
->
cs
);
if
(
found
)
{
*
obj_type
=
found
->
obj_type
;
*
object
=
found
->
object
;
hr
=
IMFAsyncResult_GetStatus
(
found
->
result
);
IMFAsyncResult_Release
(
found
->
result
);
free
(
found
);
}
else
{
*
obj_type
=
MF_OBJECT_INVALID
;
*
object
=
NULL
;
hr
=
MF_E_UNEXPECTED
;
}
return
hr
;
}
static
HRESULT
WINAPI
file_scheme_handler_CancelObjectCreation
(
IMFSchemeHandler
*
iface
,
IUnknown
*
cancel_cookie
)
{
struct
file_scheme_handler
*
handler
=
impl_from_IMFSchemeHandler
(
iface
);
struct
file_scheme_handler_result
*
found
=
NULL
,
*
cur
;
TRACE
(
"%p, %p.
\n
"
,
iface
,
cancel_cookie
);
EnterCriticalSection
(
&
handler
->
cs
);
LIST_FOR_EACH_ENTRY
(
cur
,
&
handler
->
results
,
struct
file_scheme_handler_result
,
entry
)
{
if
(
cancel_cookie
==
(
IUnknown
*
)
cur
->
result
)
{
list_remove
(
&
cur
->
entry
);
found
=
cur
;
break
;
}
}
LeaveCriticalSection
(
&
handler
->
cs
);
if
(
found
)
{
IMFAsyncResult_Release
(
found
->
result
);
if
(
found
->
object
)
IUnknown_Release
(
found
->
object
);
free
(
found
);
}
return
found
?
S_OK
:
MF_E_UNEXPECTED
;
}
static
const
IMFSchemeHandlerVtbl
file_scheme_handler_vtbl
=
{
file_scheme_handler_QueryInterface
,
file_scheme_handler_AddRef
,
file_scheme_handler_Release
,
file_scheme_handler_BeginCreateObject
,
file_scheme_handler_EndCreateObject
,
file_scheme_handler_CancelObjectCreation
,
};
static
HRESULT
WINAPI
file_scheme_handler_callback_QueryInterface
(
IMFAsyncCallback
*
iface
,
REFIID
riid
,
void
**
obj
)
{
if
(
IsEqualIID
(
riid
,
&
IID_IMFAsyncCallback
)
||
IsEqualIID
(
riid
,
&
IID_IUnknown
))
{
*
obj
=
iface
;
IMFAsyncCallback_AddRef
(
iface
);
return
S_OK
;
}
WARN
(
"Unsupported %s.
\n
"
,
debugstr_guid
(
riid
));
*
obj
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
file_scheme_handler_callback_AddRef
(
IMFAsyncCallback
*
iface
)
{
struct
file_scheme_handler
*
handler
=
impl_from_IMFAsyncCallback
(
iface
);
return
IMFSchemeHandler_AddRef
(
&
handler
->
IMFSchemeHandler_iface
);
}
static
ULONG
WINAPI
file_scheme_handler_callback_Release
(
IMFAsyncCallback
*
iface
)
{
struct
file_scheme_handler
*
handler
=
impl_from_IMFAsyncCallback
(
iface
);
return
IMFSchemeHandler_Release
(
&
handler
->
IMFSchemeHandler_iface
);
}
static
HRESULT
WINAPI
file_scheme_handler_callback_GetParameters
(
IMFAsyncCallback
*
iface
,
DWORD
*
flags
,
DWORD
*
queue
)
{
return
E_NOTIMPL
;
}
static
HRESULT
file_scheme_handler_get_resolver
(
struct
file_scheme_handler
*
handler
,
IMFSourceResolver
**
resolver
)
{
HRESULT
hr
;
if
(
!
handler
->
resolver
)
{
IMFSourceResolver
*
resolver
;
if
(
FAILED
(
hr
=
MFCreateSourceResolver
(
&
resolver
)))
return
hr
;
if
(
InterlockedCompareExchangePointer
((
void
**
)
&
handler
->
resolver
,
resolver
,
NULL
))
IMFSourceResolver_Release
(
resolver
);
}
*
resolver
=
handler
->
resolver
;
IMFSourceResolver_AddRef
(
*
resolver
);
return
S_OK
;
}
static
HRESULT
WINAPI
file_scheme_handler_callback_Invoke
(
IMFAsyncCallback
*
iface
,
IMFAsyncResult
*
result
)
{
static
const
WCHAR
schemeW
[]
=
{
'f'
,
'i'
,
'l'
,
'e'
,
':'
,
'/'
,
'/'
};
struct
file_scheme_handler
*
handler
=
impl_from_IMFAsyncCallback
(
iface
);
struct
file_scheme_handler_result
*
handler_result
;
MF_OBJECT_TYPE
obj_type
=
MF_OBJECT_INVALID
;
IUnknown
*
object
=
NULL
,
*
context_object
;
struct
create_object_context
*
context
;
IMFSourceResolver
*
resolver
;
IMFAsyncResult
*
caller
;
IMFByteStream
*
stream
;
const
WCHAR
*
url
;
HRESULT
hr
;
caller
=
(
IMFAsyncResult
*
)
IMFAsyncResult_GetStateNoAddRef
(
result
);
if
(
FAILED
(
hr
=
IMFAsyncResult_GetObject
(
result
,
&
context_object
)))
{
WARN
(
"Expected context set for callee result.
\n
"
);
return
hr
;
}
context
=
impl_from_IUnknown
(
context_object
);
/* Strip from scheme, MFCreateFile() won't be expecting it. */
url
=
context
->
url
;
if
(
!
wcsnicmp
(
context
->
url
,
schemeW
,
ARRAY_SIZE
(
schemeW
)))
url
+=
ARRAY_SIZE
(
schemeW
);
hr
=
MFCreateFile
(
context
->
flags
&
MF_RESOLUTION_WRITE
?
MF_ACCESSMODE_READWRITE
:
MF_ACCESSMODE_READ
,
MF_OPENMODE_FAIL_IF_NOT_EXIST
,
MF_FILEFLAGS_NONE
,
url
,
&
stream
);
if
(
SUCCEEDED
(
hr
))
{
if
(
context
->
flags
&
MF_RESOLUTION_MEDIASOURCE
)
{
if
(
SUCCEEDED
(
hr
=
file_scheme_handler_get_resolver
(
handler
,
&
resolver
)))
{
hr
=
IMFSourceResolver_CreateObjectFromByteStream
(
resolver
,
stream
,
context
->
url
,
context
->
flags
,
context
->
props
,
&
obj_type
,
&
object
);
IMFSourceResolver_Release
(
resolver
);
IMFByteStream_Release
(
stream
);
}
}
else
{
object
=
(
IUnknown
*
)
stream
;
obj_type
=
MF_OBJECT_BYTESTREAM
;
}
}
handler_result
=
malloc
(
sizeof
(
*
handler_result
));
if
(
handler_result
)
{
handler_result
->
result
=
caller
;
IMFAsyncResult_AddRef
(
handler_result
->
result
);
handler_result
->
obj_type
=
obj_type
;
handler_result
->
object
=
object
;
EnterCriticalSection
(
&
handler
->
cs
);
list_add_tail
(
&
handler
->
results
,
&
handler_result
->
entry
);
LeaveCriticalSection
(
&
handler
->
cs
);
}
else
{
if
(
object
)
IUnknown_Release
(
object
);
hr
=
E_OUTOFMEMORY
;
}
IUnknown_Release
(
&
context
->
IUnknown_iface
);
IMFAsyncResult_SetStatus
(
caller
,
hr
);
MFInvokeCallback
(
caller
);
return
S_OK
;
}
static
const
IMFAsyncCallbackVtbl
file_scheme_handler_callback_vtbl
=
{
file_scheme_handler_callback_QueryInterface
,
file_scheme_handler_callback_AddRef
,
file_scheme_handler_callback_Release
,
file_scheme_handler_callback_GetParameters
,
file_scheme_handler_callback_Invoke
,
};
static
HRESULT
file_scheme_handler_construct
(
REFIID
riid
,
void
**
obj
)
{
struct
file_scheme_handler
*
handler
;
HRESULT
hr
;
TRACE
(
"%s, %p.
\n
"
,
debugstr_guid
(
riid
),
obj
);
if
(
!
(
handler
=
calloc
(
1
,
sizeof
(
*
handler
))))
return
E_OUTOFMEMORY
;
handler
->
IMFSchemeHandler_iface
.
lpVtbl
=
&
file_scheme_handler_vtbl
;
handler
->
IMFAsyncCallback_iface
.
lpVtbl
=
&
file_scheme_handler_callback_vtbl
;
handler
->
refcount
=
1
;
list_init
(
&
handler
->
results
);
InitializeCriticalSection
(
&
handler
->
cs
);
hr
=
IMFSchemeHandler_QueryInterface
(
&
handler
->
IMFSchemeHandler_iface
,
riid
,
obj
);
IMFSchemeHandler_Release
(
&
handler
->
IMFSchemeHandler_iface
);
return
hr
;
}
static
struct
class_factory
file_scheme_handler_factory
=
{
{
&
class_factory_vtbl
},
file_scheme_handler_construct
};
static
const
struct
class_object
...
...
dlls/mf/mf_private.h
View file @
70970429
...
...
@@ -113,6 +113,8 @@ static inline const char *debugstr_propvar(const PROPVARIANT *v)
}
}
extern
HRESULT
file_scheme_handler_construct
(
REFIID
riid
,
void
**
obj
);
extern
BOOL
mf_is_sample_copier_transform
(
IMFTransform
*
transform
);
extern
BOOL
mf_is_sar_sink
(
IMFMediaSink
*
sink
);
extern
HRESULT
topology_node_get_object
(
IMFTopologyNode
*
node
,
REFIID
riid
,
void
**
obj
);
...
...
dlls/mf/scheme_handler.c
0 → 100644
View file @
70970429
/*
* Copyright 2022 Nikolay Sivov for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stddef.h>
#include <stdarg.h>
#define COBJMACROS
#include "windef.h"
#include "winbase.h"
#include "evr.h"
#include "mfidl.h"
#include "mf_private.h"
#include "wine/debug.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
mfplat
);
struct
scheme_handler_result
{
struct
list
entry
;
IMFAsyncResult
*
result
;
MF_OBJECT_TYPE
obj_type
;
IUnknown
*
object
;
};
struct
scheme_handler
{
IMFSchemeHandler
IMFSchemeHandler_iface
;
IMFAsyncCallback
IMFAsyncCallback_iface
;
LONG
refcount
;
IMFSourceResolver
*
resolver
;
struct
list
results
;
CRITICAL_SECTION
cs
;
};
static
struct
scheme_handler
*
impl_from_IMFSchemeHandler
(
IMFSchemeHandler
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
scheme_handler
,
IMFSchemeHandler_iface
);
}
static
struct
scheme_handler
*
impl_from_IMFAsyncCallback
(
IMFAsyncCallback
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
scheme_handler
,
IMFAsyncCallback_iface
);
}
static
HRESULT
WINAPI
scheme_handler_QueryInterface
(
IMFSchemeHandler
*
iface
,
REFIID
riid
,
void
**
obj
)
{
TRACE
(
"%p, %s, %p.
\n
"
,
iface
,
debugstr_guid
(
riid
),
obj
);
if
(
IsEqualIID
(
riid
,
&
IID_IMFSchemeHandler
)
||
IsEqualIID
(
riid
,
&
IID_IUnknown
))
{
*
obj
=
iface
;
IMFSchemeHandler_AddRef
(
iface
);
return
S_OK
;
}
WARN
(
"Unsupported %s.
\n
"
,
debugstr_guid
(
riid
));
*
obj
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
scheme_handler_AddRef
(
IMFSchemeHandler
*
iface
)
{
struct
scheme_handler
*
handler
=
impl_from_IMFSchemeHandler
(
iface
);
ULONG
refcount
=
InterlockedIncrement
(
&
handler
->
refcount
);
TRACE
(
"%p, refcount %lu.
\n
"
,
handler
,
refcount
);
return
refcount
;
}
static
ULONG
WINAPI
scheme_handler_Release
(
IMFSchemeHandler
*
iface
)
{
struct
scheme_handler
*
handler
=
impl_from_IMFSchemeHandler
(
iface
);
ULONG
refcount
=
InterlockedDecrement
(
&
handler
->
refcount
);
struct
scheme_handler_result
*
result
,
*
next
;
TRACE
(
"%p, refcount %lu.
\n
"
,
iface
,
refcount
);
if
(
!
refcount
)
{
LIST_FOR_EACH_ENTRY_SAFE
(
result
,
next
,
&
handler
->
results
,
struct
scheme_handler_result
,
entry
)
{
list_remove
(
&
result
->
entry
);
IMFAsyncResult_Release
(
result
->
result
);
if
(
result
->
object
)
IUnknown_Release
(
result
->
object
);
free
(
result
);
}
DeleteCriticalSection
(
&
handler
->
cs
);
if
(
handler
->
resolver
)
IMFSourceResolver_Release
(
handler
->
resolver
);
free
(
handler
);
}
return
refcount
;
}
struct
create_object_context
{
IUnknown
IUnknown_iface
;
LONG
refcount
;
IPropertyStore
*
props
;
WCHAR
*
url
;
DWORD
flags
;
};
static
struct
create_object_context
*
impl_from_IUnknown
(
IUnknown
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
create_object_context
,
IUnknown_iface
);
}
static
HRESULT
WINAPI
create_object_context_QueryInterface
(
IUnknown
*
iface
,
REFIID
riid
,
void
**
obj
)
{
TRACE
(
"%p, %s, %p.
\n
"
,
iface
,
debugstr_guid
(
riid
),
obj
);
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
))
{
*
obj
=
iface
;
IUnknown_AddRef
(
iface
);
return
S_OK
;
}
WARN
(
"Unsupported %s.
\n
"
,
debugstr_guid
(
riid
));
*
obj
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
create_object_context_AddRef
(
IUnknown
*
iface
)
{
struct
create_object_context
*
context
=
impl_from_IUnknown
(
iface
);
ULONG
refcount
=
InterlockedIncrement
(
&
context
->
refcount
);
TRACE
(
"%p, refcount %lu.
\n
"
,
iface
,
refcount
);
return
refcount
;
}
static
ULONG
WINAPI
create_object_context_Release
(
IUnknown
*
iface
)
{
struct
create_object_context
*
context
=
impl_from_IUnknown
(
iface
);
ULONG
refcount
=
InterlockedDecrement
(
&
context
->
refcount
);
TRACE
(
"%p, refcount %lu.
\n
"
,
iface
,
refcount
);
if
(
!
refcount
)
{
if
(
context
->
props
)
IPropertyStore_Release
(
context
->
props
);
free
(
context
->
url
);
free
(
context
);
}
return
refcount
;
}
static
const
IUnknownVtbl
create_object_context_vtbl
=
{
create_object_context_QueryInterface
,
create_object_context_AddRef
,
create_object_context_Release
,
};
static
HRESULT
WINAPI
scheme_handler_BeginCreateObject
(
IMFSchemeHandler
*
iface
,
const
WCHAR
*
url
,
DWORD
flags
,
IPropertyStore
*
props
,
IUnknown
**
cancel_cookie
,
IMFAsyncCallback
*
callback
,
IUnknown
*
state
)
{
struct
scheme_handler
*
handler
=
impl_from_IMFSchemeHandler
(
iface
);
struct
create_object_context
*
context
;
IMFAsyncResult
*
caller
,
*
item
;
HRESULT
hr
;
TRACE
(
"%p, %s, %#lx, %p, %p, %p, %p.
\n
"
,
iface
,
debugstr_w
(
url
),
flags
,
props
,
cancel_cookie
,
callback
,
state
);
if
(
cancel_cookie
)
*
cancel_cookie
=
NULL
;
if
(
FAILED
(
hr
=
MFCreateAsyncResult
(
NULL
,
callback
,
state
,
&
caller
)))
return
hr
;
if
(
!
(
context
=
malloc
(
sizeof
(
*
context
))))
{
IMFAsyncResult_Release
(
caller
);
return
E_OUTOFMEMORY
;
}
context
->
IUnknown_iface
.
lpVtbl
=
&
create_object_context_vtbl
;
context
->
refcount
=
1
;
context
->
props
=
props
;
if
(
context
->
props
)
IPropertyStore_AddRef
(
context
->
props
);
context
->
flags
=
flags
;
context
->
url
=
wcsdup
(
url
);
if
(
!
context
->
url
)
{
IMFAsyncResult_Release
(
caller
);
IUnknown_Release
(
&
context
->
IUnknown_iface
);
return
E_OUTOFMEMORY
;
}
hr
=
MFCreateAsyncResult
(
&
context
->
IUnknown_iface
,
&
handler
->
IMFAsyncCallback_iface
,
(
IUnknown
*
)
caller
,
&
item
);
IUnknown_Release
(
&
context
->
IUnknown_iface
);
if
(
SUCCEEDED
(
hr
))
{
if
(
SUCCEEDED
(
hr
=
MFPutWorkItemEx
(
MFASYNC_CALLBACK_QUEUE_IO
,
item
)))
{
if
(
cancel_cookie
)
{
*
cancel_cookie
=
(
IUnknown
*
)
caller
;
IUnknown_AddRef
(
*
cancel_cookie
);
}
}
IMFAsyncResult_Release
(
item
);
}
IMFAsyncResult_Release
(
caller
);
return
hr
;
}
static
HRESULT
WINAPI
scheme_handler_EndCreateObject
(
IMFSchemeHandler
*
iface
,
IMFAsyncResult
*
result
,
MF_OBJECT_TYPE
*
obj_type
,
IUnknown
**
object
)
{
struct
scheme_handler
*
handler
=
impl_from_IMFSchemeHandler
(
iface
);
struct
scheme_handler_result
*
found
=
NULL
,
*
cur
;
HRESULT
hr
;
TRACE
(
"%p, %p, %p, %p.
\n
"
,
iface
,
result
,
obj_type
,
object
);
EnterCriticalSection
(
&
handler
->
cs
);
LIST_FOR_EACH_ENTRY
(
cur
,
&
handler
->
results
,
struct
scheme_handler_result
,
entry
)
{
if
(
result
==
cur
->
result
)
{
list_remove
(
&
cur
->
entry
);
found
=
cur
;
break
;
}
}
LeaveCriticalSection
(
&
handler
->
cs
);
if
(
found
)
{
*
obj_type
=
found
->
obj_type
;
*
object
=
found
->
object
;
hr
=
IMFAsyncResult_GetStatus
(
found
->
result
);
IMFAsyncResult_Release
(
found
->
result
);
free
(
found
);
}
else
{
*
obj_type
=
MF_OBJECT_INVALID
;
*
object
=
NULL
;
hr
=
MF_E_UNEXPECTED
;
}
return
hr
;
}
static
HRESULT
WINAPI
scheme_handler_CancelObjectCreation
(
IMFSchemeHandler
*
iface
,
IUnknown
*
cancel_cookie
)
{
struct
scheme_handler
*
handler
=
impl_from_IMFSchemeHandler
(
iface
);
struct
scheme_handler_result
*
found
=
NULL
,
*
cur
;
TRACE
(
"%p, %p.
\n
"
,
iface
,
cancel_cookie
);
EnterCriticalSection
(
&
handler
->
cs
);
LIST_FOR_EACH_ENTRY
(
cur
,
&
handler
->
results
,
struct
scheme_handler_result
,
entry
)
{
if
(
cancel_cookie
==
(
IUnknown
*
)
cur
->
result
)
{
list_remove
(
&
cur
->
entry
);
found
=
cur
;
break
;
}
}
LeaveCriticalSection
(
&
handler
->
cs
);
if
(
found
)
{
IMFAsyncResult_Release
(
found
->
result
);
if
(
found
->
object
)
IUnknown_Release
(
found
->
object
);
free
(
found
);
}
return
found
?
S_OK
:
MF_E_UNEXPECTED
;
}
static
const
IMFSchemeHandlerVtbl
scheme_handler_vtbl
=
{
scheme_handler_QueryInterface
,
scheme_handler_AddRef
,
scheme_handler_Release
,
scheme_handler_BeginCreateObject
,
scheme_handler_EndCreateObject
,
scheme_handler_CancelObjectCreation
,
};
static
HRESULT
WINAPI
scheme_handler_callback_QueryInterface
(
IMFAsyncCallback
*
iface
,
REFIID
riid
,
void
**
obj
)
{
if
(
IsEqualIID
(
riid
,
&
IID_IMFAsyncCallback
)
||
IsEqualIID
(
riid
,
&
IID_IUnknown
))
{
*
obj
=
iface
;
IMFAsyncCallback_AddRef
(
iface
);
return
S_OK
;
}
WARN
(
"Unsupported %s.
\n
"
,
debugstr_guid
(
riid
));
*
obj
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
scheme_handler_callback_AddRef
(
IMFAsyncCallback
*
iface
)
{
struct
scheme_handler
*
handler
=
impl_from_IMFAsyncCallback
(
iface
);
return
IMFSchemeHandler_AddRef
(
&
handler
->
IMFSchemeHandler_iface
);
}
static
ULONG
WINAPI
scheme_handler_callback_Release
(
IMFAsyncCallback
*
iface
)
{
struct
scheme_handler
*
handler
=
impl_from_IMFAsyncCallback
(
iface
);
return
IMFSchemeHandler_Release
(
&
handler
->
IMFSchemeHandler_iface
);
}
static
HRESULT
WINAPI
scheme_handler_callback_GetParameters
(
IMFAsyncCallback
*
iface
,
DWORD
*
flags
,
DWORD
*
queue
)
{
return
E_NOTIMPL
;
}
static
HRESULT
scheme_handler_get_resolver
(
struct
scheme_handler
*
handler
,
IMFSourceResolver
**
resolver
)
{
HRESULT
hr
;
if
(
!
handler
->
resolver
)
{
IMFSourceResolver
*
resolver
;
if
(
FAILED
(
hr
=
MFCreateSourceResolver
(
&
resolver
)))
return
hr
;
if
(
InterlockedCompareExchangePointer
((
void
**
)
&
handler
->
resolver
,
resolver
,
NULL
))
IMFSourceResolver_Release
(
resolver
);
}
*
resolver
=
handler
->
resolver
;
IMFSourceResolver_AddRef
(
*
resolver
);
return
S_OK
;
}
static
HRESULT
WINAPI
scheme_handler_callback_Invoke
(
IMFAsyncCallback
*
iface
,
IMFAsyncResult
*
result
)
{
static
const
WCHAR
schemeW
[]
=
{
'f'
,
'i'
,
'l'
,
'e'
,
':'
,
'/'
,
'/'
};
struct
scheme_handler
*
handler
=
impl_from_IMFAsyncCallback
(
iface
);
struct
scheme_handler_result
*
handler_result
;
MF_OBJECT_TYPE
obj_type
=
MF_OBJECT_INVALID
;
IUnknown
*
object
=
NULL
,
*
context_object
;
struct
create_object_context
*
context
;
IMFSourceResolver
*
resolver
;
IMFAsyncResult
*
caller
;
IMFByteStream
*
stream
;
const
WCHAR
*
url
;
HRESULT
hr
;
caller
=
(
IMFAsyncResult
*
)
IMFAsyncResult_GetStateNoAddRef
(
result
);
if
(
FAILED
(
hr
=
IMFAsyncResult_GetObject
(
result
,
&
context_object
)))
{
WARN
(
"Expected context set for callee result.
\n
"
);
return
hr
;
}
context
=
impl_from_IUnknown
(
context_object
);
/* Strip from scheme, MFCreateFile() won't be expecting it. */
url
=
context
->
url
;
if
(
!
wcsnicmp
(
context
->
url
,
schemeW
,
ARRAY_SIZE
(
schemeW
)))
url
+=
ARRAY_SIZE
(
schemeW
);
hr
=
MFCreateFile
(
context
->
flags
&
MF_RESOLUTION_WRITE
?
MF_ACCESSMODE_READWRITE
:
MF_ACCESSMODE_READ
,
MF_OPENMODE_FAIL_IF_NOT_EXIST
,
MF_FILEFLAGS_NONE
,
url
,
&
stream
);
if
(
SUCCEEDED
(
hr
))
{
if
(
context
->
flags
&
MF_RESOLUTION_MEDIASOURCE
)
{
if
(
SUCCEEDED
(
hr
=
scheme_handler_get_resolver
(
handler
,
&
resolver
)))
{
hr
=
IMFSourceResolver_CreateObjectFromByteStream
(
resolver
,
stream
,
context
->
url
,
context
->
flags
,
context
->
props
,
&
obj_type
,
&
object
);
IMFSourceResolver_Release
(
resolver
);
IMFByteStream_Release
(
stream
);
}
}
else
{
object
=
(
IUnknown
*
)
stream
;
obj_type
=
MF_OBJECT_BYTESTREAM
;
}
}
handler_result
=
malloc
(
sizeof
(
*
handler_result
));
if
(
handler_result
)
{
handler_result
->
result
=
caller
;
IMFAsyncResult_AddRef
(
handler_result
->
result
);
handler_result
->
obj_type
=
obj_type
;
handler_result
->
object
=
object
;
EnterCriticalSection
(
&
handler
->
cs
);
list_add_tail
(
&
handler
->
results
,
&
handler_result
->
entry
);
LeaveCriticalSection
(
&
handler
->
cs
);
}
else
{
if
(
object
)
IUnknown_Release
(
object
);
hr
=
E_OUTOFMEMORY
;
}
IUnknown_Release
(
&
context
->
IUnknown_iface
);
IMFAsyncResult_SetStatus
(
caller
,
hr
);
MFInvokeCallback
(
caller
);
return
S_OK
;
}
static
const
IMFAsyncCallbackVtbl
scheme_handler_callback_vtbl
=
{
scheme_handler_callback_QueryInterface
,
scheme_handler_callback_AddRef
,
scheme_handler_callback_Release
,
scheme_handler_callback_GetParameters
,
scheme_handler_callback_Invoke
,
};
HRESULT
file_scheme_handler_construct
(
REFIID
riid
,
void
**
obj
)
{
struct
scheme_handler
*
handler
;
HRESULT
hr
;
TRACE
(
"%s, %p.
\n
"
,
debugstr_guid
(
riid
),
obj
);
if
(
!
(
handler
=
calloc
(
1
,
sizeof
(
*
handler
))))
return
E_OUTOFMEMORY
;
handler
->
IMFSchemeHandler_iface
.
lpVtbl
=
&
scheme_handler_vtbl
;
handler
->
IMFAsyncCallback_iface
.
lpVtbl
=
&
scheme_handler_callback_vtbl
;
handler
->
refcount
=
1
;
list_init
(
&
handler
->
results
);
InitializeCriticalSection
(
&
handler
->
cs
);
hr
=
IMFSchemeHandler_QueryInterface
(
&
handler
->
IMFSchemeHandler_iface
,
riid
,
obj
);
IMFSchemeHandler_Release
(
&
handler
->
IMFSchemeHandler_iface
);
return
hr
;
}
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