ntdll: Use x18 for the TEB on ARM64.
[wine.git] / dlls / mfplat / main.c
blob7027b4f9516770971eaf49400cb8ced943147251
1 /*
2 * Copyright 2014 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
19 #include <stdarg.h>
20 #include <string.h>
21 #include <math.h>
22 #include <limits.h>
24 #define COBJMACROS
25 #define NONAMELESSUNION
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winreg.h"
32 #include "initguid.h"
33 #include "rtworkq.h"
34 #include "ole2.h"
35 #include "propsys.h"
36 #include "d3d11.h"
37 #include "uuids.h"
39 #include "wine/list.h"
41 #include "mfplat_private.h"
42 #include "mfreadwrite.h"
43 #include "mfmediaengine.h"
44 #include "propvarutil.h"
45 #include "strsafe.h"
46 #undef INITGUID
47 #include "evr.h"
48 /* mfd3d12 guids are not included in mfuuid */
49 #define INITGUID
50 #undef EXTERN_GUID
51 #define EXTERN_GUID DEFINE_GUID
52 #include "initguid.h"
53 #include "mfd3d12.h"
55 #include "bcrypt.h"
56 #include "pathcch.h"
58 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
60 struct local_handler
62 struct list entry;
63 union
65 WCHAR *scheme;
66 struct
68 WCHAR *extension;
69 WCHAR *mime;
70 } bytestream;
71 } u;
72 IMFActivate *activate;
75 static CRITICAL_SECTION local_handlers_section = { NULL, -1, 0, 0, 0, 0 };
77 static struct list local_scheme_handlers = LIST_INIT(local_scheme_handlers);
78 static struct list local_bytestream_handlers = LIST_INIT(local_bytestream_handlers);
80 struct mft_registration
82 struct list entry;
83 IClassFactory *factory;
84 CLSID clsid;
85 GUID category;
86 WCHAR *name;
87 DWORD flags;
88 MFT_REGISTER_TYPE_INFO *input_types;
89 UINT32 input_types_count;
90 MFT_REGISTER_TYPE_INFO *output_types;
91 UINT32 output_types_count;
92 BOOL local;
95 static const char *debugstr_reg_typeinfo(const MFT_REGISTER_TYPE_INFO *info)
97 return info ? wine_dbg_sprintf("%p{%s,%s}", info, debugstr_mf_guid(&info->guidMajorType),
98 debugstr_mf_guid(&info->guidSubtype)) : wine_dbg_sprintf("%p", info);
101 static CRITICAL_SECTION local_mfts_section = { NULL, -1, 0, 0, 0, 0 };
103 static struct list local_mfts = LIST_INIT(local_mfts);
105 struct transform_activate
107 struct attributes attributes;
108 IMFActivate IMFActivate_iface;
109 IClassFactory *factory;
110 IMFTransform *transform;
113 struct system_clock
115 IMFClock IMFClock_iface;
116 LONG refcount;
119 struct system_time_source
121 IMFPresentationTimeSource IMFPresentationTimeSource_iface;
122 IMFClockStateSink IMFClockStateSink_iface;
123 LONG refcount;
124 MFCLOCK_STATE state;
125 IMFClock *clock;
126 LONGLONG start_offset;
127 LONGLONG system_time;
128 LONGLONG clock_time;
129 float rate;
130 int i_rate;
131 CRITICAL_SECTION cs;
134 static void system_time_source_update_clock_time(struct system_time_source *source, LONGLONG system_time)
136 LONGLONG diff = system_time - source->system_time;
137 if (source->i_rate) diff *= source->i_rate;
138 else if (source->rate != 1.0f) diff *= source->rate;
139 source->clock_time += diff;
140 source->system_time = system_time;
143 static struct system_time_source *impl_from_IMFPresentationTimeSource(IMFPresentationTimeSource *iface)
145 return CONTAINING_RECORD(iface, struct system_time_source, IMFPresentationTimeSource_iface);
148 static struct system_time_source *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
150 return CONTAINING_RECORD(iface, struct system_time_source, IMFClockStateSink_iface);
153 static struct system_clock *impl_from_IMFClock(IMFClock *iface)
155 return CONTAINING_RECORD(iface, struct system_clock, IMFClock_iface);
158 static struct transform_activate *impl_from_IMFActivate(IMFActivate *iface)
160 return CONTAINING_RECORD(iface, struct transform_activate, IMFActivate_iface);
163 static HRESULT WINAPI transform_activate_QueryInterface(IMFActivate *iface, REFIID riid, void **out)
165 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
167 if (IsEqualIID(riid, &IID_IMFActivate) ||
168 IsEqualIID(riid, &IID_IMFAttributes) ||
169 IsEqualIID(riid, &IID_IUnknown))
171 *out = iface;
172 IMFActivate_AddRef(iface);
173 return S_OK;
176 WARN("Unsupported %s.\n", debugstr_guid(riid));
177 *out = NULL;
178 return E_NOINTERFACE;
181 static ULONG WINAPI transform_activate_AddRef(IMFActivate *iface)
183 struct transform_activate *activate = impl_from_IMFActivate(iface);
184 ULONG refcount = InterlockedIncrement(&activate->attributes.ref);
186 TRACE("%p, refcount %lu.\n", iface, refcount);
188 return refcount;
191 static ULONG WINAPI transform_activate_Release(IMFActivate *iface)
193 struct transform_activate *activate = impl_from_IMFActivate(iface);
194 ULONG refcount = InterlockedDecrement(&activate->attributes.ref);
196 TRACE("%p, refcount %lu.\n", iface, refcount);
198 if (!refcount)
200 clear_attributes_object(&activate->attributes);
201 if (activate->factory)
202 IClassFactory_Release(activate->factory);
203 if (activate->transform)
204 IMFTransform_Release(activate->transform);
205 free(activate);
208 return refcount;
211 static HRESULT WINAPI transform_activate_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value)
213 struct transform_activate *activate = impl_from_IMFActivate(iface);
215 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
217 return attributes_GetItem(&activate->attributes, key, value);
220 static HRESULT WINAPI transform_activate_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
222 struct transform_activate *activate = impl_from_IMFActivate(iface);
224 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
226 return attributes_GetItemType(&activate->attributes, key, type);
229 static HRESULT WINAPI transform_activate_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value,
230 BOOL *result)
232 struct transform_activate *activate = impl_from_IMFActivate(iface);
234 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
236 return attributes_CompareItem(&activate->attributes, key, value, result);
239 static HRESULT WINAPI transform_activate_Compare(IMFActivate *iface, IMFAttributes *theirs,
240 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
242 struct transform_activate *activate = impl_from_IMFActivate(iface);
244 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
246 return attributes_Compare(&activate->attributes, theirs, match_type, ret);
249 static HRESULT WINAPI transform_activate_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value)
251 struct transform_activate *activate = impl_from_IMFActivate(iface);
253 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
255 return attributes_GetUINT32(&activate->attributes, key, value);
258 static HRESULT WINAPI transform_activate_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value)
260 struct transform_activate *activate = impl_from_IMFActivate(iface);
262 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
264 return attributes_GetUINT64(&activate->attributes, key, value);
267 static HRESULT WINAPI transform_activate_GetDouble(IMFActivate *iface, REFGUID key, double *value)
269 struct transform_activate *activate = impl_from_IMFActivate(iface);
271 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
273 return attributes_GetDouble(&activate->attributes, key, value);
276 static HRESULT WINAPI transform_activate_GetGUID(IMFActivate *iface, REFGUID key, GUID *value)
278 struct transform_activate *activate = impl_from_IMFActivate(iface);
280 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
282 return attributes_GetGUID(&activate->attributes, key, value);
285 static HRESULT WINAPI transform_activate_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length)
287 struct transform_activate *activate = impl_from_IMFActivate(iface);
289 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
291 return attributes_GetStringLength(&activate->attributes, key, length);
294 static HRESULT WINAPI transform_activate_GetString(IMFActivate *iface, REFGUID key, WCHAR *value,
295 UINT32 size, UINT32 *length)
297 struct transform_activate *activate = impl_from_IMFActivate(iface);
299 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
301 return attributes_GetString(&activate->attributes, key, value, size, length);
304 static HRESULT WINAPI transform_activate_GetAllocatedString(IMFActivate *iface, REFGUID key, WCHAR **value,
305 UINT32 *length)
307 struct transform_activate *activate = impl_from_IMFActivate(iface);
309 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
311 return attributes_GetAllocatedString(&activate->attributes, key, value, length);
314 static HRESULT WINAPI transform_activate_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size)
316 struct transform_activate *activate = impl_from_IMFActivate(iface);
318 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
320 return attributes_GetBlobSize(&activate->attributes, key, size);
323 static HRESULT WINAPI transform_activate_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf, UINT32 bufsize,
324 UINT32 *blobsize)
326 struct transform_activate *activate = impl_from_IMFActivate(iface);
328 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
330 return attributes_GetBlob(&activate->attributes, key, buf, bufsize, blobsize);
333 static HRESULT WINAPI transform_activate_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size)
335 struct transform_activate *activate = impl_from_IMFActivate(iface);
337 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
339 return attributes_GetAllocatedBlob(&activate->attributes, key, buf, size);
342 static HRESULT WINAPI transform_activate_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **out)
344 struct transform_activate *activate = impl_from_IMFActivate(iface);
346 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
348 return attributes_GetUnknown(&activate->attributes, key, riid, out);
351 static HRESULT WINAPI transform_activate_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value)
353 struct transform_activate *activate = impl_from_IMFActivate(iface);
355 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
357 return attributes_SetItem(&activate->attributes, key, value);
360 static HRESULT WINAPI transform_activate_DeleteItem(IMFActivate *iface, REFGUID key)
362 struct transform_activate *activate = impl_from_IMFActivate(iface);
364 TRACE("%p, %s.\n", iface, debugstr_attr(key));
366 return attributes_DeleteItem(&activate->attributes, key);
369 static HRESULT WINAPI transform_activate_DeleteAllItems(IMFActivate *iface)
371 struct transform_activate *activate = impl_from_IMFActivate(iface);
373 TRACE("%p.\n", iface);
375 return attributes_DeleteAllItems(&activate->attributes);
378 static HRESULT WINAPI transform_activate_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value)
380 struct transform_activate *activate = impl_from_IMFActivate(iface);
382 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
384 return attributes_SetUINT32(&activate->attributes, key, value);
387 static HRESULT WINAPI transform_activate_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value)
389 struct transform_activate *activate = impl_from_IMFActivate(iface);
391 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
393 return attributes_SetUINT64(&activate->attributes, key, value);
396 static HRESULT WINAPI transform_activate_SetDouble(IMFActivate *iface, REFGUID key, double value)
398 struct transform_activate *activate = impl_from_IMFActivate(iface);
400 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
402 return attributes_SetDouble(&activate->attributes, key, value);
405 static HRESULT WINAPI transform_activate_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value)
407 struct transform_activate *activate = impl_from_IMFActivate(iface);
409 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
411 return attributes_SetGUID(&activate->attributes, key, value);
414 static HRESULT WINAPI transform_activate_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value)
416 struct transform_activate *activate = impl_from_IMFActivate(iface);
418 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
420 return attributes_SetString(&activate->attributes, key, value);
423 static HRESULT WINAPI transform_activate_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size)
425 struct transform_activate *activate = impl_from_IMFActivate(iface);
427 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
429 return attributes_SetBlob(&activate->attributes, key, buf, size);
432 static HRESULT WINAPI transform_activate_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown)
434 struct transform_activate *activate = impl_from_IMFActivate(iface);
436 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
438 return attributes_SetUnknown(&activate->attributes, key, unknown);
441 static HRESULT WINAPI transform_activate_LockStore(IMFActivate *iface)
443 struct transform_activate *activate = impl_from_IMFActivate(iface);
445 TRACE("%p.\n", iface);
447 return attributes_LockStore(&activate->attributes);
450 static HRESULT WINAPI transform_activate_UnlockStore(IMFActivate *iface)
452 struct transform_activate *activate = impl_from_IMFActivate(iface);
454 TRACE("%p.\n", iface);
456 return attributes_UnlockStore(&activate->attributes);
459 static HRESULT WINAPI transform_activate_GetCount(IMFActivate *iface, UINT32 *count)
461 struct transform_activate *activate = impl_from_IMFActivate(iface);
463 TRACE("%p, %p.\n", iface, count);
465 return attributes_GetCount(&activate->attributes, count);
468 static HRESULT WINAPI transform_activate_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key,
469 PROPVARIANT *value)
471 struct transform_activate *activate = impl_from_IMFActivate(iface);
473 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
475 return attributes_GetItemByIndex(&activate->attributes, index, key, value);
478 static HRESULT WINAPI transform_activate_CopyAllItems(IMFActivate *iface, IMFAttributes *dest)
480 struct transform_activate *activate = impl_from_IMFActivate(iface);
482 TRACE("%p, %p.\n", iface, dest);
484 return attributes_CopyAllItems(&activate->attributes, dest);
487 static HRESULT WINAPI transform_activate_ActivateObject(IMFActivate *iface, REFIID riid, void **obj)
489 struct transform_activate *activate = impl_from_IMFActivate(iface);
490 CLSID clsid;
491 HRESULT hr;
493 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
495 EnterCriticalSection(&activate->attributes.cs);
497 if (!activate->transform)
499 if (activate->factory)
501 if (FAILED(hr = IClassFactory_CreateInstance(activate->factory, NULL, &IID_IMFTransform,
502 (void **)&activate->transform)))
504 hr = MF_E_INVALIDREQUEST;
507 else
509 if (SUCCEEDED(hr = attributes_GetGUID(&activate->attributes, &MFT_TRANSFORM_CLSID_Attribute, &clsid)))
511 if (FAILED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform,
512 (void **)&activate->transform)))
514 hr = MF_E_INVALIDREQUEST;
520 if (activate->transform)
521 hr = IMFTransform_QueryInterface(activate->transform, riid, obj);
523 LeaveCriticalSection(&activate->attributes.cs);
525 return hr;
528 static HRESULT WINAPI transform_activate_ShutdownObject(IMFActivate *iface)
530 struct transform_activate *activate = impl_from_IMFActivate(iface);
532 TRACE("%p.\n", iface);
534 EnterCriticalSection(&activate->attributes.cs);
536 if (activate->transform)
538 IMFTransform_Release(activate->transform);
539 activate->transform = NULL;
542 LeaveCriticalSection(&activate->attributes.cs);
544 return S_OK;
547 static HRESULT WINAPI transform_activate_DetachObject(IMFActivate *iface)
549 TRACE("%p.\n", iface);
551 return E_NOTIMPL;
554 static const IMFActivateVtbl transform_activate_vtbl =
556 transform_activate_QueryInterface,
557 transform_activate_AddRef,
558 transform_activate_Release,
559 transform_activate_GetItem,
560 transform_activate_GetItemType,
561 transform_activate_CompareItem,
562 transform_activate_Compare,
563 transform_activate_GetUINT32,
564 transform_activate_GetUINT64,
565 transform_activate_GetDouble,
566 transform_activate_GetGUID,
567 transform_activate_GetStringLength,
568 transform_activate_GetString,
569 transform_activate_GetAllocatedString,
570 transform_activate_GetBlobSize,
571 transform_activate_GetBlob,
572 transform_activate_GetAllocatedBlob,
573 transform_activate_GetUnknown,
574 transform_activate_SetItem,
575 transform_activate_DeleteItem,
576 transform_activate_DeleteAllItems,
577 transform_activate_SetUINT32,
578 transform_activate_SetUINT64,
579 transform_activate_SetDouble,
580 transform_activate_SetGUID,
581 transform_activate_SetString,
582 transform_activate_SetBlob,
583 transform_activate_SetUnknown,
584 transform_activate_LockStore,
585 transform_activate_UnlockStore,
586 transform_activate_GetCount,
587 transform_activate_GetItemByIndex,
588 transform_activate_CopyAllItems,
589 transform_activate_ActivateObject,
590 transform_activate_ShutdownObject,
591 transform_activate_DetachObject,
594 static HRESULT create_transform_activate(IClassFactory *factory, IMFActivate **activate)
596 struct transform_activate *object;
597 HRESULT hr;
599 if (!(object = calloc(1, sizeof(*object))))
600 return E_OUTOFMEMORY;
602 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
604 free(object);
605 return hr;
608 object->IMFActivate_iface.lpVtbl = &transform_activate_vtbl;
609 object->factory = factory;
610 if (object->factory)
611 IClassFactory_AddRef(object->factory);
613 *activate = &object->IMFActivate_iface;
615 return S_OK;
618 HRESULT WINAPI MFCreateTransformActivate(IMFActivate **activate)
620 TRACE("%p.\n", activate);
622 return create_transform_activate(NULL, activate);
625 static const WCHAR transform_keyW[] = L"MediaFoundation\\Transforms";
626 static const WCHAR categories_keyW[] = L"MediaFoundation\\Transforms\\Categories";
628 static const BYTE guid_conv_table[256] =
630 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
631 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
632 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
633 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
634 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
635 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
636 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
639 static WCHAR* guid_to_string(WCHAR *str, REFGUID guid)
641 swprintf(str, 39, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
642 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1],
643 guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5],
644 guid->Data4[6], guid->Data4[7]);
646 return str;
649 static inline BOOL is_valid_hex(WCHAR c)
651 if (!(((c >= '0') && (c <= '9')) ||
652 ((c >= 'a') && (c <= 'f')) ||
653 ((c >= 'A') && (c <= 'F'))))
654 return FALSE;
655 return TRUE;
658 static BOOL GUIDFromString(LPCWSTR s, GUID *id)
660 int i;
662 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
664 id->Data1 = 0;
665 for (i = 0; i < 8; i++)
667 if (!is_valid_hex(s[i])) return FALSE;
668 id->Data1 = (id->Data1 << 4) | guid_conv_table[s[i]];
670 if (s[8]!='-') return FALSE;
672 id->Data2 = 0;
673 for (i = 9; i < 13; i++)
675 if (!is_valid_hex(s[i])) return FALSE;
676 id->Data2 = (id->Data2 << 4) | guid_conv_table[s[i]];
678 if (s[13]!='-') return FALSE;
680 id->Data3 = 0;
681 for (i = 14; i < 18; i++)
683 if (!is_valid_hex(s[i])) return FALSE;
684 id->Data3 = (id->Data3 << 4) | guid_conv_table[s[i]];
686 if (s[18]!='-') return FALSE;
688 for (i = 19; i < 36; i+=2)
690 if (i == 23)
692 if (s[i]!='-') return FALSE;
693 i++;
695 if (!is_valid_hex(s[i]) || !is_valid_hex(s[i+1])) return FALSE;
696 id->Data4[(i-19)/2] = guid_conv_table[s[i]] << 4 | guid_conv_table[s[i+1]];
699 if (!s[36]) return TRUE;
700 return FALSE;
703 static HRESULT register_transform(const CLSID *clsid, const WCHAR *name, UINT32 flags,
704 UINT32 cinput, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
705 const MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
707 HRESULT hr = S_OK;
708 HKEY hclsid = 0;
709 WCHAR buffer[64];
710 WCHAR str[250];
711 UINT8 *blob;
712 UINT32 size;
713 DWORD ret;
715 guid_to_string(buffer, clsid);
716 swprintf(str, ARRAY_SIZE(str), L"%s\\%s", transform_keyW, buffer);
718 if ((ret = RegCreateKeyW(HKEY_CLASSES_ROOT, str, &hclsid)))
719 hr = HRESULT_FROM_WIN32(ret);
721 if (SUCCEEDED(hr))
723 size = (lstrlenW(name) + 1) * sizeof(WCHAR);
724 if ((ret = RegSetValueExW(hclsid, NULL, 0, REG_SZ, (BYTE *)name, size)))
725 hr = HRESULT_FROM_WIN32(ret);
728 if (SUCCEEDED(hr) && cinput && input_types)
730 size = cinput * sizeof(MFT_REGISTER_TYPE_INFO);
731 if ((ret = RegSetValueExW(hclsid, L"InputTypes", 0, REG_BINARY, (BYTE *)input_types, size)))
732 hr = HRESULT_FROM_WIN32(ret);
735 if (SUCCEEDED(hr) && coutput && output_types)
737 size = coutput * sizeof(MFT_REGISTER_TYPE_INFO);
738 if ((ret = RegSetValueExW(hclsid, L"OutputTypes", 0, REG_BINARY, (BYTE *)output_types, size)))
739 hr = HRESULT_FROM_WIN32(ret);
742 if (SUCCEEDED(hr) && attributes)
744 if (SUCCEEDED(hr = MFGetAttributesAsBlobSize(attributes, &size)))
746 if ((blob = malloc(size)))
748 if (SUCCEEDED(hr = MFGetAttributesAsBlob(attributes, blob, size)))
750 if ((ret = RegSetValueExW(hclsid, L"Attributes", 0, REG_BINARY, blob, size)))
751 hr = HRESULT_FROM_WIN32(ret);
753 free(blob);
755 else
756 hr = E_OUTOFMEMORY;
760 if (SUCCEEDED(hr) && flags)
762 if ((ret = RegSetValueExW(hclsid, L"MFTFlags", 0, REG_DWORD, (BYTE *)&flags, sizeof(flags))))
763 hr = HRESULT_FROM_WIN32(ret);
766 RegCloseKey(hclsid);
767 return hr;
770 static HRESULT register_category(CLSID *clsid, GUID *category)
772 HKEY htmp1;
773 WCHAR guid1[64], guid2[64];
774 WCHAR str[350];
776 guid_to_string(guid1, category);
777 guid_to_string(guid2, clsid);
779 swprintf(str, ARRAY_SIZE(str), L"%s\\%s\\%s", categories_keyW, guid1, guid2);
781 if (RegCreateKeyW(HKEY_CLASSES_ROOT, str, &htmp1))
782 return E_FAIL;
784 RegCloseKey(htmp1);
785 return S_OK;
788 /***********************************************************************
789 * MFTRegister (mfplat.@)
791 HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags, UINT32 cinput,
792 MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
793 MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
795 HRESULT hr;
797 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p, %p.\n", debugstr_guid(&clsid), debugstr_guid(&category),
798 debugstr_w(name), flags, cinput, input_types, coutput, output_types, attributes);
800 hr = register_transform(&clsid, name, flags, cinput, input_types, coutput, output_types, attributes);
801 if(FAILED(hr))
802 ERR("Failed to write register transform\n");
804 if (SUCCEEDED(hr))
805 hr = register_category(&clsid, &category);
807 return hr;
810 static void release_mft_registration(struct mft_registration *mft)
812 if (mft->factory)
813 IClassFactory_Release(mft->factory);
814 free(mft->name);
815 free(mft->input_types);
816 free(mft->output_types);
817 free(mft);
820 static HRESULT mft_register_local(IClassFactory *factory, REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
821 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
822 const MFT_REGISTER_TYPE_INFO *output_types)
824 struct mft_registration *mft, *cur, *unreg_mft = NULL;
825 HRESULT hr = S_OK;
827 if (!factory && !clsid)
829 WARN("Can't register without factory or CLSID.\n");
830 return E_FAIL;
833 if (!(mft = calloc(1, sizeof(*mft))))
834 return E_OUTOFMEMORY;
836 mft->factory = factory;
837 if (mft->factory)
838 IClassFactory_AddRef(mft->factory);
839 if (clsid)
840 mft->clsid = *clsid;
841 mft->category = *category;
842 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
843 flags |= MFT_ENUM_FLAG_SYNCMFT;
844 mft->flags = flags;
845 mft->local = TRUE;
846 if (name && !(mft->name = wcsdup(name)))
848 hr = E_OUTOFMEMORY;
849 goto failed;
852 if (input_count && input_types)
854 mft->input_types_count = input_count;
855 if (!(mft->input_types = calloc(mft->input_types_count, sizeof(*input_types))))
857 hr = E_OUTOFMEMORY;
858 goto failed;
860 memcpy(mft->input_types, input_types, mft->input_types_count * sizeof(*input_types));
863 if (output_count && output_types)
865 mft->output_types_count = output_count;
866 if (!(mft->output_types = calloc(mft->output_types_count, sizeof(*output_types))))
868 hr = E_OUTOFMEMORY;
869 goto failed;
871 memcpy(mft->output_types, output_types, mft->output_types_count * sizeof(*output_types));
874 EnterCriticalSection(&local_mfts_section);
876 LIST_FOR_EACH_ENTRY(cur, &local_mfts, struct mft_registration, entry)
878 if (cur->factory == factory)
880 unreg_mft = cur;
881 list_remove(&cur->entry);
882 break;
885 list_add_tail(&local_mfts, &mft->entry);
887 LeaveCriticalSection(&local_mfts_section);
889 if (unreg_mft)
890 release_mft_registration(unreg_mft);
892 failed:
893 if (FAILED(hr))
894 release_mft_registration(mft);
896 return hr;
899 HRESULT WINAPI MFTRegisterLocal(IClassFactory *factory, REFGUID category, LPCWSTR name, UINT32 flags,
900 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
901 const MFT_REGISTER_TYPE_INFO *output_types)
903 TRACE("%p, %s, %s, %#x, %u, %p, %u, %p.\n", factory, debugstr_guid(category), debugstr_w(name), flags, input_count,
904 input_types, output_count, output_types);
906 return mft_register_local(factory, NULL, category, name, flags, input_count, input_types, output_count, output_types);
909 HRESULT WINAPI MFTRegisterLocalByCLSID(REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
910 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
911 const MFT_REGISTER_TYPE_INFO *output_types)
913 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p.\n", debugstr_guid(clsid), debugstr_guid(category), debugstr_w(name), flags,
914 input_count, input_types, output_count, output_types);
916 return mft_register_local(NULL, clsid, category, name, flags, input_count, input_types, output_count, output_types);
919 static HRESULT mft_unregister_local(IClassFactory *factory, REFCLSID clsid)
921 struct mft_registration *cur, *cur2;
922 BOOL unregister_all = !factory && !clsid;
923 struct list unreg;
925 list_init(&unreg);
927 EnterCriticalSection(&local_mfts_section);
929 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &local_mfts, struct mft_registration, entry)
931 if (!unregister_all)
933 if ((factory && cur->factory == factory) || IsEqualCLSID(&cur->clsid, clsid))
935 list_remove(&cur->entry);
936 list_add_tail(&unreg, &cur->entry);
937 break;
940 else
942 list_remove(&cur->entry);
943 list_add_tail(&unreg, &cur->entry);
947 LeaveCriticalSection(&local_mfts_section);
949 if (!unregister_all && list_empty(&unreg))
950 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
952 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &unreg, struct mft_registration, entry)
954 list_remove(&cur->entry);
955 release_mft_registration(cur);
958 return S_OK;
961 HRESULT WINAPI MFTUnregisterLocalByCLSID(CLSID clsid)
963 TRACE("%s.\n", debugstr_guid(&clsid));
965 return mft_unregister_local(NULL, &clsid);
968 HRESULT WINAPI MFTUnregisterLocal(IClassFactory *factory)
970 TRACE("%p.\n", factory);
972 return mft_unregister_local(factory, NULL);
975 MFTIME WINAPI MFGetSystemTime(void)
977 MFTIME mf;
979 GetSystemTimeAsFileTime( (FILETIME*)&mf );
981 return mf;
984 static BOOL mft_is_type_info_match(struct mft_registration *mft, const GUID *category, UINT32 flags,
985 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
986 const MFT_REGISTER_TYPE_INFO *output_type)
988 BOOL matching = TRUE;
989 DWORD model;
990 int i;
992 if (!IsEqualGUID(category, &mft->category))
993 return FALSE;
995 /* Default model is synchronous. */
996 model = mft->flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE);
997 if (!model)
998 model = MFT_ENUM_FLAG_SYNCMFT;
999 if (!(model & flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
1000 return FALSE;
1002 /* These flags should be explicitly enabled. */
1003 if (mft->flags & ~flags & (MFT_ENUM_FLAG_FIELDOFUSE | MFT_ENUM_FLAG_TRANSCODE_ONLY))
1004 return FALSE;
1006 if (flags & MFT_ENUM_FLAG_SORTANDFILTER && !mft->factory && plugin_control
1007 && IMFPluginControl_IsDisabled(plugin_control, MF_Plugin_Type_MFT, &mft->clsid) == S_OK)
1009 return FALSE;
1012 if (input_type)
1014 for (i = 0, matching = FALSE; input_type && i < mft->input_types_count; ++i)
1016 if (!memcmp(&mft->input_types[i], input_type, sizeof(*input_type)))
1018 matching = TRUE;
1019 break;
1024 if (output_type && matching)
1026 for (i = 0, matching = FALSE; i < mft->output_types_count; ++i)
1028 if (!memcmp(&mft->output_types[i], output_type, sizeof(*output_type)))
1030 matching = TRUE;
1031 break;
1036 return matching;
1039 static void mft_get_reg_type_info_internal(const WCHAR *clsidW, const WCHAR *typeW, MFT_REGISTER_TYPE_INFO **type,
1040 UINT32 *count)
1042 HKEY htransform, hfilter;
1043 DWORD reg_type, size;
1045 *type = NULL;
1046 *count = 0;
1048 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1049 return;
1051 if (RegOpenKeyW(htransform, clsidW, &hfilter))
1053 RegCloseKey(htransform);
1054 return;
1057 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, NULL, &size))
1058 goto out;
1060 if (reg_type != REG_BINARY)
1061 goto out;
1063 if (!size || size % sizeof(**type))
1064 goto out;
1066 if (!(*type = malloc(size)))
1067 goto out;
1069 *count = size / sizeof(**type);
1071 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, (BYTE *)*type, &size))
1073 free(*type);
1074 *type = NULL;
1075 *count = 0;
1078 out:
1079 RegCloseKey(hfilter);
1080 RegCloseKey(htransform);
1083 static void mft_get_reg_flags(const WCHAR *clsidW, const WCHAR *nameW, DWORD *flags)
1085 DWORD ret, reg_type, size;
1086 HKEY hroot, hmft;
1088 *flags = 0;
1090 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &hroot))
1091 return;
1093 ret = RegOpenKeyW(hroot, clsidW, &hmft);
1094 RegCloseKey(hroot);
1095 if (ret)
1096 return;
1098 reg_type = 0;
1099 if (!RegQueryValueExW(hmft, nameW, NULL, &reg_type, NULL, &size) && reg_type == REG_DWORD)
1100 RegQueryValueExW(hmft, nameW, NULL, &reg_type, (BYTE *)flags, &size);
1102 RegCloseKey(hmft);
1105 static HRESULT mft_collect_machine_reg(struct list *mfts, const GUID *category, UINT32 flags,
1106 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
1107 const MFT_REGISTER_TYPE_INFO *output_type)
1109 struct mft_registration mft, *cur;
1110 HKEY hcategory, hlist;
1111 WCHAR clsidW[64];
1112 DWORD ret, size;
1113 int index = 0;
1115 if (RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1116 return E_FAIL;
1118 guid_to_string(clsidW, category);
1119 ret = RegOpenKeyW(hcategory, clsidW, &hlist);
1120 RegCloseKey(hcategory);
1121 if (ret)
1122 return E_FAIL;
1124 size = ARRAY_SIZE(clsidW);
1125 while (!RegEnumKeyExW(hlist, index, clsidW, &size, NULL, NULL, NULL, NULL))
1127 memset(&mft, 0, sizeof(mft));
1128 mft.category = *category;
1129 if (!GUIDFromString(clsidW, &mft.clsid))
1130 goto next;
1132 mft_get_reg_flags(clsidW, L"MFTFlags", &mft.flags);
1134 if (output_type)
1135 mft_get_reg_type_info_internal(clsidW, L"OutputTypes", &mft.output_types, &mft.output_types_count);
1137 if (input_type)
1138 mft_get_reg_type_info_internal(clsidW, L"InputTypes", &mft.input_types, &mft.input_types_count);
1140 if (!mft_is_type_info_match(&mft, category, flags, plugin_control, input_type, output_type))
1142 free(mft.input_types);
1143 free(mft.output_types);
1144 goto next;
1147 cur = malloc(sizeof(*cur));
1148 /* Reuse allocated type arrays. */
1149 *cur = mft;
1150 list_add_tail(mfts, &cur->entry);
1152 next:
1153 size = ARRAY_SIZE(clsidW);
1154 index++;
1157 return S_OK;
1160 static BOOL mft_is_preferred(IMFPluginControl *plugin_control, const CLSID *clsid)
1162 CLSID preferred;
1163 WCHAR *selector;
1164 int index = 0;
1166 while (SUCCEEDED(IMFPluginControl_GetPreferredClsidByIndex(plugin_control, MF_Plugin_Type_MFT, index++, &selector,
1167 &preferred)))
1169 CoTaskMemFree(selector);
1171 if (IsEqualGUID(&preferred, clsid))
1172 return TRUE;
1175 return FALSE;
1178 static HRESULT mft_enum(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1179 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1181 IMFPluginControl *plugin_control = NULL;
1182 struct list mfts, mfts_sorted, *result = &mfts;
1183 struct mft_registration *mft, *mft2;
1184 unsigned int obj_count;
1185 HRESULT hr;
1187 *count = 0;
1188 *activate = NULL;
1190 if (!flags)
1191 flags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER;
1193 /* Synchronous processing is default. */
1194 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
1195 flags |= MFT_ENUM_FLAG_SYNCMFT;
1197 if (FAILED(hr = MFGetPluginControl(&plugin_control)))
1199 WARN("Failed to get plugin control instance, hr %#lx.\n", hr);
1200 return hr;
1203 list_init(&mfts);
1205 /* Collect from registry */
1206 mft_collect_machine_reg(&mfts, &category, flags, plugin_control, input_type, output_type);
1208 /* Collect locally registered ones. */
1209 if (flags & MFT_ENUM_FLAG_LOCALMFT)
1211 struct mft_registration *local;
1213 EnterCriticalSection(&local_mfts_section);
1215 LIST_FOR_EACH_ENTRY(local, &local_mfts, struct mft_registration, entry)
1217 if (mft_is_type_info_match(local, &category, flags, plugin_control, input_type, output_type))
1219 mft = calloc(1, sizeof(*mft));
1221 mft->clsid = local->clsid;
1222 mft->factory = local->factory;
1223 if (mft->factory)
1224 IClassFactory_AddRef(mft->factory);
1225 mft->flags = local->flags;
1226 mft->local = local->local;
1228 list_add_tail(&mfts, &mft->entry);
1232 LeaveCriticalSection(&local_mfts_section);
1235 list_init(&mfts_sorted);
1237 if (flags & MFT_ENUM_FLAG_SORTANDFILTER)
1239 /* Local registrations. */
1240 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1242 if (mft->local)
1244 list_remove(&mft->entry);
1245 list_add_tail(&mfts_sorted, &mft->entry);
1249 /* FIXME: Sort by merit value, for the ones that got it. Currently not handled. */
1251 /* Preferred transforms. */
1252 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1254 if (!mft->factory && mft_is_preferred(plugin_control, &mft->clsid))
1256 list_remove(&mft->entry);
1257 list_add_tail(&mfts_sorted, &mft->entry);
1261 /* Append the rest. */
1262 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1264 list_remove(&mft->entry);
1265 list_add_tail(&mfts_sorted, &mft->entry);
1268 result = &mfts_sorted;
1271 IMFPluginControl_Release(plugin_control);
1273 /* Create activation objects from CLSID/IClassFactory. */
1275 obj_count = list_count(result);
1277 if (obj_count)
1279 if (!(*activate = CoTaskMemAlloc(obj_count * sizeof(**activate))))
1280 hr = E_OUTOFMEMORY;
1282 obj_count = 0;
1284 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, result, struct mft_registration, entry)
1286 IMFActivate *mft_activate;
1288 if (*activate)
1290 if (SUCCEEDED(create_transform_activate(mft->factory, &mft_activate)))
1292 (*activate)[obj_count] = mft_activate;
1294 if (mft->local)
1296 IMFActivate_SetUINT32(mft_activate, &MFT_PROCESS_LOCAL_Attribute, 1);
1298 else
1300 if (mft->name)
1301 IMFActivate_SetString(mft_activate, &MFT_FRIENDLY_NAME_Attribute, mft->name);
1302 if (mft->input_types)
1303 IMFActivate_SetBlob(mft_activate, &MFT_INPUT_TYPES_Attributes, (const UINT8 *)mft->input_types,
1304 sizeof(*mft->input_types) * mft->input_types_count);
1305 if (mft->output_types)
1306 IMFActivate_SetBlob(mft_activate, &MFT_OUTPUT_TYPES_Attributes, (const UINT8 *)mft->output_types,
1307 sizeof(*mft->output_types) * mft->output_types_count);
1310 if (!mft->factory)
1311 IMFActivate_SetGUID(mft_activate, &MFT_TRANSFORM_CLSID_Attribute, &mft->clsid);
1313 IMFActivate_SetUINT32(mft_activate, &MF_TRANSFORM_FLAGS_Attribute, mft->flags);
1314 IMFActivate_SetGUID(mft_activate, &MF_TRANSFORM_CATEGORY_Attribute, &mft->category);
1316 obj_count++;
1320 list_remove(&mft->entry);
1321 release_mft_registration(mft);
1325 if (!obj_count)
1327 CoTaskMemFree(*activate);
1328 *activate = NULL;
1330 *count = obj_count;
1332 return hr;
1335 /***********************************************************************
1336 * MFTEnum (mfplat.@)
1338 HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type,
1339 MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, CLSID **clsids, UINT32 *count)
1341 struct mft_registration *mft, *mft2;
1342 unsigned int mft_count;
1343 struct list mfts;
1344 HRESULT hr;
1346 TRACE("%s, %#x, %s, %s, %p, %p, %p.\n", debugstr_mf_guid(&category), flags, debugstr_reg_typeinfo(input_type),
1347 debugstr_reg_typeinfo(output_type), attributes, clsids, count);
1349 if (!clsids || !count)
1350 return E_INVALIDARG;
1352 *count = 0;
1353 *clsids = NULL;
1355 list_init(&mfts);
1357 if (FAILED(hr = mft_collect_machine_reg(&mfts, &category, MFT_ENUM_FLAG_SYNCMFT, NULL, input_type, output_type)))
1358 return hr;
1360 mft_count = list_count(&mfts);
1362 if (mft_count)
1364 if (!(*clsids = CoTaskMemAlloc(mft_count * sizeof(**clsids))))
1365 hr = E_OUTOFMEMORY;
1367 mft_count = 0;
1368 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1370 if (*clsids)
1371 (*clsids)[mft_count++] = mft->clsid;
1372 list_remove(&mft->entry);
1373 release_mft_registration(mft);
1377 if (!mft_count)
1379 CoTaskMemFree(*clsids);
1380 *clsids = NULL;
1382 *count = mft_count;
1384 return hr;
1387 /***********************************************************************
1388 * MFTEnumEx (mfplat.@)
1390 HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1391 const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *count)
1393 TRACE("%s, %#x, %s, %s, %p, %p.\n", debugstr_mf_guid(&category), flags, debugstr_reg_typeinfo(input_type),
1394 debugstr_reg_typeinfo(output_type), activate, count);
1396 return mft_enum(category, flags, input_type, output_type, NULL, activate, count);
1399 /***********************************************************************
1400 * MFTEnum2 (mfplat.@)
1402 HRESULT WINAPI MFTEnum2(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1403 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1405 TRACE("%s, %#x, %s, %s, %p, %p, %p.\n", debugstr_mf_guid(&category), flags, debugstr_reg_typeinfo(input_type),
1406 debugstr_reg_typeinfo(output_type), attributes, activate, count);
1408 if (attributes)
1409 FIXME("Ignoring attributes.\n");
1411 return mft_enum(category, flags, input_type, output_type, attributes, activate, count);
1414 /***********************************************************************
1415 * MFTUnregister (mfplat.@)
1417 HRESULT WINAPI MFTUnregister(CLSID clsid)
1419 WCHAR buffer[64], category[MAX_PATH];
1420 HKEY htransform, hcategory, htmp;
1421 DWORD size = MAX_PATH;
1422 DWORD index = 0;
1424 TRACE("(%s)\n", debugstr_guid(&clsid));
1426 guid_to_string(buffer, &clsid);
1428 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1430 RegDeleteKeyW(htransform, buffer);
1431 RegCloseKey(htransform);
1434 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1436 while (RegEnumKeyExW(hcategory, index, category, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
1438 if (!RegOpenKeyW(hcategory, category, &htmp))
1440 RegDeleteKeyW(htmp, buffer);
1441 RegCloseKey(htmp);
1443 size = MAX_PATH;
1444 index++;
1446 RegCloseKey(hcategory);
1449 return S_OK;
1452 static HRESULT mft_get_name(HKEY hkey, WCHAR **name)
1454 DWORD size;
1456 if (!name)
1457 return S_OK;
1459 *name = NULL;
1461 if (!RegQueryValueExW(hkey, NULL, NULL, NULL, NULL, &size))
1463 if (!(*name = CoTaskMemAlloc(size)))
1464 return E_OUTOFMEMORY;
1466 RegQueryValueExW(hkey, NULL, NULL, NULL, (BYTE *)*name, &size);
1469 return S_OK;
1472 static HRESULT mft_get_reg_type_info(const WCHAR *clsid, const WCHAR *key, MFT_REGISTER_TYPE_INFO **ret_types,
1473 UINT32 *ret_count)
1475 MFT_REGISTER_TYPE_INFO *types = NULL;
1476 UINT32 count = 0;
1478 if (!ret_types)
1479 return S_OK;
1481 mft_get_reg_type_info_internal(clsid, key, &types, &count);
1482 if (count)
1484 if (!(*ret_types = CoTaskMemAlloc(count * sizeof(**ret_types))))
1486 free(types);
1487 return E_OUTOFMEMORY;
1490 memcpy(*ret_types, types, count * sizeof(**ret_types));
1491 *ret_count = count;
1494 free(types);
1496 return S_OK;
1499 static HRESULT mft_get_attributes(HKEY hkey, IMFAttributes **ret)
1501 IMFAttributes *attributes;
1502 UINT8 *blob;
1503 DWORD size;
1504 HRESULT hr;
1506 if (!ret)
1507 return S_OK;
1509 if (FAILED(hr = MFCreateAttributes(&attributes, 0)))
1510 return hr;
1512 if (!RegQueryValueExW(hkey, L"Attributes", NULL, NULL, NULL, &size) && size)
1514 if (!(blob = malloc(size)))
1516 IMFAttributes_Release(attributes);
1517 return E_OUTOFMEMORY;
1520 if (!RegQueryValueExW(hkey, L"Attributes", NULL, NULL, blob, &size))
1522 if (FAILED(hr = MFInitAttributesFromBlob(attributes, blob, size)))
1523 WARN("Failed to initialize attributes, hr %#lx.\n", hr);
1526 free(blob);
1529 if (SUCCEEDED(hr))
1531 *ret = attributes;
1532 IMFAttributes_AddRef(*ret);
1535 IMFAttributes_Release(attributes);
1537 return hr;
1540 /***********************************************************************
1541 * MFTGetInfo (mfplat.@)
1543 HRESULT WINAPI MFTGetInfo(CLSID clsid, WCHAR **name, MFT_REGISTER_TYPE_INFO **input_types,
1544 UINT32 *input_types_count, MFT_REGISTER_TYPE_INFO **output_types, UINT32 *output_types_count,
1545 IMFAttributes **attributes)
1547 HRESULT hr = S_OK;
1548 WCHAR clsidW[64];
1549 HKEY hroot, hmft;
1550 DWORD ret;
1552 TRACE("%s, %p, %p, %p, %p, %p, %p.\n", debugstr_guid(&clsid), name, input_types,
1553 input_types_count, output_types, output_types_count, attributes);
1555 guid_to_string(clsidW, &clsid);
1557 if ((ret = RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &hroot)))
1558 return HRESULT_FROM_WIN32(ret);
1560 ret = RegOpenKeyW(hroot, clsidW, &hmft);
1561 RegCloseKey(hroot);
1562 if (ret)
1563 return HRESULT_FROM_WIN32(ret);
1565 if (input_types_count)
1566 *input_types_count = 0;
1568 if (output_types_count)
1569 *output_types_count = 0;
1571 hr = mft_get_name(hmft, name);
1573 if (SUCCEEDED(hr))
1574 hr = mft_get_reg_type_info(clsidW, L"InputTypes", input_types, input_types_count);
1576 if (SUCCEEDED(hr))
1577 hr = mft_get_reg_type_info(clsidW, L"OutputTypes", output_types, output_types_count);
1579 if (SUCCEEDED(hr))
1580 hr = mft_get_attributes(hmft, attributes);
1582 RegCloseKey(hmft);
1584 return hr;
1587 /***********************************************************************
1588 * MFStartup (mfplat.@)
1590 HRESULT WINAPI MFStartup(ULONG version, DWORD flags)
1592 #define MF_VERSION_XP MAKELONG( MF_API_VERSION, 1 )
1593 #define MF_VERSION_WIN7 MAKELONG( MF_API_VERSION, 2 )
1595 TRACE("%#lx, %#lx.\n", version, flags);
1597 if (version != MF_VERSION_XP && version != MF_VERSION_WIN7)
1598 return MF_E_BAD_STARTUP_VERSION;
1600 RtwqStartup();
1602 return S_OK;
1605 /***********************************************************************
1606 * MFShutdown (mfplat.@)
1608 HRESULT WINAPI MFShutdown(void)
1610 TRACE("\n");
1612 RtwqShutdown();
1614 return S_OK;
1617 /***********************************************************************
1618 * MFCopyImage (mfplat.@)
1620 HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines)
1622 TRACE("%p, %ld, %p, %ld, %lu, %lu.\n", dest, deststride, src, srcstride, width, lines);
1624 while (lines--)
1626 memcpy(dest, src, width);
1627 dest += deststride;
1628 src += srcstride;
1631 return S_OK;
1634 struct guid_def
1636 const GUID *guid;
1637 const char *name;
1640 static int __cdecl debug_compare_guid(const void *a, const void *b)
1642 const GUID *guid = a;
1643 const struct guid_def *guid_def = b;
1644 return memcmp(guid, guid_def->guid, sizeof(*guid));
1647 const char *debugstr_attr(const GUID *guid)
1649 static const struct guid_def guid_defs[] =
1651 #define X(g) { &(g), #g }
1652 #define MF_READER_WRITER_D3D_MANAGER MF_SOURCE_READER_D3D_MANAGER
1653 X(MF_READWRITE_MMCSS_CLASS),
1654 X(MF_TOPONODE_MARKIN_HERE),
1655 X(MF_MT_H264_SUPPORTED_SYNC_FRAME_TYPES),
1656 X(MF_TOPONODE_MARKOUT_HERE),
1657 X(EVRConfig_ForceBob),
1658 X(MF_TOPONODE_DECODER),
1659 X(EVRConfig_AllowDropToBob),
1660 X(MF_TOPOLOGY_PROJECTSTART),
1661 X(EVRConfig_ForceThrottle),
1662 X(MF_VIDEO_MAX_MB_PER_SEC),
1663 X(MF_TOPOLOGY_PROJECTSTOP),
1664 X(MF_SINK_WRITER_ENCODER_CONFIG),
1665 X(EVRConfig_AllowDropToThrottle),
1666 X(MF_TOPOLOGY_NO_MARKIN_MARKOUT),
1667 X(EVRConfig_ForceHalfInterlace),
1668 X(EVRConfig_AllowDropToHalfInterlace),
1669 X(EVRConfig_ForceScaling),
1670 X(MF_MT_H264_CAPABILITIES),
1671 X(EVRConfig_AllowScaling),
1672 X(MF_SOURCE_READER_ENABLE_TRANSCODE_ONLY_TRANSFORMS),
1673 X(MFT_PREFERRED_ENCODER_PROFILE),
1674 X(EVRConfig_ForceBatching),
1675 X(EVRConfig_AllowBatching),
1676 X(MF_TOPOLOGY_DYNAMIC_CHANGE_NOT_ALLOWED),
1677 X(MF_MT_VIDEO_PROFILE),
1678 X(MF_MT_DV_AAUX_CTRL_PACK_1),
1679 X(MF_MT_ALPHA_MODE),
1680 X(MF_MT_MPEG2_TIMECODE),
1681 X(MF_PMP_SERVER_CONTEXT),
1682 X(MF_TRANSCODE_TOPOLOGYMODE),
1683 X(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE),
1684 X(MF_MEDIA_ENGINE_TRACK_ID),
1685 X(MFTranscodeContainerType_MP3),
1686 X(MF_MT_CUSTOM_VIDEO_PRIMARIES),
1687 X(MF_MT_TIMESTAMP_CAN_BE_DTS),
1688 X(MFT_CODEC_MERIT_Attribute),
1689 X(MF_TOPOLOGY_PLAYBACK_MAX_DIMS),
1690 X(MF_XVP_DISABLE_FRC),
1691 X(MF_LOW_LATENCY),
1692 X(MF_TRANSCODE_ADJUST_PROFILE),
1693 X(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS),
1694 X(MF_MT_MPEG2_FLAGS),
1695 X(MF_MEDIA_ENGINE_AUDIO_CATEGORY),
1696 X(MF_MT_PIXEL_ASPECT_RATIO),
1697 X(MF_VIDEO_PROCESSOR_ALGORITHM),
1698 X(MF_TOPOLOGY_ENABLE_XVP_FOR_PLAYBACK),
1699 X(MFT_CONNECTED_STREAM_ATTRIBUTE),
1700 X(MF_MT_REALTIME_CONTENT),
1701 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_FLAGS),
1702 X(MF_MT_WRAPPED_TYPE),
1703 X(MF_MT_DRM_FLAGS),
1704 X(MF_MT_AVG_BITRATE),
1705 X(MF_MT_DECODER_USE_MAX_RESOLUTION),
1706 X(MF_MT_MAX_LUMINANCE_LEVEL),
1707 X(MFT_CONNECTED_TO_HW_STREAM),
1708 X(MF_SA_D3D_AWARE),
1709 X(MF_XVP_SAMPLE_LOCK_TIMEOUT),
1710 X(MF_MT_MAX_KEYFRAME_SPACING),
1711 X(MFT_TRANSFORM_CLSID_Attribute),
1712 X(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING),
1713 X(MF_MT_AM_FORMAT_TYPE),
1714 X(MF_SESSION_APPROX_EVENT_OCCURRENCE_TIME),
1715 X(MF_MEDIA_ENGINE_SYNCHRONOUS_CLOSE),
1716 X(MF_MT_H264_MAX_MB_PER_SEC),
1717 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_MAX_BUFFERS),
1718 X(MF_MT_AUDIO_BLOCK_ALIGNMENT),
1719 X(MF_PD_PMPHOST_CONTEXT),
1720 X(MF_PD_APP_CONTEXT),
1721 X(MF_PD_DURATION),
1722 X(MF_PD_TOTAL_FILE_SIZE),
1723 X(MF_PD_AUDIO_ENCODING_BITRATE),
1724 X(MF_PD_VIDEO_ENCODING_BITRATE),
1725 X(MFSampleExtension_TargetGlobalLuminance),
1726 X(MF_PD_MIME_TYPE),
1727 X(MF_MT_H264_SUPPORTED_SLICE_MODES),
1728 X(MF_PD_LAST_MODIFIED_TIME),
1729 X(VIDEO_ZOOM_RECT),
1730 X(MF_PD_PLAYBACK_ELEMENT_ID),
1731 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE9),
1732 X(MF_MT_ALL_SAMPLES_INDEPENDENT),
1733 X(MF_SA_D3D12_CLEAR_VALUE),
1734 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER),
1735 X(MF_PD_PREFERRED_LANGUAGE),
1736 X(MF_PD_PLAYBACK_BOUNDARY_TIME),
1737 X(MF_MEDIA_ENGINE_TELEMETRY_APPLICATION_ID),
1738 X(MF_ACTIVATE_MFT_LOCKED),
1739 X(MFTranscodeContainerType_WAVE),
1740 X(MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT),
1741 X(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING),
1742 X(MF_MT_FRAME_SIZE),
1743 X(MF_MT_H264_SIMULCAST_SUPPORT),
1744 X(MF_SINK_WRITER_ASYNC_CALLBACK),
1745 X(MF_TOPOLOGY_START_TIME_ON_PRESENTATION_SWITCH),
1746 X(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER),
1747 X(MF_TRANSCODE_CONTAINERTYPE),
1748 X(MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY),
1749 X(MF_MT_FRAME_RATE_RANGE_MAX),
1750 X(MF_MT_PALETTE),
1751 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_PROVIDER_DEVICE_ID),
1752 X(MF_TOPOLOGY_STATIC_PLAYBACK_OPTIMIZATIONS),
1753 X(MF_SA_D3D11_USAGE),
1754 X(MF_MEDIA_ENGINE_NEEDKEY_CALLBACK),
1755 X(MF_MT_GEOMETRIC_APERTURE),
1756 X(MF_MT_ORIGINAL_WAVE_FORMAT_TAG),
1757 X(MF_MT_DV_AAUX_SRC_PACK_1),
1758 X(MF_MEDIA_ENGINE_STREAM_CONTAINS_ALPHA_CHANNEL),
1759 X(MF_MEDIA_ENGINE_MEDIA_PLAYER_MODE),
1760 X(MF_MEDIA_ENGINE_EXTENSION),
1761 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS),
1762 X(MF_MT_DEFAULT_STRIDE),
1763 X(MF_MT_ARBITRARY_FORMAT),
1764 X(MF_TRANSFORM_CATEGORY_Attribute),
1765 X(MF_MT_MPEG2_HDCP),
1766 X(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
1767 X(MF_MT_SPATIAL_AUDIO_MAX_DYNAMIC_OBJECTS),
1768 X(MF_MT_DECODER_MAX_DPB_COUNT),
1769 X(MFSampleExtension_ForwardedDecodeUnits),
1770 X(MF_SA_D3D11_SHARED_WITHOUT_MUTEX),
1771 X(MF_MT_DV_AAUX_CTRL_PACK_0),
1772 X(MF_MT_YUV_MATRIX),
1773 X(MF_EVENT_SOURCE_TOPOLOGY_CANCELED),
1774 X(MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY),
1775 X(MF_MT_MAX_FRAME_AVERAGE_LUMINANCE_LEVEL),
1776 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID),
1777 X(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME),
1778 X(MF_MT_VIDEO_ROTATION),
1779 X(MFTranscodeContainerType_MPEG4),
1780 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_SYMBOLIC_LINK),
1781 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE11),
1782 X(MF_MT_USER_DATA),
1783 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID),
1784 X(MF_MT_MIN_MASTERING_LUMINANCE),
1785 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE),
1786 X(MF_SA_REQUIRED_SAMPLE_COUNT),
1787 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS),
1788 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID),
1789 X(MF_EVENT_STREAM_METADATA_SYSTEMID),
1790 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE),
1791 X(MF_MT_AUDIO_CHANNEL_MASK),
1792 X(MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN),
1793 X(MF_READWRITE_DISABLE_CONVERTERS),
1794 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE_EDGE),
1795 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS),
1796 X(MF_SA_D3D12_HEAP_FLAGS),
1797 X(MF_MT_MINIMUM_DISPLAY_APERTURE),
1798 X(MFSampleExtension_Token),
1799 X(MFTranscodeContainerType_3GP),
1800 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_CATEGORY),
1801 X(MF_D3D12_SYNCHRONIZATION_OBJECT),
1802 X(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
1803 X(MF_TRANSFORM_ASYNC_UNLOCK),
1804 X(MF_DISABLE_FRAME_CORRUPTION_INFO),
1805 X(MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES),
1806 X(MFTranscodeContainerType_ASF),
1807 X(MF_MT_VIDEO_NO_FRAME_ORDERING),
1808 X(MF_MEDIA_ENGINE_PLAYBACK_VISUAL),
1809 X(MF_MT_VIDEO_CHROMA_SITING),
1810 X(MF_AUDIO_RENDERER_ATTRIBUTE_STREAM_CATEGORY),
1811 X(MF_SA_BUFFERS_PER_SAMPLE),
1812 X(MFSampleExtension_3DVideo_SampleFormat),
1813 X(MF_MT_H264_RESOLUTION_SCALING),
1814 X(MF_MT_VIDEO_LEVEL),
1815 X(MF_SA_D3D12_HEAP_TYPE),
1816 X(MF_SAMPLEGRABBERSINK_SAMPLE_TIME_OFFSET),
1817 X(MF_MT_SAMPLE_SIZE),
1818 X(MF_MT_AAC_PAYLOAD_TYPE),
1819 X(MF_TOPOLOGY_PLAYBACK_FRAMERATE),
1820 X(MF_SOURCE_READER_D3D11_BIND_FLAGS),
1821 X(MF_TRANSCODE_ENCODINGPROFILE),
1822 X(MF_MT_AUDIO_FOLDDOWN_MATRIX),
1823 X(MF_MT_AUDIO_WMADRC_PEAKREF),
1824 X(MFTranscodeContainerType_ADTS),
1825 X(MF_MT_AUDIO_WMADRC_PEAKTARGET),
1826 X(MF_TRANSFORM_FLAGS_Attribute),
1827 X(MF_MT_H264_SUPPORTED_RATE_CONTROL_MODES),
1828 X(MF_PD_SAMI_STYLELIST),
1829 X(MF_MT_AUDIO_WMADRC_AVGREF),
1830 X(MF_MT_AUDIO_BITS_PER_SAMPLE),
1831 X(MF_SD_LANGUAGE),
1832 X(MF_MT_AUDIO_WMADRC_AVGTARGET),
1833 X(MF_SD_PROTECTED),
1834 X(MF_SESSION_TOPOLOADER),
1835 X(MF_SESSION_GLOBAL_TIME),
1836 X(MF_SESSION_QUALITY_MANAGER),
1837 X(MF_SESSION_CONTENT_PROTECTION_MANAGER),
1838 X(MF_MT_MPEG4_SAMPLE_DESCRIPTION),
1839 X(MF_MT_D3D_RESOURCE_VERSION),
1840 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET),
1841 X(MF_MT_MPEG_START_TIME_CODE),
1842 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1843 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1844 X(MF_READWRITE_MMCSS_PRIORITY_AUDIO),
1845 X(MF_MT_H264_MAX_CODEC_CONFIG_DELAY),
1846 X(MF_MT_DV_AAUX_SRC_PACK_0),
1847 X(MF_BYTESTREAM_ORIGIN_NAME),
1848 X(MF_BYTESTREAM_CONTENT_TYPE),
1849 X(MF_MT_DEPTH_MEASUREMENT),
1850 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WIN10),
1851 X(MF_MT_VIDEO_3D_NUM_VIEWS),
1852 X(MF_BYTESTREAM_DURATION),
1853 X(MF_SD_SAMI_LANGUAGE),
1854 X(MF_EVENT_OUTPUT_NODE),
1855 X(MF_BYTESTREAM_LAST_MODIFIED_TIME),
1856 X(MFT_ENUM_ADAPTER_LUID),
1857 X(MF_MT_FRAME_RATE_RANGE_MIN),
1858 X(MF_BYTESTREAM_IFO_FILE_URI),
1859 X(MF_EVENT_TOPOLOGY_STATUS),
1860 X(MF_BYTESTREAM_DLNA_PROFILE_ID),
1861 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ROLE),
1862 X(MF_MT_MAJOR_TYPE),
1863 X(MF_SA_REQUIRED_SAMPLE_COUNT_PROGRESSIVE),
1864 X(MF_MT_IN_BAND_PARAMETER_SET),
1865 X(MF_EVENT_SOURCE_CHARACTERISTICS),
1866 X(MF_EVENT_SOURCE_CHARACTERISTICS_OLD),
1867 X(MF_SESSION_SERVER_CONTEXT),
1868 X(MF_MT_VIDEO_3D_FIRST_IS_LEFT),
1869 X(MFT_DECODER_FINAL_VIDEO_RESOLUTION_HINT),
1870 X(MF_PD_ADAPTIVE_STREAMING),
1871 X(MF_MEDIA_ENGINE_SOURCE_RESOLVER_CONFIG_STORE),
1872 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WWA_EDGE),
1873 X(MF_MT_H264_SUPPORTED_USAGES),
1874 X(MFT_PREFERRED_OUTPUTTYPE_Attribute),
1875 X(MFSampleExtension_Timestamp),
1876 X(MF_TOPONODE_PRIMARYOUTPUT),
1877 X(MF_MT_SUBTYPE),
1878 X(MF_TRANSFORM_ASYNC),
1879 X(MF_TOPONODE_STREAMID),
1880 X(MF_MEDIA_ENGINE_PLAYBACK_HWND),
1881 X(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE),
1882 X(MF_MT_VIDEO_LIGHTING),
1883 X(MF_SD_MUTUALLY_EXCLUSIVE),
1884 X(MF_SD_STREAM_NAME),
1885 X(MF_MT_DV_VAUX_SRC_PACK),
1886 X(MF_TOPONODE_RATELESS),
1887 X(MF_EVENT_STREAM_METADATA_CONTENT_KEYIDS),
1888 X(MF_TOPONODE_DISABLE_PREROLL),
1889 X(MF_SA_D3D11_ALLOW_DYNAMIC_YUV_TEXTURE),
1890 X(MF_MT_VIDEO_3D_FORMAT),
1891 X(MF_EVENT_STREAM_METADATA_KEYDATA),
1892 X(MF_READER_WRITER_D3D_MANAGER),
1893 X(MFTranscodeContainerType_FLAC),
1894 X(MFSampleExtension_3DVideo),
1895 X(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE),
1896 X(MF_MT_H264_USAGE),
1897 X(MF_MEDIA_ENGINE_EME_CALLBACK),
1898 X(MF_EVENT_SOURCE_FAKE_START),
1899 X(MF_EVENT_SOURCE_PROJECTSTART),
1900 X(MF_EVENT_SOURCE_ACTUAL_START),
1901 X(MF_MT_D3D12_TEXTURE_LAYOUT),
1902 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_MANAGER),
1903 X(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
1904 X(MFT_ENUM_HARDWARE_URL_Attribute),
1905 X(MF_SOURCE_READER_ASYNC_CALLBACK),
1906 X(MF_MT_D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE),
1907 X(MF_MT_OUTPUT_BUFFER_NUM),
1908 X(MF_SA_D3D11_BINDFLAGS),
1909 X(MFT_ENCODER_SUPPORTS_CONFIG_EVENT),
1910 X(MF_MT_AUDIO_FLAC_MAX_BLOCK_SIZE),
1911 X(MFT_FRIENDLY_NAME_Attribute),
1912 X(MFTranscodeContainerType_AVI),
1913 X(MF_MT_FIXED_SIZE_SAMPLES),
1914 X(MFT_SUPPORT_3DVIDEO),
1915 X(MFT_SUPPORT_3DVIDEO),
1916 X(MFT_INPUT_TYPES_Attributes),
1917 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS),
1918 X(MF_MT_H264_LAYOUT_PER_STREAM),
1919 X(MF_EVENT_SCRUBSAMPLE_TIME),
1920 X(MF_MT_SPATIAL_AUDIO_MAX_METADATA_ITEMS),
1921 X(MF_MT_MPEG2_ONE_FRAME_PER_PACKET),
1922 X(MF_MT_INTERLACE_MODE),
1923 X(MF_MEDIA_ENGINE_CALLBACK),
1924 X(MF_MT_VIDEO_RENDERER_EXTENSION_PROFILE),
1925 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_HW_SOURCE),
1926 X(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
1927 X(MF_XVP_CALLER_ALLOCATES_OUTPUT),
1928 X(MF_MT_H264_SVC_CAPABILITIES),
1929 X(MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY),
1930 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_LENGTH),
1931 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_FORMAT_ID),
1932 X(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK),
1933 X(MF_SA_D3D11_SHARED),
1934 X(MF_MT_PAN_SCAN_ENABLED),
1935 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL),
1936 X(MFTranscodeContainerType_AC3),
1937 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID),
1938 X(MF_MT_DV_VAUX_CTRL_PACK),
1939 X(MFSampleExtension_ForwardedDecodeUnitType),
1940 X(MF_SA_D3D11_AWARE),
1941 X(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
1942 X(MF_SOURCE_READER_MEDIASOURCE_CHARACTERISTICS),
1943 X(MF_MT_SPATIAL_AUDIO_MIN_METADATA_ITEM_OFFSET_SPACING),
1944 X(MF_TOPONODE_TRANSFORM_OBJECTID),
1945 X(MF_DEVSOURCE_ATTRIBUTE_MEDIA_TYPE),
1946 X(MF_EVENT_MFT_INPUT_STREAM_ID),
1947 X(MF_MT_SOURCE_CONTENT_HINT),
1948 X(MFT_ENUM_HARDWARE_VENDOR_ID_Attribute),
1949 X(MFT_ENUM_TRANSCODE_ONLY_ATTRIBUTE),
1950 X(MF_READWRITE_MMCSS_PRIORITY),
1951 X(MF_TRANSCODE_DONOT_INSERT_ENCODER),
1952 X(MF_MT_VIDEO_3D),
1953 X(MF_EVENT_START_PRESENTATION_TIME),
1954 X(MF_EVENT_SESSIONCAPS),
1955 X(MF_EVENT_PRESENTATION_TIME_OFFSET),
1956 X(MF_MEDIA_ENGINE_AUDIO_ENDPOINT_ROLE),
1957 X(MF_EVENT_SESSIONCAPS_DELTA),
1958 X(MF_EVENT_START_PRESENTATION_TIME_AT_OUTPUT),
1959 X(MFTranscodeContainerType_AMR),
1960 X(MFSampleExtension_DecodeTimestamp),
1961 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE),
1962 X(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT),
1963 X(MF_MT_VIDEO_H264_NO_FMOASO),
1964 X(MF_MT_AVG_BIT_ERROR_RATE),
1965 X(MF_MT_VIDEO_PRIMARIES),
1966 X(MF_SINK_WRITER_DISABLE_THROTTLING),
1967 X(MF_MT_H264_RATE_CONTROL_MODES),
1968 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK),
1969 X(MF_READWRITE_D3D_OPTIONAL),
1970 X(MF_SA_D3D11_HW_PROTECTED),
1971 X(MF_MEDIA_ENGINE_DXGI_MANAGER),
1972 X(MF_READWRITE_MMCSS_CLASS_AUDIO),
1973 X(MF_MEDIA_ENGINE_COREWINDOW),
1974 X(MF_SOURCE_READER_DISABLE_CAMERA_PLUGINS),
1975 X(MF_MT_MPEG4_TRACK_TYPE),
1976 X(MF_ACTIVATE_VIDEO_WINDOW),
1977 X(MF_MT_PAN_SCAN_APERTURE),
1978 X(MF_TOPOLOGY_RESOLUTION_STATUS),
1979 X(MF_MT_ORIGINAL_4CC),
1980 X(MF_PD_AUDIO_ISVARIABLEBITRATE),
1981 X(MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS),
1982 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE),
1983 X(MF_MT_D3D12_CPU_READBACK),
1984 X(MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID),
1985 X(MF_MT_MPEG2_CONTENT_PACKET),
1986 X(MFT_PROCESS_LOCAL_Attribute),
1987 X(MFT_PROCESS_LOCAL_Attribute),
1988 X(MF_MT_PAD_CONTROL_FLAGS),
1989 X(MF_MT_VIDEO_NOMINAL_RANGE),
1990 X(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
1991 X(MF_MT_MPEG_SEQUENCE_HEADER),
1992 X(MF_MEDIA_ENGINE_OPM_HWND),
1993 X(MF_MT_AUDIO_SAMPLES_PER_SECOND),
1994 X(MF_MT_SPATIAL_AUDIO_DATA_PRESENT),
1995 X(MF_MT_FRAME_RATE),
1996 X(MF_TOPONODE_FLUSH),
1997 X(MF_MT_MPEG2_STANDARD),
1998 X(MF_TOPONODE_DRAIN),
1999 X(MF_MT_TRANSFER_FUNCTION),
2000 X(MF_TOPONODE_MEDIASTART),
2001 X(MF_TOPONODE_MEDIASTOP),
2002 X(MF_SOURCE_READER_MEDIASOURCE_CONFIG),
2003 X(MF_TOPONODE_SOURCE),
2004 X(MF_TOPONODE_PRESENTATION_DESCRIPTOR),
2005 X(MF_TOPONODE_D3DAWARE),
2006 X(MF_MT_COMPRESSED),
2007 X(MF_TOPONODE_STREAM_DESCRIPTOR),
2008 X(MF_TOPONODE_ERRORCODE),
2009 X(MF_TOPONODE_SEQUENCE_ELEMENTID),
2010 X(MF_TRANSCODE_SKIP_METADATA_TRANSFER),
2011 X(MF_EVENT_MFT_CONTEXT),
2012 X(MF_MT_FORWARD_CUSTOM_SEI),
2013 X(MFTranscodeContainerType_FMPEG4),
2014 X(MF_TOPONODE_CONNECT_METHOD),
2015 X(MFT_OUTPUT_TYPES_Attributes),
2016 X(MF_MT_IMAGE_LOSS_TOLERANT),
2017 X(MF_SESSION_REMOTE_SOURCE_MODE),
2018 X(MF_MT_DEPTH_VALUE_UNIT),
2019 X(MF_MT_AUDIO_NUM_CHANNELS),
2020 X(MF_MT_ARBITRARY_HEADER),
2021 X(MF_TOPOLOGY_DXVA_MODE),
2022 X(MF_TOPONODE_LOCKED),
2023 X(MF_TRANSCODE_QUALITYVSSPEED),
2024 X(MF_TOPONODE_WORKQUEUE_ID),
2025 X(MF_MEDIA_ENGINE_CONTINUE_ON_CODEC_ERROR),
2026 X(MF_TOPONODE_WORKQUEUE_MMCSS_CLASS),
2027 X(MFTranscodeContainerType_MPEG2),
2028 X(MF_TOPONODE_DECRYPTOR),
2029 X(MF_EVENT_DO_THINNING),
2030 X(MF_TOPONODE_DISCARDABLE),
2031 X(MF_TOPOLOGY_HARDWARE_MODE),
2032 X(MF_SOURCE_READER_DISABLE_DXVA),
2033 X(MF_MT_FORWARD_CUSTOM_NALU),
2034 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE10),
2035 X(MF_TOPONODE_ERROR_MAJORTYPE),
2036 X(MF_MT_SECURE),
2037 X(MFT_FIELDOFUSE_UNLOCK_Attribute),
2038 X(MF_TOPONODE_ERROR_SUBTYPE),
2039 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE),
2040 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE),
2041 X(MF_MT_VIDEO_3D_LEFT_IS_BASE),
2042 X(MF_TOPONODE_WORKQUEUE_MMCSS_TASKID),
2043 #undef MF_READER_WRITER_D3D_MANAGER
2044 #undef X
2046 struct guid_def *ret = NULL;
2048 if (guid)
2049 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
2051 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
2054 const char *debugstr_mf_guid(const GUID *guid)
2056 static const struct guid_def guid_defs[] =
2058 #define X(g) { &(g), #g }
2059 X(MFAudioFormat_ADTS),
2060 X(MFAudioFormat_PCM),
2061 X(MFAudioFormat_PCM_HDCP),
2062 X(MFAudioFormat_Float),
2063 X(MFAudioFormat_DTS),
2064 X(MFAudioFormat_DRM),
2065 X(MFAudioFormat_MSP1),
2066 X(MFAudioFormat_Vorbis),
2067 X(MFAudioFormat_AAC),
2068 X(MFVideoFormat_RGB24),
2069 X(MFVideoFormat_ARGB32),
2070 X(MFVideoFormat_RGB32),
2071 X(MFVideoFormat_RGB565),
2072 X(MFVideoFormat_RGB555),
2073 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID),
2074 X(MFT_CATEGORY_MULTIPLEXER),
2075 X(MFVideoFormat_A2R10G10B10),
2076 X(MFT_CATEGORY_VIDEO_EFFECT),
2077 X(MFMediaType_Script),
2078 X(MFMediaType_Image),
2079 X(MFMediaType_HTML),
2080 X(MFMediaType_Binary),
2081 X(MFVideoFormat_MPEG2),
2082 X(MFMediaType_FileTransfer),
2083 X(MFVideoFormat_RGB8),
2084 X(MFAudioFormat_Dolby_AC3),
2085 X(MFVideoFormat_L8),
2086 X(MFAudioFormat_LPCM),
2087 X(MFVideoFormat_420O),
2088 X(MFVideoFormat_AI44),
2089 X(MFVideoFormat_AV1),
2090 X(MFVideoFormat_AYUV),
2091 X(MFVideoFormat_H263),
2092 X(MFVideoFormat_H264),
2093 X(MFVideoFormat_H265),
2094 X(MFVideoFormat_HEVC),
2095 X(MFVideoFormat_HEVC_ES),
2096 X(MFT_CATEGORY_AUDIO_EFFECT),
2097 X(MFVideoFormat_I420),
2098 X(MFVideoFormat_IYUV),
2099 X(MFT_CATEGORY_VIDEO_DECODER),
2100 X(MFVideoFormat_M4S2),
2101 X(MFVideoFormat_MJPG),
2102 X(MFVideoFormat_MP43),
2103 X(MFVideoFormat_MP4S),
2104 X(MFVideoFormat_MP4V),
2105 X(MFVideoFormat_MPG1),
2106 X(MFVideoFormat_MSS1),
2107 X(MFVideoFormat_MSS2),
2108 X(MFVideoFormat_NV11),
2109 X(MFVideoFormat_NV12),
2110 X(MFVideoFormat_ORAW),
2111 X(MFAudioFormat_Opus),
2112 X(MFAudioFormat_MPEG),
2113 X(MFVideoFormat_D16),
2114 X(MFVideoFormat_P010),
2115 X(MFVideoFormat_P016),
2116 X(MFVideoFormat_P210),
2117 X(MFVideoFormat_P216),
2118 X(MFVideoFormat_L16),
2119 X(MFAudioFormat_MP3),
2120 X(MFVideoFormat_UYVY),
2121 X(MFVideoFormat_VP10),
2122 X(MFVideoFormat_VP80),
2123 X(MFVideoFormat_VP90),
2124 X(MFVideoFormat_WMV1),
2125 X(MFVideoFormat_WMV2),
2126 X(MFVideoFormat_WMV3),
2127 X(MFVideoFormat_WVC1),
2128 X(MFT_CATEGORY_OTHER),
2129 X(MFVideoFormat_Y210),
2130 X(MFVideoFormat_Y216),
2131 X(MFVideoFormat_Y410),
2132 X(MFVideoFormat_Y416),
2133 X(MFVideoFormat_Y41P),
2134 X(MFVideoFormat_Y41T),
2135 X(MFVideoFormat_Y42T),
2136 X(MFVideoFormat_YUY2),
2137 X(MFVideoFormat_YV12),
2138 X(MFVideoFormat_YVU9),
2139 X(MFVideoFormat_YVYU),
2140 X(MFAudioFormat_WMAudioV8),
2141 X(MFAudioFormat_ALAC),
2142 X(MFAudioFormat_AMR_NB),
2143 X(MFMediaType_Audio),
2144 X(MFAudioFormat_WMAudioV9),
2145 X(MFAudioFormat_AMR_WB),
2146 X(MFAudioFormat_WMAudio_Lossless),
2147 X(MFAudioFormat_AMR_WP),
2148 X(MFAudioFormat_WMASPDIF),
2149 X(MFVideoFormat_DV25),
2150 X(MFVideoFormat_DV50),
2151 X(MFVideoFormat_DVC),
2152 X(MFVideoFormat_DVH1),
2153 X(MFVideoFormat_DVHD),
2154 X(MFVideoFormat_DVSD),
2155 X(MFVideoFormat_DVSL),
2156 X(MFVideoFormat_A16B16G16R16F),
2157 X(MFVideoFormat_v210),
2158 X(MFVideoFormat_v216),
2159 X(MFVideoFormat_v410),
2160 X(MFMediaType_Video),
2161 X(MFAudioFormat_AAC_HDCP),
2162 X(MFT_CATEGORY_DEMULTIPLEXER),
2163 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID),
2164 X(MFT_CATEGORY_VIDEO_ENCODER),
2165 X(MFAudioFormat_Dolby_AC3_HDCP),
2166 X(MFMediaType_Subtitle),
2167 X(MFMediaType_Stream),
2168 X(MFAudioFormat_Dolby_AC3_SPDIF),
2169 X(MFAudioFormat_Float_SpatialObjects),
2170 X(MFMediaType_SAMI),
2171 X(MFAudioFormat_ADTS_HDCP),
2172 X(MFAudioFormat_FLAC),
2173 X(MFAudioFormat_Dolby_DDPlus),
2174 X(MFMediaType_MultiplexedFrames),
2175 X(MFT_CATEGORY_AUDIO_DECODER),
2176 X(MFAudioFormat_Base_HDCP),
2177 X(MFT_CATEGORY_AUDIO_ENCODER),
2178 X(MFVideoFormat_Base_HDCP),
2179 X(MFVideoFormat_H264_HDCP),
2180 X(MFVideoFormat_HEVC_HDCP),
2181 X(MFMediaType_Default),
2182 X(MFMediaType_Protected),
2183 X(MFVideoFormat_H264_ES),
2184 X(MFMediaType_Perception),
2185 X(MFT_CATEGORY_VIDEO_PROCESSOR),
2186 #undef X
2188 struct guid_def *ret = NULL;
2190 if (guid)
2191 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
2193 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
2196 struct event_id
2198 DWORD id;
2199 const char *name;
2202 static int __cdecl debug_event_id(const void *a, const void *b)
2204 const DWORD *id = a;
2205 const struct event_id *event_id = b;
2206 return *id - event_id->id;
2209 static const char *debugstr_eventid(DWORD event)
2211 static const struct event_id
2213 DWORD id;
2214 const char *name;
2216 event_ids[] =
2218 #define X(e) { e, #e }
2219 X(MEUnknown),
2220 X(MEError),
2221 X(MEExtendedType),
2222 X(MENonFatalError),
2223 X(MESessionUnknown),
2224 X(MESessionTopologySet),
2225 X(MESessionTopologiesCleared),
2226 X(MESessionStarted),
2227 X(MESessionPaused),
2228 X(MESessionStopped),
2229 X(MESessionClosed),
2230 X(MESessionEnded),
2231 X(MESessionRateChanged),
2232 X(MESessionScrubSampleComplete),
2233 X(MESessionCapabilitiesChanged),
2234 X(MESessionTopologyStatus),
2235 X(MESessionNotifyPresentationTime),
2236 X(MENewPresentation),
2237 X(MELicenseAcquisitionStart),
2238 X(MELicenseAcquisitionCompleted),
2239 X(MEIndividualizationStart),
2240 X(MEIndividualizationCompleted),
2241 X(MEEnablerProgress),
2242 X(MEEnablerCompleted),
2243 X(MEPolicyError),
2244 X(MEPolicyReport),
2245 X(MEBufferingStarted),
2246 X(MEBufferingStopped),
2247 X(MEConnectStart),
2248 X(MEConnectEnd),
2249 X(MEReconnectStart),
2250 X(MEReconnectEnd),
2251 X(MERendererEvent),
2252 X(MESessionStreamSinkFormatChanged),
2253 X(MESourceUnknown),
2254 X(MESourceStarted),
2255 X(MEStreamStarted),
2256 X(MESourceSeeked),
2257 X(MEStreamSeeked),
2258 X(MENewStream),
2259 X(MEUpdatedStream),
2260 X(MESourceStopped),
2261 X(MEStreamStopped),
2262 X(MESourcePaused),
2263 X(MEStreamPaused),
2264 X(MEEndOfPresentation),
2265 X(MEEndOfStream),
2266 X(MEMediaSample),
2267 X(MEStreamTick),
2268 X(MEStreamThinMode),
2269 X(MEStreamFormatChanged),
2270 X(MESourceRateChanged),
2271 X(MEEndOfPresentationSegment),
2272 X(MESourceCharacteristicsChanged),
2273 X(MESourceRateChangeRequested),
2274 X(MESourceMetadataChanged),
2275 X(MESequencerSourceTopologyUpdated),
2276 X(MESinkUnknown),
2277 X(MEStreamSinkStarted),
2278 X(MEStreamSinkStopped),
2279 X(MEStreamSinkPaused),
2280 X(MEStreamSinkRateChanged),
2281 X(MEStreamSinkRequestSample),
2282 X(MEStreamSinkMarker),
2283 X(MEStreamSinkPrerolled),
2284 X(MEStreamSinkScrubSampleComplete),
2285 X(MEStreamSinkFormatChanged),
2286 X(MEStreamSinkDeviceChanged),
2287 X(MEQualityNotify),
2288 X(MESinkInvalidated),
2289 X(MEAudioSessionNameChanged),
2290 X(MEAudioSessionVolumeChanged),
2291 X(MEAudioSessionDeviceRemoved),
2292 X(MEAudioSessionServerShutdown),
2293 X(MEAudioSessionGroupingParamChanged),
2294 X(MEAudioSessionIconChanged),
2295 X(MEAudioSessionFormatChanged),
2296 X(MEAudioSessionDisconnected),
2297 X(MEAudioSessionExclusiveModeOverride),
2298 X(MECaptureAudioSessionVolumeChanged),
2299 X(MECaptureAudioSessionDeviceRemoved),
2300 X(MECaptureAudioSessionFormatChanged),
2301 X(MECaptureAudioSessionDisconnected),
2302 X(MECaptureAudioSessionExclusiveModeOverride),
2303 X(MECaptureAudioSessionServerShutdown),
2304 X(METrustUnknown),
2305 X(MEPolicyChanged),
2306 X(MEContentProtectionMessage),
2307 X(MEPolicySet),
2308 X(MEWMDRMLicenseBackupCompleted),
2309 X(MEWMDRMLicenseBackupProgress),
2310 X(MEWMDRMLicenseRestoreCompleted),
2311 X(MEWMDRMLicenseRestoreProgress),
2312 X(MEWMDRMLicenseAcquisitionCompleted),
2313 X(MEWMDRMIndividualizationCompleted),
2314 X(MEWMDRMIndividualizationProgress),
2315 X(MEWMDRMProximityCompleted),
2316 X(MEWMDRMLicenseStoreCleaned),
2317 X(MEWMDRMRevocationDownloadCompleted),
2318 X(METransformUnknown),
2319 X(METransformNeedInput),
2320 X(METransformHaveOutput),
2321 X(METransformDrainComplete),
2322 X(METransformMarker),
2323 X(METransformInputStreamStateChanged),
2324 X(MEByteStreamCharacteristicsChanged),
2325 X(MEVideoCaptureDeviceRemoved),
2326 X(MEVideoCaptureDevicePreempted),
2327 X(MEStreamSinkFormatInvalidated),
2328 X(MEEncodingParameters),
2329 X(MEContentProtectionMetadata),
2330 X(MEDeviceThermalStateChanged),
2331 #undef X
2334 struct event_id *ret = bsearch(&event, event_ids, ARRAY_SIZE(event_ids), sizeof(*event_ids), debug_event_id);
2335 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbg_sprintf("%lu", event);
2338 static inline struct attributes *impl_from_IMFAttributes(IMFAttributes *iface)
2340 return CONTAINING_RECORD(iface, struct attributes, IMFAttributes_iface);
2343 static HRESULT WINAPI mfattributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
2345 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
2347 if (IsEqualIID(riid, &IID_IMFAttributes) ||
2348 IsEqualGUID(riid, &IID_IUnknown))
2350 *out = iface;
2351 IMFAttributes_AddRef(iface);
2352 return S_OK;
2355 WARN("Unsupported %s.\n", debugstr_guid(riid));
2356 *out = NULL;
2357 return E_NOINTERFACE;
2360 static ULONG WINAPI mfattributes_AddRef(IMFAttributes *iface)
2362 struct attributes *attributes = impl_from_IMFAttributes(iface);
2363 ULONG refcount = InterlockedIncrement(&attributes->ref);
2365 TRACE("%p, refcount %ld.\n", iface, refcount);
2367 return refcount;
2370 static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
2372 struct attributes *attributes = impl_from_IMFAttributes(iface);
2373 ULONG refcount = InterlockedDecrement(&attributes->ref);
2375 TRACE("%p, refcount %ld.\n", iface, refcount);
2377 if (!refcount)
2379 clear_attributes_object(attributes);
2380 free(attributes);
2383 return refcount;
2386 static struct attribute *attributes_find_item(struct attributes *attributes, REFGUID key, size_t *index)
2388 size_t i;
2390 for (i = 0; i < attributes->count; ++i)
2392 if (IsEqualGUID(key, &attributes->attributes[i].key))
2394 if (index)
2395 *index = i;
2396 return &attributes->attributes[i];
2400 return NULL;
2403 static HRESULT attributes_get_item(struct attributes *attributes, const GUID *key, PROPVARIANT *value)
2405 struct attribute *attribute;
2406 HRESULT hr;
2408 EnterCriticalSection(&attributes->cs);
2410 attribute = attributes_find_item(attributes, key, NULL);
2411 if (attribute)
2413 if (attribute->value.vt == value->vt && !(value->vt == VT_UNKNOWN && !attribute->value.punkVal))
2414 hr = PropVariantCopy(value, &attribute->value);
2415 else
2416 hr = MF_E_INVALIDTYPE;
2418 else
2419 hr = MF_E_ATTRIBUTENOTFOUND;
2421 LeaveCriticalSection(&attributes->cs);
2423 return hr;
2426 HRESULT attributes_GetItem(struct attributes *attributes, REFGUID key, PROPVARIANT *value)
2428 struct attribute *attribute;
2429 HRESULT hr;
2431 EnterCriticalSection(&attributes->cs);
2433 if ((attribute = attributes_find_item(attributes, key, NULL)))
2434 hr = value ? PropVariantCopy(value, &attribute->value) : S_OK;
2435 else
2436 hr = MF_E_ATTRIBUTENOTFOUND;
2438 LeaveCriticalSection(&attributes->cs);
2440 return hr;
2443 HRESULT attributes_GetItemType(struct attributes *attributes, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2445 struct attribute *attribute;
2446 HRESULT hr = S_OK;
2448 EnterCriticalSection(&attributes->cs);
2450 if ((attribute = attributes_find_item(attributes, key, NULL)))
2452 *type = attribute->value.vt;
2454 else
2455 hr = MF_E_ATTRIBUTENOTFOUND;
2457 LeaveCriticalSection(&attributes->cs);
2459 return hr;
2462 HRESULT attributes_CompareItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value, BOOL *result)
2464 struct attribute *attribute;
2466 *result = FALSE;
2468 EnterCriticalSection(&attributes->cs);
2470 if ((attribute = attributes_find_item(attributes, key, NULL)))
2472 *result = attribute->value.vt == value->vt &&
2473 !PropVariantCompareEx(&attribute->value, value, PVCU_DEFAULT, PVCF_DEFAULT);
2476 LeaveCriticalSection(&attributes->cs);
2478 return S_OK;
2481 HRESULT attributes_Compare(struct attributes *attributes, IMFAttributes *theirs,
2482 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2484 IMFAttributes *smaller, *other;
2485 MF_ATTRIBUTE_TYPE type;
2486 HRESULT hr = S_OK;
2487 UINT32 count;
2488 BOOL result;
2489 size_t i;
2491 if (FAILED(hr = IMFAttributes_GetCount(theirs, &count)))
2492 return hr;
2494 EnterCriticalSection(&attributes->cs);
2496 result = TRUE;
2498 switch (match_type)
2500 case MF_ATTRIBUTES_MATCH_OUR_ITEMS:
2501 for (i = 0; i < attributes->count; ++i)
2503 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2504 &attributes->attributes[i].value, &result)))
2505 break;
2506 if (!result)
2507 break;
2509 break;
2510 case MF_ATTRIBUTES_MATCH_THEIR_ITEMS:
2511 hr = IMFAttributes_Compare(theirs, &attributes->IMFAttributes_iface, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2512 break;
2513 case MF_ATTRIBUTES_MATCH_ALL_ITEMS:
2514 if (count != attributes->count)
2516 result = FALSE;
2517 break;
2519 for (i = 0; i < count; ++i)
2521 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2522 &attributes->attributes[i].value, &result)))
2523 break;
2524 if (!result)
2525 break;
2527 break;
2528 case MF_ATTRIBUTES_MATCH_INTERSECTION:
2529 for (i = 0; i < attributes->count; ++i)
2531 if (FAILED(IMFAttributes_GetItemType(theirs, &attributes->attributes[i].key, &type)))
2532 continue;
2534 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2535 &attributes->attributes[i].value, &result)))
2536 break;
2538 if (!result)
2539 break;
2541 break;
2542 case MF_ATTRIBUTES_MATCH_SMALLER:
2543 smaller = attributes->count > count ? theirs : &attributes->IMFAttributes_iface;
2544 other = attributes->count > count ? &attributes->IMFAttributes_iface : theirs;
2545 hr = IMFAttributes_Compare(smaller, other, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2546 break;
2547 default:
2548 WARN("Unknown match type %d.\n", match_type);
2549 hr = E_INVALIDARG;
2552 LeaveCriticalSection(&attributes->cs);
2554 if (SUCCEEDED(hr))
2555 *ret = result;
2557 return hr;
2560 HRESULT attributes_GetUINT32(struct attributes *attributes, REFGUID key, UINT32 *value)
2562 PROPVARIANT attrval;
2563 HRESULT hr;
2565 PropVariantInit(&attrval);
2566 attrval.vt = VT_UI4;
2567 hr = attributes_get_item(attributes, key, &attrval);
2568 if (SUCCEEDED(hr))
2569 *value = attrval.ulVal;
2571 return hr;
2574 HRESULT attributes_GetUINT64(struct attributes *attributes, REFGUID key, UINT64 *value)
2576 PROPVARIANT attrval;
2577 HRESULT hr;
2579 PropVariantInit(&attrval);
2580 attrval.vt = VT_UI8;
2581 hr = attributes_get_item(attributes, key, &attrval);
2582 if (SUCCEEDED(hr))
2583 *value = attrval.uhVal.QuadPart;
2585 return hr;
2588 HRESULT attributes_GetDouble(struct attributes *attributes, REFGUID key, double *value)
2590 PROPVARIANT attrval;
2591 HRESULT hr;
2593 PropVariantInit(&attrval);
2594 attrval.vt = VT_R8;
2595 hr = attributes_get_item(attributes, key, &attrval);
2596 if (SUCCEEDED(hr))
2597 *value = attrval.dblVal;
2599 return hr;
2602 HRESULT attributes_GetGUID(struct attributes *attributes, REFGUID key, GUID *value)
2604 struct attribute *attribute;
2605 HRESULT hr = S_OK;
2607 EnterCriticalSection(&attributes->cs);
2609 attribute = attributes_find_item(attributes, key, NULL);
2610 if (attribute)
2612 if (attribute->value.vt == MF_ATTRIBUTE_GUID)
2613 *value = *attribute->value.puuid;
2614 else
2615 hr = MF_E_INVALIDTYPE;
2617 else
2618 hr = MF_E_ATTRIBUTENOTFOUND;
2620 LeaveCriticalSection(&attributes->cs);
2622 return hr;
2625 HRESULT attributes_GetStringLength(struct attributes *attributes, REFGUID key, UINT32 *length)
2627 struct attribute *attribute;
2628 HRESULT hr = S_OK;
2630 EnterCriticalSection(&attributes->cs);
2632 attribute = attributes_find_item(attributes, key, NULL);
2633 if (attribute)
2635 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2636 *length = lstrlenW(attribute->value.pwszVal);
2637 else
2638 hr = MF_E_INVALIDTYPE;
2640 else
2641 hr = MF_E_ATTRIBUTENOTFOUND;
2643 LeaveCriticalSection(&attributes->cs);
2645 return hr;
2648 HRESULT attributes_GetString(struct attributes *attributes, REFGUID key, WCHAR *value,
2649 UINT32 size, UINT32 *length)
2651 struct attribute *attribute;
2652 HRESULT hr = S_OK;
2654 EnterCriticalSection(&attributes->cs);
2656 attribute = attributes_find_item(attributes, key, NULL);
2657 if (attribute)
2659 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2661 int len = lstrlenW(attribute->value.pwszVal);
2663 if (length)
2664 *length = len;
2666 if (size <= len)
2667 hr = STRSAFE_E_INSUFFICIENT_BUFFER;
2668 else
2669 memcpy(value, attribute->value.pwszVal, (len + 1) * sizeof(WCHAR));
2671 else
2672 hr = MF_E_INVALIDTYPE;
2674 else
2675 hr = MF_E_ATTRIBUTENOTFOUND;
2677 LeaveCriticalSection(&attributes->cs);
2679 return hr;
2682 HRESULT attributes_GetAllocatedString(struct attributes *attributes, REFGUID key, WCHAR **value, UINT32 *length)
2684 PROPVARIANT attrval;
2685 HRESULT hr;
2687 PropVariantInit(&attrval);
2688 attrval.vt = VT_LPWSTR;
2689 hr = attributes_get_item(attributes, key, &attrval);
2690 if (SUCCEEDED(hr))
2692 *value = attrval.pwszVal;
2693 if (length)
2694 *length = lstrlenW(*value);
2697 return hr;
2700 HRESULT attributes_GetBlobSize(struct attributes *attributes, REFGUID key, UINT32 *size)
2702 struct attribute *attribute;
2703 HRESULT hr = S_OK;
2705 EnterCriticalSection(&attributes->cs);
2707 attribute = attributes_find_item(attributes, key, NULL);
2708 if (attribute)
2710 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2711 *size = attribute->value.caub.cElems;
2712 else
2713 hr = MF_E_INVALIDTYPE;
2715 else
2716 hr = MF_E_ATTRIBUTENOTFOUND;
2718 LeaveCriticalSection(&attributes->cs);
2720 return hr;
2723 HRESULT attributes_GetBlob(struct attributes *attributes, REFGUID key, UINT8 *buf, UINT32 bufsize, UINT32 *blobsize)
2725 struct attribute *attribute;
2726 HRESULT hr;
2728 EnterCriticalSection(&attributes->cs);
2730 attribute = attributes_find_item(attributes, key, NULL);
2731 if (attribute)
2733 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2735 UINT32 size = attribute->value.caub.cElems;
2737 if (bufsize >= size)
2738 hr = PropVariantToBuffer(&attribute->value, buf, size);
2739 else
2740 hr = E_NOT_SUFFICIENT_BUFFER;
2742 if (blobsize)
2743 *blobsize = size;
2745 else
2746 hr = MF_E_INVALIDTYPE;
2748 else
2749 hr = MF_E_ATTRIBUTENOTFOUND;
2751 LeaveCriticalSection(&attributes->cs);
2753 return hr;
2756 HRESULT attributes_GetAllocatedBlob(struct attributes *attributes, REFGUID key, UINT8 **buf, UINT32 *size)
2758 PROPVARIANT attrval;
2759 HRESULT hr;
2761 attrval.vt = VT_VECTOR | VT_UI1;
2762 hr = attributes_get_item(attributes, key, &attrval);
2763 if (SUCCEEDED(hr))
2765 *buf = attrval.caub.pElems;
2766 if (size)
2767 *size = attrval.caub.cElems;
2770 return hr;
2773 HRESULT attributes_GetUnknown(struct attributes *attributes, REFGUID key, REFIID riid, void **out)
2775 PROPVARIANT attrval;
2776 HRESULT hr;
2778 PropVariantInit(&attrval);
2779 attrval.vt = VT_UNKNOWN;
2780 hr = attributes_get_item(attributes, key, &attrval);
2781 if (SUCCEEDED(hr))
2782 hr = IUnknown_QueryInterface(attrval.punkVal, riid, out);
2783 PropVariantClear(&attrval);
2784 return hr;
2787 static HRESULT attributes_set_item(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2789 struct attribute *attribute;
2791 EnterCriticalSection(&attributes->cs);
2793 attribute = attributes_find_item(attributes, key, NULL);
2794 if (!attribute)
2796 if (!mf_array_reserve((void **)&attributes->attributes, &attributes->capacity, attributes->count + 1,
2797 sizeof(*attributes->attributes)))
2799 LeaveCriticalSection(&attributes->cs);
2800 return E_OUTOFMEMORY;
2802 attributes->attributes[attributes->count].key = *key;
2803 attribute = &attributes->attributes[attributes->count++];
2805 else
2806 PropVariantClear(&attribute->value);
2808 PropVariantCopy(&attribute->value, value);
2810 LeaveCriticalSection(&attributes->cs);
2812 return S_OK;
2815 HRESULT attributes_SetItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2817 PROPVARIANT empty;
2819 switch (value->vt)
2821 case MF_ATTRIBUTE_UINT32:
2822 case MF_ATTRIBUTE_UINT64:
2823 case MF_ATTRIBUTE_DOUBLE:
2824 case MF_ATTRIBUTE_GUID:
2825 case MF_ATTRIBUTE_STRING:
2826 case MF_ATTRIBUTE_BLOB:
2827 case MF_ATTRIBUTE_IUNKNOWN:
2828 return attributes_set_item(attributes, key, value);
2829 default:
2830 PropVariantInit(&empty);
2831 attributes_set_item(attributes, key, &empty);
2832 return MF_E_INVALIDTYPE;
2836 HRESULT attributes_DeleteItem(struct attributes *attributes, REFGUID key)
2838 struct attribute *attribute;
2839 size_t index = 0;
2841 EnterCriticalSection(&attributes->cs);
2843 if ((attribute = attributes_find_item(attributes, key, &index)))
2845 size_t count;
2847 PropVariantClear(&attribute->value);
2849 attributes->count--;
2850 count = attributes->count - index;
2851 if (count)
2852 memmove(&attributes->attributes[index], &attributes->attributes[index + 1], count * sizeof(*attributes->attributes));
2855 LeaveCriticalSection(&attributes->cs);
2857 return S_OK;
2860 HRESULT attributes_DeleteAllItems(struct attributes *attributes)
2862 EnterCriticalSection(&attributes->cs);
2864 while (attributes->count)
2866 PropVariantClear(&attributes->attributes[--attributes->count].value);
2868 free(attributes->attributes);
2869 attributes->attributes = NULL;
2870 attributes->capacity = 0;
2872 LeaveCriticalSection(&attributes->cs);
2874 return S_OK;
2877 HRESULT attributes_SetUINT32(struct attributes *attributes, REFGUID key, UINT32 value)
2879 PROPVARIANT attrval;
2881 attrval.vt = VT_UI4;
2882 attrval.ulVal = value;
2883 return attributes_set_item(attributes, key, &attrval);
2886 HRESULT attributes_SetUINT64(struct attributes *attributes, REFGUID key, UINT64 value)
2888 PROPVARIANT attrval;
2890 attrval.vt = VT_UI8;
2891 attrval.uhVal.QuadPart = value;
2892 return attributes_set_item(attributes, key, &attrval);
2895 HRESULT attributes_SetDouble(struct attributes *attributes, REFGUID key, double value)
2897 PROPVARIANT attrval;
2899 attrval.vt = VT_R8;
2900 attrval.dblVal = value;
2901 return attributes_set_item(attributes, key, &attrval);
2904 HRESULT attributes_SetGUID(struct attributes *attributes, REFGUID key, REFGUID value)
2906 PROPVARIANT attrval;
2908 attrval.vt = VT_CLSID;
2909 attrval.puuid = (CLSID *)value;
2910 return attributes_set_item(attributes, key, &attrval);
2913 HRESULT attributes_SetString(struct attributes *attributes, REFGUID key, const WCHAR *value)
2915 PROPVARIANT attrval;
2917 attrval.vt = VT_LPWSTR;
2918 attrval.pwszVal = (WCHAR *)value;
2919 return attributes_set_item(attributes, key, &attrval);
2922 HRESULT attributes_SetBlob(struct attributes *attributes, REFGUID key, const UINT8 *buf, UINT32 size)
2924 PROPVARIANT attrval;
2926 attrval.vt = VT_VECTOR | VT_UI1;
2927 attrval.caub.cElems = size;
2928 attrval.caub.pElems = (UINT8 *)buf;
2929 return attributes_set_item(attributes, key, &attrval);
2932 HRESULT attributes_SetUnknown(struct attributes *attributes, REFGUID key, IUnknown *unknown)
2934 PROPVARIANT attrval;
2936 attrval.vt = VT_UNKNOWN;
2937 attrval.punkVal = unknown;
2938 return attributes_set_item(attributes, key, &attrval);
2941 HRESULT attributes_LockStore(struct attributes *attributes)
2943 EnterCriticalSection(&attributes->cs);
2945 return S_OK;
2948 HRESULT attributes_UnlockStore(struct attributes *attributes)
2950 LeaveCriticalSection(&attributes->cs);
2952 return S_OK;
2955 HRESULT attributes_GetCount(struct attributes *attributes, UINT32 *count)
2957 EnterCriticalSection(&attributes->cs);
2958 *count = attributes->count;
2959 LeaveCriticalSection(&attributes->cs);
2961 return S_OK;
2964 HRESULT attributes_GetItemByIndex(struct attributes *attributes, UINT32 index, GUID *key, PROPVARIANT *value)
2966 HRESULT hr = S_OK;
2968 EnterCriticalSection(&attributes->cs);
2970 if (index < attributes->count)
2972 *key = attributes->attributes[index].key;
2973 if (value)
2974 PropVariantCopy(value, &attributes->attributes[index].value);
2976 else
2977 hr = E_INVALIDARG;
2979 LeaveCriticalSection(&attributes->cs);
2981 return hr;
2984 HRESULT attributes_CopyAllItems(struct attributes *attributes, IMFAttributes *dest)
2986 HRESULT hr = S_OK;
2987 size_t i;
2989 EnterCriticalSection(&attributes->cs);
2991 IMFAttributes_LockStore(dest);
2993 IMFAttributes_DeleteAllItems(dest);
2995 for (i = 0; i < attributes->count; ++i)
2997 hr = IMFAttributes_SetItem(dest, &attributes->attributes[i].key, &attributes->attributes[i].value);
2998 if (FAILED(hr))
2999 break;
3002 IMFAttributes_UnlockStore(dest);
3004 LeaveCriticalSection(&attributes->cs);
3006 return hr;
3009 static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
3011 struct attributes *attributes = impl_from_IMFAttributes(iface);
3013 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3015 return attributes_GetItem(attributes, key, value);
3018 static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
3020 struct attributes *attributes = impl_from_IMFAttributes(iface);
3022 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
3024 return attributes_GetItemType(attributes, key, type);
3027 static HRESULT WINAPI mfattributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
3029 struct attributes *attributes = impl_from_IMFAttributes(iface);
3031 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
3033 return attributes_CompareItem(attributes, key, value, result);
3036 static HRESULT WINAPI mfattributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
3037 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
3039 struct attributes *attributes = impl_from_IMFAttributes(iface);
3041 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
3043 return attributes_Compare(attributes, theirs, match_type, ret);
3046 static HRESULT WINAPI mfattributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
3048 struct attributes *attributes = impl_from_IMFAttributes(iface);
3050 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3052 return attributes_GetUINT32(attributes, key, value);
3055 static HRESULT WINAPI mfattributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
3057 struct attributes *attributes = impl_from_IMFAttributes(iface);
3059 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3061 return attributes_GetUINT64(attributes, key, value);
3064 static HRESULT WINAPI mfattributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
3066 struct attributes *attributes = impl_from_IMFAttributes(iface);
3068 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3070 return attributes_GetDouble(attributes, key, value);
3073 static HRESULT WINAPI mfattributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
3075 struct attributes *attributes = impl_from_IMFAttributes(iface);
3077 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3079 return attributes_GetGUID(attributes, key, value);
3082 static HRESULT WINAPI mfattributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
3084 struct attributes *attributes = impl_from_IMFAttributes(iface);
3086 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
3088 return attributes_GetStringLength(attributes, key, length);
3091 static HRESULT WINAPI mfattributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
3092 UINT32 size, UINT32 *length)
3094 struct attributes *attributes = impl_from_IMFAttributes(iface);
3096 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
3098 return attributes_GetString(attributes, key, value, size, length);
3101 static HRESULT WINAPI mfattributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
3103 struct attributes *attributes = impl_from_IMFAttributes(iface);
3105 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
3107 return attributes_GetAllocatedString(attributes, key, value, length);
3110 static HRESULT WINAPI mfattributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
3112 struct attributes *attributes = impl_from_IMFAttributes(iface);
3114 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
3116 return attributes_GetBlobSize(attributes, key, size);
3119 static HRESULT WINAPI mfattributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
3120 UINT32 bufsize, UINT32 *blobsize)
3122 struct attributes *attributes = impl_from_IMFAttributes(iface);
3124 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
3126 return attributes_GetBlob(attributes, key, buf, bufsize, blobsize);
3129 static HRESULT WINAPI mfattributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
3131 struct attributes *attributes = impl_from_IMFAttributes(iface);
3133 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
3135 return attributes_GetAllocatedBlob(attributes, key, buf, size);
3138 static HRESULT WINAPI mfattributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
3140 struct attributes *attributes = impl_from_IMFAttributes(iface);
3142 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
3144 return attributes_GetUnknown(attributes, key, riid, out);
3147 static HRESULT WINAPI mfattributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
3149 struct attributes *attributes = impl_from_IMFAttributes(iface);
3151 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
3153 return attributes_SetItem(attributes, key, value);
3156 static HRESULT WINAPI mfattributes_DeleteItem(IMFAttributes *iface, REFGUID key)
3158 struct attributes *attributes = impl_from_IMFAttributes(iface);
3160 TRACE("%p, %s.\n", iface, debugstr_attr(key));
3162 return attributes_DeleteItem(attributes, key);
3165 static HRESULT WINAPI mfattributes_DeleteAllItems(IMFAttributes *iface)
3167 struct attributes *attributes = impl_from_IMFAttributes(iface);
3169 TRACE("%p.\n", iface);
3171 return attributes_DeleteAllItems(attributes);
3174 static HRESULT WINAPI mfattributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
3176 struct attributes *attributes = impl_from_IMFAttributes(iface);
3178 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
3180 return attributes_SetUINT32(attributes, key, value);
3183 static HRESULT WINAPI mfattributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
3185 struct attributes *attributes = impl_from_IMFAttributes(iface);
3187 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
3189 return attributes_SetUINT64(attributes, key, value);
3192 static HRESULT WINAPI mfattributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
3194 struct attributes *attributes = impl_from_IMFAttributes(iface);
3196 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
3198 return attributes_SetDouble(attributes, key, value);
3201 static HRESULT WINAPI mfattributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
3203 struct attributes *attributes = impl_from_IMFAttributes(iface);
3205 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
3207 return attributes_SetGUID(attributes, key, value);
3210 static HRESULT WINAPI mfattributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
3212 struct attributes *attributes = impl_from_IMFAttributes(iface);
3214 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
3216 return attributes_SetString(attributes, key, value);
3219 static HRESULT WINAPI mfattributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
3221 struct attributes *attributes = impl_from_IMFAttributes(iface);
3223 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
3225 return attributes_SetBlob(attributes, key, buf, size);
3228 static HRESULT WINAPI mfattributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
3230 struct attributes *attributes = impl_from_IMFAttributes(iface);
3232 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
3234 return attributes_SetUnknown(attributes, key, unknown);
3237 static HRESULT WINAPI mfattributes_LockStore(IMFAttributes *iface)
3239 struct attributes *attributes = impl_from_IMFAttributes(iface);
3241 TRACE("%p.\n", iface);
3243 return attributes_LockStore(attributes);
3246 static HRESULT WINAPI mfattributes_UnlockStore(IMFAttributes *iface)
3248 struct attributes *attributes = impl_from_IMFAttributes(iface);
3250 TRACE("%p.\n", iface);
3252 return attributes_UnlockStore(attributes);
3255 static HRESULT WINAPI mfattributes_GetCount(IMFAttributes *iface, UINT32 *count)
3257 struct attributes *attributes = impl_from_IMFAttributes(iface);
3259 TRACE("%p, %p.\n", iface, count);
3261 return attributes_GetCount(attributes, count);
3264 static HRESULT WINAPI mfattributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
3266 struct attributes *attributes = impl_from_IMFAttributes(iface);
3268 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
3270 return attributes_GetItemByIndex(attributes, index, key, value);
3273 static HRESULT WINAPI mfattributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
3275 struct attributes *attributes = impl_from_IMFAttributes(iface);
3277 TRACE("%p, %p.\n", iface, dest);
3279 return attributes_CopyAllItems(attributes, dest);
3282 static const IMFAttributesVtbl mfattributes_vtbl =
3284 mfattributes_QueryInterface,
3285 mfattributes_AddRef,
3286 mfattributes_Release,
3287 mfattributes_GetItem,
3288 mfattributes_GetItemType,
3289 mfattributes_CompareItem,
3290 mfattributes_Compare,
3291 mfattributes_GetUINT32,
3292 mfattributes_GetUINT64,
3293 mfattributes_GetDouble,
3294 mfattributes_GetGUID,
3295 mfattributes_GetStringLength,
3296 mfattributes_GetString,
3297 mfattributes_GetAllocatedString,
3298 mfattributes_GetBlobSize,
3299 mfattributes_GetBlob,
3300 mfattributes_GetAllocatedBlob,
3301 mfattributes_GetUnknown,
3302 mfattributes_SetItem,
3303 mfattributes_DeleteItem,
3304 mfattributes_DeleteAllItems,
3305 mfattributes_SetUINT32,
3306 mfattributes_SetUINT64,
3307 mfattributes_SetDouble,
3308 mfattributes_SetGUID,
3309 mfattributes_SetString,
3310 mfattributes_SetBlob,
3311 mfattributes_SetUnknown,
3312 mfattributes_LockStore,
3313 mfattributes_UnlockStore,
3314 mfattributes_GetCount,
3315 mfattributes_GetItemByIndex,
3316 mfattributes_CopyAllItems
3319 HRESULT init_attributes_object(struct attributes *object, UINT32 size)
3321 object->IMFAttributes_iface.lpVtbl = &mfattributes_vtbl;
3322 object->ref = 1;
3323 InitializeCriticalSection(&object->cs);
3325 object->attributes = NULL;
3326 object->count = 0;
3327 object->capacity = 0;
3328 if (!mf_array_reserve((void **)&object->attributes, &object->capacity, size,
3329 sizeof(*object->attributes)))
3331 DeleteCriticalSection(&object->cs);
3332 return E_OUTOFMEMORY;
3335 return S_OK;
3338 void clear_attributes_object(struct attributes *object)
3340 size_t i;
3342 for (i = 0; i < object->count; i++)
3343 PropVariantClear(&object->attributes[i].value);
3344 free(object->attributes);
3346 DeleteCriticalSection(&object->cs);
3349 /***********************************************************************
3350 * MFCreateAttributes (mfplat.@)
3352 HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size)
3354 struct attributes *object;
3355 HRESULT hr;
3357 TRACE("%p, %d\n", attributes, size);
3359 if (!(object = calloc(1, sizeof(*object))))
3360 return E_OUTOFMEMORY;
3362 if (FAILED(hr = init_attributes_object(object, size)))
3364 free(object);
3365 return hr;
3367 *attributes = &object->IMFAttributes_iface;
3369 return S_OK;
3372 #define ATTRIBUTES_STORE_MAGIC 0x494d4641 /* IMFA */
3374 struct attributes_store_header
3376 DWORD magic;
3377 UINT32 count;
3380 struct attributes_store_item
3382 GUID key;
3383 QWORD type;
3384 union
3386 double f;
3387 UINT32 i32;
3388 UINT64 i64;
3389 struct
3391 DWORD size;
3392 DWORD offset;
3393 } subheader;
3394 } u;
3397 /***********************************************************************
3398 * MFGetAttributesAsBlobSize (mfplat.@)
3400 HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size)
3402 unsigned int i, count, length;
3403 HRESULT hr;
3404 GUID key;
3406 TRACE("%p, %p.\n", attributes, size);
3408 IMFAttributes_LockStore(attributes);
3410 hr = IMFAttributes_GetCount(attributes, &count);
3412 *size = sizeof(struct attributes_store_header);
3414 for (i = 0; i < count; ++i)
3416 MF_ATTRIBUTE_TYPE type;
3418 hr = IMFAttributes_GetItemByIndex(attributes, i, &key, NULL);
3419 if (FAILED(hr))
3420 break;
3422 *size += sizeof(struct attributes_store_item);
3424 IMFAttributes_GetItemType(attributes, &key, &type);
3426 switch (type)
3428 case MF_ATTRIBUTE_GUID:
3429 *size += sizeof(GUID);
3430 break;
3431 case MF_ATTRIBUTE_STRING:
3432 IMFAttributes_GetStringLength(attributes, &key, &length);
3433 *size += (length + 1) * sizeof(WCHAR);
3434 break;
3435 case MF_ATTRIBUTE_BLOB:
3436 IMFAttributes_GetBlobSize(attributes, &key, &length);
3437 *size += length;
3438 break;
3439 case MF_ATTRIBUTE_UINT32:
3440 case MF_ATTRIBUTE_UINT64:
3441 case MF_ATTRIBUTE_DOUBLE:
3442 case MF_ATTRIBUTE_IUNKNOWN:
3443 default:
3448 IMFAttributes_UnlockStore(attributes);
3450 return hr;
3453 struct attr_serialize_context
3455 UINT8 *buffer;
3456 UINT8 *ptr;
3457 UINT32 size;
3460 static void attributes_serialize_write(struct attr_serialize_context *context, const void *value, unsigned int size)
3462 memcpy(context->ptr, value, size);
3463 context->ptr += size;
3466 static BOOL attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
3467 const void *value)
3469 switch (item->type)
3471 case MF_ATTRIBUTE_UINT32:
3472 case MF_ATTRIBUTE_UINT64:
3473 case MF_ATTRIBUTE_DOUBLE:
3474 attributes_serialize_write(context, item, sizeof(*item));
3475 break;
3476 case MF_ATTRIBUTE_GUID:
3477 case MF_ATTRIBUTE_STRING:
3478 case MF_ATTRIBUTE_BLOB:
3479 item->u.subheader.offset = context->size - item->u.subheader.size;
3480 attributes_serialize_write(context, item, sizeof(*item));
3481 memcpy(context->buffer + item->u.subheader.offset, value, item->u.subheader.size);
3482 context->size -= item->u.subheader.size;
3483 break;
3484 default:
3485 return FALSE;
3488 return TRUE;
3491 /***********************************************************************
3492 * MFGetAttributesAsBlob (mfplat.@)
3494 HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size)
3496 struct attributes_store_header header;
3497 struct attr_serialize_context context;
3498 unsigned int required_size, i;
3499 PROPVARIANT value;
3500 UINT32 count;
3501 HRESULT hr;
3503 TRACE("%p, %p, %u.\n", attributes, buffer, size);
3505 if (FAILED(hr = MFGetAttributesAsBlobSize(attributes, &required_size)))
3506 return hr;
3508 if (required_size > size)
3509 return MF_E_BUFFERTOOSMALL;
3511 context.buffer = buffer;
3512 context.ptr = buffer;
3513 context.size = required_size;
3515 IMFAttributes_LockStore(attributes);
3517 header.magic = ATTRIBUTES_STORE_MAGIC;
3518 header.count = 0; /* Will be updated later */
3519 IMFAttributes_GetCount(attributes, &count);
3521 attributes_serialize_write(&context, &header, sizeof(header));
3523 for (i = 0; i < count; ++i)
3525 struct attributes_store_item item;
3526 const void *data = NULL;
3528 hr = IMFAttributes_GetItemByIndex(attributes, i, &item.key, &value);
3529 if (FAILED(hr))
3530 break;
3532 item.type = value.vt;
3534 switch (value.vt)
3536 case MF_ATTRIBUTE_UINT32:
3537 case MF_ATTRIBUTE_UINT64:
3538 item.u.i64 = value.uhVal.QuadPart;
3539 break;
3540 case MF_ATTRIBUTE_DOUBLE:
3541 item.u.f = value.dblVal;
3542 break;
3543 case MF_ATTRIBUTE_GUID:
3544 item.u.subheader.size = sizeof(*value.puuid);
3545 data = value.puuid;
3546 break;
3547 case MF_ATTRIBUTE_STRING:
3548 item.u.subheader.size = (lstrlenW(value.pwszVal) + 1) * sizeof(WCHAR);
3549 data = value.pwszVal;
3550 break;
3551 case MF_ATTRIBUTE_BLOB:
3552 item.u.subheader.size = value.caub.cElems;
3553 data = value.caub.pElems;
3554 break;
3555 case MF_ATTRIBUTE_IUNKNOWN:
3556 break;
3557 default:
3558 WARN("Unknown attribute type %#x.\n", value.vt);
3561 if (attributes_serialize_write_item(&context, &item, data))
3562 header.count++;
3564 PropVariantClear(&value);
3567 memcpy(context.buffer, &header, sizeof(header));
3569 IMFAttributes_UnlockStore(attributes);
3571 return S_OK;
3574 static HRESULT attributes_deserialize_read(struct attr_serialize_context *context, void *value, unsigned int size)
3576 if (context->size < (context->ptr - context->buffer) + size)
3577 return E_INVALIDARG;
3579 memcpy(value, context->ptr, size);
3580 context->ptr += size;
3582 return S_OK;
3585 /***********************************************************************
3586 * MFInitAttributesFromBlob (mfplat.@)
3588 HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *dest, const UINT8 *buffer, UINT size)
3590 struct attr_serialize_context context;
3591 struct attributes_store_header header;
3592 struct attributes_store_item item;
3593 IMFAttributes *attributes;
3594 unsigned int i;
3595 HRESULT hr;
3597 TRACE("%p, %p, %u.\n", dest, buffer, size);
3599 context.buffer = (UINT8 *)buffer;
3600 context.ptr = (UINT8 *)buffer;
3601 context.size = size;
3603 /* Validate buffer structure. */
3604 if (FAILED(hr = attributes_deserialize_read(&context, &header, sizeof(header))))
3605 return hr;
3607 if (header.magic != ATTRIBUTES_STORE_MAGIC)
3608 return E_UNEXPECTED;
3610 if (FAILED(hr = MFCreateAttributes(&attributes, header.count)))
3611 return hr;
3613 for (i = 0; i < header.count; ++i)
3615 if (FAILED(hr = attributes_deserialize_read(&context, &item, sizeof(item))))
3616 break;
3618 hr = E_UNEXPECTED;
3620 switch (item.type)
3622 case MF_ATTRIBUTE_UINT32:
3623 hr = IMFAttributes_SetUINT32(attributes, &item.key, item.u.i32);
3624 break;
3625 case MF_ATTRIBUTE_UINT64:
3626 hr = IMFAttributes_SetUINT64(attributes, &item.key, item.u.i64);
3627 break;
3628 case MF_ATTRIBUTE_DOUBLE:
3629 hr = IMFAttributes_SetDouble(attributes, &item.key, item.u.f);
3630 break;
3631 case MF_ATTRIBUTE_GUID:
3632 if (item.u.subheader.size == sizeof(GUID) &&
3633 item.u.subheader.offset + item.u.subheader.size <= context.size)
3635 hr = IMFAttributes_SetGUID(attributes, &item.key,
3636 (const GUID *)(context.buffer + item.u.subheader.offset));
3638 break;
3639 case MF_ATTRIBUTE_STRING:
3640 if (item.u.subheader.size >= sizeof(WCHAR) &&
3641 item.u.subheader.offset + item.u.subheader.size <= context.size)
3643 hr = IMFAttributes_SetString(attributes, &item.key,
3644 (const WCHAR *)(context.buffer + item.u.subheader.offset));
3646 break;
3647 case MF_ATTRIBUTE_BLOB:
3648 if (item.u.subheader.size > 0 && item.u.subheader.offset + item.u.subheader.size <= context.size)
3650 hr = IMFAttributes_SetBlob(attributes, &item.key, context.buffer + item.u.subheader.offset,
3651 item.u.subheader.size);
3653 break;
3654 default:
3658 if (FAILED(hr))
3659 break;
3662 if (SUCCEEDED(hr))
3664 IMFAttributes_DeleteAllItems(dest);
3665 hr = IMFAttributes_CopyAllItems(attributes, dest);
3668 IMFAttributes_Release(attributes);
3670 return hr;
3673 struct bytestream
3675 struct attributes attributes;
3676 IMFByteStream IMFByteStream_iface;
3677 IMFGetService IMFGetService_iface;
3678 IRtwqAsyncCallback read_callback;
3679 IRtwqAsyncCallback write_callback;
3680 IStream *stream;
3681 HANDLE hfile;
3682 QWORD position;
3683 DWORD capabilities;
3684 struct list pending;
3685 CRITICAL_SECTION cs;
3688 static inline struct bytestream *impl_from_IMFByteStream(IMFByteStream *iface)
3690 return CONTAINING_RECORD(iface, struct bytestream, IMFByteStream_iface);
3693 static struct bytestream *impl_bytestream_from_IMFGetService(IMFGetService *iface)
3695 return CONTAINING_RECORD(iface, struct bytestream, IMFGetService_iface);
3698 static struct bytestream *impl_from_read_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3700 return CONTAINING_RECORD(iface, struct bytestream, read_callback);
3703 static struct bytestream *impl_from_write_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3705 return CONTAINING_RECORD(iface, struct bytestream, write_callback);
3708 enum async_stream_op_type
3710 ASYNC_STREAM_OP_READ,
3711 ASYNC_STREAM_OP_WRITE,
3714 struct async_stream_op
3716 IUnknown IUnknown_iface;
3717 LONG refcount;
3718 union
3720 const BYTE *src;
3721 BYTE *dest;
3722 } u;
3723 QWORD position;
3724 ULONG requested_length;
3725 ULONG actual_length;
3726 IMFAsyncResult *caller;
3727 struct list entry;
3728 enum async_stream_op_type type;
3731 static struct async_stream_op *impl_async_stream_op_from_IUnknown(IUnknown *iface)
3733 return CONTAINING_RECORD(iface, struct async_stream_op, IUnknown_iface);
3736 static HRESULT WINAPI async_stream_op_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
3738 if (IsEqualIID(riid, &IID_IUnknown))
3740 *obj = iface;
3741 IUnknown_AddRef(iface);
3742 return S_OK;
3745 WARN("Unsupported %s.\n", debugstr_guid(riid));
3746 *obj = NULL;
3747 return E_NOINTERFACE;
3750 static ULONG WINAPI async_stream_op_AddRef(IUnknown *iface)
3752 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3753 ULONG refcount = InterlockedIncrement(&op->refcount);
3755 TRACE("%p, refcount %ld.\n", iface, refcount);
3757 return refcount;
3760 static ULONG WINAPI async_stream_op_Release(IUnknown *iface)
3762 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3763 ULONG refcount = InterlockedDecrement(&op->refcount);
3765 TRACE("%p, refcount %ld.\n", iface, refcount);
3767 if (!refcount)
3769 if (op->caller)
3770 IMFAsyncResult_Release(op->caller);
3771 free(op);
3774 return refcount;
3777 static const IUnknownVtbl async_stream_op_vtbl =
3779 async_stream_op_QueryInterface,
3780 async_stream_op_AddRef,
3781 async_stream_op_Release,
3784 static HRESULT bytestream_create_io_request(struct bytestream *stream, enum async_stream_op_type type,
3785 const BYTE *data, ULONG size, IMFAsyncCallback *callback, IUnknown *state)
3787 struct async_stream_op *op;
3788 IRtwqAsyncResult *request;
3789 HRESULT hr;
3791 op = malloc(sizeof(*op));
3792 if (!op)
3793 return E_OUTOFMEMORY;
3795 op->IUnknown_iface.lpVtbl = &async_stream_op_vtbl;
3796 op->refcount = 1;
3797 op->u.src = data;
3798 op->position = stream->position;
3799 op->requested_length = size;
3800 op->type = type;
3801 if (FAILED(hr = RtwqCreateAsyncResult((IUnknown *)&stream->IMFByteStream_iface, (IRtwqAsyncCallback *)callback, state,
3802 (IRtwqAsyncResult **)&op->caller)))
3804 goto failed;
3807 if (FAILED(hr = RtwqCreateAsyncResult(&op->IUnknown_iface, type == ASYNC_STREAM_OP_READ ? &stream->read_callback :
3808 &stream->write_callback, NULL, &request)))
3809 goto failed;
3811 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, request);
3812 IRtwqAsyncResult_Release(request);
3814 failed:
3815 IUnknown_Release(&op->IUnknown_iface);
3816 return hr;
3819 static HRESULT bytestream_complete_io_request(struct bytestream *stream, enum async_stream_op_type type,
3820 IMFAsyncResult *result, ULONG *actual_length)
3822 struct async_stream_op *op = NULL, *cur;
3823 HRESULT hr;
3825 EnterCriticalSection(&stream->cs);
3826 LIST_FOR_EACH_ENTRY(cur, &stream->pending, struct async_stream_op, entry)
3828 if (cur->caller == result && cur->type == type)
3830 op = cur;
3831 list_remove(&cur->entry);
3832 break;
3835 LeaveCriticalSection(&stream->cs);
3837 if (!op)
3838 return E_INVALIDARG;
3840 if (SUCCEEDED(hr = IMFAsyncResult_GetStatus(result)))
3841 *actual_length = op->actual_length;
3843 IUnknown_Release(&op->IUnknown_iface);
3845 return hr;
3848 static HRESULT WINAPI bytestream_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
3850 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
3851 IsEqualIID(riid, &IID_IUnknown))
3853 *obj = iface;
3854 IRtwqAsyncCallback_AddRef(iface);
3855 return S_OK;
3858 WARN("Unsupported %s.\n", debugstr_guid(riid));
3859 *obj = NULL;
3860 return E_NOINTERFACE;
3863 static ULONG WINAPI bytestream_read_callback_AddRef(IRtwqAsyncCallback *iface)
3865 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3866 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3869 static ULONG WINAPI bytestream_read_callback_Release(IRtwqAsyncCallback *iface)
3871 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3872 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3875 static HRESULT WINAPI bytestream_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
3877 return E_NOTIMPL;
3880 static ULONG WINAPI bytestream_write_callback_AddRef(IRtwqAsyncCallback *iface)
3882 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3883 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3886 static ULONG WINAPI bytestream_write_callback_Release(IRtwqAsyncCallback *iface)
3888 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3889 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3892 static HRESULT WINAPI bytestream_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
3894 struct bytestream *stream = impl_from_IMFByteStream(iface);
3896 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
3898 if (IsEqualIID(riid, &IID_IMFByteStream) ||
3899 IsEqualIID(riid, &IID_IUnknown))
3901 *out = &stream->IMFByteStream_iface;
3903 else if (IsEqualIID(riid, &IID_IMFAttributes))
3905 *out = &stream->attributes.IMFAttributes_iface;
3907 else if (stream->IMFGetService_iface.lpVtbl && IsEqualIID(riid, &IID_IMFGetService))
3909 *out = &stream->IMFGetService_iface;
3911 else
3913 WARN("Unsupported %s.\n", debugstr_guid(riid));
3914 *out = NULL;
3915 return E_NOINTERFACE;
3918 IUnknown_AddRef((IUnknown*)*out);
3919 return S_OK;
3922 static ULONG WINAPI bytestream_AddRef(IMFByteStream *iface)
3924 struct bytestream *stream = impl_from_IMFByteStream(iface);
3925 ULONG refcount = InterlockedIncrement(&stream->attributes.ref);
3927 TRACE("%p, refcount %ld.\n", iface, refcount);
3929 return refcount;
3932 static ULONG WINAPI bytestream_Release(IMFByteStream *iface)
3934 struct bytestream *stream = impl_from_IMFByteStream(iface);
3935 ULONG refcount = InterlockedDecrement(&stream->attributes.ref);
3936 struct async_stream_op *cur, *cur2;
3938 TRACE("%p, refcount %ld.\n", iface, refcount);
3940 if (!refcount)
3942 clear_attributes_object(&stream->attributes);
3943 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &stream->pending, struct async_stream_op, entry)
3945 list_remove(&cur->entry);
3946 IUnknown_Release(&cur->IUnknown_iface);
3948 DeleteCriticalSection(&stream->cs);
3949 if (stream->stream)
3950 IStream_Release(stream->stream);
3951 if (stream->hfile)
3952 CloseHandle(stream->hfile);
3953 free(stream);
3956 return refcount;
3959 static HRESULT WINAPI bytestream_stream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3961 struct bytestream *stream = impl_from_IMFByteStream(iface);
3962 STATSTG stat;
3963 HRESULT hr;
3965 TRACE("%p, %p.\n", iface, capabilities);
3967 if (FAILED(hr = IStream_Stat(stream->stream, &stat, STATFLAG_NONAME)))
3968 return hr;
3970 *capabilities = MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_SEEKABLE;
3971 if (stat.grfMode & (STGM_WRITE | STGM_READWRITE))
3972 *capabilities |= MFBYTESTREAM_IS_WRITABLE;
3974 return S_OK;
3977 static HRESULT WINAPI bytestream_file_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3979 struct bytestream *stream = impl_from_IMFByteStream(iface);
3981 TRACE("%p, %p.\n", iface, capabilities);
3983 *capabilities = stream->capabilities;
3985 return S_OK;
3988 static HRESULT WINAPI bytestream_file_SetLength(IMFByteStream *iface, QWORD length)
3990 FIXME("%p, %s\n", iface, wine_dbgstr_longlong(length));
3992 return E_NOTIMPL;
3995 static HRESULT WINAPI bytestream_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
3997 struct bytestream *stream = impl_from_IMFByteStream(iface);
3999 TRACE("%p, %p.\n", iface, position);
4001 if (!position)
4002 return E_INVALIDARG;
4004 *position = stream->position;
4006 return S_OK;
4009 static HRESULT WINAPI bytestream_file_GetLength(IMFByteStream *iface, QWORD *length)
4011 struct bytestream *stream = impl_from_IMFByteStream(iface);
4012 LARGE_INTEGER li;
4014 TRACE("%p, %p.\n", iface, length);
4016 if (!length)
4017 return E_INVALIDARG;
4019 if (GetFileSizeEx(stream->hfile, &li))
4020 *length = li.QuadPart;
4021 else
4022 return HRESULT_FROM_WIN32(GetLastError());
4024 return S_OK;
4027 static HRESULT WINAPI bytestream_file_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
4029 struct bytestream *stream = impl_from_IMFByteStream(iface);
4030 LARGE_INTEGER position, length;
4031 HRESULT hr = S_OK;
4033 TRACE("%p, %p.\n", iface, ret);
4035 EnterCriticalSection(&stream->cs);
4037 position.QuadPart = 0;
4038 if (SetFilePointerEx(stream->hfile, position, &length, FILE_END))
4039 *ret = stream->position >= length.QuadPart;
4040 else
4041 hr = HRESULT_FROM_WIN32(GetLastError());
4043 LeaveCriticalSection(&stream->cs);
4045 return hr;
4048 static HRESULT WINAPI bytestream_file_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
4050 struct bytestream *stream = impl_from_IMFByteStream(iface);
4051 LARGE_INTEGER position;
4052 HRESULT hr = S_OK;
4053 BOOL ret;
4055 TRACE("%p, %p, %lu, %p.\n", iface, buffer, size, read_len);
4057 EnterCriticalSection(&stream->cs);
4059 position.QuadPart = stream->position;
4060 if ((ret = SetFilePointerEx(stream->hfile, position, NULL, FILE_BEGIN)))
4062 if ((ret = ReadFile(stream->hfile, buffer, size, read_len, NULL)))
4063 stream->position += *read_len;
4066 if (!ret)
4067 hr = HRESULT_FROM_WIN32(GetLastError());
4069 LeaveCriticalSection(&stream->cs);
4071 return hr;
4074 static HRESULT WINAPI bytestream_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size, IMFAsyncCallback *callback,
4075 IUnknown *state)
4077 struct bytestream *stream = impl_from_IMFByteStream(iface);
4079 TRACE("%p, %p, %lu, %p, %p.\n", iface, data, size, callback, state);
4081 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_READ, data, size, callback, state);
4084 static HRESULT WINAPI bytestream_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
4086 struct bytestream *stream = impl_from_IMFByteStream(iface);
4088 TRACE("%p, %p, %p.\n", iface, result, byte_read);
4090 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_READ, result, byte_read);
4093 static HRESULT WINAPI bytestream_file_Write(IMFByteStream *iface, const BYTE *data, ULONG size, ULONG *written)
4095 struct bytestream *stream = impl_from_IMFByteStream(iface);
4096 LARGE_INTEGER position;
4097 HRESULT hr = S_OK;
4098 BOOL ret;
4100 TRACE("%p, %p, %lu, %p\n", iface, data, size, written);
4102 EnterCriticalSection(&stream->cs);
4104 position.QuadPart = stream->position;
4105 if ((ret = SetFilePointerEx(stream->hfile, position, NULL, FILE_BEGIN)))
4107 if ((ret = WriteFile(stream->hfile, data, size, written, NULL)))
4108 stream->position += *written;
4111 if (!ret)
4112 hr = HRESULT_FROM_WIN32(GetLastError());
4114 LeaveCriticalSection(&stream->cs);
4116 return hr;
4119 static HRESULT WINAPI bytestream_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
4120 IMFAsyncCallback *callback, IUnknown *state)
4122 struct bytestream *stream = impl_from_IMFByteStream(iface);
4124 TRACE("%p, %p, %lu, %p, %p.\n", iface, data, size, callback, state);
4126 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_WRITE, data, size, callback, state);
4129 static HRESULT WINAPI bytestream_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
4131 struct bytestream *stream = impl_from_IMFByteStream(iface);
4133 TRACE("%p, %p, %p.\n", iface, result, written);
4135 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_WRITE, result, written);
4138 static HRESULT WINAPI bytestream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN origin, LONGLONG offset,
4139 DWORD flags, QWORD *current)
4141 struct bytestream *stream = impl_from_IMFByteStream(iface);
4142 HRESULT hr = S_OK;
4144 TRACE("%p, %u, %s, %#lx, %p.\n", iface, origin, wine_dbgstr_longlong(offset), flags, current);
4146 EnterCriticalSection(&stream->cs);
4148 switch (origin)
4150 case msoBegin:
4151 stream->position = offset;
4152 break;
4153 case msoCurrent:
4154 stream->position += offset;
4155 break;
4156 default:
4157 WARN("Unknown origin mode %d.\n", origin);
4158 hr = E_INVALIDARG;
4161 *current = stream->position;
4163 LeaveCriticalSection(&stream->cs);
4165 return hr;
4168 static HRESULT WINAPI bytestream_file_Flush(IMFByteStream *iface)
4170 FIXME("%p\n", iface);
4172 return E_NOTIMPL;
4175 static HRESULT WINAPI bytestream_file_Close(IMFByteStream *iface)
4177 FIXME("%p\n", iface);
4179 return E_NOTIMPL;
4182 static HRESULT WINAPI bytestream_SetCurrentPosition(IMFByteStream *iface, QWORD position)
4184 struct bytestream *stream = impl_from_IMFByteStream(iface);
4186 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4188 EnterCriticalSection(&stream->cs);
4189 stream->position = position;
4190 LeaveCriticalSection(&stream->cs);
4192 return S_OK;
4195 static const IMFByteStreamVtbl bytestream_file_vtbl =
4197 bytestream_QueryInterface,
4198 bytestream_AddRef,
4199 bytestream_Release,
4200 bytestream_file_GetCapabilities,
4201 bytestream_file_GetLength,
4202 bytestream_file_SetLength,
4203 bytestream_GetCurrentPosition,
4204 bytestream_SetCurrentPosition,
4205 bytestream_file_IsEndOfStream,
4206 bytestream_file_Read,
4207 bytestream_BeginRead,
4208 bytestream_EndRead,
4209 bytestream_file_Write,
4210 bytestream_BeginWrite,
4211 bytestream_EndWrite,
4212 bytestream_Seek,
4213 bytestream_file_Flush,
4214 bytestream_file_Close
4217 static HRESULT WINAPI bytestream_stream_GetLength(IMFByteStream *iface, QWORD *length)
4219 struct bytestream *stream = impl_from_IMFByteStream(iface);
4220 STATSTG statstg;
4221 HRESULT hr;
4223 TRACE("%p, %p.\n", iface, length);
4225 if (FAILED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4226 return hr;
4228 *length = statstg.cbSize.QuadPart;
4230 return S_OK;
4233 static HRESULT WINAPI bytestream_stream_SetLength(IMFByteStream *iface, QWORD length)
4235 struct bytestream *stream = impl_from_IMFByteStream(iface);
4236 ULARGE_INTEGER size;
4237 HRESULT hr;
4239 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4241 EnterCriticalSection(&stream->cs);
4243 size.QuadPart = length;
4244 hr = IStream_SetSize(stream->stream, size);
4246 LeaveCriticalSection(&stream->cs);
4248 return hr;
4251 static HRESULT WINAPI bytestream_stream_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
4253 struct bytestream *stream = impl_from_IMFByteStream(iface);
4254 STATSTG statstg;
4255 HRESULT hr;
4257 TRACE("%p, %p.\n", iface, ret);
4259 EnterCriticalSection(&stream->cs);
4261 if (SUCCEEDED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4262 *ret = stream->position >= statstg.cbSize.QuadPart;
4264 LeaveCriticalSection(&stream->cs);
4266 return hr;
4269 static HRESULT WINAPI bytestream_stream_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
4271 struct bytestream *stream = impl_from_IMFByteStream(iface);
4272 LARGE_INTEGER position;
4273 HRESULT hr;
4275 TRACE("%p, %p, %lu, %p.\n", iface, buffer, size, read_len);
4277 EnterCriticalSection(&stream->cs);
4279 position.QuadPart = stream->position;
4280 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4282 if (SUCCEEDED(hr = IStream_Read(stream->stream, buffer, size, read_len)))
4283 stream->position += *read_len;
4286 LeaveCriticalSection(&stream->cs);
4288 return hr;
4291 static HRESULT WINAPI bytestream_stream_Write(IMFByteStream *iface, const BYTE *buffer, ULONG size, ULONG *written)
4293 struct bytestream *stream = impl_from_IMFByteStream(iface);
4294 LARGE_INTEGER position;
4295 HRESULT hr;
4297 TRACE("%p, %p, %lu, %p.\n", iface, buffer, size, written);
4299 EnterCriticalSection(&stream->cs);
4301 position.QuadPart = stream->position;
4302 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4304 if (SUCCEEDED(hr = IStream_Write(stream->stream, buffer, size, written)))
4305 stream->position += *written;
4308 LeaveCriticalSection(&stream->cs);
4310 return hr;
4313 static HRESULT WINAPI bytestream_stream_Flush(IMFByteStream *iface)
4315 struct bytestream *stream = impl_from_IMFByteStream(iface);
4317 TRACE("%p.\n", iface);
4319 return IStream_Commit(stream->stream, STGC_DEFAULT);
4322 static HRESULT WINAPI bytestream_stream_Close(IMFByteStream *iface)
4324 TRACE("%p.\n", iface);
4326 return S_OK;
4329 static const IMFByteStreamVtbl bytestream_stream_vtbl =
4331 bytestream_QueryInterface,
4332 bytestream_AddRef,
4333 bytestream_Release,
4334 bytestream_stream_GetCapabilities,
4335 bytestream_stream_GetLength,
4336 bytestream_stream_SetLength,
4337 bytestream_GetCurrentPosition,
4338 bytestream_SetCurrentPosition,
4339 bytestream_stream_IsEndOfStream,
4340 bytestream_stream_Read,
4341 bytestream_BeginRead,
4342 bytestream_EndRead,
4343 bytestream_stream_Write,
4344 bytestream_BeginWrite,
4345 bytestream_EndWrite,
4346 bytestream_Seek,
4347 bytestream_stream_Flush,
4348 bytestream_stream_Close,
4351 static inline struct bytestream *impl_from_IMFByteStream_IMFAttributes(IMFAttributes *iface)
4353 return CONTAINING_RECORD(iface, struct bytestream, attributes.IMFAttributes_iface);
4356 static HRESULT WINAPI bytestream_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
4358 struct bytestream *stream = impl_from_IMFByteStream_IMFAttributes(iface);
4359 return IMFByteStream_QueryInterface(&stream->IMFByteStream_iface, riid, out);
4362 static ULONG WINAPI bytestream_attributes_AddRef(IMFAttributes *iface)
4364 struct bytestream *stream = impl_from_IMFByteStream_IMFAttributes(iface);
4365 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
4368 static ULONG WINAPI bytestream_attributes_Release(IMFAttributes *iface)
4370 struct bytestream *stream = impl_from_IMFByteStream_IMFAttributes(iface);
4371 return IMFByteStream_Release(&stream->IMFByteStream_iface);
4374 static const IMFAttributesVtbl bytestream_attributes_vtbl =
4376 bytestream_attributes_QueryInterface,
4377 bytestream_attributes_AddRef,
4378 bytestream_attributes_Release,
4379 mfattributes_GetItem,
4380 mfattributes_GetItemType,
4381 mfattributes_CompareItem,
4382 mfattributes_Compare,
4383 mfattributes_GetUINT32,
4384 mfattributes_GetUINT64,
4385 mfattributes_GetDouble,
4386 mfattributes_GetGUID,
4387 mfattributes_GetStringLength,
4388 mfattributes_GetString,
4389 mfattributes_GetAllocatedString,
4390 mfattributes_GetBlobSize,
4391 mfattributes_GetBlob,
4392 mfattributes_GetAllocatedBlob,
4393 mfattributes_GetUnknown,
4394 mfattributes_SetItem,
4395 mfattributes_DeleteItem,
4396 mfattributes_DeleteAllItems,
4397 mfattributes_SetUINT32,
4398 mfattributes_SetUINT64,
4399 mfattributes_SetDouble,
4400 mfattributes_SetGUID,
4401 mfattributes_SetString,
4402 mfattributes_SetBlob,
4403 mfattributes_SetUnknown,
4404 mfattributes_LockStore,
4405 mfattributes_UnlockStore,
4406 mfattributes_GetCount,
4407 mfattributes_GetItemByIndex,
4408 mfattributes_CopyAllItems
4411 static HRESULT WINAPI bytestream_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4413 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4414 struct async_stream_op *op;
4415 IUnknown *object;
4416 HRESULT hr;
4418 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4419 return hr;
4421 op = impl_async_stream_op_from_IUnknown(object);
4423 EnterCriticalSection(&stream->cs);
4425 hr = IMFByteStream_Read(&stream->IMFByteStream_iface, op->u.dest, op->requested_length, &op->actual_length);
4426 if(FAILED(hr)) TRACE("Read failed: %#lx\n", hr);
4427 IMFAsyncResult_SetStatus(op->caller, hr);
4428 list_add_tail(&stream->pending, &op->entry);
4430 LeaveCriticalSection(&stream->cs);
4432 MFInvokeCallback(op->caller);
4434 return S_OK;
4437 static HRESULT WINAPI bytestream_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4439 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4440 struct async_stream_op *op;
4441 IUnknown *object;
4442 HRESULT hr;
4444 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4445 return hr;
4447 op = impl_async_stream_op_from_IUnknown(object);
4449 EnterCriticalSection(&stream->cs);
4451 hr = IMFByteStream_Write(&stream->IMFByteStream_iface, op->u.src, op->requested_length, &op->actual_length);
4452 if(FAILED(hr)) TRACE("Write failed: %#lx\n", hr);
4453 IMFAsyncResult_SetStatus(op->caller, hr);
4454 list_add_tail(&stream->pending, &op->entry);
4456 LeaveCriticalSection(&stream->cs);
4458 MFInvokeCallback(op->caller);
4460 return S_OK;
4463 static const IRtwqAsyncCallbackVtbl bytestream_read_callback_vtbl =
4465 bytestream_callback_QueryInterface,
4466 bytestream_read_callback_AddRef,
4467 bytestream_read_callback_Release,
4468 bytestream_callback_GetParameters,
4469 bytestream_read_callback_Invoke,
4472 static const IRtwqAsyncCallbackVtbl bytestream_write_callback_vtbl =
4474 bytestream_callback_QueryInterface,
4475 bytestream_write_callback_AddRef,
4476 bytestream_write_callback_Release,
4477 bytestream_callback_GetParameters,
4478 bytestream_write_callback_Invoke,
4481 /***********************************************************************
4482 * MFCreateMFByteStreamOnStream (mfplat.@)
4484 HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **bytestream)
4486 struct bytestream *object;
4487 LARGE_INTEGER position;
4488 STATSTG stat;
4489 HRESULT hr;
4491 TRACE("%p, %p.\n", stream, bytestream);
4493 if (!(object = calloc(1, sizeof(*object))))
4494 return E_OUTOFMEMORY;
4496 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
4498 free(object);
4499 return hr;
4502 object->IMFByteStream_iface.lpVtbl = &bytestream_stream_vtbl;
4503 object->attributes.IMFAttributes_iface.lpVtbl = &bytestream_attributes_vtbl;
4504 object->read_callback.lpVtbl = &bytestream_read_callback_vtbl;
4505 object->write_callback.lpVtbl = &bytestream_write_callback_vtbl;
4506 InitializeCriticalSection(&object->cs);
4507 list_init(&object->pending);
4509 object->stream = stream;
4510 IStream_AddRef(object->stream);
4511 position.QuadPart = 0;
4512 IStream_Seek(object->stream, position, STREAM_SEEK_SET, NULL);
4514 if (SUCCEEDED(IStream_Stat(object->stream, &stat, 0)))
4516 if (stat.pwcsName)
4518 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME,
4519 stat.pwcsName);
4520 CoTaskMemFree(stat.pwcsName);
4524 *bytestream = &object->IMFByteStream_iface;
4526 return S_OK;
4529 static HRESULT WINAPI bytestream_file_getservice_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
4531 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4532 return IMFByteStream_QueryInterface(&stream->IMFByteStream_iface, riid, obj);
4535 static ULONG WINAPI bytestream_file_getservice_AddRef(IMFGetService *iface)
4537 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4538 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
4541 static ULONG WINAPI bytestream_file_getservice_Release(IMFGetService *iface)
4543 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4544 return IMFByteStream_Release(&stream->IMFByteStream_iface);
4547 static HRESULT WINAPI bytestream_file_getservice_GetService(IMFGetService *iface, REFGUID service,
4548 REFIID riid, void **obj)
4550 FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
4552 return E_NOTIMPL;
4555 static const IMFGetServiceVtbl bytestream_file_getservice_vtbl =
4557 bytestream_file_getservice_QueryInterface,
4558 bytestream_file_getservice_AddRef,
4559 bytestream_file_getservice_Release,
4560 bytestream_file_getservice_GetService,
4563 static HRESULT create_file_bytestream(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4564 const WCHAR *path, BOOL is_tempfile, IMFByteStream **bytestream)
4566 DWORD capabilities = MFBYTESTREAM_IS_SEEKABLE | MFBYTESTREAM_DOES_NOT_USE_NETWORK;
4567 DWORD filecreation_disposition = 0, fileaccessmode = 0, fileattributes = 0;
4568 DWORD filesharemode = FILE_SHARE_READ | FILE_SHARE_DELETE;
4569 struct bytestream *object;
4570 FILETIME writetime;
4571 HANDLE file;
4572 HRESULT hr;
4574 switch (accessmode)
4576 case MF_ACCESSMODE_READ:
4577 fileaccessmode = GENERIC_READ;
4578 capabilities |= MFBYTESTREAM_IS_READABLE;
4579 break;
4580 case MF_ACCESSMODE_WRITE:
4581 fileaccessmode = GENERIC_WRITE;
4582 capabilities |= MFBYTESTREAM_IS_WRITABLE;
4583 break;
4584 case MF_ACCESSMODE_READWRITE:
4585 fileaccessmode = GENERIC_READ | GENERIC_WRITE;
4586 capabilities |= (MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_WRITABLE);
4587 break;
4590 switch (openmode)
4592 case MF_OPENMODE_FAIL_IF_NOT_EXIST:
4593 filecreation_disposition = OPEN_EXISTING;
4594 break;
4595 case MF_OPENMODE_FAIL_IF_EXIST:
4596 filecreation_disposition = CREATE_NEW;
4597 break;
4598 case MF_OPENMODE_RESET_IF_EXIST:
4599 filecreation_disposition = TRUNCATE_EXISTING;
4600 break;
4601 case MF_OPENMODE_APPEND_IF_EXIST:
4602 filecreation_disposition = OPEN_ALWAYS;
4603 fileaccessmode |= FILE_APPEND_DATA;
4604 break;
4605 case MF_OPENMODE_DELETE_IF_EXIST:
4606 filecreation_disposition = CREATE_ALWAYS;
4607 break;
4610 if (flags & MF_FILEFLAGS_NOBUFFERING)
4611 fileattributes |= FILE_FLAG_NO_BUFFERING;
4612 if (is_tempfile)
4613 fileattributes |= FILE_FLAG_DELETE_ON_CLOSE;
4615 /* Open HANDLE to file */
4616 file = CreateFileW(path, fileaccessmode, filesharemode, NULL, filecreation_disposition, fileattributes, 0);
4617 if (file == INVALID_HANDLE_VALUE)
4618 return HRESULT_FROM_WIN32(GetLastError());
4620 if (!(object = calloc(1, sizeof(*object))))
4622 CloseHandle(file);
4623 return E_OUTOFMEMORY;
4626 if (FAILED(hr = init_attributes_object(&object->attributes, 2)))
4628 CloseHandle(file);
4629 free(object);
4630 return hr;
4632 object->IMFByteStream_iface.lpVtbl = &bytestream_file_vtbl;
4633 object->attributes.IMFAttributes_iface.lpVtbl = &bytestream_attributes_vtbl;
4634 object->IMFGetService_iface.lpVtbl = &bytestream_file_getservice_vtbl;
4635 object->read_callback.lpVtbl = &bytestream_read_callback_vtbl;
4636 object->write_callback.lpVtbl = &bytestream_write_callback_vtbl;
4637 InitializeCriticalSection(&object->cs);
4638 list_init(&object->pending);
4639 object->capabilities = capabilities;
4640 object->hfile = file;
4642 if (!is_tempfile && GetFileTime(file, NULL, NULL, &writetime))
4644 IMFAttributes_SetBlob(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_LAST_MODIFIED_TIME,
4645 (const UINT8 *)&writetime, sizeof(writetime));
4648 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME, path);
4650 *bytestream = &object->IMFByteStream_iface;
4652 return S_OK;
4655 /***********************************************************************
4656 * MFCreateFile (mfplat.@)
4658 HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4659 const WCHAR *path, IMFByteStream **bytestream)
4661 TRACE("%d, %d, %#x, %s, %p.\n", accessmode, openmode, flags, debugstr_w(path), bytestream);
4663 return create_file_bytestream(accessmode, openmode, flags, path, FALSE, bytestream);
4666 /***********************************************************************
4667 * MFCreateTempFile (mfplat.@)
4669 HRESULT WINAPI MFCreateTempFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4670 IMFByteStream **bytestream)
4672 WCHAR name[24], tmppath[MAX_PATH], *path;
4673 ULONG64 rnd;
4674 size_t len;
4675 HRESULT hr;
4677 TRACE("%d, %d, %#x, %p.\n", accessmode, openmode, flags, bytestream);
4679 BCryptGenRandom(NULL, (UCHAR *)&rnd, sizeof(rnd), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
4680 swprintf(name, ARRAY_SIZE(name), L"MFP%llX.TMP", rnd);
4681 GetTempPathW(ARRAY_SIZE(tmppath), tmppath);
4683 len = wcslen(tmppath) + wcslen(name) + 2;
4684 if (!(path = malloc(len * sizeof(*path))))
4685 return E_OUTOFMEMORY;
4687 wcscpy(path, tmppath);
4688 PathCchAppend(path, len, name);
4690 hr = create_file_bytestream(accessmode, openmode, flags, path, TRUE, bytestream);
4692 free(path);
4694 return hr;
4697 struct bytestream_wrapper
4699 IMFByteStreamCacheControl IMFByteStreamCacheControl_iface;
4700 IMFByteStreamBuffering IMFByteStreamBuffering_iface;
4701 IMFMediaEventGenerator IMFMediaEventGenerator_iface;
4702 IMFByteStreamTimeSeek IMFByteStreamTimeSeek_iface;
4703 IMFSampleOutputStream IMFSampleOutputStream_iface;
4704 IPropertyStore IPropertyStore_iface;
4705 IMFByteStream IMFByteStream_iface;
4706 IMFAttributes IMFAttributes_iface;
4707 LONG refcount;
4709 IMFByteStreamCacheControl *cache_control;
4710 IMFByteStreamBuffering *stream_buffering;
4711 IMFMediaEventGenerator *event_generator;
4712 IMFByteStreamTimeSeek *time_seek;
4713 IMFSampleOutputStream *sample_output;
4714 IPropertyStore *propstore;
4715 IMFByteStream *stream;
4716 IMFAttributes *attributes;
4717 BOOL is_closed;
4720 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStream(IMFByteStream *iface)
4722 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStream_iface);
4725 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamCacheControl(IMFByteStreamCacheControl *iface)
4727 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamCacheControl_iface);
4730 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamBuffering(IMFByteStreamBuffering *iface)
4732 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamBuffering_iface);
4735 static struct bytestream_wrapper *impl_wrapper_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
4737 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFMediaEventGenerator_iface);
4740 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamTimeSeek(IMFByteStreamTimeSeek *iface)
4742 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamTimeSeek_iface);
4745 static struct bytestream_wrapper *impl_wrapper_from_IMFSampleOutputStream(IMFSampleOutputStream *iface)
4747 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFSampleOutputStream_iface);
4750 static struct bytestream_wrapper *impl_wrapper_from_IPropertyStore(IPropertyStore *iface)
4752 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IPropertyStore_iface);
4755 static struct bytestream_wrapper *impl_wrapper_from_IMFAttributes(IMFAttributes *iface)
4757 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFAttributes_iface);
4760 static HRESULT WINAPI bytestream_wrapper_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
4762 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4764 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
4766 if (IsEqualIID(riid, &IID_IMFByteStream) ||
4767 IsEqualIID(riid, &IID_IUnknown))
4769 *out = &wrapper->IMFByteStream_iface;
4771 else if (wrapper->cache_control && IsEqualIID(riid, &IID_IMFByteStreamCacheControl))
4773 *out = &wrapper->IMFByteStreamCacheControl_iface;
4775 else if (wrapper->stream_buffering && IsEqualIID(riid, &IID_IMFByteStreamBuffering))
4777 *out = &wrapper->IMFByteStreamBuffering_iface;
4779 else if (wrapper->event_generator && IsEqualIID(riid, &IID_IMFMediaEventGenerator))
4781 *out = &wrapper->IMFMediaEventGenerator_iface;
4783 else if (wrapper->time_seek && IsEqualIID(riid, &IID_IMFByteStreamTimeSeek))
4785 *out = &wrapper->IMFByteStreamTimeSeek_iface;
4787 else if (wrapper->sample_output && IsEqualIID(riid, &IID_IMFSampleOutputStream))
4789 *out = &wrapper->IMFSampleOutputStream_iface;
4791 else if (wrapper->propstore && IsEqualIID(riid, &IID_IPropertyStore))
4793 *out = &wrapper->IPropertyStore_iface;
4795 else if (wrapper->attributes && IsEqualIID(riid, &IID_IMFAttributes))
4797 *out = &wrapper->IMFAttributes_iface;
4799 else
4801 WARN("Unsupported %s.\n", debugstr_guid(riid));
4802 *out = NULL;
4803 return E_NOINTERFACE;
4806 IUnknown_AddRef((IUnknown *)*out);
4807 return S_OK;
4810 static ULONG WINAPI bytestream_wrapper_AddRef(IMFByteStream *iface)
4812 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4813 ULONG refcount = InterlockedIncrement(&wrapper->refcount);
4815 TRACE("%p, refcount %ld.\n", iface, refcount);
4817 return refcount;
4820 static ULONG WINAPI bytestream_wrapper_Release(IMFByteStream *iface)
4822 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4823 ULONG refcount = InterlockedDecrement(&wrapper->refcount);
4825 TRACE("%p, refcount %ld.\n", iface, refcount);
4827 if (!refcount)
4829 if (wrapper->cache_control)
4830 IMFByteStreamCacheControl_Release(wrapper->cache_control);
4831 if (wrapper->stream_buffering)
4832 IMFByteStreamBuffering_Release(wrapper->stream_buffering);
4833 if (wrapper->event_generator)
4834 IMFMediaEventGenerator_Release(wrapper->event_generator);
4835 if (wrapper->time_seek)
4836 IMFByteStreamTimeSeek_Release(wrapper->time_seek);
4837 if (wrapper->sample_output)
4838 IMFSampleOutputStream_Release(wrapper->sample_output);
4839 if (wrapper->propstore)
4840 IPropertyStore_Release(wrapper->propstore);
4841 if (wrapper->attributes)
4842 IMFAttributes_Release(wrapper->attributes);
4843 IMFByteStream_Release(wrapper->stream);
4844 free(wrapper);
4847 return refcount;
4850 static HRESULT WINAPI bytestream_wrapper_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
4852 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4854 TRACE("%p, %p.\n", iface, capabilities);
4856 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4857 IMFByteStream_GetCapabilities(wrapper->stream, capabilities);
4860 static HRESULT WINAPI bytestream_wrapper_GetLength(IMFByteStream *iface, QWORD *length)
4862 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4864 TRACE("%p, %p.\n", iface, length);
4866 if (wrapper->is_closed)
4867 return MF_E_INVALIDREQUEST;
4869 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4870 IMFByteStream_GetLength(wrapper->stream, length);
4873 static HRESULT WINAPI bytestream_wrapper_SetLength(IMFByteStream *iface, QWORD length)
4875 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4877 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4879 if (wrapper->is_closed)
4880 return MF_E_INVALIDREQUEST;
4882 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4883 IMFByteStream_SetLength(wrapper->stream, length);
4886 static HRESULT WINAPI bytestream_wrapper_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4888 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4890 TRACE("%p, %p.\n", iface, position);
4892 if (wrapper->is_closed)
4893 return MF_E_INVALIDREQUEST;
4895 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4896 IMFByteStream_GetCurrentPosition(wrapper->stream, position);
4899 static HRESULT WINAPI bytestream_wrapper_SetCurrentPosition(IMFByteStream *iface, QWORD position)
4901 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4903 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4905 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4906 IMFByteStream_SetCurrentPosition(wrapper->stream, position);
4909 static HRESULT WINAPI bytestream_wrapper_IsEndOfStream(IMFByteStream *iface, BOOL *eos)
4911 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4913 TRACE("%p, %p.\n", iface, eos);
4915 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4916 IMFByteStream_IsEndOfStream(wrapper->stream, eos);
4919 static HRESULT WINAPI bytestream_wrapper_Read(IMFByteStream *iface, BYTE *data, ULONG count, ULONG *byte_read)
4921 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4923 TRACE("%p, %p, %lu, %p.\n", iface, data, count, byte_read);
4925 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4926 IMFByteStream_Read(wrapper->stream, data, count, byte_read);
4929 static HRESULT WINAPI bytestream_wrapper_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size,
4930 IMFAsyncCallback *callback, IUnknown *state)
4932 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4934 TRACE("%p, %p, %lu, %p, %p.\n", iface, data, size, callback, state);
4936 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4937 IMFByteStream_BeginRead(wrapper->stream, data, size, callback, state);
4940 static HRESULT WINAPI bytestream_wrapper_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
4942 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4944 TRACE("%p, %p, %p.\n", iface, result, byte_read);
4946 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4947 IMFByteStream_EndRead(wrapper->stream, result, byte_read);
4950 static HRESULT WINAPI bytestream_wrapper_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
4952 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4954 TRACE("%p, %p, %lu, %p.\n", iface, data, count, written);
4956 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4957 IMFByteStream_Write(wrapper->stream, data, count, written);
4960 static HRESULT WINAPI bytestream_wrapper_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
4961 IMFAsyncCallback *callback, IUnknown *state)
4963 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4965 TRACE("%p, %p, %lu, %p, %p.\n", iface, data, size, callback, state);
4967 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4968 IMFByteStream_BeginWrite(wrapper->stream, data, size, callback, state);
4971 static HRESULT WINAPI bytestream_wrapper_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
4973 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4975 TRACE("%p, %p, %p.\n", iface, result, written);
4977 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4978 IMFByteStream_EndWrite(wrapper->stream, result, written);
4981 static HRESULT WINAPI bytestream_wrapper_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
4982 DWORD flags, QWORD *current)
4984 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4986 TRACE("%p, %u, %s, %#lx, %p.\n", iface, seek, wine_dbgstr_longlong(offset), flags, current);
4988 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4989 IMFByteStream_Seek(wrapper->stream, seek, offset, flags, current);
4992 static HRESULT WINAPI bytestream_wrapper_Flush(IMFByteStream *iface)
4994 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4996 TRACE("%p\n", iface);
4998 return wrapper->is_closed ? MF_E_INVALIDREQUEST : IMFByteStream_Flush(wrapper->stream);
5001 static HRESULT WINAPI bytestream_wrapper_Close(IMFByteStream *iface)
5003 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
5005 TRACE("%p\n", iface);
5007 wrapper->is_closed = TRUE;
5009 return S_OK;
5012 static const IMFByteStreamVtbl bytestream_wrapper_vtbl =
5014 bytestream_wrapper_QueryInterface,
5015 bytestream_wrapper_AddRef,
5016 bytestream_wrapper_Release,
5017 bytestream_wrapper_GetCapabilities,
5018 bytestream_wrapper_GetLength,
5019 bytestream_wrapper_SetLength,
5020 bytestream_wrapper_GetCurrentPosition,
5021 bytestream_wrapper_SetCurrentPosition,
5022 bytestream_wrapper_IsEndOfStream,
5023 bytestream_wrapper_Read,
5024 bytestream_wrapper_BeginRead,
5025 bytestream_wrapper_EndRead,
5026 bytestream_wrapper_Write,
5027 bytestream_wrapper_BeginWrite,
5028 bytestream_wrapper_EndWrite,
5029 bytestream_wrapper_Seek,
5030 bytestream_wrapper_Flush,
5031 bytestream_wrapper_Close,
5034 static HRESULT WINAPI bytestream_wrapper_cache_control_QueryInterface(IMFByteStreamCacheControl *iface,
5035 REFIID riid, void **obj)
5037 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
5038 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5041 static ULONG WINAPI bytestream_wrapper_cache_control_AddRef(IMFByteStreamCacheControl *iface)
5043 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
5044 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5047 static ULONG WINAPI bytestream_wrapper_cache_control_Release(IMFByteStreamCacheControl *iface)
5049 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
5050 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5053 static HRESULT WINAPI bytestream_wrapper_cache_control_StopBackgroundTransfer(IMFByteStreamCacheControl *iface)
5055 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
5057 TRACE("%p.\n", iface);
5059 return IMFByteStreamCacheControl_StopBackgroundTransfer(wrapper->cache_control);
5062 static const IMFByteStreamCacheControlVtbl bytestream_wrapper_cache_control_vtbl =
5064 bytestream_wrapper_cache_control_QueryInterface,
5065 bytestream_wrapper_cache_control_AddRef,
5066 bytestream_wrapper_cache_control_Release,
5067 bytestream_wrapper_cache_control_StopBackgroundTransfer,
5070 static HRESULT WINAPI bytestream_wrapper_buffering_QueryInterface(IMFByteStreamBuffering *iface,
5071 REFIID riid, void **obj)
5073 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5074 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5077 static ULONG WINAPI bytestream_wrapper_buffering_AddRef(IMFByteStreamBuffering *iface)
5079 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5080 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5083 static ULONG WINAPI bytestream_wrapper_buffering_Release(IMFByteStreamBuffering *iface)
5085 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5086 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5089 static HRESULT WINAPI bytestream_wrapper_buffering_SetBufferingParams(IMFByteStreamBuffering *iface,
5090 MFBYTESTREAM_BUFFERING_PARAMS *params)
5092 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5094 TRACE("%p, %p.\n", iface, params);
5096 return IMFByteStreamBuffering_SetBufferingParams(wrapper->stream_buffering, params);
5099 static HRESULT WINAPI bytestream_wrapper_buffering_EnableBuffering(IMFByteStreamBuffering *iface,
5100 BOOL enable)
5102 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5104 TRACE("%p, %d.\n", iface, enable);
5106 return IMFByteStreamBuffering_EnableBuffering(wrapper->stream_buffering, enable);
5109 static HRESULT WINAPI bytestream_wrapper_buffering_StopBuffering(IMFByteStreamBuffering *iface)
5111 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5113 TRACE("%p.\n", iface);
5115 return IMFByteStreamBuffering_StopBuffering(wrapper->stream_buffering);
5118 static const IMFByteStreamBufferingVtbl bytestream_wrapper_buffering_vtbl =
5120 bytestream_wrapper_buffering_QueryInterface,
5121 bytestream_wrapper_buffering_AddRef,
5122 bytestream_wrapper_buffering_Release,
5123 bytestream_wrapper_buffering_SetBufferingParams,
5124 bytestream_wrapper_buffering_EnableBuffering,
5125 bytestream_wrapper_buffering_StopBuffering,
5128 static HRESULT WINAPI bytestream_wrapper_timeseek_QueryInterface(IMFByteStreamTimeSeek *iface,
5129 REFIID riid, void **obj)
5131 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5132 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5135 static ULONG WINAPI bytestream_wrapper_timeseek_AddRef(IMFByteStreamTimeSeek *iface)
5137 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5138 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5141 static ULONG WINAPI bytestream_wrapper_timeseek_Release(IMFByteStreamTimeSeek *iface)
5143 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5144 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5147 static HRESULT WINAPI bytestream_wrapper_timeseek_IsTimeSeekSupported(IMFByteStreamTimeSeek *iface, BOOL *result)
5149 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5151 TRACE("%p, %p.\n", iface, result);
5153 return IMFByteStreamTimeSeek_IsTimeSeekSupported(wrapper->time_seek, result);
5156 static HRESULT WINAPI bytestream_wrapper_timeseek_TimeSeek(IMFByteStreamTimeSeek *iface, QWORD position)
5158 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5160 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
5162 return IMFByteStreamTimeSeek_TimeSeek(wrapper->time_seek, position);
5165 static HRESULT WINAPI bytestream_wrapper_timeseek_GetTimeSeekResult(IMFByteStreamTimeSeek *iface, QWORD *start_time,
5166 QWORD *stop_time, QWORD *duration)
5168 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5170 TRACE("%p, %p, %p, %p.\n", iface, start_time, stop_time, duration);
5172 return IMFByteStreamTimeSeek_GetTimeSeekResult(wrapper->time_seek, start_time, stop_time, duration);
5175 static const IMFByteStreamTimeSeekVtbl bytestream_wrapper_timeseek_vtbl =
5177 bytestream_wrapper_timeseek_QueryInterface,
5178 bytestream_wrapper_timeseek_AddRef,
5179 bytestream_wrapper_timeseek_Release,
5180 bytestream_wrapper_timeseek_IsTimeSeekSupported,
5181 bytestream_wrapper_timeseek_TimeSeek,
5182 bytestream_wrapper_timeseek_GetTimeSeekResult,
5185 static HRESULT WINAPI bytestream_wrapper_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
5187 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5188 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5191 static ULONG WINAPI bytestream_wrapper_events_AddRef(IMFMediaEventGenerator *iface)
5193 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5194 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5197 static ULONG WINAPI bytestream_wrapper_events_Release(IMFMediaEventGenerator *iface)
5199 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5200 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5203 static HRESULT WINAPI bytestream_wrapper_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
5205 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5207 TRACE("%p, %#lx, %p.\n", iface, flags, event);
5209 return IMFMediaEventGenerator_GetEvent(wrapper->event_generator, flags, event);
5212 static HRESULT WINAPI bytestream_wrapper_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback, IUnknown *state)
5214 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5216 TRACE("%p, %p, %p.\n", iface, callback, state);
5218 return IMFMediaEventGenerator_BeginGetEvent(wrapper->event_generator, callback, state);
5221 static HRESULT WINAPI bytestream_wrapper_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result, IMFMediaEvent **event)
5223 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5225 TRACE("%p, %p, %p.\n", iface, result, event);
5227 return IMFMediaEventGenerator_EndGetEvent(wrapper->event_generator, result, event);
5230 static HRESULT WINAPI bytestream_wrapper_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType type,
5231 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
5233 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5235 TRACE("%p, %ld, %s, %#lx, %s.\n", iface, type, debugstr_guid(ext_type), hr, debugstr_propvar(value));
5237 return IMFMediaEventGenerator_QueueEvent(wrapper->event_generator, type, ext_type, hr, value);
5240 static const IMFMediaEventGeneratorVtbl bytestream_wrapper_events_vtbl =
5242 bytestream_wrapper_events_QueryInterface,
5243 bytestream_wrapper_events_AddRef,
5244 bytestream_wrapper_events_Release,
5245 bytestream_wrapper_events_GetEvent,
5246 bytestream_wrapper_events_BeginGetEvent,
5247 bytestream_wrapper_events_EndGetEvent,
5248 bytestream_wrapper_events_QueueEvent,
5251 static HRESULT WINAPI bytestream_wrapper_sample_output_QueryInterface(IMFSampleOutputStream *iface, REFIID riid, void **obj)
5253 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5254 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5257 static ULONG WINAPI bytestream_wrapper_sample_output_AddRef(IMFSampleOutputStream *iface)
5259 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5260 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5263 static ULONG WINAPI bytestream_wrapper_sample_output_Release(IMFSampleOutputStream *iface)
5265 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5266 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5269 static HRESULT WINAPI bytestream_wrapper_sample_output_BeginWriteSample(IMFSampleOutputStream *iface, IMFSample *sample,
5270 IMFAsyncCallback *callback, IUnknown *state)
5272 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5274 TRACE("%p, %p, %p, %p.\n", iface, sample, callback, state);
5276 return IMFSampleOutputStream_BeginWriteSample(wrapper->sample_output, sample, callback, state);
5279 static HRESULT WINAPI bytestream_wrapper_sample_output_EndWriteSample(IMFSampleOutputStream *iface, IMFAsyncResult *result)
5281 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5283 TRACE("%p, %p.\n", iface, result);
5285 return IMFSampleOutputStream_EndWriteSample(wrapper->sample_output, result);
5288 static HRESULT WINAPI bytestream_wrapper_sample_output_Close(IMFSampleOutputStream *iface)
5290 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5292 TRACE("%p.\n", iface);
5294 return IMFSampleOutputStream_Close(wrapper->sample_output);
5297 static const IMFSampleOutputStreamVtbl bytestream_wrapper_sample_output_vtbl =
5299 bytestream_wrapper_sample_output_QueryInterface,
5300 bytestream_wrapper_sample_output_AddRef,
5301 bytestream_wrapper_sample_output_Release,
5302 bytestream_wrapper_sample_output_BeginWriteSample,
5303 bytestream_wrapper_sample_output_EndWriteSample,
5304 bytestream_wrapper_sample_output_Close,
5307 static HRESULT WINAPI bytestream_wrapper_propstore_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
5309 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5310 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5313 static ULONG WINAPI bytestream_wrapper_propstore_AddRef(IPropertyStore *iface)
5315 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5316 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5319 static ULONG WINAPI bytestream_wrapper_propstore_Release(IPropertyStore *iface)
5321 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5322 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5325 static HRESULT WINAPI bytestream_wrapper_propstore_GetCount(IPropertyStore *iface, DWORD *count)
5327 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5329 TRACE("%p, %p.\n", iface, count);
5331 return IPropertyStore_GetCount(wrapper->propstore, count);
5334 static HRESULT WINAPI bytestream_wrapper_propstore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
5336 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5338 TRACE("%p, %lu, %p.\n", iface, prop, key);
5340 return IPropertyStore_GetAt(wrapper->propstore, prop, key);
5343 static HRESULT WINAPI bytestream_wrapper_propstore_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
5345 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5347 TRACE("%p, %p, %p.\n", iface, key, value);
5349 return IPropertyStore_GetValue(wrapper->propstore, key, value);
5352 static HRESULT WINAPI bytestream_wrapper_propstore_SetValue(IPropertyStore *iface, REFPROPERTYKEY key,
5353 const PROPVARIANT *value)
5355 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5357 TRACE("%p, %p, %s.\n", iface, key, debugstr_propvar(value));
5359 return IPropertyStore_SetValue(wrapper->propstore, key, value);
5362 static HRESULT WINAPI bytestream_wrapper_propstore_Commit(IPropertyStore *iface)
5364 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5366 TRACE("%p.\n", iface);
5368 return IPropertyStore_Commit(wrapper->propstore);
5371 static const IPropertyStoreVtbl bytestream_wrapper_propstore_vtbl =
5373 bytestream_wrapper_propstore_QueryInterface,
5374 bytestream_wrapper_propstore_AddRef,
5375 bytestream_wrapper_propstore_Release,
5376 bytestream_wrapper_propstore_GetCount,
5377 bytestream_wrapper_propstore_GetAt,
5378 bytestream_wrapper_propstore_GetValue,
5379 bytestream_wrapper_propstore_SetValue,
5380 bytestream_wrapper_propstore_Commit,
5383 static HRESULT WINAPI bytestream_wrapper_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
5385 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5386 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5389 static ULONG WINAPI bytestream_wrapper_attributes_AddRef(IMFAttributes *iface)
5391 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5392 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5395 static ULONG WINAPI bytestream_wrapper_attributes_Release(IMFAttributes *iface)
5397 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5398 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5401 static HRESULT WINAPI bytestream_wrapper_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
5403 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5405 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5407 return IMFAttributes_GetItem(wrapper->attributes, key, value);
5410 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
5412 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5414 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
5416 return IMFAttributes_GetItemType(wrapper->attributes, key, type);
5419 static HRESULT WINAPI bytestream_wrapper_attributes_CompareItem(IMFAttributes *iface, REFGUID key,
5420 REFPROPVARIANT value, BOOL *result)
5422 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5424 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
5426 return IMFAttributes_CompareItem(wrapper->attributes, key, value, result);
5429 static HRESULT WINAPI bytestream_wrapper_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
5430 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
5432 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5434 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
5436 return IMFAttributes_Compare(wrapper->attributes, theirs, match_type, ret);
5439 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
5441 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5443 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5445 return IMFAttributes_GetUINT32(wrapper->attributes, key, value);
5448 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
5450 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5452 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5454 return IMFAttributes_GetUINT64(wrapper->attributes, key, value);
5457 static HRESULT WINAPI bytestream_wrapper_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
5459 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5461 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5463 return IMFAttributes_GetDouble(wrapper->attributes, key, value);
5466 static HRESULT WINAPI bytestream_wrapper_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
5468 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5470 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5472 return IMFAttributes_GetGUID(wrapper->attributes, key, value);
5475 static HRESULT WINAPI bytestream_wrapper_attributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
5477 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5479 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
5481 return IMFAttributes_GetStringLength(wrapper->attributes, key, length);
5484 static HRESULT WINAPI bytestream_wrapper_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
5485 UINT32 size, UINT32 *length)
5487 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5489 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
5491 return IMFAttributes_GetString(wrapper->attributes, key, value, size, length);
5494 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
5496 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5498 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
5500 return IMFAttributes_GetAllocatedString(wrapper->attributes, key, value, length);
5503 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
5505 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5507 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
5509 return IMFAttributes_GetBlobSize(wrapper->attributes, key, size);
5512 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
5513 UINT32 bufsize, UINT32 *blobsize)
5515 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5517 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
5519 return IMFAttributes_GetBlob(wrapper->attributes, key, buf, bufsize, blobsize);
5522 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
5524 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5526 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
5528 return IMFAttributes_GetAllocatedBlob(wrapper->attributes, key, buf, size);
5531 static HRESULT WINAPI bytestream_wrapper_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **obj)
5533 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5535 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), obj);
5537 return IMFAttributes_GetUnknown(wrapper->attributes, key, riid, obj);
5540 static HRESULT WINAPI bytestream_wrapper_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
5542 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5544 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
5546 return IMFAttributes_SetItem(wrapper->attributes, key, value);
5549 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
5551 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5553 TRACE("%p, %s.\n", iface, debugstr_attr(key));
5555 return IMFAttributes_DeleteItem(wrapper->attributes, key);
5558 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteAllItems(IMFAttributes *iface)
5560 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5562 TRACE("%p.\n", iface);
5564 return IMFAttributes_DeleteAllItems(wrapper->attributes);
5567 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
5569 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5571 TRACE("%p, %s, %d.\n", iface, debugstr_attr(key), value);
5573 return IMFAttributes_SetUINT32(wrapper->attributes, key, value);
5576 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
5578 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5580 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
5582 return IMFAttributes_SetUINT64(wrapper->attributes, key, value);
5585 static HRESULT WINAPI bytestream_wrapper_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
5587 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5589 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
5591 return IMFAttributes_SetDouble(wrapper->attributes, key, value);
5594 static HRESULT WINAPI bytestream_wrapper_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
5596 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5598 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
5600 return IMFAttributes_SetGUID(wrapper->attributes, key, value);
5603 static HRESULT WINAPI bytestream_wrapper_attributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
5605 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5607 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
5609 return IMFAttributes_SetString(wrapper->attributes, key, value);
5612 static HRESULT WINAPI bytestream_wrapper_attributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
5614 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5616 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
5618 return IMFAttributes_SetBlob(wrapper->attributes, key, buf, size);
5621 static HRESULT WINAPI bytestream_wrapper_attributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
5623 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5625 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
5627 return IMFAttributes_SetUnknown(wrapper->attributes, key, unknown);
5630 static HRESULT WINAPI bytestream_wrapper_attributes_LockStore(IMFAttributes *iface)
5632 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5634 TRACE("%p.\n", iface);
5636 return IMFAttributes_LockStore(wrapper->attributes);
5639 static HRESULT WINAPI bytestream_wrapper_attributes_UnlockStore(IMFAttributes *iface)
5641 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5643 TRACE("%p.\n", iface);
5645 return IMFAttributes_UnlockStore(wrapper->attributes);
5648 static HRESULT WINAPI bytestream_wrapper_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
5650 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5652 TRACE("%p, %p.\n", iface, count);
5654 return IMFAttributes_GetCount(wrapper->attributes, count);
5657 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
5659 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5661 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
5663 return IMFAttributes_GetItemByIndex(wrapper->attributes, index, key, value);
5666 static HRESULT WINAPI bytestream_wrapper_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
5668 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5670 TRACE("%p, %p.\n", iface, dest);
5672 return IMFAttributes_CopyAllItems(wrapper->attributes, dest);
5675 static const IMFAttributesVtbl bytestream_wrapper_attributes_vtbl =
5677 bytestream_wrapper_attributes_QueryInterface,
5678 bytestream_wrapper_attributes_AddRef,
5679 bytestream_wrapper_attributes_Release,
5680 bytestream_wrapper_attributes_GetItem,
5681 bytestream_wrapper_attributes_GetItemType,
5682 bytestream_wrapper_attributes_CompareItem,
5683 bytestream_wrapper_attributes_Compare,
5684 bytestream_wrapper_attributes_GetUINT32,
5685 bytestream_wrapper_attributes_GetUINT64,
5686 bytestream_wrapper_attributes_GetDouble,
5687 bytestream_wrapper_attributes_GetGUID,
5688 bytestream_wrapper_attributes_GetStringLength,
5689 bytestream_wrapper_attributes_GetString,
5690 bytestream_wrapper_attributes_GetAllocatedString,
5691 bytestream_wrapper_attributes_GetBlobSize,
5692 bytestream_wrapper_attributes_GetBlob,
5693 bytestream_wrapper_attributes_GetAllocatedBlob,
5694 bytestream_wrapper_attributes_GetUnknown,
5695 bytestream_wrapper_attributes_SetItem,
5696 bytestream_wrapper_attributes_DeleteItem,
5697 bytestream_wrapper_attributes_DeleteAllItems,
5698 bytestream_wrapper_attributes_SetUINT32,
5699 bytestream_wrapper_attributes_SetUINT64,
5700 bytestream_wrapper_attributes_SetDouble,
5701 bytestream_wrapper_attributes_SetGUID,
5702 bytestream_wrapper_attributes_SetString,
5703 bytestream_wrapper_attributes_SetBlob,
5704 bytestream_wrapper_attributes_SetUnknown,
5705 bytestream_wrapper_attributes_LockStore,
5706 bytestream_wrapper_attributes_UnlockStore,
5707 bytestream_wrapper_attributes_GetCount,
5708 bytestream_wrapper_attributes_GetItemByIndex,
5709 bytestream_wrapper_attributes_CopyAllItems
5712 /***********************************************************************
5713 * MFCreateMFByteStreamWrapper (mfplat.@)
5715 HRESULT WINAPI MFCreateMFByteStreamWrapper(IMFByteStream *stream, IMFByteStream **wrapper)
5717 struct bytestream_wrapper *object;
5719 TRACE("%p, %p.\n", stream, wrapper);
5721 if (!(object = calloc(1, sizeof(*object))))
5722 return E_OUTOFMEMORY;
5724 object->IMFByteStreamCacheControl_iface.lpVtbl = &bytestream_wrapper_cache_control_vtbl;
5725 object->IMFByteStreamBuffering_iface.lpVtbl = &bytestream_wrapper_buffering_vtbl;
5726 object->IMFMediaEventGenerator_iface.lpVtbl = &bytestream_wrapper_events_vtbl;
5727 object->IMFByteStreamTimeSeek_iface.lpVtbl = &bytestream_wrapper_timeseek_vtbl;
5728 object->IMFSampleOutputStream_iface.lpVtbl = &bytestream_wrapper_sample_output_vtbl;
5729 object->IMFByteStream_iface.lpVtbl = &bytestream_wrapper_vtbl;
5730 object->IPropertyStore_iface.lpVtbl = &bytestream_wrapper_propstore_vtbl;
5731 object->IMFAttributes_iface.lpVtbl = &bytestream_wrapper_attributes_vtbl;
5733 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamCacheControl, (void **)&object->cache_control);
5734 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamBuffering, (void **)&object->stream_buffering);
5735 IMFByteStream_QueryInterface(stream, &IID_IMFMediaEventGenerator, (void **)&object->event_generator);
5736 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamTimeSeek, (void **)&object->time_seek);
5737 IMFByteStream_QueryInterface(stream, &IID_IMFSampleOutputStream, (void **)&object->sample_output);
5738 IMFByteStream_QueryInterface(stream, &IID_IPropertyStore, (void **)&object->propstore);
5739 IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&object->attributes);
5741 object->stream = stream;
5742 IMFByteStream_AddRef(object->stream);
5744 object->refcount = 1;
5746 *wrapper = &object->IMFByteStream_iface;
5748 return S_OK;
5751 static HRESULT WINAPI MFPluginControl_QueryInterface(IMFPluginControl *iface, REFIID riid, void **ppv)
5753 if(IsEqualGUID(riid, &IID_IUnknown)) {
5754 TRACE("(IID_IUnknown %p)\n", ppv);
5755 *ppv = iface;
5756 }else if(IsEqualGUID(riid, &IID_IMFPluginControl)) {
5757 TRACE("(IID_IMFPluginControl %p)\n", ppv);
5758 *ppv = iface;
5759 }else {
5760 FIXME("(%s %p)\n", debugstr_guid(riid), ppv);
5761 *ppv = NULL;
5762 return E_NOINTERFACE;
5765 IUnknown_AddRef((IUnknown*)*ppv);
5766 return S_OK;
5769 static ULONG WINAPI MFPluginControl_AddRef(IMFPluginControl *iface)
5771 TRACE("\n");
5772 return 2;
5775 static ULONG WINAPI MFPluginControl_Release(IMFPluginControl *iface)
5777 TRACE("\n");
5778 return 1;
5781 static HRESULT WINAPI MFPluginControl_GetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5782 const WCHAR *selector, CLSID *clsid)
5784 FIXME("(%ld %s %p)\n", plugin_type, debugstr_w(selector), clsid);
5785 return E_NOTIMPL;
5788 static HRESULT WINAPI MFPluginControl_GetPreferredClsidByIndex(IMFPluginControl *iface, DWORD plugin_type,
5789 DWORD index, WCHAR **selector, CLSID *clsid)
5791 FIXME("(%ld %ld %p %p)\n", plugin_type, index, selector, clsid);
5792 return E_NOTIMPL;
5795 static HRESULT WINAPI MFPluginControl_SetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5796 const WCHAR *selector, const CLSID *clsid)
5798 FIXME("(%ld %s %s)\n", plugin_type, debugstr_w(selector), debugstr_guid(clsid));
5799 return E_NOTIMPL;
5802 static HRESULT WINAPI MFPluginControl_IsDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid)
5804 FIXME("(%ld %s)\n", plugin_type, debugstr_guid(clsid));
5805 return E_NOTIMPL;
5808 static HRESULT WINAPI MFPluginControl_GetDisabledByIndex(IMFPluginControl *iface, DWORD plugin_type, DWORD index, CLSID *clsid)
5810 FIXME("(%ld %ld %p)\n", plugin_type, index, clsid);
5811 return E_NOTIMPL;
5814 static HRESULT WINAPI MFPluginControl_SetDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid, BOOL disabled)
5816 FIXME("(%ld %s %x)\n", plugin_type, debugstr_guid(clsid), disabled);
5817 return E_NOTIMPL;
5820 static const IMFPluginControlVtbl MFPluginControlVtbl = {
5821 MFPluginControl_QueryInterface,
5822 MFPluginControl_AddRef,
5823 MFPluginControl_Release,
5824 MFPluginControl_GetPreferredClsid,
5825 MFPluginControl_GetPreferredClsidByIndex,
5826 MFPluginControl_SetPreferredClsid,
5827 MFPluginControl_IsDisabled,
5828 MFPluginControl_GetDisabledByIndex,
5829 MFPluginControl_SetDisabled
5832 static IMFPluginControl plugin_control = { &MFPluginControlVtbl };
5834 /***********************************************************************
5835 * MFGetPluginControl (mfplat.@)
5837 HRESULT WINAPI MFGetPluginControl(IMFPluginControl **ret)
5839 TRACE("(%p)\n", ret);
5841 *ret = &plugin_control;
5842 return S_OK;
5845 enum resolved_object_origin
5847 OBJECT_FROM_BYTESTREAM,
5848 OBJECT_FROM_URL,
5851 struct resolver_queued_result
5853 struct list entry;
5854 IUnknown *object;
5855 MF_OBJECT_TYPE obj_type;
5856 HRESULT hr;
5857 IRtwqAsyncResult *inner_result;
5858 enum resolved_object_origin origin;
5861 struct resolver_cancel_object
5863 IUnknown IUnknown_iface;
5864 LONG refcount;
5865 union
5867 IUnknown *handler;
5868 IMFByteStreamHandler *stream_handler;
5869 IMFSchemeHandler *scheme_handler;
5870 } u;
5871 IUnknown *cancel_cookie;
5872 enum resolved_object_origin origin;
5875 struct source_resolver
5877 IMFSourceResolver IMFSourceResolver_iface;
5878 LONG refcount;
5879 IRtwqAsyncCallback stream_callback;
5880 IRtwqAsyncCallback url_callback;
5881 CRITICAL_SECTION cs;
5882 struct list pending;
5885 static struct source_resolver *impl_from_IMFSourceResolver(IMFSourceResolver *iface)
5887 return CONTAINING_RECORD(iface, struct source_resolver, IMFSourceResolver_iface);
5890 static struct source_resolver *impl_from_stream_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5892 return CONTAINING_RECORD(iface, struct source_resolver, stream_callback);
5895 static struct source_resolver *impl_from_url_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5897 return CONTAINING_RECORD(iface, struct source_resolver, url_callback);
5900 static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enum resolved_object_origin origin,
5901 IRtwqAsyncResult *result)
5903 IRtwqAsyncResult *inner_result = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
5904 RTWQASYNCRESULT *data = (RTWQASYNCRESULT *)inner_result;
5905 struct resolver_queued_result *queued_result;
5906 union
5908 IUnknown *handler;
5909 IMFByteStreamHandler *stream_handler;
5910 IMFSchemeHandler *scheme_handler;
5911 } handler;
5913 if (!(queued_result = calloc(1, sizeof(*queued_result))))
5914 return E_OUTOFMEMORY;
5916 queued_result->origin = origin;
5918 IRtwqAsyncResult_GetObject(inner_result, &handler.handler);
5920 switch (origin)
5922 case OBJECT_FROM_BYTESTREAM:
5923 queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, (IMFAsyncResult *)result,
5924 &queued_result->obj_type, &queued_result->object);
5925 break;
5926 case OBJECT_FROM_URL:
5927 queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, (IMFAsyncResult *)result,
5928 &queued_result->obj_type, &queued_result->object);
5929 break;
5930 default:
5931 queued_result->hr = E_FAIL;
5934 IUnknown_Release(handler.handler);
5936 if (data->hEvent)
5938 queued_result->inner_result = inner_result;
5939 IRtwqAsyncResult_AddRef(queued_result->inner_result);
5942 /* Push resolved object type and created object, so we don't have to guess on End*() call. */
5943 EnterCriticalSection(&resolver->cs);
5944 list_add_tail(&resolver->pending, &queued_result->entry);
5945 LeaveCriticalSection(&resolver->cs);
5947 if (data->hEvent)
5948 SetEvent(data->hEvent);
5949 else
5951 IUnknown *caller_state = IRtwqAsyncResult_GetStateNoAddRef(inner_result);
5952 IRtwqAsyncResult *caller_result;
5954 if (SUCCEEDED(RtwqCreateAsyncResult(queued_result->object, data->pCallback, caller_state, &caller_result)))
5956 RtwqInvokeCallback(caller_result);
5957 IRtwqAsyncResult_Release(caller_result);
5961 return S_OK;
5964 static struct resolver_cancel_object *impl_cancel_obj_from_IUnknown(IUnknown *iface)
5966 return CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface);
5969 static HRESULT WINAPI resolver_cancel_object_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
5971 if (IsEqualIID(riid, &IID_IUnknown))
5973 *obj = iface;
5974 IUnknown_AddRef(iface);
5975 return S_OK;
5978 *obj = NULL;
5979 return E_NOINTERFACE;
5982 static ULONG WINAPI resolver_cancel_object_AddRef(IUnknown *iface)
5984 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5985 return InterlockedIncrement(&object->refcount);
5988 static ULONG WINAPI resolver_cancel_object_Release(IUnknown *iface)
5990 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5991 ULONG refcount = InterlockedDecrement(&object->refcount);
5993 if (!refcount)
5995 if (object->cancel_cookie)
5996 IUnknown_Release(object->cancel_cookie);
5997 IUnknown_Release(object->u.handler);
5998 free(object);
6001 return refcount;
6004 static const IUnknownVtbl resolver_cancel_object_vtbl =
6006 resolver_cancel_object_QueryInterface,
6007 resolver_cancel_object_AddRef,
6008 resolver_cancel_object_Release,
6011 static struct resolver_cancel_object *unsafe_impl_cancel_obj_from_IUnknown(IUnknown *iface)
6013 if (!iface)
6014 return NULL;
6016 return (iface->lpVtbl == &resolver_cancel_object_vtbl) ?
6017 CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface) : NULL;
6020 static HRESULT resolver_create_cancel_object(IUnknown *handler, enum resolved_object_origin origin,
6021 IUnknown *cancel_cookie, IUnknown **cancel_object)
6023 struct resolver_cancel_object *object;
6025 if (!(object = calloc(1, sizeof(*object))))
6026 return E_OUTOFMEMORY;
6028 object->IUnknown_iface.lpVtbl = &resolver_cancel_object_vtbl;
6029 object->refcount = 1;
6030 object->u.handler = handler;
6031 IUnknown_AddRef(object->u.handler);
6032 object->cancel_cookie = cancel_cookie;
6033 IUnknown_AddRef(object->cancel_cookie);
6034 object->origin = origin;
6036 *cancel_object = &object->IUnknown_iface;
6038 return S_OK;
6041 static HRESULT WINAPI source_resolver_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
6043 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
6044 IsEqualIID(riid, &IID_IUnknown))
6046 *obj = iface;
6047 IRtwqAsyncCallback_AddRef(iface);
6048 return S_OK;
6051 *obj = NULL;
6052 return E_NOINTERFACE;
6055 static ULONG WINAPI source_resolver_callback_stream_AddRef(IRtwqAsyncCallback *iface)
6057 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
6058 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
6061 static ULONG WINAPI source_resolver_callback_stream_Release(IRtwqAsyncCallback *iface)
6063 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
6064 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
6067 static HRESULT WINAPI source_resolver_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
6069 return E_NOTIMPL;
6072 static HRESULT WINAPI source_resolver_callback_stream_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
6074 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
6076 return resolver_handler_end_create(resolver, OBJECT_FROM_BYTESTREAM, result);
6079 static const IRtwqAsyncCallbackVtbl source_resolver_callback_stream_vtbl =
6081 source_resolver_callback_QueryInterface,
6082 source_resolver_callback_stream_AddRef,
6083 source_resolver_callback_stream_Release,
6084 source_resolver_callback_GetParameters,
6085 source_resolver_callback_stream_Invoke,
6088 static ULONG WINAPI source_resolver_callback_url_AddRef(IRtwqAsyncCallback *iface)
6090 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
6091 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
6094 static ULONG WINAPI source_resolver_callback_url_Release(IRtwqAsyncCallback *iface)
6096 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
6097 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
6100 static HRESULT WINAPI source_resolver_callback_url_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
6102 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
6104 return resolver_handler_end_create(resolver, OBJECT_FROM_URL, result);
6107 static const IRtwqAsyncCallbackVtbl source_resolver_callback_url_vtbl =
6109 source_resolver_callback_QueryInterface,
6110 source_resolver_callback_url_AddRef,
6111 source_resolver_callback_url_Release,
6112 source_resolver_callback_GetParameters,
6113 source_resolver_callback_url_Invoke,
6116 static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void **handler)
6118 DWORD name_length, type;
6119 HRESULT hr = E_FAIL;
6120 unsigned int j = 0;
6121 WCHAR clsidW[39];
6122 CLSID clsid;
6124 name_length = ARRAY_SIZE(clsidW);
6125 while (!RegEnumValueW(hkey, j++, clsidW, &name_length, NULL, &type, NULL, NULL))
6127 if (type == REG_SZ)
6129 if (SUCCEEDED(CLSIDFromString(clsidW, &clsid)))
6131 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, riid, handler);
6132 if (SUCCEEDED(hr))
6133 break;
6137 name_length = ARRAY_SIZE(clsidW);
6140 return hr;
6143 static HRESULT resolver_create_bytestream_handler(IMFByteStream *stream, DWORD flags, const WCHAR *mime,
6144 const WCHAR *extension, IMFByteStreamHandler **handler)
6146 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6147 HRESULT hr = E_FAIL;
6148 unsigned int i, j;
6150 *handler = NULL;
6152 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6154 struct local_handler *local_handler;
6156 EnterCriticalSection(&local_handlers_section);
6158 LIST_FOR_EACH_ENTRY(local_handler, &local_bytestream_handlers, struct local_handler, entry)
6160 if ((mime && !lstrcmpiW(mime, local_handler->u.bytestream.mime))
6161 || (extension && !lstrcmpiW(extension, local_handler->u.bytestream.extension)))
6163 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFByteStreamHandler,
6164 (void **)handler)))
6165 break;
6169 LeaveCriticalSection(&local_handlers_section);
6171 if (*handler)
6172 return hr;
6175 for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i)
6177 const WCHAR *namesW[2] = { mime, extension };
6178 HKEY hkey, hkey_handler;
6180 if (RegOpenKeyW(hkey_roots[i], L"Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers", &hkey))
6181 continue;
6183 for (j = 0; j < ARRAY_SIZE(namesW); ++j)
6185 if (!namesW[j])
6186 continue;
6188 if (!RegOpenKeyW(hkey, namesW[j], &hkey_handler))
6190 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFByteStreamHandler, (void **)handler);
6191 RegCloseKey(hkey_handler);
6194 if (SUCCEEDED(hr))
6195 break;
6198 RegCloseKey(hkey);
6200 if (SUCCEEDED(hr))
6201 break;
6204 return hr;
6207 static HRESULT resolver_get_bytestream_url_hint(IMFByteStream *stream, WCHAR const **url)
6209 static const unsigned char asfmagic[] = {0x30,0x26,0xb2,0x75,0x8e,0x66,0xcf,0x11,0xa6,0xd9,0x00,0xaa,0x00,0x62,0xce,0x6c};
6210 static const unsigned char wavmagic[] = { 'R', 'I', 'F', 'F',0x00,0x00,0x00,0x00, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' '};
6211 static const unsigned char wavmask[] = {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
6212 static const unsigned char isommagic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'i', 's', 'o', 'm',0x00,0x00,0x00,0x00};
6213 static const unsigned char mp4_magic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'M', 'S', 'N', 'V',0x00,0x00,0x00,0x00};
6214 static const unsigned char mp42magic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'm', 'p', '4', '2',0x00,0x00,0x00,0x00};
6215 static const unsigned char mp4vmagic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'M', '4', 'V', ' ',0x00,0x00,0x00,0x00};
6216 static const unsigned char mp4mask[] = {0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00};
6217 static const struct stream_content_url_hint
6219 const unsigned char *magic;
6220 const WCHAR *url;
6221 const unsigned char *mask;
6223 url_hints[] =
6225 { asfmagic, L".asf" },
6226 { wavmagic, L".wav", wavmask },
6227 { isommagic, L".mp4", mp4mask },
6228 { mp42magic, L".mp4", mp4mask },
6229 { mp4_magic, L".mp4", mp4mask },
6230 { mp4vmagic, L".m4v", mp4mask },
6232 unsigned char buffer[4 * sizeof(unsigned int)], pattern[4 * sizeof(unsigned int)];
6233 IMFAttributes *attributes;
6234 DWORD length = 0, caps = 0;
6235 unsigned int i, j;
6236 QWORD position;
6237 HRESULT hr;
6239 *url = NULL;
6241 if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
6243 UINT32 string_length = 0;
6244 IMFAttributes_GetStringLength(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &string_length);
6245 IMFAttributes_Release(attributes);
6247 if (string_length)
6248 return S_OK;
6251 if (FAILED(hr = IMFByteStream_GetCapabilities(stream, &caps)))
6252 return hr;
6254 if (!(caps & MFBYTESTREAM_IS_SEEKABLE))
6255 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6257 if (FAILED(hr = IMFByteStream_GetCurrentPosition(stream, &position)))
6258 return hr;
6260 hr = IMFByteStream_Read(stream, buffer, sizeof(buffer), &length);
6261 IMFByteStream_SetCurrentPosition(stream, position);
6262 if (FAILED(hr))
6263 return hr;
6265 if (length < sizeof(buffer))
6266 return S_OK;
6268 for (i = 0; i < ARRAY_SIZE(url_hints); ++i)
6270 memcpy(pattern, buffer, sizeof(buffer));
6271 if (url_hints[i].mask)
6273 unsigned int *mask = (unsigned int *)url_hints[i].mask;
6274 unsigned int *data = (unsigned int *)pattern;
6276 for (j = 0; j < sizeof(buffer) / sizeof(unsigned int); ++j)
6277 data[j] &= mask[j];
6280 if (!memcmp(pattern, url_hints[i].magic, sizeof(pattern)))
6282 *url = url_hints[i].url;
6283 break;
6287 if (*url)
6288 TRACE("Content type guessed as %s from %s.\n", debugstr_w(*url), debugstr_an((char *)buffer, length));
6289 else
6290 WARN("Unrecognized content type %s.\n", debugstr_an((char *)buffer, length));
6292 return S_OK;
6295 static HRESULT resolver_create_gstreamer_handler(IMFByteStreamHandler **handler)
6297 static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
6298 return CoCreateInstance(&CLSID_GStreamerByteStreamHandler, NULL, CLSCTX_INPROC_SERVER, &IID_IMFByteStreamHandler, (void **)handler);
6301 static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags,
6302 IMFByteStreamHandler **handler)
6304 WCHAR *mimeW = NULL, *urlW = NULL;
6305 IMFAttributes *attributes;
6306 const WCHAR *url_ext;
6307 HRESULT hr = E_FAIL;
6308 UINT32 length;
6310 *handler = NULL;
6312 /* MIME type */
6313 if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
6315 IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length);
6316 if (!url)
6318 IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_ORIGIN_NAME, &urlW, &length);
6319 url = urlW;
6321 IMFAttributes_Release(attributes);
6324 /* Extension */
6325 url_ext = url ? wcsrchr(url, '.') : NULL;
6327 /* If content type was provided by the caller, it's tried first. Otherwise an attempt to deduce
6328 content type from the content itself is made.
6330 TODO: wine specific fallback to predefined handler could be replaced by normally registering
6331 this handler for all possible types.
6334 if (url_ext || mimeW)
6336 hr = resolver_create_bytestream_handler(stream, flags, mimeW, url_ext, handler);
6338 if (FAILED(hr))
6339 hr = resolver_create_gstreamer_handler(handler);
6342 CoTaskMemFree(mimeW);
6343 CoTaskMemFree(urlW);
6345 if (SUCCEEDED(hr))
6346 return hr;
6348 if (!(flags & MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE))
6349 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6351 if (FAILED(hr = resolver_get_bytestream_url_hint(stream, &url_ext)))
6352 return hr;
6354 hr = resolver_create_bytestream_handler(stream, flags, NULL, url_ext, handler);
6356 if (FAILED(hr))
6357 hr = resolver_create_gstreamer_handler(handler);
6359 return hr;
6362 static HRESULT resolver_create_scheme_handler(const WCHAR *scheme, DWORD flags, IMFSchemeHandler **handler)
6364 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6365 HRESULT hr = MF_E_UNSUPPORTED_SCHEME;
6366 unsigned int i;
6368 TRACE("%s, %#lx, %p.\n", debugstr_w(scheme), flags, handler);
6370 *handler = NULL;
6372 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6374 struct local_handler *local_handler;
6376 EnterCriticalSection(&local_handlers_section);
6378 LIST_FOR_EACH_ENTRY(local_handler, &local_scheme_handlers, struct local_handler, entry)
6380 if (!lstrcmpiW(scheme, local_handler->u.scheme))
6382 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFSchemeHandler,
6383 (void **)handler)))
6384 break;
6388 LeaveCriticalSection(&local_handlers_section);
6390 if (*handler)
6391 return hr;
6394 for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
6396 HKEY hkey, hkey_handler;
6398 hr = MF_E_UNSUPPORTED_SCHEME;
6400 if (RegOpenKeyW(hkey_roots[i], L"Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers", &hkey))
6401 continue;
6403 if (!RegOpenKeyW(hkey, scheme, &hkey_handler))
6405 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFSchemeHandler, (void **)handler);
6406 RegCloseKey(hkey_handler);
6409 RegCloseKey(hkey);
6411 if (SUCCEEDED(hr))
6412 break;
6415 return hr;
6418 static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSchemeHandler **handler)
6420 static const WCHAR fileschemeW[] = L"file:";
6421 const WCHAR *ptr = url;
6422 unsigned int len;
6423 WCHAR *scheme;
6424 HRESULT hr;
6426 /* RFC 3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
6427 while (*ptr)
6429 WCHAR ch = towlower(*ptr);
6431 if (*ptr == '*' && ptr == url)
6433 ptr++;
6434 break;
6436 else if (!(*ptr >= '0' && *ptr <= '9') &&
6437 !(ch >= 'a' && ch <= 'z') &&
6438 *ptr != '+' && *ptr != '-' && *ptr != '.')
6440 break;
6443 ptr++;
6446 /* Schemes must end with a ':', if not found try "file:" */
6447 if (ptr == url || *ptr != ':')
6449 url = fileschemeW;
6450 len = ARRAY_SIZE(fileschemeW) - 1;
6452 else
6453 len = ptr - url + 1;
6455 scheme = malloc((len + 1) * sizeof(WCHAR));
6456 if (!scheme)
6457 return E_OUTOFMEMORY;
6459 memcpy(scheme, url, len * sizeof(WCHAR));
6460 scheme[len] = 0;
6462 hr = resolver_create_scheme_handler(scheme, flags, handler);
6463 if (FAILED(hr) && url != fileschemeW)
6464 hr = resolver_create_scheme_handler(fileschemeW, flags, handler);
6466 free(scheme);
6468 return hr;
6471 static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum resolved_object_origin origin,
6472 IRtwqAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out)
6474 struct resolver_queued_result *queued_result = NULL, *iter;
6475 IUnknown *object;
6476 HRESULT hr;
6478 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
6479 return hr;
6481 EnterCriticalSection(&resolver->cs);
6483 LIST_FOR_EACH_ENTRY(iter, &resolver->pending, struct resolver_queued_result, entry)
6485 if (iter->inner_result == result || (iter->object == object && iter->origin == origin))
6487 list_remove(&iter->entry);
6488 queued_result = iter;
6489 break;
6493 LeaveCriticalSection(&resolver->cs);
6495 IUnknown_Release(object);
6497 if (queued_result)
6499 *out = queued_result->object;
6500 *obj_type = queued_result->obj_type;
6501 hr = queued_result->hr;
6502 if (queued_result->inner_result)
6503 IRtwqAsyncResult_Release(queued_result->inner_result);
6504 free(queued_result);
6506 else
6507 hr = E_UNEXPECTED;
6509 return hr;
6512 static HRESULT WINAPI source_resolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj)
6514 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6516 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
6518 if (IsEqualIID(riid, &IID_IMFSourceResolver) ||
6519 IsEqualIID(riid, &IID_IUnknown))
6521 *obj = &resolver->IMFSourceResolver_iface;
6523 else
6525 *obj = NULL;
6526 FIXME("unsupported interface %s\n", debugstr_guid(riid));
6527 return E_NOINTERFACE;
6530 IUnknown_AddRef((IUnknown *)*obj);
6531 return S_OK;
6534 static ULONG WINAPI source_resolver_AddRef(IMFSourceResolver *iface)
6536 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6537 ULONG refcount = InterlockedIncrement(&resolver->refcount);
6539 TRACE("%p, refcount %ld.\n", iface, refcount);
6541 return refcount;
6544 static ULONG WINAPI source_resolver_Release(IMFSourceResolver *iface)
6546 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6547 ULONG refcount = InterlockedDecrement(&resolver->refcount);
6548 struct resolver_queued_result *result, *result2;
6550 TRACE("%p, refcount %ld.\n", iface, refcount);
6552 if (!refcount)
6554 LIST_FOR_EACH_ENTRY_SAFE(result, result2, &resolver->pending, struct resolver_queued_result, entry)
6556 if (result->object)
6557 IUnknown_Release(result->object);
6558 list_remove(&result->entry);
6559 free(result);
6561 DeleteCriticalSection(&resolver->cs);
6562 free(resolver);
6565 return refcount;
6568 static HRESULT WINAPI source_resolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6569 DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6571 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6572 IMFSchemeHandler *handler;
6573 IRtwqAsyncResult *result;
6574 RTWQASYNCRESULT *data;
6575 HRESULT hr;
6577 TRACE("%p, %s, %#lx, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, obj_type, object);
6579 if (!url || !obj_type || !object)
6580 return E_POINTER;
6582 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6583 return hr;
6585 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6586 IMFSchemeHandler_Release(handler);
6587 if (FAILED(hr))
6588 return hr;
6590 data = (RTWQASYNCRESULT *)result;
6591 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6593 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, NULL, (IMFAsyncCallback *)&resolver->url_callback,
6594 (IUnknown *)result);
6595 if (FAILED(hr))
6597 IRtwqAsyncResult_Release(result);
6598 return hr;
6601 WaitForSingleObject(data->hEvent, INFINITE);
6603 hr = resolver_end_create_object(resolver, OBJECT_FROM_URL, result, obj_type, object);
6604 IRtwqAsyncResult_Release(result);
6606 return hr;
6609 static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6610 const WCHAR *url, DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6612 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6613 IMFByteStreamHandler *handler;
6614 IRtwqAsyncResult *result;
6615 RTWQASYNCRESULT *data;
6616 HRESULT hr;
6618 TRACE("%p, %p, %s, %#lx, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, obj_type, object);
6620 if (!stream || !obj_type || !object)
6621 return E_POINTER;
6623 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6624 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6626 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6627 IMFByteStreamHandler_Release(handler);
6628 if (FAILED(hr))
6629 return hr;
6631 data = (RTWQASYNCRESULT *)result;
6632 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6634 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props, NULL,
6635 (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6636 if (FAILED(hr))
6638 IRtwqAsyncResult_Release(result);
6639 return hr;
6642 WaitForSingleObject(data->hEvent, INFINITE);
6644 hr = resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, result, obj_type, object);
6645 IRtwqAsyncResult_Release(result);
6647 return hr;
6650 static HRESULT WINAPI source_resolver_BeginCreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6651 DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
6653 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6654 IMFSchemeHandler *handler;
6655 IUnknown *inner_cookie = NULL;
6656 IRtwqAsyncResult *result;
6657 HRESULT hr;
6659 TRACE("%p, %s, %#lx, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
6661 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6662 return hr;
6664 if (cancel_cookie)
6665 *cancel_cookie = NULL;
6667 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6668 IMFSchemeHandler_Release(handler);
6669 if (FAILED(hr))
6670 return hr;
6672 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, cancel_cookie ? &inner_cookie : NULL,
6673 (IMFAsyncCallback *)&resolver->url_callback, (IUnknown *)result);
6675 if (SUCCEEDED(hr) && inner_cookie)
6676 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_URL, inner_cookie, cancel_cookie);
6678 IRtwqAsyncResult_Release(result);
6680 return hr;
6683 static HRESULT WINAPI source_resolver_EndCreateObjectFromURL(IMFSourceResolver *iface, IMFAsyncResult *result,
6684 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6686 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6688 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6690 return resolver_end_create_object(resolver, OBJECT_FROM_URL, (IRtwqAsyncResult *)result, obj_type, object);
6693 static HRESULT WINAPI source_resolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6694 const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback,
6695 IUnknown *state)
6697 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6698 IMFByteStreamHandler *handler;
6699 IUnknown *inner_cookie = NULL;
6700 IRtwqAsyncResult *result;
6701 HRESULT hr;
6703 TRACE("%p, %p, %s, %#lx, %p, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, cancel_cookie,
6704 callback, state);
6706 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6707 return hr;
6709 if (cancel_cookie)
6710 *cancel_cookie = NULL;
6712 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6713 IMFByteStreamHandler_Release(handler);
6714 if (FAILED(hr))
6715 return hr;
6717 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props,
6718 cancel_cookie ? &inner_cookie : NULL, (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6720 /* Cancel object wraps underlying handler cancel cookie with context necessary to call CancelObjectCreate(). */
6721 if (SUCCEEDED(hr) && inner_cookie)
6722 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_BYTESTREAM, inner_cookie, cancel_cookie);
6724 IRtwqAsyncResult_Release(result);
6726 return hr;
6729 static HRESULT WINAPI source_resolver_EndCreateObjectFromByteStream(IMFSourceResolver *iface, IMFAsyncResult *result,
6730 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6732 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6734 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6736 return resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, (IRtwqAsyncResult *)result, obj_type, object);
6739 static HRESULT WINAPI source_resolver_CancelObjectCreation(IMFSourceResolver *iface, IUnknown *cancel_cookie)
6741 struct resolver_cancel_object *object;
6742 HRESULT hr;
6744 TRACE("%p, %p.\n", iface, cancel_cookie);
6746 if (!(object = unsafe_impl_cancel_obj_from_IUnknown(cancel_cookie)))
6747 return E_UNEXPECTED;
6749 switch (object->origin)
6751 case OBJECT_FROM_BYTESTREAM:
6752 hr = IMFByteStreamHandler_CancelObjectCreation(object->u.stream_handler, object->cancel_cookie);
6753 break;
6754 case OBJECT_FROM_URL:
6755 hr = IMFSchemeHandler_CancelObjectCreation(object->u.scheme_handler, object->cancel_cookie);
6756 break;
6757 default:
6758 hr = E_UNEXPECTED;
6761 return hr;
6764 static const IMFSourceResolverVtbl mfsourceresolvervtbl =
6766 source_resolver_QueryInterface,
6767 source_resolver_AddRef,
6768 source_resolver_Release,
6769 source_resolver_CreateObjectFromURL,
6770 source_resolver_CreateObjectFromByteStream,
6771 source_resolver_BeginCreateObjectFromURL,
6772 source_resolver_EndCreateObjectFromURL,
6773 source_resolver_BeginCreateObjectFromByteStream,
6774 source_resolver_EndCreateObjectFromByteStream,
6775 source_resolver_CancelObjectCreation,
6778 /***********************************************************************
6779 * MFCreateSourceResolver (mfplat.@)
6781 HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver)
6783 struct source_resolver *object;
6785 TRACE("%p\n", resolver);
6787 if (!resolver)
6788 return E_POINTER;
6790 if (!(object = calloc(1, sizeof(*object))))
6791 return E_OUTOFMEMORY;
6793 object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl;
6794 object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl;
6795 object->url_callback.lpVtbl = &source_resolver_callback_url_vtbl;
6796 object->refcount = 1;
6797 list_init(&object->pending);
6798 InitializeCriticalSection(&object->cs);
6800 *resolver = &object->IMFSourceResolver_iface;
6802 return S_OK;
6805 struct media_event
6807 struct attributes attributes;
6808 IMFMediaEvent IMFMediaEvent_iface;
6810 MediaEventType type;
6811 GUID extended_type;
6812 HRESULT status;
6813 PROPVARIANT value;
6816 static inline struct media_event *impl_from_IMFMediaEvent(IMFMediaEvent *iface)
6818 return CONTAINING_RECORD(iface, struct media_event, IMFMediaEvent_iface);
6821 static HRESULT WINAPI mfmediaevent_QueryInterface(IMFMediaEvent *iface, REFIID riid, void **out)
6823 struct media_event *event = impl_from_IMFMediaEvent(iface);
6825 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
6827 if(IsEqualGUID(riid, &IID_IUnknown) ||
6828 IsEqualGUID(riid, &IID_IMFAttributes) ||
6829 IsEqualGUID(riid, &IID_IMFMediaEvent))
6831 *out = &event->IMFMediaEvent_iface;
6833 else
6835 FIXME("%s, %p.\n", debugstr_guid(riid), out);
6836 *out = NULL;
6837 return E_NOINTERFACE;
6840 IUnknown_AddRef((IUnknown*)*out);
6841 return S_OK;
6844 static ULONG WINAPI mfmediaevent_AddRef(IMFMediaEvent *iface)
6846 struct media_event *event = impl_from_IMFMediaEvent(iface);
6847 ULONG refcount = InterlockedIncrement(&event->attributes.ref);
6849 TRACE("%p, refcount %lu.\n", iface, refcount);
6851 return refcount;
6854 static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface)
6856 struct media_event *event = impl_from_IMFMediaEvent(iface);
6857 ULONG refcount = InterlockedDecrement(&event->attributes.ref);
6859 TRACE("%p, refcount %lu.\n", iface, refcount);
6861 if (!refcount)
6863 clear_attributes_object(&event->attributes);
6864 PropVariantClear(&event->value);
6865 free(event);
6868 return refcount;
6871 static HRESULT WINAPI mfmediaevent_GetItem(IMFMediaEvent *iface, REFGUID key, PROPVARIANT *value)
6873 struct media_event *event = impl_from_IMFMediaEvent(iface);
6875 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6877 return attributes_GetItem(&event->attributes, key, value);
6880 static HRESULT WINAPI mfmediaevent_GetItemType(IMFMediaEvent *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
6882 struct media_event *event = impl_from_IMFMediaEvent(iface);
6884 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
6886 return attributes_GetItemType(&event->attributes, key, type);
6889 static HRESULT WINAPI mfmediaevent_CompareItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
6891 struct media_event *event = impl_from_IMFMediaEvent(iface);
6893 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
6895 return attributes_CompareItem(&event->attributes, key, value, result);
6898 static HRESULT WINAPI mfmediaevent_Compare(IMFMediaEvent *iface, IMFAttributes *attrs, MF_ATTRIBUTES_MATCH_TYPE type,
6899 BOOL *result)
6901 struct media_event *event = impl_from_IMFMediaEvent(iface);
6903 TRACE("%p, %p, %d, %p.\n", iface, attrs, type, result);
6905 return attributes_Compare(&event->attributes, attrs, type, result);
6908 static HRESULT WINAPI mfmediaevent_GetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 *value)
6910 struct media_event *event = impl_from_IMFMediaEvent(iface);
6912 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6914 return attributes_GetUINT32(&event->attributes, key, value);
6917 static HRESULT WINAPI mfmediaevent_GetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 *value)
6919 struct media_event *event = impl_from_IMFMediaEvent(iface);
6921 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6923 return attributes_GetUINT64(&event->attributes, key, value);
6926 static HRESULT WINAPI mfmediaevent_GetDouble(IMFMediaEvent *iface, REFGUID key, double *value)
6928 struct media_event *event = impl_from_IMFMediaEvent(iface);
6930 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6932 return attributes_GetDouble(&event->attributes, key, value);
6935 static HRESULT WINAPI mfmediaevent_GetGUID(IMFMediaEvent *iface, REFGUID key, GUID *value)
6937 struct media_event *event = impl_from_IMFMediaEvent(iface);
6939 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6941 return attributes_GetGUID(&event->attributes, key, value);
6944 static HRESULT WINAPI mfmediaevent_GetStringLength(IMFMediaEvent *iface, REFGUID key, UINT32 *length)
6946 struct media_event *event = impl_from_IMFMediaEvent(iface);
6948 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
6950 return attributes_GetStringLength(&event->attributes, key, length);
6953 static HRESULT WINAPI mfmediaevent_GetString(IMFMediaEvent *iface, REFGUID key, WCHAR *value,
6954 UINT32 size, UINT32 *length)
6956 struct media_event *event = impl_from_IMFMediaEvent(iface);
6958 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), value, size, length);
6960 return attributes_GetString(&event->attributes, key, value, size, length);
6963 static HRESULT WINAPI mfmediaevent_GetAllocatedString(IMFMediaEvent *iface, REFGUID key,
6964 WCHAR **value, UINT32 *length)
6966 struct media_event *event = impl_from_IMFMediaEvent(iface);
6968 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
6970 return attributes_GetAllocatedString(&event->attributes, key, value, length);
6973 static HRESULT WINAPI mfmediaevent_GetBlobSize(IMFMediaEvent *iface, REFGUID key, UINT32 *size)
6975 struct media_event *event = impl_from_IMFMediaEvent(iface);
6977 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
6979 return attributes_GetBlobSize(&event->attributes, key, size);
6982 static HRESULT WINAPI mfmediaevent_GetBlob(IMFMediaEvent *iface, REFGUID key, UINT8 *buf,
6983 UINT32 bufsize, UINT32 *blobsize)
6985 struct media_event *event = impl_from_IMFMediaEvent(iface);
6987 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
6989 return attributes_GetBlob(&event->attributes, key, buf, bufsize, blobsize);
6992 static HRESULT WINAPI mfmediaevent_GetAllocatedBlob(IMFMediaEvent *iface, REFGUID key, UINT8 **buf, UINT32 *size)
6994 struct media_event *event = impl_from_IMFMediaEvent(iface);
6996 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
6998 return attributes_GetAllocatedBlob(&event->attributes, key, buf, size);
7001 static HRESULT WINAPI mfmediaevent_GetUnknown(IMFMediaEvent *iface, REFGUID key, REFIID riid, void **out)
7003 struct media_event *event = impl_from_IMFMediaEvent(iface);
7005 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
7007 return attributes_GetUnknown(&event->attributes, key, riid, out);
7010 static HRESULT WINAPI mfmediaevent_SetItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value)
7012 struct media_event *event = impl_from_IMFMediaEvent(iface);
7014 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
7016 return attributes_SetItem(&event->attributes, key, value);
7019 static HRESULT WINAPI mfmediaevent_DeleteItem(IMFMediaEvent *iface, REFGUID key)
7021 struct media_event *event = impl_from_IMFMediaEvent(iface);
7023 TRACE("%p, %s.\n", iface, debugstr_attr(key));
7025 return attributes_DeleteItem(&event->attributes, key);
7028 static HRESULT WINAPI mfmediaevent_DeleteAllItems(IMFMediaEvent *iface)
7030 struct media_event *event = impl_from_IMFMediaEvent(iface);
7032 TRACE("%p.\n", iface);
7034 return attributes_DeleteAllItems(&event->attributes);
7037 static HRESULT WINAPI mfmediaevent_SetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 value)
7039 struct media_event *event = impl_from_IMFMediaEvent(iface);
7041 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
7043 return attributes_SetUINT32(&event->attributes, key, value);
7046 static HRESULT WINAPI mfmediaevent_SetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 value)
7048 struct media_event *event = impl_from_IMFMediaEvent(iface);
7050 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
7052 return attributes_SetUINT64(&event->attributes, key, value);
7055 static HRESULT WINAPI mfmediaevent_SetDouble(IMFMediaEvent *iface, REFGUID key, double value)
7057 struct media_event *event = impl_from_IMFMediaEvent(iface);
7059 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
7061 return attributes_SetDouble(&event->attributes, key, value);
7064 static HRESULT WINAPI mfmediaevent_SetGUID(IMFMediaEvent *iface, REFGUID key, REFGUID value)
7066 struct media_event *event = impl_from_IMFMediaEvent(iface);
7068 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
7070 return attributes_SetGUID(&event->attributes, key, value);
7073 static HRESULT WINAPI mfmediaevent_SetString(IMFMediaEvent *iface, REFGUID key, const WCHAR *value)
7075 struct media_event *event = impl_from_IMFMediaEvent(iface);
7077 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
7079 return attributes_SetString(&event->attributes, key, value);
7082 static HRESULT WINAPI mfmediaevent_SetBlob(IMFMediaEvent *iface, REFGUID key, const UINT8 *buf, UINT32 size)
7084 struct media_event *event = impl_from_IMFMediaEvent(iface);
7086 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
7088 return attributes_SetBlob(&event->attributes, key, buf, size);
7091 static HRESULT WINAPI mfmediaevent_SetUnknown(IMFMediaEvent *iface, REFGUID key, IUnknown *unknown)
7093 struct media_event *event = impl_from_IMFMediaEvent(iface);
7095 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
7097 return attributes_SetUnknown(&event->attributes, key, unknown);
7100 static HRESULT WINAPI mfmediaevent_LockStore(IMFMediaEvent *iface)
7102 struct media_event *event = impl_from_IMFMediaEvent(iface);
7104 TRACE("%p.\n", iface);
7106 return attributes_LockStore(&event->attributes);
7109 static HRESULT WINAPI mfmediaevent_UnlockStore(IMFMediaEvent *iface)
7111 struct media_event *event = impl_from_IMFMediaEvent(iface);
7113 TRACE("%p.\n", iface);
7115 return attributes_UnlockStore(&event->attributes);
7118 static HRESULT WINAPI mfmediaevent_GetCount(IMFMediaEvent *iface, UINT32 *count)
7120 struct media_event *event = impl_from_IMFMediaEvent(iface);
7122 TRACE("%p, %p.\n", iface, count);
7124 return attributes_GetCount(&event->attributes, count);
7127 static HRESULT WINAPI mfmediaevent_GetItemByIndex(IMFMediaEvent *iface, UINT32 index, GUID *key, PROPVARIANT *value)
7129 struct media_event *event = impl_from_IMFMediaEvent(iface);
7131 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
7133 return attributes_GetItemByIndex(&event->attributes, index, key, value);
7136 static HRESULT WINAPI mfmediaevent_CopyAllItems(IMFMediaEvent *iface, IMFAttributes *dest)
7138 struct media_event *event = impl_from_IMFMediaEvent(iface);
7140 TRACE("%p, %p.\n", iface, dest);
7142 return attributes_CopyAllItems(&event->attributes, dest);
7145 static HRESULT WINAPI mfmediaevent_GetType(IMFMediaEvent *iface, MediaEventType *type)
7147 struct media_event *event = impl_from_IMFMediaEvent(iface);
7149 TRACE("%p, %p.\n", iface, type);
7151 *type = event->type;
7153 return S_OK;
7156 static HRESULT WINAPI mfmediaevent_GetExtendedType(IMFMediaEvent *iface, GUID *extended_type)
7158 struct media_event *event = impl_from_IMFMediaEvent(iface);
7160 TRACE("%p, %p.\n", iface, extended_type);
7162 *extended_type = event->extended_type;
7164 return S_OK;
7167 static HRESULT WINAPI mfmediaevent_GetStatus(IMFMediaEvent *iface, HRESULT *status)
7169 struct media_event *event = impl_from_IMFMediaEvent(iface);
7171 TRACE("%p, %p.\n", iface, status);
7173 *status = event->status;
7175 return S_OK;
7178 static HRESULT WINAPI mfmediaevent_GetValue(IMFMediaEvent *iface, PROPVARIANT *value)
7180 struct media_event *event = impl_from_IMFMediaEvent(iface);
7182 TRACE("%p, %p.\n", iface, value);
7184 PropVariantCopy(value, &event->value);
7186 return S_OK;
7189 static const IMFMediaEventVtbl mfmediaevent_vtbl =
7191 mfmediaevent_QueryInterface,
7192 mfmediaevent_AddRef,
7193 mfmediaevent_Release,
7194 mfmediaevent_GetItem,
7195 mfmediaevent_GetItemType,
7196 mfmediaevent_CompareItem,
7197 mfmediaevent_Compare,
7198 mfmediaevent_GetUINT32,
7199 mfmediaevent_GetUINT64,
7200 mfmediaevent_GetDouble,
7201 mfmediaevent_GetGUID,
7202 mfmediaevent_GetStringLength,
7203 mfmediaevent_GetString,
7204 mfmediaevent_GetAllocatedString,
7205 mfmediaevent_GetBlobSize,
7206 mfmediaevent_GetBlob,
7207 mfmediaevent_GetAllocatedBlob,
7208 mfmediaevent_GetUnknown,
7209 mfmediaevent_SetItem,
7210 mfmediaevent_DeleteItem,
7211 mfmediaevent_DeleteAllItems,
7212 mfmediaevent_SetUINT32,
7213 mfmediaevent_SetUINT64,
7214 mfmediaevent_SetDouble,
7215 mfmediaevent_SetGUID,
7216 mfmediaevent_SetString,
7217 mfmediaevent_SetBlob,
7218 mfmediaevent_SetUnknown,
7219 mfmediaevent_LockStore,
7220 mfmediaevent_UnlockStore,
7221 mfmediaevent_GetCount,
7222 mfmediaevent_GetItemByIndex,
7223 mfmediaevent_CopyAllItems,
7224 mfmediaevent_GetType,
7225 mfmediaevent_GetExtendedType,
7226 mfmediaevent_GetStatus,
7227 mfmediaevent_GetValue,
7230 /***********************************************************************
7231 * MFCreateMediaEvent (mfplat.@)
7233 HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HRESULT status, const PROPVARIANT *value,
7234 IMFMediaEvent **event)
7236 struct media_event *object;
7237 HRESULT hr;
7239 TRACE("%s, %s, %#lx, %s, %p.\n", debugstr_eventid(type), debugstr_guid(extended_type), status,
7240 debugstr_propvar(value), event);
7242 object = malloc(sizeof(*object));
7243 if (!object)
7244 return E_OUTOFMEMORY;
7246 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
7248 free(object);
7249 return hr;
7251 object->IMFMediaEvent_iface.lpVtbl = &mfmediaevent_vtbl;
7253 object->type = type;
7254 object->extended_type = *extended_type;
7255 object->status = status;
7257 PropVariantInit(&object->value);
7258 if (value)
7259 PropVariantCopy(&object->value, value);
7261 *event = &object->IMFMediaEvent_iface;
7263 TRACE("Created event %p.\n", *event);
7265 return S_OK;
7268 struct event_queue
7270 IMFMediaEventQueue IMFMediaEventQueue_iface;
7271 LONG refcount;
7273 CRITICAL_SECTION cs;
7274 CONDITION_VARIABLE update_event;
7275 struct list events;
7276 BOOL is_shut_down;
7277 BOOL notified;
7278 IRtwqAsyncResult *subscriber;
7281 struct queued_event
7283 struct list entry;
7284 IMFMediaEvent *event;
7287 static inline struct event_queue *impl_from_IMFMediaEventQueue(IMFMediaEventQueue *iface)
7289 return CONTAINING_RECORD(iface, struct event_queue, IMFMediaEventQueue_iface);
7292 static IMFMediaEvent *queue_pop_event(struct event_queue *queue)
7294 struct list *head = list_head(&queue->events);
7295 struct queued_event *queued_event;
7296 IMFMediaEvent *event;
7298 if (!head)
7299 return NULL;
7301 queued_event = LIST_ENTRY(head, struct queued_event, entry);
7302 event = queued_event->event;
7303 list_remove(&queued_event->entry);
7304 free(queued_event);
7305 return event;
7308 static void event_queue_clear_subscriber(struct event_queue *queue)
7310 if (queue->subscriber)
7311 IRtwqAsyncResult_Release(queue->subscriber);
7312 queue->subscriber = NULL;
7315 static void event_queue_cleanup(struct event_queue *queue)
7317 IMFMediaEvent *event;
7319 while ((event = queue_pop_event(queue)))
7320 IMFMediaEvent_Release(event);
7321 event_queue_clear_subscriber(queue);
7324 static HRESULT WINAPI eventqueue_QueryInterface(IMFMediaEventQueue *iface, REFIID riid, void **out)
7326 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7328 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7330 if (IsEqualIID(riid, &IID_IMFMediaEventQueue) ||
7331 IsEqualIID(riid, &IID_IUnknown))
7333 *out = &queue->IMFMediaEventQueue_iface;
7334 IMFMediaEventQueue_AddRef(iface);
7335 return S_OK;
7338 WARN("Unsupported %s.\n", debugstr_guid(riid));
7339 *out = NULL;
7340 return E_NOINTERFACE;
7343 static ULONG WINAPI eventqueue_AddRef(IMFMediaEventQueue *iface)
7345 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7346 ULONG refcount = InterlockedIncrement(&queue->refcount);
7348 TRACE("%p, refcount %lu.\n", iface, refcount);
7350 return refcount;
7353 static ULONG WINAPI eventqueue_Release(IMFMediaEventQueue *iface)
7355 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7356 ULONG refcount = InterlockedDecrement(&queue->refcount);
7358 TRACE("%p, refcount %lu.\n", queue, refcount);
7360 if (!refcount)
7362 event_queue_cleanup(queue);
7363 DeleteCriticalSection(&queue->cs);
7364 free(queue);
7367 return refcount;
7370 static HRESULT WINAPI eventqueue_GetEvent(IMFMediaEventQueue *iface, DWORD flags, IMFMediaEvent **event)
7372 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7373 HRESULT hr = S_OK;
7375 TRACE("%p, %p.\n", iface, event);
7377 EnterCriticalSection(&queue->cs);
7379 if (queue->is_shut_down)
7380 hr = MF_E_SHUTDOWN;
7381 else if (queue->subscriber)
7382 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7383 else
7385 if (flags & MF_EVENT_FLAG_NO_WAIT)
7387 if (!(*event = queue_pop_event(queue)))
7388 hr = MF_E_NO_EVENTS_AVAILABLE;
7390 else
7392 while (list_empty(&queue->events) && !queue->is_shut_down)
7394 SleepConditionVariableCS(&queue->update_event, &queue->cs, INFINITE);
7396 *event = queue_pop_event(queue);
7397 if (queue->is_shut_down)
7398 hr = MF_E_SHUTDOWN;
7402 LeaveCriticalSection(&queue->cs);
7404 return hr;
7407 static void queue_notify_subscriber(struct event_queue *queue)
7409 if (list_empty(&queue->events) || !queue->subscriber || queue->notified)
7410 return;
7412 queue->notified = TRUE;
7413 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, queue->subscriber);
7416 static HRESULT WINAPI eventqueue_BeginGetEvent(IMFMediaEventQueue *iface, IMFAsyncCallback *callback, IUnknown *state)
7418 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7419 RTWQASYNCRESULT *result_data;
7420 HRESULT hr;
7422 TRACE("%p, %p, %p.\n", iface, callback, state);
7424 if (!callback)
7425 return E_INVALIDARG;
7427 EnterCriticalSection(&queue->cs);
7429 if (queue->is_shut_down)
7430 hr = MF_E_SHUTDOWN;
7431 else if ((result_data = (RTWQASYNCRESULT *)queue->subscriber))
7433 if (result_data->pCallback == (IRtwqAsyncCallback *)callback)
7434 hr = IRtwqAsyncResult_GetStateNoAddRef(queue->subscriber) == state ?
7435 MF_S_MULTIPLE_BEGIN : MF_E_MULTIPLE_BEGIN;
7436 else
7437 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7439 else
7441 hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &queue->subscriber);
7442 if (SUCCEEDED(hr))
7443 queue_notify_subscriber(queue);
7446 LeaveCriticalSection(&queue->cs);
7448 return hr;
7451 static HRESULT WINAPI eventqueue_EndGetEvent(IMFMediaEventQueue *iface, IMFAsyncResult *result, IMFMediaEvent **event)
7453 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7454 HRESULT hr = E_FAIL;
7456 TRACE("%p, %p, %p.\n", iface, result, event);
7458 EnterCriticalSection(&queue->cs);
7460 if (queue->is_shut_down)
7461 hr = MF_E_SHUTDOWN;
7462 else if (queue->subscriber == (IRtwqAsyncResult *)result)
7464 *event = queue_pop_event(queue);
7465 event_queue_clear_subscriber(queue);
7466 queue->notified = FALSE;
7467 hr = *event ? S_OK : E_FAIL;
7470 LeaveCriticalSection(&queue->cs);
7472 return hr;
7475 static HRESULT eventqueue_queue_event(struct event_queue *queue, IMFMediaEvent *event)
7477 struct queued_event *queued_event;
7478 HRESULT hr = S_OK;
7480 queued_event = malloc(sizeof(*queued_event));
7481 if (!queued_event)
7482 return E_OUTOFMEMORY;
7484 queued_event->event = event;
7486 EnterCriticalSection(&queue->cs);
7488 if (queue->is_shut_down)
7489 hr = MF_E_SHUTDOWN;
7490 else
7492 IMFMediaEvent_AddRef(queued_event->event);
7493 list_add_tail(&queue->events, &queued_event->entry);
7494 queue_notify_subscriber(queue);
7497 LeaveCriticalSection(&queue->cs);
7499 if (FAILED(hr))
7500 free(queued_event);
7502 WakeAllConditionVariable(&queue->update_event);
7504 return hr;
7507 static HRESULT WINAPI eventqueue_QueueEvent(IMFMediaEventQueue *iface, IMFMediaEvent *event)
7509 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7511 TRACE("%p, %p.\n", iface, event);
7513 return eventqueue_queue_event(queue, event);
7516 static HRESULT WINAPI eventqueue_QueueEventParamVar(IMFMediaEventQueue *iface, MediaEventType event_type,
7517 REFGUID extended_type, HRESULT status, const PROPVARIANT *value)
7519 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7520 IMFMediaEvent *event;
7521 HRESULT hr;
7523 TRACE("%p, %s, %s, %#lx, %s\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status,
7524 debugstr_propvar(value));
7526 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, value, &event)))
7527 return hr;
7529 hr = eventqueue_queue_event(queue, event);
7530 IMFMediaEvent_Release(event);
7531 return hr;
7534 static HRESULT WINAPI eventqueue_QueueEventParamUnk(IMFMediaEventQueue *iface, MediaEventType event_type,
7535 REFGUID extended_type, HRESULT status, IUnknown *unk)
7537 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7538 IMFMediaEvent *event;
7539 PROPVARIANT value;
7540 HRESULT hr;
7542 TRACE("%p, %s, %s, %#lx, %p.\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status, unk);
7544 value.vt = VT_UNKNOWN;
7545 value.punkVal = unk;
7547 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, &value, &event)))
7548 return hr;
7550 hr = eventqueue_queue_event(queue, event);
7551 IMFMediaEvent_Release(event);
7552 return hr;
7555 static HRESULT WINAPI eventqueue_Shutdown(IMFMediaEventQueue *iface)
7557 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7559 TRACE("%p\n", queue);
7561 EnterCriticalSection(&queue->cs);
7563 if (!queue->is_shut_down)
7565 event_queue_cleanup(queue);
7566 queue->is_shut_down = TRUE;
7569 LeaveCriticalSection(&queue->cs);
7571 WakeAllConditionVariable(&queue->update_event);
7573 return S_OK;
7576 static const IMFMediaEventQueueVtbl eventqueuevtbl =
7578 eventqueue_QueryInterface,
7579 eventqueue_AddRef,
7580 eventqueue_Release,
7581 eventqueue_GetEvent,
7582 eventqueue_BeginGetEvent,
7583 eventqueue_EndGetEvent,
7584 eventqueue_QueueEvent,
7585 eventqueue_QueueEventParamVar,
7586 eventqueue_QueueEventParamUnk,
7587 eventqueue_Shutdown
7590 /***********************************************************************
7591 * MFCreateEventQueue (mfplat.@)
7593 HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue)
7595 struct event_queue *object;
7597 TRACE("%p\n", queue);
7599 if (!(object = calloc(1, sizeof(*object))))
7600 return E_OUTOFMEMORY;
7602 object->IMFMediaEventQueue_iface.lpVtbl = &eventqueuevtbl;
7603 object->refcount = 1;
7604 list_init(&object->events);
7605 InitializeCriticalSection(&object->cs);
7606 InitializeConditionVariable(&object->update_event);
7608 *queue = &object->IMFMediaEventQueue_iface;
7610 return S_OK;
7613 struct collection
7615 IMFCollection IMFCollection_iface;
7616 LONG refcount;
7617 IUnknown **elements;
7618 size_t capacity;
7619 size_t count;
7622 static struct collection *impl_from_IMFCollection(IMFCollection *iface)
7624 return CONTAINING_RECORD(iface, struct collection, IMFCollection_iface);
7627 static void collection_clear(struct collection *collection)
7629 size_t i;
7631 for (i = 0; i < collection->count; ++i)
7633 if (collection->elements[i])
7634 IUnknown_Release(collection->elements[i]);
7637 free(collection->elements);
7638 collection->elements = NULL;
7639 collection->count = 0;
7640 collection->capacity = 0;
7643 static HRESULT WINAPI collection_QueryInterface(IMFCollection *iface, REFIID riid, void **out)
7645 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7647 if (IsEqualIID(riid, &IID_IMFCollection) ||
7648 IsEqualIID(riid, &IID_IUnknown))
7650 *out = iface;
7651 IMFCollection_AddRef(iface);
7652 return S_OK;
7655 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
7656 *out = NULL;
7657 return E_NOINTERFACE;
7660 static ULONG WINAPI collection_AddRef(IMFCollection *iface)
7662 struct collection *collection = impl_from_IMFCollection(iface);
7663 ULONG refcount = InterlockedIncrement(&collection->refcount);
7665 TRACE("%p, %ld.\n", collection, refcount);
7667 return refcount;
7670 static ULONG WINAPI collection_Release(IMFCollection *iface)
7672 struct collection *collection = impl_from_IMFCollection(iface);
7673 ULONG refcount = InterlockedDecrement(&collection->refcount);
7675 TRACE("%p, %ld.\n", collection, refcount);
7677 if (!refcount)
7679 collection_clear(collection);
7680 free(collection->elements);
7681 free(collection);
7684 return refcount;
7687 static HRESULT WINAPI collection_GetElementCount(IMFCollection *iface, DWORD *count)
7689 struct collection *collection = impl_from_IMFCollection(iface);
7691 TRACE("%p, %p.\n", iface, count);
7693 if (!count)
7694 return E_POINTER;
7696 *count = collection->count;
7698 return S_OK;
7701 static HRESULT WINAPI collection_GetElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7703 struct collection *collection = impl_from_IMFCollection(iface);
7705 TRACE("%p, %lu, %p.\n", iface, idx, element);
7707 if (!element)
7708 return E_POINTER;
7710 if (idx >= collection->count)
7711 return E_INVALIDARG;
7713 *element = collection->elements[idx];
7714 if (*element)
7715 IUnknown_AddRef(*element);
7717 return *element ? S_OK : E_UNEXPECTED;
7720 static HRESULT WINAPI collection_AddElement(IMFCollection *iface, IUnknown *element)
7722 struct collection *collection = impl_from_IMFCollection(iface);
7724 TRACE("%p, %p.\n", iface, element);
7726 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, collection->count + 1,
7727 sizeof(*collection->elements)))
7728 return E_OUTOFMEMORY;
7730 collection->elements[collection->count++] = element;
7731 if (element)
7732 IUnknown_AddRef(element);
7734 return S_OK;
7737 static HRESULT WINAPI collection_RemoveElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7739 struct collection *collection = impl_from_IMFCollection(iface);
7740 size_t count;
7742 TRACE("%p, %lu, %p.\n", iface, idx, element);
7744 if (!element)
7745 return E_POINTER;
7747 if (idx >= collection->count)
7748 return E_INVALIDARG;
7750 *element = collection->elements[idx];
7752 count = collection->count - idx - 1;
7753 if (count)
7754 memmove(&collection->elements[idx], &collection->elements[idx + 1], count * sizeof(*collection->elements));
7755 collection->count--;
7757 return S_OK;
7760 static HRESULT WINAPI collection_InsertElementAt(IMFCollection *iface, DWORD idx, IUnknown *element)
7762 struct collection *collection = impl_from_IMFCollection(iface);
7763 size_t i;
7765 TRACE("%p, %lu, %p.\n", iface, idx, element);
7767 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, idx + 1,
7768 sizeof(*collection->elements)))
7769 return E_OUTOFMEMORY;
7771 if (idx < collection->count)
7773 memmove(&collection->elements[idx + 1], &collection->elements[idx],
7774 (collection->count - idx) * sizeof(*collection->elements));
7775 collection->count++;
7777 else
7779 for (i = collection->count; i < idx; ++i)
7780 collection->elements[i] = NULL;
7781 collection->count = idx + 1;
7784 collection->elements[idx] = element;
7785 if (collection->elements[idx])
7786 IUnknown_AddRef(collection->elements[idx]);
7788 return S_OK;
7791 static HRESULT WINAPI collection_RemoveAllElements(IMFCollection *iface)
7793 struct collection *collection = impl_from_IMFCollection(iface);
7795 TRACE("%p.\n", iface);
7797 collection_clear(collection);
7799 return S_OK;
7802 static const IMFCollectionVtbl mfcollectionvtbl =
7804 collection_QueryInterface,
7805 collection_AddRef,
7806 collection_Release,
7807 collection_GetElementCount,
7808 collection_GetElement,
7809 collection_AddElement,
7810 collection_RemoveElement,
7811 collection_InsertElementAt,
7812 collection_RemoveAllElements,
7815 /***********************************************************************
7816 * MFCreateCollection (mfplat.@)
7818 HRESULT WINAPI MFCreateCollection(IMFCollection **collection)
7820 struct collection *object;
7822 TRACE("%p\n", collection);
7824 if (!collection)
7825 return E_POINTER;
7827 if (!(object = calloc(1, sizeof(*object))))
7828 return E_OUTOFMEMORY;
7830 object->IMFCollection_iface.lpVtbl = &mfcollectionvtbl;
7831 object->refcount = 1;
7833 *collection = &object->IMFCollection_iface;
7835 return S_OK;
7838 /***********************************************************************
7839 * MFHeapAlloc (mfplat.@)
7841 void *WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type)
7843 TRACE("%Iu, %#lx, %s, %d, %#x.\n", size, flags, debugstr_a(file), line, type);
7844 return HeapAlloc(GetProcessHeap(), flags, size);
7847 /***********************************************************************
7848 * MFHeapFree (mfplat.@)
7850 void WINAPI MFHeapFree(void *p)
7852 TRACE("%p\n", p);
7853 HeapFree(GetProcessHeap(), 0, p);
7856 /***********************************************************************
7857 * MFCreateMFByteStreamOnStreamEx (mfplat.@)
7859 HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream **bytestream)
7861 FIXME("(%p, %p): stub\n", stream, bytestream);
7863 return E_NOTIMPL;
7866 static HRESULT WINAPI system_clock_QueryInterface(IMFClock *iface, REFIID riid, void **obj)
7868 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7870 if (IsEqualIID(riid, &IID_IMFClock) ||
7871 IsEqualIID(riid, &IID_IUnknown))
7873 *obj = iface;
7874 IMFClock_AddRef(iface);
7875 return S_OK;
7878 WARN("Unsupported %s.\n", debugstr_guid(riid));
7879 *obj = NULL;
7880 return E_NOINTERFACE;
7883 static ULONG WINAPI system_clock_AddRef(IMFClock *iface)
7885 struct system_clock *clock = impl_from_IMFClock(iface);
7886 ULONG refcount = InterlockedIncrement(&clock->refcount);
7888 TRACE("%p, refcount %lu.\n", iface, refcount);
7890 return refcount;
7893 static ULONG WINAPI system_clock_Release(IMFClock *iface)
7895 struct system_clock *clock = impl_from_IMFClock(iface);
7896 ULONG refcount = InterlockedDecrement(&clock->refcount);
7898 TRACE("%p, refcount %lu.\n", iface, refcount);
7900 if (!refcount)
7901 free(clock);
7903 return refcount;
7906 static HRESULT WINAPI system_clock_GetClockCharacteristics(IMFClock *iface, DWORD *flags)
7908 TRACE("%p, %p.\n", iface, flags);
7910 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING |
7911 MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7913 return S_OK;
7916 static HRESULT WINAPI system_clock_GetCorrelatedTime(IMFClock *iface, DWORD reserved, LONGLONG *clock_time,
7917 MFTIME *system_time)
7919 TRACE("%p, %#lx, %p, %p.\n", iface, reserved, clock_time, system_time);
7921 *clock_time = *system_time = MFGetSystemTime();
7923 return S_OK;
7926 static HRESULT WINAPI system_clock_GetContinuityKey(IMFClock *iface, DWORD *key)
7928 TRACE("%p, %p.\n", iface, key);
7930 *key = 0;
7932 return S_OK;
7935 static HRESULT WINAPI system_clock_GetState(IMFClock *iface, DWORD reserved, MFCLOCK_STATE *state)
7937 TRACE("%p, %#lx, %p.\n", iface, reserved, state);
7939 *state = MFCLOCK_STATE_RUNNING;
7941 return S_OK;
7944 static HRESULT WINAPI system_clock_GetProperties(IMFClock *iface, MFCLOCK_PROPERTIES *props)
7946 TRACE("%p, %p.\n", iface, props);
7948 if (!props)
7949 return E_POINTER;
7951 memset(props, 0, sizeof(*props));
7952 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7953 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7954 props->dwClockJitter = 1;
7956 return S_OK;
7959 static const IMFClockVtbl system_clock_vtbl =
7961 system_clock_QueryInterface,
7962 system_clock_AddRef,
7963 system_clock_Release,
7964 system_clock_GetClockCharacteristics,
7965 system_clock_GetCorrelatedTime,
7966 system_clock_GetContinuityKey,
7967 system_clock_GetState,
7968 system_clock_GetProperties,
7971 static HRESULT create_system_clock(IMFClock **clock)
7973 struct system_clock *object;
7975 if (!(object = malloc(sizeof(*object))))
7976 return E_OUTOFMEMORY;
7978 object->IMFClock_iface.lpVtbl = &system_clock_vtbl;
7979 object->refcount = 1;
7981 *clock = &object->IMFClock_iface;
7983 return S_OK;
7986 static HRESULT WINAPI system_time_source_QueryInterface(IMFPresentationTimeSource *iface, REFIID riid, void **obj)
7988 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7990 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7992 if (IsEqualIID(riid, &IID_IMFPresentationTimeSource) ||
7993 IsEqualIID(riid, &IID_IUnknown))
7995 *obj = &source->IMFPresentationTimeSource_iface;
7997 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
7999 *obj = &source->IMFClockStateSink_iface;
8001 else
8003 WARN("Unsupported %s.\n", debugstr_guid(riid));
8004 *obj = NULL;
8005 return E_NOINTERFACE;
8008 IUnknown_AddRef((IUnknown *)*obj);
8009 return S_OK;
8012 static ULONG WINAPI system_time_source_AddRef(IMFPresentationTimeSource *iface)
8014 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8015 ULONG refcount = InterlockedIncrement(&source->refcount);
8017 TRACE("%p, refcount %lu.\n", iface, refcount);
8019 return refcount;
8022 static ULONG WINAPI system_time_source_Release(IMFPresentationTimeSource *iface)
8024 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8025 ULONG refcount = InterlockedDecrement(&source->refcount);
8027 TRACE("%p, refcount %lu.\n", iface, refcount);
8029 if (!refcount)
8031 if (source->clock)
8032 IMFClock_Release(source->clock);
8033 DeleteCriticalSection(&source->cs);
8034 free(source);
8037 return refcount;
8040 static HRESULT WINAPI system_time_source_GetClockCharacteristics(IMFPresentationTimeSource *iface, DWORD *flags)
8042 TRACE("%p, %p.\n", iface, flags);
8044 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
8046 return S_OK;
8049 static HRESULT WINAPI system_time_source_GetCorrelatedTime(IMFPresentationTimeSource *iface, DWORD reserved,
8050 LONGLONG *clock_time, MFTIME *system_time)
8052 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8053 HRESULT hr;
8055 TRACE("%p, %#lx, %p, %p.\n", iface, reserved, clock_time, system_time);
8057 EnterCriticalSection(&source->cs);
8058 if (SUCCEEDED(hr = IMFClock_GetCorrelatedTime(source->clock, 0, clock_time, system_time)))
8060 if (source->state == MFCLOCK_STATE_RUNNING)
8061 system_time_source_update_clock_time(source, *system_time);
8062 *clock_time = source->start_offset + source->clock_time;
8064 LeaveCriticalSection(&source->cs);
8066 return hr;
8069 static HRESULT WINAPI system_time_source_GetContinuityKey(IMFPresentationTimeSource *iface, DWORD *key)
8071 TRACE("%p, %p.\n", iface, key);
8073 *key = 0;
8075 return S_OK;
8078 static HRESULT WINAPI system_time_source_GetState(IMFPresentationTimeSource *iface, DWORD reserved,
8079 MFCLOCK_STATE *state)
8081 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8083 TRACE("%p, %#lx, %p.\n", iface, reserved, state);
8085 EnterCriticalSection(&source->cs);
8086 *state = source->state;
8087 LeaveCriticalSection(&source->cs);
8089 return S_OK;
8092 static HRESULT WINAPI system_time_source_GetProperties(IMFPresentationTimeSource *iface, MFCLOCK_PROPERTIES *props)
8094 TRACE("%p, %p.\n", iface, props);
8096 if (!props)
8097 return E_POINTER;
8099 memset(props, 0, sizeof(*props));
8100 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
8101 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
8102 props->dwClockJitter = 1;
8104 return S_OK;
8107 static HRESULT WINAPI system_time_source_GetUnderlyingClock(IMFPresentationTimeSource *iface, IMFClock **clock)
8109 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8111 TRACE("%p, %p.\n", iface, clock);
8113 *clock = source->clock;
8114 IMFClock_AddRef(*clock);
8116 return S_OK;
8119 static const IMFPresentationTimeSourceVtbl systemtimesourcevtbl =
8121 system_time_source_QueryInterface,
8122 system_time_source_AddRef,
8123 system_time_source_Release,
8124 system_time_source_GetClockCharacteristics,
8125 system_time_source_GetCorrelatedTime,
8126 system_time_source_GetContinuityKey,
8127 system_time_source_GetState,
8128 system_time_source_GetProperties,
8129 system_time_source_GetUnderlyingClock,
8132 static HRESULT WINAPI system_time_source_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **out)
8134 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8135 return IMFPresentationTimeSource_QueryInterface(&source->IMFPresentationTimeSource_iface, riid, out);
8138 static ULONG WINAPI system_time_source_sink_AddRef(IMFClockStateSink *iface)
8140 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8141 return IMFPresentationTimeSource_AddRef(&source->IMFPresentationTimeSource_iface);
8144 static ULONG WINAPI system_time_source_sink_Release(IMFClockStateSink *iface)
8146 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8147 return IMFPresentationTimeSource_Release(&source->IMFPresentationTimeSource_iface);
8150 enum clock_command
8152 CLOCK_CMD_START = 0,
8153 CLOCK_CMD_STOP,
8154 CLOCK_CMD_PAUSE,
8155 CLOCK_CMD_RESTART,
8156 CLOCK_CMD_MAX,
8159 static HRESULT system_time_source_change_state(struct system_time_source *source, enum clock_command command)
8161 static const BYTE state_change_is_allowed[MFCLOCK_STATE_PAUSED+1][CLOCK_CMD_MAX] =
8162 { /* S S* P R */
8163 /* INVALID */ { 1, 0, 1, 0 },
8164 /* RUNNING */ { 1, 1, 1, 0 },
8165 /* STOPPED */ { 1, 1, 0, 0 },
8166 /* PAUSED */ { 1, 1, 0, 1 },
8168 static const MFCLOCK_STATE states[CLOCK_CMD_MAX] =
8170 /* CLOCK_CMD_START */ MFCLOCK_STATE_RUNNING,
8171 /* CLOCK_CMD_STOP */ MFCLOCK_STATE_STOPPED,
8172 /* CLOCK_CMD_PAUSE */ MFCLOCK_STATE_PAUSED,
8173 /* CLOCK_CMD_RESTART */ MFCLOCK_STATE_RUNNING,
8176 /* Special case that go against usual state change vs return value behavior. */
8177 if (source->state == MFCLOCK_STATE_INVALID && command == CLOCK_CMD_STOP)
8178 return S_OK;
8180 if (!state_change_is_allowed[source->state][command])
8181 return MF_E_INVALIDREQUEST;
8183 source->state = states[command];
8185 return S_OK;
8188 static HRESULT WINAPI system_time_source_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time,
8189 LONGLONG start_offset)
8191 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8192 MFCLOCK_STATE state;
8193 HRESULT hr;
8195 TRACE("%p, %s, %s.\n", iface, debugstr_time(system_time), debugstr_time(start_offset));
8197 EnterCriticalSection(&source->cs);
8198 state = source->state;
8199 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_START)))
8201 if (start_offset == PRESENTATION_CURRENT_POSITION)
8203 if (state != MFCLOCK_STATE_RUNNING)
8205 source->start_offset -= system_time;
8206 source->system_time = 0;
8209 else
8211 source->start_offset = start_offset;
8212 source->system_time = system_time;
8213 source->clock_time = 0;
8216 LeaveCriticalSection(&source->cs);
8218 return hr;
8221 static HRESULT WINAPI system_time_source_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
8223 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8224 HRESULT hr;
8226 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
8228 EnterCriticalSection(&source->cs);
8229 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_STOP)))
8231 source->start_offset = source->system_time = source->clock_time = 0;
8233 LeaveCriticalSection(&source->cs);
8235 return hr;
8238 static HRESULT WINAPI system_time_source_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
8240 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8241 HRESULT hr;
8243 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
8245 EnterCriticalSection(&source->cs);
8246 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_PAUSE)))
8248 system_time_source_update_clock_time(source, system_time);
8250 LeaveCriticalSection(&source->cs);
8252 return hr;
8255 static HRESULT WINAPI system_time_source_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
8257 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8258 HRESULT hr;
8260 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
8262 EnterCriticalSection(&source->cs);
8263 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_RESTART)))
8265 source->system_time = system_time;
8267 LeaveCriticalSection(&source->cs);
8269 return hr;
8272 static HRESULT WINAPI system_time_source_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
8274 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8275 double intpart;
8277 TRACE("%p, %s, %f.\n", iface, debugstr_time(system_time), rate);
8279 if (rate == 0.0f)
8280 return MF_E_UNSUPPORTED_RATE;
8282 modf(rate, &intpart);
8284 EnterCriticalSection(&source->cs);
8285 source->rate = rate;
8286 source->i_rate = rate == intpart ? rate : 0;
8287 LeaveCriticalSection(&source->cs);
8289 return S_OK;
8292 static const IMFClockStateSinkVtbl systemtimesourcesinkvtbl =
8294 system_time_source_sink_QueryInterface,
8295 system_time_source_sink_AddRef,
8296 system_time_source_sink_Release,
8297 system_time_source_sink_OnClockStart,
8298 system_time_source_sink_OnClockStop,
8299 system_time_source_sink_OnClockPause,
8300 system_time_source_sink_OnClockRestart,
8301 system_time_source_sink_OnClockSetRate,
8304 /***********************************************************************
8305 * MFCreateSystemTimeSource (mfplat.@)
8307 HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source)
8309 struct system_time_source *object;
8310 HRESULT hr;
8312 TRACE("%p.\n", time_source);
8314 object = calloc(1, sizeof(*object));
8315 if (!object)
8316 return E_OUTOFMEMORY;
8318 object->IMFPresentationTimeSource_iface.lpVtbl = &systemtimesourcevtbl;
8319 object->IMFClockStateSink_iface.lpVtbl = &systemtimesourcesinkvtbl;
8320 object->refcount = 1;
8321 object->rate = 1.0f;
8322 object->i_rate = 1;
8323 InitializeCriticalSection(&object->cs);
8325 if (FAILED(hr = create_system_clock(&object->clock)))
8327 IMFPresentationTimeSource_Release(&object->IMFPresentationTimeSource_iface);
8328 return hr;
8331 *time_source = &object->IMFPresentationTimeSource_iface;
8333 return S_OK;
8336 struct async_create_file
8338 IRtwqAsyncCallback IRtwqAsyncCallback_iface;
8339 LONG refcount;
8340 MF_FILE_ACCESSMODE access_mode;
8341 MF_FILE_OPENMODE open_mode;
8342 MF_FILE_FLAGS flags;
8343 WCHAR *path;
8346 struct async_create_file_result
8348 struct list entry;
8349 IRtwqAsyncResult *result;
8350 IMFByteStream *stream;
8353 static struct list async_create_file_results = LIST_INIT(async_create_file_results);
8354 static CRITICAL_SECTION async_create_file_cs = { NULL, -1, 0, 0, 0, 0 };
8356 static struct async_create_file *impl_from_create_file_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
8358 return CONTAINING_RECORD(iface, struct async_create_file, IRtwqAsyncCallback_iface);
8361 static HRESULT WINAPI async_create_file_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
8363 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
8364 IsEqualIID(riid, &IID_IUnknown))
8366 *obj = iface;
8367 IRtwqAsyncCallback_AddRef(iface);
8368 return S_OK;
8371 *obj = NULL;
8372 return E_NOINTERFACE;
8375 static ULONG WINAPI async_create_file_callback_AddRef(IRtwqAsyncCallback *iface)
8377 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8378 ULONG refcount = InterlockedIncrement(&async->refcount);
8380 TRACE("%p, refcount %lu.\n", iface, refcount);
8382 return refcount;
8385 static ULONG WINAPI async_create_file_callback_Release(IRtwqAsyncCallback *iface)
8387 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8388 ULONG refcount = InterlockedDecrement(&async->refcount);
8390 TRACE("%p, refcount %lu.\n", iface, refcount);
8392 if (!refcount)
8394 free(async->path);
8395 free(async);
8398 return refcount;
8401 static HRESULT WINAPI async_create_file_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
8403 return E_NOTIMPL;
8406 static HRESULT WINAPI async_create_file_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
8408 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8409 IRtwqAsyncResult *caller;
8410 IMFByteStream *stream;
8411 HRESULT hr;
8413 caller = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
8415 hr = MFCreateFile(async->access_mode, async->open_mode, async->flags, async->path, &stream);
8416 if (SUCCEEDED(hr))
8418 struct async_create_file_result *result_item;
8420 result_item = malloc(sizeof(*result_item));
8421 if (result_item)
8423 result_item->result = caller;
8424 IRtwqAsyncResult_AddRef(caller);
8425 result_item->stream = stream;
8426 IMFByteStream_AddRef(stream);
8428 EnterCriticalSection(&async_create_file_cs);
8429 list_add_tail(&async_create_file_results, &result_item->entry);
8430 LeaveCriticalSection(&async_create_file_cs);
8433 IMFByteStream_Release(stream);
8435 else
8436 IRtwqAsyncResult_SetStatus(caller, hr);
8438 RtwqInvokeCallback(caller);
8440 return S_OK;
8443 static const IRtwqAsyncCallbackVtbl async_create_file_callback_vtbl =
8445 async_create_file_callback_QueryInterface,
8446 async_create_file_callback_AddRef,
8447 async_create_file_callback_Release,
8448 async_create_file_callback_GetParameters,
8449 async_create_file_callback_Invoke,
8452 /***********************************************************************
8453 * MFBeginCreateFile (mfplat.@)
8455 HRESULT WINAPI MFBeginCreateFile(MF_FILE_ACCESSMODE access_mode, MF_FILE_OPENMODE open_mode, MF_FILE_FLAGS flags,
8456 const WCHAR *path, IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_cookie)
8458 struct async_create_file *async = NULL;
8459 IRtwqAsyncResult *caller, *item = NULL;
8460 HRESULT hr;
8462 TRACE("%#x, %#x, %#x, %s, %p, %p, %p.\n", access_mode, open_mode, flags, debugstr_w(path), callback, state,
8463 cancel_cookie);
8465 if (cancel_cookie)
8466 *cancel_cookie = NULL;
8468 if (FAILED(hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &caller)))
8469 return hr;
8471 if (!(async = malloc(sizeof(*async))))
8473 hr = E_OUTOFMEMORY;
8474 goto failed;
8477 async->IRtwqAsyncCallback_iface.lpVtbl = &async_create_file_callback_vtbl;
8478 async->refcount = 1;
8479 async->access_mode = access_mode;
8480 async->open_mode = open_mode;
8481 async->flags = flags;
8482 if (!(async->path = wcsdup(path)))
8484 hr = E_OUTOFMEMORY;
8485 goto failed;
8488 hr = RtwqCreateAsyncResult(NULL, &async->IRtwqAsyncCallback_iface, (IUnknown *)caller, &item);
8489 if (FAILED(hr))
8490 goto failed;
8492 if (cancel_cookie)
8494 *cancel_cookie = (IUnknown *)caller;
8495 IUnknown_AddRef(*cancel_cookie);
8498 hr = RtwqInvokeCallback(item);
8500 failed:
8501 if (async)
8502 IRtwqAsyncCallback_Release(&async->IRtwqAsyncCallback_iface);
8503 if (item)
8504 IRtwqAsyncResult_Release(item);
8505 if (caller)
8506 IRtwqAsyncResult_Release(caller);
8508 return hr;
8511 static HRESULT async_create_file_pull_result(IUnknown *unk, IMFByteStream **stream)
8513 struct async_create_file_result *item;
8514 HRESULT hr = MF_E_UNEXPECTED;
8515 IRtwqAsyncResult *result;
8517 *stream = NULL;
8519 if (FAILED(IUnknown_QueryInterface(unk, &IID_IRtwqAsyncResult, (void **)&result)))
8520 return hr;
8522 EnterCriticalSection(&async_create_file_cs);
8524 LIST_FOR_EACH_ENTRY(item, &async_create_file_results, struct async_create_file_result, entry)
8526 if (result == item->result)
8528 *stream = item->stream;
8529 IRtwqAsyncResult_Release(item->result);
8530 list_remove(&item->entry);
8531 free(item);
8532 break;
8536 LeaveCriticalSection(&async_create_file_cs);
8538 if (*stream)
8539 hr = IRtwqAsyncResult_GetStatus(result);
8541 IRtwqAsyncResult_Release(result);
8543 return hr;
8546 /***********************************************************************
8547 * MFEndCreateFile (mfplat.@)
8549 HRESULT WINAPI MFEndCreateFile(IMFAsyncResult *result, IMFByteStream **stream)
8551 TRACE("%p, %p.\n", result, stream);
8553 return async_create_file_pull_result((IUnknown *)result, stream);
8556 /***********************************************************************
8557 * MFCancelCreateFile (mfplat.@)
8559 HRESULT WINAPI MFCancelCreateFile(IUnknown *cancel_cookie)
8561 IMFByteStream *stream = NULL;
8562 HRESULT hr;
8564 TRACE("%p.\n", cancel_cookie);
8566 hr = async_create_file_pull_result(cancel_cookie, &stream);
8568 if (stream)
8569 IMFByteStream_Release(stream);
8571 return hr;
8574 /***********************************************************************
8575 * MFRegisterLocalSchemeHandler (mfplat.@)
8577 HRESULT WINAPI MFRegisterLocalSchemeHandler(const WCHAR *scheme, IMFActivate *activate)
8579 struct local_handler *handler;
8581 TRACE("%s, %p.\n", debugstr_w(scheme), activate);
8583 if (!scheme || !activate)
8584 return E_INVALIDARG;
8586 if (!(handler = malloc(sizeof(*handler))))
8587 return E_OUTOFMEMORY;
8589 if (!(handler->u.scheme = wcsdup(scheme)))
8591 free(handler);
8592 return E_OUTOFMEMORY;
8594 handler->activate = activate;
8595 IMFActivate_AddRef(handler->activate);
8597 EnterCriticalSection(&local_handlers_section);
8598 list_add_head(&local_scheme_handlers, &handler->entry);
8599 LeaveCriticalSection(&local_handlers_section);
8601 return S_OK;
8604 /***********************************************************************
8605 * MFRegisterLocalByteStreamHandler (mfplat.@)
8607 HRESULT WINAPI MFRegisterLocalByteStreamHandler(const WCHAR *extension, const WCHAR *mime, IMFActivate *activate)
8609 struct local_handler *handler;
8611 TRACE("%s, %s, %p.\n", debugstr_w(extension), debugstr_w(mime), activate);
8613 if ((!extension && !mime) || !activate)
8614 return E_INVALIDARG;
8616 if (!(handler = calloc(1, sizeof(*handler))))
8617 return E_OUTOFMEMORY;
8619 if (extension && !(handler->u.bytestream.extension = wcsdup(extension)))
8620 goto failed;
8621 if (mime && !(handler->u.bytestream.mime = wcsdup(mime)))
8622 goto failed;
8624 EnterCriticalSection(&local_handlers_section);
8625 list_add_head(&local_bytestream_handlers, &handler->entry);
8626 LeaveCriticalSection(&local_handlers_section);
8628 return S_OK;
8630 failed:
8631 free(handler->u.bytestream.extension);
8632 free(handler->u.bytestream.mime);
8633 free(handler);
8635 return E_OUTOFMEMORY;
8638 struct property_store
8640 IPropertyStore IPropertyStore_iface;
8641 LONG refcount;
8642 CRITICAL_SECTION cs;
8643 size_t count, capacity;
8644 struct
8646 PROPERTYKEY key;
8647 PROPVARIANT value;
8648 } *values;
8651 static struct property_store *impl_from_IPropertyStore(IPropertyStore *iface)
8653 return CONTAINING_RECORD(iface, struct property_store, IPropertyStore_iface);
8656 static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
8658 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8660 if (IsEqualIID(riid, &IID_IPropertyStore) || IsEqualIID(riid, &IID_IUnknown))
8662 *obj = iface;
8663 IPropertyStore_AddRef(iface);
8664 return S_OK;
8667 *obj = NULL;
8668 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
8669 return E_NOINTERFACE;
8672 static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
8674 struct property_store *store = impl_from_IPropertyStore(iface);
8675 ULONG refcount = InterlockedIncrement(&store->refcount);
8677 TRACE("%p, refcount %ld.\n", iface, refcount);
8679 return refcount;
8682 static ULONG WINAPI property_store_Release(IPropertyStore *iface)
8684 struct property_store *store = impl_from_IPropertyStore(iface);
8685 ULONG refcount = InterlockedDecrement(&store->refcount);
8687 TRACE("%p, refcount %ld.\n", iface, refcount);
8689 if (!refcount)
8691 DeleteCriticalSection(&store->cs);
8692 free(store->values);
8693 free(store);
8696 return refcount;
8699 static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
8701 struct property_store *store = impl_from_IPropertyStore(iface);
8703 TRACE("%p, %p.\n", iface, count);
8705 if (!count)
8706 return E_INVALIDARG;
8708 EnterCriticalSection(&store->cs);
8709 *count = store->count;
8710 LeaveCriticalSection(&store->cs);
8711 return S_OK;
8714 static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
8716 struct property_store *store = impl_from_IPropertyStore(iface);
8718 TRACE("%p, %lu, %p.\n", iface, index, key);
8720 EnterCriticalSection(&store->cs);
8722 if (index >= store->count)
8724 LeaveCriticalSection(&store->cs);
8725 return E_INVALIDARG;
8728 *key = store->values[index].key;
8730 LeaveCriticalSection(&store->cs);
8731 return S_OK;
8734 static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
8736 struct property_store *store = impl_from_IPropertyStore(iface);
8737 unsigned int i;
8739 TRACE("%p, %p, %p.\n", iface, key, value);
8741 if (!value)
8742 return E_INVALIDARG;
8744 if (!key)
8745 return S_FALSE;
8747 EnterCriticalSection(&store->cs);
8749 for (i = 0; i < store->count; ++i)
8751 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8753 PropVariantCopy(value, &store->values[i].value);
8754 LeaveCriticalSection(&store->cs);
8755 return S_OK;
8759 LeaveCriticalSection(&store->cs);
8760 return S_FALSE;
8763 static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
8765 struct property_store *store = impl_from_IPropertyStore(iface);
8766 unsigned int i;
8768 TRACE("%p, %p, %p.\n", iface, key, value);
8770 EnterCriticalSection(&store->cs);
8772 for (i = 0; i < store->count; ++i)
8774 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8776 PropVariantCopy(&store->values[i].value, value);
8777 LeaveCriticalSection(&store->cs);
8778 return S_OK;
8782 if (!mf_array_reserve((void **)&store->values, &store->capacity, store->count + 1, sizeof(*store->values)))
8784 LeaveCriticalSection(&store->cs);
8785 return E_OUTOFMEMORY;
8788 store->values[store->count].key = *key;
8789 PropVariantCopy(&store->values[store->count].value, value);
8790 ++store->count;
8792 LeaveCriticalSection(&store->cs);
8793 return S_OK;
8796 static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
8798 TRACE("%p.\n", iface);
8800 return E_NOTIMPL;
8803 static const IPropertyStoreVtbl property_store_vtbl =
8805 property_store_QueryInterface,
8806 property_store_AddRef,
8807 property_store_Release,
8808 property_store_GetCount,
8809 property_store_GetAt,
8810 property_store_GetValue,
8811 property_store_SetValue,
8812 property_store_Commit,
8815 /***********************************************************************
8816 * CreatePropertyStore (mfplat.@)
8818 HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
8820 struct property_store *object;
8822 TRACE("%p.\n", store);
8824 if (!store)
8825 return E_INVALIDARG;
8827 if (!(object = calloc(1, sizeof(*object))))
8828 return E_OUTOFMEMORY;
8830 object->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
8831 object->refcount = 1;
8832 InitializeCriticalSection(&object->cs);
8834 TRACE("Created store %p.\n", object);
8835 *store = &object->IPropertyStore_iface;
8837 return S_OK;
8840 struct shared_dxgi_manager
8842 IMFDXGIDeviceManager *manager;
8843 unsigned int token;
8844 unsigned int locks;
8847 static struct shared_dxgi_manager shared_dm;
8848 static CRITICAL_SECTION shared_dm_cs = { NULL, -1, 0, 0, 0, 0 };
8850 enum dxgi_device_handle_flags
8852 DXGI_DEVICE_HANDLE_FLAG_OPEN = 0x1,
8853 DXGI_DEVICE_HANDLE_FLAG_INVALID = 0x2,
8854 DXGI_DEVICE_HANDLE_FLAG_LOCKED = 0x4,
8857 struct dxgi_device_manager
8859 IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
8860 LONG refcount;
8861 UINT token;
8862 IUnknown *device;
8864 unsigned int *handles;
8865 size_t count;
8866 size_t capacity;
8868 unsigned int locks;
8869 unsigned int locking_tid;
8871 CRITICAL_SECTION cs;
8872 CONDITION_VARIABLE lock;
8875 static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
8877 return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface);
8880 static HRESULT dxgi_device_manager_get_handle_index(struct dxgi_device_manager *manager, HANDLE hdevice, size_t *idx)
8882 if (!hdevice || hdevice > ULongToHandle(manager->count))
8883 return E_HANDLE;
8884 *idx = (ULONG_PTR)hdevice - 1;
8885 return S_OK;
8888 static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj)
8890 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8892 if (IsEqualIID(riid, &IID_IMFDXGIDeviceManager) ||
8893 IsEqualGUID(riid, &IID_IUnknown))
8895 *obj = iface;
8896 IMFDXGIDeviceManager_AddRef(iface);
8897 return S_OK;
8900 WARN("Unsupported %s.\n", debugstr_guid(riid));
8901 *obj = NULL;
8902 return E_NOINTERFACE;
8905 static ULONG WINAPI dxgi_device_manager_AddRef(IMFDXGIDeviceManager *iface)
8907 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8908 ULONG refcount = InterlockedIncrement(&manager->refcount);
8910 TRACE("%p, refcount %lu.\n", iface, refcount);
8912 return refcount;
8915 static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
8917 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8918 ULONG refcount = InterlockedDecrement(&manager->refcount);
8920 TRACE("%p, refcount %lu.\n", iface, refcount);
8922 if (!refcount)
8924 if (manager->device)
8925 IUnknown_Release(manager->device);
8926 DeleteCriticalSection(&manager->cs);
8927 free(manager->handles);
8928 free(manager);
8931 return refcount;
8934 static void dxgi_device_manager_lock_handle(struct dxgi_device_manager *manager, size_t idx)
8936 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED)
8937 return;
8939 manager->handles[idx] |= DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8940 manager->locks++;
8943 static void dxgi_device_manager_unlock_handle(struct dxgi_device_manager *manager, size_t idx)
8945 if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED))
8946 return;
8948 manager->handles[idx] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8949 if (!--manager->locks)
8950 manager->locking_tid = 0;
8953 static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8955 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8956 HRESULT hr;
8957 size_t idx;
8959 TRACE("%p, %p.\n", iface, hdevice);
8961 EnterCriticalSection(&manager->cs);
8963 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8965 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8967 dxgi_device_manager_unlock_handle(manager, idx);
8968 manager->handles[idx] = 0;
8969 if (idx == manager->count - 1)
8970 manager->count--;
8972 else
8973 hr = E_HANDLE;
8976 LeaveCriticalSection(&manager->cs);
8978 WakeAllConditionVariable(&manager->lock);
8980 return hr;
8983 static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8984 REFIID riid, void **service)
8986 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8987 HRESULT hr;
8988 size_t idx;
8990 TRACE("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), service);
8992 EnterCriticalSection(&manager->cs);
8994 if (!manager->device)
8995 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8996 else if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8998 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8999 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
9000 else if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
9001 hr = IUnknown_QueryInterface(manager->device, riid, service);
9002 else
9003 hr = E_HANDLE;
9006 LeaveCriticalSection(&manager->cs);
9008 return hr;
9011 static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
9012 REFIID riid, void **obj, BOOL block)
9014 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9015 HRESULT hr;
9016 size_t idx;
9018 TRACE("%p, %p, %s, %p, %d.\n", iface, hdevice, wine_dbgstr_guid(riid), obj, block);
9020 EnterCriticalSection(&manager->cs);
9022 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
9024 if (!manager->device)
9026 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
9028 else if (manager->locking_tid == GetCurrentThreadId())
9030 if (SUCCEEDED(hr = IUnknown_QueryInterface(manager->device, riid, obj)))
9031 dxgi_device_manager_lock_handle(manager, idx);
9033 else if (manager->locking_tid && !block)
9035 hr = MF_E_DXGI_VIDEO_DEVICE_LOCKED;
9037 else
9039 while (manager->locking_tid)
9041 SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE);
9044 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
9046 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
9047 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
9048 else if (SUCCEEDED(hr = IUnknown_QueryInterface(manager->device, riid, obj)))
9050 manager->locking_tid = GetCurrentThreadId();
9051 dxgi_device_manager_lock_handle(manager, idx);
9057 LeaveCriticalSection(&manager->cs);
9059 return hr;
9062 static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *hdevice)
9064 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9065 HRESULT hr = S_OK;
9066 size_t i;
9068 TRACE("%p, %p.\n", iface, hdevice);
9070 *hdevice = NULL;
9072 EnterCriticalSection(&manager->cs);
9074 if (!manager->device)
9075 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
9076 else
9078 for (i = 0; i < manager->count; ++i)
9080 if (!(manager->handles[i] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
9082 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_OPEN;
9083 *hdevice = ULongToHandle(i + 1);
9084 break;
9088 if (mf_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1,
9089 sizeof(*manager->handles)))
9091 *hdevice = ULongToHandle(manager->count + 1);
9092 manager->handles[manager->count++] = DXGI_DEVICE_HANDLE_FLAG_OPEN;
9094 else
9095 hr = E_OUTOFMEMORY;
9098 LeaveCriticalSection(&manager->cs);
9100 return hr;
9103 static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
9105 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9106 IUnknown *d3d_device;
9107 size_t i;
9109 TRACE("%p, %p, %u.\n", iface, device, token);
9111 if (!device || token != manager->token)
9112 return E_INVALIDARG;
9114 if (FAILED(IUnknown_QueryInterface(device, &IID_ID3D11Device, (void **)&d3d_device)))
9116 if (FAILED(IUnknown_QueryInterface(device, &IID_ID3D12Device, (void **)&d3d_device)))
9118 WARN("Unsupported device interface.\n");
9119 return E_INVALIDARG;
9123 EnterCriticalSection(&manager->cs);
9125 if (manager->device)
9127 for (i = 0; i < manager->count; ++i)
9129 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_INVALID;
9130 manager->handles[i] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
9132 manager->locking_tid = 0;
9133 manager->locks = 0;
9134 IUnknown_Release(manager->device);
9136 manager->device = d3d_device;
9138 LeaveCriticalSection(&manager->cs);
9140 WakeAllConditionVariable(&manager->lock);
9142 return S_OK;
9145 static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice)
9147 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9148 HRESULT hr;
9149 size_t idx;
9151 TRACE("%p, %p.\n", iface, hdevice);
9153 EnterCriticalSection(&manager->cs);
9155 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
9157 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
9158 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
9159 else if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
9160 hr = E_HANDLE;
9163 LeaveCriticalSection(&manager->cs);
9165 return hr;
9168 static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
9169 BOOL savestate)
9171 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9172 HRESULT hr = E_FAIL;
9173 size_t idx;
9175 TRACE("%p, %p, %d.\n", iface, hdevice, savestate);
9177 EnterCriticalSection(&manager->cs);
9179 if (SUCCEEDED(dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
9181 hr = manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED ? S_OK : E_INVALIDARG;
9182 if (SUCCEEDED(hr))
9183 dxgi_device_manager_unlock_handle(manager, idx);
9186 LeaveCriticalSection(&manager->cs);
9188 WakeAllConditionVariable(&manager->lock);
9190 return hr;
9193 static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
9195 dxgi_device_manager_QueryInterface,
9196 dxgi_device_manager_AddRef,
9197 dxgi_device_manager_Release,
9198 dxgi_device_manager_CloseDeviceHandle,
9199 dxgi_device_manager_GetVideoService,
9200 dxgi_device_manager_LockDevice,
9201 dxgi_device_manager_OpenDeviceHandle,
9202 dxgi_device_manager_ResetDevice,
9203 dxgi_device_manager_TestDevice,
9204 dxgi_device_manager_UnlockDevice,
9207 /***********************************************************************
9208 * MFCreateDXGIDeviceManager (mfplat.@)
9210 HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
9212 struct dxgi_device_manager *object;
9214 TRACE("%p, %p.\n", token, manager);
9216 if (!token || !manager)
9217 return E_POINTER;
9219 if (!(object = calloc(1, sizeof(*object))))
9220 return E_OUTOFMEMORY;
9222 object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
9223 object->refcount = 1;
9224 object->token = GetTickCount();
9225 InitializeCriticalSection(&object->cs);
9226 InitializeConditionVariable(&object->lock);
9228 TRACE("Created device manager: %p, token: %u.\n", object, object->token);
9230 *token = object->token;
9231 *manager = &object->IMFDXGIDeviceManager_iface;
9233 return S_OK;
9236 /***********************************************************************
9237 * MFLockDXGIDeviceManager (mfplat.@)
9239 HRESULT WINAPI MFLockDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
9241 HRESULT hr = S_OK;
9243 TRACE("%p, %p.\n", token, manager);
9245 EnterCriticalSection(&shared_dm_cs);
9247 if (!shared_dm.manager)
9248 hr = MFCreateDXGIDeviceManager(&shared_dm.token, &shared_dm.manager);
9250 if (SUCCEEDED(hr))
9252 *manager = shared_dm.manager;
9253 IMFDXGIDeviceManager_AddRef(*manager);
9254 shared_dm.locks++;
9256 if (token) *token = shared_dm.token;
9259 LeaveCriticalSection(&shared_dm_cs);
9261 return hr;
9264 /***********************************************************************
9265 * MFUnlockDXGIDeviceManager (mfplat.@)
9267 HRESULT WINAPI MFUnlockDXGIDeviceManager(void)
9269 TRACE("\n");
9271 EnterCriticalSection(&shared_dm_cs);
9273 if (shared_dm.manager)
9275 IMFDXGIDeviceManager_Release(shared_dm.manager);
9276 if (!--shared_dm.locks)
9278 shared_dm.manager = NULL;
9279 shared_dm.token = 0;
9283 LeaveCriticalSection(&shared_dm_cs);
9285 return S_OK;
9290 * MFllMulDiv implementation is derived from gstreamer utility functions code (gstutils.c),
9291 * released under LGPL2. Full authors list follows.
9292 * ===================================================================================
9293 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
9294 * 2000 Wim Taymans <wtay@chello.be>
9295 * 2002 Thomas Vander Stichele <thomas@apestaart.org>
9296 * 2004 Wim Taymans <wim@fluendo.com>
9297 * 2015 Jan Schmidt <jan@centricular.com>
9298 * ===================================================================================
9301 static void llmult128(ULARGE_INTEGER *c1, ULARGE_INTEGER *c0, LONGLONG val, LONGLONG num)
9303 ULARGE_INTEGER a1, b0, v, n;
9305 v.QuadPart = llabs(val);
9306 n.QuadPart = llabs(num);
9308 /* do 128 bits multiply
9309 * nh nl
9310 * * vh vl
9311 * ----------
9312 * a0 = vl * nl
9313 * a1 = vl * nh
9314 * b0 = vh * nl
9315 * b1 = + vh * nh
9316 * -------------------
9317 * c1h c1l c0h c0l
9319 * "a0" is optimized away, result is stored directly in c0. "b1" is
9320 * optimized away, result is stored directly in c1.
9322 c0->QuadPart = (ULONGLONG)v.LowPart * n.LowPart;
9323 a1.QuadPart = (ULONGLONG)v.LowPart * n.HighPart;
9324 b0.QuadPart = (ULONGLONG)v.HighPart * n.LowPart;
9326 /* add the high word of a0 to the low words of a1 and b0 using c1 as
9327 * scratch space to capture the carry. the low word of the result becomes
9328 * the final high word of c0 */
9329 c1->QuadPart = (ULONGLONG)c0->HighPart + a1.LowPart + b0.LowPart;
9330 c0->HighPart = c1->LowPart;
9332 /* add the carry from the result above (found in the high word of c1) and
9333 * the high words of a1 and b0 to b1, the result is c1. */
9334 c1->QuadPart = (ULONGLONG)v.HighPart * n.HighPart + c1->HighPart + a1.HighPart + b0.HighPart;
9337 static ULONGLONG lldiv128(ULARGE_INTEGER c1, ULARGE_INTEGER c0, LONGLONG denom)
9339 ULARGE_INTEGER q1, q0, rhat;
9340 ULARGE_INTEGER v, cmp1, cmp2;
9341 DWORD s = 0;
9343 v.QuadPart = llabs(denom);
9345 /* 64bit numerator */
9346 if (c1.QuadPart == 0)
9347 return c0.QuadPart / v.QuadPart;
9349 /* 96bit numerator, 32bit denominator */
9350 if (v.HighPart == 0 && c1.HighPart == 0)
9352 ULONGLONG low = c0.LowPart, high = c0.HighPart + ((ULONGLONG)c1.LowPart << 32);
9353 low += (high % v.LowPart) << 32;
9354 return ((high / v.LowPart) << 32) + (low / v.LowPart);
9357 /* 128bit numerator, 32bit denominator */
9358 if (v.HighPart == 0)
9359 return UI64_MAX;
9361 /* count number of leading zeroes */
9362 BitScanReverse(&s, v.HighPart);
9363 s = 31 - s;
9365 if (s)
9367 /* normalize divisor and dividend */
9368 v.QuadPart <<= s;
9369 c1.QuadPart = (c1.QuadPart << s) | (c0.HighPart >> (32 - s));
9370 c0.QuadPart <<= s;
9373 q1.QuadPart = c1.QuadPart / v.HighPart;
9374 rhat.QuadPart = c1.QuadPart - q1.QuadPart * v.HighPart;
9376 cmp1.HighPart = rhat.LowPart;
9377 cmp1.LowPart = c0.HighPart;
9378 cmp2.QuadPart = q1.QuadPart * v.LowPart;
9380 while (q1.HighPart || cmp2.QuadPart > cmp1.QuadPart)
9382 q1.QuadPart--;
9383 rhat.QuadPart += v.HighPart;
9384 if (rhat.HighPart)
9385 break;
9386 cmp1.HighPart = rhat.LowPart;
9387 cmp2.QuadPart -= v.LowPart;
9389 c1.HighPart = c1.LowPart;
9390 c1.LowPart = c0.HighPart;
9391 c1.QuadPart -= q1.QuadPart * v.QuadPart;
9392 q0.QuadPart = c1.QuadPart / v.HighPart;
9393 rhat.QuadPart = c1.QuadPart - q0.QuadPart * v.HighPart;
9395 cmp1.HighPart = rhat.LowPart;
9396 cmp1.LowPart = c0.LowPart;
9397 cmp2.QuadPart = q0.QuadPart * v.LowPart;
9399 while (q0.HighPart || cmp2.QuadPart > cmp1.QuadPart)
9401 q0.QuadPart--;
9402 rhat.QuadPart += v.HighPart;
9403 if (rhat.HighPart)
9404 break;
9405 cmp1.HighPart = rhat.LowPart;
9406 cmp2.QuadPart -= v.LowPart;
9408 q0.HighPart += q1.LowPart;
9410 return q0.QuadPart;
9413 /***********************************************************************
9414 * MFllMulDiv (mfplat.@)
9416 LONGLONG WINAPI MFllMulDiv(LONGLONG val, LONGLONG num, LONGLONG denom, LONGLONG factor)
9418 #define LLOVERFLOW (sign ? I64_MIN : I64_MAX)
9419 unsigned int sign, factor_sign, denom_sign;
9420 ULARGE_INTEGER c1, c0;
9421 ULONGLONG ret;
9423 TRACE("%s, %s, %s, %s.\n", wine_dbgstr_longlong(val), wine_dbgstr_longlong(num),
9424 wine_dbgstr_longlong(denom), wine_dbgstr_longlong(factor));
9426 /* compute 128-bit numerator product */
9427 llmult128(&c1, &c0, val, num);
9429 sign = (val < 0) ^ (num < 0);
9430 factor_sign = factor < 0;
9431 denom_sign = denom < 0;
9433 factor = llabs(factor);
9434 if (sign == factor_sign)
9436 if (UI64_MAX - c0.QuadPart < factor)
9438 if (c1.QuadPart == UI64_MAX) return LLOVERFLOW;
9439 c1.QuadPart++;
9441 c0.QuadPart += factor;
9443 else
9445 if (c0.QuadPart >= factor)
9446 c0.QuadPart -= factor;
9447 else
9449 if (c1.QuadPart)
9450 c1.QuadPart--;
9451 else
9452 sign = !sign;
9454 c0.QuadPart = factor - c0.QuadPart;
9458 if (c1.QuadPart >= denom) return LLOVERFLOW;
9460 /* compute quotient, fits in 64 bits */
9461 ret = lldiv128(c1, c0, denom);
9462 sign ^= denom_sign;
9463 if (ret >= I64_MAX) return LLOVERFLOW;
9464 return sign ? -(LONGLONG)ret : ret;
9465 #undef LLOVERFLOW
9468 /***********************************************************************
9469 * MFCreatePathFromURL (mfplat.@)
9471 HRESULT WINAPI MFCreatePathFromURL(const WCHAR *url, WCHAR **ret_path)
9473 WCHAR path[MAX_PATH];
9474 DWORD length;
9475 HRESULT hr;
9477 TRACE("%s, %p.\n", debugstr_w(url), ret_path);
9479 if (!url || !ret_path)
9480 return E_POINTER;
9482 length = ARRAY_SIZE(path);
9483 if (FAILED(hr = PathCreateFromUrlW(url, path, &length, 0)))
9484 return hr;
9486 if (!(*ret_path = CoTaskMemAlloc((length + 1) * sizeof(*path))))
9487 return E_OUTOFMEMORY;
9489 memcpy(*ret_path, path, (length + 1) * sizeof(*path));
9490 return S_OK;