kernel32/tests/pipe: Enable compilation with long types.
[wine.git] / dlls / mfplat / main.c
blobcee052defeb14a2686290583fe5be9622a86a475
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;
1354 list_init(&mfts);
1356 if (FAILED(hr = mft_collect_machine_reg(&mfts, &category, MFT_ENUM_FLAG_SYNCMFT, NULL, input_type, output_type)))
1357 return hr;
1359 mft_count = list_count(&mfts);
1361 if (mft_count)
1363 if (!(*clsids = CoTaskMemAlloc(mft_count * sizeof(**clsids))))
1364 hr = E_OUTOFMEMORY;
1366 mft_count = 0;
1367 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1369 if (*clsids)
1370 (*clsids)[mft_count++] = mft->clsid;
1371 list_remove(&mft->entry);
1372 release_mft_registration(mft);
1376 if (!mft_count)
1378 CoTaskMemFree(*clsids);
1379 *clsids = NULL;
1381 *count = mft_count;
1383 return hr;
1386 /***********************************************************************
1387 * MFTEnumEx (mfplat.@)
1389 HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1390 const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *count)
1392 TRACE("%s, %#x, %s, %s, %p, %p.\n", debugstr_mf_guid(&category), flags, debugstr_reg_typeinfo(input_type),
1393 debugstr_reg_typeinfo(output_type), activate, count);
1395 return mft_enum(category, flags, input_type, output_type, NULL, activate, count);
1398 /***********************************************************************
1399 * MFTEnum2 (mfplat.@)
1401 HRESULT WINAPI MFTEnum2(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1402 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1404 TRACE("%s, %#x, %s, %s, %p, %p, %p.\n", debugstr_mf_guid(&category), flags, debugstr_reg_typeinfo(input_type),
1405 debugstr_reg_typeinfo(output_type), attributes, activate, count);
1407 if (attributes)
1408 FIXME("Ignoring attributes.\n");
1410 return mft_enum(category, flags, input_type, output_type, attributes, activate, count);
1413 /***********************************************************************
1414 * MFTUnregister (mfplat.@)
1416 HRESULT WINAPI MFTUnregister(CLSID clsid)
1418 WCHAR buffer[64], category[MAX_PATH];
1419 HKEY htransform, hcategory, htmp;
1420 DWORD size = MAX_PATH;
1421 DWORD index = 0;
1423 TRACE("(%s)\n", debugstr_guid(&clsid));
1425 guid_to_string(buffer, &clsid);
1427 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1429 RegDeleteKeyW(htransform, buffer);
1430 RegCloseKey(htransform);
1433 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1435 while (RegEnumKeyExW(hcategory, index, category, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
1437 if (!RegOpenKeyW(hcategory, category, &htmp))
1439 RegDeleteKeyW(htmp, buffer);
1440 RegCloseKey(htmp);
1442 size = MAX_PATH;
1443 index++;
1445 RegCloseKey(hcategory);
1448 return S_OK;
1451 static HRESULT mft_get_name(HKEY hkey, WCHAR **name)
1453 DWORD size;
1455 if (!name)
1456 return S_OK;
1458 *name = NULL;
1460 if (!RegQueryValueExW(hkey, NULL, NULL, NULL, NULL, &size))
1462 if (!(*name = CoTaskMemAlloc(size)))
1463 return E_OUTOFMEMORY;
1465 RegQueryValueExW(hkey, NULL, NULL, NULL, (BYTE *)*name, &size);
1468 return S_OK;
1471 static HRESULT mft_get_reg_type_info(const WCHAR *clsid, const WCHAR *key, MFT_REGISTER_TYPE_INFO **ret_types,
1472 UINT32 *ret_count)
1474 MFT_REGISTER_TYPE_INFO *types = NULL;
1475 UINT32 count = 0;
1477 if (!ret_types)
1478 return S_OK;
1480 mft_get_reg_type_info_internal(clsid, key, &types, &count);
1481 if (count)
1483 if (!(*ret_types = CoTaskMemAlloc(count * sizeof(**ret_types))))
1485 free(types);
1486 return E_OUTOFMEMORY;
1489 memcpy(*ret_types, types, count * sizeof(**ret_types));
1490 *ret_count = count;
1493 free(types);
1495 return S_OK;
1498 static HRESULT mft_get_attributes(HKEY hkey, IMFAttributes **ret)
1500 IMFAttributes *attributes;
1501 UINT8 *blob;
1502 DWORD size;
1503 HRESULT hr;
1505 if (!ret)
1506 return S_OK;
1508 if (FAILED(hr = MFCreateAttributes(&attributes, 0)))
1509 return hr;
1511 if (!RegQueryValueExW(hkey, L"Attributes", NULL, NULL, NULL, &size) && size)
1513 if (!(blob = malloc(size)))
1515 IMFAttributes_Release(attributes);
1516 return E_OUTOFMEMORY;
1519 if (!RegQueryValueExW(hkey, L"Attributes", NULL, NULL, blob, &size))
1521 if (FAILED(hr = MFInitAttributesFromBlob(attributes, blob, size)))
1522 WARN("Failed to initialize attributes, hr %#lx.\n", hr);
1525 free(blob);
1528 if (SUCCEEDED(hr))
1530 *ret = attributes;
1531 IMFAttributes_AddRef(*ret);
1534 IMFAttributes_Release(attributes);
1536 return hr;
1539 /***********************************************************************
1540 * MFTGetInfo (mfplat.@)
1542 HRESULT WINAPI MFTGetInfo(CLSID clsid, WCHAR **name, MFT_REGISTER_TYPE_INFO **input_types,
1543 UINT32 *input_types_count, MFT_REGISTER_TYPE_INFO **output_types, UINT32 *output_types_count,
1544 IMFAttributes **attributes)
1546 HRESULT hr = S_OK;
1547 WCHAR clsidW[64];
1548 HKEY hroot, hmft;
1549 DWORD ret;
1551 TRACE("%s, %p, %p, %p, %p, %p, %p.\n", debugstr_guid(&clsid), name, input_types,
1552 input_types_count, output_types, output_types_count, attributes);
1554 guid_to_string(clsidW, &clsid);
1556 if ((ret = RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &hroot)))
1557 return HRESULT_FROM_WIN32(ret);
1559 ret = RegOpenKeyW(hroot, clsidW, &hmft);
1560 RegCloseKey(hroot);
1561 if (ret)
1562 return HRESULT_FROM_WIN32(ret);
1564 if (input_types_count)
1565 *input_types_count = 0;
1567 if (output_types_count)
1568 *output_types_count = 0;
1570 hr = mft_get_name(hmft, name);
1572 if (SUCCEEDED(hr))
1573 hr = mft_get_reg_type_info(clsidW, L"InputTypes", input_types, input_types_count);
1575 if (SUCCEEDED(hr))
1576 hr = mft_get_reg_type_info(clsidW, L"OutputTypes", output_types, output_types_count);
1578 if (SUCCEEDED(hr))
1579 hr = mft_get_attributes(hmft, attributes);
1581 RegCloseKey(hmft);
1583 return hr;
1586 /***********************************************************************
1587 * MFStartup (mfplat.@)
1589 HRESULT WINAPI MFStartup(ULONG version, DWORD flags)
1591 #define MF_VERSION_XP MAKELONG( MF_API_VERSION, 1 )
1592 #define MF_VERSION_WIN7 MAKELONG( MF_API_VERSION, 2 )
1594 TRACE("%#lx, %#lx.\n", version, flags);
1596 if (version != MF_VERSION_XP && version != MF_VERSION_WIN7)
1597 return MF_E_BAD_STARTUP_VERSION;
1599 RtwqStartup();
1601 return S_OK;
1604 /***********************************************************************
1605 * MFShutdown (mfplat.@)
1607 HRESULT WINAPI MFShutdown(void)
1609 TRACE("\n");
1611 RtwqShutdown();
1613 return S_OK;
1616 /***********************************************************************
1617 * MFCopyImage (mfplat.@)
1619 HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines)
1621 TRACE("%p, %ld, %p, %ld, %lu, %lu.\n", dest, deststride, src, srcstride, width, lines);
1623 while (lines--)
1625 memcpy(dest, src, width);
1626 dest += deststride;
1627 src += srcstride;
1630 return S_OK;
1633 struct guid_def
1635 const GUID *guid;
1636 const char *name;
1639 static int __cdecl debug_compare_guid(const void *a, const void *b)
1641 const GUID *guid = a;
1642 const struct guid_def *guid_def = b;
1643 return memcmp(guid, guid_def->guid, sizeof(*guid));
1646 const char *debugstr_attr(const GUID *guid)
1648 static const struct guid_def guid_defs[] =
1650 #define X(g) { &(g), #g }
1651 #define MF_READER_WRITER_D3D_MANAGER MF_SOURCE_READER_D3D_MANAGER
1652 X(MF_READWRITE_MMCSS_CLASS),
1653 X(MF_TOPONODE_MARKIN_HERE),
1654 X(MF_MT_H264_SUPPORTED_SYNC_FRAME_TYPES),
1655 X(MF_TOPONODE_MARKOUT_HERE),
1656 X(EVRConfig_ForceBob),
1657 X(MF_TOPONODE_DECODER),
1658 X(EVRConfig_AllowDropToBob),
1659 X(MF_TOPOLOGY_PROJECTSTART),
1660 X(EVRConfig_ForceThrottle),
1661 X(MF_VIDEO_MAX_MB_PER_SEC),
1662 X(MF_TOPOLOGY_PROJECTSTOP),
1663 X(MF_SINK_WRITER_ENCODER_CONFIG),
1664 X(EVRConfig_AllowDropToThrottle),
1665 X(MF_TOPOLOGY_NO_MARKIN_MARKOUT),
1666 X(EVRConfig_ForceHalfInterlace),
1667 X(EVRConfig_AllowDropToHalfInterlace),
1668 X(EVRConfig_ForceScaling),
1669 X(MF_MT_H264_CAPABILITIES),
1670 X(EVRConfig_AllowScaling),
1671 X(MF_SOURCE_READER_ENABLE_TRANSCODE_ONLY_TRANSFORMS),
1672 X(MFT_PREFERRED_ENCODER_PROFILE),
1673 X(EVRConfig_ForceBatching),
1674 X(EVRConfig_AllowBatching),
1675 X(MF_TOPOLOGY_DYNAMIC_CHANGE_NOT_ALLOWED),
1676 X(MF_MT_VIDEO_PROFILE),
1677 X(MF_MT_DV_AAUX_CTRL_PACK_1),
1678 X(MF_MT_ALPHA_MODE),
1679 X(MF_MT_MPEG2_TIMECODE),
1680 X(MF_PMP_SERVER_CONTEXT),
1681 X(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE),
1682 X(MF_MEDIA_ENGINE_TRACK_ID),
1683 X(MF_MT_CUSTOM_VIDEO_PRIMARIES),
1684 X(MF_MT_TIMESTAMP_CAN_BE_DTS),
1685 X(MFT_CODEC_MERIT_Attribute),
1686 X(MF_TOPOLOGY_PLAYBACK_MAX_DIMS),
1687 X(MF_XVP_DISABLE_FRC),
1688 X(MF_LOW_LATENCY),
1689 X(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS),
1690 X(MF_MT_MPEG2_FLAGS),
1691 X(MF_MEDIA_ENGINE_AUDIO_CATEGORY),
1692 X(MF_MT_PIXEL_ASPECT_RATIO),
1693 X(MF_VIDEO_PROCESSOR_ALGORITHM),
1694 X(MF_TOPOLOGY_ENABLE_XVP_FOR_PLAYBACK),
1695 X(MFT_CONNECTED_STREAM_ATTRIBUTE),
1696 X(MF_MT_REALTIME_CONTENT),
1697 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_FLAGS),
1698 X(MF_MT_WRAPPED_TYPE),
1699 X(MF_MT_DRM_FLAGS),
1700 X(MF_MT_AVG_BITRATE),
1701 X(MF_MT_DECODER_USE_MAX_RESOLUTION),
1702 X(MF_MT_MAX_LUMINANCE_LEVEL),
1703 X(MFT_CONNECTED_TO_HW_STREAM),
1704 X(MF_SA_D3D_AWARE),
1705 X(MF_XVP_SAMPLE_LOCK_TIMEOUT),
1706 X(MF_MT_MAX_KEYFRAME_SPACING),
1707 X(MFT_TRANSFORM_CLSID_Attribute),
1708 X(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING),
1709 X(MF_MT_AM_FORMAT_TYPE),
1710 X(MF_SESSION_APPROX_EVENT_OCCURRENCE_TIME),
1711 X(MF_MEDIA_ENGINE_SYNCHRONOUS_CLOSE),
1712 X(MF_MT_H264_MAX_MB_PER_SEC),
1713 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_MAX_BUFFERS),
1714 X(MF_MT_AUDIO_BLOCK_ALIGNMENT),
1715 X(MF_PD_PMPHOST_CONTEXT),
1716 X(MF_PD_APP_CONTEXT),
1717 X(MF_PD_DURATION),
1718 X(MF_PD_TOTAL_FILE_SIZE),
1719 X(MF_PD_AUDIO_ENCODING_BITRATE),
1720 X(MF_PD_VIDEO_ENCODING_BITRATE),
1721 X(MFSampleExtension_TargetGlobalLuminance),
1722 X(MF_PD_MIME_TYPE),
1723 X(MF_MT_H264_SUPPORTED_SLICE_MODES),
1724 X(MF_PD_LAST_MODIFIED_TIME),
1725 X(VIDEO_ZOOM_RECT),
1726 X(MF_PD_PLAYBACK_ELEMENT_ID),
1727 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE9),
1728 X(MF_MT_ALL_SAMPLES_INDEPENDENT),
1729 X(MF_SA_D3D12_CLEAR_VALUE),
1730 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER),
1731 X(MF_PD_PREFERRED_LANGUAGE),
1732 X(MF_PD_PLAYBACK_BOUNDARY_TIME),
1733 X(MF_MEDIA_ENGINE_TELEMETRY_APPLICATION_ID),
1734 X(MF_ACTIVATE_MFT_LOCKED),
1735 X(MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT),
1736 X(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING),
1737 X(MF_MT_FRAME_SIZE),
1738 X(MF_MT_H264_SIMULCAST_SUPPORT),
1739 X(MF_SINK_WRITER_ASYNC_CALLBACK),
1740 X(MF_TOPOLOGY_START_TIME_ON_PRESENTATION_SWITCH),
1741 X(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER),
1742 X(MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY),
1743 X(MF_MT_FRAME_RATE_RANGE_MAX),
1744 X(MF_MT_PALETTE),
1745 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_PROVIDER_DEVICE_ID),
1746 X(MF_TOPOLOGY_STATIC_PLAYBACK_OPTIMIZATIONS),
1747 X(MF_SA_D3D11_USAGE),
1748 X(MF_MEDIA_ENGINE_NEEDKEY_CALLBACK),
1749 X(MF_MT_GEOMETRIC_APERTURE),
1750 X(MF_MT_ORIGINAL_WAVE_FORMAT_TAG),
1751 X(MF_MT_DV_AAUX_SRC_PACK_1),
1752 X(MF_MEDIA_ENGINE_STREAM_CONTAINS_ALPHA_CHANNEL),
1753 X(MF_MEDIA_ENGINE_MEDIA_PLAYER_MODE),
1754 X(MF_MEDIA_ENGINE_EXTENSION),
1755 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS),
1756 X(MF_MT_DEFAULT_STRIDE),
1757 X(MF_MT_ARBITRARY_FORMAT),
1758 X(MF_TRANSFORM_CATEGORY_Attribute),
1759 X(MF_MT_MPEG2_HDCP),
1760 X(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
1761 X(MF_MT_SPATIAL_AUDIO_MAX_DYNAMIC_OBJECTS),
1762 X(MF_MT_DECODER_MAX_DPB_COUNT),
1763 X(MFSampleExtension_ForwardedDecodeUnits),
1764 X(MF_SA_D3D11_SHARED_WITHOUT_MUTEX),
1765 X(MF_MT_DV_AAUX_CTRL_PACK_0),
1766 X(MF_MT_YUV_MATRIX),
1767 X(MF_EVENT_SOURCE_TOPOLOGY_CANCELED),
1768 X(MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY),
1769 X(MF_MT_MAX_FRAME_AVERAGE_LUMINANCE_LEVEL),
1770 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID),
1771 X(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME),
1772 X(MF_MT_VIDEO_ROTATION),
1773 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_SYMBOLIC_LINK),
1774 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE11),
1775 X(MF_MT_USER_DATA),
1776 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID),
1777 X(MF_MT_MIN_MASTERING_LUMINANCE),
1778 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE),
1779 X(MF_SA_REQUIRED_SAMPLE_COUNT),
1780 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS),
1781 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID),
1782 X(MF_EVENT_STREAM_METADATA_SYSTEMID),
1783 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE),
1784 X(MF_MT_AUDIO_CHANNEL_MASK),
1785 X(MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN),
1786 X(MF_READWRITE_DISABLE_CONVERTERS),
1787 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE_EDGE),
1788 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS),
1789 X(MF_SA_D3D12_HEAP_FLAGS),
1790 X(MF_MT_MINIMUM_DISPLAY_APERTURE),
1791 X(MFSampleExtension_Token),
1792 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_CATEGORY),
1793 X(MF_D3D12_SYNCHRONIZATION_OBJECT),
1794 X(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
1795 X(MF_TRANSFORM_ASYNC_UNLOCK),
1796 X(MF_DISABLE_FRAME_CORRUPTION_INFO),
1797 X(MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES),
1798 X(MF_MT_VIDEO_NO_FRAME_ORDERING),
1799 X(MF_MEDIA_ENGINE_PLAYBACK_VISUAL),
1800 X(MF_MT_VIDEO_CHROMA_SITING),
1801 X(MF_AUDIO_RENDERER_ATTRIBUTE_STREAM_CATEGORY),
1802 X(MF_SA_BUFFERS_PER_SAMPLE),
1803 X(MFSampleExtension_3DVideo_SampleFormat),
1804 X(MF_MT_H264_RESOLUTION_SCALING),
1805 X(MF_MT_VIDEO_LEVEL),
1806 X(MF_SA_D3D12_HEAP_TYPE),
1807 X(MF_SAMPLEGRABBERSINK_SAMPLE_TIME_OFFSET),
1808 X(MF_MT_SAMPLE_SIZE),
1809 X(MF_MT_AAC_PAYLOAD_TYPE),
1810 X(MF_TOPOLOGY_PLAYBACK_FRAMERATE),
1811 X(MF_SOURCE_READER_D3D11_BIND_FLAGS),
1812 X(MF_MT_AUDIO_FOLDDOWN_MATRIX),
1813 X(MF_MT_AUDIO_WMADRC_PEAKREF),
1814 X(MF_MT_AUDIO_WMADRC_PEAKTARGET),
1815 X(MF_TRANSFORM_FLAGS_Attribute),
1816 X(MF_MT_H264_SUPPORTED_RATE_CONTROL_MODES),
1817 X(MF_PD_SAMI_STYLELIST),
1818 X(MF_MT_AUDIO_WMADRC_AVGREF),
1819 X(MF_MT_AUDIO_BITS_PER_SAMPLE),
1820 X(MF_SD_LANGUAGE),
1821 X(MF_MT_AUDIO_WMADRC_AVGTARGET),
1822 X(MF_SD_PROTECTED),
1823 X(MF_SESSION_TOPOLOADER),
1824 X(MF_SESSION_GLOBAL_TIME),
1825 X(MF_SESSION_QUALITY_MANAGER),
1826 X(MF_SESSION_CONTENT_PROTECTION_MANAGER),
1827 X(MF_MT_MPEG4_SAMPLE_DESCRIPTION),
1828 X(MF_MT_D3D_RESOURCE_VERSION),
1829 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET),
1830 X(MF_MT_MPEG_START_TIME_CODE),
1831 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1832 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1833 X(MF_READWRITE_MMCSS_PRIORITY_AUDIO),
1834 X(MF_MT_H264_MAX_CODEC_CONFIG_DELAY),
1835 X(MF_MT_DV_AAUX_SRC_PACK_0),
1836 X(MF_BYTESTREAM_ORIGIN_NAME),
1837 X(MF_BYTESTREAM_CONTENT_TYPE),
1838 X(MF_MT_DEPTH_MEASUREMENT),
1839 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WIN10),
1840 X(MF_MT_VIDEO_3D_NUM_VIEWS),
1841 X(MF_BYTESTREAM_DURATION),
1842 X(MF_SD_SAMI_LANGUAGE),
1843 X(MF_EVENT_OUTPUT_NODE),
1844 X(MF_BYTESTREAM_LAST_MODIFIED_TIME),
1845 X(MFT_ENUM_ADAPTER_LUID),
1846 X(MF_MT_FRAME_RATE_RANGE_MIN),
1847 X(MF_BYTESTREAM_IFO_FILE_URI),
1848 X(MF_EVENT_TOPOLOGY_STATUS),
1849 X(MF_BYTESTREAM_DLNA_PROFILE_ID),
1850 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ROLE),
1851 X(MF_MT_MAJOR_TYPE),
1852 X(MF_SA_REQUIRED_SAMPLE_COUNT_PROGRESSIVE),
1853 X(MF_MT_IN_BAND_PARAMETER_SET),
1854 X(MF_EVENT_SOURCE_CHARACTERISTICS),
1855 X(MF_EVENT_SOURCE_CHARACTERISTICS_OLD),
1856 X(MF_SESSION_SERVER_CONTEXT),
1857 X(MF_MT_VIDEO_3D_FIRST_IS_LEFT),
1858 X(MFT_DECODER_FINAL_VIDEO_RESOLUTION_HINT),
1859 X(MF_PD_ADAPTIVE_STREAMING),
1860 X(MF_MEDIA_ENGINE_SOURCE_RESOLVER_CONFIG_STORE),
1861 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WWA_EDGE),
1862 X(MF_MT_H264_SUPPORTED_USAGES),
1863 X(MFT_PREFERRED_OUTPUTTYPE_Attribute),
1864 X(MFSampleExtension_Timestamp),
1865 X(MF_TOPONODE_PRIMARYOUTPUT),
1866 X(MF_MT_SUBTYPE),
1867 X(MF_TRANSFORM_ASYNC),
1868 X(MF_TOPONODE_STREAMID),
1869 X(MF_MEDIA_ENGINE_PLAYBACK_HWND),
1870 X(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE),
1871 X(MF_MT_VIDEO_LIGHTING),
1872 X(MF_SD_MUTUALLY_EXCLUSIVE),
1873 X(MF_SD_STREAM_NAME),
1874 X(MF_MT_DV_VAUX_SRC_PACK),
1875 X(MF_TOPONODE_RATELESS),
1876 X(MF_EVENT_STREAM_METADATA_CONTENT_KEYIDS),
1877 X(MF_TOPONODE_DISABLE_PREROLL),
1878 X(MF_SA_D3D11_ALLOW_DYNAMIC_YUV_TEXTURE),
1879 X(MF_MT_VIDEO_3D_FORMAT),
1880 X(MF_EVENT_STREAM_METADATA_KEYDATA),
1881 X(MF_READER_WRITER_D3D_MANAGER),
1882 X(MFSampleExtension_3DVideo),
1883 X(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE),
1884 X(MF_MT_H264_USAGE),
1885 X(MF_MEDIA_ENGINE_EME_CALLBACK),
1886 X(MF_EVENT_SOURCE_FAKE_START),
1887 X(MF_EVENT_SOURCE_PROJECTSTART),
1888 X(MF_EVENT_SOURCE_ACTUAL_START),
1889 X(MF_MT_D3D12_TEXTURE_LAYOUT),
1890 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_MANAGER),
1891 X(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
1892 X(MFT_ENUM_HARDWARE_URL_Attribute),
1893 X(MF_SOURCE_READER_ASYNC_CALLBACK),
1894 X(MF_MT_D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE),
1895 X(MF_MT_OUTPUT_BUFFER_NUM),
1896 X(MF_SA_D3D11_BINDFLAGS),
1897 X(MFT_ENCODER_SUPPORTS_CONFIG_EVENT),
1898 X(MF_MT_AUDIO_FLAC_MAX_BLOCK_SIZE),
1899 X(MFT_FRIENDLY_NAME_Attribute),
1900 X(MF_MT_FIXED_SIZE_SAMPLES),
1901 X(MFT_SUPPORT_3DVIDEO),
1902 X(MFT_SUPPORT_3DVIDEO),
1903 X(MFT_INPUT_TYPES_Attributes),
1904 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS),
1905 X(MF_MT_H264_LAYOUT_PER_STREAM),
1906 X(MF_EVENT_SCRUBSAMPLE_TIME),
1907 X(MF_MT_SPATIAL_AUDIO_MAX_METADATA_ITEMS),
1908 X(MF_MT_MPEG2_ONE_FRAME_PER_PACKET),
1909 X(MF_MT_INTERLACE_MODE),
1910 X(MF_MEDIA_ENGINE_CALLBACK),
1911 X(MF_MT_VIDEO_RENDERER_EXTENSION_PROFILE),
1912 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_HW_SOURCE),
1913 X(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
1914 X(MF_XVP_CALLER_ALLOCATES_OUTPUT),
1915 X(MF_MT_H264_SVC_CAPABILITIES),
1916 X(MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY),
1917 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_LENGTH),
1918 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_FORMAT_ID),
1919 X(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK),
1920 X(MF_SA_D3D11_SHARED),
1921 X(MF_MT_PAN_SCAN_ENABLED),
1922 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL),
1923 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID),
1924 X(MF_MT_DV_VAUX_CTRL_PACK),
1925 X(MFSampleExtension_ForwardedDecodeUnitType),
1926 X(MF_SA_D3D11_AWARE),
1927 X(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
1928 X(MF_SOURCE_READER_MEDIASOURCE_CHARACTERISTICS),
1929 X(MF_MT_SPATIAL_AUDIO_MIN_METADATA_ITEM_OFFSET_SPACING),
1930 X(MF_TOPONODE_TRANSFORM_OBJECTID),
1931 X(MF_DEVSOURCE_ATTRIBUTE_MEDIA_TYPE),
1932 X(MF_EVENT_MFT_INPUT_STREAM_ID),
1933 X(MF_MT_SOURCE_CONTENT_HINT),
1934 X(MFT_ENUM_HARDWARE_VENDOR_ID_Attribute),
1935 X(MFT_ENUM_TRANSCODE_ONLY_ATTRIBUTE),
1936 X(MF_READWRITE_MMCSS_PRIORITY),
1937 X(MF_MT_VIDEO_3D),
1938 X(MF_EVENT_START_PRESENTATION_TIME),
1939 X(MF_EVENT_SESSIONCAPS),
1940 X(MF_EVENT_PRESENTATION_TIME_OFFSET),
1941 X(MF_MEDIA_ENGINE_AUDIO_ENDPOINT_ROLE),
1942 X(MF_EVENT_SESSIONCAPS_DELTA),
1943 X(MF_EVENT_START_PRESENTATION_TIME_AT_OUTPUT),
1944 X(MFSampleExtension_DecodeTimestamp),
1945 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE),
1946 X(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT),
1947 X(MF_MT_VIDEO_H264_NO_FMOASO),
1948 X(MF_MT_AVG_BIT_ERROR_RATE),
1949 X(MF_MT_VIDEO_PRIMARIES),
1950 X(MF_SINK_WRITER_DISABLE_THROTTLING),
1951 X(MF_MT_H264_RATE_CONTROL_MODES),
1952 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK),
1953 X(MF_READWRITE_D3D_OPTIONAL),
1954 X(MF_SA_D3D11_HW_PROTECTED),
1955 X(MF_MEDIA_ENGINE_DXGI_MANAGER),
1956 X(MF_READWRITE_MMCSS_CLASS_AUDIO),
1957 X(MF_MEDIA_ENGINE_COREWINDOW),
1958 X(MF_SOURCE_READER_DISABLE_CAMERA_PLUGINS),
1959 X(MF_MT_MPEG4_TRACK_TYPE),
1960 X(MF_ACTIVATE_VIDEO_WINDOW),
1961 X(MF_MT_PAN_SCAN_APERTURE),
1962 X(MF_TOPOLOGY_RESOLUTION_STATUS),
1963 X(MF_MT_ORIGINAL_4CC),
1964 X(MF_PD_AUDIO_ISVARIABLEBITRATE),
1965 X(MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS),
1966 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE),
1967 X(MF_MT_D3D12_CPU_READBACK),
1968 X(MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID),
1969 X(MF_MT_MPEG2_CONTENT_PACKET),
1970 X(MFT_PROCESS_LOCAL_Attribute),
1971 X(MFT_PROCESS_LOCAL_Attribute),
1972 X(MF_MT_PAD_CONTROL_FLAGS),
1973 X(MF_MT_VIDEO_NOMINAL_RANGE),
1974 X(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
1975 X(MF_MT_MPEG_SEQUENCE_HEADER),
1976 X(MF_MEDIA_ENGINE_OPM_HWND),
1977 X(MF_MT_AUDIO_SAMPLES_PER_SECOND),
1978 X(MF_MT_SPATIAL_AUDIO_DATA_PRESENT),
1979 X(MF_MT_FRAME_RATE),
1980 X(MF_TOPONODE_FLUSH),
1981 X(MF_MT_MPEG2_STANDARD),
1982 X(MF_TOPONODE_DRAIN),
1983 X(MF_MT_TRANSFER_FUNCTION),
1984 X(MF_TOPONODE_MEDIASTART),
1985 X(MF_TOPONODE_MEDIASTOP),
1986 X(MF_SOURCE_READER_MEDIASOURCE_CONFIG),
1987 X(MF_TOPONODE_SOURCE),
1988 X(MF_TOPONODE_PRESENTATION_DESCRIPTOR),
1989 X(MF_TOPONODE_D3DAWARE),
1990 X(MF_MT_COMPRESSED),
1991 X(MF_TOPONODE_STREAM_DESCRIPTOR),
1992 X(MF_TOPONODE_ERRORCODE),
1993 X(MF_TOPONODE_SEQUENCE_ELEMENTID),
1994 X(MF_EVENT_MFT_CONTEXT),
1995 X(MF_MT_FORWARD_CUSTOM_SEI),
1996 X(MF_TOPONODE_CONNECT_METHOD),
1997 X(MFT_OUTPUT_TYPES_Attributes),
1998 X(MF_MT_IMAGE_LOSS_TOLERANT),
1999 X(MF_SESSION_REMOTE_SOURCE_MODE),
2000 X(MF_MT_DEPTH_VALUE_UNIT),
2001 X(MF_MT_AUDIO_NUM_CHANNELS),
2002 X(MF_MT_ARBITRARY_HEADER),
2003 X(MF_TOPOLOGY_DXVA_MODE),
2004 X(MF_TOPONODE_LOCKED),
2005 X(MF_TOPONODE_WORKQUEUE_ID),
2006 X(MF_MEDIA_ENGINE_CONTINUE_ON_CODEC_ERROR),
2007 X(MF_TOPONODE_WORKQUEUE_MMCSS_CLASS),
2008 X(MF_TOPONODE_DECRYPTOR),
2009 X(MF_EVENT_DO_THINNING),
2010 X(MF_TOPONODE_DISCARDABLE),
2011 X(MF_TOPOLOGY_HARDWARE_MODE),
2012 X(MF_SOURCE_READER_DISABLE_DXVA),
2013 X(MF_MT_FORWARD_CUSTOM_NALU),
2014 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE10),
2015 X(MF_TOPONODE_ERROR_MAJORTYPE),
2016 X(MF_MT_SECURE),
2017 X(MFT_FIELDOFUSE_UNLOCK_Attribute),
2018 X(MF_TOPONODE_ERROR_SUBTYPE),
2019 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE),
2020 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE),
2021 X(MF_MT_VIDEO_3D_LEFT_IS_BASE),
2022 X(MF_TOPONODE_WORKQUEUE_MMCSS_TASKID),
2023 #undef MF_READER_WRITER_D3D_MANAGER
2024 #undef X
2026 struct guid_def *ret = NULL;
2028 if (guid)
2029 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
2031 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
2034 const char *debugstr_mf_guid(const GUID *guid)
2036 static const struct guid_def guid_defs[] =
2038 #define X(g) { &(g), #g }
2039 X(MFAudioFormat_ADTS),
2040 X(MFAudioFormat_PCM),
2041 X(MFAudioFormat_PCM_HDCP),
2042 X(MFAudioFormat_Float),
2043 X(MFAudioFormat_DTS),
2044 X(MFAudioFormat_DRM),
2045 X(MFAudioFormat_MSP1),
2046 X(MFAudioFormat_Vorbis),
2047 X(MFAudioFormat_AAC),
2048 X(MFVideoFormat_RGB24),
2049 X(MFVideoFormat_ARGB32),
2050 X(MFVideoFormat_RGB32),
2051 X(MFVideoFormat_RGB565),
2052 X(MFVideoFormat_RGB555),
2053 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID),
2054 X(MFT_CATEGORY_MULTIPLEXER),
2055 X(MFVideoFormat_A2R10G10B10),
2056 X(MFT_CATEGORY_VIDEO_EFFECT),
2057 X(MFMediaType_Script),
2058 X(MFMediaType_Image),
2059 X(MFMediaType_HTML),
2060 X(MFMediaType_Binary),
2061 X(MFVideoFormat_MPEG2),
2062 X(MFMediaType_FileTransfer),
2063 X(MFVideoFormat_RGB8),
2064 X(MFAudioFormat_Dolby_AC3),
2065 X(MFVideoFormat_L8),
2066 X(MFAudioFormat_LPCM),
2067 X(MFVideoFormat_420O),
2068 X(MFVideoFormat_AI44),
2069 X(MFVideoFormat_AV1),
2070 X(MFVideoFormat_AYUV),
2071 X(MFVideoFormat_H263),
2072 X(MFVideoFormat_H264),
2073 X(MFVideoFormat_H265),
2074 X(MFVideoFormat_HEVC),
2075 X(MFVideoFormat_HEVC_ES),
2076 X(MFT_CATEGORY_AUDIO_EFFECT),
2077 X(MFVideoFormat_I420),
2078 X(MFVideoFormat_IYUV),
2079 X(MFT_CATEGORY_VIDEO_DECODER),
2080 X(MFVideoFormat_M4S2),
2081 X(MFVideoFormat_MJPG),
2082 X(MFVideoFormat_MP43),
2083 X(MFVideoFormat_MP4S),
2084 X(MFVideoFormat_MP4V),
2085 X(MFVideoFormat_MPG1),
2086 X(MFVideoFormat_MSS1),
2087 X(MFVideoFormat_MSS2),
2088 X(MFVideoFormat_NV11),
2089 X(MFVideoFormat_NV12),
2090 X(MFVideoFormat_ORAW),
2091 X(MFAudioFormat_Opus),
2092 X(MFAudioFormat_MPEG),
2093 X(MFVideoFormat_D16),
2094 X(MFVideoFormat_P010),
2095 X(MFVideoFormat_P016),
2096 X(MFVideoFormat_P210),
2097 X(MFVideoFormat_P216),
2098 X(MFVideoFormat_L16),
2099 X(MFAudioFormat_MP3),
2100 X(MFVideoFormat_UYVY),
2101 X(MFVideoFormat_VP10),
2102 X(MFVideoFormat_VP80),
2103 X(MFVideoFormat_VP90),
2104 X(MFVideoFormat_WMV1),
2105 X(MFVideoFormat_WMV2),
2106 X(MFVideoFormat_WMV3),
2107 X(MFVideoFormat_WVC1),
2108 X(MFT_CATEGORY_OTHER),
2109 X(MFVideoFormat_Y210),
2110 X(MFVideoFormat_Y216),
2111 X(MFVideoFormat_Y410),
2112 X(MFVideoFormat_Y416),
2113 X(MFVideoFormat_Y41P),
2114 X(MFVideoFormat_Y41T),
2115 X(MFVideoFormat_Y42T),
2116 X(MFVideoFormat_YUY2),
2117 X(MFVideoFormat_YV12),
2118 X(MFVideoFormat_YVU9),
2119 X(MFVideoFormat_YVYU),
2120 X(MFAudioFormat_WMAudioV8),
2121 X(MFAudioFormat_ALAC),
2122 X(MFAudioFormat_AMR_NB),
2123 X(MFMediaType_Audio),
2124 X(MFAudioFormat_WMAudioV9),
2125 X(MFAudioFormat_AMR_WB),
2126 X(MFAudioFormat_WMAudio_Lossless),
2127 X(MFAudioFormat_AMR_WP),
2128 X(MFAudioFormat_WMASPDIF),
2129 X(MFVideoFormat_DV25),
2130 X(MFVideoFormat_DV50),
2131 X(MFVideoFormat_DVC),
2132 X(MFVideoFormat_DVH1),
2133 X(MFVideoFormat_DVHD),
2134 X(MFVideoFormat_DVSD),
2135 X(MFVideoFormat_DVSL),
2136 X(MFVideoFormat_A16B16G16R16F),
2137 X(MFVideoFormat_v210),
2138 X(MFVideoFormat_v216),
2139 X(MFVideoFormat_v410),
2140 X(MFMediaType_Video),
2141 X(MFAudioFormat_AAC_HDCP),
2142 X(MFT_CATEGORY_DEMULTIPLEXER),
2143 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID),
2144 X(MFT_CATEGORY_VIDEO_ENCODER),
2145 X(MFAudioFormat_Dolby_AC3_HDCP),
2146 X(MFMediaType_Subtitle),
2147 X(MFMediaType_Stream),
2148 X(MFAudioFormat_Dolby_AC3_SPDIF),
2149 X(MFAudioFormat_Float_SpatialObjects),
2150 X(MFMediaType_SAMI),
2151 X(MFAudioFormat_ADTS_HDCP),
2152 X(MFAudioFormat_FLAC),
2153 X(MFAudioFormat_Dolby_DDPlus),
2154 X(MFMediaType_MultiplexedFrames),
2155 X(MFT_CATEGORY_AUDIO_DECODER),
2156 X(MFAudioFormat_Base_HDCP),
2157 X(MFT_CATEGORY_AUDIO_ENCODER),
2158 X(MFVideoFormat_Base_HDCP),
2159 X(MFVideoFormat_H264_HDCP),
2160 X(MFVideoFormat_HEVC_HDCP),
2161 X(MFMediaType_Default),
2162 X(MFMediaType_Protected),
2163 X(MFVideoFormat_H264_ES),
2164 X(MFMediaType_Perception),
2165 X(MFT_CATEGORY_VIDEO_PROCESSOR),
2166 #undef X
2168 struct guid_def *ret = NULL;
2170 if (guid)
2171 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
2173 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
2176 struct event_id
2178 DWORD id;
2179 const char *name;
2182 static int __cdecl debug_event_id(const void *a, const void *b)
2184 const DWORD *id = a;
2185 const struct event_id *event_id = b;
2186 return *id - event_id->id;
2189 static const char *debugstr_eventid(DWORD event)
2191 static const struct event_id
2193 DWORD id;
2194 const char *name;
2196 event_ids[] =
2198 #define X(e) { e, #e }
2199 X(MEUnknown),
2200 X(MEError),
2201 X(MEExtendedType),
2202 X(MENonFatalError),
2203 X(MESessionUnknown),
2204 X(MESessionTopologySet),
2205 X(MESessionTopologiesCleared),
2206 X(MESessionStarted),
2207 X(MESessionPaused),
2208 X(MESessionStopped),
2209 X(MESessionClosed),
2210 X(MESessionEnded),
2211 X(MESessionRateChanged),
2212 X(MESessionScrubSampleComplete),
2213 X(MESessionCapabilitiesChanged),
2214 X(MESessionTopologyStatus),
2215 X(MESessionNotifyPresentationTime),
2216 X(MENewPresentation),
2217 X(MELicenseAcquisitionStart),
2218 X(MELicenseAcquisitionCompleted),
2219 X(MEIndividualizationStart),
2220 X(MEIndividualizationCompleted),
2221 X(MEEnablerProgress),
2222 X(MEEnablerCompleted),
2223 X(MEPolicyError),
2224 X(MEPolicyReport),
2225 X(MEBufferingStarted),
2226 X(MEBufferingStopped),
2227 X(MEConnectStart),
2228 X(MEConnectEnd),
2229 X(MEReconnectStart),
2230 X(MEReconnectEnd),
2231 X(MERendererEvent),
2232 X(MESessionStreamSinkFormatChanged),
2233 X(MESourceUnknown),
2234 X(MESourceStarted),
2235 X(MEStreamStarted),
2236 X(MESourceSeeked),
2237 X(MEStreamSeeked),
2238 X(MENewStream),
2239 X(MEUpdatedStream),
2240 X(MESourceStopped),
2241 X(MEStreamStopped),
2242 X(MESourcePaused),
2243 X(MEStreamPaused),
2244 X(MEEndOfPresentation),
2245 X(MEEndOfStream),
2246 X(MEMediaSample),
2247 X(MEStreamTick),
2248 X(MEStreamThinMode),
2249 X(MEStreamFormatChanged),
2250 X(MESourceRateChanged),
2251 X(MEEndOfPresentationSegment),
2252 X(MESourceCharacteristicsChanged),
2253 X(MESourceRateChangeRequested),
2254 X(MESourceMetadataChanged),
2255 X(MESequencerSourceTopologyUpdated),
2256 X(MESinkUnknown),
2257 X(MEStreamSinkStarted),
2258 X(MEStreamSinkStopped),
2259 X(MEStreamSinkPaused),
2260 X(MEStreamSinkRateChanged),
2261 X(MEStreamSinkRequestSample),
2262 X(MEStreamSinkMarker),
2263 X(MEStreamSinkPrerolled),
2264 X(MEStreamSinkScrubSampleComplete),
2265 X(MEStreamSinkFormatChanged),
2266 X(MEStreamSinkDeviceChanged),
2267 X(MEQualityNotify),
2268 X(MESinkInvalidated),
2269 X(MEAudioSessionNameChanged),
2270 X(MEAudioSessionVolumeChanged),
2271 X(MEAudioSessionDeviceRemoved),
2272 X(MEAudioSessionServerShutdown),
2273 X(MEAudioSessionGroupingParamChanged),
2274 X(MEAudioSessionIconChanged),
2275 X(MEAudioSessionFormatChanged),
2276 X(MEAudioSessionDisconnected),
2277 X(MEAudioSessionExclusiveModeOverride),
2278 X(MECaptureAudioSessionVolumeChanged),
2279 X(MECaptureAudioSessionDeviceRemoved),
2280 X(MECaptureAudioSessionFormatChanged),
2281 X(MECaptureAudioSessionDisconnected),
2282 X(MECaptureAudioSessionExclusiveModeOverride),
2283 X(MECaptureAudioSessionServerShutdown),
2284 X(METrustUnknown),
2285 X(MEPolicyChanged),
2286 X(MEContentProtectionMessage),
2287 X(MEPolicySet),
2288 X(MEWMDRMLicenseBackupCompleted),
2289 X(MEWMDRMLicenseBackupProgress),
2290 X(MEWMDRMLicenseRestoreCompleted),
2291 X(MEWMDRMLicenseRestoreProgress),
2292 X(MEWMDRMLicenseAcquisitionCompleted),
2293 X(MEWMDRMIndividualizationCompleted),
2294 X(MEWMDRMIndividualizationProgress),
2295 X(MEWMDRMProximityCompleted),
2296 X(MEWMDRMLicenseStoreCleaned),
2297 X(MEWMDRMRevocationDownloadCompleted),
2298 X(METransformUnknown),
2299 X(METransformNeedInput),
2300 X(METransformHaveOutput),
2301 X(METransformDrainComplete),
2302 X(METransformMarker),
2303 X(METransformInputStreamStateChanged),
2304 X(MEByteStreamCharacteristicsChanged),
2305 X(MEVideoCaptureDeviceRemoved),
2306 X(MEVideoCaptureDevicePreempted),
2307 X(MEStreamSinkFormatInvalidated),
2308 X(MEEncodingParameters),
2309 X(MEContentProtectionMetadata),
2310 X(MEDeviceThermalStateChanged),
2311 #undef X
2314 struct event_id *ret = bsearch(&event, event_ids, ARRAY_SIZE(event_ids), sizeof(*event_ids), debug_event_id);
2315 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbg_sprintf("%lu", event);
2318 static inline struct attributes *impl_from_IMFAttributes(IMFAttributes *iface)
2320 return CONTAINING_RECORD(iface, struct attributes, IMFAttributes_iface);
2323 static HRESULT WINAPI mfattributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
2325 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
2327 if (IsEqualIID(riid, &IID_IMFAttributes) ||
2328 IsEqualGUID(riid, &IID_IUnknown))
2330 *out = iface;
2331 IMFAttributes_AddRef(iface);
2332 return S_OK;
2335 WARN("Unsupported %s.\n", debugstr_guid(riid));
2336 *out = NULL;
2337 return E_NOINTERFACE;
2340 static ULONG WINAPI mfattributes_AddRef(IMFAttributes *iface)
2342 struct attributes *attributes = impl_from_IMFAttributes(iface);
2343 ULONG refcount = InterlockedIncrement(&attributes->ref);
2345 TRACE("%p, refcount %ld.\n", iface, refcount);
2347 return refcount;
2350 static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
2352 struct attributes *attributes = impl_from_IMFAttributes(iface);
2353 ULONG refcount = InterlockedDecrement(&attributes->ref);
2355 TRACE("%p, refcount %ld.\n", iface, refcount);
2357 if (!refcount)
2359 clear_attributes_object(attributes);
2360 free(attributes);
2363 return refcount;
2366 static struct attribute *attributes_find_item(struct attributes *attributes, REFGUID key, size_t *index)
2368 size_t i;
2370 for (i = 0; i < attributes->count; ++i)
2372 if (IsEqualGUID(key, &attributes->attributes[i].key))
2374 if (index)
2375 *index = i;
2376 return &attributes->attributes[i];
2380 return NULL;
2383 static HRESULT attributes_get_item(struct attributes *attributes, const GUID *key, PROPVARIANT *value)
2385 struct attribute *attribute;
2386 HRESULT hr;
2388 EnterCriticalSection(&attributes->cs);
2390 attribute = attributes_find_item(attributes, key, NULL);
2391 if (attribute)
2393 if (attribute->value.vt == value->vt && !(value->vt == VT_UNKNOWN && !attribute->value.punkVal))
2394 hr = PropVariantCopy(value, &attribute->value);
2395 else
2396 hr = MF_E_INVALIDTYPE;
2398 else
2399 hr = MF_E_ATTRIBUTENOTFOUND;
2401 LeaveCriticalSection(&attributes->cs);
2403 return hr;
2406 HRESULT attributes_GetItem(struct attributes *attributes, REFGUID key, PROPVARIANT *value)
2408 struct attribute *attribute;
2409 HRESULT hr;
2411 EnterCriticalSection(&attributes->cs);
2413 if ((attribute = attributes_find_item(attributes, key, NULL)))
2414 hr = value ? PropVariantCopy(value, &attribute->value) : S_OK;
2415 else
2416 hr = MF_E_ATTRIBUTENOTFOUND;
2418 LeaveCriticalSection(&attributes->cs);
2420 return hr;
2423 HRESULT attributes_GetItemType(struct attributes *attributes, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2425 struct attribute *attribute;
2426 HRESULT hr = S_OK;
2428 EnterCriticalSection(&attributes->cs);
2430 if ((attribute = attributes_find_item(attributes, key, NULL)))
2432 *type = attribute->value.vt;
2434 else
2435 hr = MF_E_ATTRIBUTENOTFOUND;
2437 LeaveCriticalSection(&attributes->cs);
2439 return hr;
2442 HRESULT attributes_CompareItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value, BOOL *result)
2444 struct attribute *attribute;
2446 *result = FALSE;
2448 EnterCriticalSection(&attributes->cs);
2450 if ((attribute = attributes_find_item(attributes, key, NULL)))
2452 *result = attribute->value.vt == value->vt &&
2453 !PropVariantCompareEx(&attribute->value, value, PVCU_DEFAULT, PVCF_DEFAULT);
2456 LeaveCriticalSection(&attributes->cs);
2458 return S_OK;
2461 HRESULT attributes_Compare(struct attributes *attributes, IMFAttributes *theirs,
2462 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2464 IMFAttributes *smaller, *other;
2465 MF_ATTRIBUTE_TYPE type;
2466 HRESULT hr = S_OK;
2467 UINT32 count;
2468 BOOL result;
2469 size_t i;
2471 if (FAILED(hr = IMFAttributes_GetCount(theirs, &count)))
2472 return hr;
2474 EnterCriticalSection(&attributes->cs);
2476 result = TRUE;
2478 switch (match_type)
2480 case MF_ATTRIBUTES_MATCH_OUR_ITEMS:
2481 for (i = 0; i < attributes->count; ++i)
2483 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2484 &attributes->attributes[i].value, &result)))
2485 break;
2486 if (!result)
2487 break;
2489 break;
2490 case MF_ATTRIBUTES_MATCH_THEIR_ITEMS:
2491 hr = IMFAttributes_Compare(theirs, &attributes->IMFAttributes_iface, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2492 break;
2493 case MF_ATTRIBUTES_MATCH_ALL_ITEMS:
2494 if (count != attributes->count)
2496 result = FALSE;
2497 break;
2499 for (i = 0; i < count; ++i)
2501 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2502 &attributes->attributes[i].value, &result)))
2503 break;
2504 if (!result)
2505 break;
2507 break;
2508 case MF_ATTRIBUTES_MATCH_INTERSECTION:
2509 for (i = 0; i < attributes->count; ++i)
2511 if (FAILED(IMFAttributes_GetItemType(theirs, &attributes->attributes[i].key, &type)))
2512 continue;
2514 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2515 &attributes->attributes[i].value, &result)))
2516 break;
2518 if (!result)
2519 break;
2521 break;
2522 case MF_ATTRIBUTES_MATCH_SMALLER:
2523 smaller = attributes->count > count ? theirs : &attributes->IMFAttributes_iface;
2524 other = attributes->count > count ? &attributes->IMFAttributes_iface : theirs;
2525 hr = IMFAttributes_Compare(smaller, other, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2526 break;
2527 default:
2528 WARN("Unknown match type %d.\n", match_type);
2529 hr = E_INVALIDARG;
2532 LeaveCriticalSection(&attributes->cs);
2534 if (SUCCEEDED(hr))
2535 *ret = result;
2537 return hr;
2540 HRESULT attributes_GetUINT32(struct attributes *attributes, REFGUID key, UINT32 *value)
2542 PROPVARIANT attrval;
2543 HRESULT hr;
2545 PropVariantInit(&attrval);
2546 attrval.vt = VT_UI4;
2547 hr = attributes_get_item(attributes, key, &attrval);
2548 if (SUCCEEDED(hr))
2549 *value = attrval.ulVal;
2551 return hr;
2554 HRESULT attributes_GetUINT64(struct attributes *attributes, REFGUID key, UINT64 *value)
2556 PROPVARIANT attrval;
2557 HRESULT hr;
2559 PropVariantInit(&attrval);
2560 attrval.vt = VT_UI8;
2561 hr = attributes_get_item(attributes, key, &attrval);
2562 if (SUCCEEDED(hr))
2563 *value = attrval.uhVal.QuadPart;
2565 return hr;
2568 HRESULT attributes_GetDouble(struct attributes *attributes, REFGUID key, double *value)
2570 PROPVARIANT attrval;
2571 HRESULT hr;
2573 PropVariantInit(&attrval);
2574 attrval.vt = VT_R8;
2575 hr = attributes_get_item(attributes, key, &attrval);
2576 if (SUCCEEDED(hr))
2577 *value = attrval.dblVal;
2579 return hr;
2582 HRESULT attributes_GetGUID(struct attributes *attributes, REFGUID key, GUID *value)
2584 struct attribute *attribute;
2585 HRESULT hr = S_OK;
2587 EnterCriticalSection(&attributes->cs);
2589 attribute = attributes_find_item(attributes, key, NULL);
2590 if (attribute)
2592 if (attribute->value.vt == MF_ATTRIBUTE_GUID)
2593 *value = *attribute->value.puuid;
2594 else
2595 hr = MF_E_INVALIDTYPE;
2597 else
2598 hr = MF_E_ATTRIBUTENOTFOUND;
2600 LeaveCriticalSection(&attributes->cs);
2602 return hr;
2605 HRESULT attributes_GetStringLength(struct attributes *attributes, REFGUID key, UINT32 *length)
2607 struct attribute *attribute;
2608 HRESULT hr = S_OK;
2610 EnterCriticalSection(&attributes->cs);
2612 attribute = attributes_find_item(attributes, key, NULL);
2613 if (attribute)
2615 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2616 *length = lstrlenW(attribute->value.pwszVal);
2617 else
2618 hr = MF_E_INVALIDTYPE;
2620 else
2621 hr = MF_E_ATTRIBUTENOTFOUND;
2623 LeaveCriticalSection(&attributes->cs);
2625 return hr;
2628 HRESULT attributes_GetString(struct attributes *attributes, REFGUID key, WCHAR *value,
2629 UINT32 size, UINT32 *length)
2631 struct attribute *attribute;
2632 HRESULT hr = S_OK;
2634 EnterCriticalSection(&attributes->cs);
2636 attribute = attributes_find_item(attributes, key, NULL);
2637 if (attribute)
2639 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2641 int len = lstrlenW(attribute->value.pwszVal);
2643 if (length)
2644 *length = len;
2646 if (size <= len)
2647 hr = STRSAFE_E_INSUFFICIENT_BUFFER;
2648 else
2649 memcpy(value, attribute->value.pwszVal, (len + 1) * sizeof(WCHAR));
2651 else
2652 hr = MF_E_INVALIDTYPE;
2654 else
2655 hr = MF_E_ATTRIBUTENOTFOUND;
2657 LeaveCriticalSection(&attributes->cs);
2659 return hr;
2662 HRESULT attributes_GetAllocatedString(struct attributes *attributes, REFGUID key, WCHAR **value, UINT32 *length)
2664 PROPVARIANT attrval;
2665 HRESULT hr;
2667 PropVariantInit(&attrval);
2668 attrval.vt = VT_LPWSTR;
2669 hr = attributes_get_item(attributes, key, &attrval);
2670 if (SUCCEEDED(hr))
2672 *value = attrval.pwszVal;
2673 *length = lstrlenW(*value);
2676 return hr;
2679 HRESULT attributes_GetBlobSize(struct attributes *attributes, REFGUID key, UINT32 *size)
2681 struct attribute *attribute;
2682 HRESULT hr = S_OK;
2684 EnterCriticalSection(&attributes->cs);
2686 attribute = attributes_find_item(attributes, key, NULL);
2687 if (attribute)
2689 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2690 *size = attribute->value.caub.cElems;
2691 else
2692 hr = MF_E_INVALIDTYPE;
2694 else
2695 hr = MF_E_ATTRIBUTENOTFOUND;
2697 LeaveCriticalSection(&attributes->cs);
2699 return hr;
2702 HRESULT attributes_GetBlob(struct attributes *attributes, REFGUID key, UINT8 *buf, UINT32 bufsize, UINT32 *blobsize)
2704 struct attribute *attribute;
2705 HRESULT hr;
2707 EnterCriticalSection(&attributes->cs);
2709 attribute = attributes_find_item(attributes, key, NULL);
2710 if (attribute)
2712 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2714 UINT32 size = attribute->value.caub.cElems;
2716 if (bufsize >= size)
2717 hr = PropVariantToBuffer(&attribute->value, buf, size);
2718 else
2719 hr = E_NOT_SUFFICIENT_BUFFER;
2721 if (blobsize)
2722 *blobsize = size;
2724 else
2725 hr = MF_E_INVALIDTYPE;
2727 else
2728 hr = MF_E_ATTRIBUTENOTFOUND;
2730 LeaveCriticalSection(&attributes->cs);
2732 return hr;
2735 HRESULT attributes_GetAllocatedBlob(struct attributes *attributes, REFGUID key, UINT8 **buf, UINT32 *size)
2737 PROPVARIANT attrval;
2738 HRESULT hr;
2740 attrval.vt = VT_VECTOR | VT_UI1;
2741 hr = attributes_get_item(attributes, key, &attrval);
2742 if (SUCCEEDED(hr))
2744 *buf = attrval.caub.pElems;
2745 *size = attrval.caub.cElems;
2748 return hr;
2751 HRESULT attributes_GetUnknown(struct attributes *attributes, REFGUID key, REFIID riid, void **out)
2753 PROPVARIANT attrval;
2754 HRESULT hr;
2756 PropVariantInit(&attrval);
2757 attrval.vt = VT_UNKNOWN;
2758 hr = attributes_get_item(attributes, key, &attrval);
2759 if (SUCCEEDED(hr))
2760 hr = IUnknown_QueryInterface(attrval.punkVal, riid, out);
2761 PropVariantClear(&attrval);
2762 return hr;
2765 static HRESULT attributes_set_item(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2767 struct attribute *attribute;
2769 EnterCriticalSection(&attributes->cs);
2771 attribute = attributes_find_item(attributes, key, NULL);
2772 if (!attribute)
2774 if (!mf_array_reserve((void **)&attributes->attributes, &attributes->capacity, attributes->count + 1,
2775 sizeof(*attributes->attributes)))
2777 LeaveCriticalSection(&attributes->cs);
2778 return E_OUTOFMEMORY;
2780 attributes->attributes[attributes->count].key = *key;
2781 attribute = &attributes->attributes[attributes->count++];
2783 else
2784 PropVariantClear(&attribute->value);
2786 PropVariantCopy(&attribute->value, value);
2788 LeaveCriticalSection(&attributes->cs);
2790 return S_OK;
2793 HRESULT attributes_SetItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2795 PROPVARIANT empty;
2797 switch (value->vt)
2799 case MF_ATTRIBUTE_UINT32:
2800 case MF_ATTRIBUTE_UINT64:
2801 case MF_ATTRIBUTE_DOUBLE:
2802 case MF_ATTRIBUTE_GUID:
2803 case MF_ATTRIBUTE_STRING:
2804 case MF_ATTRIBUTE_BLOB:
2805 case MF_ATTRIBUTE_IUNKNOWN:
2806 return attributes_set_item(attributes, key, value);
2807 default:
2808 PropVariantInit(&empty);
2809 attributes_set_item(attributes, key, &empty);
2810 return MF_E_INVALIDTYPE;
2814 HRESULT attributes_DeleteItem(struct attributes *attributes, REFGUID key)
2816 struct attribute *attribute;
2817 size_t index = 0;
2819 EnterCriticalSection(&attributes->cs);
2821 if ((attribute = attributes_find_item(attributes, key, &index)))
2823 size_t count;
2825 PropVariantClear(&attribute->value);
2827 attributes->count--;
2828 count = attributes->count - index;
2829 if (count)
2830 memmove(&attributes->attributes[index], &attributes->attributes[index + 1], count * sizeof(*attributes->attributes));
2833 LeaveCriticalSection(&attributes->cs);
2835 return S_OK;
2838 HRESULT attributes_DeleteAllItems(struct attributes *attributes)
2840 EnterCriticalSection(&attributes->cs);
2842 while (attributes->count)
2844 PropVariantClear(&attributes->attributes[--attributes->count].value);
2846 free(attributes->attributes);
2847 attributes->attributes = NULL;
2848 attributes->capacity = 0;
2850 LeaveCriticalSection(&attributes->cs);
2852 return S_OK;
2855 HRESULT attributes_SetUINT32(struct attributes *attributes, REFGUID key, UINT32 value)
2857 PROPVARIANT attrval;
2859 attrval.vt = VT_UI4;
2860 attrval.ulVal = value;
2861 return attributes_set_item(attributes, key, &attrval);
2864 HRESULT attributes_SetUINT64(struct attributes *attributes, REFGUID key, UINT64 value)
2866 PROPVARIANT attrval;
2868 attrval.vt = VT_UI8;
2869 attrval.uhVal.QuadPart = value;
2870 return attributes_set_item(attributes, key, &attrval);
2873 HRESULT attributes_SetDouble(struct attributes *attributes, REFGUID key, double value)
2875 PROPVARIANT attrval;
2877 attrval.vt = VT_R8;
2878 attrval.dblVal = value;
2879 return attributes_set_item(attributes, key, &attrval);
2882 HRESULT attributes_SetGUID(struct attributes *attributes, REFGUID key, REFGUID value)
2884 PROPVARIANT attrval;
2886 attrval.vt = VT_CLSID;
2887 attrval.puuid = (CLSID *)value;
2888 return attributes_set_item(attributes, key, &attrval);
2891 HRESULT attributes_SetString(struct attributes *attributes, REFGUID key, const WCHAR *value)
2893 PROPVARIANT attrval;
2895 attrval.vt = VT_LPWSTR;
2896 attrval.pwszVal = (WCHAR *)value;
2897 return attributes_set_item(attributes, key, &attrval);
2900 HRESULT attributes_SetBlob(struct attributes *attributes, REFGUID key, const UINT8 *buf, UINT32 size)
2902 PROPVARIANT attrval;
2904 attrval.vt = VT_VECTOR | VT_UI1;
2905 attrval.caub.cElems = size;
2906 attrval.caub.pElems = (UINT8 *)buf;
2907 return attributes_set_item(attributes, key, &attrval);
2910 HRESULT attributes_SetUnknown(struct attributes *attributes, REFGUID key, IUnknown *unknown)
2912 PROPVARIANT attrval;
2914 attrval.vt = VT_UNKNOWN;
2915 attrval.punkVal = unknown;
2916 return attributes_set_item(attributes, key, &attrval);
2919 HRESULT attributes_LockStore(struct attributes *attributes)
2921 EnterCriticalSection(&attributes->cs);
2923 return S_OK;
2926 HRESULT attributes_UnlockStore(struct attributes *attributes)
2928 LeaveCriticalSection(&attributes->cs);
2930 return S_OK;
2933 HRESULT attributes_GetCount(struct attributes *attributes, UINT32 *count)
2935 EnterCriticalSection(&attributes->cs);
2936 *count = attributes->count;
2937 LeaveCriticalSection(&attributes->cs);
2939 return S_OK;
2942 HRESULT attributes_GetItemByIndex(struct attributes *attributes, UINT32 index, GUID *key, PROPVARIANT *value)
2944 HRESULT hr = S_OK;
2946 EnterCriticalSection(&attributes->cs);
2948 if (index < attributes->count)
2950 *key = attributes->attributes[index].key;
2951 if (value)
2952 PropVariantCopy(value, &attributes->attributes[index].value);
2954 else
2955 hr = E_INVALIDARG;
2957 LeaveCriticalSection(&attributes->cs);
2959 return hr;
2962 HRESULT attributes_CopyAllItems(struct attributes *attributes, IMFAttributes *dest)
2964 HRESULT hr = S_OK;
2965 size_t i;
2967 EnterCriticalSection(&attributes->cs);
2969 IMFAttributes_LockStore(dest);
2971 IMFAttributes_DeleteAllItems(dest);
2973 for (i = 0; i < attributes->count; ++i)
2975 hr = IMFAttributes_SetItem(dest, &attributes->attributes[i].key, &attributes->attributes[i].value);
2976 if (FAILED(hr))
2977 break;
2980 IMFAttributes_UnlockStore(dest);
2982 LeaveCriticalSection(&attributes->cs);
2984 return hr;
2987 static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
2989 struct attributes *attributes = impl_from_IMFAttributes(iface);
2991 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2993 return attributes_GetItem(attributes, key, value);
2996 static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2998 struct attributes *attributes = impl_from_IMFAttributes(iface);
3000 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
3002 return attributes_GetItemType(attributes, key, type);
3005 static HRESULT WINAPI mfattributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
3007 struct attributes *attributes = impl_from_IMFAttributes(iface);
3009 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
3011 return attributes_CompareItem(attributes, key, value, result);
3014 static HRESULT WINAPI mfattributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
3015 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
3017 struct attributes *attributes = impl_from_IMFAttributes(iface);
3019 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
3021 return attributes_Compare(attributes, theirs, match_type, ret);
3024 static HRESULT WINAPI mfattributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
3026 struct attributes *attributes = impl_from_IMFAttributes(iface);
3028 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3030 return attributes_GetUINT32(attributes, key, value);
3033 static HRESULT WINAPI mfattributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
3035 struct attributes *attributes = impl_from_IMFAttributes(iface);
3037 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3039 return attributes_GetUINT64(attributes, key, value);
3042 static HRESULT WINAPI mfattributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
3044 struct attributes *attributes = impl_from_IMFAttributes(iface);
3046 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3048 return attributes_GetDouble(attributes, key, value);
3051 static HRESULT WINAPI mfattributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
3053 struct attributes *attributes = impl_from_IMFAttributes(iface);
3055 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3057 return attributes_GetGUID(attributes, key, value);
3060 static HRESULT WINAPI mfattributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
3062 struct attributes *attributes = impl_from_IMFAttributes(iface);
3064 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
3066 return attributes_GetStringLength(attributes, key, length);
3069 static HRESULT WINAPI mfattributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
3070 UINT32 size, UINT32 *length)
3072 struct attributes *attributes = impl_from_IMFAttributes(iface);
3074 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
3076 return attributes_GetString(attributes, key, value, size, length);
3079 static HRESULT WINAPI mfattributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
3081 struct attributes *attributes = impl_from_IMFAttributes(iface);
3083 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
3085 return attributes_GetAllocatedString(attributes, key, value, length);
3088 static HRESULT WINAPI mfattributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
3090 struct attributes *attributes = impl_from_IMFAttributes(iface);
3092 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
3094 return attributes_GetBlobSize(attributes, key, size);
3097 static HRESULT WINAPI mfattributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
3098 UINT32 bufsize, UINT32 *blobsize)
3100 struct attributes *attributes = impl_from_IMFAttributes(iface);
3102 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
3104 return attributes_GetBlob(attributes, key, buf, bufsize, blobsize);
3107 static HRESULT WINAPI mfattributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
3109 struct attributes *attributes = impl_from_IMFAttributes(iface);
3111 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
3113 return attributes_GetAllocatedBlob(attributes, key, buf, size);
3116 static HRESULT WINAPI mfattributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
3118 struct attributes *attributes = impl_from_IMFAttributes(iface);
3120 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
3122 return attributes_GetUnknown(attributes, key, riid, out);
3125 static HRESULT WINAPI mfattributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
3127 struct attributes *attributes = impl_from_IMFAttributes(iface);
3129 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
3131 return attributes_SetItem(attributes, key, value);
3134 static HRESULT WINAPI mfattributes_DeleteItem(IMFAttributes *iface, REFGUID key)
3136 struct attributes *attributes = impl_from_IMFAttributes(iface);
3138 TRACE("%p, %s.\n", iface, debugstr_attr(key));
3140 return attributes_DeleteItem(attributes, key);
3143 static HRESULT WINAPI mfattributes_DeleteAllItems(IMFAttributes *iface)
3145 struct attributes *attributes = impl_from_IMFAttributes(iface);
3147 TRACE("%p.\n", iface);
3149 return attributes_DeleteAllItems(attributes);
3152 static HRESULT WINAPI mfattributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
3154 struct attributes *attributes = impl_from_IMFAttributes(iface);
3156 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
3158 return attributes_SetUINT32(attributes, key, value);
3161 static HRESULT WINAPI mfattributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
3163 struct attributes *attributes = impl_from_IMFAttributes(iface);
3165 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
3167 return attributes_SetUINT64(attributes, key, value);
3170 static HRESULT WINAPI mfattributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
3172 struct attributes *attributes = impl_from_IMFAttributes(iface);
3174 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
3176 return attributes_SetDouble(attributes, key, value);
3179 static HRESULT WINAPI mfattributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
3181 struct attributes *attributes = impl_from_IMFAttributes(iface);
3183 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
3185 return attributes_SetGUID(attributes, key, value);
3188 static HRESULT WINAPI mfattributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
3190 struct attributes *attributes = impl_from_IMFAttributes(iface);
3192 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
3194 return attributes_SetString(attributes, key, value);
3197 static HRESULT WINAPI mfattributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
3199 struct attributes *attributes = impl_from_IMFAttributes(iface);
3201 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
3203 return attributes_SetBlob(attributes, key, buf, size);
3206 static HRESULT WINAPI mfattributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
3208 struct attributes *attributes = impl_from_IMFAttributes(iface);
3210 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
3212 return attributes_SetUnknown(attributes, key, unknown);
3215 static HRESULT WINAPI mfattributes_LockStore(IMFAttributes *iface)
3217 struct attributes *attributes = impl_from_IMFAttributes(iface);
3219 TRACE("%p.\n", iface);
3221 return attributes_LockStore(attributes);
3224 static HRESULT WINAPI mfattributes_UnlockStore(IMFAttributes *iface)
3226 struct attributes *attributes = impl_from_IMFAttributes(iface);
3228 TRACE("%p.\n", iface);
3230 return attributes_UnlockStore(attributes);
3233 static HRESULT WINAPI mfattributes_GetCount(IMFAttributes *iface, UINT32 *count)
3235 struct attributes *attributes = impl_from_IMFAttributes(iface);
3237 TRACE("%p, %p.\n", iface, count);
3239 return attributes_GetCount(attributes, count);
3242 static HRESULT WINAPI mfattributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
3244 struct attributes *attributes = impl_from_IMFAttributes(iface);
3246 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
3248 return attributes_GetItemByIndex(attributes, index, key, value);
3251 static HRESULT WINAPI mfattributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
3253 struct attributes *attributes = impl_from_IMFAttributes(iface);
3255 TRACE("%p, %p.\n", iface, dest);
3257 return attributes_CopyAllItems(attributes, dest);
3260 static const IMFAttributesVtbl mfattributes_vtbl =
3262 mfattributes_QueryInterface,
3263 mfattributes_AddRef,
3264 mfattributes_Release,
3265 mfattributes_GetItem,
3266 mfattributes_GetItemType,
3267 mfattributes_CompareItem,
3268 mfattributes_Compare,
3269 mfattributes_GetUINT32,
3270 mfattributes_GetUINT64,
3271 mfattributes_GetDouble,
3272 mfattributes_GetGUID,
3273 mfattributes_GetStringLength,
3274 mfattributes_GetString,
3275 mfattributes_GetAllocatedString,
3276 mfattributes_GetBlobSize,
3277 mfattributes_GetBlob,
3278 mfattributes_GetAllocatedBlob,
3279 mfattributes_GetUnknown,
3280 mfattributes_SetItem,
3281 mfattributes_DeleteItem,
3282 mfattributes_DeleteAllItems,
3283 mfattributes_SetUINT32,
3284 mfattributes_SetUINT64,
3285 mfattributes_SetDouble,
3286 mfattributes_SetGUID,
3287 mfattributes_SetString,
3288 mfattributes_SetBlob,
3289 mfattributes_SetUnknown,
3290 mfattributes_LockStore,
3291 mfattributes_UnlockStore,
3292 mfattributes_GetCount,
3293 mfattributes_GetItemByIndex,
3294 mfattributes_CopyAllItems
3297 HRESULT init_attributes_object(struct attributes *object, UINT32 size)
3299 object->IMFAttributes_iface.lpVtbl = &mfattributes_vtbl;
3300 object->ref = 1;
3301 InitializeCriticalSection(&object->cs);
3303 object->attributes = NULL;
3304 object->count = 0;
3305 object->capacity = 0;
3306 if (!mf_array_reserve((void **)&object->attributes, &object->capacity, size,
3307 sizeof(*object->attributes)))
3309 DeleteCriticalSection(&object->cs);
3310 return E_OUTOFMEMORY;
3313 return S_OK;
3316 void clear_attributes_object(struct attributes *object)
3318 size_t i;
3320 for (i = 0; i < object->count; i++)
3321 PropVariantClear(&object->attributes[i].value);
3322 free(object->attributes);
3324 DeleteCriticalSection(&object->cs);
3327 /***********************************************************************
3328 * MFCreateAttributes (mfplat.@)
3330 HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size)
3332 struct attributes *object;
3333 HRESULT hr;
3335 TRACE("%p, %d\n", attributes, size);
3337 if (!(object = calloc(1, sizeof(*object))))
3338 return E_OUTOFMEMORY;
3340 if (FAILED(hr = init_attributes_object(object, size)))
3342 free(object);
3343 return hr;
3345 *attributes = &object->IMFAttributes_iface;
3347 return S_OK;
3350 #define ATTRIBUTES_STORE_MAGIC 0x494d4641 /* IMFA */
3352 struct attributes_store_header
3354 DWORD magic;
3355 UINT32 count;
3358 struct attributes_store_item
3360 GUID key;
3361 QWORD type;
3362 union
3364 double f;
3365 UINT32 i32;
3366 UINT64 i64;
3367 struct
3369 DWORD size;
3370 DWORD offset;
3371 } subheader;
3372 } u;
3375 /***********************************************************************
3376 * MFGetAttributesAsBlobSize (mfplat.@)
3378 HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size)
3380 unsigned int i, count, length;
3381 HRESULT hr;
3382 GUID key;
3384 TRACE("%p, %p.\n", attributes, size);
3386 IMFAttributes_LockStore(attributes);
3388 hr = IMFAttributes_GetCount(attributes, &count);
3390 *size = sizeof(struct attributes_store_header);
3392 for (i = 0; i < count; ++i)
3394 MF_ATTRIBUTE_TYPE type;
3396 hr = IMFAttributes_GetItemByIndex(attributes, i, &key, NULL);
3397 if (FAILED(hr))
3398 break;
3400 *size += sizeof(struct attributes_store_item);
3402 IMFAttributes_GetItemType(attributes, &key, &type);
3404 switch (type)
3406 case MF_ATTRIBUTE_GUID:
3407 *size += sizeof(GUID);
3408 break;
3409 case MF_ATTRIBUTE_STRING:
3410 IMFAttributes_GetStringLength(attributes, &key, &length);
3411 *size += (length + 1) * sizeof(WCHAR);
3412 break;
3413 case MF_ATTRIBUTE_BLOB:
3414 IMFAttributes_GetBlobSize(attributes, &key, &length);
3415 *size += length;
3416 break;
3417 case MF_ATTRIBUTE_UINT32:
3418 case MF_ATTRIBUTE_UINT64:
3419 case MF_ATTRIBUTE_DOUBLE:
3420 case MF_ATTRIBUTE_IUNKNOWN:
3421 default:
3426 IMFAttributes_UnlockStore(attributes);
3428 return hr;
3431 struct attr_serialize_context
3433 UINT8 *buffer;
3434 UINT8 *ptr;
3435 UINT32 size;
3438 static void attributes_serialize_write(struct attr_serialize_context *context, const void *value, unsigned int size)
3440 memcpy(context->ptr, value, size);
3441 context->ptr += size;
3444 static BOOL attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
3445 const void *value)
3447 switch (item->type)
3449 case MF_ATTRIBUTE_UINT32:
3450 case MF_ATTRIBUTE_UINT64:
3451 case MF_ATTRIBUTE_DOUBLE:
3452 attributes_serialize_write(context, item, sizeof(*item));
3453 break;
3454 case MF_ATTRIBUTE_GUID:
3455 case MF_ATTRIBUTE_STRING:
3456 case MF_ATTRIBUTE_BLOB:
3457 item->u.subheader.offset = context->size - item->u.subheader.size;
3458 attributes_serialize_write(context, item, sizeof(*item));
3459 memcpy(context->buffer + item->u.subheader.offset, value, item->u.subheader.size);
3460 context->size -= item->u.subheader.size;
3461 break;
3462 default:
3463 return FALSE;
3466 return TRUE;
3469 /***********************************************************************
3470 * MFGetAttributesAsBlob (mfplat.@)
3472 HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size)
3474 struct attributes_store_header header;
3475 struct attr_serialize_context context;
3476 unsigned int required_size, i;
3477 PROPVARIANT value;
3478 UINT32 count;
3479 HRESULT hr;
3481 TRACE("%p, %p, %u.\n", attributes, buffer, size);
3483 if (FAILED(hr = MFGetAttributesAsBlobSize(attributes, &required_size)))
3484 return hr;
3486 if (required_size > size)
3487 return MF_E_BUFFERTOOSMALL;
3489 context.buffer = buffer;
3490 context.ptr = buffer;
3491 context.size = required_size;
3493 IMFAttributes_LockStore(attributes);
3495 header.magic = ATTRIBUTES_STORE_MAGIC;
3496 header.count = 0; /* Will be updated later */
3497 IMFAttributes_GetCount(attributes, &count);
3499 attributes_serialize_write(&context, &header, sizeof(header));
3501 for (i = 0; i < count; ++i)
3503 struct attributes_store_item item;
3504 const void *data = NULL;
3506 hr = IMFAttributes_GetItemByIndex(attributes, i, &item.key, &value);
3507 if (FAILED(hr))
3508 break;
3510 item.type = value.vt;
3512 switch (value.vt)
3514 case MF_ATTRIBUTE_UINT32:
3515 case MF_ATTRIBUTE_UINT64:
3516 item.u.i64 = value.uhVal.QuadPart;
3517 break;
3518 case MF_ATTRIBUTE_DOUBLE:
3519 item.u.f = value.dblVal;
3520 break;
3521 case MF_ATTRIBUTE_GUID:
3522 item.u.subheader.size = sizeof(*value.puuid);
3523 data = value.puuid;
3524 break;
3525 case MF_ATTRIBUTE_STRING:
3526 item.u.subheader.size = (lstrlenW(value.pwszVal) + 1) * sizeof(WCHAR);
3527 data = value.pwszVal;
3528 break;
3529 case MF_ATTRIBUTE_BLOB:
3530 item.u.subheader.size = value.caub.cElems;
3531 data = value.caub.pElems;
3532 break;
3533 case MF_ATTRIBUTE_IUNKNOWN:
3534 break;
3535 default:
3536 WARN("Unknown attribute type %#x.\n", value.vt);
3539 if (attributes_serialize_write_item(&context, &item, data))
3540 header.count++;
3542 PropVariantClear(&value);
3545 memcpy(context.buffer, &header, sizeof(header));
3547 IMFAttributes_UnlockStore(attributes);
3549 return S_OK;
3552 static HRESULT attributes_deserialize_read(struct attr_serialize_context *context, void *value, unsigned int size)
3554 if (context->size < (context->ptr - context->buffer) + size)
3555 return E_INVALIDARG;
3557 memcpy(value, context->ptr, size);
3558 context->ptr += size;
3560 return S_OK;
3563 /***********************************************************************
3564 * MFInitAttributesFromBlob (mfplat.@)
3566 HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *dest, const UINT8 *buffer, UINT size)
3568 struct attr_serialize_context context;
3569 struct attributes_store_header header;
3570 struct attributes_store_item item;
3571 IMFAttributes *attributes;
3572 unsigned int i;
3573 HRESULT hr;
3575 TRACE("%p, %p, %u.\n", dest, buffer, size);
3577 context.buffer = (UINT8 *)buffer;
3578 context.ptr = (UINT8 *)buffer;
3579 context.size = size;
3581 /* Validate buffer structure. */
3582 if (FAILED(hr = attributes_deserialize_read(&context, &header, sizeof(header))))
3583 return hr;
3585 if (header.magic != ATTRIBUTES_STORE_MAGIC)
3586 return E_UNEXPECTED;
3588 if (FAILED(hr = MFCreateAttributes(&attributes, header.count)))
3589 return hr;
3591 for (i = 0; i < header.count; ++i)
3593 if (FAILED(hr = attributes_deserialize_read(&context, &item, sizeof(item))))
3594 break;
3596 hr = E_UNEXPECTED;
3598 switch (item.type)
3600 case MF_ATTRIBUTE_UINT32:
3601 hr = IMFAttributes_SetUINT32(attributes, &item.key, item.u.i32);
3602 break;
3603 case MF_ATTRIBUTE_UINT64:
3604 hr = IMFAttributes_SetUINT64(attributes, &item.key, item.u.i64);
3605 break;
3606 case MF_ATTRIBUTE_DOUBLE:
3607 hr = IMFAttributes_SetDouble(attributes, &item.key, item.u.f);
3608 break;
3609 case MF_ATTRIBUTE_GUID:
3610 if (item.u.subheader.size == sizeof(GUID) &&
3611 item.u.subheader.offset + item.u.subheader.size <= context.size)
3613 hr = IMFAttributes_SetGUID(attributes, &item.key,
3614 (const GUID *)(context.buffer + item.u.subheader.offset));
3616 break;
3617 case MF_ATTRIBUTE_STRING:
3618 if (item.u.subheader.size >= sizeof(WCHAR) &&
3619 item.u.subheader.offset + item.u.subheader.size <= context.size)
3621 hr = IMFAttributes_SetString(attributes, &item.key,
3622 (const WCHAR *)(context.buffer + item.u.subheader.offset));
3624 break;
3625 case MF_ATTRIBUTE_BLOB:
3626 if (item.u.subheader.size > 0 && item.u.subheader.offset + item.u.subheader.size <= context.size)
3628 hr = IMFAttributes_SetBlob(attributes, &item.key, context.buffer + item.u.subheader.offset,
3629 item.u.subheader.size);
3631 break;
3632 default:
3636 if (FAILED(hr))
3637 break;
3640 if (SUCCEEDED(hr))
3642 IMFAttributes_DeleteAllItems(dest);
3643 hr = IMFAttributes_CopyAllItems(attributes, dest);
3646 IMFAttributes_Release(attributes);
3648 return hr;
3651 struct bytestream
3653 struct attributes attributes;
3654 IMFByteStream IMFByteStream_iface;
3655 IMFGetService IMFGetService_iface;
3656 IRtwqAsyncCallback read_callback;
3657 IRtwqAsyncCallback write_callback;
3658 IStream *stream;
3659 HANDLE hfile;
3660 QWORD position;
3661 DWORD capabilities;
3662 struct list pending;
3663 CRITICAL_SECTION cs;
3666 static inline struct bytestream *impl_from_IMFByteStream(IMFByteStream *iface)
3668 return CONTAINING_RECORD(iface, struct bytestream, IMFByteStream_iface);
3671 static struct bytestream *impl_bytestream_from_IMFGetService(IMFGetService *iface)
3673 return CONTAINING_RECORD(iface, struct bytestream, IMFGetService_iface);
3676 static struct bytestream *impl_from_read_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3678 return CONTAINING_RECORD(iface, struct bytestream, read_callback);
3681 static struct bytestream *impl_from_write_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3683 return CONTAINING_RECORD(iface, struct bytestream, write_callback);
3686 enum async_stream_op_type
3688 ASYNC_STREAM_OP_READ,
3689 ASYNC_STREAM_OP_WRITE,
3692 struct async_stream_op
3694 IUnknown IUnknown_iface;
3695 LONG refcount;
3696 union
3698 const BYTE *src;
3699 BYTE *dest;
3700 } u;
3701 QWORD position;
3702 ULONG requested_length;
3703 ULONG actual_length;
3704 IMFAsyncResult *caller;
3705 struct list entry;
3706 enum async_stream_op_type type;
3709 static struct async_stream_op *impl_async_stream_op_from_IUnknown(IUnknown *iface)
3711 return CONTAINING_RECORD(iface, struct async_stream_op, IUnknown_iface);
3714 static HRESULT WINAPI async_stream_op_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
3716 if (IsEqualIID(riid, &IID_IUnknown))
3718 *obj = iface;
3719 IUnknown_AddRef(iface);
3720 return S_OK;
3723 WARN("Unsupported %s.\n", debugstr_guid(riid));
3724 *obj = NULL;
3725 return E_NOINTERFACE;
3728 static ULONG WINAPI async_stream_op_AddRef(IUnknown *iface)
3730 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3731 ULONG refcount = InterlockedIncrement(&op->refcount);
3733 TRACE("%p, refcount %ld.\n", iface, refcount);
3735 return refcount;
3738 static ULONG WINAPI async_stream_op_Release(IUnknown *iface)
3740 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3741 ULONG refcount = InterlockedDecrement(&op->refcount);
3743 TRACE("%p, refcount %ld.\n", iface, refcount);
3745 if (!refcount)
3747 if (op->caller)
3748 IMFAsyncResult_Release(op->caller);
3749 free(op);
3752 return refcount;
3755 static const IUnknownVtbl async_stream_op_vtbl =
3757 async_stream_op_QueryInterface,
3758 async_stream_op_AddRef,
3759 async_stream_op_Release,
3762 static HRESULT bytestream_create_io_request(struct bytestream *stream, enum async_stream_op_type type,
3763 const BYTE *data, ULONG size, IMFAsyncCallback *callback, IUnknown *state)
3765 struct async_stream_op *op;
3766 IRtwqAsyncResult *request;
3767 HRESULT hr;
3769 op = malloc(sizeof(*op));
3770 if (!op)
3771 return E_OUTOFMEMORY;
3773 op->IUnknown_iface.lpVtbl = &async_stream_op_vtbl;
3774 op->refcount = 1;
3775 op->u.src = data;
3776 op->position = stream->position;
3777 op->requested_length = size;
3778 op->type = type;
3779 if (FAILED(hr = RtwqCreateAsyncResult((IUnknown *)&stream->IMFByteStream_iface, (IRtwqAsyncCallback *)callback, state,
3780 (IRtwqAsyncResult **)&op->caller)))
3782 goto failed;
3785 if (FAILED(hr = RtwqCreateAsyncResult(&op->IUnknown_iface, type == ASYNC_STREAM_OP_READ ? &stream->read_callback :
3786 &stream->write_callback, NULL, &request)))
3787 goto failed;
3789 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, request);
3790 IRtwqAsyncResult_Release(request);
3792 failed:
3793 IUnknown_Release(&op->IUnknown_iface);
3794 return hr;
3797 static HRESULT bytestream_complete_io_request(struct bytestream *stream, enum async_stream_op_type type,
3798 IMFAsyncResult *result, ULONG *actual_length)
3800 struct async_stream_op *op = NULL, *cur;
3801 HRESULT hr;
3803 EnterCriticalSection(&stream->cs);
3804 LIST_FOR_EACH_ENTRY(cur, &stream->pending, struct async_stream_op, entry)
3806 if (cur->caller == result && cur->type == type)
3808 op = cur;
3809 list_remove(&cur->entry);
3810 break;
3813 LeaveCriticalSection(&stream->cs);
3815 if (!op)
3816 return E_INVALIDARG;
3818 if (SUCCEEDED(hr = IMFAsyncResult_GetStatus(result)))
3819 *actual_length = op->actual_length;
3821 IUnknown_Release(&op->IUnknown_iface);
3823 return hr;
3826 static HRESULT WINAPI bytestream_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
3828 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
3829 IsEqualIID(riid, &IID_IUnknown))
3831 *obj = iface;
3832 IRtwqAsyncCallback_AddRef(iface);
3833 return S_OK;
3836 WARN("Unsupported %s.\n", debugstr_guid(riid));
3837 *obj = NULL;
3838 return E_NOINTERFACE;
3841 static ULONG WINAPI bytestream_read_callback_AddRef(IRtwqAsyncCallback *iface)
3843 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3844 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3847 static ULONG WINAPI bytestream_read_callback_Release(IRtwqAsyncCallback *iface)
3849 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3850 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3853 static HRESULT WINAPI bytestream_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
3855 return E_NOTIMPL;
3858 static ULONG WINAPI bytestream_write_callback_AddRef(IRtwqAsyncCallback *iface)
3860 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3861 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3864 static ULONG WINAPI bytestream_write_callback_Release(IRtwqAsyncCallback *iface)
3866 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3867 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3870 static HRESULT WINAPI bytestream_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
3872 struct bytestream *stream = impl_from_IMFByteStream(iface);
3874 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
3876 if (IsEqualIID(riid, &IID_IMFByteStream) ||
3877 IsEqualIID(riid, &IID_IUnknown))
3879 *out = &stream->IMFByteStream_iface;
3881 else if (IsEqualIID(riid, &IID_IMFAttributes))
3883 *out = &stream->attributes.IMFAttributes_iface;
3885 else if (stream->IMFGetService_iface.lpVtbl && IsEqualIID(riid, &IID_IMFGetService))
3887 *out = &stream->IMFGetService_iface;
3889 else
3891 WARN("Unsupported %s.\n", debugstr_guid(riid));
3892 *out = NULL;
3893 return E_NOINTERFACE;
3896 IUnknown_AddRef((IUnknown*)*out);
3897 return S_OK;
3900 static ULONG WINAPI bytestream_AddRef(IMFByteStream *iface)
3902 struct bytestream *stream = impl_from_IMFByteStream(iface);
3903 ULONG refcount = InterlockedIncrement(&stream->attributes.ref);
3905 TRACE("%p, refcount %ld.\n", iface, refcount);
3907 return refcount;
3910 static ULONG WINAPI bytestream_Release(IMFByteStream *iface)
3912 struct bytestream *stream = impl_from_IMFByteStream(iface);
3913 ULONG refcount = InterlockedDecrement(&stream->attributes.ref);
3914 struct async_stream_op *cur, *cur2;
3916 TRACE("%p, refcount %ld.\n", iface, refcount);
3918 if (!refcount)
3920 clear_attributes_object(&stream->attributes);
3921 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &stream->pending, struct async_stream_op, entry)
3923 list_remove(&cur->entry);
3924 IUnknown_Release(&cur->IUnknown_iface);
3926 DeleteCriticalSection(&stream->cs);
3927 if (stream->stream)
3928 IStream_Release(stream->stream);
3929 if (stream->hfile)
3930 CloseHandle(stream->hfile);
3931 free(stream);
3934 return refcount;
3937 static HRESULT WINAPI bytestream_stream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3939 struct bytestream *stream = impl_from_IMFByteStream(iface);
3940 STATSTG stat;
3941 HRESULT hr;
3943 TRACE("%p, %p.\n", iface, capabilities);
3945 if (FAILED(hr = IStream_Stat(stream->stream, &stat, STATFLAG_NONAME)))
3946 return hr;
3948 *capabilities = MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_SEEKABLE;
3949 if (stat.grfMode & (STGM_WRITE | STGM_READWRITE))
3950 *capabilities |= MFBYTESTREAM_IS_WRITABLE;
3952 return S_OK;
3955 static HRESULT WINAPI bytestream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3957 struct bytestream *stream = impl_from_IMFByteStream(iface);
3959 TRACE("%p, %p.\n", iface, capabilities);
3961 *capabilities = stream->capabilities;
3963 return S_OK;
3966 static HRESULT WINAPI bytestream_SetLength(IMFByteStream *iface, QWORD length)
3968 FIXME("%p, %s\n", iface, wine_dbgstr_longlong(length));
3970 return E_NOTIMPL;
3973 static HRESULT WINAPI bytestream_file_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
3975 struct bytestream *stream = impl_from_IMFByteStream(iface);
3977 TRACE("%p, %p.\n", iface, position);
3979 if (!position)
3980 return E_INVALIDARG;
3982 *position = stream->position;
3984 return S_OK;
3987 static HRESULT WINAPI bytestream_file_GetLength(IMFByteStream *iface, QWORD *length)
3989 struct bytestream *stream = impl_from_IMFByteStream(iface);
3990 LARGE_INTEGER li;
3992 TRACE("%p, %p.\n", iface, length);
3994 if (!length)
3995 return E_INVALIDARG;
3997 if (GetFileSizeEx(stream->hfile, &li))
3998 *length = li.QuadPart;
3999 else
4000 return HRESULT_FROM_WIN32(GetLastError());
4002 return S_OK;
4005 static HRESULT WINAPI bytestream_file_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
4007 struct bytestream *stream = impl_from_IMFByteStream(iface);
4008 LARGE_INTEGER position, length;
4009 HRESULT hr = S_OK;
4011 TRACE("%p, %p.\n", iface, ret);
4013 EnterCriticalSection(&stream->cs);
4015 position.QuadPart = 0;
4016 if (SetFilePointerEx(stream->hfile, position, &length, FILE_END))
4017 *ret = stream->position >= length.QuadPart;
4018 else
4019 hr = HRESULT_FROM_WIN32(GetLastError());
4021 LeaveCriticalSection(&stream->cs);
4023 return hr;
4026 static HRESULT WINAPI bytestream_file_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
4028 struct bytestream *stream = impl_from_IMFByteStream(iface);
4029 LARGE_INTEGER position;
4030 HRESULT hr = S_OK;
4031 BOOL ret;
4033 TRACE("%p, %p, %lu, %p.\n", iface, buffer, size, read_len);
4035 EnterCriticalSection(&stream->cs);
4037 position.QuadPart = stream->position;
4038 if ((ret = SetFilePointerEx(stream->hfile, position, NULL, FILE_BEGIN)))
4040 if ((ret = ReadFile(stream->hfile, buffer, size, read_len, NULL)))
4041 stream->position += *read_len;
4044 if (!ret)
4045 hr = HRESULT_FROM_WIN32(GetLastError());
4047 LeaveCriticalSection(&stream->cs);
4049 return hr;
4052 static HRESULT WINAPI bytestream_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size, IMFAsyncCallback *callback,
4053 IUnknown *state)
4055 struct bytestream *stream = impl_from_IMFByteStream(iface);
4057 TRACE("%p, %p, %lu, %p, %p.\n", iface, data, size, callback, state);
4059 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_READ, data, size, callback, state);
4062 static HRESULT WINAPI bytestream_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
4064 struct bytestream *stream = impl_from_IMFByteStream(iface);
4066 TRACE("%p, %p, %p.\n", iface, result, byte_read);
4068 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_READ, result, byte_read);
4071 static HRESULT WINAPI bytestream_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
4073 FIXME("%p, %p, %lu, %p\n", iface, data, count, written);
4075 return E_NOTIMPL;
4078 static HRESULT WINAPI bytestream_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
4079 IMFAsyncCallback *callback, IUnknown *state)
4081 struct bytestream *stream = impl_from_IMFByteStream(iface);
4083 TRACE("%p, %p, %lu, %p, %p.\n", iface, data, size, callback, state);
4085 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_WRITE, data, size, callback, state);
4088 static HRESULT WINAPI bytestream_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
4090 struct bytestream *stream = impl_from_IMFByteStream(iface);
4092 TRACE("%p, %p, %p.\n", iface, result, written);
4094 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_WRITE, result, written);
4097 static HRESULT WINAPI bytestream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
4098 DWORD flags, QWORD *current)
4100 FIXME("%p, %u, %s, 0x%08lx, %p\n", iface, seek, wine_dbgstr_longlong(offset), flags, current);
4102 return E_NOTIMPL;
4105 static HRESULT WINAPI bytestream_Flush(IMFByteStream *iface)
4107 FIXME("%p\n", iface);
4109 return E_NOTIMPL;
4112 static HRESULT WINAPI bytestream_Close(IMFByteStream *iface)
4114 FIXME("%p\n", iface);
4116 return E_NOTIMPL;
4119 static HRESULT WINAPI bytestream_SetCurrentPosition(IMFByteStream *iface, QWORD position)
4121 struct bytestream *stream = impl_from_IMFByteStream(iface);
4123 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4125 EnterCriticalSection(&stream->cs);
4126 stream->position = position;
4127 LeaveCriticalSection(&stream->cs);
4129 return S_OK;
4132 static const IMFByteStreamVtbl bytestream_file_vtbl =
4134 bytestream_QueryInterface,
4135 bytestream_AddRef,
4136 bytestream_Release,
4137 bytestream_GetCapabilities,
4138 bytestream_file_GetLength,
4139 bytestream_SetLength,
4140 bytestream_file_GetCurrentPosition,
4141 bytestream_SetCurrentPosition,
4142 bytestream_file_IsEndOfStream,
4143 bytestream_file_Read,
4144 bytestream_BeginRead,
4145 bytestream_EndRead,
4146 bytestream_Write,
4147 bytestream_BeginWrite,
4148 bytestream_EndWrite,
4149 bytestream_Seek,
4150 bytestream_Flush,
4151 bytestream_Close
4154 static HRESULT WINAPI bytestream_stream_GetLength(IMFByteStream *iface, QWORD *length)
4156 struct bytestream *stream = impl_from_IMFByteStream(iface);
4157 STATSTG statstg;
4158 HRESULT hr;
4160 TRACE("%p, %p.\n", iface, length);
4162 if (FAILED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4163 return hr;
4165 *length = statstg.cbSize.QuadPart;
4167 return S_OK;
4170 static HRESULT WINAPI bytestream_stream_SetLength(IMFByteStream *iface, QWORD length)
4172 struct bytestream *stream = impl_from_IMFByteStream(iface);
4173 ULARGE_INTEGER size;
4174 HRESULT hr;
4176 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4178 EnterCriticalSection(&stream->cs);
4180 size.QuadPart = length;
4181 hr = IStream_SetSize(stream->stream, size);
4183 LeaveCriticalSection(&stream->cs);
4185 return hr;
4188 static HRESULT WINAPI bytestream_stream_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4190 struct bytestream *stream = impl_from_IMFByteStream(iface);
4192 TRACE("%p, %p.\n", iface, position);
4194 *position = stream->position;
4196 return S_OK;
4199 static HRESULT WINAPI bytestream_stream_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
4201 struct bytestream *stream = impl_from_IMFByteStream(iface);
4202 STATSTG statstg;
4203 HRESULT hr;
4205 TRACE("%p, %p.\n", iface, ret);
4207 EnterCriticalSection(&stream->cs);
4209 if (SUCCEEDED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4210 *ret = stream->position >= statstg.cbSize.QuadPart;
4212 LeaveCriticalSection(&stream->cs);
4214 return hr;
4217 static HRESULT WINAPI bytestream_stream_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
4219 struct bytestream *stream = impl_from_IMFByteStream(iface);
4220 LARGE_INTEGER position;
4221 HRESULT hr;
4223 TRACE("%p, %p, %lu, %p.\n", iface, buffer, size, read_len);
4225 EnterCriticalSection(&stream->cs);
4227 position.QuadPart = stream->position;
4228 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4230 if (SUCCEEDED(hr = IStream_Read(stream->stream, buffer, size, read_len)))
4231 stream->position += *read_len;
4234 LeaveCriticalSection(&stream->cs);
4236 return hr;
4239 static HRESULT WINAPI bytestream_stream_Write(IMFByteStream *iface, const BYTE *buffer, ULONG size, ULONG *written)
4241 struct bytestream *stream = impl_from_IMFByteStream(iface);
4242 LARGE_INTEGER position;
4243 HRESULT hr;
4245 TRACE("%p, %p, %lu, %p.\n", iface, buffer, size, written);
4247 EnterCriticalSection(&stream->cs);
4249 position.QuadPart = stream->position;
4250 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4252 if (SUCCEEDED(hr = IStream_Write(stream->stream, buffer, size, written)))
4253 stream->position += *written;
4256 LeaveCriticalSection(&stream->cs);
4258 return hr;
4261 static HRESULT WINAPI bytestream_stream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN origin, LONGLONG offset,
4262 DWORD flags, QWORD *current)
4264 struct bytestream *stream = impl_from_IMFByteStream(iface);
4265 HRESULT hr = S_OK;
4267 TRACE("%p, %u, %s, %#lx, %p.\n", iface, origin, wine_dbgstr_longlong(offset), flags, current);
4269 EnterCriticalSection(&stream->cs);
4271 switch (origin)
4273 case msoBegin:
4274 stream->position = offset;
4275 break;
4276 case msoCurrent:
4277 stream->position += offset;
4278 break;
4279 default:
4280 WARN("Unknown origin mode %d.\n", origin);
4281 hr = E_INVALIDARG;
4284 *current = stream->position;
4286 LeaveCriticalSection(&stream->cs);
4288 return hr;
4291 static HRESULT WINAPI bytestream_stream_Flush(IMFByteStream *iface)
4293 struct bytestream *stream = impl_from_IMFByteStream(iface);
4295 TRACE("%p.\n", iface);
4297 return IStream_Commit(stream->stream, STGC_DEFAULT);
4300 static HRESULT WINAPI bytestream_stream_Close(IMFByteStream *iface)
4302 TRACE("%p.\n", iface);
4304 return S_OK;
4307 static const IMFByteStreamVtbl bytestream_stream_vtbl =
4309 bytestream_QueryInterface,
4310 bytestream_AddRef,
4311 bytestream_Release,
4312 bytestream_stream_GetCapabilities,
4313 bytestream_stream_GetLength,
4314 bytestream_stream_SetLength,
4315 bytestream_stream_GetCurrentPosition,
4316 bytestream_SetCurrentPosition,
4317 bytestream_stream_IsEndOfStream,
4318 bytestream_stream_Read,
4319 bytestream_BeginRead,
4320 bytestream_EndRead,
4321 bytestream_stream_Write,
4322 bytestream_BeginWrite,
4323 bytestream_EndWrite,
4324 bytestream_stream_Seek,
4325 bytestream_stream_Flush,
4326 bytestream_stream_Close,
4329 static inline struct bytestream *impl_from_IMFByteStream_IMFAttributes(IMFAttributes *iface)
4331 return CONTAINING_RECORD(iface, struct bytestream, attributes.IMFAttributes_iface);
4334 static HRESULT WINAPI bytestream_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
4336 struct bytestream *stream = impl_from_IMFByteStream_IMFAttributes(iface);
4337 return IMFByteStream_QueryInterface(&stream->IMFByteStream_iface, riid, out);
4340 static ULONG WINAPI bytestream_attributes_AddRef(IMFAttributes *iface)
4342 struct bytestream *stream = impl_from_IMFByteStream_IMFAttributes(iface);
4343 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
4346 static ULONG WINAPI bytestream_attributes_Release(IMFAttributes *iface)
4348 struct bytestream *stream = impl_from_IMFByteStream_IMFAttributes(iface);
4349 return IMFByteStream_Release(&stream->IMFByteStream_iface);
4352 static const IMFAttributesVtbl bytestream_attributes_vtbl =
4354 bytestream_attributes_QueryInterface,
4355 bytestream_attributes_AddRef,
4356 bytestream_attributes_Release,
4357 mfattributes_GetItem,
4358 mfattributes_GetItemType,
4359 mfattributes_CompareItem,
4360 mfattributes_Compare,
4361 mfattributes_GetUINT32,
4362 mfattributes_GetUINT64,
4363 mfattributes_GetDouble,
4364 mfattributes_GetGUID,
4365 mfattributes_GetStringLength,
4366 mfattributes_GetString,
4367 mfattributes_GetAllocatedString,
4368 mfattributes_GetBlobSize,
4369 mfattributes_GetBlob,
4370 mfattributes_GetAllocatedBlob,
4371 mfattributes_GetUnknown,
4372 mfattributes_SetItem,
4373 mfattributes_DeleteItem,
4374 mfattributes_DeleteAllItems,
4375 mfattributes_SetUINT32,
4376 mfattributes_SetUINT64,
4377 mfattributes_SetDouble,
4378 mfattributes_SetGUID,
4379 mfattributes_SetString,
4380 mfattributes_SetBlob,
4381 mfattributes_SetUnknown,
4382 mfattributes_LockStore,
4383 mfattributes_UnlockStore,
4384 mfattributes_GetCount,
4385 mfattributes_GetItemByIndex,
4386 mfattributes_CopyAllItems
4389 static HRESULT WINAPI bytestream_stream_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4391 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4392 struct async_stream_op *op;
4393 LARGE_INTEGER position;
4394 IUnknown *object;
4395 HRESULT hr;
4397 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4398 return hr;
4400 op = impl_async_stream_op_from_IUnknown(object);
4402 EnterCriticalSection(&stream->cs);
4404 position.QuadPart = op->position;
4405 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4407 if (SUCCEEDED(hr = IStream_Read(stream->stream, op->u.dest, op->requested_length, &op->actual_length)))
4408 stream->position += op->actual_length;
4411 IMFAsyncResult_SetStatus(op->caller, hr);
4412 list_add_tail(&stream->pending, &op->entry);
4414 LeaveCriticalSection(&stream->cs);
4416 MFInvokeCallback(op->caller);
4418 return S_OK;
4421 static HRESULT WINAPI bytestream_stream_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4423 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4424 struct async_stream_op *op;
4425 LARGE_INTEGER position;
4426 IUnknown *object;
4427 HRESULT hr;
4429 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4430 return hr;
4432 op = impl_async_stream_op_from_IUnknown(object);
4434 EnterCriticalSection(&stream->cs);
4436 position.QuadPart = op->position;
4437 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4439 if (SUCCEEDED(hr = IStream_Write(stream->stream, op->u.src, op->requested_length, &op->actual_length)))
4440 stream->position += op->actual_length;
4443 IMFAsyncResult_SetStatus(op->caller, hr);
4444 list_add_tail(&stream->pending, &op->entry);
4446 LeaveCriticalSection(&stream->cs);
4448 MFInvokeCallback(op->caller);
4450 return S_OK;
4453 static const IRtwqAsyncCallbackVtbl bytestream_stream_read_callback_vtbl =
4455 bytestream_callback_QueryInterface,
4456 bytestream_read_callback_AddRef,
4457 bytestream_read_callback_Release,
4458 bytestream_callback_GetParameters,
4459 bytestream_stream_read_callback_Invoke,
4462 static const IRtwqAsyncCallbackVtbl bytestream_stream_write_callback_vtbl =
4464 bytestream_callback_QueryInterface,
4465 bytestream_write_callback_AddRef,
4466 bytestream_write_callback_Release,
4467 bytestream_callback_GetParameters,
4468 bytestream_stream_write_callback_Invoke,
4471 /***********************************************************************
4472 * MFCreateMFByteStreamOnStream (mfplat.@)
4474 HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **bytestream)
4476 struct bytestream *object;
4477 LARGE_INTEGER position;
4478 STATSTG stat;
4479 HRESULT hr;
4481 TRACE("%p, %p.\n", stream, bytestream);
4483 if (!(object = calloc(1, sizeof(*object))))
4484 return E_OUTOFMEMORY;
4486 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
4488 free(object);
4489 return hr;
4492 object->IMFByteStream_iface.lpVtbl = &bytestream_stream_vtbl;
4493 object->attributes.IMFAttributes_iface.lpVtbl = &bytestream_attributes_vtbl;
4494 object->read_callback.lpVtbl = &bytestream_stream_read_callback_vtbl;
4495 object->write_callback.lpVtbl = &bytestream_stream_write_callback_vtbl;
4496 InitializeCriticalSection(&object->cs);
4497 list_init(&object->pending);
4499 object->stream = stream;
4500 IStream_AddRef(object->stream);
4501 position.QuadPart = 0;
4502 IStream_Seek(object->stream, position, STREAM_SEEK_SET, NULL);
4504 if (SUCCEEDED(IStream_Stat(object->stream, &stat, 0)))
4506 if (stat.pwcsName)
4508 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME,
4509 stat.pwcsName);
4510 CoTaskMemFree(stat.pwcsName);
4514 *bytestream = &object->IMFByteStream_iface;
4516 return S_OK;
4519 static HRESULT WINAPI bytestream_file_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4521 FIXME("%p, %p.\n", iface, result);
4523 return E_NOTIMPL;
4526 static HRESULT WINAPI bytestream_file_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4528 FIXME("%p, %p.\n", iface, result);
4530 return E_NOTIMPL;
4533 static const IRtwqAsyncCallbackVtbl bytestream_file_read_callback_vtbl =
4535 bytestream_callback_QueryInterface,
4536 bytestream_read_callback_AddRef,
4537 bytestream_read_callback_Release,
4538 bytestream_callback_GetParameters,
4539 bytestream_file_read_callback_Invoke,
4542 static const IRtwqAsyncCallbackVtbl bytestream_file_write_callback_vtbl =
4544 bytestream_callback_QueryInterface,
4545 bytestream_write_callback_AddRef,
4546 bytestream_write_callback_Release,
4547 bytestream_callback_GetParameters,
4548 bytestream_file_write_callback_Invoke,
4551 static HRESULT WINAPI bytestream_file_getservice_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
4553 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4554 return IMFByteStream_QueryInterface(&stream->IMFByteStream_iface, riid, obj);
4557 static ULONG WINAPI bytestream_file_getservice_AddRef(IMFGetService *iface)
4559 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4560 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
4563 static ULONG WINAPI bytestream_file_getservice_Release(IMFGetService *iface)
4565 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4566 return IMFByteStream_Release(&stream->IMFByteStream_iface);
4569 static HRESULT WINAPI bytestream_file_getservice_GetService(IMFGetService *iface, REFGUID service,
4570 REFIID riid, void **obj)
4572 FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
4574 return E_NOTIMPL;
4577 static const IMFGetServiceVtbl bytestream_file_getservice_vtbl =
4579 bytestream_file_getservice_QueryInterface,
4580 bytestream_file_getservice_AddRef,
4581 bytestream_file_getservice_Release,
4582 bytestream_file_getservice_GetService,
4585 static HRESULT create_file_bytestream(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4586 const WCHAR *path, BOOL is_tempfile, IMFByteStream **bytestream)
4588 DWORD capabilities = MFBYTESTREAM_IS_SEEKABLE | MFBYTESTREAM_DOES_NOT_USE_NETWORK;
4589 DWORD filecreation_disposition = 0, fileaccessmode = 0, fileattributes = 0;
4590 DWORD filesharemode = FILE_SHARE_READ | FILE_SHARE_DELETE;
4591 struct bytestream *object;
4592 FILETIME writetime;
4593 HANDLE file;
4594 HRESULT hr;
4596 switch (accessmode)
4598 case MF_ACCESSMODE_READ:
4599 fileaccessmode = GENERIC_READ;
4600 capabilities |= MFBYTESTREAM_IS_READABLE;
4601 break;
4602 case MF_ACCESSMODE_WRITE:
4603 fileaccessmode = GENERIC_WRITE;
4604 capabilities |= MFBYTESTREAM_IS_WRITABLE;
4605 break;
4606 case MF_ACCESSMODE_READWRITE:
4607 fileaccessmode = GENERIC_READ | GENERIC_WRITE;
4608 capabilities |= (MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_WRITABLE);
4609 break;
4612 switch (openmode)
4614 case MF_OPENMODE_FAIL_IF_NOT_EXIST:
4615 filecreation_disposition = OPEN_EXISTING;
4616 break;
4617 case MF_OPENMODE_FAIL_IF_EXIST:
4618 filecreation_disposition = CREATE_NEW;
4619 break;
4620 case MF_OPENMODE_RESET_IF_EXIST:
4621 filecreation_disposition = TRUNCATE_EXISTING;
4622 break;
4623 case MF_OPENMODE_APPEND_IF_EXIST:
4624 filecreation_disposition = OPEN_ALWAYS;
4625 fileaccessmode |= FILE_APPEND_DATA;
4626 break;
4627 case MF_OPENMODE_DELETE_IF_EXIST:
4628 filecreation_disposition = CREATE_ALWAYS;
4629 break;
4632 if (flags & MF_FILEFLAGS_NOBUFFERING)
4633 fileattributes |= FILE_FLAG_NO_BUFFERING;
4634 if (is_tempfile)
4635 fileattributes |= FILE_FLAG_DELETE_ON_CLOSE;
4637 /* Open HANDLE to file */
4638 file = CreateFileW(path, fileaccessmode, filesharemode, NULL, filecreation_disposition, fileattributes, 0);
4639 if (file == INVALID_HANDLE_VALUE)
4640 return HRESULT_FROM_WIN32(GetLastError());
4642 if (!(object = calloc(1, sizeof(*object))))
4644 CloseHandle(file);
4645 return E_OUTOFMEMORY;
4648 if (FAILED(hr = init_attributes_object(&object->attributes, 2)))
4650 CloseHandle(file);
4651 free(object);
4652 return hr;
4654 object->IMFByteStream_iface.lpVtbl = &bytestream_file_vtbl;
4655 object->attributes.IMFAttributes_iface.lpVtbl = &bytestream_attributes_vtbl;
4656 object->IMFGetService_iface.lpVtbl = &bytestream_file_getservice_vtbl;
4657 object->read_callback.lpVtbl = &bytestream_file_read_callback_vtbl;
4658 object->write_callback.lpVtbl = &bytestream_file_write_callback_vtbl;
4659 InitializeCriticalSection(&object->cs);
4660 list_init(&object->pending);
4661 object->capabilities = capabilities;
4662 object->hfile = file;
4664 if (!is_tempfile && GetFileTime(file, NULL, NULL, &writetime))
4666 IMFAttributes_SetBlob(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_LAST_MODIFIED_TIME,
4667 (const UINT8 *)&writetime, sizeof(writetime));
4670 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME, path);
4672 *bytestream = &object->IMFByteStream_iface;
4674 return S_OK;
4677 /***********************************************************************
4678 * MFCreateFile (mfplat.@)
4680 HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4681 const WCHAR *path, IMFByteStream **bytestream)
4683 TRACE("%d, %d, %#x, %s, %p.\n", accessmode, openmode, flags, debugstr_w(path), bytestream);
4685 return create_file_bytestream(accessmode, openmode, flags, path, FALSE, bytestream);
4688 /***********************************************************************
4689 * MFCreateTempFile (mfplat.@)
4691 HRESULT WINAPI MFCreateTempFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4692 IMFByteStream **bytestream)
4694 WCHAR name[24], tmppath[MAX_PATH], *path;
4695 ULONG64 rnd;
4696 size_t len;
4697 HRESULT hr;
4699 TRACE("%d, %d, %#x, %p.\n", accessmode, openmode, flags, bytestream);
4701 BCryptGenRandom(NULL, (UCHAR *)&rnd, sizeof(rnd), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
4702 swprintf(name, ARRAY_SIZE(name), L"MFP%llX.TMP", rnd);
4703 GetTempPathW(ARRAY_SIZE(tmppath), tmppath);
4705 len = wcslen(tmppath) + wcslen(name) + 2;
4706 if (!(path = malloc(len * sizeof(*path))))
4707 return E_OUTOFMEMORY;
4709 wcscpy(path, tmppath);
4710 PathCchAppend(path, len, name);
4712 hr = create_file_bytestream(accessmode, openmode, flags, path, TRUE, bytestream);
4714 free(path);
4716 return hr;
4719 struct bytestream_wrapper
4721 IMFByteStreamCacheControl IMFByteStreamCacheControl_iface;
4722 IMFByteStreamBuffering IMFByteStreamBuffering_iface;
4723 IMFMediaEventGenerator IMFMediaEventGenerator_iface;
4724 IMFByteStreamTimeSeek IMFByteStreamTimeSeek_iface;
4725 IMFSampleOutputStream IMFSampleOutputStream_iface;
4726 IPropertyStore IPropertyStore_iface;
4727 IMFByteStream IMFByteStream_iface;
4728 IMFAttributes IMFAttributes_iface;
4729 LONG refcount;
4731 IMFByteStreamCacheControl *cache_control;
4732 IMFByteStreamBuffering *stream_buffering;
4733 IMFMediaEventGenerator *event_generator;
4734 IMFByteStreamTimeSeek *time_seek;
4735 IMFSampleOutputStream *sample_output;
4736 IPropertyStore *propstore;
4737 IMFByteStream *stream;
4738 IMFAttributes *attributes;
4739 BOOL is_closed;
4742 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStream(IMFByteStream *iface)
4744 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStream_iface);
4747 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamCacheControl(IMFByteStreamCacheControl *iface)
4749 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamCacheControl_iface);
4752 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamBuffering(IMFByteStreamBuffering *iface)
4754 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamBuffering_iface);
4757 static struct bytestream_wrapper *impl_wrapper_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
4759 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFMediaEventGenerator_iface);
4762 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamTimeSeek(IMFByteStreamTimeSeek *iface)
4764 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamTimeSeek_iface);
4767 static struct bytestream_wrapper *impl_wrapper_from_IMFSampleOutputStream(IMFSampleOutputStream *iface)
4769 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFSampleOutputStream_iface);
4772 static struct bytestream_wrapper *impl_wrapper_from_IPropertyStore(IPropertyStore *iface)
4774 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IPropertyStore_iface);
4777 static struct bytestream_wrapper *impl_wrapper_from_IMFAttributes(IMFAttributes *iface)
4779 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFAttributes_iface);
4782 static HRESULT WINAPI bytestream_wrapper_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
4784 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4786 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
4788 if (IsEqualIID(riid, &IID_IMFByteStream) ||
4789 IsEqualIID(riid, &IID_IUnknown))
4791 *out = &wrapper->IMFByteStream_iface;
4793 else if (wrapper->cache_control && IsEqualIID(riid, &IID_IMFByteStreamCacheControl))
4795 *out = &wrapper->IMFByteStreamCacheControl_iface;
4797 else if (wrapper->stream_buffering && IsEqualIID(riid, &IID_IMFByteStreamBuffering))
4799 *out = &wrapper->IMFByteStreamBuffering_iface;
4801 else if (wrapper->event_generator && IsEqualIID(riid, &IID_IMFMediaEventGenerator))
4803 *out = &wrapper->IMFMediaEventGenerator_iface;
4805 else if (wrapper->time_seek && IsEqualIID(riid, &IID_IMFByteStreamTimeSeek))
4807 *out = &wrapper->IMFByteStreamTimeSeek_iface;
4809 else if (wrapper->sample_output && IsEqualIID(riid, &IID_IMFSampleOutputStream))
4811 *out = &wrapper->IMFSampleOutputStream_iface;
4813 else if (wrapper->propstore && IsEqualIID(riid, &IID_IPropertyStore))
4815 *out = &wrapper->IPropertyStore_iface;
4817 else if (wrapper->attributes && IsEqualIID(riid, &IID_IMFAttributes))
4819 *out = &wrapper->IMFAttributes_iface;
4821 else
4823 WARN("Unsupported %s.\n", debugstr_guid(riid));
4824 *out = NULL;
4825 return E_NOINTERFACE;
4828 IUnknown_AddRef((IUnknown *)*out);
4829 return S_OK;
4832 static ULONG WINAPI bytestream_wrapper_AddRef(IMFByteStream *iface)
4834 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4835 ULONG refcount = InterlockedIncrement(&wrapper->refcount);
4837 TRACE("%p, refcount %ld.\n", iface, refcount);
4839 return refcount;
4842 static ULONG WINAPI bytestream_wrapper_Release(IMFByteStream *iface)
4844 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4845 ULONG refcount = InterlockedDecrement(&wrapper->refcount);
4847 TRACE("%p, refcount %ld.\n", iface, refcount);
4849 if (!refcount)
4851 if (wrapper->cache_control)
4852 IMFByteStreamCacheControl_Release(wrapper->cache_control);
4853 if (wrapper->stream_buffering)
4854 IMFByteStreamBuffering_Release(wrapper->stream_buffering);
4855 if (wrapper->event_generator)
4856 IMFMediaEventGenerator_Release(wrapper->event_generator);
4857 if (wrapper->time_seek)
4858 IMFByteStreamTimeSeek_Release(wrapper->time_seek);
4859 if (wrapper->sample_output)
4860 IMFSampleOutputStream_Release(wrapper->sample_output);
4861 if (wrapper->propstore)
4862 IPropertyStore_Release(wrapper->propstore);
4863 if (wrapper->attributes)
4864 IMFAttributes_Release(wrapper->attributes);
4865 IMFByteStream_Release(wrapper->stream);
4866 free(wrapper);
4869 return refcount;
4872 static HRESULT WINAPI bytestream_wrapper_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
4874 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4876 TRACE("%p, %p.\n", iface, capabilities);
4878 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4879 IMFByteStream_GetCapabilities(wrapper->stream, capabilities);
4882 static HRESULT WINAPI bytestream_wrapper_GetLength(IMFByteStream *iface, QWORD *length)
4884 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4886 TRACE("%p, %p.\n", iface, length);
4888 if (wrapper->is_closed)
4889 return MF_E_INVALIDREQUEST;
4891 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4892 IMFByteStream_GetLength(wrapper->stream, length);
4895 static HRESULT WINAPI bytestream_wrapper_SetLength(IMFByteStream *iface, QWORD length)
4897 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4899 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4901 if (wrapper->is_closed)
4902 return MF_E_INVALIDREQUEST;
4904 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4905 IMFByteStream_SetLength(wrapper->stream, length);
4908 static HRESULT WINAPI bytestream_wrapper_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4910 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4912 TRACE("%p, %p.\n", iface, position);
4914 if (wrapper->is_closed)
4915 return MF_E_INVALIDREQUEST;
4917 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4918 IMFByteStream_GetCurrentPosition(wrapper->stream, position);
4921 static HRESULT WINAPI bytestream_wrapper_SetCurrentPosition(IMFByteStream *iface, QWORD position)
4923 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4925 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4927 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4928 IMFByteStream_SetCurrentPosition(wrapper->stream, position);
4931 static HRESULT WINAPI bytestream_wrapper_IsEndOfStream(IMFByteStream *iface, BOOL *eos)
4933 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4935 TRACE("%p, %p.\n", iface, eos);
4937 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4938 IMFByteStream_IsEndOfStream(wrapper->stream, eos);
4941 static HRESULT WINAPI bytestream_wrapper_Read(IMFByteStream *iface, BYTE *data, ULONG count, ULONG *byte_read)
4943 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4945 TRACE("%p, %p, %lu, %p.\n", iface, data, count, byte_read);
4947 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4948 IMFByteStream_Read(wrapper->stream, data, count, byte_read);
4951 static HRESULT WINAPI bytestream_wrapper_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size,
4952 IMFAsyncCallback *callback, IUnknown *state)
4954 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4956 TRACE("%p, %p, %lu, %p, %p.\n", iface, data, size, callback, state);
4958 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4959 IMFByteStream_BeginRead(wrapper->stream, data, size, callback, state);
4962 static HRESULT WINAPI bytestream_wrapper_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
4964 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4966 TRACE("%p, %p, %p.\n", iface, result, byte_read);
4968 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4969 IMFByteStream_EndRead(wrapper->stream, result, byte_read);
4972 static HRESULT WINAPI bytestream_wrapper_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
4974 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4976 TRACE("%p, %p, %lu, %p.\n", iface, data, count, written);
4978 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4979 IMFByteStream_Write(wrapper->stream, data, count, written);
4982 static HRESULT WINAPI bytestream_wrapper_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
4983 IMFAsyncCallback *callback, IUnknown *state)
4985 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4987 TRACE("%p, %p, %lu, %p, %p.\n", iface, data, size, callback, state);
4989 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4990 IMFByteStream_BeginWrite(wrapper->stream, data, size, callback, state);
4993 static HRESULT WINAPI bytestream_wrapper_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
4995 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4997 TRACE("%p, %p, %p.\n", iface, result, written);
4999 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
5000 IMFByteStream_EndWrite(wrapper->stream, result, written);
5003 static HRESULT WINAPI bytestream_wrapper_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
5004 DWORD flags, QWORD *current)
5006 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
5008 TRACE("%p, %u, %s, %#lx, %p.\n", iface, seek, wine_dbgstr_longlong(offset), flags, current);
5010 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
5011 IMFByteStream_Seek(wrapper->stream, seek, offset, flags, current);
5014 static HRESULT WINAPI bytestream_wrapper_Flush(IMFByteStream *iface)
5016 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
5018 TRACE("%p\n", iface);
5020 return wrapper->is_closed ? MF_E_INVALIDREQUEST : IMFByteStream_Flush(wrapper->stream);
5023 static HRESULT WINAPI bytestream_wrapper_Close(IMFByteStream *iface)
5025 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
5027 TRACE("%p\n", iface);
5029 wrapper->is_closed = TRUE;
5031 return S_OK;
5034 static const IMFByteStreamVtbl bytestream_wrapper_vtbl =
5036 bytestream_wrapper_QueryInterface,
5037 bytestream_wrapper_AddRef,
5038 bytestream_wrapper_Release,
5039 bytestream_wrapper_GetCapabilities,
5040 bytestream_wrapper_GetLength,
5041 bytestream_wrapper_SetLength,
5042 bytestream_wrapper_GetCurrentPosition,
5043 bytestream_wrapper_SetCurrentPosition,
5044 bytestream_wrapper_IsEndOfStream,
5045 bytestream_wrapper_Read,
5046 bytestream_wrapper_BeginRead,
5047 bytestream_wrapper_EndRead,
5048 bytestream_wrapper_Write,
5049 bytestream_wrapper_BeginWrite,
5050 bytestream_wrapper_EndWrite,
5051 bytestream_wrapper_Seek,
5052 bytestream_wrapper_Flush,
5053 bytestream_wrapper_Close,
5056 static HRESULT WINAPI bytestream_wrapper_cache_control_QueryInterface(IMFByteStreamCacheControl *iface,
5057 REFIID riid, void **obj)
5059 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
5060 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5063 static ULONG WINAPI bytestream_wrapper_cache_control_AddRef(IMFByteStreamCacheControl *iface)
5065 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
5066 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5069 static ULONG WINAPI bytestream_wrapper_cache_control_Release(IMFByteStreamCacheControl *iface)
5071 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
5072 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5075 static HRESULT WINAPI bytestream_wrapper_cache_control_StopBackgroundTransfer(IMFByteStreamCacheControl *iface)
5077 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
5079 TRACE("%p.\n", iface);
5081 return IMFByteStreamCacheControl_StopBackgroundTransfer(wrapper->cache_control);
5084 static const IMFByteStreamCacheControlVtbl bytestream_wrapper_cache_control_vtbl =
5086 bytestream_wrapper_cache_control_QueryInterface,
5087 bytestream_wrapper_cache_control_AddRef,
5088 bytestream_wrapper_cache_control_Release,
5089 bytestream_wrapper_cache_control_StopBackgroundTransfer,
5092 static HRESULT WINAPI bytestream_wrapper_buffering_QueryInterface(IMFByteStreamBuffering *iface,
5093 REFIID riid, void **obj)
5095 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5096 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5099 static ULONG WINAPI bytestream_wrapper_buffering_AddRef(IMFByteStreamBuffering *iface)
5101 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5102 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5105 static ULONG WINAPI bytestream_wrapper_buffering_Release(IMFByteStreamBuffering *iface)
5107 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5108 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5111 static HRESULT WINAPI bytestream_wrapper_buffering_SetBufferingParams(IMFByteStreamBuffering *iface,
5112 MFBYTESTREAM_BUFFERING_PARAMS *params)
5114 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5116 TRACE("%p, %p.\n", iface, params);
5118 return IMFByteStreamBuffering_SetBufferingParams(wrapper->stream_buffering, params);
5121 static HRESULT WINAPI bytestream_wrapper_buffering_EnableBuffering(IMFByteStreamBuffering *iface,
5122 BOOL enable)
5124 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5126 TRACE("%p, %d.\n", iface, enable);
5128 return IMFByteStreamBuffering_EnableBuffering(wrapper->stream_buffering, enable);
5131 static HRESULT WINAPI bytestream_wrapper_buffering_StopBuffering(IMFByteStreamBuffering *iface)
5133 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5135 TRACE("%p.\n", iface);
5137 return IMFByteStreamBuffering_StopBuffering(wrapper->stream_buffering);
5140 static const IMFByteStreamBufferingVtbl bytestream_wrapper_buffering_vtbl =
5142 bytestream_wrapper_buffering_QueryInterface,
5143 bytestream_wrapper_buffering_AddRef,
5144 bytestream_wrapper_buffering_Release,
5145 bytestream_wrapper_buffering_SetBufferingParams,
5146 bytestream_wrapper_buffering_EnableBuffering,
5147 bytestream_wrapper_buffering_StopBuffering,
5150 static HRESULT WINAPI bytestream_wrapper_timeseek_QueryInterface(IMFByteStreamTimeSeek *iface,
5151 REFIID riid, void **obj)
5153 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5154 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5157 static ULONG WINAPI bytestream_wrapper_timeseek_AddRef(IMFByteStreamTimeSeek *iface)
5159 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5160 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5163 static ULONG WINAPI bytestream_wrapper_timeseek_Release(IMFByteStreamTimeSeek *iface)
5165 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5166 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5169 static HRESULT WINAPI bytestream_wrapper_timeseek_IsTimeSeekSupported(IMFByteStreamTimeSeek *iface, BOOL *result)
5171 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5173 TRACE("%p, %p.\n", iface, result);
5175 return IMFByteStreamTimeSeek_IsTimeSeekSupported(wrapper->time_seek, result);
5178 static HRESULT WINAPI bytestream_wrapper_timeseek_TimeSeek(IMFByteStreamTimeSeek *iface, QWORD position)
5180 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5182 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
5184 return IMFByteStreamTimeSeek_TimeSeek(wrapper->time_seek, position);
5187 static HRESULT WINAPI bytestream_wrapper_timeseek_GetTimeSeekResult(IMFByteStreamTimeSeek *iface, QWORD *start_time,
5188 QWORD *stop_time, QWORD *duration)
5190 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5192 TRACE("%p, %p, %p, %p.\n", iface, start_time, stop_time, duration);
5194 return IMFByteStreamTimeSeek_GetTimeSeekResult(wrapper->time_seek, start_time, stop_time, duration);
5197 static const IMFByteStreamTimeSeekVtbl bytestream_wrapper_timeseek_vtbl =
5199 bytestream_wrapper_timeseek_QueryInterface,
5200 bytestream_wrapper_timeseek_AddRef,
5201 bytestream_wrapper_timeseek_Release,
5202 bytestream_wrapper_timeseek_IsTimeSeekSupported,
5203 bytestream_wrapper_timeseek_TimeSeek,
5204 bytestream_wrapper_timeseek_GetTimeSeekResult,
5207 static HRESULT WINAPI bytestream_wrapper_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
5209 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5210 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5213 static ULONG WINAPI bytestream_wrapper_events_AddRef(IMFMediaEventGenerator *iface)
5215 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5216 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5219 static ULONG WINAPI bytestream_wrapper_events_Release(IMFMediaEventGenerator *iface)
5221 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5222 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5225 static HRESULT WINAPI bytestream_wrapper_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
5227 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5229 TRACE("%p, %#lx, %p.\n", iface, flags, event);
5231 return IMFMediaEventGenerator_GetEvent(wrapper->event_generator, flags, event);
5234 static HRESULT WINAPI bytestream_wrapper_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback, IUnknown *state)
5236 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5238 TRACE("%p, %p, %p.\n", iface, callback, state);
5240 return IMFMediaEventGenerator_BeginGetEvent(wrapper->event_generator, callback, state);
5243 static HRESULT WINAPI bytestream_wrapper_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result, IMFMediaEvent **event)
5245 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5247 TRACE("%p, %p, %p.\n", iface, result, event);
5249 return IMFMediaEventGenerator_EndGetEvent(wrapper->event_generator, result, event);
5252 static HRESULT WINAPI bytestream_wrapper_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType type,
5253 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
5255 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5257 TRACE("%p, %ld, %s, %#lx, %s.\n", iface, type, debugstr_guid(ext_type), hr, debugstr_propvar(value));
5259 return IMFMediaEventGenerator_QueueEvent(wrapper->event_generator, type, ext_type, hr, value);
5262 static const IMFMediaEventGeneratorVtbl bytestream_wrapper_events_vtbl =
5264 bytestream_wrapper_events_QueryInterface,
5265 bytestream_wrapper_events_AddRef,
5266 bytestream_wrapper_events_Release,
5267 bytestream_wrapper_events_GetEvent,
5268 bytestream_wrapper_events_BeginGetEvent,
5269 bytestream_wrapper_events_EndGetEvent,
5270 bytestream_wrapper_events_QueueEvent,
5273 static HRESULT WINAPI bytestream_wrapper_sample_output_QueryInterface(IMFSampleOutputStream *iface, REFIID riid, void **obj)
5275 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5276 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5279 static ULONG WINAPI bytestream_wrapper_sample_output_AddRef(IMFSampleOutputStream *iface)
5281 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5282 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5285 static ULONG WINAPI bytestream_wrapper_sample_output_Release(IMFSampleOutputStream *iface)
5287 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5288 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5291 static HRESULT WINAPI bytestream_wrapper_sample_output_BeginWriteSample(IMFSampleOutputStream *iface, IMFSample *sample,
5292 IMFAsyncCallback *callback, IUnknown *state)
5294 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5296 TRACE("%p, %p, %p, %p.\n", iface, sample, callback, state);
5298 return IMFSampleOutputStream_BeginWriteSample(wrapper->sample_output, sample, callback, state);
5301 static HRESULT WINAPI bytestream_wrapper_sample_output_EndWriteSample(IMFSampleOutputStream *iface, IMFAsyncResult *result)
5303 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5305 TRACE("%p, %p.\n", iface, result);
5307 return IMFSampleOutputStream_EndWriteSample(wrapper->sample_output, result);
5310 static HRESULT WINAPI bytestream_wrapper_sample_output_Close(IMFSampleOutputStream *iface)
5312 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5314 TRACE("%p.\n", iface);
5316 return IMFSampleOutputStream_Close(wrapper->sample_output);
5319 static const IMFSampleOutputStreamVtbl bytestream_wrapper_sample_output_vtbl =
5321 bytestream_wrapper_sample_output_QueryInterface,
5322 bytestream_wrapper_sample_output_AddRef,
5323 bytestream_wrapper_sample_output_Release,
5324 bytestream_wrapper_sample_output_BeginWriteSample,
5325 bytestream_wrapper_sample_output_EndWriteSample,
5326 bytestream_wrapper_sample_output_Close,
5329 static HRESULT WINAPI bytestream_wrapper_propstore_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
5331 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5332 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5335 static ULONG WINAPI bytestream_wrapper_propstore_AddRef(IPropertyStore *iface)
5337 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5338 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5341 static ULONG WINAPI bytestream_wrapper_propstore_Release(IPropertyStore *iface)
5343 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5344 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5347 static HRESULT WINAPI bytestream_wrapper_propstore_GetCount(IPropertyStore *iface, DWORD *count)
5349 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5351 TRACE("%p, %p.\n", iface, count);
5353 return IPropertyStore_GetCount(wrapper->propstore, count);
5356 static HRESULT WINAPI bytestream_wrapper_propstore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
5358 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5360 TRACE("%p, %lu, %p.\n", iface, prop, key);
5362 return IPropertyStore_GetAt(wrapper->propstore, prop, key);
5365 static HRESULT WINAPI bytestream_wrapper_propstore_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
5367 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5369 TRACE("%p, %p, %p.\n", iface, key, value);
5371 return IPropertyStore_GetValue(wrapper->propstore, key, value);
5374 static HRESULT WINAPI bytestream_wrapper_propstore_SetValue(IPropertyStore *iface, REFPROPERTYKEY key,
5375 const PROPVARIANT *value)
5377 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5379 TRACE("%p, %p, %s.\n", iface, key, debugstr_propvar(value));
5381 return IPropertyStore_SetValue(wrapper->propstore, key, value);
5384 static HRESULT WINAPI bytestream_wrapper_propstore_Commit(IPropertyStore *iface)
5386 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5388 TRACE("%p.\n", iface);
5390 return IPropertyStore_Commit(wrapper->propstore);
5393 static const IPropertyStoreVtbl bytestream_wrapper_propstore_vtbl =
5395 bytestream_wrapper_propstore_QueryInterface,
5396 bytestream_wrapper_propstore_AddRef,
5397 bytestream_wrapper_propstore_Release,
5398 bytestream_wrapper_propstore_GetCount,
5399 bytestream_wrapper_propstore_GetAt,
5400 bytestream_wrapper_propstore_GetValue,
5401 bytestream_wrapper_propstore_SetValue,
5402 bytestream_wrapper_propstore_Commit,
5405 static HRESULT WINAPI bytestream_wrapper_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
5407 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5408 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5411 static ULONG WINAPI bytestream_wrapper_attributes_AddRef(IMFAttributes *iface)
5413 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5414 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5417 static ULONG WINAPI bytestream_wrapper_attributes_Release(IMFAttributes *iface)
5419 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5420 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5423 static HRESULT WINAPI bytestream_wrapper_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
5425 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5427 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5429 return IMFAttributes_GetItem(wrapper->attributes, key, value);
5432 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
5434 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5436 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
5438 return IMFAttributes_GetItemType(wrapper->attributes, key, type);
5441 static HRESULT WINAPI bytestream_wrapper_attributes_CompareItem(IMFAttributes *iface, REFGUID key,
5442 REFPROPVARIANT value, BOOL *result)
5444 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5446 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
5448 return IMFAttributes_CompareItem(wrapper->attributes, key, value, result);
5451 static HRESULT WINAPI bytestream_wrapper_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
5452 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
5454 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5456 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
5458 return IMFAttributes_Compare(wrapper->attributes, theirs, match_type, ret);
5461 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
5463 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5465 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5467 return IMFAttributes_GetUINT32(wrapper->attributes, key, value);
5470 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
5472 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5474 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5476 return IMFAttributes_GetUINT64(wrapper->attributes, key, value);
5479 static HRESULT WINAPI bytestream_wrapper_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
5481 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5483 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5485 return IMFAttributes_GetDouble(wrapper->attributes, key, value);
5488 static HRESULT WINAPI bytestream_wrapper_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
5490 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5492 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5494 return IMFAttributes_GetGUID(wrapper->attributes, key, value);
5497 static HRESULT WINAPI bytestream_wrapper_attributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
5499 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5501 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
5503 return IMFAttributes_GetStringLength(wrapper->attributes, key, length);
5506 static HRESULT WINAPI bytestream_wrapper_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
5507 UINT32 size, UINT32 *length)
5509 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5511 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
5513 return IMFAttributes_GetString(wrapper->attributes, key, value, size, length);
5516 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
5518 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5520 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
5522 return IMFAttributes_GetAllocatedString(wrapper->attributes, key, value, length);
5525 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
5527 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5529 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
5531 return IMFAttributes_GetBlobSize(wrapper->attributes, key, size);
5534 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
5535 UINT32 bufsize, UINT32 *blobsize)
5537 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5539 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
5541 return IMFAttributes_GetBlob(wrapper->attributes, key, buf, bufsize, blobsize);
5544 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
5546 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5548 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
5550 return IMFAttributes_GetAllocatedBlob(wrapper->attributes, key, buf, size);
5553 static HRESULT WINAPI bytestream_wrapper_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **obj)
5555 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5557 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), obj);
5559 return IMFAttributes_GetUnknown(wrapper->attributes, key, riid, obj);
5562 static HRESULT WINAPI bytestream_wrapper_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
5564 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5566 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
5568 return IMFAttributes_SetItem(wrapper->attributes, key, value);
5571 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
5573 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5575 TRACE("%p, %s.\n", iface, debugstr_attr(key));
5577 return IMFAttributes_DeleteItem(wrapper->attributes, key);
5580 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteAllItems(IMFAttributes *iface)
5582 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5584 TRACE("%p.\n", iface);
5586 return IMFAttributes_DeleteAllItems(wrapper->attributes);
5589 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
5591 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5593 TRACE("%p, %s, %d.\n", iface, debugstr_attr(key), value);
5595 return IMFAttributes_SetUINT32(wrapper->attributes, key, value);
5598 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
5600 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5602 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
5604 return IMFAttributes_SetUINT64(wrapper->attributes, key, value);
5607 static HRESULT WINAPI bytestream_wrapper_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
5609 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5611 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
5613 return IMFAttributes_SetDouble(wrapper->attributes, key, value);
5616 static HRESULT WINAPI bytestream_wrapper_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
5618 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5620 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
5622 return IMFAttributes_SetGUID(wrapper->attributes, key, value);
5625 static HRESULT WINAPI bytestream_wrapper_attributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
5627 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5629 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
5631 return IMFAttributes_SetString(wrapper->attributes, key, value);
5634 static HRESULT WINAPI bytestream_wrapper_attributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
5636 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5638 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
5640 return IMFAttributes_SetBlob(wrapper->attributes, key, buf, size);
5643 static HRESULT WINAPI bytestream_wrapper_attributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
5645 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5647 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
5649 return IMFAttributes_SetUnknown(wrapper->attributes, key, unknown);
5652 static HRESULT WINAPI bytestream_wrapper_attributes_LockStore(IMFAttributes *iface)
5654 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5656 TRACE("%p.\n", iface);
5658 return IMFAttributes_LockStore(wrapper->attributes);
5661 static HRESULT WINAPI bytestream_wrapper_attributes_UnlockStore(IMFAttributes *iface)
5663 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5665 TRACE("%p.\n", iface);
5667 return IMFAttributes_UnlockStore(wrapper->attributes);
5670 static HRESULT WINAPI bytestream_wrapper_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
5672 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5674 TRACE("%p, %p.\n", iface, count);
5676 return IMFAttributes_GetCount(wrapper->attributes, count);
5679 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
5681 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5683 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
5685 return IMFAttributes_GetItemByIndex(wrapper->attributes, index, key, value);
5688 static HRESULT WINAPI bytestream_wrapper_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
5690 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5692 TRACE("%p, %p.\n", iface, dest);
5694 return IMFAttributes_CopyAllItems(wrapper->attributes, dest);
5697 static const IMFAttributesVtbl bytestream_wrapper_attributes_vtbl =
5699 bytestream_wrapper_attributes_QueryInterface,
5700 bytestream_wrapper_attributes_AddRef,
5701 bytestream_wrapper_attributes_Release,
5702 bytestream_wrapper_attributes_GetItem,
5703 bytestream_wrapper_attributes_GetItemType,
5704 bytestream_wrapper_attributes_CompareItem,
5705 bytestream_wrapper_attributes_Compare,
5706 bytestream_wrapper_attributes_GetUINT32,
5707 bytestream_wrapper_attributes_GetUINT64,
5708 bytestream_wrapper_attributes_GetDouble,
5709 bytestream_wrapper_attributes_GetGUID,
5710 bytestream_wrapper_attributes_GetStringLength,
5711 bytestream_wrapper_attributes_GetString,
5712 bytestream_wrapper_attributes_GetAllocatedString,
5713 bytestream_wrapper_attributes_GetBlobSize,
5714 bytestream_wrapper_attributes_GetBlob,
5715 bytestream_wrapper_attributes_GetAllocatedBlob,
5716 bytestream_wrapper_attributes_GetUnknown,
5717 bytestream_wrapper_attributes_SetItem,
5718 bytestream_wrapper_attributes_DeleteItem,
5719 bytestream_wrapper_attributes_DeleteAllItems,
5720 bytestream_wrapper_attributes_SetUINT32,
5721 bytestream_wrapper_attributes_SetUINT64,
5722 bytestream_wrapper_attributes_SetDouble,
5723 bytestream_wrapper_attributes_SetGUID,
5724 bytestream_wrapper_attributes_SetString,
5725 bytestream_wrapper_attributes_SetBlob,
5726 bytestream_wrapper_attributes_SetUnknown,
5727 bytestream_wrapper_attributes_LockStore,
5728 bytestream_wrapper_attributes_UnlockStore,
5729 bytestream_wrapper_attributes_GetCount,
5730 bytestream_wrapper_attributes_GetItemByIndex,
5731 bytestream_wrapper_attributes_CopyAllItems
5734 /***********************************************************************
5735 * MFCreateMFByteStreamWrapper (mfplat.@)
5737 HRESULT WINAPI MFCreateMFByteStreamWrapper(IMFByteStream *stream, IMFByteStream **wrapper)
5739 struct bytestream_wrapper *object;
5741 TRACE("%p, %p.\n", stream, wrapper);
5743 if (!(object = calloc(1, sizeof(*object))))
5744 return E_OUTOFMEMORY;
5746 object->IMFByteStreamCacheControl_iface.lpVtbl = &bytestream_wrapper_cache_control_vtbl;
5747 object->IMFByteStreamBuffering_iface.lpVtbl = &bytestream_wrapper_buffering_vtbl;
5748 object->IMFMediaEventGenerator_iface.lpVtbl = &bytestream_wrapper_events_vtbl;
5749 object->IMFByteStreamTimeSeek_iface.lpVtbl = &bytestream_wrapper_timeseek_vtbl;
5750 object->IMFSampleOutputStream_iface.lpVtbl = &bytestream_wrapper_sample_output_vtbl;
5751 object->IMFByteStream_iface.lpVtbl = &bytestream_wrapper_vtbl;
5752 object->IPropertyStore_iface.lpVtbl = &bytestream_wrapper_propstore_vtbl;
5753 object->IMFAttributes_iface.lpVtbl = &bytestream_wrapper_attributes_vtbl;
5755 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamCacheControl, (void **)&object->cache_control);
5756 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamBuffering, (void **)&object->stream_buffering);
5757 IMFByteStream_QueryInterface(stream, &IID_IMFMediaEventGenerator, (void **)&object->event_generator);
5758 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamTimeSeek, (void **)&object->time_seek);
5759 IMFByteStream_QueryInterface(stream, &IID_IMFSampleOutputStream, (void **)&object->sample_output);
5760 IMFByteStream_QueryInterface(stream, &IID_IPropertyStore, (void **)&object->propstore);
5761 IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&object->attributes);
5763 object->stream = stream;
5764 IMFByteStream_AddRef(object->stream);
5766 object->refcount = 1;
5768 *wrapper = &object->IMFByteStream_iface;
5770 return S_OK;
5773 static HRESULT WINAPI MFPluginControl_QueryInterface(IMFPluginControl *iface, REFIID riid, void **ppv)
5775 if(IsEqualGUID(riid, &IID_IUnknown)) {
5776 TRACE("(IID_IUnknown %p)\n", ppv);
5777 *ppv = iface;
5778 }else if(IsEqualGUID(riid, &IID_IMFPluginControl)) {
5779 TRACE("(IID_IMFPluginControl %p)\n", ppv);
5780 *ppv = iface;
5781 }else {
5782 FIXME("(%s %p)\n", debugstr_guid(riid), ppv);
5783 *ppv = NULL;
5784 return E_NOINTERFACE;
5787 IUnknown_AddRef((IUnknown*)*ppv);
5788 return S_OK;
5791 static ULONG WINAPI MFPluginControl_AddRef(IMFPluginControl *iface)
5793 TRACE("\n");
5794 return 2;
5797 static ULONG WINAPI MFPluginControl_Release(IMFPluginControl *iface)
5799 TRACE("\n");
5800 return 1;
5803 static HRESULT WINAPI MFPluginControl_GetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5804 const WCHAR *selector, CLSID *clsid)
5806 FIXME("(%ld %s %p)\n", plugin_type, debugstr_w(selector), clsid);
5807 return E_NOTIMPL;
5810 static HRESULT WINAPI MFPluginControl_GetPreferredClsidByIndex(IMFPluginControl *iface, DWORD plugin_type,
5811 DWORD index, WCHAR **selector, CLSID *clsid)
5813 FIXME("(%ld %ld %p %p)\n", plugin_type, index, selector, clsid);
5814 return E_NOTIMPL;
5817 static HRESULT WINAPI MFPluginControl_SetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5818 const WCHAR *selector, const CLSID *clsid)
5820 FIXME("(%ld %s %s)\n", plugin_type, debugstr_w(selector), debugstr_guid(clsid));
5821 return E_NOTIMPL;
5824 static HRESULT WINAPI MFPluginControl_IsDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid)
5826 FIXME("(%ld %s)\n", plugin_type, debugstr_guid(clsid));
5827 return E_NOTIMPL;
5830 static HRESULT WINAPI MFPluginControl_GetDisabledByIndex(IMFPluginControl *iface, DWORD plugin_type, DWORD index, CLSID *clsid)
5832 FIXME("(%ld %ld %p)\n", plugin_type, index, clsid);
5833 return E_NOTIMPL;
5836 static HRESULT WINAPI MFPluginControl_SetDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid, BOOL disabled)
5838 FIXME("(%ld %s %x)\n", plugin_type, debugstr_guid(clsid), disabled);
5839 return E_NOTIMPL;
5842 static const IMFPluginControlVtbl MFPluginControlVtbl = {
5843 MFPluginControl_QueryInterface,
5844 MFPluginControl_AddRef,
5845 MFPluginControl_Release,
5846 MFPluginControl_GetPreferredClsid,
5847 MFPluginControl_GetPreferredClsidByIndex,
5848 MFPluginControl_SetPreferredClsid,
5849 MFPluginControl_IsDisabled,
5850 MFPluginControl_GetDisabledByIndex,
5851 MFPluginControl_SetDisabled
5854 static IMFPluginControl plugin_control = { &MFPluginControlVtbl };
5856 /***********************************************************************
5857 * MFGetPluginControl (mfplat.@)
5859 HRESULT WINAPI MFGetPluginControl(IMFPluginControl **ret)
5861 TRACE("(%p)\n", ret);
5863 *ret = &plugin_control;
5864 return S_OK;
5867 enum resolved_object_origin
5869 OBJECT_FROM_BYTESTREAM,
5870 OBJECT_FROM_URL,
5873 struct resolver_queued_result
5875 struct list entry;
5876 IUnknown *object;
5877 MF_OBJECT_TYPE obj_type;
5878 HRESULT hr;
5879 IRtwqAsyncResult *inner_result;
5880 enum resolved_object_origin origin;
5883 struct resolver_cancel_object
5885 IUnknown IUnknown_iface;
5886 LONG refcount;
5887 union
5889 IUnknown *handler;
5890 IMFByteStreamHandler *stream_handler;
5891 IMFSchemeHandler *scheme_handler;
5892 } u;
5893 IUnknown *cancel_cookie;
5894 enum resolved_object_origin origin;
5897 struct source_resolver
5899 IMFSourceResolver IMFSourceResolver_iface;
5900 LONG refcount;
5901 IRtwqAsyncCallback stream_callback;
5902 IRtwqAsyncCallback url_callback;
5903 CRITICAL_SECTION cs;
5904 struct list pending;
5907 static struct source_resolver *impl_from_IMFSourceResolver(IMFSourceResolver *iface)
5909 return CONTAINING_RECORD(iface, struct source_resolver, IMFSourceResolver_iface);
5912 static struct source_resolver *impl_from_stream_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5914 return CONTAINING_RECORD(iface, struct source_resolver, stream_callback);
5917 static struct source_resolver *impl_from_url_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5919 return CONTAINING_RECORD(iface, struct source_resolver, url_callback);
5922 static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enum resolved_object_origin origin,
5923 IRtwqAsyncResult *result)
5925 IRtwqAsyncResult *inner_result = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
5926 RTWQASYNCRESULT *data = (RTWQASYNCRESULT *)inner_result;
5927 struct resolver_queued_result *queued_result;
5928 union
5930 IUnknown *handler;
5931 IMFByteStreamHandler *stream_handler;
5932 IMFSchemeHandler *scheme_handler;
5933 } handler;
5935 if (!(queued_result = calloc(1, sizeof(*queued_result))))
5936 return E_OUTOFMEMORY;
5938 queued_result->origin = origin;
5940 IRtwqAsyncResult_GetObject(inner_result, &handler.handler);
5942 switch (origin)
5944 case OBJECT_FROM_BYTESTREAM:
5945 queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, (IMFAsyncResult *)result,
5946 &queued_result->obj_type, &queued_result->object);
5947 break;
5948 case OBJECT_FROM_URL:
5949 queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, (IMFAsyncResult *)result,
5950 &queued_result->obj_type, &queued_result->object);
5951 break;
5952 default:
5953 queued_result->hr = E_FAIL;
5956 IUnknown_Release(handler.handler);
5958 if (data->hEvent)
5960 queued_result->inner_result = inner_result;
5961 IRtwqAsyncResult_AddRef(queued_result->inner_result);
5964 /* Push resolved object type and created object, so we don't have to guess on End*() call. */
5965 EnterCriticalSection(&resolver->cs);
5966 list_add_tail(&resolver->pending, &queued_result->entry);
5967 LeaveCriticalSection(&resolver->cs);
5969 if (data->hEvent)
5970 SetEvent(data->hEvent);
5971 else
5973 IUnknown *caller_state = IRtwqAsyncResult_GetStateNoAddRef(inner_result);
5974 IRtwqAsyncResult *caller_result;
5976 if (SUCCEEDED(RtwqCreateAsyncResult(queued_result->object, data->pCallback, caller_state, &caller_result)))
5978 RtwqInvokeCallback(caller_result);
5979 IRtwqAsyncResult_Release(caller_result);
5983 return S_OK;
5986 static struct resolver_cancel_object *impl_cancel_obj_from_IUnknown(IUnknown *iface)
5988 return CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface);
5991 static HRESULT WINAPI resolver_cancel_object_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
5993 if (IsEqualIID(riid, &IID_IUnknown))
5995 *obj = iface;
5996 IUnknown_AddRef(iface);
5997 return S_OK;
6000 *obj = NULL;
6001 return E_NOINTERFACE;
6004 static ULONG WINAPI resolver_cancel_object_AddRef(IUnknown *iface)
6006 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
6007 return InterlockedIncrement(&object->refcount);
6010 static ULONG WINAPI resolver_cancel_object_Release(IUnknown *iface)
6012 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
6013 ULONG refcount = InterlockedDecrement(&object->refcount);
6015 if (!refcount)
6017 if (object->cancel_cookie)
6018 IUnknown_Release(object->cancel_cookie);
6019 IUnknown_Release(object->u.handler);
6020 free(object);
6023 return refcount;
6026 static const IUnknownVtbl resolver_cancel_object_vtbl =
6028 resolver_cancel_object_QueryInterface,
6029 resolver_cancel_object_AddRef,
6030 resolver_cancel_object_Release,
6033 static struct resolver_cancel_object *unsafe_impl_cancel_obj_from_IUnknown(IUnknown *iface)
6035 if (!iface)
6036 return NULL;
6038 return (iface->lpVtbl == &resolver_cancel_object_vtbl) ?
6039 CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface) : NULL;
6042 static HRESULT resolver_create_cancel_object(IUnknown *handler, enum resolved_object_origin origin,
6043 IUnknown *cancel_cookie, IUnknown **cancel_object)
6045 struct resolver_cancel_object *object;
6047 if (!(object = calloc(1, sizeof(*object))))
6048 return E_OUTOFMEMORY;
6050 object->IUnknown_iface.lpVtbl = &resolver_cancel_object_vtbl;
6051 object->refcount = 1;
6052 object->u.handler = handler;
6053 IUnknown_AddRef(object->u.handler);
6054 object->cancel_cookie = cancel_cookie;
6055 IUnknown_AddRef(object->cancel_cookie);
6056 object->origin = origin;
6058 *cancel_object = &object->IUnknown_iface;
6060 return S_OK;
6063 static HRESULT WINAPI source_resolver_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
6065 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
6066 IsEqualIID(riid, &IID_IUnknown))
6068 *obj = iface;
6069 IRtwqAsyncCallback_AddRef(iface);
6070 return S_OK;
6073 *obj = NULL;
6074 return E_NOINTERFACE;
6077 static ULONG WINAPI source_resolver_callback_stream_AddRef(IRtwqAsyncCallback *iface)
6079 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
6080 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
6083 static ULONG WINAPI source_resolver_callback_stream_Release(IRtwqAsyncCallback *iface)
6085 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
6086 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
6089 static HRESULT WINAPI source_resolver_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
6091 return E_NOTIMPL;
6094 static HRESULT WINAPI source_resolver_callback_stream_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
6096 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
6098 return resolver_handler_end_create(resolver, OBJECT_FROM_BYTESTREAM, result);
6101 static const IRtwqAsyncCallbackVtbl source_resolver_callback_stream_vtbl =
6103 source_resolver_callback_QueryInterface,
6104 source_resolver_callback_stream_AddRef,
6105 source_resolver_callback_stream_Release,
6106 source_resolver_callback_GetParameters,
6107 source_resolver_callback_stream_Invoke,
6110 static ULONG WINAPI source_resolver_callback_url_AddRef(IRtwqAsyncCallback *iface)
6112 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
6113 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
6116 static ULONG WINAPI source_resolver_callback_url_Release(IRtwqAsyncCallback *iface)
6118 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
6119 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
6122 static HRESULT WINAPI source_resolver_callback_url_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
6124 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
6126 return resolver_handler_end_create(resolver, OBJECT_FROM_URL, result);
6129 static const IRtwqAsyncCallbackVtbl source_resolver_callback_url_vtbl =
6131 source_resolver_callback_QueryInterface,
6132 source_resolver_callback_url_AddRef,
6133 source_resolver_callback_url_Release,
6134 source_resolver_callback_GetParameters,
6135 source_resolver_callback_url_Invoke,
6138 static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void **handler)
6140 DWORD name_length, type;
6141 HRESULT hr = E_FAIL;
6142 unsigned int j = 0;
6143 WCHAR clsidW[39];
6144 CLSID clsid;
6146 name_length = ARRAY_SIZE(clsidW);
6147 while (!RegEnumValueW(hkey, j++, clsidW, &name_length, NULL, &type, NULL, NULL))
6149 if (type == REG_SZ)
6151 if (SUCCEEDED(CLSIDFromString(clsidW, &clsid)))
6153 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, riid, handler);
6154 if (SUCCEEDED(hr))
6155 break;
6159 name_length = ARRAY_SIZE(clsidW);
6162 return hr;
6165 static HRESULT resolver_create_bytestream_handler(IMFByteStream *stream, DWORD flags, const WCHAR *mime,
6166 const WCHAR *extension, IMFByteStreamHandler **handler)
6168 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6169 HRESULT hr = E_FAIL;
6170 unsigned int i, j;
6172 *handler = NULL;
6174 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6176 struct local_handler *local_handler;
6178 EnterCriticalSection(&local_handlers_section);
6180 LIST_FOR_EACH_ENTRY(local_handler, &local_bytestream_handlers, struct local_handler, entry)
6182 if ((mime && !lstrcmpiW(mime, local_handler->u.bytestream.mime))
6183 || (extension && !lstrcmpiW(extension, local_handler->u.bytestream.extension)))
6185 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFByteStreamHandler,
6186 (void **)handler)))
6187 break;
6191 LeaveCriticalSection(&local_handlers_section);
6193 if (*handler)
6194 return hr;
6197 for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i)
6199 const WCHAR *namesW[2] = { mime, extension };
6200 HKEY hkey, hkey_handler;
6202 if (RegOpenKeyW(hkey_roots[i], L"Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers", &hkey))
6203 continue;
6205 for (j = 0; j < ARRAY_SIZE(namesW); ++j)
6207 if (!namesW[j])
6208 continue;
6210 if (!RegOpenKeyW(hkey, namesW[j], &hkey_handler))
6212 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFByteStreamHandler, (void **)handler);
6213 RegCloseKey(hkey_handler);
6216 if (SUCCEEDED(hr))
6217 break;
6220 RegCloseKey(hkey);
6222 if (SUCCEEDED(hr))
6223 break;
6226 return hr;
6229 static HRESULT resolver_get_bytestream_url_hint(IMFByteStream *stream, WCHAR const **url)
6231 static const unsigned char asfmagic[] = {0x30,0x26,0xb2,0x75,0x8e,0x66,0xcf,0x11,0xa6,0xd9,0x00,0xaa,0x00,0x62,0xce,0x6c};
6232 static const unsigned char wavmagic[] = { 'R', 'I', 'F', 'F',0x00,0x00,0x00,0x00, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' '};
6233 static const unsigned char wavmask[] = {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
6234 static const unsigned char isommagic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'i', 's', 'o', 'm',0x00,0x00,0x00,0x00};
6235 static const unsigned char mp4_magic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'M', 'S', 'N', 'V',0x00,0x00,0x00,0x00};
6236 static const unsigned char mp42magic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'm', 'p', '4', '2',0x00,0x00,0x00,0x00};
6237 static const unsigned char mp4vmagic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'M', '4', 'V', ' ',0x00,0x00,0x00,0x00};
6238 static const unsigned char mp4mask[] = {0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00};
6239 static const struct stream_content_url_hint
6241 const unsigned char *magic;
6242 const WCHAR *url;
6243 const unsigned char *mask;
6245 url_hints[] =
6247 { asfmagic, L".asf" },
6248 { wavmagic, L".wav", wavmask },
6249 { isommagic, L".mp4", mp4mask },
6250 { mp42magic, L".mp4", mp4mask },
6251 { mp4_magic, L".mp4", mp4mask },
6252 { mp4vmagic, L".m4v", mp4mask },
6254 unsigned char buffer[4 * sizeof(unsigned int)], pattern[4 * sizeof(unsigned int)];
6255 IMFAttributes *attributes;
6256 DWORD length = 0, caps = 0;
6257 unsigned int i, j;
6258 QWORD position;
6259 HRESULT hr;
6261 *url = NULL;
6263 if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
6265 UINT32 string_length = 0;
6266 IMFAttributes_GetStringLength(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &string_length);
6267 IMFAttributes_Release(attributes);
6269 if (string_length)
6270 return S_OK;
6273 if (FAILED(hr = IMFByteStream_GetCapabilities(stream, &caps)))
6274 return hr;
6276 if (!(caps & MFBYTESTREAM_IS_SEEKABLE))
6277 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6279 if (FAILED(hr = IMFByteStream_GetCurrentPosition(stream, &position)))
6280 return hr;
6282 hr = IMFByteStream_Read(stream, buffer, sizeof(buffer), &length);
6283 IMFByteStream_SetCurrentPosition(stream, position);
6284 if (FAILED(hr))
6285 return hr;
6287 if (length < sizeof(buffer))
6288 return S_OK;
6290 for (i = 0; i < ARRAY_SIZE(url_hints); ++i)
6292 memcpy(pattern, buffer, sizeof(buffer));
6293 if (url_hints[i].mask)
6295 unsigned int *mask = (unsigned int *)url_hints[i].mask;
6296 unsigned int *data = (unsigned int *)pattern;
6298 for (j = 0; j < sizeof(buffer) / sizeof(unsigned int); ++j)
6299 data[j] &= mask[j];
6302 if (!memcmp(pattern, url_hints[i].magic, sizeof(pattern)))
6304 *url = url_hints[i].url;
6305 break;
6309 if (*url)
6310 TRACE("Content type guessed as %s from %s.\n", debugstr_w(*url), debugstr_an((char *)buffer, length));
6311 else
6312 WARN("Unrecognized content type %s.\n", debugstr_an((char *)buffer, length));
6314 return S_OK;
6317 static HRESULT resolver_create_gstreamer_handler(IMFByteStreamHandler **handler)
6319 static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
6320 return CoCreateInstance(&CLSID_GStreamerByteStreamHandler, NULL, CLSCTX_INPROC_SERVER, &IID_IMFByteStreamHandler, (void **)handler);
6323 static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags,
6324 IMFByteStreamHandler **handler)
6326 WCHAR *mimeW = NULL, *urlW = NULL;
6327 IMFAttributes *attributes;
6328 const WCHAR *url_ext;
6329 HRESULT hr = E_FAIL;
6330 UINT32 length;
6332 *handler = NULL;
6334 /* MIME type */
6335 if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
6337 IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length);
6338 if (!url)
6340 IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_ORIGIN_NAME, &urlW, &length);
6341 url = urlW;
6343 IMFAttributes_Release(attributes);
6346 /* Extension */
6347 url_ext = url ? wcsrchr(url, '.') : NULL;
6349 /* If content type was provided by the caller, it's tried first. Otherwise an attempt to deduce
6350 content type from the content itself is made.
6352 TODO: wine specific fallback to predefined handler could be replaced by normally registering
6353 this handler for all possible types.
6356 if (url_ext || mimeW)
6358 hr = resolver_create_bytestream_handler(stream, flags, mimeW, url_ext, handler);
6360 if (FAILED(hr))
6361 hr = resolver_create_gstreamer_handler(handler);
6364 CoTaskMemFree(mimeW);
6365 CoTaskMemFree(urlW);
6367 if (SUCCEEDED(hr))
6368 return hr;
6370 if (!(flags & MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE))
6371 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6373 if (FAILED(hr = resolver_get_bytestream_url_hint(stream, &url_ext)))
6374 return hr;
6376 hr = resolver_create_bytestream_handler(stream, flags, NULL, url_ext, handler);
6378 if (FAILED(hr))
6379 hr = resolver_create_gstreamer_handler(handler);
6381 return hr;
6384 static HRESULT resolver_create_scheme_handler(const WCHAR *scheme, DWORD flags, IMFSchemeHandler **handler)
6386 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6387 HRESULT hr = MF_E_UNSUPPORTED_SCHEME;
6388 unsigned int i;
6390 TRACE("%s, %#lx, %p.\n", debugstr_w(scheme), flags, handler);
6392 *handler = NULL;
6394 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6396 struct local_handler *local_handler;
6398 EnterCriticalSection(&local_handlers_section);
6400 LIST_FOR_EACH_ENTRY(local_handler, &local_scheme_handlers, struct local_handler, entry)
6402 if (!lstrcmpiW(scheme, local_handler->u.scheme))
6404 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFSchemeHandler,
6405 (void **)handler)))
6406 break;
6410 LeaveCriticalSection(&local_handlers_section);
6412 if (*handler)
6413 return hr;
6416 for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
6418 HKEY hkey, hkey_handler;
6420 hr = MF_E_UNSUPPORTED_SCHEME;
6422 if (RegOpenKeyW(hkey_roots[i], L"Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers", &hkey))
6423 continue;
6425 if (!RegOpenKeyW(hkey, scheme, &hkey_handler))
6427 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFSchemeHandler, (void **)handler);
6428 RegCloseKey(hkey_handler);
6431 RegCloseKey(hkey);
6433 if (SUCCEEDED(hr))
6434 break;
6437 return hr;
6440 static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSchemeHandler **handler)
6442 static const WCHAR fileschemeW[] = L"file:";
6443 const WCHAR *ptr = url;
6444 unsigned int len;
6445 WCHAR *scheme;
6446 HRESULT hr;
6448 /* RFC 3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
6449 while (*ptr)
6451 WCHAR ch = towlower(*ptr);
6453 if (*ptr == '*' && ptr == url)
6455 ptr++;
6456 break;
6458 else if (!(*ptr >= '0' && *ptr <= '9') &&
6459 !(ch >= 'a' && ch <= 'z') &&
6460 *ptr != '+' && *ptr != '-' && *ptr != '.')
6462 break;
6465 ptr++;
6468 /* Schemes must end with a ':', if not found try "file:" */
6469 if (ptr == url || *ptr != ':')
6471 url = fileschemeW;
6472 len = ARRAY_SIZE(fileschemeW) - 1;
6474 else
6475 len = ptr - url + 1;
6477 scheme = malloc((len + 1) * sizeof(WCHAR));
6478 if (!scheme)
6479 return E_OUTOFMEMORY;
6481 memcpy(scheme, url, len * sizeof(WCHAR));
6482 scheme[len] = 0;
6484 hr = resolver_create_scheme_handler(scheme, flags, handler);
6485 if (FAILED(hr) && url != fileschemeW)
6486 hr = resolver_create_scheme_handler(fileschemeW, flags, handler);
6488 free(scheme);
6490 return hr;
6493 static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum resolved_object_origin origin,
6494 IRtwqAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out)
6496 struct resolver_queued_result *queued_result = NULL, *iter;
6497 IUnknown *object;
6498 HRESULT hr;
6500 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
6501 return hr;
6503 EnterCriticalSection(&resolver->cs);
6505 LIST_FOR_EACH_ENTRY(iter, &resolver->pending, struct resolver_queued_result, entry)
6507 if (iter->inner_result == result || (iter->object == object && iter->origin == origin))
6509 list_remove(&iter->entry);
6510 queued_result = iter;
6511 break;
6515 LeaveCriticalSection(&resolver->cs);
6517 IUnknown_Release(object);
6519 if (queued_result)
6521 *out = queued_result->object;
6522 *obj_type = queued_result->obj_type;
6523 hr = queued_result->hr;
6524 if (queued_result->inner_result)
6525 IRtwqAsyncResult_Release(queued_result->inner_result);
6526 free(queued_result);
6528 else
6529 hr = E_UNEXPECTED;
6531 return hr;
6534 static HRESULT WINAPI source_resolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj)
6536 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6538 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
6540 if (IsEqualIID(riid, &IID_IMFSourceResolver) ||
6541 IsEqualIID(riid, &IID_IUnknown))
6543 *obj = &resolver->IMFSourceResolver_iface;
6545 else
6547 *obj = NULL;
6548 FIXME("unsupported interface %s\n", debugstr_guid(riid));
6549 return E_NOINTERFACE;
6552 IUnknown_AddRef((IUnknown *)*obj);
6553 return S_OK;
6556 static ULONG WINAPI source_resolver_AddRef(IMFSourceResolver *iface)
6558 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6559 ULONG refcount = InterlockedIncrement(&resolver->refcount);
6561 TRACE("%p, refcount %ld.\n", iface, refcount);
6563 return refcount;
6566 static ULONG WINAPI source_resolver_Release(IMFSourceResolver *iface)
6568 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6569 ULONG refcount = InterlockedDecrement(&resolver->refcount);
6570 struct resolver_queued_result *result, *result2;
6572 TRACE("%p, refcount %ld.\n", iface, refcount);
6574 if (!refcount)
6576 LIST_FOR_EACH_ENTRY_SAFE(result, result2, &resolver->pending, struct resolver_queued_result, entry)
6578 if (result->object)
6579 IUnknown_Release(result->object);
6580 list_remove(&result->entry);
6581 free(result);
6583 DeleteCriticalSection(&resolver->cs);
6584 free(resolver);
6587 return refcount;
6590 static HRESULT WINAPI source_resolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6591 DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6593 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6594 IMFSchemeHandler *handler;
6595 IRtwqAsyncResult *result;
6596 RTWQASYNCRESULT *data;
6597 HRESULT hr;
6599 TRACE("%p, %s, %#lx, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, obj_type, object);
6601 if (!url || !obj_type || !object)
6602 return E_POINTER;
6604 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6605 return hr;
6607 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6608 IMFSchemeHandler_Release(handler);
6609 if (FAILED(hr))
6610 return hr;
6612 data = (RTWQASYNCRESULT *)result;
6613 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6615 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, NULL, (IMFAsyncCallback *)&resolver->url_callback,
6616 (IUnknown *)result);
6617 if (FAILED(hr))
6619 IRtwqAsyncResult_Release(result);
6620 return hr;
6623 WaitForSingleObject(data->hEvent, INFINITE);
6625 hr = resolver_end_create_object(resolver, OBJECT_FROM_URL, result, obj_type, object);
6626 IRtwqAsyncResult_Release(result);
6628 return hr;
6631 static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6632 const WCHAR *url, DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6634 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6635 IMFByteStreamHandler *handler;
6636 IRtwqAsyncResult *result;
6637 RTWQASYNCRESULT *data;
6638 HRESULT hr;
6640 TRACE("%p, %p, %s, %#lx, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, obj_type, object);
6642 if (!stream || !obj_type || !object)
6643 return E_POINTER;
6645 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6646 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6648 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6649 IMFByteStreamHandler_Release(handler);
6650 if (FAILED(hr))
6651 return hr;
6653 data = (RTWQASYNCRESULT *)result;
6654 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6656 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props, NULL,
6657 (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6658 if (FAILED(hr))
6660 IRtwqAsyncResult_Release(result);
6661 return hr;
6664 WaitForSingleObject(data->hEvent, INFINITE);
6666 hr = resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, result, obj_type, object);
6667 IRtwqAsyncResult_Release(result);
6669 return hr;
6672 static HRESULT WINAPI source_resolver_BeginCreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6673 DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
6675 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6676 IMFSchemeHandler *handler;
6677 IUnknown *inner_cookie = NULL;
6678 IRtwqAsyncResult *result;
6679 HRESULT hr;
6681 TRACE("%p, %s, %#lx, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
6683 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6684 return hr;
6686 if (cancel_cookie)
6687 *cancel_cookie = NULL;
6689 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6690 IMFSchemeHandler_Release(handler);
6691 if (FAILED(hr))
6692 return hr;
6694 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, cancel_cookie ? &inner_cookie : NULL,
6695 (IMFAsyncCallback *)&resolver->url_callback, (IUnknown *)result);
6697 if (SUCCEEDED(hr) && inner_cookie)
6698 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_URL, inner_cookie, cancel_cookie);
6700 IRtwqAsyncResult_Release(result);
6702 return hr;
6705 static HRESULT WINAPI source_resolver_EndCreateObjectFromURL(IMFSourceResolver *iface, IMFAsyncResult *result,
6706 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6708 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6710 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6712 return resolver_end_create_object(resolver, OBJECT_FROM_URL, (IRtwqAsyncResult *)result, obj_type, object);
6715 static HRESULT WINAPI source_resolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6716 const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback,
6717 IUnknown *state)
6719 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6720 IMFByteStreamHandler *handler;
6721 IUnknown *inner_cookie = NULL;
6722 IRtwqAsyncResult *result;
6723 HRESULT hr;
6725 TRACE("%p, %p, %s, %#lx, %p, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, cancel_cookie,
6726 callback, state);
6728 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6729 return hr;
6731 if (cancel_cookie)
6732 *cancel_cookie = NULL;
6734 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6735 IMFByteStreamHandler_Release(handler);
6736 if (FAILED(hr))
6737 return hr;
6739 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props,
6740 cancel_cookie ? &inner_cookie : NULL, (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6742 /* Cancel object wraps underlying handler cancel cookie with context necessary to call CancelObjectCreate(). */
6743 if (SUCCEEDED(hr) && inner_cookie)
6744 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_BYTESTREAM, inner_cookie, cancel_cookie);
6746 IRtwqAsyncResult_Release(result);
6748 return hr;
6751 static HRESULT WINAPI source_resolver_EndCreateObjectFromByteStream(IMFSourceResolver *iface, IMFAsyncResult *result,
6752 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6754 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6756 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6758 return resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, (IRtwqAsyncResult *)result, obj_type, object);
6761 static HRESULT WINAPI source_resolver_CancelObjectCreation(IMFSourceResolver *iface, IUnknown *cancel_cookie)
6763 struct resolver_cancel_object *object;
6764 HRESULT hr;
6766 TRACE("%p, %p.\n", iface, cancel_cookie);
6768 if (!(object = unsafe_impl_cancel_obj_from_IUnknown(cancel_cookie)))
6769 return E_UNEXPECTED;
6771 switch (object->origin)
6773 case OBJECT_FROM_BYTESTREAM:
6774 hr = IMFByteStreamHandler_CancelObjectCreation(object->u.stream_handler, object->cancel_cookie);
6775 break;
6776 case OBJECT_FROM_URL:
6777 hr = IMFSchemeHandler_CancelObjectCreation(object->u.scheme_handler, object->cancel_cookie);
6778 break;
6779 default:
6780 hr = E_UNEXPECTED;
6783 return hr;
6786 static const IMFSourceResolverVtbl mfsourceresolvervtbl =
6788 source_resolver_QueryInterface,
6789 source_resolver_AddRef,
6790 source_resolver_Release,
6791 source_resolver_CreateObjectFromURL,
6792 source_resolver_CreateObjectFromByteStream,
6793 source_resolver_BeginCreateObjectFromURL,
6794 source_resolver_EndCreateObjectFromURL,
6795 source_resolver_BeginCreateObjectFromByteStream,
6796 source_resolver_EndCreateObjectFromByteStream,
6797 source_resolver_CancelObjectCreation,
6800 /***********************************************************************
6801 * MFCreateSourceResolver (mfplat.@)
6803 HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver)
6805 struct source_resolver *object;
6807 TRACE("%p\n", resolver);
6809 if (!resolver)
6810 return E_POINTER;
6812 if (!(object = calloc(1, sizeof(*object))))
6813 return E_OUTOFMEMORY;
6815 object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl;
6816 object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl;
6817 object->url_callback.lpVtbl = &source_resolver_callback_url_vtbl;
6818 object->refcount = 1;
6819 list_init(&object->pending);
6820 InitializeCriticalSection(&object->cs);
6822 *resolver = &object->IMFSourceResolver_iface;
6824 return S_OK;
6827 struct media_event
6829 struct attributes attributes;
6830 IMFMediaEvent IMFMediaEvent_iface;
6832 MediaEventType type;
6833 GUID extended_type;
6834 HRESULT status;
6835 PROPVARIANT value;
6838 static inline struct media_event *impl_from_IMFMediaEvent(IMFMediaEvent *iface)
6840 return CONTAINING_RECORD(iface, struct media_event, IMFMediaEvent_iface);
6843 static HRESULT WINAPI mfmediaevent_QueryInterface(IMFMediaEvent *iface, REFIID riid, void **out)
6845 struct media_event *event = impl_from_IMFMediaEvent(iface);
6847 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
6849 if(IsEqualGUID(riid, &IID_IUnknown) ||
6850 IsEqualGUID(riid, &IID_IMFAttributes) ||
6851 IsEqualGUID(riid, &IID_IMFMediaEvent))
6853 *out = &event->IMFMediaEvent_iface;
6855 else
6857 FIXME("%s, %p.\n", debugstr_guid(riid), out);
6858 *out = NULL;
6859 return E_NOINTERFACE;
6862 IUnknown_AddRef((IUnknown*)*out);
6863 return S_OK;
6866 static ULONG WINAPI mfmediaevent_AddRef(IMFMediaEvent *iface)
6868 struct media_event *event = impl_from_IMFMediaEvent(iface);
6869 ULONG refcount = InterlockedIncrement(&event->attributes.ref);
6871 TRACE("%p, refcount %lu.\n", iface, refcount);
6873 return refcount;
6876 static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface)
6878 struct media_event *event = impl_from_IMFMediaEvent(iface);
6879 ULONG refcount = InterlockedDecrement(&event->attributes.ref);
6881 TRACE("%p, refcount %lu.\n", iface, refcount);
6883 if (!refcount)
6885 clear_attributes_object(&event->attributes);
6886 PropVariantClear(&event->value);
6887 free(event);
6890 return refcount;
6893 static HRESULT WINAPI mfmediaevent_GetItem(IMFMediaEvent *iface, REFGUID key, PROPVARIANT *value)
6895 struct media_event *event = impl_from_IMFMediaEvent(iface);
6897 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6899 return attributes_GetItem(&event->attributes, key, value);
6902 static HRESULT WINAPI mfmediaevent_GetItemType(IMFMediaEvent *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
6904 struct media_event *event = impl_from_IMFMediaEvent(iface);
6906 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
6908 return attributes_GetItemType(&event->attributes, key, type);
6911 static HRESULT WINAPI mfmediaevent_CompareItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
6913 struct media_event *event = impl_from_IMFMediaEvent(iface);
6915 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
6917 return attributes_CompareItem(&event->attributes, key, value, result);
6920 static HRESULT WINAPI mfmediaevent_Compare(IMFMediaEvent *iface, IMFAttributes *attrs, MF_ATTRIBUTES_MATCH_TYPE type,
6921 BOOL *result)
6923 struct media_event *event = impl_from_IMFMediaEvent(iface);
6925 TRACE("%p, %p, %d, %p.\n", iface, attrs, type, result);
6927 return attributes_Compare(&event->attributes, attrs, type, result);
6930 static HRESULT WINAPI mfmediaevent_GetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 *value)
6932 struct media_event *event = impl_from_IMFMediaEvent(iface);
6934 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6936 return attributes_GetUINT32(&event->attributes, key, value);
6939 static HRESULT WINAPI mfmediaevent_GetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 *value)
6941 struct media_event *event = impl_from_IMFMediaEvent(iface);
6943 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6945 return attributes_GetUINT64(&event->attributes, key, value);
6948 static HRESULT WINAPI mfmediaevent_GetDouble(IMFMediaEvent *iface, REFGUID key, double *value)
6950 struct media_event *event = impl_from_IMFMediaEvent(iface);
6952 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6954 return attributes_GetDouble(&event->attributes, key, value);
6957 static HRESULT WINAPI mfmediaevent_GetGUID(IMFMediaEvent *iface, REFGUID key, GUID *value)
6959 struct media_event *event = impl_from_IMFMediaEvent(iface);
6961 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6963 return attributes_GetGUID(&event->attributes, key, value);
6966 static HRESULT WINAPI mfmediaevent_GetStringLength(IMFMediaEvent *iface, REFGUID key, UINT32 *length)
6968 struct media_event *event = impl_from_IMFMediaEvent(iface);
6970 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
6972 return attributes_GetStringLength(&event->attributes, key, length);
6975 static HRESULT WINAPI mfmediaevent_GetString(IMFMediaEvent *iface, REFGUID key, WCHAR *value,
6976 UINT32 size, UINT32 *length)
6978 struct media_event *event = impl_from_IMFMediaEvent(iface);
6980 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), value, size, length);
6982 return attributes_GetString(&event->attributes, key, value, size, length);
6985 static HRESULT WINAPI mfmediaevent_GetAllocatedString(IMFMediaEvent *iface, REFGUID key,
6986 WCHAR **value, UINT32 *length)
6988 struct media_event *event = impl_from_IMFMediaEvent(iface);
6990 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
6992 return attributes_GetAllocatedString(&event->attributes, key, value, length);
6995 static HRESULT WINAPI mfmediaevent_GetBlobSize(IMFMediaEvent *iface, REFGUID key, UINT32 *size)
6997 struct media_event *event = impl_from_IMFMediaEvent(iface);
6999 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
7001 return attributes_GetBlobSize(&event->attributes, key, size);
7004 static HRESULT WINAPI mfmediaevent_GetBlob(IMFMediaEvent *iface, REFGUID key, UINT8 *buf,
7005 UINT32 bufsize, UINT32 *blobsize)
7007 struct media_event *event = impl_from_IMFMediaEvent(iface);
7009 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
7011 return attributes_GetBlob(&event->attributes, key, buf, bufsize, blobsize);
7014 static HRESULT WINAPI mfmediaevent_GetAllocatedBlob(IMFMediaEvent *iface, REFGUID key, UINT8 **buf, UINT32 *size)
7016 struct media_event *event = impl_from_IMFMediaEvent(iface);
7018 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
7020 return attributes_GetAllocatedBlob(&event->attributes, key, buf, size);
7023 static HRESULT WINAPI mfmediaevent_GetUnknown(IMFMediaEvent *iface, REFGUID key, REFIID riid, void **out)
7025 struct media_event *event = impl_from_IMFMediaEvent(iface);
7027 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
7029 return attributes_GetUnknown(&event->attributes, key, riid, out);
7032 static HRESULT WINAPI mfmediaevent_SetItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value)
7034 struct media_event *event = impl_from_IMFMediaEvent(iface);
7036 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
7038 return attributes_SetItem(&event->attributes, key, value);
7041 static HRESULT WINAPI mfmediaevent_DeleteItem(IMFMediaEvent *iface, REFGUID key)
7043 struct media_event *event = impl_from_IMFMediaEvent(iface);
7045 TRACE("%p, %s.\n", iface, debugstr_attr(key));
7047 return attributes_DeleteItem(&event->attributes, key);
7050 static HRESULT WINAPI mfmediaevent_DeleteAllItems(IMFMediaEvent *iface)
7052 struct media_event *event = impl_from_IMFMediaEvent(iface);
7054 TRACE("%p.\n", iface);
7056 return attributes_DeleteAllItems(&event->attributes);
7059 static HRESULT WINAPI mfmediaevent_SetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 value)
7061 struct media_event *event = impl_from_IMFMediaEvent(iface);
7063 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
7065 return attributes_SetUINT32(&event->attributes, key, value);
7068 static HRESULT WINAPI mfmediaevent_SetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 value)
7070 struct media_event *event = impl_from_IMFMediaEvent(iface);
7072 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
7074 return attributes_SetUINT64(&event->attributes, key, value);
7077 static HRESULT WINAPI mfmediaevent_SetDouble(IMFMediaEvent *iface, REFGUID key, double value)
7079 struct media_event *event = impl_from_IMFMediaEvent(iface);
7081 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
7083 return attributes_SetDouble(&event->attributes, key, value);
7086 static HRESULT WINAPI mfmediaevent_SetGUID(IMFMediaEvent *iface, REFGUID key, REFGUID value)
7088 struct media_event *event = impl_from_IMFMediaEvent(iface);
7090 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
7092 return attributes_SetGUID(&event->attributes, key, value);
7095 static HRESULT WINAPI mfmediaevent_SetString(IMFMediaEvent *iface, REFGUID key, const WCHAR *value)
7097 struct media_event *event = impl_from_IMFMediaEvent(iface);
7099 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
7101 return attributes_SetString(&event->attributes, key, value);
7104 static HRESULT WINAPI mfmediaevent_SetBlob(IMFMediaEvent *iface, REFGUID key, const UINT8 *buf, UINT32 size)
7106 struct media_event *event = impl_from_IMFMediaEvent(iface);
7108 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
7110 return attributes_SetBlob(&event->attributes, key, buf, size);
7113 static HRESULT WINAPI mfmediaevent_SetUnknown(IMFMediaEvent *iface, REFGUID key, IUnknown *unknown)
7115 struct media_event *event = impl_from_IMFMediaEvent(iface);
7117 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
7119 return attributes_SetUnknown(&event->attributes, key, unknown);
7122 static HRESULT WINAPI mfmediaevent_LockStore(IMFMediaEvent *iface)
7124 struct media_event *event = impl_from_IMFMediaEvent(iface);
7126 TRACE("%p.\n", iface);
7128 return attributes_LockStore(&event->attributes);
7131 static HRESULT WINAPI mfmediaevent_UnlockStore(IMFMediaEvent *iface)
7133 struct media_event *event = impl_from_IMFMediaEvent(iface);
7135 TRACE("%p.\n", iface);
7137 return attributes_UnlockStore(&event->attributes);
7140 static HRESULT WINAPI mfmediaevent_GetCount(IMFMediaEvent *iface, UINT32 *count)
7142 struct media_event *event = impl_from_IMFMediaEvent(iface);
7144 TRACE("%p, %p.\n", iface, count);
7146 return attributes_GetCount(&event->attributes, count);
7149 static HRESULT WINAPI mfmediaevent_GetItemByIndex(IMFMediaEvent *iface, UINT32 index, GUID *key, PROPVARIANT *value)
7151 struct media_event *event = impl_from_IMFMediaEvent(iface);
7153 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
7155 return attributes_GetItemByIndex(&event->attributes, index, key, value);
7158 static HRESULT WINAPI mfmediaevent_CopyAllItems(IMFMediaEvent *iface, IMFAttributes *dest)
7160 struct media_event *event = impl_from_IMFMediaEvent(iface);
7162 TRACE("%p, %p.\n", iface, dest);
7164 return attributes_CopyAllItems(&event->attributes, dest);
7167 static HRESULT WINAPI mfmediaevent_GetType(IMFMediaEvent *iface, MediaEventType *type)
7169 struct media_event *event = impl_from_IMFMediaEvent(iface);
7171 TRACE("%p, %p.\n", iface, type);
7173 *type = event->type;
7175 return S_OK;
7178 static HRESULT WINAPI mfmediaevent_GetExtendedType(IMFMediaEvent *iface, GUID *extended_type)
7180 struct media_event *event = impl_from_IMFMediaEvent(iface);
7182 TRACE("%p, %p.\n", iface, extended_type);
7184 *extended_type = event->extended_type;
7186 return S_OK;
7189 static HRESULT WINAPI mfmediaevent_GetStatus(IMFMediaEvent *iface, HRESULT *status)
7191 struct media_event *event = impl_from_IMFMediaEvent(iface);
7193 TRACE("%p, %p.\n", iface, status);
7195 *status = event->status;
7197 return S_OK;
7200 static HRESULT WINAPI mfmediaevent_GetValue(IMFMediaEvent *iface, PROPVARIANT *value)
7202 struct media_event *event = impl_from_IMFMediaEvent(iface);
7204 TRACE("%p, %p.\n", iface, value);
7206 PropVariantCopy(value, &event->value);
7208 return S_OK;
7211 static const IMFMediaEventVtbl mfmediaevent_vtbl =
7213 mfmediaevent_QueryInterface,
7214 mfmediaevent_AddRef,
7215 mfmediaevent_Release,
7216 mfmediaevent_GetItem,
7217 mfmediaevent_GetItemType,
7218 mfmediaevent_CompareItem,
7219 mfmediaevent_Compare,
7220 mfmediaevent_GetUINT32,
7221 mfmediaevent_GetUINT64,
7222 mfmediaevent_GetDouble,
7223 mfmediaevent_GetGUID,
7224 mfmediaevent_GetStringLength,
7225 mfmediaevent_GetString,
7226 mfmediaevent_GetAllocatedString,
7227 mfmediaevent_GetBlobSize,
7228 mfmediaevent_GetBlob,
7229 mfmediaevent_GetAllocatedBlob,
7230 mfmediaevent_GetUnknown,
7231 mfmediaevent_SetItem,
7232 mfmediaevent_DeleteItem,
7233 mfmediaevent_DeleteAllItems,
7234 mfmediaevent_SetUINT32,
7235 mfmediaevent_SetUINT64,
7236 mfmediaevent_SetDouble,
7237 mfmediaevent_SetGUID,
7238 mfmediaevent_SetString,
7239 mfmediaevent_SetBlob,
7240 mfmediaevent_SetUnknown,
7241 mfmediaevent_LockStore,
7242 mfmediaevent_UnlockStore,
7243 mfmediaevent_GetCount,
7244 mfmediaevent_GetItemByIndex,
7245 mfmediaevent_CopyAllItems,
7246 mfmediaevent_GetType,
7247 mfmediaevent_GetExtendedType,
7248 mfmediaevent_GetStatus,
7249 mfmediaevent_GetValue,
7252 /***********************************************************************
7253 * MFCreateMediaEvent (mfplat.@)
7255 HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HRESULT status, const PROPVARIANT *value,
7256 IMFMediaEvent **event)
7258 struct media_event *object;
7259 HRESULT hr;
7261 TRACE("%s, %s, %#lx, %s, %p.\n", debugstr_eventid(type), debugstr_guid(extended_type), status,
7262 debugstr_propvar(value), event);
7264 object = malloc(sizeof(*object));
7265 if (!object)
7266 return E_OUTOFMEMORY;
7268 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
7270 free(object);
7271 return hr;
7273 object->IMFMediaEvent_iface.lpVtbl = &mfmediaevent_vtbl;
7275 object->type = type;
7276 object->extended_type = *extended_type;
7277 object->status = status;
7279 PropVariantInit(&object->value);
7280 if (value)
7281 PropVariantCopy(&object->value, value);
7283 *event = &object->IMFMediaEvent_iface;
7285 TRACE("Created event %p.\n", *event);
7287 return S_OK;
7290 struct event_queue
7292 IMFMediaEventQueue IMFMediaEventQueue_iface;
7293 LONG refcount;
7295 CRITICAL_SECTION cs;
7296 CONDITION_VARIABLE update_event;
7297 struct list events;
7298 BOOL is_shut_down;
7299 BOOL notified;
7300 IRtwqAsyncResult *subscriber;
7303 struct queued_event
7305 struct list entry;
7306 IMFMediaEvent *event;
7309 static inline struct event_queue *impl_from_IMFMediaEventQueue(IMFMediaEventQueue *iface)
7311 return CONTAINING_RECORD(iface, struct event_queue, IMFMediaEventQueue_iface);
7314 static IMFMediaEvent *queue_pop_event(struct event_queue *queue)
7316 struct list *head = list_head(&queue->events);
7317 struct queued_event *queued_event;
7318 IMFMediaEvent *event;
7320 if (!head)
7321 return NULL;
7323 queued_event = LIST_ENTRY(head, struct queued_event, entry);
7324 event = queued_event->event;
7325 list_remove(&queued_event->entry);
7326 free(queued_event);
7327 return event;
7330 static void event_queue_clear_subscriber(struct event_queue *queue)
7332 if (queue->subscriber)
7333 IRtwqAsyncResult_Release(queue->subscriber);
7334 queue->subscriber = NULL;
7337 static void event_queue_cleanup(struct event_queue *queue)
7339 IMFMediaEvent *event;
7341 while ((event = queue_pop_event(queue)))
7342 IMFMediaEvent_Release(event);
7343 event_queue_clear_subscriber(queue);
7346 static HRESULT WINAPI eventqueue_QueryInterface(IMFMediaEventQueue *iface, REFIID riid, void **out)
7348 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7350 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7352 if (IsEqualIID(riid, &IID_IMFMediaEventQueue) ||
7353 IsEqualIID(riid, &IID_IUnknown))
7355 *out = &queue->IMFMediaEventQueue_iface;
7356 IMFMediaEventQueue_AddRef(iface);
7357 return S_OK;
7360 WARN("Unsupported %s.\n", debugstr_guid(riid));
7361 *out = NULL;
7362 return E_NOINTERFACE;
7365 static ULONG WINAPI eventqueue_AddRef(IMFMediaEventQueue *iface)
7367 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7368 ULONG refcount = InterlockedIncrement(&queue->refcount);
7370 TRACE("%p, refcount %lu.\n", iface, refcount);
7372 return refcount;
7375 static ULONG WINAPI eventqueue_Release(IMFMediaEventQueue *iface)
7377 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7378 ULONG refcount = InterlockedDecrement(&queue->refcount);
7380 TRACE("%p, refcount %lu.\n", queue, refcount);
7382 if (!refcount)
7384 event_queue_cleanup(queue);
7385 DeleteCriticalSection(&queue->cs);
7386 free(queue);
7389 return refcount;
7392 static HRESULT WINAPI eventqueue_GetEvent(IMFMediaEventQueue *iface, DWORD flags, IMFMediaEvent **event)
7394 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7395 HRESULT hr = S_OK;
7397 TRACE("%p, %p.\n", iface, event);
7399 EnterCriticalSection(&queue->cs);
7401 if (queue->is_shut_down)
7402 hr = MF_E_SHUTDOWN;
7403 else if (queue->subscriber)
7404 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7405 else
7407 if (flags & MF_EVENT_FLAG_NO_WAIT)
7409 if (!(*event = queue_pop_event(queue)))
7410 hr = MF_E_NO_EVENTS_AVAILABLE;
7412 else
7414 while (list_empty(&queue->events) && !queue->is_shut_down)
7416 SleepConditionVariableCS(&queue->update_event, &queue->cs, INFINITE);
7418 *event = queue_pop_event(queue);
7419 if (queue->is_shut_down)
7420 hr = MF_E_SHUTDOWN;
7424 LeaveCriticalSection(&queue->cs);
7426 return hr;
7429 static void queue_notify_subscriber(struct event_queue *queue)
7431 if (list_empty(&queue->events) || !queue->subscriber || queue->notified)
7432 return;
7434 queue->notified = TRUE;
7435 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, queue->subscriber);
7438 static HRESULT WINAPI eventqueue_BeginGetEvent(IMFMediaEventQueue *iface, IMFAsyncCallback *callback, IUnknown *state)
7440 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7441 RTWQASYNCRESULT *result_data;
7442 HRESULT hr;
7444 TRACE("%p, %p, %p.\n", iface, callback, state);
7446 if (!callback)
7447 return E_INVALIDARG;
7449 EnterCriticalSection(&queue->cs);
7451 if (queue->is_shut_down)
7452 hr = MF_E_SHUTDOWN;
7453 else if ((result_data = (RTWQASYNCRESULT *)queue->subscriber))
7455 if (result_data->pCallback == (IRtwqAsyncCallback *)callback)
7456 hr = IRtwqAsyncResult_GetStateNoAddRef(queue->subscriber) == state ?
7457 MF_S_MULTIPLE_BEGIN : MF_E_MULTIPLE_BEGIN;
7458 else
7459 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7461 else
7463 hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &queue->subscriber);
7464 if (SUCCEEDED(hr))
7465 queue_notify_subscriber(queue);
7468 LeaveCriticalSection(&queue->cs);
7470 return hr;
7473 static HRESULT WINAPI eventqueue_EndGetEvent(IMFMediaEventQueue *iface, IMFAsyncResult *result, IMFMediaEvent **event)
7475 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7476 HRESULT hr = E_FAIL;
7478 TRACE("%p, %p, %p.\n", iface, result, event);
7480 EnterCriticalSection(&queue->cs);
7482 if (queue->is_shut_down)
7483 hr = MF_E_SHUTDOWN;
7484 else if (queue->subscriber == (IRtwqAsyncResult *)result)
7486 *event = queue_pop_event(queue);
7487 event_queue_clear_subscriber(queue);
7488 queue->notified = FALSE;
7489 hr = *event ? S_OK : E_FAIL;
7492 LeaveCriticalSection(&queue->cs);
7494 return hr;
7497 static HRESULT eventqueue_queue_event(struct event_queue *queue, IMFMediaEvent *event)
7499 struct queued_event *queued_event;
7500 HRESULT hr = S_OK;
7502 queued_event = malloc(sizeof(*queued_event));
7503 if (!queued_event)
7504 return E_OUTOFMEMORY;
7506 queued_event->event = event;
7508 EnterCriticalSection(&queue->cs);
7510 if (queue->is_shut_down)
7511 hr = MF_E_SHUTDOWN;
7512 else
7514 IMFMediaEvent_AddRef(queued_event->event);
7515 list_add_tail(&queue->events, &queued_event->entry);
7516 queue_notify_subscriber(queue);
7519 LeaveCriticalSection(&queue->cs);
7521 if (FAILED(hr))
7522 free(queued_event);
7524 WakeAllConditionVariable(&queue->update_event);
7526 return hr;
7529 static HRESULT WINAPI eventqueue_QueueEvent(IMFMediaEventQueue *iface, IMFMediaEvent *event)
7531 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7533 TRACE("%p, %p.\n", iface, event);
7535 return eventqueue_queue_event(queue, event);
7538 static HRESULT WINAPI eventqueue_QueueEventParamVar(IMFMediaEventQueue *iface, MediaEventType event_type,
7539 REFGUID extended_type, HRESULT status, const PROPVARIANT *value)
7541 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7542 IMFMediaEvent *event;
7543 HRESULT hr;
7545 TRACE("%p, %s, %s, %#lx, %s\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status,
7546 debugstr_propvar(value));
7548 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, value, &event)))
7549 return hr;
7551 hr = eventqueue_queue_event(queue, event);
7552 IMFMediaEvent_Release(event);
7553 return hr;
7556 static HRESULT WINAPI eventqueue_QueueEventParamUnk(IMFMediaEventQueue *iface, MediaEventType event_type,
7557 REFGUID extended_type, HRESULT status, IUnknown *unk)
7559 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7560 IMFMediaEvent *event;
7561 PROPVARIANT value;
7562 HRESULT hr;
7564 TRACE("%p, %s, %s, %#lx, %p.\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status, unk);
7566 value.vt = VT_UNKNOWN;
7567 value.punkVal = unk;
7569 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, &value, &event)))
7570 return hr;
7572 hr = eventqueue_queue_event(queue, event);
7573 IMFMediaEvent_Release(event);
7574 return hr;
7577 static HRESULT WINAPI eventqueue_Shutdown(IMFMediaEventQueue *iface)
7579 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7581 TRACE("%p\n", queue);
7583 EnterCriticalSection(&queue->cs);
7585 if (!queue->is_shut_down)
7587 event_queue_cleanup(queue);
7588 queue->is_shut_down = TRUE;
7591 LeaveCriticalSection(&queue->cs);
7593 WakeAllConditionVariable(&queue->update_event);
7595 return S_OK;
7598 static const IMFMediaEventQueueVtbl eventqueuevtbl =
7600 eventqueue_QueryInterface,
7601 eventqueue_AddRef,
7602 eventqueue_Release,
7603 eventqueue_GetEvent,
7604 eventqueue_BeginGetEvent,
7605 eventqueue_EndGetEvent,
7606 eventqueue_QueueEvent,
7607 eventqueue_QueueEventParamVar,
7608 eventqueue_QueueEventParamUnk,
7609 eventqueue_Shutdown
7612 /***********************************************************************
7613 * MFCreateEventQueue (mfplat.@)
7615 HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue)
7617 struct event_queue *object;
7619 TRACE("%p\n", queue);
7621 if (!(object = calloc(1, sizeof(*object))))
7622 return E_OUTOFMEMORY;
7624 object->IMFMediaEventQueue_iface.lpVtbl = &eventqueuevtbl;
7625 object->refcount = 1;
7626 list_init(&object->events);
7627 InitializeCriticalSection(&object->cs);
7628 InitializeConditionVariable(&object->update_event);
7630 *queue = &object->IMFMediaEventQueue_iface;
7632 return S_OK;
7635 struct collection
7637 IMFCollection IMFCollection_iface;
7638 LONG refcount;
7639 IUnknown **elements;
7640 size_t capacity;
7641 size_t count;
7644 static struct collection *impl_from_IMFCollection(IMFCollection *iface)
7646 return CONTAINING_RECORD(iface, struct collection, IMFCollection_iface);
7649 static void collection_clear(struct collection *collection)
7651 size_t i;
7653 for (i = 0; i < collection->count; ++i)
7655 if (collection->elements[i])
7656 IUnknown_Release(collection->elements[i]);
7659 free(collection->elements);
7660 collection->elements = NULL;
7661 collection->count = 0;
7662 collection->capacity = 0;
7665 static HRESULT WINAPI collection_QueryInterface(IMFCollection *iface, REFIID riid, void **out)
7667 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7669 if (IsEqualIID(riid, &IID_IMFCollection) ||
7670 IsEqualIID(riid, &IID_IUnknown))
7672 *out = iface;
7673 IMFCollection_AddRef(iface);
7674 return S_OK;
7677 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
7678 *out = NULL;
7679 return E_NOINTERFACE;
7682 static ULONG WINAPI collection_AddRef(IMFCollection *iface)
7684 struct collection *collection = impl_from_IMFCollection(iface);
7685 ULONG refcount = InterlockedIncrement(&collection->refcount);
7687 TRACE("%p, %ld.\n", collection, refcount);
7689 return refcount;
7692 static ULONG WINAPI collection_Release(IMFCollection *iface)
7694 struct collection *collection = impl_from_IMFCollection(iface);
7695 ULONG refcount = InterlockedDecrement(&collection->refcount);
7697 TRACE("%p, %ld.\n", collection, refcount);
7699 if (!refcount)
7701 collection_clear(collection);
7702 free(collection->elements);
7703 free(collection);
7706 return refcount;
7709 static HRESULT WINAPI collection_GetElementCount(IMFCollection *iface, DWORD *count)
7711 struct collection *collection = impl_from_IMFCollection(iface);
7713 TRACE("%p, %p.\n", iface, count);
7715 if (!count)
7716 return E_POINTER;
7718 *count = collection->count;
7720 return S_OK;
7723 static HRESULT WINAPI collection_GetElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7725 struct collection *collection = impl_from_IMFCollection(iface);
7727 TRACE("%p, %lu, %p.\n", iface, idx, element);
7729 if (!element)
7730 return E_POINTER;
7732 if (idx >= collection->count)
7733 return E_INVALIDARG;
7735 *element = collection->elements[idx];
7736 if (*element)
7737 IUnknown_AddRef(*element);
7739 return *element ? S_OK : E_UNEXPECTED;
7742 static HRESULT WINAPI collection_AddElement(IMFCollection *iface, IUnknown *element)
7744 struct collection *collection = impl_from_IMFCollection(iface);
7746 TRACE("%p, %p.\n", iface, element);
7748 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, collection->count + 1,
7749 sizeof(*collection->elements)))
7750 return E_OUTOFMEMORY;
7752 collection->elements[collection->count++] = element;
7753 if (element)
7754 IUnknown_AddRef(element);
7756 return S_OK;
7759 static HRESULT WINAPI collection_RemoveElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7761 struct collection *collection = impl_from_IMFCollection(iface);
7762 size_t count;
7764 TRACE("%p, %lu, %p.\n", iface, idx, element);
7766 if (!element)
7767 return E_POINTER;
7769 if (idx >= collection->count)
7770 return E_INVALIDARG;
7772 *element = collection->elements[idx];
7774 count = collection->count - idx - 1;
7775 if (count)
7776 memmove(&collection->elements[idx], &collection->elements[idx + 1], count * sizeof(*collection->elements));
7777 collection->count--;
7779 return S_OK;
7782 static HRESULT WINAPI collection_InsertElementAt(IMFCollection *iface, DWORD idx, IUnknown *element)
7784 struct collection *collection = impl_from_IMFCollection(iface);
7785 size_t i;
7787 TRACE("%p, %lu, %p.\n", iface, idx, element);
7789 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, idx + 1,
7790 sizeof(*collection->elements)))
7791 return E_OUTOFMEMORY;
7793 if (idx < collection->count)
7795 memmove(&collection->elements[idx + 1], &collection->elements[idx],
7796 (collection->count - idx) * sizeof(*collection->elements));
7797 collection->count++;
7799 else
7801 for (i = collection->count; i < idx; ++i)
7802 collection->elements[i] = NULL;
7803 collection->count = idx + 1;
7806 collection->elements[idx] = element;
7807 if (collection->elements[idx])
7808 IUnknown_AddRef(collection->elements[idx]);
7810 return S_OK;
7813 static HRESULT WINAPI collection_RemoveAllElements(IMFCollection *iface)
7815 struct collection *collection = impl_from_IMFCollection(iface);
7817 TRACE("%p.\n", iface);
7819 collection_clear(collection);
7821 return S_OK;
7824 static const IMFCollectionVtbl mfcollectionvtbl =
7826 collection_QueryInterface,
7827 collection_AddRef,
7828 collection_Release,
7829 collection_GetElementCount,
7830 collection_GetElement,
7831 collection_AddElement,
7832 collection_RemoveElement,
7833 collection_InsertElementAt,
7834 collection_RemoveAllElements,
7837 /***********************************************************************
7838 * MFCreateCollection (mfplat.@)
7840 HRESULT WINAPI MFCreateCollection(IMFCollection **collection)
7842 struct collection *object;
7844 TRACE("%p\n", collection);
7846 if (!collection)
7847 return E_POINTER;
7849 if (!(object = calloc(1, sizeof(*object))))
7850 return E_OUTOFMEMORY;
7852 object->IMFCollection_iface.lpVtbl = &mfcollectionvtbl;
7853 object->refcount = 1;
7855 *collection = &object->IMFCollection_iface;
7857 return S_OK;
7860 /***********************************************************************
7861 * MFHeapAlloc (mfplat.@)
7863 void *WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type)
7865 TRACE("%Iu, %#lx, %s, %d, %#x.\n", size, flags, debugstr_a(file), line, type);
7866 return HeapAlloc(GetProcessHeap(), flags, size);
7869 /***********************************************************************
7870 * MFHeapFree (mfplat.@)
7872 void WINAPI MFHeapFree(void *p)
7874 TRACE("%p\n", p);
7875 HeapFree(GetProcessHeap(), 0, p);
7878 /***********************************************************************
7879 * MFCreateMFByteStreamOnStreamEx (mfplat.@)
7881 HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream **bytestream)
7883 FIXME("(%p, %p): stub\n", stream, bytestream);
7885 return E_NOTIMPL;
7888 static HRESULT WINAPI system_clock_QueryInterface(IMFClock *iface, REFIID riid, void **obj)
7890 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7892 if (IsEqualIID(riid, &IID_IMFClock) ||
7893 IsEqualIID(riid, &IID_IUnknown))
7895 *obj = iface;
7896 IMFClock_AddRef(iface);
7897 return S_OK;
7900 WARN("Unsupported %s.\n", debugstr_guid(riid));
7901 *obj = NULL;
7902 return E_NOINTERFACE;
7905 static ULONG WINAPI system_clock_AddRef(IMFClock *iface)
7907 struct system_clock *clock = impl_from_IMFClock(iface);
7908 ULONG refcount = InterlockedIncrement(&clock->refcount);
7910 TRACE("%p, refcount %lu.\n", iface, refcount);
7912 return refcount;
7915 static ULONG WINAPI system_clock_Release(IMFClock *iface)
7917 struct system_clock *clock = impl_from_IMFClock(iface);
7918 ULONG refcount = InterlockedDecrement(&clock->refcount);
7920 TRACE("%p, refcount %lu.\n", iface, refcount);
7922 if (!refcount)
7923 free(clock);
7925 return refcount;
7928 static HRESULT WINAPI system_clock_GetClockCharacteristics(IMFClock *iface, DWORD *flags)
7930 TRACE("%p, %p.\n", iface, flags);
7932 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING |
7933 MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7935 return S_OK;
7938 static HRESULT WINAPI system_clock_GetCorrelatedTime(IMFClock *iface, DWORD reserved, LONGLONG *clock_time,
7939 MFTIME *system_time)
7941 TRACE("%p, %#lx, %p, %p.\n", iface, reserved, clock_time, system_time);
7943 *clock_time = *system_time = MFGetSystemTime();
7945 return S_OK;
7948 static HRESULT WINAPI system_clock_GetContinuityKey(IMFClock *iface, DWORD *key)
7950 TRACE("%p, %p.\n", iface, key);
7952 *key = 0;
7954 return S_OK;
7957 static HRESULT WINAPI system_clock_GetState(IMFClock *iface, DWORD reserved, MFCLOCK_STATE *state)
7959 TRACE("%p, %#lx, %p.\n", iface, reserved, state);
7961 *state = MFCLOCK_STATE_RUNNING;
7963 return S_OK;
7966 static HRESULT WINAPI system_clock_GetProperties(IMFClock *iface, MFCLOCK_PROPERTIES *props)
7968 TRACE("%p, %p.\n", iface, props);
7970 if (!props)
7971 return E_POINTER;
7973 memset(props, 0, sizeof(*props));
7974 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7975 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7976 props->dwClockJitter = 1;
7978 return S_OK;
7981 static const IMFClockVtbl system_clock_vtbl =
7983 system_clock_QueryInterface,
7984 system_clock_AddRef,
7985 system_clock_Release,
7986 system_clock_GetClockCharacteristics,
7987 system_clock_GetCorrelatedTime,
7988 system_clock_GetContinuityKey,
7989 system_clock_GetState,
7990 system_clock_GetProperties,
7993 static HRESULT create_system_clock(IMFClock **clock)
7995 struct system_clock *object;
7997 if (!(object = malloc(sizeof(*object))))
7998 return E_OUTOFMEMORY;
8000 object->IMFClock_iface.lpVtbl = &system_clock_vtbl;
8001 object->refcount = 1;
8003 *clock = &object->IMFClock_iface;
8005 return S_OK;
8008 static HRESULT WINAPI system_time_source_QueryInterface(IMFPresentationTimeSource *iface, REFIID riid, void **obj)
8010 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8012 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8014 if (IsEqualIID(riid, &IID_IMFPresentationTimeSource) ||
8015 IsEqualIID(riid, &IID_IUnknown))
8017 *obj = &source->IMFPresentationTimeSource_iface;
8019 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
8021 *obj = &source->IMFClockStateSink_iface;
8023 else
8025 WARN("Unsupported %s.\n", debugstr_guid(riid));
8026 *obj = NULL;
8027 return E_NOINTERFACE;
8030 IUnknown_AddRef((IUnknown *)*obj);
8031 return S_OK;
8034 static ULONG WINAPI system_time_source_AddRef(IMFPresentationTimeSource *iface)
8036 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8037 ULONG refcount = InterlockedIncrement(&source->refcount);
8039 TRACE("%p, refcount %lu.\n", iface, refcount);
8041 return refcount;
8044 static ULONG WINAPI system_time_source_Release(IMFPresentationTimeSource *iface)
8046 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8047 ULONG refcount = InterlockedDecrement(&source->refcount);
8049 TRACE("%p, refcount %lu.\n", iface, refcount);
8051 if (!refcount)
8053 if (source->clock)
8054 IMFClock_Release(source->clock);
8055 DeleteCriticalSection(&source->cs);
8056 free(source);
8059 return refcount;
8062 static HRESULT WINAPI system_time_source_GetClockCharacteristics(IMFPresentationTimeSource *iface, DWORD *flags)
8064 TRACE("%p, %p.\n", iface, flags);
8066 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
8068 return S_OK;
8071 static HRESULT WINAPI system_time_source_GetCorrelatedTime(IMFPresentationTimeSource *iface, DWORD reserved,
8072 LONGLONG *clock_time, MFTIME *system_time)
8074 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8075 HRESULT hr;
8077 TRACE("%p, %#lx, %p, %p.\n", iface, reserved, clock_time, system_time);
8079 EnterCriticalSection(&source->cs);
8080 if (SUCCEEDED(hr = IMFClock_GetCorrelatedTime(source->clock, 0, clock_time, system_time)))
8082 if (source->state == MFCLOCK_STATE_RUNNING)
8083 system_time_source_update_clock_time(source, *system_time);
8084 *clock_time = source->start_offset + source->clock_time;
8086 LeaveCriticalSection(&source->cs);
8088 return hr;
8091 static HRESULT WINAPI system_time_source_GetContinuityKey(IMFPresentationTimeSource *iface, DWORD *key)
8093 TRACE("%p, %p.\n", iface, key);
8095 *key = 0;
8097 return S_OK;
8100 static HRESULT WINAPI system_time_source_GetState(IMFPresentationTimeSource *iface, DWORD reserved,
8101 MFCLOCK_STATE *state)
8103 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8105 TRACE("%p, %#lx, %p.\n", iface, reserved, state);
8107 EnterCriticalSection(&source->cs);
8108 *state = source->state;
8109 LeaveCriticalSection(&source->cs);
8111 return S_OK;
8114 static HRESULT WINAPI system_time_source_GetProperties(IMFPresentationTimeSource *iface, MFCLOCK_PROPERTIES *props)
8116 TRACE("%p, %p.\n", iface, props);
8118 if (!props)
8119 return E_POINTER;
8121 memset(props, 0, sizeof(*props));
8122 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
8123 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
8124 props->dwClockJitter = 1;
8126 return S_OK;
8129 static HRESULT WINAPI system_time_source_GetUnderlyingClock(IMFPresentationTimeSource *iface, IMFClock **clock)
8131 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8133 TRACE("%p, %p.\n", iface, clock);
8135 *clock = source->clock;
8136 IMFClock_AddRef(*clock);
8138 return S_OK;
8141 static const IMFPresentationTimeSourceVtbl systemtimesourcevtbl =
8143 system_time_source_QueryInterface,
8144 system_time_source_AddRef,
8145 system_time_source_Release,
8146 system_time_source_GetClockCharacteristics,
8147 system_time_source_GetCorrelatedTime,
8148 system_time_source_GetContinuityKey,
8149 system_time_source_GetState,
8150 system_time_source_GetProperties,
8151 system_time_source_GetUnderlyingClock,
8154 static HRESULT WINAPI system_time_source_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **out)
8156 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8157 return IMFPresentationTimeSource_QueryInterface(&source->IMFPresentationTimeSource_iface, riid, out);
8160 static ULONG WINAPI system_time_source_sink_AddRef(IMFClockStateSink *iface)
8162 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8163 return IMFPresentationTimeSource_AddRef(&source->IMFPresentationTimeSource_iface);
8166 static ULONG WINAPI system_time_source_sink_Release(IMFClockStateSink *iface)
8168 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8169 return IMFPresentationTimeSource_Release(&source->IMFPresentationTimeSource_iface);
8172 enum clock_command
8174 CLOCK_CMD_START = 0,
8175 CLOCK_CMD_STOP,
8176 CLOCK_CMD_PAUSE,
8177 CLOCK_CMD_RESTART,
8178 CLOCK_CMD_MAX,
8181 static HRESULT system_time_source_change_state(struct system_time_source *source, enum clock_command command)
8183 static const BYTE state_change_is_allowed[MFCLOCK_STATE_PAUSED+1][CLOCK_CMD_MAX] =
8184 { /* S S* P R */
8185 /* INVALID */ { 1, 0, 1, 0 },
8186 /* RUNNING */ { 1, 1, 1, 0 },
8187 /* STOPPED */ { 1, 1, 0, 0 },
8188 /* PAUSED */ { 1, 1, 0, 1 },
8190 static const MFCLOCK_STATE states[CLOCK_CMD_MAX] =
8192 /* CLOCK_CMD_START */ MFCLOCK_STATE_RUNNING,
8193 /* CLOCK_CMD_STOP */ MFCLOCK_STATE_STOPPED,
8194 /* CLOCK_CMD_PAUSE */ MFCLOCK_STATE_PAUSED,
8195 /* CLOCK_CMD_RESTART */ MFCLOCK_STATE_RUNNING,
8198 /* Special case that go against usual state change vs return value behavior. */
8199 if (source->state == MFCLOCK_STATE_INVALID && command == CLOCK_CMD_STOP)
8200 return S_OK;
8202 if (!state_change_is_allowed[source->state][command])
8203 return MF_E_INVALIDREQUEST;
8205 source->state = states[command];
8207 return S_OK;
8210 static HRESULT WINAPI system_time_source_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time,
8211 LONGLONG start_offset)
8213 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8214 MFCLOCK_STATE state;
8215 HRESULT hr;
8217 TRACE("%p, %s, %s.\n", iface, debugstr_time(system_time), debugstr_time(start_offset));
8219 EnterCriticalSection(&source->cs);
8220 state = source->state;
8221 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_START)))
8223 if (start_offset == PRESENTATION_CURRENT_POSITION)
8225 if (state != MFCLOCK_STATE_RUNNING)
8227 source->start_offset -= system_time;
8228 source->system_time = 0;
8231 else
8233 source->start_offset = start_offset;
8234 source->system_time = system_time;
8235 source->clock_time = 0;
8238 LeaveCriticalSection(&source->cs);
8240 return hr;
8243 static HRESULT WINAPI system_time_source_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
8245 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8246 HRESULT hr;
8248 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
8250 EnterCriticalSection(&source->cs);
8251 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_STOP)))
8253 source->start_offset = source->system_time = source->clock_time = 0;
8255 LeaveCriticalSection(&source->cs);
8257 return hr;
8260 static HRESULT WINAPI system_time_source_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
8262 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8263 HRESULT hr;
8265 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
8267 EnterCriticalSection(&source->cs);
8268 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_PAUSE)))
8270 system_time_source_update_clock_time(source, system_time);
8272 LeaveCriticalSection(&source->cs);
8274 return hr;
8277 static HRESULT WINAPI system_time_source_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
8279 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8280 HRESULT hr;
8282 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
8284 EnterCriticalSection(&source->cs);
8285 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_RESTART)))
8287 source->system_time = system_time;
8289 LeaveCriticalSection(&source->cs);
8291 return hr;
8294 static HRESULT WINAPI system_time_source_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
8296 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8297 double intpart;
8299 TRACE("%p, %s, %f.\n", iface, debugstr_time(system_time), rate);
8301 if (rate == 0.0f)
8302 return MF_E_UNSUPPORTED_RATE;
8304 modf(rate, &intpart);
8306 EnterCriticalSection(&source->cs);
8307 source->rate = rate;
8308 source->i_rate = rate == intpart ? rate : 0;
8309 LeaveCriticalSection(&source->cs);
8311 return S_OK;
8314 static const IMFClockStateSinkVtbl systemtimesourcesinkvtbl =
8316 system_time_source_sink_QueryInterface,
8317 system_time_source_sink_AddRef,
8318 system_time_source_sink_Release,
8319 system_time_source_sink_OnClockStart,
8320 system_time_source_sink_OnClockStop,
8321 system_time_source_sink_OnClockPause,
8322 system_time_source_sink_OnClockRestart,
8323 system_time_source_sink_OnClockSetRate,
8326 /***********************************************************************
8327 * MFCreateSystemTimeSource (mfplat.@)
8329 HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source)
8331 struct system_time_source *object;
8332 HRESULT hr;
8334 TRACE("%p.\n", time_source);
8336 object = calloc(1, sizeof(*object));
8337 if (!object)
8338 return E_OUTOFMEMORY;
8340 object->IMFPresentationTimeSource_iface.lpVtbl = &systemtimesourcevtbl;
8341 object->IMFClockStateSink_iface.lpVtbl = &systemtimesourcesinkvtbl;
8342 object->refcount = 1;
8343 object->rate = 1.0f;
8344 object->i_rate = 1;
8345 InitializeCriticalSection(&object->cs);
8347 if (FAILED(hr = create_system_clock(&object->clock)))
8349 IMFPresentationTimeSource_Release(&object->IMFPresentationTimeSource_iface);
8350 return hr;
8353 *time_source = &object->IMFPresentationTimeSource_iface;
8355 return S_OK;
8358 struct async_create_file
8360 IRtwqAsyncCallback IRtwqAsyncCallback_iface;
8361 LONG refcount;
8362 MF_FILE_ACCESSMODE access_mode;
8363 MF_FILE_OPENMODE open_mode;
8364 MF_FILE_FLAGS flags;
8365 WCHAR *path;
8368 struct async_create_file_result
8370 struct list entry;
8371 IRtwqAsyncResult *result;
8372 IMFByteStream *stream;
8375 static struct list async_create_file_results = LIST_INIT(async_create_file_results);
8376 static CRITICAL_SECTION async_create_file_cs = { NULL, -1, 0, 0, 0, 0 };
8378 static struct async_create_file *impl_from_create_file_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
8380 return CONTAINING_RECORD(iface, struct async_create_file, IRtwqAsyncCallback_iface);
8383 static HRESULT WINAPI async_create_file_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
8385 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
8386 IsEqualIID(riid, &IID_IUnknown))
8388 *obj = iface;
8389 IRtwqAsyncCallback_AddRef(iface);
8390 return S_OK;
8393 *obj = NULL;
8394 return E_NOINTERFACE;
8397 static ULONG WINAPI async_create_file_callback_AddRef(IRtwqAsyncCallback *iface)
8399 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8400 ULONG refcount = InterlockedIncrement(&async->refcount);
8402 TRACE("%p, refcount %lu.\n", iface, refcount);
8404 return refcount;
8407 static ULONG WINAPI async_create_file_callback_Release(IRtwqAsyncCallback *iface)
8409 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8410 ULONG refcount = InterlockedDecrement(&async->refcount);
8412 TRACE("%p, refcount %lu.\n", iface, refcount);
8414 if (!refcount)
8416 free(async->path);
8417 free(async);
8420 return refcount;
8423 static HRESULT WINAPI async_create_file_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
8425 return E_NOTIMPL;
8428 static HRESULT WINAPI async_create_file_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
8430 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8431 IRtwqAsyncResult *caller;
8432 IMFByteStream *stream;
8433 HRESULT hr;
8435 caller = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
8437 hr = MFCreateFile(async->access_mode, async->open_mode, async->flags, async->path, &stream);
8438 if (SUCCEEDED(hr))
8440 struct async_create_file_result *result_item;
8442 result_item = malloc(sizeof(*result_item));
8443 if (result_item)
8445 result_item->result = caller;
8446 IRtwqAsyncResult_AddRef(caller);
8447 result_item->stream = stream;
8448 IMFByteStream_AddRef(stream);
8450 EnterCriticalSection(&async_create_file_cs);
8451 list_add_tail(&async_create_file_results, &result_item->entry);
8452 LeaveCriticalSection(&async_create_file_cs);
8455 IMFByteStream_Release(stream);
8457 else
8458 IRtwqAsyncResult_SetStatus(caller, hr);
8460 RtwqInvokeCallback(caller);
8462 return S_OK;
8465 static const IRtwqAsyncCallbackVtbl async_create_file_callback_vtbl =
8467 async_create_file_callback_QueryInterface,
8468 async_create_file_callback_AddRef,
8469 async_create_file_callback_Release,
8470 async_create_file_callback_GetParameters,
8471 async_create_file_callback_Invoke,
8474 /***********************************************************************
8475 * MFBeginCreateFile (mfplat.@)
8477 HRESULT WINAPI MFBeginCreateFile(MF_FILE_ACCESSMODE access_mode, MF_FILE_OPENMODE open_mode, MF_FILE_FLAGS flags,
8478 const WCHAR *path, IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_cookie)
8480 struct async_create_file *async = NULL;
8481 IRtwqAsyncResult *caller, *item = NULL;
8482 HRESULT hr;
8484 TRACE("%#x, %#x, %#x, %s, %p, %p, %p.\n", access_mode, open_mode, flags, debugstr_w(path), callback, state,
8485 cancel_cookie);
8487 if (cancel_cookie)
8488 *cancel_cookie = NULL;
8490 if (FAILED(hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &caller)))
8491 return hr;
8493 if (!(async = malloc(sizeof(*async))))
8495 hr = E_OUTOFMEMORY;
8496 goto failed;
8499 async->IRtwqAsyncCallback_iface.lpVtbl = &async_create_file_callback_vtbl;
8500 async->refcount = 1;
8501 async->access_mode = access_mode;
8502 async->open_mode = open_mode;
8503 async->flags = flags;
8504 if (!(async->path = wcsdup(path)))
8506 hr = E_OUTOFMEMORY;
8507 goto failed;
8510 hr = RtwqCreateAsyncResult(NULL, &async->IRtwqAsyncCallback_iface, (IUnknown *)caller, &item);
8511 if (FAILED(hr))
8512 goto failed;
8514 if (cancel_cookie)
8516 *cancel_cookie = (IUnknown *)caller;
8517 IUnknown_AddRef(*cancel_cookie);
8520 hr = RtwqInvokeCallback(item);
8522 failed:
8523 if (async)
8524 IRtwqAsyncCallback_Release(&async->IRtwqAsyncCallback_iface);
8525 if (item)
8526 IRtwqAsyncResult_Release(item);
8527 if (caller)
8528 IRtwqAsyncResult_Release(caller);
8530 return hr;
8533 static HRESULT async_create_file_pull_result(IUnknown *unk, IMFByteStream **stream)
8535 struct async_create_file_result *item;
8536 HRESULT hr = MF_E_UNEXPECTED;
8537 IRtwqAsyncResult *result;
8539 *stream = NULL;
8541 if (FAILED(IUnknown_QueryInterface(unk, &IID_IRtwqAsyncResult, (void **)&result)))
8542 return hr;
8544 EnterCriticalSection(&async_create_file_cs);
8546 LIST_FOR_EACH_ENTRY(item, &async_create_file_results, struct async_create_file_result, entry)
8548 if (result == item->result)
8550 *stream = item->stream;
8551 IRtwqAsyncResult_Release(item->result);
8552 list_remove(&item->entry);
8553 free(item);
8554 break;
8558 LeaveCriticalSection(&async_create_file_cs);
8560 if (*stream)
8561 hr = IRtwqAsyncResult_GetStatus(result);
8563 IRtwqAsyncResult_Release(result);
8565 return hr;
8568 /***********************************************************************
8569 * MFEndCreateFile (mfplat.@)
8571 HRESULT WINAPI MFEndCreateFile(IMFAsyncResult *result, IMFByteStream **stream)
8573 TRACE("%p, %p.\n", result, stream);
8575 return async_create_file_pull_result((IUnknown *)result, stream);
8578 /***********************************************************************
8579 * MFCancelCreateFile (mfplat.@)
8581 HRESULT WINAPI MFCancelCreateFile(IUnknown *cancel_cookie)
8583 IMFByteStream *stream = NULL;
8584 HRESULT hr;
8586 TRACE("%p.\n", cancel_cookie);
8588 hr = async_create_file_pull_result(cancel_cookie, &stream);
8590 if (stream)
8591 IMFByteStream_Release(stream);
8593 return hr;
8596 /***********************************************************************
8597 * MFRegisterLocalSchemeHandler (mfplat.@)
8599 HRESULT WINAPI MFRegisterLocalSchemeHandler(const WCHAR *scheme, IMFActivate *activate)
8601 struct local_handler *handler;
8603 TRACE("%s, %p.\n", debugstr_w(scheme), activate);
8605 if (!scheme || !activate)
8606 return E_INVALIDARG;
8608 if (!(handler = malloc(sizeof(*handler))))
8609 return E_OUTOFMEMORY;
8611 if (!(handler->u.scheme = wcsdup(scheme)))
8613 free(handler);
8614 return E_OUTOFMEMORY;
8616 handler->activate = activate;
8617 IMFActivate_AddRef(handler->activate);
8619 EnterCriticalSection(&local_handlers_section);
8620 list_add_head(&local_scheme_handlers, &handler->entry);
8621 LeaveCriticalSection(&local_handlers_section);
8623 return S_OK;
8626 /***********************************************************************
8627 * MFRegisterLocalByteStreamHandler (mfplat.@)
8629 HRESULT WINAPI MFRegisterLocalByteStreamHandler(const WCHAR *extension, const WCHAR *mime, IMFActivate *activate)
8631 struct local_handler *handler;
8633 TRACE("%s, %s, %p.\n", debugstr_w(extension), debugstr_w(mime), activate);
8635 if ((!extension && !mime) || !activate)
8636 return E_INVALIDARG;
8638 if (!(handler = calloc(1, sizeof(*handler))))
8639 return E_OUTOFMEMORY;
8641 if (extension && !(handler->u.bytestream.extension = wcsdup(extension)))
8642 goto failed;
8643 if (mime && !(handler->u.bytestream.mime = wcsdup(mime)))
8644 goto failed;
8646 EnterCriticalSection(&local_handlers_section);
8647 list_add_head(&local_bytestream_handlers, &handler->entry);
8648 LeaveCriticalSection(&local_handlers_section);
8650 return S_OK;
8652 failed:
8653 free(handler->u.bytestream.extension);
8654 free(handler->u.bytestream.mime);
8655 free(handler);
8657 return E_OUTOFMEMORY;
8660 struct property_store
8662 IPropertyStore IPropertyStore_iface;
8663 LONG refcount;
8664 CRITICAL_SECTION cs;
8665 size_t count, capacity;
8666 struct
8668 PROPERTYKEY key;
8669 PROPVARIANT value;
8670 } *values;
8673 static struct property_store *impl_from_IPropertyStore(IPropertyStore *iface)
8675 return CONTAINING_RECORD(iface, struct property_store, IPropertyStore_iface);
8678 static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
8680 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8682 if (IsEqualIID(riid, &IID_IPropertyStore) || IsEqualIID(riid, &IID_IUnknown))
8684 *obj = iface;
8685 IPropertyStore_AddRef(iface);
8686 return S_OK;
8689 *obj = NULL;
8690 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
8691 return E_NOINTERFACE;
8694 static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
8696 struct property_store *store = impl_from_IPropertyStore(iface);
8697 ULONG refcount = InterlockedIncrement(&store->refcount);
8699 TRACE("%p, refcount %ld.\n", iface, refcount);
8701 return refcount;
8704 static ULONG WINAPI property_store_Release(IPropertyStore *iface)
8706 struct property_store *store = impl_from_IPropertyStore(iface);
8707 ULONG refcount = InterlockedDecrement(&store->refcount);
8709 TRACE("%p, refcount %ld.\n", iface, refcount);
8711 if (!refcount)
8713 DeleteCriticalSection(&store->cs);
8714 free(store->values);
8715 free(store);
8718 return refcount;
8721 static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
8723 struct property_store *store = impl_from_IPropertyStore(iface);
8725 TRACE("%p, %p.\n", iface, count);
8727 if (!count)
8728 return E_INVALIDARG;
8730 EnterCriticalSection(&store->cs);
8731 *count = store->count;
8732 LeaveCriticalSection(&store->cs);
8733 return S_OK;
8736 static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
8738 struct property_store *store = impl_from_IPropertyStore(iface);
8740 TRACE("%p, %lu, %p.\n", iface, index, key);
8742 EnterCriticalSection(&store->cs);
8744 if (index >= store->count)
8746 LeaveCriticalSection(&store->cs);
8747 return E_INVALIDARG;
8750 *key = store->values[index].key;
8752 LeaveCriticalSection(&store->cs);
8753 return S_OK;
8756 static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
8758 struct property_store *store = impl_from_IPropertyStore(iface);
8759 unsigned int i;
8761 TRACE("%p, %p, %p.\n", iface, key, value);
8763 if (!value)
8764 return E_INVALIDARG;
8766 if (!key)
8767 return S_FALSE;
8769 EnterCriticalSection(&store->cs);
8771 for (i = 0; i < store->count; ++i)
8773 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8775 PropVariantCopy(value, &store->values[i].value);
8776 LeaveCriticalSection(&store->cs);
8777 return S_OK;
8781 LeaveCriticalSection(&store->cs);
8782 return S_FALSE;
8785 static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
8787 struct property_store *store = impl_from_IPropertyStore(iface);
8788 unsigned int i;
8790 TRACE("%p, %p, %p.\n", iface, key, value);
8792 EnterCriticalSection(&store->cs);
8794 for (i = 0; i < store->count; ++i)
8796 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8798 PropVariantCopy(&store->values[i].value, value);
8799 LeaveCriticalSection(&store->cs);
8800 return S_OK;
8804 if (!mf_array_reserve((void **)&store->values, &store->capacity, store->count + 1, sizeof(*store->values)))
8806 LeaveCriticalSection(&store->cs);
8807 return E_OUTOFMEMORY;
8810 store->values[store->count].key = *key;
8811 PropVariantCopy(&store->values[store->count].value, value);
8812 ++store->count;
8814 LeaveCriticalSection(&store->cs);
8815 return S_OK;
8818 static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
8820 TRACE("%p.\n", iface);
8822 return E_NOTIMPL;
8825 static const IPropertyStoreVtbl property_store_vtbl =
8827 property_store_QueryInterface,
8828 property_store_AddRef,
8829 property_store_Release,
8830 property_store_GetCount,
8831 property_store_GetAt,
8832 property_store_GetValue,
8833 property_store_SetValue,
8834 property_store_Commit,
8837 /***********************************************************************
8838 * CreatePropertyStore (mfplat.@)
8840 HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
8842 struct property_store *object;
8844 TRACE("%p.\n", store);
8846 if (!store)
8847 return E_INVALIDARG;
8849 if (!(object = calloc(1, sizeof(*object))))
8850 return E_OUTOFMEMORY;
8852 object->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
8853 object->refcount = 1;
8854 InitializeCriticalSection(&object->cs);
8856 TRACE("Created store %p.\n", object);
8857 *store = &object->IPropertyStore_iface;
8859 return S_OK;
8862 struct shared_dxgi_manager
8864 IMFDXGIDeviceManager *manager;
8865 unsigned int token;
8866 unsigned int locks;
8869 static struct shared_dxgi_manager shared_dm;
8870 static CRITICAL_SECTION shared_dm_cs = { NULL, -1, 0, 0, 0, 0 };
8872 enum dxgi_device_handle_flags
8874 DXGI_DEVICE_HANDLE_FLAG_OPEN = 0x1,
8875 DXGI_DEVICE_HANDLE_FLAG_INVALID = 0x2,
8876 DXGI_DEVICE_HANDLE_FLAG_LOCKED = 0x4,
8879 struct dxgi_device_manager
8881 IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
8882 LONG refcount;
8883 UINT token;
8884 IUnknown *device;
8886 unsigned int *handles;
8887 size_t count;
8888 size_t capacity;
8890 unsigned int locks;
8891 unsigned int locking_tid;
8893 CRITICAL_SECTION cs;
8894 CONDITION_VARIABLE lock;
8897 static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
8899 return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface);
8902 static HRESULT dxgi_device_manager_get_handle_index(struct dxgi_device_manager *manager, HANDLE hdevice, size_t *idx)
8904 if (!hdevice || hdevice > ULongToHandle(manager->count))
8905 return E_HANDLE;
8906 *idx = (ULONG_PTR)hdevice - 1;
8907 return S_OK;
8910 static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj)
8912 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8914 if (IsEqualIID(riid, &IID_IMFDXGIDeviceManager) ||
8915 IsEqualGUID(riid, &IID_IUnknown))
8917 *obj = iface;
8918 IMFDXGIDeviceManager_AddRef(iface);
8919 return S_OK;
8922 WARN("Unsupported %s.\n", debugstr_guid(riid));
8923 *obj = NULL;
8924 return E_NOINTERFACE;
8927 static ULONG WINAPI dxgi_device_manager_AddRef(IMFDXGIDeviceManager *iface)
8929 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8930 ULONG refcount = InterlockedIncrement(&manager->refcount);
8932 TRACE("%p, refcount %lu.\n", iface, refcount);
8934 return refcount;
8937 static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
8939 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8940 ULONG refcount = InterlockedDecrement(&manager->refcount);
8942 TRACE("%p, refcount %lu.\n", iface, refcount);
8944 if (!refcount)
8946 if (manager->device)
8947 IUnknown_Release(manager->device);
8948 DeleteCriticalSection(&manager->cs);
8949 free(manager->handles);
8950 free(manager);
8953 return refcount;
8956 static void dxgi_device_manager_lock_handle(struct dxgi_device_manager *manager, size_t idx)
8958 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED)
8959 return;
8961 manager->handles[idx] |= DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8962 manager->locks++;
8965 static void dxgi_device_manager_unlock_handle(struct dxgi_device_manager *manager, size_t idx)
8967 if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED))
8968 return;
8970 manager->handles[idx] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8971 if (!--manager->locks)
8972 manager->locking_tid = 0;
8975 static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8977 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8978 HRESULT hr;
8979 size_t idx;
8981 TRACE("%p, %p.\n", iface, hdevice);
8983 EnterCriticalSection(&manager->cs);
8985 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8987 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8989 dxgi_device_manager_unlock_handle(manager, idx);
8990 manager->handles[idx] = 0;
8991 if (idx == manager->count - 1)
8992 manager->count--;
8994 else
8995 hr = E_HANDLE;
8998 LeaveCriticalSection(&manager->cs);
9000 WakeAllConditionVariable(&manager->lock);
9002 return hr;
9005 static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE hdevice,
9006 REFIID riid, void **service)
9008 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9009 HRESULT hr;
9010 size_t idx;
9012 TRACE("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), service);
9014 EnterCriticalSection(&manager->cs);
9016 if (!manager->device)
9017 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
9018 else if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
9020 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
9021 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
9022 else if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
9023 hr = IUnknown_QueryInterface(manager->device, riid, service);
9024 else
9025 hr = E_HANDLE;
9028 LeaveCriticalSection(&manager->cs);
9030 return hr;
9033 static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
9034 REFIID riid, void **obj, BOOL block)
9036 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9037 HRESULT hr;
9038 size_t idx;
9040 TRACE("%p, %p, %s, %p, %d.\n", iface, hdevice, wine_dbgstr_guid(riid), obj, block);
9042 EnterCriticalSection(&manager->cs);
9044 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
9046 if (!manager->device)
9048 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
9050 else if (manager->locking_tid == GetCurrentThreadId())
9052 if (SUCCEEDED(hr = IUnknown_QueryInterface(manager->device, riid, obj)))
9053 dxgi_device_manager_lock_handle(manager, idx);
9055 else if (manager->locking_tid && !block)
9057 hr = MF_E_DXGI_VIDEO_DEVICE_LOCKED;
9059 else
9061 while (manager->locking_tid)
9063 SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE);
9066 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
9068 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
9069 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
9070 else if (SUCCEEDED(hr = IUnknown_QueryInterface(manager->device, riid, obj)))
9072 manager->locking_tid = GetCurrentThreadId();
9073 dxgi_device_manager_lock_handle(manager, idx);
9079 LeaveCriticalSection(&manager->cs);
9081 return hr;
9084 static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *hdevice)
9086 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9087 HRESULT hr = S_OK;
9088 size_t i;
9090 TRACE("%p, %p.\n", iface, hdevice);
9092 *hdevice = NULL;
9094 EnterCriticalSection(&manager->cs);
9096 if (!manager->device)
9097 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
9098 else
9100 for (i = 0; i < manager->count; ++i)
9102 if (!(manager->handles[i] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
9104 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_OPEN;
9105 *hdevice = ULongToHandle(i + 1);
9106 break;
9110 if (mf_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1,
9111 sizeof(*manager->handles)))
9113 *hdevice = ULongToHandle(manager->count + 1);
9114 manager->handles[manager->count++] = DXGI_DEVICE_HANDLE_FLAG_OPEN;
9116 else
9117 hr = E_OUTOFMEMORY;
9120 LeaveCriticalSection(&manager->cs);
9122 return hr;
9125 static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
9127 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9128 IUnknown *d3d_device;
9129 size_t i;
9131 TRACE("%p, %p, %u.\n", iface, device, token);
9133 if (!device || token != manager->token)
9134 return E_INVALIDARG;
9136 if (FAILED(IUnknown_QueryInterface(device, &IID_ID3D11Device, (void **)&d3d_device)))
9138 if (FAILED(IUnknown_QueryInterface(device, &IID_ID3D12Device, (void **)&d3d_device)))
9140 WARN("Unsupported device interface.\n");
9141 return E_INVALIDARG;
9145 EnterCriticalSection(&manager->cs);
9147 if (manager->device)
9149 for (i = 0; i < manager->count; ++i)
9151 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_INVALID;
9152 manager->handles[i] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
9154 manager->locking_tid = 0;
9155 manager->locks = 0;
9156 IUnknown_Release(manager->device);
9158 manager->device = d3d_device;
9160 LeaveCriticalSection(&manager->cs);
9162 WakeAllConditionVariable(&manager->lock);
9164 return S_OK;
9167 static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice)
9169 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9170 HRESULT hr;
9171 size_t idx;
9173 TRACE("%p, %p.\n", iface, hdevice);
9175 EnterCriticalSection(&manager->cs);
9177 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
9179 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
9180 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
9181 else if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
9182 hr = E_HANDLE;
9185 LeaveCriticalSection(&manager->cs);
9187 return hr;
9190 static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
9191 BOOL savestate)
9193 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9194 HRESULT hr = E_FAIL;
9195 size_t idx;
9197 TRACE("%p, %p, %d.\n", iface, hdevice, savestate);
9199 EnterCriticalSection(&manager->cs);
9201 if (SUCCEEDED(dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
9203 hr = manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED ? S_OK : E_INVALIDARG;
9204 if (SUCCEEDED(hr))
9205 dxgi_device_manager_unlock_handle(manager, idx);
9208 LeaveCriticalSection(&manager->cs);
9210 WakeAllConditionVariable(&manager->lock);
9212 return hr;
9215 static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
9217 dxgi_device_manager_QueryInterface,
9218 dxgi_device_manager_AddRef,
9219 dxgi_device_manager_Release,
9220 dxgi_device_manager_CloseDeviceHandle,
9221 dxgi_device_manager_GetVideoService,
9222 dxgi_device_manager_LockDevice,
9223 dxgi_device_manager_OpenDeviceHandle,
9224 dxgi_device_manager_ResetDevice,
9225 dxgi_device_manager_TestDevice,
9226 dxgi_device_manager_UnlockDevice,
9229 /***********************************************************************
9230 * MFCreateDXGIDeviceManager (mfplat.@)
9232 HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
9234 struct dxgi_device_manager *object;
9236 TRACE("%p, %p.\n", token, manager);
9238 if (!token || !manager)
9239 return E_POINTER;
9241 if (!(object = calloc(1, sizeof(*object))))
9242 return E_OUTOFMEMORY;
9244 object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
9245 object->refcount = 1;
9246 object->token = GetTickCount();
9247 InitializeCriticalSection(&object->cs);
9248 InitializeConditionVariable(&object->lock);
9250 TRACE("Created device manager: %p, token: %u.\n", object, object->token);
9252 *token = object->token;
9253 *manager = &object->IMFDXGIDeviceManager_iface;
9255 return S_OK;
9258 /***********************************************************************
9259 * MFLockDXGIDeviceManager (mfplat.@)
9261 HRESULT WINAPI MFLockDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
9263 HRESULT hr = S_OK;
9265 TRACE("%p, %p.\n", token, manager);
9267 EnterCriticalSection(&shared_dm_cs);
9269 if (!shared_dm.manager)
9270 hr = MFCreateDXGIDeviceManager(&shared_dm.token, &shared_dm.manager);
9272 if (SUCCEEDED(hr))
9274 *manager = shared_dm.manager;
9275 IMFDXGIDeviceManager_AddRef(*manager);
9276 shared_dm.locks++;
9278 if (token) *token = shared_dm.token;
9281 LeaveCriticalSection(&shared_dm_cs);
9283 return hr;
9286 /***********************************************************************
9287 * MFUnlockDXGIDeviceManager (mfplat.@)
9289 HRESULT WINAPI MFUnlockDXGIDeviceManager(void)
9291 TRACE("\n");
9293 EnterCriticalSection(&shared_dm_cs);
9295 if (shared_dm.manager)
9297 IMFDXGIDeviceManager_Release(shared_dm.manager);
9298 if (!--shared_dm.locks)
9300 shared_dm.manager = NULL;
9301 shared_dm.token = 0;
9305 LeaveCriticalSection(&shared_dm_cs);
9307 return S_OK;
9312 * MFllMulDiv implementation is derived from gstreamer utility functions code (gstutils.c),
9313 * released under LGPL2. Full authors list follows.
9314 * ===================================================================================
9315 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
9316 * 2000 Wim Taymans <wtay@chello.be>
9317 * 2002 Thomas Vander Stichele <thomas@apestaart.org>
9318 * 2004 Wim Taymans <wim@fluendo.com>
9319 * 2015 Jan Schmidt <jan@centricular.com>
9320 * ===================================================================================
9323 static void llmult128(ULARGE_INTEGER *c1, ULARGE_INTEGER *c0, LONGLONG val, LONGLONG num)
9325 ULARGE_INTEGER a1, b0, v, n;
9327 v.QuadPart = llabs(val);
9328 n.QuadPart = llabs(num);
9330 /* do 128 bits multiply
9331 * nh nl
9332 * * vh vl
9333 * ----------
9334 * a0 = vl * nl
9335 * a1 = vl * nh
9336 * b0 = vh * nl
9337 * b1 = + vh * nh
9338 * -------------------
9339 * c1h c1l c0h c0l
9341 * "a0" is optimized away, result is stored directly in c0. "b1" is
9342 * optimized away, result is stored directly in c1.
9344 c0->QuadPart = (ULONGLONG)v.LowPart * n.LowPart;
9345 a1.QuadPart = (ULONGLONG)v.LowPart * n.HighPart;
9346 b0.QuadPart = (ULONGLONG)v.HighPart * n.LowPart;
9348 /* add the high word of a0 to the low words of a1 and b0 using c1 as
9349 * scratch space to capture the carry. the low word of the result becomes
9350 * the final high word of c0 */
9351 c1->QuadPart = (ULONGLONG)c0->HighPart + a1.LowPart + b0.LowPart;
9352 c0->HighPart = c1->LowPart;
9354 /* add the carry from the result above (found in the high word of c1) and
9355 * the high words of a1 and b0 to b1, the result is c1. */
9356 c1->QuadPart = (ULONGLONG)v.HighPart * n.HighPart + c1->HighPart + a1.HighPart + b0.HighPart;
9359 static ULONGLONG lldiv128(ULARGE_INTEGER c1, ULARGE_INTEGER c0, LONGLONG denom)
9361 ULARGE_INTEGER q1, q0, rhat;
9362 ULARGE_INTEGER v, cmp1, cmp2;
9363 DWORD s = 0;
9365 v.QuadPart = llabs(denom);
9367 /* 64bit numerator */
9368 if (c1.QuadPart == 0)
9369 return c0.QuadPart / v.QuadPart;
9371 /* 96bit numerator, 32bit denominator */
9372 if (v.HighPart == 0 && c1.HighPart == 0)
9374 ULONGLONG low = c0.LowPart, high = c0.HighPart + ((ULONGLONG)c1.LowPart << 32);
9375 low += (high % v.LowPart) << 32;
9376 return ((high / v.LowPart) << 32) + (low / v.LowPart);
9379 /* 128bit numerator, 32bit denominator */
9380 if (v.HighPart == 0)
9381 return UI64_MAX;
9383 /* count number of leading zeroes */
9384 BitScanReverse(&s, v.HighPart);
9385 s = 31 - s;
9387 if (s)
9389 /* normalize divisor and dividend */
9390 v.QuadPart <<= s;
9391 c1.QuadPart = (c1.QuadPart << s) | (c0.HighPart >> (32 - s));
9392 c0.QuadPart <<= s;
9395 q1.QuadPart = c1.QuadPart / v.HighPart;
9396 rhat.QuadPart = c1.QuadPart - q1.QuadPart * v.HighPart;
9398 cmp1.HighPart = rhat.LowPart;
9399 cmp1.LowPart = c0.HighPart;
9400 cmp2.QuadPart = q1.QuadPart * v.LowPart;
9402 while (q1.HighPart || cmp2.QuadPart > cmp1.QuadPart)
9404 q1.QuadPart--;
9405 rhat.QuadPart += v.HighPart;
9406 if (rhat.HighPart)
9407 break;
9408 cmp1.HighPart = rhat.LowPart;
9409 cmp2.QuadPart -= v.LowPart;
9411 c1.HighPart = c1.LowPart;
9412 c1.LowPart = c0.HighPart;
9413 c1.QuadPart -= q1.QuadPart * v.QuadPart;
9414 q0.QuadPart = c1.QuadPart / v.HighPart;
9415 rhat.QuadPart = c1.QuadPart - q0.QuadPart * v.HighPart;
9417 cmp1.HighPart = rhat.LowPart;
9418 cmp1.LowPart = c0.LowPart;
9419 cmp2.QuadPart = q0.QuadPart * v.LowPart;
9421 while (q0.HighPart || cmp2.QuadPart > cmp1.QuadPart)
9423 q0.QuadPart--;
9424 rhat.QuadPart += v.HighPart;
9425 if (rhat.HighPart)
9426 break;
9427 cmp1.HighPart = rhat.LowPart;
9428 cmp2.QuadPart -= v.LowPart;
9430 q0.HighPart += q1.LowPart;
9432 return q0.QuadPart;
9435 /***********************************************************************
9436 * MFllMulDiv (mfplat.@)
9438 LONGLONG WINAPI MFllMulDiv(LONGLONG val, LONGLONG num, LONGLONG denom, LONGLONG factor)
9440 #define LLOVERFLOW (sign ? I64_MIN : I64_MAX)
9441 unsigned int sign, factor_sign, denom_sign;
9442 ULARGE_INTEGER c1, c0;
9443 ULONGLONG ret;
9445 TRACE("%s, %s, %s, %s.\n", wine_dbgstr_longlong(val), wine_dbgstr_longlong(num),
9446 wine_dbgstr_longlong(denom), wine_dbgstr_longlong(factor));
9448 /* compute 128-bit numerator product */
9449 llmult128(&c1, &c0, val, num);
9451 sign = (val < 0) ^ (num < 0);
9452 factor_sign = factor < 0;
9453 denom_sign = denom < 0;
9455 factor = llabs(factor);
9456 if (sign == factor_sign)
9458 if (UI64_MAX - c0.QuadPart < factor)
9460 if (c1.QuadPart == UI64_MAX) return LLOVERFLOW;
9461 c1.QuadPart++;
9463 c0.QuadPart += factor;
9465 else
9467 if (c0.QuadPart >= factor)
9468 c0.QuadPart -= factor;
9469 else
9471 if (c1.QuadPart)
9472 c1.QuadPart--;
9473 else
9474 sign = !sign;
9476 c0.QuadPart = factor - c0.QuadPart;
9480 if (c1.QuadPart >= denom) return LLOVERFLOW;
9482 /* compute quotient, fits in 64 bits */
9483 ret = lldiv128(c1, c0, denom);
9484 sign ^= denom_sign;
9485 if (ret >= I64_MAX) return LLOVERFLOW;
9486 return sign ? -(LONGLONG)ret : ret;
9487 #undef LLOVERFLOW