riched20: Merge the richole object with the text services object.
[wine.git] / dlls / mf / main.c
blobbf7066ad032945a17989639d8912688f3b15043a
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/heap.h"
33 #include "wine/list.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
37 static HINSTANCE mf_instance;
38 extern const GUID CLSID_FileSchemePlugin;
40 struct activate_object
42 IMFActivate IMFActivate_iface;
43 LONG refcount;
44 IMFAttributes *attributes;
45 IUnknown *object;
46 const struct activate_funcs *funcs;
47 void *context;
50 static struct activate_object *impl_from_IMFActivate(IMFActivate *iface)
52 return CONTAINING_RECORD(iface, struct activate_object, IMFActivate_iface);
55 static HRESULT WINAPI activate_object_QueryInterface(IMFActivate *iface, REFIID riid, void **obj)
57 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
59 if (IsEqualIID(riid, &IID_IMFActivate) ||
60 IsEqualIID(riid, &IID_IMFAttributes) ||
61 IsEqualIID(riid, &IID_IUnknown))
63 *obj = iface;
64 IMFActivate_AddRef(iface);
65 return S_OK;
68 WARN("Unsupported %s.\n", debugstr_guid(riid));
69 *obj = NULL;
70 return E_NOINTERFACE;
73 static ULONG WINAPI activate_object_AddRef(IMFActivate *iface)
75 struct activate_object *activate = impl_from_IMFActivate(iface);
76 ULONG refcount = InterlockedIncrement(&activate->refcount);
78 TRACE("%p, refcount %u.\n", iface, refcount);
80 return refcount;
83 static ULONG WINAPI activate_object_Release(IMFActivate *iface)
85 struct activate_object *activate = impl_from_IMFActivate(iface);
86 ULONG refcount = InterlockedDecrement(&activate->refcount);
88 TRACE("%p, refcount %u.\n", iface, refcount);
90 if (!refcount)
92 if (activate->funcs->free_private)
93 activate->funcs->free_private(activate->context);
94 if (activate->object)
95 IUnknown_Release(activate->object);
96 IMFAttributes_Release(activate->attributes);
97 heap_free(activate);
100 return refcount;
103 static HRESULT WINAPI activate_object_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value)
105 struct activate_object *activate = impl_from_IMFActivate(iface);
107 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
109 return IMFAttributes_GetItem(activate->attributes, key, value);
112 static HRESULT WINAPI activate_object_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
114 struct activate_object *activate = impl_from_IMFActivate(iface);
116 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), type);
118 return IMFAttributes_GetItemType(activate->attributes, key, type);
121 static HRESULT WINAPI activate_object_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
123 struct activate_object *activate = impl_from_IMFActivate(iface);
125 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, result);
127 return IMFAttributes_CompareItem(activate->attributes, key, value, result);
130 static HRESULT WINAPI activate_object_Compare(IMFActivate *iface, IMFAttributes *theirs, MF_ATTRIBUTES_MATCH_TYPE type,
131 BOOL *result)
133 struct activate_object *activate = impl_from_IMFActivate(iface);
135 TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
137 return IMFAttributes_Compare(activate->attributes, theirs, type, result);
140 static HRESULT WINAPI activate_object_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value)
142 struct activate_object *activate = impl_from_IMFActivate(iface);
144 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
146 return IMFAttributes_GetUINT32(activate->attributes, key, value);
149 static HRESULT WINAPI activate_object_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value)
151 struct activate_object *activate = impl_from_IMFActivate(iface);
153 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
155 return IMFAttributes_GetUINT64(activate->attributes, key, value);
158 static HRESULT WINAPI activate_object_GetDouble(IMFActivate *iface, REFGUID key, double *value)
160 struct activate_object *activate = impl_from_IMFActivate(iface);
162 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
164 return IMFAttributes_GetDouble(activate->attributes, key, value);
167 static HRESULT WINAPI activate_object_GetGUID(IMFActivate *iface, REFGUID key, GUID *value)
169 struct activate_object *activate = impl_from_IMFActivate(iface);
171 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
173 return IMFAttributes_GetGUID(activate->attributes, key, value);
176 static HRESULT WINAPI activate_object_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length)
178 struct activate_object *activate = impl_from_IMFActivate(iface);
180 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), length);
182 return IMFAttributes_GetStringLength(activate->attributes, key, length);
185 static HRESULT WINAPI activate_object_GetString(IMFActivate *iface, REFGUID key, WCHAR *value,
186 UINT32 size, UINT32 *length)
188 struct activate_object *activate = impl_from_IMFActivate(iface);
190 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_guid(key), value, size, length);
192 return IMFAttributes_GetString(activate->attributes, key, value, size, length);
195 static HRESULT WINAPI activate_object_GetAllocatedString(IMFActivate *iface, REFGUID key,
196 WCHAR **value, UINT32 *length)
198 struct activate_object *activate = impl_from_IMFActivate(iface);
200 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, length);
202 return IMFAttributes_GetAllocatedString(activate->attributes, key, value, length);
205 static HRESULT WINAPI activate_object_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size)
207 struct activate_object *activate = impl_from_IMFActivate(iface);
209 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), size);
211 return IMFAttributes_GetBlobSize(activate->attributes, key, size);
214 static HRESULT WINAPI activate_object_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf,
215 UINT32 bufsize, UINT32 *blobsize)
217 struct activate_object *activate = impl_from_IMFActivate(iface);
219 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_guid(key), buf, bufsize, blobsize);
221 return IMFAttributes_GetBlob(activate->attributes, key, buf, bufsize, blobsize);
224 static HRESULT WINAPI activate_object_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size)
226 struct activate_object *activate = impl_from_IMFActivate(iface);
228 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), buf, size);
230 return IMFAttributes_GetAllocatedBlob(activate->attributes, key, buf, size);
233 static HRESULT WINAPI activate_object_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **ppv)
235 struct activate_object *activate = impl_from_IMFActivate(iface);
237 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(key), debugstr_guid(riid), ppv);
239 return IMFAttributes_GetUnknown(activate->attributes, key, riid, ppv);
242 static HRESULT WINAPI activate_object_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value)
244 struct activate_object *activate = impl_from_IMFActivate(iface);
246 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
248 return IMFAttributes_SetItem(activate->attributes, key, value);
251 static HRESULT WINAPI activate_object_DeleteItem(IMFActivate *iface, REFGUID key)
253 struct activate_object *activate = impl_from_IMFActivate(iface);
255 TRACE("%p, %s.\n", iface, debugstr_guid(key));
257 return IMFAttributes_DeleteItem(activate->attributes, key);
260 static HRESULT WINAPI activate_object_DeleteAllItems(IMFActivate *iface)
262 struct activate_object *activate = impl_from_IMFActivate(iface);
264 TRACE("%p.\n", iface);
266 return IMFAttributes_DeleteAllItems(activate->attributes);
269 static HRESULT WINAPI activate_object_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value)
271 struct activate_object *activate = impl_from_IMFActivate(iface);
273 TRACE("%p, %s, %d.\n", iface, debugstr_guid(key), value);
275 return IMFAttributes_SetUINT32(activate->attributes, key, value);
278 static HRESULT WINAPI activate_object_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value)
280 struct activate_object *activate = impl_from_IMFActivate(iface);
282 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), wine_dbgstr_longlong(value));
284 return IMFAttributes_SetUINT64(activate->attributes, key, value);
287 static HRESULT WINAPI activate_object_SetDouble(IMFActivate *iface, REFGUID key, double value)
289 struct activate_object *activate = impl_from_IMFActivate(iface);
291 TRACE("%p, %s, %f.\n", iface, debugstr_guid(key), value);
293 return IMFAttributes_SetDouble(activate->attributes, key, value);
296 static HRESULT WINAPI activate_object_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value)
298 struct activate_object *activate = impl_from_IMFActivate(iface);
300 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_guid(value));
302 return IMFAttributes_SetGUID(activate->attributes, key, value);
305 static HRESULT WINAPI activate_object_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value)
307 struct activate_object *activate = impl_from_IMFActivate(iface);
309 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_w(value));
311 return IMFAttributes_SetString(activate->attributes, key, value);
314 static HRESULT WINAPI activate_object_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size)
316 struct activate_object *activate = impl_from_IMFActivate(iface);
318 TRACE("%p, %s, %p, %d.\n", iface, debugstr_guid(key), buf, size);
320 return IMFAttributes_SetBlob(activate->attributes, key, buf, size);
323 static HRESULT WINAPI activate_object_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown)
325 struct activate_object *activate = impl_from_IMFActivate(iface);
327 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(key), unknown);
329 return IMFAttributes_SetUnknown(activate->attributes, key, unknown);
332 static HRESULT WINAPI activate_object_LockStore(IMFActivate *iface)
334 struct activate_object *activate = impl_from_IMFActivate(iface);
336 TRACE("%p.\n", iface);
338 return IMFAttributes_LockStore(activate->attributes);
341 static HRESULT WINAPI activate_object_UnlockStore(IMFActivate *iface)
343 struct activate_object *activate = impl_from_IMFActivate(iface);
345 TRACE("%p.\n", iface);
347 return IMFAttributes_UnlockStore(activate->attributes);
350 static HRESULT WINAPI activate_object_GetCount(IMFActivate *iface, UINT32 *count)
352 struct activate_object *activate = impl_from_IMFActivate(iface);
354 TRACE("%p, %p.\n", iface, count);
356 return IMFAttributes_GetCount(activate->attributes, count);
359 static HRESULT WINAPI activate_object_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key, PROPVARIANT *value)
361 struct activate_object *activate = impl_from_IMFActivate(iface);
363 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
365 return IMFAttributes_GetItemByIndex(activate->attributes, index, key, value);
368 static HRESULT WINAPI activate_object_CopyAllItems(IMFActivate *iface, IMFAttributes *dest)
370 struct activate_object *activate = impl_from_IMFActivate(iface);
372 TRACE("%p, %p.\n", iface, dest);
374 return IMFAttributes_CopyAllItems(activate->attributes, dest);
377 static HRESULT WINAPI activate_object_ActivateObject(IMFActivate *iface, REFIID riid, void **obj)
379 struct activate_object *activate = impl_from_IMFActivate(iface);
380 IUnknown *object;
381 HRESULT hr;
383 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
385 if (!activate->object)
387 if (FAILED(hr = activate->funcs->create_object((IMFAttributes *)iface, activate->context, &object)))
388 return hr;
390 if (InterlockedCompareExchangePointer((void **)&activate->object, object, NULL))
391 IUnknown_Release(object);
394 return IUnknown_QueryInterface(activate->object, riid, obj);
397 static HRESULT WINAPI activate_object_ShutdownObject(IMFActivate *iface)
399 struct activate_object *activate = impl_from_IMFActivate(iface);
400 IUnknown *object;
402 TRACE("%p.\n", iface);
404 if ((object = InterlockedCompareExchangePointer((void **)&activate->object, NULL, activate->object)))
406 activate->funcs->shutdown_object(activate->context, object);
407 IUnknown_Release(object);
410 return S_OK;
413 static HRESULT WINAPI activate_object_DetachObject(IMFActivate *iface)
415 TRACE("%p.\n", iface);
417 return E_NOTIMPL;
420 static const IMFActivateVtbl activate_object_vtbl =
422 activate_object_QueryInterface,
423 activate_object_AddRef,
424 activate_object_Release,
425 activate_object_GetItem,
426 activate_object_GetItemType,
427 activate_object_CompareItem,
428 activate_object_Compare,
429 activate_object_GetUINT32,
430 activate_object_GetUINT64,
431 activate_object_GetDouble,
432 activate_object_GetGUID,
433 activate_object_GetStringLength,
434 activate_object_GetString,
435 activate_object_GetAllocatedString,
436 activate_object_GetBlobSize,
437 activate_object_GetBlob,
438 activate_object_GetAllocatedBlob,
439 activate_object_GetUnknown,
440 activate_object_SetItem,
441 activate_object_DeleteItem,
442 activate_object_DeleteAllItems,
443 activate_object_SetUINT32,
444 activate_object_SetUINT64,
445 activate_object_SetDouble,
446 activate_object_SetGUID,
447 activate_object_SetString,
448 activate_object_SetBlob,
449 activate_object_SetUnknown,
450 activate_object_LockStore,
451 activate_object_UnlockStore,
452 activate_object_GetCount,
453 activate_object_GetItemByIndex,
454 activate_object_CopyAllItems,
455 activate_object_ActivateObject,
456 activate_object_ShutdownObject,
457 activate_object_DetachObject,
460 HRESULT create_activation_object(void *context, const struct activate_funcs *funcs, IMFActivate **ret)
462 struct activate_object *object;
463 HRESULT hr;
465 object = heap_alloc_zero(sizeof(*object));
466 if (!object)
467 return E_OUTOFMEMORY;
469 object->IMFActivate_iface.lpVtbl = &activate_object_vtbl;
470 object->refcount = 1;
471 if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
473 heap_free(object);
474 return hr;
476 object->funcs = funcs;
477 object->context = context;
479 *ret = &object->IMFActivate_iface;
481 return S_OK;
484 struct class_factory
486 IClassFactory IClassFactory_iface;
487 HRESULT (*create_instance)(REFIID riid, void **obj);
490 static inline struct class_factory *impl_from_IClassFactory(IClassFactory *iface)
492 return CONTAINING_RECORD(iface, struct class_factory, IClassFactory_iface);
495 static HRESULT WINAPI class_factory_QueryInterface(IClassFactory *iface, REFIID riid, void **obj)
497 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
499 if (IsEqualGUID(riid, &IID_IClassFactory) ||
500 IsEqualGUID(riid, &IID_IUnknown))
502 *obj = iface;
503 IClassFactory_AddRef(iface);
504 return S_OK;
507 WARN("%s is not supported.\n", debugstr_guid(riid));
508 *obj = NULL;
509 return E_NOINTERFACE;
512 static ULONG WINAPI class_factory_AddRef(IClassFactory *iface)
514 return 2;
517 static ULONG WINAPI class_factory_Release(IClassFactory *iface)
519 return 1;
522 static HRESULT WINAPI class_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **obj)
524 struct class_factory *factory = impl_from_IClassFactory(iface);
526 TRACE("%p, %p, %s, %p.\n", iface, outer, debugstr_guid(riid), obj);
528 if (outer)
530 *obj = NULL;
531 return CLASS_E_NOAGGREGATION;
534 return factory->create_instance(riid, obj);
537 static HRESULT WINAPI class_factory_LockServer(IClassFactory *iface, BOOL dolock)
539 FIXME("%d.\n", dolock);
541 return S_OK;
544 static const IClassFactoryVtbl class_factory_vtbl =
546 class_factory_QueryInterface,
547 class_factory_AddRef,
548 class_factory_Release,
549 class_factory_CreateInstance,
550 class_factory_LockServer,
553 struct file_scheme_handler_result
555 struct list entry;
556 IMFAsyncResult *result;
557 MF_OBJECT_TYPE obj_type;
558 IUnknown *object;
561 struct file_scheme_handler
563 IMFSchemeHandler IMFSchemeHandler_iface;
564 IMFAsyncCallback IMFAsyncCallback_iface;
565 LONG refcount;
566 IMFSourceResolver *resolver;
567 struct list results;
568 CRITICAL_SECTION cs;
571 static struct file_scheme_handler *impl_from_IMFSchemeHandler(IMFSchemeHandler *iface)
573 return CONTAINING_RECORD(iface, struct file_scheme_handler, IMFSchemeHandler_iface);
576 static struct file_scheme_handler *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface)
578 return CONTAINING_RECORD(iface, struct file_scheme_handler, IMFAsyncCallback_iface);
581 static HRESULT WINAPI file_scheme_handler_QueryInterface(IMFSchemeHandler *iface, REFIID riid, void **obj)
583 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
585 if (IsEqualIID(riid, &IID_IMFSchemeHandler) ||
586 IsEqualIID(riid, &IID_IUnknown))
588 *obj = iface;
589 IMFSchemeHandler_AddRef(iface);
590 return S_OK;
593 WARN("Unsupported %s.\n", debugstr_guid(riid));
594 *obj = NULL;
595 return E_NOINTERFACE;
598 static ULONG WINAPI file_scheme_handler_AddRef(IMFSchemeHandler *iface)
600 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
601 ULONG refcount = InterlockedIncrement(&handler->refcount);
603 TRACE("%p, refcount %u.\n", handler, refcount);
605 return refcount;
608 static ULONG WINAPI file_scheme_handler_Release(IMFSchemeHandler *iface)
610 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
611 ULONG refcount = InterlockedDecrement(&handler->refcount);
612 struct file_scheme_handler_result *result, *next;
614 TRACE("%p, refcount %u.\n", iface, refcount);
616 if (!refcount)
618 LIST_FOR_EACH_ENTRY_SAFE(result, next, &handler->results, struct file_scheme_handler_result, entry)
620 list_remove(&result->entry);
621 IMFAsyncResult_Release(result->result);
622 if (result->object)
623 IUnknown_Release(result->object);
624 heap_free(result);
626 DeleteCriticalSection(&handler->cs);
627 if (handler->resolver)
628 IMFSourceResolver_Release(handler->resolver);
629 heap_free(handler);
632 return refcount;
635 struct create_object_context
637 IUnknown IUnknown_iface;
638 LONG refcount;
640 IPropertyStore *props;
641 WCHAR *url;
642 DWORD flags;
645 static struct create_object_context *impl_from_IUnknown(IUnknown *iface)
647 return CONTAINING_RECORD(iface, struct create_object_context, IUnknown_iface);
650 static HRESULT WINAPI create_object_context_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
652 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
654 if (IsEqualIID(riid, &IID_IUnknown))
656 *obj = iface;
657 IUnknown_AddRef(iface);
658 return S_OK;
661 WARN("Unsupported %s.\n", debugstr_guid(riid));
662 *obj = NULL;
663 return E_NOINTERFACE;
666 static ULONG WINAPI create_object_context_AddRef(IUnknown *iface)
668 struct create_object_context *context = impl_from_IUnknown(iface);
669 ULONG refcount = InterlockedIncrement(&context->refcount);
671 TRACE("%p, refcount %u.\n", iface, refcount);
673 return refcount;
676 static ULONG WINAPI create_object_context_Release(IUnknown *iface)
678 struct create_object_context *context = impl_from_IUnknown(iface);
679 ULONG refcount = InterlockedDecrement(&context->refcount);
681 TRACE("%p, refcount %u.\n", iface, refcount);
683 if (!refcount)
685 if (context->props)
686 IPropertyStore_Release(context->props);
687 heap_free(context->url);
688 heap_free(context);
691 return refcount;
694 static const IUnknownVtbl create_object_context_vtbl =
696 create_object_context_QueryInterface,
697 create_object_context_AddRef,
698 create_object_context_Release,
701 static WCHAR *heap_strdupW(const WCHAR *str)
703 WCHAR *ret = NULL;
705 if (str)
707 unsigned int size;
709 size = (lstrlenW(str) + 1) * sizeof(WCHAR);
710 ret = heap_alloc(size);
711 if (ret)
712 memcpy(ret, str, size);
715 return ret;
718 static HRESULT WINAPI file_scheme_handler_BeginCreateObject(IMFSchemeHandler *iface, const WCHAR *url, DWORD flags,
719 IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
721 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
722 struct create_object_context *context;
723 IMFAsyncResult *caller, *item;
724 HRESULT hr;
726 TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
728 if (cancel_cookie)
729 *cancel_cookie = NULL;
731 if (FAILED(hr = MFCreateAsyncResult(NULL, callback, state, &caller)))
732 return hr;
734 context = heap_alloc(sizeof(*context));
735 if (!context)
737 IMFAsyncResult_Release(caller);
738 return E_OUTOFMEMORY;
741 context->IUnknown_iface.lpVtbl = &create_object_context_vtbl;
742 context->refcount = 1;
743 context->props = props;
744 if (context->props)
745 IPropertyStore_AddRef(context->props);
746 context->flags = flags;
747 context->url = heap_strdupW(url);
748 if (!context->url)
750 IMFAsyncResult_Release(caller);
751 IUnknown_Release(&context->IUnknown_iface);
752 return E_OUTOFMEMORY;
755 hr = MFCreateAsyncResult(&context->IUnknown_iface, &handler->IMFAsyncCallback_iface, (IUnknown *)caller, &item);
756 IUnknown_Release(&context->IUnknown_iface);
757 if (SUCCEEDED(hr))
759 if (SUCCEEDED(hr = MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_IO, item)))
761 if (cancel_cookie)
763 *cancel_cookie = (IUnknown *)caller;
764 IUnknown_AddRef(*cancel_cookie);
768 IMFAsyncResult_Release(item);
770 IMFAsyncResult_Release(caller);
772 return hr;
775 static HRESULT WINAPI file_scheme_handler_EndCreateObject(IMFSchemeHandler *iface, IMFAsyncResult *result,
776 MF_OBJECT_TYPE *obj_type, IUnknown **object)
778 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
779 struct file_scheme_handler_result *found = NULL, *cur;
780 HRESULT hr;
782 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
784 EnterCriticalSection(&handler->cs);
786 LIST_FOR_EACH_ENTRY(cur, &handler->results, struct file_scheme_handler_result, entry)
788 if (result == cur->result)
790 list_remove(&cur->entry);
791 found = cur;
792 break;
796 LeaveCriticalSection(&handler->cs);
798 if (found)
800 *obj_type = found->obj_type;
801 *object = found->object;
802 hr = IMFAsyncResult_GetStatus(found->result);
803 IMFAsyncResult_Release(found->result);
804 heap_free(found);
806 else
808 *obj_type = MF_OBJECT_INVALID;
809 *object = NULL;
810 hr = MF_E_UNEXPECTED;
813 return hr;
816 static HRESULT WINAPI file_scheme_handler_CancelObjectCreation(IMFSchemeHandler *iface, IUnknown *cancel_cookie)
818 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
819 struct file_scheme_handler_result *found = NULL, *cur;
821 TRACE("%p, %p.\n", iface, cancel_cookie);
823 EnterCriticalSection(&handler->cs);
825 LIST_FOR_EACH_ENTRY(cur, &handler->results, struct file_scheme_handler_result, entry)
827 if (cancel_cookie == (IUnknown *)cur->result)
829 list_remove(&cur->entry);
830 found = cur;
831 break;
835 LeaveCriticalSection(&handler->cs);
837 if (found)
839 IMFAsyncResult_Release(found->result);
840 if (found->object)
841 IUnknown_Release(found->object);
842 heap_free(found);
845 return found ? S_OK : MF_E_UNEXPECTED;
848 static const IMFSchemeHandlerVtbl file_scheme_handler_vtbl =
850 file_scheme_handler_QueryInterface,
851 file_scheme_handler_AddRef,
852 file_scheme_handler_Release,
853 file_scheme_handler_BeginCreateObject,
854 file_scheme_handler_EndCreateObject,
855 file_scheme_handler_CancelObjectCreation,
858 static HRESULT WINAPI file_scheme_handler_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
860 if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
861 IsEqualIID(riid, &IID_IUnknown))
863 *obj = iface;
864 IMFAsyncCallback_AddRef(iface);
865 return S_OK;
868 WARN("Unsupported %s.\n", debugstr_guid(riid));
869 *obj = NULL;
870 return E_NOINTERFACE;
873 static ULONG WINAPI file_scheme_handler_callback_AddRef(IMFAsyncCallback *iface)
875 struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
876 return IMFSchemeHandler_AddRef(&handler->IMFSchemeHandler_iface);
879 static ULONG WINAPI file_scheme_handler_callback_Release(IMFAsyncCallback *iface)
881 struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
882 return IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
885 static HRESULT WINAPI file_scheme_handler_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
887 return E_NOTIMPL;
890 static HRESULT file_scheme_handler_get_resolver(struct file_scheme_handler *handler, IMFSourceResolver **resolver)
892 HRESULT hr;
894 if (!handler->resolver)
896 IMFSourceResolver *resolver;
898 if (FAILED(hr = MFCreateSourceResolver(&resolver)))
899 return hr;
901 if (InterlockedCompareExchangePointer((void **)&handler->resolver, resolver, NULL))
902 IMFSourceResolver_Release(resolver);
905 *resolver = handler->resolver;
906 IMFSourceResolver_AddRef(*resolver);
908 return S_OK;
911 static HRESULT WINAPI file_scheme_handler_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
913 static const WCHAR schemeW[] = {'f','i','l','e',':','/','/'};
914 struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
915 struct file_scheme_handler_result *handler_result;
916 MF_OBJECT_TYPE obj_type = MF_OBJECT_INVALID;
917 IUnknown *object = NULL, *context_object;
918 struct create_object_context *context;
919 IMFSourceResolver *resolver;
920 IMFAsyncResult *caller;
921 IMFByteStream *stream;
922 const WCHAR *url;
923 HRESULT hr;
925 caller = (IMFAsyncResult *)IMFAsyncResult_GetStateNoAddRef(result);
927 if (FAILED(hr = IMFAsyncResult_GetObject(result, &context_object)))
929 WARN("Expected context set for callee result.\n");
930 return hr;
933 context = impl_from_IUnknown(context_object);
935 /* Strip from scheme, MFCreateFile() won't be expecting it. */
936 url = context->url;
937 if (!wcsnicmp(context->url, schemeW, ARRAY_SIZE(schemeW)))
938 url += ARRAY_SIZE(schemeW);
940 hr = MFCreateFile(context->flags & MF_RESOLUTION_WRITE ? MF_ACCESSMODE_READWRITE : MF_ACCESSMODE_READ,
941 MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, url, &stream);
942 if (SUCCEEDED(hr))
944 if (context->flags & MF_RESOLUTION_MEDIASOURCE)
946 if (SUCCEEDED(hr = file_scheme_handler_get_resolver(handler, &resolver)))
948 hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, context->url, context->flags,
949 context->props, &obj_type, &object);
950 IMFSourceResolver_Release(resolver);
951 IMFByteStream_Release(stream);
954 else
956 object = (IUnknown *)stream;
957 obj_type = MF_OBJECT_BYTESTREAM;
961 handler_result = heap_alloc(sizeof(*handler_result));
962 if (handler_result)
964 handler_result->result = caller;
965 IMFAsyncResult_AddRef(handler_result->result);
966 handler_result->obj_type = obj_type;
967 handler_result->object = object;
969 EnterCriticalSection(&handler->cs);
970 list_add_tail(&handler->results, &handler_result->entry);
971 LeaveCriticalSection(&handler->cs);
973 else
975 if (object)
976 IUnknown_Release(object);
977 hr = E_OUTOFMEMORY;
980 IUnknown_Release(&context->IUnknown_iface);
982 IMFAsyncResult_SetStatus(caller, hr);
983 MFInvokeCallback(caller);
985 return S_OK;
988 static const IMFAsyncCallbackVtbl file_scheme_handler_callback_vtbl =
990 file_scheme_handler_callback_QueryInterface,
991 file_scheme_handler_callback_AddRef,
992 file_scheme_handler_callback_Release,
993 file_scheme_handler_callback_GetParameters,
994 file_scheme_handler_callback_Invoke,
997 static HRESULT file_scheme_handler_construct(REFIID riid, void **obj)
999 struct file_scheme_handler *handler;
1000 HRESULT hr;
1002 TRACE("%s, %p.\n", debugstr_guid(riid), obj);
1004 handler = heap_alloc_zero(sizeof(*handler));
1005 if (!handler)
1006 return E_OUTOFMEMORY;
1008 handler->IMFSchemeHandler_iface.lpVtbl = &file_scheme_handler_vtbl;
1009 handler->IMFAsyncCallback_iface.lpVtbl = &file_scheme_handler_callback_vtbl;
1010 handler->refcount = 1;
1011 list_init(&handler->results);
1012 InitializeCriticalSection(&handler->cs);
1014 hr = IMFSchemeHandler_QueryInterface(&handler->IMFSchemeHandler_iface, riid, obj);
1015 IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
1017 return hr;
1020 static struct class_factory file_scheme_handler_factory = { { &class_factory_vtbl }, file_scheme_handler_construct };
1022 static const struct class_object
1024 const GUID *clsid;
1025 IClassFactory *factory;
1027 class_objects[] =
1029 { &CLSID_FileSchemePlugin, &file_scheme_handler_factory.IClassFactory_iface },
1032 /*******************************************************************************
1033 * DllGetClassObject (mf.@)
1035 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **obj)
1037 unsigned int i;
1039 TRACE("%s, %s, %p.\n", debugstr_guid(rclsid), debugstr_guid(riid), obj);
1041 for (i = 0; i < ARRAY_SIZE(class_objects); ++i)
1043 if (IsEqualGUID(class_objects[i].clsid, rclsid))
1044 return IClassFactory_QueryInterface(class_objects[i].factory, riid, obj);
1047 WARN("%s: class not found.\n", debugstr_guid(rclsid));
1048 return CLASS_E_CLASSNOTAVAILABLE;
1051 /******************************************************************
1052 * DllCanUnloadNow (mf.@)
1054 HRESULT WINAPI DllCanUnloadNow(void)
1056 return S_FALSE;
1059 /***********************************************************************
1060 * DllRegisterServer (mf.@)
1062 HRESULT WINAPI DllRegisterServer(void)
1064 return __wine_register_resources( mf_instance );
1067 /***********************************************************************
1068 * DllUnregisterServer (mf.@)
1070 HRESULT WINAPI DllUnregisterServer(void)
1072 return __wine_unregister_resources( mf_instance );
1075 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
1077 switch (reason)
1079 case DLL_PROCESS_ATTACH:
1080 mf_instance = instance;
1081 DisableThreadLibraryCalls(instance);
1082 break;
1085 return TRUE;
1088 static HRESULT prop_string_vector_append(PROPVARIANT *vector, unsigned int *capacity, BOOL unique, const WCHAR *str)
1090 WCHAR *ptrW;
1091 int len, i;
1093 if (unique)
1095 for (i = 0; i < vector->calpwstr.cElems; ++i)
1097 if (!lstrcmpW(vector->calpwstr.pElems[i], str))
1098 return S_OK;
1102 if (!*capacity || *capacity - 1 < vector->calpwstr.cElems)
1104 unsigned int new_count;
1105 WCHAR **ptr;
1107 new_count = *capacity ? *capacity * 2 : 10;
1108 ptr = CoTaskMemRealloc(vector->calpwstr.pElems, new_count * sizeof(*vector->calpwstr.pElems));
1109 if (!ptr)
1110 return E_OUTOFMEMORY;
1111 vector->calpwstr.pElems = ptr;
1112 *capacity = new_count;
1115 len = lstrlenW(str);
1116 if (!(vector->calpwstr.pElems[vector->calpwstr.cElems] = ptrW = CoTaskMemAlloc((len + 1) * sizeof(WCHAR))))
1117 return E_OUTOFMEMORY;
1119 lstrcpyW(ptrW, str);
1120 vector->calpwstr.cElems++;
1122 return S_OK;
1125 static int __cdecl qsort_string_compare(const void *a, const void *b)
1127 const WCHAR *left = *(const WCHAR **)a, *right = *(const WCHAR **)b;
1128 return lstrcmpW(left, right);
1131 static HRESULT mf_get_handler_strings(const WCHAR *path, WCHAR filter, unsigned int maxlen, PROPVARIANT *dst)
1133 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
1134 unsigned int capacity = 0, count, size;
1135 HRESULT hr = S_OK;
1136 int i, index;
1137 WCHAR *buffW;
1139 buffW = heap_calloc(maxlen, sizeof(*buffW));
1140 if (!buffW)
1141 return E_OUTOFMEMORY;
1143 memset(dst, 0, sizeof(*dst));
1144 dst->vt = VT_VECTOR | VT_LPWSTR;
1146 for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
1148 HKEY hkey;
1150 if (RegOpenKeyW(hkey_roots[i], path, &hkey))
1151 continue;
1153 index = 0;
1154 size = maxlen;
1155 count = dst->calpwstr.cElems;
1156 while (!RegEnumKeyExW(hkey, index++, buffW, &size, NULL, NULL, NULL, NULL))
1158 if (filter && !wcschr(buffW, filter))
1159 continue;
1161 if (FAILED(hr = prop_string_vector_append(dst, &capacity, i > 0, buffW)))
1162 break;
1163 size = maxlen;
1166 /* Sort last pass results. */
1167 qsort(&dst->calpwstr.pElems[count], dst->calpwstr.cElems - count, sizeof(*dst->calpwstr.pElems),
1168 qsort_string_compare);
1170 RegCloseKey(hkey);
1173 if (FAILED(hr))
1174 PropVariantClear(dst);
1176 heap_free(buffW);
1178 return hr;
1181 /***********************************************************************
1182 * MFGetSupportedMimeTypes (mf.@)
1184 HRESULT WINAPI MFGetSupportedMimeTypes(PROPVARIANT *dst)
1186 unsigned int maxlen;
1188 TRACE("%p.\n", dst);
1190 if (!dst)
1191 return E_POINTER;
1193 /* According to RFC4288 it's 127/127 characters. */
1194 maxlen = 127 /* type */ + 1 /* / */ + 127 /* subtype */ + 1;
1195 return mf_get_handler_strings(L"Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers", '/',
1196 maxlen, dst);
1199 /***********************************************************************
1200 * MFGetSupportedSchemes (mf.@)
1202 HRESULT WINAPI MFGetSupportedSchemes(PROPVARIANT *dst)
1204 TRACE("%p.\n", dst);
1206 if (!dst)
1207 return E_POINTER;
1209 return mf_get_handler_strings(L"Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers", 0, 64, dst);
1212 /***********************************************************************
1213 * MFGetService (mf.@)
1215 HRESULT WINAPI MFGetService(IUnknown *object, REFGUID service, REFIID riid, void **obj)
1217 IMFGetService *gs;
1218 HRESULT hr;
1220 TRACE("(%p, %s, %s, %p)\n", object, debugstr_guid(service), debugstr_guid(riid), obj);
1222 if (!object)
1223 return E_POINTER;
1225 if (FAILED(hr = IUnknown_QueryInterface(object, &IID_IMFGetService, (void **)&gs)))
1226 return hr;
1228 hr = IMFGetService_GetService(gs, service, riid, obj);
1229 IMFGetService_Release(gs);
1230 return hr;
1233 /***********************************************************************
1234 * MFShutdownObject (mf.@)
1236 HRESULT WINAPI MFShutdownObject(IUnknown *object)
1238 IMFShutdown *shutdown;
1240 TRACE("%p.\n", object);
1242 if (object && SUCCEEDED(IUnknown_QueryInterface(object, &IID_IMFShutdown, (void **)&shutdown)))
1244 IMFShutdown_Shutdown(shutdown);
1245 IMFShutdown_Release(shutdown);
1248 return S_OK;
1251 /***********************************************************************
1252 * MFEnumDeviceSources (mf.@)
1254 HRESULT WINAPI MFEnumDeviceSources(IMFAttributes *attributes, IMFActivate ***sources, UINT32 *count)
1256 FIXME("%p, %p, %p.\n", attributes, sources, count);
1258 if (!attributes || !sources || !count)
1259 return E_INVALIDARG;
1261 *count = 0;
1263 return S_OK;
1266 struct simple_type_handler
1268 IMFMediaTypeHandler IMFMediaTypeHandler_iface;
1269 LONG refcount;
1270 IMFMediaType *media_type;
1271 CRITICAL_SECTION cs;
1274 static struct simple_type_handler *impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler *iface)
1276 return CONTAINING_RECORD(iface, struct simple_type_handler, IMFMediaTypeHandler_iface);
1279 static HRESULT WINAPI simple_type_handler_QueryInterface(IMFMediaTypeHandler *iface, REFIID riid, void **obj)
1281 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1283 if (IsEqualIID(riid, &IID_IMFMediaTypeHandler) ||
1284 IsEqualIID(riid, &IID_IUnknown))
1286 *obj = iface;
1287 IMFMediaTypeHandler_AddRef(iface);
1288 return S_OK;
1291 *obj = NULL;
1292 return E_NOINTERFACE;
1295 static ULONG WINAPI simple_type_handler_AddRef(IMFMediaTypeHandler *iface)
1297 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1298 ULONG refcount = InterlockedIncrement(&handler->refcount);
1300 TRACE("%p, refcount %u.\n", iface, refcount);
1302 return refcount;
1305 static ULONG WINAPI simple_type_handler_Release(IMFMediaTypeHandler *iface)
1307 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1308 ULONG refcount = InterlockedDecrement(&handler->refcount);
1310 TRACE("%p, refcount %u.\n", iface, refcount);
1312 if (!refcount)
1314 if (handler->media_type)
1315 IMFMediaType_Release(handler->media_type);
1316 DeleteCriticalSection(&handler->cs);
1317 heap_free(handler);
1320 return refcount;
1323 static HRESULT WINAPI simple_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler *iface, IMFMediaType *in_type,
1324 IMFMediaType **out_type)
1326 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1327 DWORD flags = 0;
1328 HRESULT hr;
1330 TRACE("%p, %p, %p.\n", iface, in_type, out_type);
1332 if (out_type)
1333 *out_type = NULL;
1335 EnterCriticalSection(&handler->cs);
1336 if (!handler->media_type)
1337 hr = MF_E_UNEXPECTED;
1338 else
1340 if (SUCCEEDED(hr = IMFMediaType_IsEqual(handler->media_type, in_type, &flags)))
1341 hr = (flags & (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES)) ==
1342 (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES) ? S_OK : E_FAIL;
1344 LeaveCriticalSection(&handler->cs);
1346 return hr;
1349 static HRESULT WINAPI simple_type_handler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count)
1351 TRACE("%p, %p.\n", iface, count);
1353 if (!count)
1354 return E_POINTER;
1356 *count = 1;
1358 return S_OK;
1361 static HRESULT WINAPI simple_type_handler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index,
1362 IMFMediaType **type)
1364 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1366 TRACE("%p, %u, %p.\n", iface, index, type);
1368 if (index > 0)
1369 return MF_E_NO_MORE_TYPES;
1371 EnterCriticalSection(&handler->cs);
1372 *type = handler->media_type;
1373 if (*type)
1374 IMFMediaType_AddRef(*type);
1375 LeaveCriticalSection(&handler->cs);
1377 return S_OK;
1380 static HRESULT WINAPI simple_type_handler_SetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType *media_type)
1382 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1384 TRACE("%p, %p.\n", iface, media_type);
1386 EnterCriticalSection(&handler->cs);
1387 if (handler->media_type)
1388 IMFMediaType_Release(handler->media_type);
1389 handler->media_type = media_type;
1390 if (handler->media_type)
1391 IMFMediaType_AddRef(handler->media_type);
1392 LeaveCriticalSection(&handler->cs);
1394 return S_OK;
1397 static HRESULT WINAPI simple_type_handler_GetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType **media_type)
1399 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1401 TRACE("%p, %p.\n", iface, media_type);
1403 if (!media_type)
1404 return E_POINTER;
1406 EnterCriticalSection(&handler->cs);
1407 *media_type = handler->media_type;
1408 if (*media_type)
1409 IMFMediaType_AddRef(*media_type);
1410 LeaveCriticalSection(&handler->cs);
1412 return S_OK;
1415 static HRESULT WINAPI simple_type_handler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type)
1417 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1418 HRESULT hr;
1420 TRACE("%p, %p.\n", iface, type);
1422 EnterCriticalSection(&handler->cs);
1423 if (handler->media_type)
1424 hr = IMFMediaType_GetGUID(handler->media_type, &MF_MT_MAJOR_TYPE, type);
1425 else
1426 hr = MF_E_NOT_INITIALIZED;
1427 LeaveCriticalSection(&handler->cs);
1429 return hr;
1432 static const IMFMediaTypeHandlerVtbl simple_type_handler_vtbl =
1434 simple_type_handler_QueryInterface,
1435 simple_type_handler_AddRef,
1436 simple_type_handler_Release,
1437 simple_type_handler_IsMediaTypeSupported,
1438 simple_type_handler_GetMediaTypeCount,
1439 simple_type_handler_GetMediaTypeByIndex,
1440 simple_type_handler_SetCurrentMediaType,
1441 simple_type_handler_GetCurrentMediaType,
1442 simple_type_handler_GetMajorType,
1445 HRESULT WINAPI MFCreateSimpleTypeHandler(IMFMediaTypeHandler **handler)
1447 struct simple_type_handler *object;
1449 TRACE("%p.\n", handler);
1451 object = heap_alloc_zero(sizeof(*object));
1452 if (!object)
1453 return E_OUTOFMEMORY;
1455 object->IMFMediaTypeHandler_iface.lpVtbl = &simple_type_handler_vtbl;
1456 object->refcount = 1;
1457 InitializeCriticalSection(&object->cs);
1459 *handler = &object->IMFMediaTypeHandler_iface;
1461 return S_OK;