user32: Move unpack_message call to User32CallWindowProc.
[wine.git] / dlls / mf / main.c
blob6b1d9293c8a967cd5fd80ebf3d30f6930222eb4e
1 /*
2 * Copyright (C) 2015 Austin English
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdarg.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "mfidl.h"
27 #include "rpcproxy.h"
29 #include "mf_private.h"
31 #include "wine/debug.h"
32 #include "wine/list.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
36 extern const GUID CLSID_FileSchemePlugin;
38 struct activate_object
40 IMFActivate IMFActivate_iface;
41 LONG refcount;
42 IMFAttributes *attributes;
43 IUnknown *object;
44 const struct activate_funcs *funcs;
45 void *context;
48 static struct activate_object *impl_from_IMFActivate(IMFActivate *iface)
50 return CONTAINING_RECORD(iface, struct activate_object, IMFActivate_iface);
53 static HRESULT WINAPI activate_object_QueryInterface(IMFActivate *iface, REFIID riid, void **obj)
55 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
57 if (IsEqualIID(riid, &IID_IMFActivate) ||
58 IsEqualIID(riid, &IID_IMFAttributes) ||
59 IsEqualIID(riid, &IID_IUnknown))
61 *obj = iface;
62 IMFActivate_AddRef(iface);
63 return S_OK;
66 WARN("Unsupported %s.\n", debugstr_guid(riid));
67 *obj = NULL;
68 return E_NOINTERFACE;
71 static ULONG WINAPI activate_object_AddRef(IMFActivate *iface)
73 struct activate_object *activate = impl_from_IMFActivate(iface);
74 ULONG refcount = InterlockedIncrement(&activate->refcount);
76 TRACE("%p, refcount %lu.\n", iface, refcount);
78 return refcount;
81 static ULONG WINAPI activate_object_Release(IMFActivate *iface)
83 struct activate_object *activate = impl_from_IMFActivate(iface);
84 ULONG refcount = InterlockedDecrement(&activate->refcount);
86 TRACE("%p, refcount %lu.\n", iface, refcount);
88 if (!refcount)
90 if (activate->funcs->free_private)
91 activate->funcs->free_private(activate->context);
92 if (activate->object)
93 IUnknown_Release(activate->object);
94 IMFAttributes_Release(activate->attributes);
95 free(activate);
98 return refcount;
101 static HRESULT WINAPI activate_object_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value)
103 struct activate_object *activate = impl_from_IMFActivate(iface);
105 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
107 return IMFAttributes_GetItem(activate->attributes, key, value);
110 static HRESULT WINAPI activate_object_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
112 struct activate_object *activate = impl_from_IMFActivate(iface);
114 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), type);
116 return IMFAttributes_GetItemType(activate->attributes, key, type);
119 static HRESULT WINAPI activate_object_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
121 struct activate_object *activate = impl_from_IMFActivate(iface);
123 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, result);
125 return IMFAttributes_CompareItem(activate->attributes, key, value, result);
128 static HRESULT WINAPI activate_object_Compare(IMFActivate *iface, IMFAttributes *theirs, MF_ATTRIBUTES_MATCH_TYPE type,
129 BOOL *result)
131 struct activate_object *activate = impl_from_IMFActivate(iface);
133 TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
135 return IMFAttributes_Compare(activate->attributes, theirs, type, result);
138 static HRESULT WINAPI activate_object_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value)
140 struct activate_object *activate = impl_from_IMFActivate(iface);
142 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
144 return IMFAttributes_GetUINT32(activate->attributes, key, value);
147 static HRESULT WINAPI activate_object_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value)
149 struct activate_object *activate = impl_from_IMFActivate(iface);
151 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
153 return IMFAttributes_GetUINT64(activate->attributes, key, value);
156 static HRESULT WINAPI activate_object_GetDouble(IMFActivate *iface, REFGUID key, double *value)
158 struct activate_object *activate = impl_from_IMFActivate(iface);
160 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
162 return IMFAttributes_GetDouble(activate->attributes, key, value);
165 static HRESULT WINAPI activate_object_GetGUID(IMFActivate *iface, REFGUID key, GUID *value)
167 struct activate_object *activate = impl_from_IMFActivate(iface);
169 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
171 return IMFAttributes_GetGUID(activate->attributes, key, value);
174 static HRESULT WINAPI activate_object_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length)
176 struct activate_object *activate = impl_from_IMFActivate(iface);
178 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), length);
180 return IMFAttributes_GetStringLength(activate->attributes, key, length);
183 static HRESULT WINAPI activate_object_GetString(IMFActivate *iface, REFGUID key, WCHAR *value,
184 UINT32 size, UINT32 *length)
186 struct activate_object *activate = impl_from_IMFActivate(iface);
188 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_guid(key), value, size, length);
190 return IMFAttributes_GetString(activate->attributes, key, value, size, length);
193 static HRESULT WINAPI activate_object_GetAllocatedString(IMFActivate *iface, REFGUID key,
194 WCHAR **value, UINT32 *length)
196 struct activate_object *activate = impl_from_IMFActivate(iface);
198 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, length);
200 return IMFAttributes_GetAllocatedString(activate->attributes, key, value, length);
203 static HRESULT WINAPI activate_object_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size)
205 struct activate_object *activate = impl_from_IMFActivate(iface);
207 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), size);
209 return IMFAttributes_GetBlobSize(activate->attributes, key, size);
212 static HRESULT WINAPI activate_object_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf,
213 UINT32 bufsize, UINT32 *blobsize)
215 struct activate_object *activate = impl_from_IMFActivate(iface);
217 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_guid(key), buf, bufsize, blobsize);
219 return IMFAttributes_GetBlob(activate->attributes, key, buf, bufsize, blobsize);
222 static HRESULT WINAPI activate_object_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size)
224 struct activate_object *activate = impl_from_IMFActivate(iface);
226 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), buf, size);
228 return IMFAttributes_GetAllocatedBlob(activate->attributes, key, buf, size);
231 static HRESULT WINAPI activate_object_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **ppv)
233 struct activate_object *activate = impl_from_IMFActivate(iface);
235 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(key), debugstr_guid(riid), ppv);
237 return IMFAttributes_GetUnknown(activate->attributes, key, riid, ppv);
240 static HRESULT WINAPI activate_object_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value)
242 struct activate_object *activate = impl_from_IMFActivate(iface);
244 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
246 return IMFAttributes_SetItem(activate->attributes, key, value);
249 static HRESULT WINAPI activate_object_DeleteItem(IMFActivate *iface, REFGUID key)
251 struct activate_object *activate = impl_from_IMFActivate(iface);
253 TRACE("%p, %s.\n", iface, debugstr_guid(key));
255 return IMFAttributes_DeleteItem(activate->attributes, key);
258 static HRESULT WINAPI activate_object_DeleteAllItems(IMFActivate *iface)
260 struct activate_object *activate = impl_from_IMFActivate(iface);
262 TRACE("%p.\n", iface);
264 return IMFAttributes_DeleteAllItems(activate->attributes);
267 static HRESULT WINAPI activate_object_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value)
269 struct activate_object *activate = impl_from_IMFActivate(iface);
271 TRACE("%p, %s, %d.\n", iface, debugstr_guid(key), value);
273 return IMFAttributes_SetUINT32(activate->attributes, key, value);
276 static HRESULT WINAPI activate_object_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value)
278 struct activate_object *activate = impl_from_IMFActivate(iface);
280 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), wine_dbgstr_longlong(value));
282 return IMFAttributes_SetUINT64(activate->attributes, key, value);
285 static HRESULT WINAPI activate_object_SetDouble(IMFActivate *iface, REFGUID key, double value)
287 struct activate_object *activate = impl_from_IMFActivate(iface);
289 TRACE("%p, %s, %f.\n", iface, debugstr_guid(key), value);
291 return IMFAttributes_SetDouble(activate->attributes, key, value);
294 static HRESULT WINAPI activate_object_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value)
296 struct activate_object *activate = impl_from_IMFActivate(iface);
298 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_guid(value));
300 return IMFAttributes_SetGUID(activate->attributes, key, value);
303 static HRESULT WINAPI activate_object_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value)
305 struct activate_object *activate = impl_from_IMFActivate(iface);
307 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_w(value));
309 return IMFAttributes_SetString(activate->attributes, key, value);
312 static HRESULT WINAPI activate_object_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size)
314 struct activate_object *activate = impl_from_IMFActivate(iface);
316 TRACE("%p, %s, %p, %d.\n", iface, debugstr_guid(key), buf, size);
318 return IMFAttributes_SetBlob(activate->attributes, key, buf, size);
321 static HRESULT WINAPI activate_object_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown)
323 struct activate_object *activate = impl_from_IMFActivate(iface);
325 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(key), unknown);
327 return IMFAttributes_SetUnknown(activate->attributes, key, unknown);
330 static HRESULT WINAPI activate_object_LockStore(IMFActivate *iface)
332 struct activate_object *activate = impl_from_IMFActivate(iface);
334 TRACE("%p.\n", iface);
336 return IMFAttributes_LockStore(activate->attributes);
339 static HRESULT WINAPI activate_object_UnlockStore(IMFActivate *iface)
341 struct activate_object *activate = impl_from_IMFActivate(iface);
343 TRACE("%p.\n", iface);
345 return IMFAttributes_UnlockStore(activate->attributes);
348 static HRESULT WINAPI activate_object_GetCount(IMFActivate *iface, UINT32 *count)
350 struct activate_object *activate = impl_from_IMFActivate(iface);
352 TRACE("%p, %p.\n", iface, count);
354 return IMFAttributes_GetCount(activate->attributes, count);
357 static HRESULT WINAPI activate_object_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key, PROPVARIANT *value)
359 struct activate_object *activate = impl_from_IMFActivate(iface);
361 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
363 return IMFAttributes_GetItemByIndex(activate->attributes, index, key, value);
366 static HRESULT WINAPI activate_object_CopyAllItems(IMFActivate *iface, IMFAttributes *dest)
368 struct activate_object *activate = impl_from_IMFActivate(iface);
370 TRACE("%p, %p.\n", iface, dest);
372 return IMFAttributes_CopyAllItems(activate->attributes, dest);
375 static HRESULT WINAPI activate_object_ActivateObject(IMFActivate *iface, REFIID riid, void **obj)
377 struct activate_object *activate = impl_from_IMFActivate(iface);
378 IUnknown *object;
379 HRESULT hr;
381 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
383 if (!activate->object)
385 if (FAILED(hr = activate->funcs->create_object((IMFAttributes *)iface, activate->context, &object)))
386 return hr;
388 if (InterlockedCompareExchangePointer((void **)&activate->object, object, NULL))
389 IUnknown_Release(object);
392 return IUnknown_QueryInterface(activate->object, riid, obj);
395 static HRESULT WINAPI activate_object_ShutdownObject(IMFActivate *iface)
397 struct activate_object *activate = impl_from_IMFActivate(iface);
398 IUnknown *object;
400 TRACE("%p.\n", iface);
402 if ((object = InterlockedCompareExchangePointer((void **)&activate->object, NULL, activate->object)))
404 activate->funcs->shutdown_object(activate->context, object);
405 IUnknown_Release(object);
408 return S_OK;
411 static HRESULT WINAPI activate_object_DetachObject(IMFActivate *iface)
413 TRACE("%p.\n", iface);
415 return E_NOTIMPL;
418 static const IMFActivateVtbl activate_object_vtbl =
420 activate_object_QueryInterface,
421 activate_object_AddRef,
422 activate_object_Release,
423 activate_object_GetItem,
424 activate_object_GetItemType,
425 activate_object_CompareItem,
426 activate_object_Compare,
427 activate_object_GetUINT32,
428 activate_object_GetUINT64,
429 activate_object_GetDouble,
430 activate_object_GetGUID,
431 activate_object_GetStringLength,
432 activate_object_GetString,
433 activate_object_GetAllocatedString,
434 activate_object_GetBlobSize,
435 activate_object_GetBlob,
436 activate_object_GetAllocatedBlob,
437 activate_object_GetUnknown,
438 activate_object_SetItem,
439 activate_object_DeleteItem,
440 activate_object_DeleteAllItems,
441 activate_object_SetUINT32,
442 activate_object_SetUINT64,
443 activate_object_SetDouble,
444 activate_object_SetGUID,
445 activate_object_SetString,
446 activate_object_SetBlob,
447 activate_object_SetUnknown,
448 activate_object_LockStore,
449 activate_object_UnlockStore,
450 activate_object_GetCount,
451 activate_object_GetItemByIndex,
452 activate_object_CopyAllItems,
453 activate_object_ActivateObject,
454 activate_object_ShutdownObject,
455 activate_object_DetachObject,
458 HRESULT create_activation_object(void *context, const struct activate_funcs *funcs, IMFActivate **ret)
460 struct activate_object *object;
461 HRESULT hr;
463 if (!(object = calloc(1, sizeof(*object))))
464 return E_OUTOFMEMORY;
466 object->IMFActivate_iface.lpVtbl = &activate_object_vtbl;
467 object->refcount = 1;
468 if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
470 free(object);
471 return hr;
473 object->funcs = funcs;
474 object->context = context;
476 *ret = &object->IMFActivate_iface;
478 return S_OK;
481 struct class_factory
483 IClassFactory IClassFactory_iface;
484 HRESULT (*create_instance)(REFIID riid, void **obj);
487 static inline struct class_factory *impl_from_IClassFactory(IClassFactory *iface)
489 return CONTAINING_RECORD(iface, struct class_factory, IClassFactory_iface);
492 static HRESULT WINAPI class_factory_QueryInterface(IClassFactory *iface, REFIID riid, void **obj)
494 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
496 if (IsEqualGUID(riid, &IID_IClassFactory) ||
497 IsEqualGUID(riid, &IID_IUnknown))
499 *obj = iface;
500 IClassFactory_AddRef(iface);
501 return S_OK;
504 WARN("%s is not supported.\n", debugstr_guid(riid));
505 *obj = NULL;
506 return E_NOINTERFACE;
509 static ULONG WINAPI class_factory_AddRef(IClassFactory *iface)
511 return 2;
514 static ULONG WINAPI class_factory_Release(IClassFactory *iface)
516 return 1;
519 static HRESULT WINAPI class_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **obj)
521 struct class_factory *factory = impl_from_IClassFactory(iface);
523 TRACE("%p, %p, %s, %p.\n", iface, outer, debugstr_guid(riid), obj);
525 if (outer)
527 *obj = NULL;
528 return CLASS_E_NOAGGREGATION;
531 return factory->create_instance(riid, obj);
534 static HRESULT WINAPI class_factory_LockServer(IClassFactory *iface, BOOL dolock)
536 FIXME("%d.\n", dolock);
538 return S_OK;
541 static const IClassFactoryVtbl class_factory_vtbl =
543 class_factory_QueryInterface,
544 class_factory_AddRef,
545 class_factory_Release,
546 class_factory_CreateInstance,
547 class_factory_LockServer,
550 struct file_scheme_handler_result
552 struct list entry;
553 IMFAsyncResult *result;
554 MF_OBJECT_TYPE obj_type;
555 IUnknown *object;
558 struct file_scheme_handler
560 IMFSchemeHandler IMFSchemeHandler_iface;
561 IMFAsyncCallback IMFAsyncCallback_iface;
562 LONG refcount;
563 IMFSourceResolver *resolver;
564 struct list results;
565 CRITICAL_SECTION cs;
568 static struct file_scheme_handler *impl_from_IMFSchemeHandler(IMFSchemeHandler *iface)
570 return CONTAINING_RECORD(iface, struct file_scheme_handler, IMFSchemeHandler_iface);
573 static struct file_scheme_handler *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface)
575 return CONTAINING_RECORD(iface, struct file_scheme_handler, IMFAsyncCallback_iface);
578 static HRESULT WINAPI file_scheme_handler_QueryInterface(IMFSchemeHandler *iface, REFIID riid, void **obj)
580 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
582 if (IsEqualIID(riid, &IID_IMFSchemeHandler) ||
583 IsEqualIID(riid, &IID_IUnknown))
585 *obj = iface;
586 IMFSchemeHandler_AddRef(iface);
587 return S_OK;
590 WARN("Unsupported %s.\n", debugstr_guid(riid));
591 *obj = NULL;
592 return E_NOINTERFACE;
595 static ULONG WINAPI file_scheme_handler_AddRef(IMFSchemeHandler *iface)
597 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
598 ULONG refcount = InterlockedIncrement(&handler->refcount);
600 TRACE("%p, refcount %lu.\n", handler, refcount);
602 return refcount;
605 static ULONG WINAPI file_scheme_handler_Release(IMFSchemeHandler *iface)
607 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
608 ULONG refcount = InterlockedDecrement(&handler->refcount);
609 struct file_scheme_handler_result *result, *next;
611 TRACE("%p, refcount %lu.\n", iface, refcount);
613 if (!refcount)
615 LIST_FOR_EACH_ENTRY_SAFE(result, next, &handler->results, struct file_scheme_handler_result, entry)
617 list_remove(&result->entry);
618 IMFAsyncResult_Release(result->result);
619 if (result->object)
620 IUnknown_Release(result->object);
621 free(result);
623 DeleteCriticalSection(&handler->cs);
624 if (handler->resolver)
625 IMFSourceResolver_Release(handler->resolver);
626 free(handler);
629 return refcount;
632 struct create_object_context
634 IUnknown IUnknown_iface;
635 LONG refcount;
637 IPropertyStore *props;
638 WCHAR *url;
639 DWORD flags;
642 static struct create_object_context *impl_from_IUnknown(IUnknown *iface)
644 return CONTAINING_RECORD(iface, struct create_object_context, IUnknown_iface);
647 static HRESULT WINAPI create_object_context_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
649 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
651 if (IsEqualIID(riid, &IID_IUnknown))
653 *obj = iface;
654 IUnknown_AddRef(iface);
655 return S_OK;
658 WARN("Unsupported %s.\n", debugstr_guid(riid));
659 *obj = NULL;
660 return E_NOINTERFACE;
663 static ULONG WINAPI create_object_context_AddRef(IUnknown *iface)
665 struct create_object_context *context = impl_from_IUnknown(iface);
666 ULONG refcount = InterlockedIncrement(&context->refcount);
668 TRACE("%p, refcount %lu.\n", iface, refcount);
670 return refcount;
673 static ULONG WINAPI create_object_context_Release(IUnknown *iface)
675 struct create_object_context *context = impl_from_IUnknown(iface);
676 ULONG refcount = InterlockedDecrement(&context->refcount);
678 TRACE("%p, refcount %lu.\n", iface, refcount);
680 if (!refcount)
682 if (context->props)
683 IPropertyStore_Release(context->props);
684 free(context->url);
685 free(context);
688 return refcount;
691 static const IUnknownVtbl create_object_context_vtbl =
693 create_object_context_QueryInterface,
694 create_object_context_AddRef,
695 create_object_context_Release,
698 static HRESULT WINAPI file_scheme_handler_BeginCreateObject(IMFSchemeHandler *iface, const WCHAR *url, DWORD flags,
699 IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
701 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
702 struct create_object_context *context;
703 IMFAsyncResult *caller, *item;
704 HRESULT hr;
706 TRACE("%p, %s, %#lx, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
708 if (cancel_cookie)
709 *cancel_cookie = NULL;
711 if (FAILED(hr = MFCreateAsyncResult(NULL, callback, state, &caller)))
712 return hr;
714 if (!(context = malloc(sizeof(*context))))
716 IMFAsyncResult_Release(caller);
717 return E_OUTOFMEMORY;
720 context->IUnknown_iface.lpVtbl = &create_object_context_vtbl;
721 context->refcount = 1;
722 context->props = props;
723 if (context->props)
724 IPropertyStore_AddRef(context->props);
725 context->flags = flags;
726 context->url = wcsdup(url);
727 if (!context->url)
729 IMFAsyncResult_Release(caller);
730 IUnknown_Release(&context->IUnknown_iface);
731 return E_OUTOFMEMORY;
734 hr = MFCreateAsyncResult(&context->IUnknown_iface, &handler->IMFAsyncCallback_iface, (IUnknown *)caller, &item);
735 IUnknown_Release(&context->IUnknown_iface);
736 if (SUCCEEDED(hr))
738 if (SUCCEEDED(hr = MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_IO, item)))
740 if (cancel_cookie)
742 *cancel_cookie = (IUnknown *)caller;
743 IUnknown_AddRef(*cancel_cookie);
747 IMFAsyncResult_Release(item);
749 IMFAsyncResult_Release(caller);
751 return hr;
754 static HRESULT WINAPI file_scheme_handler_EndCreateObject(IMFSchemeHandler *iface, IMFAsyncResult *result,
755 MF_OBJECT_TYPE *obj_type, IUnknown **object)
757 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
758 struct file_scheme_handler_result *found = NULL, *cur;
759 HRESULT hr;
761 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
763 EnterCriticalSection(&handler->cs);
765 LIST_FOR_EACH_ENTRY(cur, &handler->results, struct file_scheme_handler_result, entry)
767 if (result == cur->result)
769 list_remove(&cur->entry);
770 found = cur;
771 break;
775 LeaveCriticalSection(&handler->cs);
777 if (found)
779 *obj_type = found->obj_type;
780 *object = found->object;
781 hr = IMFAsyncResult_GetStatus(found->result);
782 IMFAsyncResult_Release(found->result);
783 free(found);
785 else
787 *obj_type = MF_OBJECT_INVALID;
788 *object = NULL;
789 hr = MF_E_UNEXPECTED;
792 return hr;
795 static HRESULT WINAPI file_scheme_handler_CancelObjectCreation(IMFSchemeHandler *iface, IUnknown *cancel_cookie)
797 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
798 struct file_scheme_handler_result *found = NULL, *cur;
800 TRACE("%p, %p.\n", iface, cancel_cookie);
802 EnterCriticalSection(&handler->cs);
804 LIST_FOR_EACH_ENTRY(cur, &handler->results, struct file_scheme_handler_result, entry)
806 if (cancel_cookie == (IUnknown *)cur->result)
808 list_remove(&cur->entry);
809 found = cur;
810 break;
814 LeaveCriticalSection(&handler->cs);
816 if (found)
818 IMFAsyncResult_Release(found->result);
819 if (found->object)
820 IUnknown_Release(found->object);
821 free(found);
824 return found ? S_OK : MF_E_UNEXPECTED;
827 static const IMFSchemeHandlerVtbl file_scheme_handler_vtbl =
829 file_scheme_handler_QueryInterface,
830 file_scheme_handler_AddRef,
831 file_scheme_handler_Release,
832 file_scheme_handler_BeginCreateObject,
833 file_scheme_handler_EndCreateObject,
834 file_scheme_handler_CancelObjectCreation,
837 static HRESULT WINAPI file_scheme_handler_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
839 if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
840 IsEqualIID(riid, &IID_IUnknown))
842 *obj = iface;
843 IMFAsyncCallback_AddRef(iface);
844 return S_OK;
847 WARN("Unsupported %s.\n", debugstr_guid(riid));
848 *obj = NULL;
849 return E_NOINTERFACE;
852 static ULONG WINAPI file_scheme_handler_callback_AddRef(IMFAsyncCallback *iface)
854 struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
855 return IMFSchemeHandler_AddRef(&handler->IMFSchemeHandler_iface);
858 static ULONG WINAPI file_scheme_handler_callback_Release(IMFAsyncCallback *iface)
860 struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
861 return IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
864 static HRESULT WINAPI file_scheme_handler_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
866 return E_NOTIMPL;
869 static HRESULT file_scheme_handler_get_resolver(struct file_scheme_handler *handler, IMFSourceResolver **resolver)
871 HRESULT hr;
873 if (!handler->resolver)
875 IMFSourceResolver *resolver;
877 if (FAILED(hr = MFCreateSourceResolver(&resolver)))
878 return hr;
880 if (InterlockedCompareExchangePointer((void **)&handler->resolver, resolver, NULL))
881 IMFSourceResolver_Release(resolver);
884 *resolver = handler->resolver;
885 IMFSourceResolver_AddRef(*resolver);
887 return S_OK;
890 static HRESULT WINAPI file_scheme_handler_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
892 static const WCHAR schemeW[] = {'f','i','l','e',':','/','/'};
893 struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
894 struct file_scheme_handler_result *handler_result;
895 MF_OBJECT_TYPE obj_type = MF_OBJECT_INVALID;
896 IUnknown *object = NULL, *context_object;
897 struct create_object_context *context;
898 IMFSourceResolver *resolver;
899 IMFAsyncResult *caller;
900 IMFByteStream *stream;
901 const WCHAR *url;
902 HRESULT hr;
904 caller = (IMFAsyncResult *)IMFAsyncResult_GetStateNoAddRef(result);
906 if (FAILED(hr = IMFAsyncResult_GetObject(result, &context_object)))
908 WARN("Expected context set for callee result.\n");
909 return hr;
912 context = impl_from_IUnknown(context_object);
914 /* Strip from scheme, MFCreateFile() won't be expecting it. */
915 url = context->url;
916 if (!wcsnicmp(context->url, schemeW, ARRAY_SIZE(schemeW)))
917 url += ARRAY_SIZE(schemeW);
919 hr = MFCreateFile(context->flags & MF_RESOLUTION_WRITE ? MF_ACCESSMODE_READWRITE : MF_ACCESSMODE_READ,
920 MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, url, &stream);
921 if (SUCCEEDED(hr))
923 if (context->flags & MF_RESOLUTION_MEDIASOURCE)
925 if (SUCCEEDED(hr = file_scheme_handler_get_resolver(handler, &resolver)))
927 hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, context->url, context->flags,
928 context->props, &obj_type, &object);
929 IMFSourceResolver_Release(resolver);
930 IMFByteStream_Release(stream);
933 else
935 object = (IUnknown *)stream;
936 obj_type = MF_OBJECT_BYTESTREAM;
940 handler_result = malloc(sizeof(*handler_result));
941 if (handler_result)
943 handler_result->result = caller;
944 IMFAsyncResult_AddRef(handler_result->result);
945 handler_result->obj_type = obj_type;
946 handler_result->object = object;
948 EnterCriticalSection(&handler->cs);
949 list_add_tail(&handler->results, &handler_result->entry);
950 LeaveCriticalSection(&handler->cs);
952 else
954 if (object)
955 IUnknown_Release(object);
956 hr = E_OUTOFMEMORY;
959 IUnknown_Release(&context->IUnknown_iface);
961 IMFAsyncResult_SetStatus(caller, hr);
962 MFInvokeCallback(caller);
964 return S_OK;
967 static const IMFAsyncCallbackVtbl file_scheme_handler_callback_vtbl =
969 file_scheme_handler_callback_QueryInterface,
970 file_scheme_handler_callback_AddRef,
971 file_scheme_handler_callback_Release,
972 file_scheme_handler_callback_GetParameters,
973 file_scheme_handler_callback_Invoke,
976 static HRESULT file_scheme_handler_construct(REFIID riid, void **obj)
978 struct file_scheme_handler *handler;
979 HRESULT hr;
981 TRACE("%s, %p.\n", debugstr_guid(riid), obj);
983 if (!(handler = calloc(1, sizeof(*handler))))
984 return E_OUTOFMEMORY;
986 handler->IMFSchemeHandler_iface.lpVtbl = &file_scheme_handler_vtbl;
987 handler->IMFAsyncCallback_iface.lpVtbl = &file_scheme_handler_callback_vtbl;
988 handler->refcount = 1;
989 list_init(&handler->results);
990 InitializeCriticalSection(&handler->cs);
992 hr = IMFSchemeHandler_QueryInterface(&handler->IMFSchemeHandler_iface, riid, obj);
993 IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
995 return hr;
998 static struct class_factory file_scheme_handler_factory = { { &class_factory_vtbl }, file_scheme_handler_construct };
1000 static const struct class_object
1002 const GUID *clsid;
1003 IClassFactory *factory;
1005 class_objects[] =
1007 { &CLSID_FileSchemePlugin, &file_scheme_handler_factory.IClassFactory_iface },
1010 /*******************************************************************************
1011 * DllGetClassObject (mf.@)
1013 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **obj)
1015 unsigned int i;
1017 TRACE("%s, %s, %p.\n", debugstr_guid(rclsid), debugstr_guid(riid), obj);
1019 for (i = 0; i < ARRAY_SIZE(class_objects); ++i)
1021 if (IsEqualGUID(class_objects[i].clsid, rclsid))
1022 return IClassFactory_QueryInterface(class_objects[i].factory, riid, obj);
1025 WARN("%s: class not found.\n", debugstr_guid(rclsid));
1026 return CLASS_E_CLASSNOTAVAILABLE;
1029 static HRESULT prop_string_vector_append(PROPVARIANT *vector, unsigned int *capacity, BOOL unique, const WCHAR *str)
1031 WCHAR *ptrW;
1032 int len, i;
1034 if (unique)
1036 for (i = 0; i < vector->calpwstr.cElems; ++i)
1038 if (!lstrcmpW(vector->calpwstr.pElems[i], str))
1039 return S_OK;
1043 if (!*capacity || *capacity - 1 < vector->calpwstr.cElems)
1045 unsigned int new_count;
1046 WCHAR **ptr;
1048 new_count = *capacity ? *capacity * 2 : 10;
1049 ptr = CoTaskMemRealloc(vector->calpwstr.pElems, new_count * sizeof(*vector->calpwstr.pElems));
1050 if (!ptr)
1051 return E_OUTOFMEMORY;
1052 vector->calpwstr.pElems = ptr;
1053 *capacity = new_count;
1056 len = lstrlenW(str);
1057 if (!(vector->calpwstr.pElems[vector->calpwstr.cElems] = ptrW = CoTaskMemAlloc((len + 1) * sizeof(WCHAR))))
1058 return E_OUTOFMEMORY;
1060 lstrcpyW(ptrW, str);
1061 vector->calpwstr.cElems++;
1063 return S_OK;
1066 static int __cdecl qsort_string_compare(const void *a, const void *b)
1068 const WCHAR *left = *(const WCHAR **)a, *right = *(const WCHAR **)b;
1069 return lstrcmpW(left, right);
1072 static HRESULT mf_get_handler_strings(const WCHAR *path, WCHAR filter, unsigned int maxlen, PROPVARIANT *dst)
1074 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
1075 unsigned int capacity = 0, count;
1076 HRESULT hr = S_OK;
1077 int i, index;
1078 WCHAR *buffW;
1079 DWORD size;
1081 if (!(buffW = calloc(maxlen, sizeof(*buffW))))
1082 return E_OUTOFMEMORY;
1084 memset(dst, 0, sizeof(*dst));
1085 dst->vt = VT_VECTOR | VT_LPWSTR;
1087 for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
1089 HKEY hkey;
1091 if (RegOpenKeyW(hkey_roots[i], path, &hkey))
1092 continue;
1094 index = 0;
1095 size = maxlen;
1096 count = dst->calpwstr.cElems;
1097 while (!RegEnumKeyExW(hkey, index++, buffW, &size, NULL, NULL, NULL, NULL))
1099 if (filter && !wcschr(buffW, filter))
1100 continue;
1102 if (FAILED(hr = prop_string_vector_append(dst, &capacity, i > 0, buffW)))
1103 break;
1104 size = maxlen;
1107 /* Sort last pass results. */
1108 qsort(&dst->calpwstr.pElems[count], dst->calpwstr.cElems - count, sizeof(*dst->calpwstr.pElems),
1109 qsort_string_compare);
1111 RegCloseKey(hkey);
1114 if (FAILED(hr))
1115 PropVariantClear(dst);
1117 free(buffW);
1119 return hr;
1122 /***********************************************************************
1123 * MFGetSupportedMimeTypes (mf.@)
1125 HRESULT WINAPI MFGetSupportedMimeTypes(PROPVARIANT *dst)
1127 unsigned int maxlen;
1129 TRACE("%p.\n", dst);
1131 if (!dst)
1132 return E_POINTER;
1134 /* According to RFC4288 it's 127/127 characters. */
1135 maxlen = 127 /* type */ + 1 /* / */ + 127 /* subtype */ + 1;
1136 return mf_get_handler_strings(L"Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers", '/',
1137 maxlen, dst);
1140 /***********************************************************************
1141 * MFGetSupportedSchemes (mf.@)
1143 HRESULT WINAPI MFGetSupportedSchemes(PROPVARIANT *dst)
1145 TRACE("%p.\n", dst);
1147 if (!dst)
1148 return E_POINTER;
1150 return mf_get_handler_strings(L"Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers", 0, 64, dst);
1153 /***********************************************************************
1154 * MFGetService (mf.@)
1156 HRESULT WINAPI MFGetService(IUnknown *object, REFGUID service, REFIID riid, void **obj)
1158 IMFGetService *gs;
1159 HRESULT hr;
1161 TRACE("(%p, %s, %s, %p)\n", object, debugstr_guid(service), debugstr_guid(riid), obj);
1163 if (!object)
1164 return E_POINTER;
1166 if (FAILED(hr = IUnknown_QueryInterface(object, &IID_IMFGetService, (void **)&gs)))
1167 return hr;
1169 hr = IMFGetService_GetService(gs, service, riid, obj);
1170 IMFGetService_Release(gs);
1171 return hr;
1174 /***********************************************************************
1175 * MFShutdownObject (mf.@)
1177 HRESULT WINAPI MFShutdownObject(IUnknown *object)
1179 IMFShutdown *shutdown;
1181 TRACE("%p.\n", object);
1183 if (object && SUCCEEDED(IUnknown_QueryInterface(object, &IID_IMFShutdown, (void **)&shutdown)))
1185 IMFShutdown_Shutdown(shutdown);
1186 IMFShutdown_Release(shutdown);
1189 return S_OK;
1192 /***********************************************************************
1193 * MFEnumDeviceSources (mf.@)
1195 HRESULT WINAPI MFEnumDeviceSources(IMFAttributes *attributes, IMFActivate ***sources, UINT32 *count)
1197 FIXME("%p, %p, %p.\n", attributes, sources, count);
1199 if (!attributes || !sources || !count)
1200 return E_INVALIDARG;
1202 *count = 0;
1204 return S_OK;
1207 struct simple_type_handler
1209 IMFMediaTypeHandler IMFMediaTypeHandler_iface;
1210 LONG refcount;
1211 IMFMediaType *media_type;
1212 CRITICAL_SECTION cs;
1215 static struct simple_type_handler *impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler *iface)
1217 return CONTAINING_RECORD(iface, struct simple_type_handler, IMFMediaTypeHandler_iface);
1220 static HRESULT WINAPI simple_type_handler_QueryInterface(IMFMediaTypeHandler *iface, REFIID riid, void **obj)
1222 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1224 if (IsEqualIID(riid, &IID_IMFMediaTypeHandler) ||
1225 IsEqualIID(riid, &IID_IUnknown))
1227 *obj = iface;
1228 IMFMediaTypeHandler_AddRef(iface);
1229 return S_OK;
1232 *obj = NULL;
1233 return E_NOINTERFACE;
1236 static ULONG WINAPI simple_type_handler_AddRef(IMFMediaTypeHandler *iface)
1238 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1239 ULONG refcount = InterlockedIncrement(&handler->refcount);
1241 TRACE("%p, refcount %lu.\n", iface, refcount);
1243 return refcount;
1246 static ULONG WINAPI simple_type_handler_Release(IMFMediaTypeHandler *iface)
1248 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1249 ULONG refcount = InterlockedDecrement(&handler->refcount);
1251 TRACE("%p, refcount %lu.\n", iface, refcount);
1253 if (!refcount)
1255 if (handler->media_type)
1256 IMFMediaType_Release(handler->media_type);
1257 DeleteCriticalSection(&handler->cs);
1258 free(handler);
1261 return refcount;
1264 static HRESULT WINAPI simple_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler *iface, IMFMediaType *in_type,
1265 IMFMediaType **out_type)
1267 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1268 DWORD flags = 0;
1269 HRESULT hr;
1271 TRACE("%p, %p, %p.\n", iface, in_type, out_type);
1273 if (out_type)
1274 *out_type = NULL;
1276 EnterCriticalSection(&handler->cs);
1277 if (!handler->media_type)
1278 hr = MF_E_UNEXPECTED;
1279 else
1281 if (SUCCEEDED(hr = IMFMediaType_IsEqual(handler->media_type, in_type, &flags)))
1282 hr = (flags & (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES)) ==
1283 (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES) ? S_OK : E_FAIL;
1285 LeaveCriticalSection(&handler->cs);
1287 return hr;
1290 static HRESULT WINAPI simple_type_handler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count)
1292 TRACE("%p, %p.\n", iface, count);
1294 if (!count)
1295 return E_POINTER;
1297 *count = 1;
1299 return S_OK;
1302 static HRESULT WINAPI simple_type_handler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index,
1303 IMFMediaType **type)
1305 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1307 TRACE("%p, %lu, %p.\n", iface, index, type);
1309 if (index > 0)
1310 return MF_E_NO_MORE_TYPES;
1312 EnterCriticalSection(&handler->cs);
1313 *type = handler->media_type;
1314 if (*type)
1315 IMFMediaType_AddRef(*type);
1316 LeaveCriticalSection(&handler->cs);
1318 return S_OK;
1321 static HRESULT WINAPI simple_type_handler_SetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType *media_type)
1323 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1325 TRACE("%p, %p.\n", iface, media_type);
1327 EnterCriticalSection(&handler->cs);
1328 if (handler->media_type)
1329 IMFMediaType_Release(handler->media_type);
1330 handler->media_type = media_type;
1331 if (handler->media_type)
1332 IMFMediaType_AddRef(handler->media_type);
1333 LeaveCriticalSection(&handler->cs);
1335 return S_OK;
1338 static HRESULT WINAPI simple_type_handler_GetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType **media_type)
1340 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1342 TRACE("%p, %p.\n", iface, media_type);
1344 if (!media_type)
1345 return E_POINTER;
1347 EnterCriticalSection(&handler->cs);
1348 *media_type = handler->media_type;
1349 if (*media_type)
1350 IMFMediaType_AddRef(*media_type);
1351 LeaveCriticalSection(&handler->cs);
1353 return S_OK;
1356 static HRESULT WINAPI simple_type_handler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type)
1358 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1359 HRESULT hr;
1361 TRACE("%p, %p.\n", iface, type);
1363 EnterCriticalSection(&handler->cs);
1364 if (handler->media_type)
1365 hr = IMFMediaType_GetGUID(handler->media_type, &MF_MT_MAJOR_TYPE, type);
1366 else
1367 hr = MF_E_NOT_INITIALIZED;
1368 LeaveCriticalSection(&handler->cs);
1370 return hr;
1373 static const IMFMediaTypeHandlerVtbl simple_type_handler_vtbl =
1375 simple_type_handler_QueryInterface,
1376 simple_type_handler_AddRef,
1377 simple_type_handler_Release,
1378 simple_type_handler_IsMediaTypeSupported,
1379 simple_type_handler_GetMediaTypeCount,
1380 simple_type_handler_GetMediaTypeByIndex,
1381 simple_type_handler_SetCurrentMediaType,
1382 simple_type_handler_GetCurrentMediaType,
1383 simple_type_handler_GetMajorType,
1386 HRESULT WINAPI MFCreateSimpleTypeHandler(IMFMediaTypeHandler **handler)
1388 struct simple_type_handler *object;
1390 TRACE("%p.\n", handler);
1392 if (!(object = calloc(1, sizeof(*object))))
1393 return E_OUTOFMEMORY;
1395 object->IMFMediaTypeHandler_iface.lpVtbl = &simple_type_handler_vtbl;
1396 object->refcount = 1;
1397 InitializeCriticalSection(&object->cs);
1399 *handler = &object->IMFMediaTypeHandler_iface;
1401 return S_OK;
1404 HRESULT WINAPI MFRequireProtectedEnvironment(IMFPresentationDescriptor *pd)
1406 BOOL selected, protected = FALSE;
1407 unsigned int i = 0, value;
1408 IMFStreamDescriptor *sd;
1410 TRACE("%p.\n", pd);
1412 while (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, i++, &selected, &sd)))
1414 value = 0;
1415 protected = SUCCEEDED(IMFStreamDescriptor_GetUINT32(sd, &MF_SD_PROTECTED, &value)) && value;
1416 IMFStreamDescriptor_Release(sd);
1417 if (protected) break;
1420 return protected ? S_OK : S_FALSE;