mfplat: Implement shared device manager API.
[wine.git] / dlls / mfplat / main.c
blobf1d0aaad94df56c7d49a5cdf8a49f5392781e885
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/debug.h"
40 #include "wine/list.h"
42 #include "mfplat_private.h"
43 #include "mfreadwrite.h"
44 #include "mfmediaengine.h"
45 #include "propvarutil.h"
46 #include "strsafe.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
50 static HRESULT heap_strdupW(const WCHAR *str, WCHAR **dest)
52 HRESULT hr = S_OK;
54 if (str)
56 unsigned int size;
58 size = (lstrlenW(str) + 1) * sizeof(WCHAR);
59 *dest = heap_alloc(size);
60 if (*dest)
61 memcpy(*dest, str, size);
62 else
63 hr = E_OUTOFMEMORY;
65 else
66 *dest = NULL;
68 return hr;
71 struct local_handler
73 struct list entry;
74 union
76 WCHAR *scheme;
77 struct
79 WCHAR *extension;
80 WCHAR *mime;
81 } bytestream;
82 } u;
83 IMFActivate *activate;
86 static CRITICAL_SECTION local_handlers_section = { NULL, -1, 0, 0, 0, 0 };
88 static struct list local_scheme_handlers = LIST_INIT(local_scheme_handlers);
89 static struct list local_bytestream_handlers = LIST_INIT(local_bytestream_handlers);
91 struct mft_registration
93 struct list entry;
94 IClassFactory *factory;
95 CLSID clsid;
96 GUID category;
97 WCHAR *name;
98 DWORD flags;
99 MFT_REGISTER_TYPE_INFO *input_types;
100 UINT32 input_types_count;
101 MFT_REGISTER_TYPE_INFO *output_types;
102 UINT32 output_types_count;
103 BOOL local;
106 static CRITICAL_SECTION local_mfts_section = { NULL, -1, 0, 0, 0, 0 };
108 static struct list local_mfts = LIST_INIT(local_mfts);
110 struct transform_activate
112 struct attributes attributes;
113 IMFActivate IMFActivate_iface;
114 IClassFactory *factory;
115 IMFTransform *transform;
118 struct system_clock
120 IMFClock IMFClock_iface;
121 LONG refcount;
124 struct system_time_source
126 IMFPresentationTimeSource IMFPresentationTimeSource_iface;
127 IMFClockStateSink IMFClockStateSink_iface;
128 LONG refcount;
129 MFCLOCK_STATE state;
130 IMFClock *clock;
131 LONGLONG start_offset;
132 float rate;
133 int i_rate;
134 CRITICAL_SECTION cs;
137 static void system_time_source_apply_rate(const struct system_time_source *source, LONGLONG *value)
139 if (source->i_rate)
140 *value *= source->i_rate;
141 else
142 *value *= source->rate;
145 static struct system_time_source *impl_from_IMFPresentationTimeSource(IMFPresentationTimeSource *iface)
147 return CONTAINING_RECORD(iface, struct system_time_source, IMFPresentationTimeSource_iface);
150 static struct system_time_source *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
152 return CONTAINING_RECORD(iface, struct system_time_source, IMFClockStateSink_iface);
155 static struct system_clock *impl_from_IMFClock(IMFClock *iface)
157 return CONTAINING_RECORD(iface, struct system_clock, IMFClock_iface);
160 static struct transform_activate *impl_from_IMFActivate(IMFActivate *iface)
162 return CONTAINING_RECORD(iface, struct transform_activate, IMFActivate_iface);
165 static HRESULT WINAPI transform_activate_QueryInterface(IMFActivate *iface, REFIID riid, void **out)
167 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
169 if (IsEqualIID(riid, &IID_IMFActivate) ||
170 IsEqualIID(riid, &IID_IMFAttributes) ||
171 IsEqualIID(riid, &IID_IUnknown))
173 *out = iface;
174 IMFActivate_AddRef(iface);
175 return S_OK;
178 WARN("Unsupported %s.\n", debugstr_guid(riid));
179 *out = NULL;
180 return E_NOINTERFACE;
183 static ULONG WINAPI transform_activate_AddRef(IMFActivate *iface)
185 struct transform_activate *activate = impl_from_IMFActivate(iface);
186 ULONG refcount = InterlockedIncrement(&activate->attributes.ref);
188 TRACE("%p, refcount %u.\n", iface, refcount);
190 return refcount;
193 static ULONG WINAPI transform_activate_Release(IMFActivate *iface)
195 struct transform_activate *activate = impl_from_IMFActivate(iface);
196 ULONG refcount = InterlockedDecrement(&activate->attributes.ref);
198 TRACE("%p, refcount %u.\n", iface, refcount);
200 if (!refcount)
202 clear_attributes_object(&activate->attributes);
203 if (activate->factory)
204 IClassFactory_Release(activate->factory);
205 if (activate->transform)
206 IMFTransform_Release(activate->transform);
207 heap_free(activate);
210 return refcount;
213 static HRESULT WINAPI transform_activate_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value)
215 struct transform_activate *activate = impl_from_IMFActivate(iface);
217 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
219 return attributes_GetItem(&activate->attributes, key, value);
222 static HRESULT WINAPI transform_activate_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
224 struct transform_activate *activate = impl_from_IMFActivate(iface);
226 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
228 return attributes_GetItemType(&activate->attributes, key, type);
231 static HRESULT WINAPI transform_activate_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value,
232 BOOL *result)
234 struct transform_activate *activate = impl_from_IMFActivate(iface);
236 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
238 return attributes_CompareItem(&activate->attributes, key, value, result);
241 static HRESULT WINAPI transform_activate_Compare(IMFActivate *iface, IMFAttributes *theirs,
242 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
244 struct transform_activate *activate = impl_from_IMFActivate(iface);
246 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
248 return attributes_Compare(&activate->attributes, theirs, match_type, ret);
251 static HRESULT WINAPI transform_activate_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value)
253 struct transform_activate *activate = impl_from_IMFActivate(iface);
255 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
257 return attributes_GetUINT32(&activate->attributes, key, value);
260 static HRESULT WINAPI transform_activate_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value)
262 struct transform_activate *activate = impl_from_IMFActivate(iface);
264 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
266 return attributes_GetUINT64(&activate->attributes, key, value);
269 static HRESULT WINAPI transform_activate_GetDouble(IMFActivate *iface, REFGUID key, double *value)
271 struct transform_activate *activate = impl_from_IMFActivate(iface);
273 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
275 return attributes_GetDouble(&activate->attributes, key, value);
278 static HRESULT WINAPI transform_activate_GetGUID(IMFActivate *iface, REFGUID key, GUID *value)
280 struct transform_activate *activate = impl_from_IMFActivate(iface);
282 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
284 return attributes_GetGUID(&activate->attributes, key, value);
287 static HRESULT WINAPI transform_activate_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length)
289 struct transform_activate *activate = impl_from_IMFActivate(iface);
291 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
293 return attributes_GetStringLength(&activate->attributes, key, length);
296 static HRESULT WINAPI transform_activate_GetString(IMFActivate *iface, REFGUID key, WCHAR *value,
297 UINT32 size, UINT32 *length)
299 struct transform_activate *activate = impl_from_IMFActivate(iface);
301 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
303 return attributes_GetString(&activate->attributes, key, value, size, length);
306 static HRESULT WINAPI transform_activate_GetAllocatedString(IMFActivate *iface, REFGUID key, WCHAR **value,
307 UINT32 *length)
309 struct transform_activate *activate = impl_from_IMFActivate(iface);
311 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
313 return attributes_GetAllocatedString(&activate->attributes, key, value, length);
316 static HRESULT WINAPI transform_activate_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size)
318 struct transform_activate *activate = impl_from_IMFActivate(iface);
320 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
322 return attributes_GetBlobSize(&activate->attributes, key, size);
325 static HRESULT WINAPI transform_activate_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf, UINT32 bufsize,
326 UINT32 *blobsize)
328 struct transform_activate *activate = impl_from_IMFActivate(iface);
330 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
332 return attributes_GetBlob(&activate->attributes, key, buf, bufsize, blobsize);
335 static HRESULT WINAPI transform_activate_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size)
337 struct transform_activate *activate = impl_from_IMFActivate(iface);
339 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
341 return attributes_GetAllocatedBlob(&activate->attributes, key, buf, size);
344 static HRESULT WINAPI transform_activate_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **out)
346 struct transform_activate *activate = impl_from_IMFActivate(iface);
348 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
350 return attributes_GetUnknown(&activate->attributes, key, riid, out);
353 static HRESULT WINAPI transform_activate_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value)
355 struct transform_activate *activate = impl_from_IMFActivate(iface);
357 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
359 return attributes_SetItem(&activate->attributes, key, value);
362 static HRESULT WINAPI transform_activate_DeleteItem(IMFActivate *iface, REFGUID key)
364 struct transform_activate *activate = impl_from_IMFActivate(iface);
366 TRACE("%p, %s.\n", iface, debugstr_attr(key));
368 return attributes_DeleteItem(&activate->attributes, key);
371 static HRESULT WINAPI transform_activate_DeleteAllItems(IMFActivate *iface)
373 struct transform_activate *activate = impl_from_IMFActivate(iface);
375 TRACE("%p.\n", iface);
377 return attributes_DeleteAllItems(&activate->attributes);
380 static HRESULT WINAPI transform_activate_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value)
382 struct transform_activate *activate = impl_from_IMFActivate(iface);
384 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
386 return attributes_SetUINT32(&activate->attributes, key, value);
389 static HRESULT WINAPI transform_activate_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value)
391 struct transform_activate *activate = impl_from_IMFActivate(iface);
393 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
395 return attributes_SetUINT64(&activate->attributes, key, value);
398 static HRESULT WINAPI transform_activate_SetDouble(IMFActivate *iface, REFGUID key, double value)
400 struct transform_activate *activate = impl_from_IMFActivate(iface);
402 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
404 return attributes_SetDouble(&activate->attributes, key, value);
407 static HRESULT WINAPI transform_activate_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value)
409 struct transform_activate *activate = impl_from_IMFActivate(iface);
411 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
413 return attributes_SetGUID(&activate->attributes, key, value);
416 static HRESULT WINAPI transform_activate_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value)
418 struct transform_activate *activate = impl_from_IMFActivate(iface);
420 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
422 return attributes_SetString(&activate->attributes, key, value);
425 static HRESULT WINAPI transform_activate_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size)
427 struct transform_activate *activate = impl_from_IMFActivate(iface);
429 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
431 return attributes_SetBlob(&activate->attributes, key, buf, size);
434 static HRESULT WINAPI transform_activate_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown)
436 struct transform_activate *activate = impl_from_IMFActivate(iface);
438 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
440 return attributes_SetUnknown(&activate->attributes, key, unknown);
443 static HRESULT WINAPI transform_activate_LockStore(IMFActivate *iface)
445 struct transform_activate *activate = impl_from_IMFActivate(iface);
447 TRACE("%p.\n", iface);
449 return attributes_LockStore(&activate->attributes);
452 static HRESULT WINAPI transform_activate_UnlockStore(IMFActivate *iface)
454 struct transform_activate *activate = impl_from_IMFActivate(iface);
456 TRACE("%p.\n", iface);
458 return attributes_UnlockStore(&activate->attributes);
461 static HRESULT WINAPI transform_activate_GetCount(IMFActivate *iface, UINT32 *count)
463 struct transform_activate *activate = impl_from_IMFActivate(iface);
465 TRACE("%p, %p.\n", iface, count);
467 return attributes_GetCount(&activate->attributes, count);
470 static HRESULT WINAPI transform_activate_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key,
471 PROPVARIANT *value)
473 struct transform_activate *activate = impl_from_IMFActivate(iface);
475 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
477 return attributes_GetItemByIndex(&activate->attributes, index, key, value);
480 static HRESULT WINAPI transform_activate_CopyAllItems(IMFActivate *iface, IMFAttributes *dest)
482 struct transform_activate *activate = impl_from_IMFActivate(iface);
484 TRACE("%p, %p.\n", iface, dest);
486 return attributes_CopyAllItems(&activate->attributes, dest);
489 static HRESULT WINAPI transform_activate_ActivateObject(IMFActivate *iface, REFIID riid, void **obj)
491 struct transform_activate *activate = impl_from_IMFActivate(iface);
492 CLSID clsid;
493 HRESULT hr;
495 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
497 EnterCriticalSection(&activate->attributes.cs);
499 if (!activate->transform)
501 if (activate->factory)
503 if (FAILED(hr = IClassFactory_CreateInstance(activate->factory, NULL, &IID_IMFTransform,
504 (void **)&activate->transform)))
506 hr = MF_E_INVALIDREQUEST;
509 else
511 if (SUCCEEDED(hr = attributes_GetGUID(&activate->attributes, &MFT_TRANSFORM_CLSID_Attribute, &clsid)))
513 if (FAILED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform,
514 (void **)&activate->transform)))
516 hr = MF_E_INVALIDREQUEST;
522 if (activate->transform)
523 hr = IMFTransform_QueryInterface(activate->transform, riid, obj);
525 LeaveCriticalSection(&activate->attributes.cs);
527 return hr;
530 static HRESULT WINAPI transform_activate_ShutdownObject(IMFActivate *iface)
532 struct transform_activate *activate = impl_from_IMFActivate(iface);
534 TRACE("%p.\n", iface);
536 EnterCriticalSection(&activate->attributes.cs);
538 if (activate->transform)
540 IMFTransform_Release(activate->transform);
541 activate->transform = NULL;
544 LeaveCriticalSection(&activate->attributes.cs);
546 return S_OK;
549 static HRESULT WINAPI transform_activate_DetachObject(IMFActivate *iface)
551 TRACE("%p.\n", iface);
553 return E_NOTIMPL;
556 static const IMFActivateVtbl transform_activate_vtbl =
558 transform_activate_QueryInterface,
559 transform_activate_AddRef,
560 transform_activate_Release,
561 transform_activate_GetItem,
562 transform_activate_GetItemType,
563 transform_activate_CompareItem,
564 transform_activate_Compare,
565 transform_activate_GetUINT32,
566 transform_activate_GetUINT64,
567 transform_activate_GetDouble,
568 transform_activate_GetGUID,
569 transform_activate_GetStringLength,
570 transform_activate_GetString,
571 transform_activate_GetAllocatedString,
572 transform_activate_GetBlobSize,
573 transform_activate_GetBlob,
574 transform_activate_GetAllocatedBlob,
575 transform_activate_GetUnknown,
576 transform_activate_SetItem,
577 transform_activate_DeleteItem,
578 transform_activate_DeleteAllItems,
579 transform_activate_SetUINT32,
580 transform_activate_SetUINT64,
581 transform_activate_SetDouble,
582 transform_activate_SetGUID,
583 transform_activate_SetString,
584 transform_activate_SetBlob,
585 transform_activate_SetUnknown,
586 transform_activate_LockStore,
587 transform_activate_UnlockStore,
588 transform_activate_GetCount,
589 transform_activate_GetItemByIndex,
590 transform_activate_CopyAllItems,
591 transform_activate_ActivateObject,
592 transform_activate_ShutdownObject,
593 transform_activate_DetachObject,
596 static HRESULT create_transform_activate(IClassFactory *factory, IMFActivate **activate)
598 struct transform_activate *object;
599 HRESULT hr;
601 object = heap_alloc_zero(sizeof(*object));
602 if (!object)
603 return E_OUTOFMEMORY;
605 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
607 heap_free(object);
608 return hr;
611 object->IMFActivate_iface.lpVtbl = &transform_activate_vtbl;
612 object->factory = factory;
613 if (object->factory)
614 IClassFactory_AddRef(object->factory);
616 *activate = &object->IMFActivate_iface;
618 return S_OK;
621 HRESULT WINAPI MFCreateTransformActivate(IMFActivate **activate)
623 TRACE("%p.\n", activate);
625 return create_transform_activate(NULL, activate);
628 static const WCHAR transform_keyW[] = L"MediaFoundation\\Transforms";
629 static const WCHAR categories_keyW[] = L"MediaFoundation\\Transforms\\Categories";
631 static const BYTE guid_conv_table[256] =
633 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
634 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
635 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
636 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
637 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
638 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
639 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
642 static WCHAR* GUIDToString(WCHAR *str, REFGUID guid)
644 swprintf(str, 39, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
645 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1],
646 guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5],
647 guid->Data4[6], guid->Data4[7]);
649 return str;
652 static inline BOOL is_valid_hex(WCHAR c)
654 if (!(((c >= '0') && (c <= '9')) ||
655 ((c >= 'a') && (c <= 'f')) ||
656 ((c >= 'A') && (c <= 'F'))))
657 return FALSE;
658 return TRUE;
661 static BOOL GUIDFromString(LPCWSTR s, GUID *id)
663 int i;
665 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
667 id->Data1 = 0;
668 for (i = 0; i < 8; i++)
670 if (!is_valid_hex(s[i])) return FALSE;
671 id->Data1 = (id->Data1 << 4) | guid_conv_table[s[i]];
673 if (s[8]!='-') return FALSE;
675 id->Data2 = 0;
676 for (i = 9; i < 13; i++)
678 if (!is_valid_hex(s[i])) return FALSE;
679 id->Data2 = (id->Data2 << 4) | guid_conv_table[s[i]];
681 if (s[13]!='-') return FALSE;
683 id->Data3 = 0;
684 for (i = 14; i < 18; i++)
686 if (!is_valid_hex(s[i])) return FALSE;
687 id->Data3 = (id->Data3 << 4) | guid_conv_table[s[i]];
689 if (s[18]!='-') return FALSE;
691 for (i = 19; i < 36; i+=2)
693 if (i == 23)
695 if (s[i]!='-') return FALSE;
696 i++;
698 if (!is_valid_hex(s[i]) || !is_valid_hex(s[i+1])) return FALSE;
699 id->Data4[(i-19)/2] = guid_conv_table[s[i]] << 4 | guid_conv_table[s[i+1]];
702 if (!s[36]) return TRUE;
703 return FALSE;
706 static HRESULT register_transform(const CLSID *clsid, const WCHAR *name, UINT32 flags,
707 UINT32 cinput, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
708 const MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
710 HRESULT hr = S_OK;
711 HKEY hclsid = 0;
712 WCHAR buffer[64];
713 DWORD size, ret;
714 WCHAR str[250];
715 UINT8 *blob;
717 GUIDToString(buffer, clsid);
718 swprintf(str, ARRAY_SIZE(str), L"%s\\%s", transform_keyW, buffer);
720 if ((ret = RegCreateKeyW(HKEY_CLASSES_ROOT, str, &hclsid)))
721 hr = HRESULT_FROM_WIN32(ret);
723 if (SUCCEEDED(hr))
725 size = (lstrlenW(name) + 1) * sizeof(WCHAR);
726 if ((ret = RegSetValueExW(hclsid, NULL, 0, REG_SZ, (BYTE *)name, size)))
727 hr = HRESULT_FROM_WIN32(ret);
730 if (SUCCEEDED(hr) && cinput && input_types)
732 size = cinput * sizeof(MFT_REGISTER_TYPE_INFO);
733 if ((ret = RegSetValueExW(hclsid, L"InputTypes", 0, REG_BINARY, (BYTE *)input_types, size)))
734 hr = HRESULT_FROM_WIN32(ret);
737 if (SUCCEEDED(hr) && coutput && output_types)
739 size = coutput * sizeof(MFT_REGISTER_TYPE_INFO);
740 if ((ret = RegSetValueExW(hclsid, L"OutputTypes", 0, REG_BINARY, (BYTE *)output_types, size)))
741 hr = HRESULT_FROM_WIN32(ret);
744 if (SUCCEEDED(hr) && attributes)
746 if (SUCCEEDED(hr = MFGetAttributesAsBlobSize(attributes, &size)))
748 if ((blob = heap_alloc(size)))
750 if (SUCCEEDED(hr = MFGetAttributesAsBlob(attributes, blob, size)))
752 if ((ret = RegSetValueExW(hclsid, L"Attributes", 0, REG_BINARY, blob, size)))
753 hr = HRESULT_FROM_WIN32(ret);
755 heap_free(blob);
757 else
758 hr = E_OUTOFMEMORY;
762 if (SUCCEEDED(hr) && flags)
764 if ((ret = RegSetValueExW(hclsid, L"MFTFlags", 0, REG_DWORD, (BYTE *)&flags, sizeof(flags))))
765 hr = HRESULT_FROM_WIN32(ret);
768 RegCloseKey(hclsid);
769 return hr;
772 static HRESULT register_category(CLSID *clsid, GUID *category)
774 HKEY htmp1;
775 WCHAR guid1[64], guid2[64];
776 WCHAR str[350];
778 GUIDToString(guid1, category);
779 GUIDToString(guid2, clsid);
781 swprintf(str, ARRAY_SIZE(str), L"%s\\%s\\%s", categories_keyW, guid1, guid2);
783 if (RegCreateKeyW(HKEY_CLASSES_ROOT, str, &htmp1))
784 return E_FAIL;
786 RegCloseKey(htmp1);
787 return S_OK;
790 /***********************************************************************
791 * MFTRegister (mfplat.@)
793 HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags, UINT32 cinput,
794 MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
795 MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
797 HRESULT hr;
799 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p, %p.\n", debugstr_guid(&clsid), debugstr_guid(&category),
800 debugstr_w(name), flags, cinput, input_types, coutput, output_types, attributes);
802 hr = register_transform(&clsid, name, flags, cinput, input_types, coutput, output_types, attributes);
803 if(FAILED(hr))
804 ERR("Failed to write register transform\n");
806 if (SUCCEEDED(hr))
807 hr = register_category(&clsid, &category);
809 return hr;
812 static void release_mft_registration(struct mft_registration *mft)
814 if (mft->factory)
815 IClassFactory_Release(mft->factory);
816 heap_free(mft->name);
817 heap_free(mft->input_types);
818 heap_free(mft->output_types);
819 heap_free(mft);
822 static HRESULT mft_register_local(IClassFactory *factory, REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
823 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
824 const MFT_REGISTER_TYPE_INFO *output_types)
826 struct mft_registration *mft, *cur, *unreg_mft = NULL;
827 HRESULT hr;
829 if (!factory && !clsid)
831 WARN("Can't register without factory or CLSID.\n");
832 return E_FAIL;
835 mft = heap_alloc_zero(sizeof(*mft));
836 if (!mft)
837 return E_OUTOFMEMORY;
839 mft->factory = factory;
840 if (mft->factory)
841 IClassFactory_AddRef(mft->factory);
842 if (clsid)
843 mft->clsid = *clsid;
844 mft->category = *category;
845 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
846 flags |= MFT_ENUM_FLAG_SYNCMFT;
847 mft->flags = flags;
848 mft->local = TRUE;
849 if (FAILED(hr = heap_strdupW(name, &mft->name)))
850 goto failed;
852 if (input_count && input_types)
854 mft->input_types_count = input_count;
855 if (!(mft->input_types = heap_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 = heap_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(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 = heap_alloc(size)))
1067 goto out;
1069 *count = size / sizeof(**type);
1071 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, (BYTE *)*type, &size))
1073 heap_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 GUIDToString(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(clsidW, L"OutputTypes", &mft.output_types, &mft.output_types_count);
1137 if (input_type)
1138 mft_get_reg_type_info(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 heap_free(mft.input_types);
1143 heap_free(mft.output_types);
1144 goto next;
1147 cur = heap_alloc(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 %#x.\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 = heap_alloc_zero(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, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes,
1347 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, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, activate, count);
1394 return mft_enum(category, flags, input_type, output_type, NULL, activate, count);
1397 /***********************************************************************
1398 * MFTEnum2 (mfplat.@)
1400 HRESULT WINAPI MFTEnum2(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1401 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1403 TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes,
1404 activate, count);
1406 if (attributes)
1407 FIXME("Ignoring attributes.\n");
1409 return mft_enum(category, flags, input_type, output_type, attributes, activate, count);
1412 /***********************************************************************
1413 * MFTUnregister (mfplat.@)
1415 HRESULT WINAPI MFTUnregister(CLSID clsid)
1417 WCHAR buffer[64], category[MAX_PATH];
1418 HKEY htransform, hcategory, htmp;
1419 DWORD size = MAX_PATH;
1420 DWORD index = 0;
1422 TRACE("(%s)\n", debugstr_guid(&clsid));
1424 GUIDToString(buffer, &clsid);
1426 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1428 RegDeleteKeyW(htransform, buffer);
1429 RegCloseKey(htransform);
1432 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1434 while (RegEnumKeyExW(hcategory, index, category, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
1436 if (!RegOpenKeyW(hcategory, category, &htmp))
1438 RegDeleteKeyW(htmp, buffer);
1439 RegCloseKey(htmp);
1441 size = MAX_PATH;
1442 index++;
1444 RegCloseKey(hcategory);
1447 return S_OK;
1450 /***********************************************************************
1451 * MFStartup (mfplat.@)
1453 HRESULT WINAPI MFStartup(ULONG version, DWORD flags)
1455 #define MF_VERSION_XP MAKELONG( MF_API_VERSION, 1 )
1456 #define MF_VERSION_WIN7 MAKELONG( MF_API_VERSION, 2 )
1458 TRACE("%#x, %#x.\n", version, flags);
1460 if (version != MF_VERSION_XP && version != MF_VERSION_WIN7)
1461 return MF_E_BAD_STARTUP_VERSION;
1463 RtwqStartup();
1465 return S_OK;
1468 /***********************************************************************
1469 * MFShutdown (mfplat.@)
1471 HRESULT WINAPI MFShutdown(void)
1473 TRACE("\n");
1475 RtwqShutdown();
1477 return S_OK;
1480 /***********************************************************************
1481 * MFCopyImage (mfplat.@)
1483 HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines)
1485 TRACE("%p, %d, %p, %d, %u, %u.\n", dest, deststride, src, srcstride, width, lines);
1487 while (lines--)
1489 memcpy(dest, src, width);
1490 dest += deststride;
1491 src += srcstride;
1494 return S_OK;
1497 struct guid_def
1499 const GUID *guid;
1500 const char *name;
1503 static int __cdecl debug_compare_guid(const void *a, const void *b)
1505 const GUID *guid = a;
1506 const struct guid_def *guid_def = b;
1507 return memcmp(guid, guid_def->guid, sizeof(*guid));
1510 const char *debugstr_attr(const GUID *guid)
1512 static const struct guid_def guid_defs[] =
1514 #define X(g) { &(g), #g }
1515 #define MF_READER_WRITER_D3D_MANAGER MF_SOURCE_READER_D3D_MANAGER
1516 X(MF_READWRITE_MMCSS_CLASS),
1517 X(MF_TOPONODE_MARKIN_HERE),
1518 X(MF_MT_H264_SUPPORTED_SYNC_FRAME_TYPES),
1519 X(MF_TOPONODE_MARKOUT_HERE),
1520 X(EVRConfig_ForceBob),
1521 X(MF_TOPONODE_DECODER),
1522 X(EVRConfig_AllowDropToBob),
1523 X(MF_TOPOLOGY_PROJECTSTART),
1524 X(EVRConfig_ForceThrottle),
1525 X(MF_VIDEO_MAX_MB_PER_SEC),
1526 X(MF_TOPOLOGY_PROJECTSTOP),
1527 X(MF_SINK_WRITER_ENCODER_CONFIG),
1528 X(EVRConfig_AllowDropToThrottle),
1529 X(MF_TOPOLOGY_NO_MARKIN_MARKOUT),
1530 X(EVRConfig_ForceHalfInterlace),
1531 X(EVRConfig_AllowDropToHalfInterlace),
1532 X(EVRConfig_ForceScaling),
1533 X(MF_MT_H264_CAPABILITIES),
1534 X(EVRConfig_AllowScaling),
1535 X(MF_SOURCE_READER_ENABLE_TRANSCODE_ONLY_TRANSFORMS),
1536 X(MFT_PREFERRED_ENCODER_PROFILE),
1537 X(EVRConfig_ForceBatching),
1538 X(EVRConfig_AllowBatching),
1539 X(MF_TOPOLOGY_DYNAMIC_CHANGE_NOT_ALLOWED),
1540 X(MF_MT_VIDEO_PROFILE),
1541 X(MF_MT_MPEG2_PROFILE),
1542 X(MF_MT_DV_AAUX_CTRL_PACK_1),
1543 X(MF_MT_ALPHA_MODE),
1544 X(MF_MT_MPEG2_TIMECODE),
1545 X(MF_PMP_SERVER_CONTEXT),
1546 X(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE),
1547 X(MF_MEDIA_ENGINE_TRACK_ID),
1548 X(MF_MT_CUSTOM_VIDEO_PRIMARIES),
1549 X(MF_MT_TIMESTAMP_CAN_BE_DTS),
1550 X(MFT_CODEC_MERIT_Attribute),
1551 X(MF_TOPOLOGY_PLAYBACK_MAX_DIMS),
1552 X(MF_LOW_LATENCY),
1553 X(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS),
1554 X(MF_MT_MPEG2_FLAGS),
1555 X(MF_MEDIA_ENGINE_AUDIO_CATEGORY),
1556 X(MF_MT_PIXEL_ASPECT_RATIO),
1557 X(MF_TOPOLOGY_ENABLE_XVP_FOR_PLAYBACK),
1558 X(MFT_CONNECTED_STREAM_ATTRIBUTE),
1559 X(MF_MT_REALTIME_CONTENT),
1560 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_FLAGS),
1561 X(MF_MT_WRAPPED_TYPE),
1562 X(MF_MT_DRM_FLAGS),
1563 X(MF_MT_AVG_BITRATE),
1564 X(MF_MT_DECODER_USE_MAX_RESOLUTION),
1565 X(MF_MT_MAX_LUMINANCE_LEVEL),
1566 X(MFT_CONNECTED_TO_HW_STREAM),
1567 X(MF_SA_D3D_AWARE),
1568 X(MF_MT_MAX_KEYFRAME_SPACING),
1569 X(MFT_TRANSFORM_CLSID_Attribute),
1570 X(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING),
1571 X(MF_MT_AM_FORMAT_TYPE),
1572 X(MF_SESSION_APPROX_EVENT_OCCURRENCE_TIME),
1573 X(MF_MEDIA_ENGINE_SYNCHRONOUS_CLOSE),
1574 X(MF_MT_H264_MAX_MB_PER_SEC),
1575 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_MAX_BUFFERS),
1576 X(MF_MT_AUDIO_BLOCK_ALIGNMENT),
1577 X(MF_PD_PMPHOST_CONTEXT),
1578 X(MF_PD_APP_CONTEXT),
1579 X(MF_PD_DURATION),
1580 X(MF_PD_TOTAL_FILE_SIZE),
1581 X(MF_PD_AUDIO_ENCODING_BITRATE),
1582 X(MF_PD_VIDEO_ENCODING_BITRATE),
1583 X(MFSampleExtension_TargetGlobalLuminance),
1584 X(MF_PD_MIME_TYPE),
1585 X(MF_MT_H264_SUPPORTED_SLICE_MODES),
1586 X(MF_PD_LAST_MODIFIED_TIME),
1587 X(MF_PD_PLAYBACK_ELEMENT_ID),
1588 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE9),
1589 X(MF_MT_ALL_SAMPLES_INDEPENDENT),
1590 X(MF_PD_PREFERRED_LANGUAGE),
1591 X(MF_PD_PLAYBACK_BOUNDARY_TIME),
1592 X(MF_MEDIA_ENGINE_TELEMETRY_APPLICATION_ID),
1593 X(MF_ACTIVATE_MFT_LOCKED),
1594 X(MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT),
1595 X(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING),
1596 X(MF_MT_FRAME_SIZE),
1597 X(MF_MT_H264_SIMULCAST_SUPPORT),
1598 X(MF_SINK_WRITER_ASYNC_CALLBACK),
1599 X(MF_TOPOLOGY_START_TIME_ON_PRESENTATION_SWITCH),
1600 X(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER),
1601 X(MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY),
1602 X(MF_MT_FRAME_RATE_RANGE_MAX),
1603 X(MF_MT_PALETTE),
1604 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_PROVIDER_DEVICE_ID),
1605 X(MF_TOPOLOGY_STATIC_PLAYBACK_OPTIMIZATIONS),
1606 X(MF_SA_D3D11_USAGE),
1607 X(MF_MEDIA_ENGINE_NEEDKEY_CALLBACK),
1608 X(MF_MT_GEOMETRIC_APERTURE),
1609 X(MF_MT_ORIGINAL_WAVE_FORMAT_TAG),
1610 X(MF_MT_DV_AAUX_SRC_PACK_1),
1611 X(MF_MEDIA_ENGINE_STREAM_CONTAINS_ALPHA_CHANNEL),
1612 X(MF_MEDIA_ENGINE_MEDIA_PLAYER_MODE),
1613 X(MF_MEDIA_ENGINE_EXTENSION),
1614 X(MF_MT_DEFAULT_STRIDE),
1615 X(MF_MT_ARBITRARY_FORMAT),
1616 X(MF_TRANSFORM_CATEGORY_Attribute),
1617 X(MF_MT_MPEG2_HDCP),
1618 X(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
1619 X(MF_MT_SPATIAL_AUDIO_MAX_DYNAMIC_OBJECTS),
1620 X(MF_MT_DECODER_MAX_DPB_COUNT),
1621 X(MFSampleExtension_ForwardedDecodeUnits),
1622 X(MF_SA_D3D11_SHARED_WITHOUT_MUTEX),
1623 X(MF_MT_DV_AAUX_CTRL_PACK_0),
1624 X(MF_MT_YUV_MATRIX),
1625 X(MF_EVENT_SOURCE_TOPOLOGY_CANCELED),
1626 X(MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY),
1627 X(MF_MT_MAX_FRAME_AVERAGE_LUMINANCE_LEVEL),
1628 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID),
1629 X(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME),
1630 X(MF_MT_VIDEO_ROTATION),
1631 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_SYMBOLIC_LINK),
1632 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE11),
1633 X(MF_MT_USER_DATA),
1634 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID),
1635 X(MF_MT_MIN_MASTERING_LUMINANCE),
1636 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE),
1637 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS),
1638 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID),
1639 X(MF_EVENT_STREAM_METADATA_SYSTEMID),
1640 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE),
1641 X(MF_MT_AUDIO_CHANNEL_MASK),
1642 X(MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN),
1643 X(MF_READWRITE_DISABLE_CONVERTERS),
1644 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE_EDGE),
1645 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS),
1646 X(MF_MT_MINIMUM_DISPLAY_APERTURE),
1647 X(MFSampleExtension_Token),
1648 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_CATEGORY),
1649 X(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
1650 X(MF_TRANSFORM_ASYNC_UNLOCK),
1651 X(MF_DISABLE_FRAME_CORRUPTION_INFO),
1652 X(MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES),
1653 X(MF_MT_VIDEO_NO_FRAME_ORDERING),
1654 X(MF_MEDIA_ENGINE_PLAYBACK_VISUAL),
1655 X(MF_MT_VIDEO_CHROMA_SITING),
1656 X(MF_AUDIO_RENDERER_ATTRIBUTE_STREAM_CATEGORY),
1657 X(MF_SA_BUFFERS_PER_SAMPLE),
1658 X(MFSampleExtension_3DVideo_SampleFormat),
1659 X(MF_MT_H264_RESOLUTION_SCALING),
1660 X(MF_MT_VIDEO_LEVEL),
1661 X(MF_MT_MPEG2_LEVEL),
1662 X(MF_SAMPLEGRABBERSINK_SAMPLE_TIME_OFFSET),
1663 X(MF_MT_SAMPLE_SIZE),
1664 X(MF_MT_AAC_PAYLOAD_TYPE),
1665 X(MF_TOPOLOGY_PLAYBACK_FRAMERATE),
1666 X(MF_SOURCE_READER_D3D11_BIND_FLAGS),
1667 X(MF_MT_AUDIO_FOLDDOWN_MATRIX),
1668 X(MF_MT_AUDIO_WMADRC_PEAKREF),
1669 X(MF_MT_AUDIO_WMADRC_PEAKTARGET),
1670 X(MF_TRANSFORM_FLAGS_Attribute),
1671 X(MF_MT_H264_SUPPORTED_RATE_CONTROL_MODES),
1672 X(MF_PD_SAMI_STYLELIST),
1673 X(MF_MT_AUDIO_WMADRC_AVGREF),
1674 X(MF_MT_AUDIO_BITS_PER_SAMPLE),
1675 X(MF_SD_LANGUAGE),
1676 X(MF_MT_AUDIO_WMADRC_AVGTARGET),
1677 X(MF_SD_PROTECTED),
1678 X(MF_SESSION_TOPOLOADER),
1679 X(MF_SESSION_GLOBAL_TIME),
1680 X(MF_SESSION_QUALITY_MANAGER),
1681 X(MF_SESSION_CONTENT_PROTECTION_MANAGER),
1682 X(MF_MT_MPEG4_SAMPLE_DESCRIPTION),
1683 X(MF_MT_MPEG_START_TIME_CODE),
1684 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1685 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1686 X(MF_READWRITE_MMCSS_PRIORITY_AUDIO),
1687 X(MF_MT_H264_MAX_CODEC_CONFIG_DELAY),
1688 X(MF_MT_DV_AAUX_SRC_PACK_0),
1689 X(MF_BYTESTREAM_ORIGIN_NAME),
1690 X(MF_BYTESTREAM_CONTENT_TYPE),
1691 X(MF_MT_DEPTH_MEASUREMENT),
1692 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WIN10),
1693 X(MF_MT_VIDEO_3D_NUM_VIEWS),
1694 X(MF_BYTESTREAM_DURATION),
1695 X(MF_SD_SAMI_LANGUAGE),
1696 X(MF_EVENT_OUTPUT_NODE),
1697 X(MF_BYTESTREAM_LAST_MODIFIED_TIME),
1698 X(MFT_ENUM_ADAPTER_LUID),
1699 X(MF_MT_FRAME_RATE_RANGE_MIN),
1700 X(MF_BYTESTREAM_IFO_FILE_URI),
1701 X(MF_EVENT_TOPOLOGY_STATUS),
1702 X(MF_BYTESTREAM_DLNA_PROFILE_ID),
1703 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ROLE),
1704 X(MF_MT_MAJOR_TYPE),
1705 X(MF_MT_IN_BAND_PARAMETER_SET),
1706 X(MF_EVENT_SOURCE_CHARACTERISTICS),
1707 X(MF_EVENT_SOURCE_CHARACTERISTICS_OLD),
1708 X(MF_SESSION_SERVER_CONTEXT),
1709 X(MF_MT_VIDEO_3D_FIRST_IS_LEFT),
1710 X(MFT_DECODER_FINAL_VIDEO_RESOLUTION_HINT),
1711 X(MF_PD_ADAPTIVE_STREAMING),
1712 X(MF_MEDIA_ENGINE_SOURCE_RESOLVER_CONFIG_STORE),
1713 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WWA_EDGE),
1714 X(MF_MT_H264_SUPPORTED_USAGES),
1715 X(MFT_PREFERRED_OUTPUTTYPE_Attribute),
1716 X(MFSampleExtension_Timestamp),
1717 X(MF_TOPONODE_PRIMARYOUTPUT),
1718 X(MF_MT_SUBTYPE),
1719 X(MF_TRANSFORM_ASYNC),
1720 X(MF_TOPONODE_STREAMID),
1721 X(MF_MEDIA_ENGINE_PLAYBACK_HWND),
1722 X(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE),
1723 X(MF_MT_VIDEO_LIGHTING),
1724 X(MF_SD_MUTUALLY_EXCLUSIVE),
1725 X(MF_SD_STREAM_NAME),
1726 X(MF_MT_DV_VAUX_SRC_PACK),
1727 X(MF_TOPONODE_RATELESS),
1728 X(MF_EVENT_STREAM_METADATA_CONTENT_KEYIDS),
1729 X(MF_TOPONODE_DISABLE_PREROLL),
1730 X(MF_SA_D3D11_ALLOW_DYNAMIC_YUV_TEXTURE),
1731 X(MF_MT_VIDEO_3D_FORMAT),
1732 X(MF_EVENT_STREAM_METADATA_KEYDATA),
1733 X(MF_READER_WRITER_D3D_MANAGER),
1734 X(MFSampleExtension_3DVideo),
1735 X(MF_MT_H264_USAGE),
1736 X(MF_MEDIA_ENGINE_EME_CALLBACK),
1737 X(MF_EVENT_SOURCE_FAKE_START),
1738 X(MF_EVENT_SOURCE_PROJECTSTART),
1739 X(MF_EVENT_SOURCE_ACTUAL_START),
1740 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_MANAGER),
1741 X(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
1742 X(MFT_ENUM_HARDWARE_URL_Attribute),
1743 X(MF_SOURCE_READER_ASYNC_CALLBACK),
1744 X(MF_MT_OUTPUT_BUFFER_NUM),
1745 X(MF_SA_D3D11_BINDFLAGS),
1746 X(MFT_ENCODER_SUPPORTS_CONFIG_EVENT),
1747 X(MF_MT_AUDIO_FLAC_MAX_BLOCK_SIZE),
1748 X(MFT_FRIENDLY_NAME_Attribute),
1749 X(MF_MT_FIXED_SIZE_SAMPLES),
1750 X(MFT_SUPPORT_3DVIDEO),
1751 X(MFT_SUPPORT_3DVIDEO),
1752 X(MFT_INPUT_TYPES_Attributes),
1753 X(MF_MT_H264_LAYOUT_PER_STREAM),
1754 X(MF_EVENT_SCRUBSAMPLE_TIME),
1755 X(MF_MT_SPATIAL_AUDIO_MAX_METADATA_ITEMS),
1756 X(MF_MT_MPEG2_ONE_FRAME_PER_PACKET),
1757 X(MF_MT_INTERLACE_MODE),
1758 X(MF_MEDIA_ENGINE_CALLBACK),
1759 X(MF_MT_VIDEO_RENDERER_EXTENSION_PROFILE),
1760 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_HW_SOURCE),
1761 X(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
1762 X(MF_MT_H264_SVC_CAPABILITIES),
1763 X(MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY),
1764 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_LENGTH),
1765 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_FORMAT_ID),
1766 X(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK),
1767 X(MF_SA_D3D11_SHARED),
1768 X(MF_MT_PAN_SCAN_ENABLED),
1769 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID),
1770 X(MF_MT_DV_VAUX_CTRL_PACK),
1771 X(MFSampleExtension_ForwardedDecodeUnitType),
1772 X(MF_SA_D3D11_AWARE),
1773 X(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
1774 X(MF_SOURCE_READER_MEDIASOURCE_CHARACTERISTICS),
1775 X(MF_MT_SPATIAL_AUDIO_MIN_METADATA_ITEM_OFFSET_SPACING),
1776 X(MF_TOPONODE_TRANSFORM_OBJECTID),
1777 X(MF_DEVSOURCE_ATTRIBUTE_MEDIA_TYPE),
1778 X(MF_EVENT_MFT_INPUT_STREAM_ID),
1779 X(MF_MT_SOURCE_CONTENT_HINT),
1780 X(MFT_ENUM_HARDWARE_VENDOR_ID_Attribute),
1781 X(MFT_ENUM_TRANSCODE_ONLY_ATTRIBUTE),
1782 X(MF_READWRITE_MMCSS_PRIORITY),
1783 X(MF_MT_VIDEO_3D),
1784 X(MF_EVENT_START_PRESENTATION_TIME),
1785 X(MF_EVENT_SESSIONCAPS),
1786 X(MF_EVENT_PRESENTATION_TIME_OFFSET),
1787 X(MF_MEDIA_ENGINE_AUDIO_ENDPOINT_ROLE),
1788 X(MF_EVENT_SESSIONCAPS_DELTA),
1789 X(MF_EVENT_START_PRESENTATION_TIME_AT_OUTPUT),
1790 X(MFSampleExtension_DecodeTimestamp),
1791 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE),
1792 X(MF_MT_VIDEO_H264_NO_FMOASO),
1793 X(MF_MT_AVG_BIT_ERROR_RATE),
1794 X(MF_MT_VIDEO_PRIMARIES),
1795 X(MF_SINK_WRITER_DISABLE_THROTTLING),
1796 X(MF_MT_H264_RATE_CONTROL_MODES),
1797 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK),
1798 X(MF_READWRITE_D3D_OPTIONAL),
1799 X(MF_SA_D3D11_HW_PROTECTED),
1800 X(MF_MEDIA_ENGINE_DXGI_MANAGER),
1801 X(MF_READWRITE_MMCSS_CLASS_AUDIO),
1802 X(MF_MEDIA_ENGINE_COREWINDOW),
1803 X(MF_SOURCE_READER_DISABLE_CAMERA_PLUGINS),
1804 X(MF_MT_MPEG4_TRACK_TYPE),
1805 X(MF_ACTIVATE_VIDEO_WINDOW),
1806 X(MF_MT_PAN_SCAN_APERTURE),
1807 X(MF_TOPOLOGY_RESOLUTION_STATUS),
1808 X(MF_MT_ORIGINAL_4CC),
1809 X(MF_PD_AUDIO_ISVARIABLEBITRATE),
1810 X(MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS),
1811 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE),
1812 X(MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID),
1813 X(MF_MT_MPEG2_CONTENT_PACKET),
1814 X(MFT_PROCESS_LOCAL_Attribute),
1815 X(MFT_PROCESS_LOCAL_Attribute),
1816 X(MF_MT_PAD_CONTROL_FLAGS),
1817 X(MF_MT_VIDEO_NOMINAL_RANGE),
1818 X(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
1819 X(MF_MT_MPEG_SEQUENCE_HEADER),
1820 X(MF_MEDIA_ENGINE_OPM_HWND),
1821 X(MF_MT_AUDIO_SAMPLES_PER_SECOND),
1822 X(MF_MT_SPATIAL_AUDIO_DATA_PRESENT),
1823 X(MF_MT_FRAME_RATE),
1824 X(MF_TOPONODE_FLUSH),
1825 X(MF_MT_MPEG2_STANDARD),
1826 X(MF_TOPONODE_DRAIN),
1827 X(MF_MT_TRANSFER_FUNCTION),
1828 X(MF_TOPONODE_MEDIASTART),
1829 X(MF_TOPONODE_MEDIASTOP),
1830 X(MF_SOURCE_READER_MEDIASOURCE_CONFIG),
1831 X(MF_TOPONODE_SOURCE),
1832 X(MF_TOPONODE_PRESENTATION_DESCRIPTOR),
1833 X(MF_TOPONODE_D3DAWARE),
1834 X(MF_MT_COMPRESSED),
1835 X(MF_TOPONODE_STREAM_DESCRIPTOR),
1836 X(MF_TOPONODE_ERRORCODE),
1837 X(MF_TOPONODE_SEQUENCE_ELEMENTID),
1838 X(MF_EVENT_MFT_CONTEXT),
1839 X(MF_MT_FORWARD_CUSTOM_SEI),
1840 X(MF_TOPONODE_CONNECT_METHOD),
1841 X(MFT_OUTPUT_TYPES_Attributes),
1842 X(MF_MT_IMAGE_LOSS_TOLERANT),
1843 X(MF_SESSION_REMOTE_SOURCE_MODE),
1844 X(MF_MT_DEPTH_VALUE_UNIT),
1845 X(MF_MT_AUDIO_NUM_CHANNELS),
1846 X(MF_MT_ARBITRARY_HEADER),
1847 X(MF_TOPOLOGY_DXVA_MODE),
1848 X(MF_TOPONODE_LOCKED),
1849 X(MF_TOPONODE_WORKQUEUE_ID),
1850 X(MF_MEDIA_ENGINE_CONTINUE_ON_CODEC_ERROR),
1851 X(MF_TOPONODE_WORKQUEUE_MMCSS_CLASS),
1852 X(MF_TOPONODE_DECRYPTOR),
1853 X(MF_EVENT_DO_THINNING),
1854 X(MF_TOPONODE_DISCARDABLE),
1855 X(MF_TOPOLOGY_HARDWARE_MODE),
1856 X(MF_SOURCE_READER_DISABLE_DXVA),
1857 X(MF_MT_FORWARD_CUSTOM_NALU),
1858 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE10),
1859 X(MF_TOPONODE_ERROR_MAJORTYPE),
1860 X(MF_MT_SECURE),
1861 X(MFT_FIELDOFUSE_UNLOCK_Attribute),
1862 X(MF_TOPONODE_ERROR_SUBTYPE),
1863 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE),
1864 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE),
1865 X(MF_MT_VIDEO_3D_LEFT_IS_BASE),
1866 X(MF_TOPONODE_WORKQUEUE_MMCSS_TASKID),
1867 #undef MF_READER_WRITER_D3D_MANAGER
1868 #undef X
1870 struct guid_def *ret = NULL;
1872 if (guid)
1873 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
1875 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
1878 const char *debugstr_mf_guid(const GUID *guid)
1880 static const struct guid_def guid_defs[] =
1882 #define X(g) { &(g), #g }
1883 X(MFAudioFormat_ADTS),
1884 X(MFAudioFormat_PCM),
1885 X(MFAudioFormat_PCM_HDCP),
1886 X(MFAudioFormat_Float),
1887 X(MFAudioFormat_DTS),
1888 X(MFAudioFormat_DRM),
1889 X(MFAudioFormat_MSP1),
1890 X(MFAudioFormat_Vorbis),
1891 X(MFAudioFormat_AAC),
1892 X(MFVideoFormat_RGB24),
1893 X(MFVideoFormat_ARGB32),
1894 X(MFVideoFormat_RGB32),
1895 X(MFVideoFormat_RGB565),
1896 X(MFVideoFormat_RGB555),
1897 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID),
1898 X(MFVideoFormat_A2R10G10B10),
1899 X(MFMediaType_Script),
1900 X(MFMediaType_Image),
1901 X(MFMediaType_HTML),
1902 X(MFMediaType_Binary),
1903 X(MFVideoFormat_MPEG2),
1904 X(MFMediaType_FileTransfer),
1905 X(MFVideoFormat_RGB8),
1906 X(MFAudioFormat_Dolby_AC3),
1907 X(MFVideoFormat_L8),
1908 X(MFAudioFormat_LPCM),
1909 X(MFVideoFormat_420O),
1910 X(MFVideoFormat_AI44),
1911 X(MFVideoFormat_AV1),
1912 X(MFVideoFormat_AYUV),
1913 X(MFVideoFormat_H263),
1914 X(MFVideoFormat_H264),
1915 X(MFVideoFormat_H265),
1916 X(MFVideoFormat_HEVC),
1917 X(MFVideoFormat_HEVC_ES),
1918 X(MFVideoFormat_I420),
1919 X(MFVideoFormat_IYUV),
1920 X(MFVideoFormat_M4S2),
1921 X(MFVideoFormat_MJPG),
1922 X(MFVideoFormat_MP43),
1923 X(MFVideoFormat_MP4S),
1924 X(MFVideoFormat_MP4V),
1925 X(MFVideoFormat_MPG1),
1926 X(MFVideoFormat_MSS1),
1927 X(MFVideoFormat_MSS2),
1928 X(MFVideoFormat_NV11),
1929 X(MFVideoFormat_NV12),
1930 X(MFVideoFormat_ORAW),
1931 X(MFAudioFormat_Opus),
1932 X(MFVideoFormat_D16),
1933 X(MFAudioFormat_MPEG),
1934 X(MFVideoFormat_P010),
1935 X(MFVideoFormat_P016),
1936 X(MFVideoFormat_P210),
1937 X(MFVideoFormat_P216),
1938 X(MFVideoFormat_L16),
1939 X(MFAudioFormat_MP3),
1940 X(MFVideoFormat_UYVY),
1941 X(MFVideoFormat_VP10),
1942 X(MFVideoFormat_VP80),
1943 X(MFVideoFormat_VP90),
1944 X(MFVideoFormat_WMV1),
1945 X(MFVideoFormat_WMV2),
1946 X(MFVideoFormat_WMV3),
1947 X(MFVideoFormat_WVC1),
1948 X(MFVideoFormat_Y210),
1949 X(MFVideoFormat_Y216),
1950 X(MFVideoFormat_Y410),
1951 X(MFVideoFormat_Y416),
1952 X(MFVideoFormat_Y41P),
1953 X(MFVideoFormat_Y41T),
1954 X(MFVideoFormat_Y42T),
1955 X(MFVideoFormat_YUY2),
1956 X(MFVideoFormat_YV12),
1957 X(MFVideoFormat_YVU9),
1958 X(MFVideoFormat_YVYU),
1959 X(MFAudioFormat_WMAudioV8),
1960 X(MFAudioFormat_ALAC),
1961 X(MFAudioFormat_AMR_NB),
1962 X(MFMediaType_Audio),
1963 X(MFAudioFormat_WMAudioV9),
1964 X(MFAudioFormat_AMR_WB),
1965 X(MFAudioFormat_WMAudio_Lossless),
1966 X(MFAudioFormat_AMR_WP),
1967 X(MFAudioFormat_WMASPDIF),
1968 X(MFVideoFormat_DV25),
1969 X(MFVideoFormat_DV50),
1970 X(MFVideoFormat_DVC),
1971 X(MFVideoFormat_DVH1),
1972 X(MFVideoFormat_DVHD),
1973 X(MFVideoFormat_DVSD),
1974 X(MFVideoFormat_DVSL),
1975 X(MFVideoFormat_A16B16G16R16F),
1976 X(MFVideoFormat_v210),
1977 X(MFVideoFormat_v216),
1978 X(MFVideoFormat_v410),
1979 X(MFMediaType_Video),
1980 X(MFAudioFormat_AAC_HDCP),
1981 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID),
1982 X(MFAudioFormat_Dolby_AC3_HDCP),
1983 X(MFMediaType_Subtitle),
1984 X(MFMediaType_Stream),
1985 X(MFAudioFormat_Dolby_AC3_SPDIF),
1986 X(MFAudioFormat_Float_SpatialObjects),
1987 X(MFMediaType_SAMI),
1988 X(MFAudioFormat_ADTS_HDCP),
1989 X(MFAudioFormat_FLAC),
1990 X(MFAudioFormat_Dolby_DDPlus),
1991 X(MFMediaType_MultiplexedFrames),
1992 X(MFAudioFormat_Base_HDCP),
1993 X(MFVideoFormat_Base_HDCP),
1994 X(MFVideoFormat_H264_HDCP),
1995 X(MFVideoFormat_HEVC_HDCP),
1996 X(MFMediaType_Default),
1997 X(MFMediaType_Protected),
1998 X(MFVideoFormat_H264_ES),
1999 X(MFMediaType_Perception),
2000 #undef X
2002 struct guid_def *ret = NULL;
2004 if (guid)
2005 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
2007 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
2010 struct event_id
2012 DWORD id;
2013 const char *name;
2016 static int __cdecl debug_event_id(const void *a, const void *b)
2018 const DWORD *id = a;
2019 const struct event_id *event_id = b;
2020 return *id - event_id->id;
2023 static const char *debugstr_eventid(DWORD event)
2025 static const struct event_id
2027 DWORD id;
2028 const char *name;
2030 event_ids[] =
2032 #define X(e) { e, #e }
2033 X(MEUnknown),
2034 X(MEError),
2035 X(MEExtendedType),
2036 X(MENonFatalError),
2037 X(MESessionUnknown),
2038 X(MESessionTopologySet),
2039 X(MESessionTopologiesCleared),
2040 X(MESessionStarted),
2041 X(MESessionPaused),
2042 X(MESessionStopped),
2043 X(MESessionClosed),
2044 X(MESessionEnded),
2045 X(MESessionRateChanged),
2046 X(MESessionScrubSampleComplete),
2047 X(MESessionCapabilitiesChanged),
2048 X(MESessionTopologyStatus),
2049 X(MESessionNotifyPresentationTime),
2050 X(MENewPresentation),
2051 X(MELicenseAcquisitionStart),
2052 X(MELicenseAcquisitionCompleted),
2053 X(MEIndividualizationStart),
2054 X(MEIndividualizationCompleted),
2055 X(MEEnablerProgress),
2056 X(MEEnablerCompleted),
2057 X(MEPolicyError),
2058 X(MEPolicyReport),
2059 X(MEBufferingStarted),
2060 X(MEBufferingStopped),
2061 X(MEConnectStart),
2062 X(MEConnectEnd),
2063 X(MEReconnectStart),
2064 X(MEReconnectEnd),
2065 X(MERendererEvent),
2066 X(MESessionStreamSinkFormatChanged),
2067 X(MESourceUnknown),
2068 X(MESourceStarted),
2069 X(MEStreamStarted),
2070 X(MESourceSeeked),
2071 X(MEStreamSeeked),
2072 X(MENewStream),
2073 X(MEUpdatedStream),
2074 X(MESourceStopped),
2075 X(MEStreamStopped),
2076 X(MESourcePaused),
2077 X(MEStreamPaused),
2078 X(MEEndOfPresentation),
2079 X(MEEndOfStream),
2080 X(MEMediaSample),
2081 X(MEStreamTick),
2082 X(MEStreamThinMode),
2083 X(MEStreamFormatChanged),
2084 X(MESourceRateChanged),
2085 X(MEEndOfPresentationSegment),
2086 X(MESourceCharacteristicsChanged),
2087 X(MESourceRateChangeRequested),
2088 X(MESourceMetadataChanged),
2089 X(MESequencerSourceTopologyUpdated),
2090 X(MESinkUnknown),
2091 X(MEStreamSinkStarted),
2092 X(MEStreamSinkStopped),
2093 X(MEStreamSinkPaused),
2094 X(MEStreamSinkRateChanged),
2095 X(MEStreamSinkRequestSample),
2096 X(MEStreamSinkMarker),
2097 X(MEStreamSinkPrerolled),
2098 X(MEStreamSinkScrubSampleComplete),
2099 X(MEStreamSinkFormatChanged),
2100 X(MEStreamSinkDeviceChanged),
2101 X(MEQualityNotify),
2102 X(MESinkInvalidated),
2103 X(MEAudioSessionNameChanged),
2104 X(MEAudioSessionVolumeChanged),
2105 X(MEAudioSessionDeviceRemoved),
2106 X(MEAudioSessionServerShutdown),
2107 X(MEAudioSessionGroupingParamChanged),
2108 X(MEAudioSessionIconChanged),
2109 X(MEAudioSessionFormatChanged),
2110 X(MEAudioSessionDisconnected),
2111 X(MEAudioSessionExclusiveModeOverride),
2112 X(METrustUnknown),
2113 X(MEPolicyChanged),
2114 X(MEContentProtectionMessage),
2115 X(MEPolicySet),
2116 X(MEWMDRMLicenseBackupCompleted),
2117 X(MEWMDRMLicenseBackupProgress),
2118 X(MEWMDRMLicenseRestoreCompleted),
2119 X(MEWMDRMLicenseRestoreProgress),
2120 X(MEWMDRMLicenseAcquisitionCompleted),
2121 X(MEWMDRMIndividualizationCompleted),
2122 X(MEWMDRMIndividualizationProgress),
2123 X(MEWMDRMProximityCompleted),
2124 X(MEWMDRMLicenseStoreCleaned),
2125 X(MEWMDRMRevocationDownloadCompleted),
2126 X(METransformUnknown),
2127 X(METransformNeedInput),
2128 X(METransformHaveOutput),
2129 X(METransformDrainComplete),
2130 X(METransformMarker),
2131 X(METransformInputStreamStateChanged),
2132 X(MEByteStreamCharacteristicsChanged),
2133 X(MEVideoCaptureDeviceRemoved),
2134 X(MEVideoCaptureDevicePreempted),
2135 X(MEStreamSinkFormatInvalidated),
2136 X(MEEncodingParameters),
2137 X(MEContentProtectionMetadata),
2138 X(MEDeviceThermalStateChanged),
2139 #undef X
2142 struct event_id *ret = bsearch(&event, event_ids, ARRAY_SIZE(event_ids), sizeof(*event_ids), debug_event_id);
2143 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbg_sprintf("%u", event);
2146 static inline struct attributes *impl_from_IMFAttributes(IMFAttributes *iface)
2148 return CONTAINING_RECORD(iface, struct attributes, IMFAttributes_iface);
2151 static HRESULT WINAPI mfattributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
2153 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
2155 if (IsEqualIID(riid, &IID_IMFAttributes) ||
2156 IsEqualGUID(riid, &IID_IUnknown))
2158 *out = iface;
2159 IMFAttributes_AddRef(iface);
2160 return S_OK;
2163 WARN("Unsupported %s.\n", debugstr_guid(riid));
2164 *out = NULL;
2165 return E_NOINTERFACE;
2168 static ULONG WINAPI mfattributes_AddRef(IMFAttributes *iface)
2170 struct attributes *attributes = impl_from_IMFAttributes(iface);
2171 ULONG refcount = InterlockedIncrement(&attributes->ref);
2173 TRACE("%p, refcount %d.\n", iface, refcount);
2175 return refcount;
2178 static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
2180 struct attributes *attributes = impl_from_IMFAttributes(iface);
2181 ULONG refcount = InterlockedDecrement(&attributes->ref);
2183 TRACE("%p, refcount %d.\n", iface, refcount);
2185 if (!refcount)
2187 clear_attributes_object(attributes);
2188 heap_free(attributes);
2191 return refcount;
2194 static struct attribute *attributes_find_item(struct attributes *attributes, REFGUID key, size_t *index)
2196 size_t i;
2198 for (i = 0; i < attributes->count; ++i)
2200 if (IsEqualGUID(key, &attributes->attributes[i].key))
2202 if (index)
2203 *index = i;
2204 return &attributes->attributes[i];
2208 return NULL;
2211 static HRESULT attributes_get_item(struct attributes *attributes, const GUID *key, PROPVARIANT *value)
2213 struct attribute *attribute;
2214 HRESULT hr;
2216 EnterCriticalSection(&attributes->cs);
2218 attribute = attributes_find_item(attributes, key, NULL);
2219 if (attribute)
2221 if (attribute->value.vt == value->vt && !(value->vt == VT_UNKNOWN && !attribute->value.punkVal))
2222 hr = PropVariantCopy(value, &attribute->value);
2223 else
2224 hr = MF_E_INVALIDTYPE;
2226 else
2227 hr = MF_E_ATTRIBUTENOTFOUND;
2229 LeaveCriticalSection(&attributes->cs);
2231 return hr;
2234 HRESULT attributes_GetItem(struct attributes *attributes, REFGUID key, PROPVARIANT *value)
2236 struct attribute *attribute;
2237 HRESULT hr;
2239 EnterCriticalSection(&attributes->cs);
2241 if ((attribute = attributes_find_item(attributes, key, NULL)))
2242 hr = value ? PropVariantCopy(value, &attribute->value) : S_OK;
2243 else
2244 hr = MF_E_ATTRIBUTENOTFOUND;
2246 LeaveCriticalSection(&attributes->cs);
2248 return hr;
2251 HRESULT attributes_GetItemType(struct attributes *attributes, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2253 struct attribute *attribute;
2254 HRESULT hr = S_OK;
2256 EnterCriticalSection(&attributes->cs);
2258 if ((attribute = attributes_find_item(attributes, key, NULL)))
2260 *type = attribute->value.vt;
2262 else
2263 hr = MF_E_ATTRIBUTENOTFOUND;
2265 LeaveCriticalSection(&attributes->cs);
2267 return hr;
2270 HRESULT attributes_CompareItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value, BOOL *result)
2272 struct attribute *attribute;
2274 *result = FALSE;
2276 EnterCriticalSection(&attributes->cs);
2278 if ((attribute = attributes_find_item(attributes, key, NULL)))
2280 *result = attribute->value.vt == value->vt &&
2281 !PropVariantCompareEx(&attribute->value, value, PVCU_DEFAULT, PVCF_DEFAULT);
2284 LeaveCriticalSection(&attributes->cs);
2286 return S_OK;
2289 HRESULT attributes_Compare(struct attributes *attributes, IMFAttributes *theirs,
2290 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2292 IMFAttributes *smaller, *other;
2293 MF_ATTRIBUTE_TYPE type;
2294 HRESULT hr = S_OK;
2295 UINT32 count;
2296 BOOL result;
2297 size_t i;
2299 if (FAILED(hr = IMFAttributes_GetCount(theirs, &count)))
2300 return hr;
2302 EnterCriticalSection(&attributes->cs);
2304 result = TRUE;
2306 switch (match_type)
2308 case MF_ATTRIBUTES_MATCH_OUR_ITEMS:
2309 for (i = 0; i < attributes->count; ++i)
2311 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2312 &attributes->attributes[i].value, &result)))
2313 break;
2314 if (!result)
2315 break;
2317 break;
2318 case MF_ATTRIBUTES_MATCH_THEIR_ITEMS:
2319 hr = IMFAttributes_Compare(theirs, &attributes->IMFAttributes_iface, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2320 break;
2321 case MF_ATTRIBUTES_MATCH_ALL_ITEMS:
2322 if (count != attributes->count)
2324 result = FALSE;
2325 break;
2327 for (i = 0; i < count; ++i)
2329 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2330 &attributes->attributes[i].value, &result)))
2331 break;
2332 if (!result)
2333 break;
2335 break;
2336 case MF_ATTRIBUTES_MATCH_INTERSECTION:
2337 for (i = 0; i < attributes->count; ++i)
2339 if (FAILED(IMFAttributes_GetItemType(theirs, &attributes->attributes[i].key, &type)))
2340 continue;
2342 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2343 &attributes->attributes[i].value, &result)))
2344 break;
2346 if (!result)
2347 break;
2349 break;
2350 case MF_ATTRIBUTES_MATCH_SMALLER:
2351 smaller = attributes->count > count ? theirs : &attributes->IMFAttributes_iface;
2352 other = attributes->count > count ? &attributes->IMFAttributes_iface : theirs;
2353 hr = IMFAttributes_Compare(smaller, other, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2354 break;
2355 default:
2356 WARN("Unknown match type %d.\n", match_type);
2357 hr = E_INVALIDARG;
2360 LeaveCriticalSection(&attributes->cs);
2362 if (SUCCEEDED(hr))
2363 *ret = result;
2365 return hr;
2368 HRESULT attributes_GetUINT32(struct attributes *attributes, REFGUID key, UINT32 *value)
2370 PROPVARIANT attrval;
2371 HRESULT hr;
2373 PropVariantInit(&attrval);
2374 attrval.vt = VT_UI4;
2375 hr = attributes_get_item(attributes, key, &attrval);
2376 if (SUCCEEDED(hr))
2377 *value = attrval.ulVal;
2379 return hr;
2382 HRESULT attributes_GetUINT64(struct attributes *attributes, REFGUID key, UINT64 *value)
2384 PROPVARIANT attrval;
2385 HRESULT hr;
2387 PropVariantInit(&attrval);
2388 attrval.vt = VT_UI8;
2389 hr = attributes_get_item(attributes, key, &attrval);
2390 if (SUCCEEDED(hr))
2391 *value = attrval.uhVal.QuadPart;
2393 return hr;
2396 HRESULT attributes_GetDouble(struct attributes *attributes, REFGUID key, double *value)
2398 PROPVARIANT attrval;
2399 HRESULT hr;
2401 PropVariantInit(&attrval);
2402 attrval.vt = VT_R8;
2403 hr = attributes_get_item(attributes, key, &attrval);
2404 if (SUCCEEDED(hr))
2405 *value = attrval.dblVal;
2407 return hr;
2410 HRESULT attributes_GetGUID(struct attributes *attributes, REFGUID key, GUID *value)
2412 struct attribute *attribute;
2413 HRESULT hr = S_OK;
2415 EnterCriticalSection(&attributes->cs);
2417 attribute = attributes_find_item(attributes, key, NULL);
2418 if (attribute)
2420 if (attribute->value.vt == MF_ATTRIBUTE_GUID)
2421 *value = *attribute->value.puuid;
2422 else
2423 hr = MF_E_INVALIDTYPE;
2425 else
2426 hr = MF_E_ATTRIBUTENOTFOUND;
2428 LeaveCriticalSection(&attributes->cs);
2430 return hr;
2433 HRESULT attributes_GetStringLength(struct attributes *attributes, REFGUID key, UINT32 *length)
2435 struct attribute *attribute;
2436 HRESULT hr = S_OK;
2438 EnterCriticalSection(&attributes->cs);
2440 attribute = attributes_find_item(attributes, key, NULL);
2441 if (attribute)
2443 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2444 *length = lstrlenW(attribute->value.pwszVal);
2445 else
2446 hr = MF_E_INVALIDTYPE;
2448 else
2449 hr = MF_E_ATTRIBUTENOTFOUND;
2451 LeaveCriticalSection(&attributes->cs);
2453 return hr;
2456 HRESULT attributes_GetString(struct attributes *attributes, REFGUID key, WCHAR *value,
2457 UINT32 size, UINT32 *length)
2459 struct attribute *attribute;
2460 HRESULT hr = S_OK;
2462 EnterCriticalSection(&attributes->cs);
2464 attribute = attributes_find_item(attributes, key, NULL);
2465 if (attribute)
2467 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2469 int len = lstrlenW(attribute->value.pwszVal);
2471 if (length)
2472 *length = len;
2474 if (size <= len)
2475 hr = STRSAFE_E_INSUFFICIENT_BUFFER;
2476 else
2477 memcpy(value, attribute->value.pwszVal, (len + 1) * sizeof(WCHAR));
2479 else
2480 hr = MF_E_INVALIDTYPE;
2482 else
2483 hr = MF_E_ATTRIBUTENOTFOUND;
2485 LeaveCriticalSection(&attributes->cs);
2487 return hr;
2490 HRESULT attributes_GetAllocatedString(struct attributes *attributes, REFGUID key, WCHAR **value, UINT32 *length)
2492 PROPVARIANT attrval;
2493 HRESULT hr;
2495 PropVariantInit(&attrval);
2496 attrval.vt = VT_LPWSTR;
2497 hr = attributes_get_item(attributes, key, &attrval);
2498 if (SUCCEEDED(hr))
2500 *value = attrval.pwszVal;
2501 *length = lstrlenW(*value);
2504 return hr;
2507 HRESULT attributes_GetBlobSize(struct attributes *attributes, REFGUID key, UINT32 *size)
2509 struct attribute *attribute;
2510 HRESULT hr = S_OK;
2512 EnterCriticalSection(&attributes->cs);
2514 attribute = attributes_find_item(attributes, key, NULL);
2515 if (attribute)
2517 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2518 *size = attribute->value.caub.cElems;
2519 else
2520 hr = MF_E_INVALIDTYPE;
2522 else
2523 hr = MF_E_ATTRIBUTENOTFOUND;
2525 LeaveCriticalSection(&attributes->cs);
2527 return hr;
2530 HRESULT attributes_GetBlob(struct attributes *attributes, REFGUID key, UINT8 *buf, UINT32 bufsize, UINT32 *blobsize)
2532 struct attribute *attribute;
2533 HRESULT hr;
2535 EnterCriticalSection(&attributes->cs);
2537 attribute = attributes_find_item(attributes, key, NULL);
2538 if (attribute)
2540 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2542 UINT32 size = attribute->value.caub.cElems;
2544 if (bufsize >= size)
2545 hr = PropVariantToBuffer(&attribute->value, buf, size);
2546 else
2547 hr = E_NOT_SUFFICIENT_BUFFER;
2549 if (blobsize)
2550 *blobsize = size;
2552 else
2553 hr = MF_E_INVALIDTYPE;
2555 else
2556 hr = MF_E_ATTRIBUTENOTFOUND;
2558 LeaveCriticalSection(&attributes->cs);
2560 return hr;
2563 HRESULT attributes_GetAllocatedBlob(struct attributes *attributes, REFGUID key, UINT8 **buf, UINT32 *size)
2565 PROPVARIANT attrval;
2566 HRESULT hr;
2568 attrval.vt = VT_VECTOR | VT_UI1;
2569 hr = attributes_get_item(attributes, key, &attrval);
2570 if (SUCCEEDED(hr))
2572 *buf = attrval.caub.pElems;
2573 *size = attrval.caub.cElems;
2576 return hr;
2579 HRESULT attributes_GetUnknown(struct attributes *attributes, REFGUID key, REFIID riid, void **out)
2581 PROPVARIANT attrval;
2582 HRESULT hr;
2584 PropVariantInit(&attrval);
2585 attrval.vt = VT_UNKNOWN;
2586 hr = attributes_get_item(attributes, key, &attrval);
2587 if (SUCCEEDED(hr))
2588 hr = IUnknown_QueryInterface(attrval.punkVal, riid, out);
2589 PropVariantClear(&attrval);
2590 return hr;
2593 static HRESULT attributes_set_item(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2595 struct attribute *attribute;
2597 EnterCriticalSection(&attributes->cs);
2599 attribute = attributes_find_item(attributes, key, NULL);
2600 if (!attribute)
2602 if (!mf_array_reserve((void **)&attributes->attributes, &attributes->capacity, attributes->count + 1,
2603 sizeof(*attributes->attributes)))
2605 LeaveCriticalSection(&attributes->cs);
2606 return E_OUTOFMEMORY;
2608 attributes->attributes[attributes->count].key = *key;
2609 attribute = &attributes->attributes[attributes->count++];
2611 else
2612 PropVariantClear(&attribute->value);
2614 PropVariantCopy(&attribute->value, value);
2616 LeaveCriticalSection(&attributes->cs);
2618 return S_OK;
2621 HRESULT attributes_SetItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2623 PROPVARIANT empty;
2625 switch (value->vt)
2627 case MF_ATTRIBUTE_UINT32:
2628 case MF_ATTRIBUTE_UINT64:
2629 case MF_ATTRIBUTE_DOUBLE:
2630 case MF_ATTRIBUTE_GUID:
2631 case MF_ATTRIBUTE_STRING:
2632 case MF_ATTRIBUTE_BLOB:
2633 case MF_ATTRIBUTE_IUNKNOWN:
2634 return attributes_set_item(attributes, key, value);
2635 default:
2636 PropVariantInit(&empty);
2637 attributes_set_item(attributes, key, &empty);
2638 return MF_E_INVALIDTYPE;
2642 HRESULT attributes_DeleteItem(struct attributes *attributes, REFGUID key)
2644 struct attribute *attribute;
2645 size_t index = 0;
2647 EnterCriticalSection(&attributes->cs);
2649 if ((attribute = attributes_find_item(attributes, key, &index)))
2651 size_t count;
2653 PropVariantClear(&attribute->value);
2655 attributes->count--;
2656 count = attributes->count - index;
2657 if (count)
2658 memmove(&attributes->attributes[index], &attributes->attributes[index + 1], count * sizeof(*attributes->attributes));
2661 LeaveCriticalSection(&attributes->cs);
2663 return S_OK;
2666 HRESULT attributes_DeleteAllItems(struct attributes *attributes)
2668 EnterCriticalSection(&attributes->cs);
2670 while (attributes->count)
2672 PropVariantClear(&attributes->attributes[--attributes->count].value);
2674 heap_free(attributes->attributes);
2675 attributes->attributes = NULL;
2676 attributes->capacity = 0;
2678 LeaveCriticalSection(&attributes->cs);
2680 return S_OK;
2683 HRESULT attributes_SetUINT32(struct attributes *attributes, REFGUID key, UINT32 value)
2685 PROPVARIANT attrval;
2687 attrval.vt = VT_UI4;
2688 attrval.ulVal = value;
2689 return attributes_set_item(attributes, key, &attrval);
2692 HRESULT attributes_SetUINT64(struct attributes *attributes, REFGUID key, UINT64 value)
2694 PROPVARIANT attrval;
2696 attrval.vt = VT_UI8;
2697 attrval.uhVal.QuadPart = value;
2698 return attributes_set_item(attributes, key, &attrval);
2701 HRESULT attributes_SetDouble(struct attributes *attributes, REFGUID key, double value)
2703 PROPVARIANT attrval;
2705 attrval.vt = VT_R8;
2706 attrval.dblVal = value;
2707 return attributes_set_item(attributes, key, &attrval);
2710 HRESULT attributes_SetGUID(struct attributes *attributes, REFGUID key, REFGUID value)
2712 PROPVARIANT attrval;
2714 attrval.vt = VT_CLSID;
2715 attrval.puuid = (CLSID *)value;
2716 return attributes_set_item(attributes, key, &attrval);
2719 HRESULT attributes_SetString(struct attributes *attributes, REFGUID key, const WCHAR *value)
2721 PROPVARIANT attrval;
2723 attrval.vt = VT_LPWSTR;
2724 attrval.pwszVal = (WCHAR *)value;
2725 return attributes_set_item(attributes, key, &attrval);
2728 HRESULT attributes_SetBlob(struct attributes *attributes, REFGUID key, const UINT8 *buf, UINT32 size)
2730 PROPVARIANT attrval;
2732 attrval.vt = VT_VECTOR | VT_UI1;
2733 attrval.caub.cElems = size;
2734 attrval.caub.pElems = (UINT8 *)buf;
2735 return attributes_set_item(attributes, key, &attrval);
2738 HRESULT attributes_SetUnknown(struct attributes *attributes, REFGUID key, IUnknown *unknown)
2740 PROPVARIANT attrval;
2742 attrval.vt = VT_UNKNOWN;
2743 attrval.punkVal = unknown;
2744 return attributes_set_item(attributes, key, &attrval);
2747 HRESULT attributes_LockStore(struct attributes *attributes)
2749 EnterCriticalSection(&attributes->cs);
2751 return S_OK;
2754 HRESULT attributes_UnlockStore(struct attributes *attributes)
2756 LeaveCriticalSection(&attributes->cs);
2758 return S_OK;
2761 HRESULT attributes_GetCount(struct attributes *attributes, UINT32 *count)
2763 EnterCriticalSection(&attributes->cs);
2764 *count = attributes->count;
2765 LeaveCriticalSection(&attributes->cs);
2767 return S_OK;
2770 HRESULT attributes_GetItemByIndex(struct attributes *attributes, UINT32 index, GUID *key, PROPVARIANT *value)
2772 HRESULT hr = S_OK;
2774 EnterCriticalSection(&attributes->cs);
2776 if (index < attributes->count)
2778 *key = attributes->attributes[index].key;
2779 if (value)
2780 PropVariantCopy(value, &attributes->attributes[index].value);
2782 else
2783 hr = E_INVALIDARG;
2785 LeaveCriticalSection(&attributes->cs);
2787 return hr;
2790 HRESULT attributes_CopyAllItems(struct attributes *attributes, IMFAttributes *dest)
2792 HRESULT hr = S_OK;
2793 size_t i;
2795 EnterCriticalSection(&attributes->cs);
2797 IMFAttributes_LockStore(dest);
2799 IMFAttributes_DeleteAllItems(dest);
2801 for (i = 0; i < attributes->count; ++i)
2803 hr = IMFAttributes_SetItem(dest, &attributes->attributes[i].key, &attributes->attributes[i].value);
2804 if (FAILED(hr))
2805 break;
2808 IMFAttributes_UnlockStore(dest);
2810 LeaveCriticalSection(&attributes->cs);
2812 return hr;
2815 static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
2817 struct attributes *attributes = impl_from_IMFAttributes(iface);
2819 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2821 return attributes_GetItem(attributes, key, value);
2824 static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2826 struct attributes *attributes = impl_from_IMFAttributes(iface);
2828 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
2830 return attributes_GetItemType(attributes, key, type);
2833 static HRESULT WINAPI mfattributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
2835 struct attributes *attributes = impl_from_IMFAttributes(iface);
2837 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
2839 return attributes_CompareItem(attributes, key, value, result);
2842 static HRESULT WINAPI mfattributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
2843 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2845 struct attributes *attributes = impl_from_IMFAttributes(iface);
2847 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
2849 return attributes_Compare(attributes, theirs, match_type, ret);
2852 static HRESULT WINAPI mfattributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
2854 struct attributes *attributes = impl_from_IMFAttributes(iface);
2856 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2858 return attributes_GetUINT32(attributes, key, value);
2861 static HRESULT WINAPI mfattributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
2863 struct attributes *attributes = impl_from_IMFAttributes(iface);
2865 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2867 return attributes_GetUINT64(attributes, key, value);
2870 static HRESULT WINAPI mfattributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
2872 struct attributes *attributes = impl_from_IMFAttributes(iface);
2874 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2876 return attributes_GetDouble(attributes, key, value);
2879 static HRESULT WINAPI mfattributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
2881 struct attributes *attributes = impl_from_IMFAttributes(iface);
2883 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2885 return attributes_GetGUID(attributes, key, value);
2888 static HRESULT WINAPI mfattributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
2890 struct attributes *attributes = impl_from_IMFAttributes(iface);
2892 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
2894 return attributes_GetStringLength(attributes, key, length);
2897 static HRESULT WINAPI mfattributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
2898 UINT32 size, UINT32 *length)
2900 struct attributes *attributes = impl_from_IMFAttributes(iface);
2902 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
2904 return attributes_GetString(attributes, key, value, size, length);
2907 static HRESULT WINAPI mfattributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
2909 struct attributes *attributes = impl_from_IMFAttributes(iface);
2911 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
2913 return attributes_GetAllocatedString(attributes, key, value, length);
2916 static HRESULT WINAPI mfattributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
2918 struct attributes *attributes = impl_from_IMFAttributes(iface);
2920 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
2922 return attributes_GetBlobSize(attributes, key, size);
2925 static HRESULT WINAPI mfattributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
2926 UINT32 bufsize, UINT32 *blobsize)
2928 struct attributes *attributes = impl_from_IMFAttributes(iface);
2930 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
2932 return attributes_GetBlob(attributes, key, buf, bufsize, blobsize);
2935 static HRESULT WINAPI mfattributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
2937 struct attributes *attributes = impl_from_IMFAttributes(iface);
2939 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
2941 return attributes_GetAllocatedBlob(attributes, key, buf, size);
2944 static HRESULT WINAPI mfattributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
2946 struct attributes *attributes = impl_from_IMFAttributes(iface);
2948 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
2950 return attributes_GetUnknown(attributes, key, riid, out);
2953 static HRESULT WINAPI mfattributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
2955 struct attributes *attributes = impl_from_IMFAttributes(iface);
2957 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
2959 return attributes_SetItem(attributes, key, value);
2962 static HRESULT WINAPI mfattributes_DeleteItem(IMFAttributes *iface, REFGUID key)
2964 struct attributes *attributes = impl_from_IMFAttributes(iface);
2966 TRACE("%p, %s.\n", iface, debugstr_attr(key));
2968 return attributes_DeleteItem(attributes, key);
2971 static HRESULT WINAPI mfattributes_DeleteAllItems(IMFAttributes *iface)
2973 struct attributes *attributes = impl_from_IMFAttributes(iface);
2975 TRACE("%p.\n", iface);
2977 return attributes_DeleteAllItems(attributes);
2980 static HRESULT WINAPI mfattributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
2982 struct attributes *attributes = impl_from_IMFAttributes(iface);
2984 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
2986 return attributes_SetUINT32(attributes, key, value);
2989 static HRESULT WINAPI mfattributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
2991 struct attributes *attributes = impl_from_IMFAttributes(iface);
2993 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
2995 return attributes_SetUINT64(attributes, key, value);
2998 static HRESULT WINAPI mfattributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
3000 struct attributes *attributes = impl_from_IMFAttributes(iface);
3002 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
3004 return attributes_SetDouble(attributes, key, value);
3007 static HRESULT WINAPI mfattributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
3009 struct attributes *attributes = impl_from_IMFAttributes(iface);
3011 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
3013 return attributes_SetGUID(attributes, key, value);
3016 static HRESULT WINAPI mfattributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
3018 struct attributes *attributes = impl_from_IMFAttributes(iface);
3020 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
3022 return attributes_SetString(attributes, key, value);
3025 static HRESULT WINAPI mfattributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
3027 struct attributes *attributes = impl_from_IMFAttributes(iface);
3029 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
3031 return attributes_SetBlob(attributes, key, buf, size);
3034 static HRESULT WINAPI mfattributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
3036 struct attributes *attributes = impl_from_IMFAttributes(iface);
3038 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
3040 return attributes_SetUnknown(attributes, key, unknown);
3043 static HRESULT WINAPI mfattributes_LockStore(IMFAttributes *iface)
3045 struct attributes *attributes = impl_from_IMFAttributes(iface);
3047 TRACE("%p.\n", iface);
3049 return attributes_LockStore(attributes);
3052 static HRESULT WINAPI mfattributes_UnlockStore(IMFAttributes *iface)
3054 struct attributes *attributes = impl_from_IMFAttributes(iface);
3056 TRACE("%p.\n", iface);
3058 return attributes_UnlockStore(attributes);
3061 static HRESULT WINAPI mfattributes_GetCount(IMFAttributes *iface, UINT32 *count)
3063 struct attributes *attributes = impl_from_IMFAttributes(iface);
3065 TRACE("%p, %p.\n", iface, count);
3067 return attributes_GetCount(attributes, count);
3070 static HRESULT WINAPI mfattributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
3072 struct attributes *attributes = impl_from_IMFAttributes(iface);
3074 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
3076 return attributes_GetItemByIndex(attributes, index, key, value);
3079 static HRESULT WINAPI mfattributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
3081 struct attributes *attributes = impl_from_IMFAttributes(iface);
3083 TRACE("%p, %p.\n", iface, dest);
3085 return attributes_CopyAllItems(attributes, dest);
3088 static const IMFAttributesVtbl mfattributes_vtbl =
3090 mfattributes_QueryInterface,
3091 mfattributes_AddRef,
3092 mfattributes_Release,
3093 mfattributes_GetItem,
3094 mfattributes_GetItemType,
3095 mfattributes_CompareItem,
3096 mfattributes_Compare,
3097 mfattributes_GetUINT32,
3098 mfattributes_GetUINT64,
3099 mfattributes_GetDouble,
3100 mfattributes_GetGUID,
3101 mfattributes_GetStringLength,
3102 mfattributes_GetString,
3103 mfattributes_GetAllocatedString,
3104 mfattributes_GetBlobSize,
3105 mfattributes_GetBlob,
3106 mfattributes_GetAllocatedBlob,
3107 mfattributes_GetUnknown,
3108 mfattributes_SetItem,
3109 mfattributes_DeleteItem,
3110 mfattributes_DeleteAllItems,
3111 mfattributes_SetUINT32,
3112 mfattributes_SetUINT64,
3113 mfattributes_SetDouble,
3114 mfattributes_SetGUID,
3115 mfattributes_SetString,
3116 mfattributes_SetBlob,
3117 mfattributes_SetUnknown,
3118 mfattributes_LockStore,
3119 mfattributes_UnlockStore,
3120 mfattributes_GetCount,
3121 mfattributes_GetItemByIndex,
3122 mfattributes_CopyAllItems
3125 HRESULT init_attributes_object(struct attributes *object, UINT32 size)
3127 object->IMFAttributes_iface.lpVtbl = &mfattributes_vtbl;
3128 object->ref = 1;
3129 InitializeCriticalSection(&object->cs);
3131 object->attributes = NULL;
3132 object->count = 0;
3133 object->capacity = 0;
3134 if (!mf_array_reserve((void **)&object->attributes, &object->capacity, size,
3135 sizeof(*object->attributes)))
3137 DeleteCriticalSection(&object->cs);
3138 return E_OUTOFMEMORY;
3141 return S_OK;
3144 void clear_attributes_object(struct attributes *object)
3146 size_t i;
3148 for (i = 0; i < object->count; i++)
3149 PropVariantClear(&object->attributes[i].value);
3150 heap_free(object->attributes);
3152 DeleteCriticalSection(&object->cs);
3155 /***********************************************************************
3156 * MFCreateAttributes (mfplat.@)
3158 HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size)
3160 struct attributes *object;
3161 HRESULT hr;
3163 TRACE("%p, %d\n", attributes, size);
3165 object = heap_alloc_zero(sizeof(*object));
3166 if (!object)
3167 return E_OUTOFMEMORY;
3169 if (FAILED(hr = init_attributes_object(object, size)))
3171 heap_free(object);
3172 return hr;
3174 *attributes = &object->IMFAttributes_iface;
3176 return S_OK;
3179 #define ATTRIBUTES_STORE_MAGIC 0x494d4641 /* IMFA */
3181 struct attributes_store_header
3183 DWORD magic;
3184 UINT32 count;
3187 struct attributes_store_item
3189 GUID key;
3190 QWORD type;
3191 union
3193 double f;
3194 UINT32 i32;
3195 UINT64 i64;
3196 struct
3198 DWORD size;
3199 DWORD offset;
3200 } subheader;
3201 } u;
3204 /***********************************************************************
3205 * MFGetAttributesAsBlobSize (mfplat.@)
3207 HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size)
3209 unsigned int i, count, length;
3210 HRESULT hr;
3211 GUID key;
3213 TRACE("%p, %p.\n", attributes, size);
3215 IMFAttributes_LockStore(attributes);
3217 hr = IMFAttributes_GetCount(attributes, &count);
3219 *size = sizeof(struct attributes_store_header);
3221 for (i = 0; i < count; ++i)
3223 MF_ATTRIBUTE_TYPE type;
3225 hr = IMFAttributes_GetItemByIndex(attributes, i, &key, NULL);
3226 if (FAILED(hr))
3227 break;
3229 *size += sizeof(struct attributes_store_item);
3231 IMFAttributes_GetItemType(attributes, &key, &type);
3233 switch (type)
3235 case MF_ATTRIBUTE_GUID:
3236 *size += sizeof(GUID);
3237 break;
3238 case MF_ATTRIBUTE_STRING:
3239 IMFAttributes_GetStringLength(attributes, &key, &length);
3240 *size += (length + 1) * sizeof(WCHAR);
3241 break;
3242 case MF_ATTRIBUTE_BLOB:
3243 IMFAttributes_GetBlobSize(attributes, &key, &length);
3244 *size += length;
3245 break;
3246 case MF_ATTRIBUTE_UINT32:
3247 case MF_ATTRIBUTE_UINT64:
3248 case MF_ATTRIBUTE_DOUBLE:
3249 case MF_ATTRIBUTE_IUNKNOWN:
3250 default:
3255 IMFAttributes_UnlockStore(attributes);
3257 return hr;
3260 struct attr_serialize_context
3262 UINT8 *buffer;
3263 UINT8 *ptr;
3264 UINT32 size;
3267 static void attributes_serialize_write(struct attr_serialize_context *context, const void *value, unsigned int size)
3269 memcpy(context->ptr, value, size);
3270 context->ptr += size;
3273 static BOOL attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
3274 const void *value)
3276 switch (item->type)
3278 case MF_ATTRIBUTE_UINT32:
3279 case MF_ATTRIBUTE_UINT64:
3280 case MF_ATTRIBUTE_DOUBLE:
3281 attributes_serialize_write(context, item, sizeof(*item));
3282 break;
3283 case MF_ATTRIBUTE_GUID:
3284 case MF_ATTRIBUTE_STRING:
3285 case MF_ATTRIBUTE_BLOB:
3286 item->u.subheader.offset = context->size - item->u.subheader.size;
3287 attributes_serialize_write(context, item, sizeof(*item));
3288 memcpy(context->buffer + item->u.subheader.offset, value, item->u.subheader.size);
3289 context->size -= item->u.subheader.size;
3290 break;
3291 default:
3292 return FALSE;
3295 return TRUE;
3298 /***********************************************************************
3299 * MFGetAttributesAsBlob (mfplat.@)
3301 HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size)
3303 struct attributes_store_header header;
3304 struct attr_serialize_context context;
3305 unsigned int required_size, i;
3306 PROPVARIANT value;
3307 UINT32 count;
3308 HRESULT hr;
3310 TRACE("%p, %p, %u.\n", attributes, buffer, size);
3312 if (FAILED(hr = MFGetAttributesAsBlobSize(attributes, &required_size)))
3313 return hr;
3315 if (required_size > size)
3316 return MF_E_BUFFERTOOSMALL;
3318 context.buffer = buffer;
3319 context.ptr = buffer;
3320 context.size = required_size;
3322 IMFAttributes_LockStore(attributes);
3324 header.magic = ATTRIBUTES_STORE_MAGIC;
3325 header.count = 0; /* Will be updated later */
3326 IMFAttributes_GetCount(attributes, &count);
3328 attributes_serialize_write(&context, &header, sizeof(header));
3330 for (i = 0; i < count; ++i)
3332 struct attributes_store_item item;
3333 const void *data = NULL;
3335 hr = IMFAttributes_GetItemByIndex(attributes, i, &item.key, &value);
3336 if (FAILED(hr))
3337 break;
3339 item.type = value.vt;
3341 switch (value.vt)
3343 case MF_ATTRIBUTE_UINT32:
3344 case MF_ATTRIBUTE_UINT64:
3345 item.u.i64 = value.uhVal.QuadPart;
3346 break;
3347 case MF_ATTRIBUTE_DOUBLE:
3348 item.u.f = value.dblVal;
3349 break;
3350 case MF_ATTRIBUTE_GUID:
3351 item.u.subheader.size = sizeof(*value.puuid);
3352 data = value.puuid;
3353 break;
3354 case MF_ATTRIBUTE_STRING:
3355 item.u.subheader.size = (lstrlenW(value.pwszVal) + 1) * sizeof(WCHAR);
3356 data = value.pwszVal;
3357 break;
3358 case MF_ATTRIBUTE_BLOB:
3359 item.u.subheader.size = value.caub.cElems;
3360 data = value.caub.pElems;
3361 break;
3362 case MF_ATTRIBUTE_IUNKNOWN:
3363 break;
3364 default:
3365 WARN("Unknown attribute type %#x.\n", value.vt);
3368 if (attributes_serialize_write_item(&context, &item, data))
3369 header.count++;
3371 PropVariantClear(&value);
3374 memcpy(context.buffer, &header, sizeof(header));
3376 IMFAttributes_UnlockStore(attributes);
3378 return S_OK;
3381 static HRESULT attributes_deserialize_read(struct attr_serialize_context *context, void *value, unsigned int size)
3383 if (context->size < (context->ptr - context->buffer) + size)
3384 return E_INVALIDARG;
3386 memcpy(value, context->ptr, size);
3387 context->ptr += size;
3389 return S_OK;
3392 /***********************************************************************
3393 * MFInitAttributesFromBlob (mfplat.@)
3395 HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *dest, const UINT8 *buffer, UINT size)
3397 struct attr_serialize_context context;
3398 struct attributes_store_header header;
3399 struct attributes_store_item item;
3400 IMFAttributes *attributes;
3401 unsigned int i;
3402 HRESULT hr;
3404 TRACE("%p, %p, %u.\n", dest, buffer, size);
3406 context.buffer = (UINT8 *)buffer;
3407 context.ptr = (UINT8 *)buffer;
3408 context.size = size;
3410 /* Validate buffer structure. */
3411 if (FAILED(hr = attributes_deserialize_read(&context, &header, sizeof(header))))
3412 return hr;
3414 if (header.magic != ATTRIBUTES_STORE_MAGIC)
3415 return E_UNEXPECTED;
3417 if (FAILED(hr = MFCreateAttributes(&attributes, header.count)))
3418 return hr;
3420 for (i = 0; i < header.count; ++i)
3422 if (FAILED(hr = attributes_deserialize_read(&context, &item, sizeof(item))))
3423 break;
3425 hr = E_UNEXPECTED;
3427 switch (item.type)
3429 case MF_ATTRIBUTE_UINT32:
3430 hr = IMFAttributes_SetUINT32(attributes, &item.key, item.u.i32);
3431 break;
3432 case MF_ATTRIBUTE_UINT64:
3433 hr = IMFAttributes_SetUINT64(attributes, &item.key, item.u.i64);
3434 break;
3435 case MF_ATTRIBUTE_DOUBLE:
3436 hr = IMFAttributes_SetDouble(attributes, &item.key, item.u.f);
3437 break;
3438 case MF_ATTRIBUTE_GUID:
3439 if (item.u.subheader.size == sizeof(GUID) &&
3440 item.u.subheader.offset + item.u.subheader.size <= context.size)
3442 hr = IMFAttributes_SetGUID(attributes, &item.key,
3443 (const GUID *)(context.buffer + item.u.subheader.offset));
3445 break;
3446 case MF_ATTRIBUTE_STRING:
3447 if (item.u.subheader.size >= sizeof(WCHAR) &&
3448 item.u.subheader.offset + item.u.subheader.size <= context.size)
3450 hr = IMFAttributes_SetString(attributes, &item.key,
3451 (const WCHAR *)(context.buffer + item.u.subheader.offset));
3453 break;
3454 case MF_ATTRIBUTE_BLOB:
3455 if (item.u.subheader.size > 0 && item.u.subheader.offset + item.u.subheader.size <= context.size)
3457 hr = IMFAttributes_SetBlob(attributes, &item.key, context.buffer + item.u.subheader.offset,
3458 item.u.subheader.size);
3460 break;
3461 default:
3465 if (FAILED(hr))
3466 break;
3469 if (SUCCEEDED(hr))
3471 IMFAttributes_DeleteAllItems(dest);
3472 hr = IMFAttributes_CopyAllItems(attributes, dest);
3475 IMFAttributes_Release(attributes);
3477 return hr;
3480 typedef struct bytestream
3482 struct attributes attributes;
3483 IMFByteStream IMFByteStream_iface;
3484 IMFGetService IMFGetService_iface;
3485 IRtwqAsyncCallback read_callback;
3486 IRtwqAsyncCallback write_callback;
3487 IStream *stream;
3488 HANDLE hfile;
3489 QWORD position;
3490 DWORD capabilities;
3491 struct list pending;
3492 CRITICAL_SECTION cs;
3493 } mfbytestream;
3495 static inline mfbytestream *impl_from_IMFByteStream(IMFByteStream *iface)
3497 return CONTAINING_RECORD(iface, mfbytestream, IMFByteStream_iface);
3500 static struct bytestream *impl_bytestream_from_IMFGetService(IMFGetService *iface)
3502 return CONTAINING_RECORD(iface, struct bytestream, IMFGetService_iface);
3505 static struct bytestream *impl_from_read_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3507 return CONTAINING_RECORD(iface, struct bytestream, read_callback);
3510 static struct bytestream *impl_from_write_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3512 return CONTAINING_RECORD(iface, struct bytestream, write_callback);
3515 enum async_stream_op_type
3517 ASYNC_STREAM_OP_READ,
3518 ASYNC_STREAM_OP_WRITE,
3521 struct async_stream_op
3523 IUnknown IUnknown_iface;
3524 LONG refcount;
3525 union
3527 const BYTE *src;
3528 BYTE *dest;
3529 } u;
3530 QWORD position;
3531 ULONG requested_length;
3532 ULONG actual_length;
3533 IMFAsyncResult *caller;
3534 struct list entry;
3535 enum async_stream_op_type type;
3538 static struct async_stream_op *impl_async_stream_op_from_IUnknown(IUnknown *iface)
3540 return CONTAINING_RECORD(iface, struct async_stream_op, IUnknown_iface);
3543 static HRESULT WINAPI async_stream_op_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
3545 if (IsEqualIID(riid, &IID_IUnknown))
3547 *obj = iface;
3548 IUnknown_AddRef(iface);
3549 return S_OK;
3552 WARN("Unsupported %s.\n", debugstr_guid(riid));
3553 *obj = NULL;
3554 return E_NOINTERFACE;
3557 static ULONG WINAPI async_stream_op_AddRef(IUnknown *iface)
3559 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3560 ULONG refcount = InterlockedIncrement(&op->refcount);
3562 TRACE("%p, refcount %d.\n", iface, refcount);
3564 return refcount;
3567 static ULONG WINAPI async_stream_op_Release(IUnknown *iface)
3569 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3570 ULONG refcount = InterlockedDecrement(&op->refcount);
3572 TRACE("%p, refcount %d.\n", iface, refcount);
3574 if (!refcount)
3576 if (op->caller)
3577 IMFAsyncResult_Release(op->caller);
3578 heap_free(op);
3581 return refcount;
3584 static const IUnknownVtbl async_stream_op_vtbl =
3586 async_stream_op_QueryInterface,
3587 async_stream_op_AddRef,
3588 async_stream_op_Release,
3591 static HRESULT bytestream_create_io_request(struct bytestream *stream, enum async_stream_op_type type,
3592 const BYTE *data, ULONG size, IMFAsyncCallback *callback, IUnknown *state)
3594 struct async_stream_op *op;
3595 IRtwqAsyncResult *request;
3596 HRESULT hr;
3598 op = heap_alloc(sizeof(*op));
3599 if (!op)
3600 return E_OUTOFMEMORY;
3602 op->IUnknown_iface.lpVtbl = &async_stream_op_vtbl;
3603 op->refcount = 1;
3604 op->u.src = data;
3605 op->position = stream->position;
3606 op->requested_length = size;
3607 op->type = type;
3608 if (FAILED(hr = RtwqCreateAsyncResult((IUnknown *)&stream->IMFByteStream_iface, (IRtwqAsyncCallback *)callback, state,
3609 (IRtwqAsyncResult **)&op->caller)))
3611 goto failed;
3614 if (FAILED(hr = RtwqCreateAsyncResult(&op->IUnknown_iface, type == ASYNC_STREAM_OP_READ ? &stream->read_callback :
3615 &stream->write_callback, NULL, &request)))
3616 goto failed;
3618 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, request);
3619 IRtwqAsyncResult_Release(request);
3621 failed:
3622 IUnknown_Release(&op->IUnknown_iface);
3623 return hr;
3626 static HRESULT bytestream_complete_io_request(struct bytestream *stream, enum async_stream_op_type type,
3627 IMFAsyncResult *result, ULONG *actual_length)
3629 struct async_stream_op *op = NULL, *cur;
3630 HRESULT hr;
3632 EnterCriticalSection(&stream->cs);
3633 LIST_FOR_EACH_ENTRY(cur, &stream->pending, struct async_stream_op, entry)
3635 if (cur->caller == result && cur->type == type)
3637 op = cur;
3638 list_remove(&cur->entry);
3639 break;
3642 LeaveCriticalSection(&stream->cs);
3644 if (!op)
3645 return E_INVALIDARG;
3647 if (SUCCEEDED(hr = IMFAsyncResult_GetStatus(result)))
3648 *actual_length = op->actual_length;
3650 IUnknown_Release(&op->IUnknown_iface);
3652 return hr;
3655 static HRESULT WINAPI bytestream_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
3657 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
3658 IsEqualIID(riid, &IID_IUnknown))
3660 *obj = iface;
3661 IRtwqAsyncCallback_AddRef(iface);
3662 return S_OK;
3665 WARN("Unsupported %s.\n", debugstr_guid(riid));
3666 *obj = NULL;
3667 return E_NOINTERFACE;
3670 static ULONG WINAPI bytestream_read_callback_AddRef(IRtwqAsyncCallback *iface)
3672 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3673 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3676 static ULONG WINAPI bytestream_read_callback_Release(IRtwqAsyncCallback *iface)
3678 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3679 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3682 static HRESULT WINAPI bytestream_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
3684 return E_NOTIMPL;
3687 static ULONG WINAPI bytestream_write_callback_AddRef(IRtwqAsyncCallback *iface)
3689 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3690 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3693 static ULONG WINAPI bytestream_write_callback_Release(IRtwqAsyncCallback *iface)
3695 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3696 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3699 static HRESULT WINAPI bytestream_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
3701 struct bytestream *stream = impl_from_IMFByteStream(iface);
3703 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
3705 if (IsEqualIID(riid, &IID_IMFByteStream) ||
3706 IsEqualIID(riid, &IID_IUnknown))
3708 *out = &stream->IMFByteStream_iface;
3710 else if (IsEqualIID(riid, &IID_IMFAttributes))
3712 *out = &stream->attributes.IMFAttributes_iface;
3714 else if (stream->IMFGetService_iface.lpVtbl && IsEqualIID(riid, &IID_IMFGetService))
3716 *out = &stream->IMFGetService_iface;
3718 else
3720 WARN("Unsupported %s.\n", debugstr_guid(riid));
3721 *out = NULL;
3722 return E_NOINTERFACE;
3725 IUnknown_AddRef((IUnknown*)*out);
3726 return S_OK;
3729 static ULONG WINAPI bytestream_AddRef(IMFByteStream *iface)
3731 struct bytestream *stream = impl_from_IMFByteStream(iface);
3732 ULONG refcount = InterlockedIncrement(&stream->attributes.ref);
3734 TRACE("%p, refcount %d.\n", iface, refcount);
3736 return refcount;
3739 static ULONG WINAPI bytestream_Release(IMFByteStream *iface)
3741 struct bytestream *stream = impl_from_IMFByteStream(iface);
3742 ULONG refcount = InterlockedDecrement(&stream->attributes.ref);
3743 struct async_stream_op *cur, *cur2;
3745 TRACE("%p, refcount %d.\n", iface, refcount);
3747 if (!refcount)
3749 clear_attributes_object(&stream->attributes);
3750 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &stream->pending, struct async_stream_op, entry)
3752 list_remove(&cur->entry);
3753 IUnknown_Release(&cur->IUnknown_iface);
3755 DeleteCriticalSection(&stream->cs);
3756 if (stream->stream)
3757 IStream_Release(stream->stream);
3758 if (stream->hfile)
3759 CloseHandle(stream->hfile);
3760 heap_free(stream);
3763 return refcount;
3766 static HRESULT WINAPI bytestream_stream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3768 struct bytestream *stream = impl_from_IMFByteStream(iface);
3769 STATSTG stat;
3770 HRESULT hr;
3772 TRACE("%p, %p.\n", iface, capabilities);
3774 if (FAILED(hr = IStream_Stat(stream->stream, &stat, STATFLAG_NONAME)))
3775 return hr;
3777 *capabilities = MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_SEEKABLE;
3778 if (stat.grfMode & (STGM_WRITE | STGM_READWRITE))
3779 *capabilities |= MFBYTESTREAM_IS_WRITABLE;
3781 return S_OK;
3784 static HRESULT WINAPI bytestream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3786 struct bytestream *stream = impl_from_IMFByteStream(iface);
3788 TRACE("%p, %p.\n", iface, capabilities);
3790 *capabilities = stream->capabilities;
3792 return S_OK;
3795 static HRESULT WINAPI mfbytestream_SetLength(IMFByteStream *iface, QWORD length)
3797 mfbytestream *This = impl_from_IMFByteStream(iface);
3799 FIXME("%p, %s\n", This, wine_dbgstr_longlong(length));
3801 return E_NOTIMPL;
3804 static HRESULT WINAPI bytestream_file_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
3806 struct bytestream *stream = impl_from_IMFByteStream(iface);
3808 TRACE("%p, %p.\n", iface, position);
3810 if (!position)
3811 return E_INVALIDARG;
3813 *position = stream->position;
3815 return S_OK;
3818 static HRESULT WINAPI bytestream_file_GetLength(IMFByteStream *iface, QWORD *length)
3820 struct bytestream *stream = impl_from_IMFByteStream(iface);
3821 LARGE_INTEGER li;
3823 TRACE("%p, %p.\n", iface, length);
3825 if (!length)
3826 return E_INVALIDARG;
3828 if (GetFileSizeEx(stream->hfile, &li))
3829 *length = li.QuadPart;
3830 else
3831 return HRESULT_FROM_WIN32(GetLastError());
3833 return S_OK;
3836 static HRESULT WINAPI bytestream_file_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
3838 struct bytestream *stream = impl_from_IMFByteStream(iface);
3839 LARGE_INTEGER position, length;
3840 HRESULT hr = S_OK;
3842 TRACE("%p, %p.\n", iface, ret);
3844 EnterCriticalSection(&stream->cs);
3846 position.QuadPart = 0;
3847 if (SetFilePointerEx(stream->hfile, position, &length, FILE_END))
3848 *ret = stream->position >= length.QuadPart;
3849 else
3850 hr = HRESULT_FROM_WIN32(GetLastError());
3852 LeaveCriticalSection(&stream->cs);
3854 return hr;
3857 static HRESULT WINAPI bytestream_file_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
3859 struct bytestream *stream = impl_from_IMFByteStream(iface);
3860 LARGE_INTEGER position;
3861 HRESULT hr = S_OK;
3862 BOOL ret;
3864 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, read_len);
3866 EnterCriticalSection(&stream->cs);
3868 position.QuadPart = stream->position;
3869 if ((ret = SetFilePointerEx(stream->hfile, position, NULL, FILE_BEGIN)))
3871 if ((ret = ReadFile(stream->hfile, buffer, size, read_len, NULL)))
3872 stream->position += *read_len;
3875 if (!ret)
3876 hr = HRESULT_FROM_WIN32(GetLastError());
3878 LeaveCriticalSection(&stream->cs);
3880 return hr;
3883 static HRESULT WINAPI bytestream_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size, IMFAsyncCallback *callback,
3884 IUnknown *state)
3886 struct bytestream *stream = impl_from_IMFByteStream(iface);
3888 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
3890 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_READ, data, size, callback, state);
3893 static HRESULT WINAPI bytestream_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
3895 struct bytestream *stream = impl_from_IMFByteStream(iface);
3897 TRACE("%p, %p, %p.\n", iface, result, byte_read);
3899 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_READ, result, byte_read);
3902 static HRESULT WINAPI mfbytestream_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
3904 mfbytestream *This = impl_from_IMFByteStream(iface);
3906 FIXME("%p, %p, %u, %p\n", This, data, count, written);
3908 return E_NOTIMPL;
3911 static HRESULT WINAPI bytestream_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
3912 IMFAsyncCallback *callback, IUnknown *state)
3914 struct bytestream *stream = impl_from_IMFByteStream(iface);
3916 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
3918 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_WRITE, data, size, callback, state);
3921 static HRESULT WINAPI bytestream_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
3923 struct bytestream *stream = impl_from_IMFByteStream(iface);
3925 TRACE("%p, %p, %p.\n", iface, result, written);
3927 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_WRITE, result, written);
3930 static HRESULT WINAPI mfbytestream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
3931 DWORD flags, QWORD *current)
3933 mfbytestream *This = impl_from_IMFByteStream(iface);
3935 FIXME("%p, %u, %s, 0x%08x, %p\n", This, seek, wine_dbgstr_longlong(offset), flags, current);
3937 return E_NOTIMPL;
3940 static HRESULT WINAPI mfbytestream_Flush(IMFByteStream *iface)
3942 mfbytestream *This = impl_from_IMFByteStream(iface);
3944 FIXME("%p\n", This);
3946 return E_NOTIMPL;
3949 static HRESULT WINAPI mfbytestream_Close(IMFByteStream *iface)
3951 mfbytestream *This = impl_from_IMFByteStream(iface);
3953 FIXME("%p\n", This);
3955 return E_NOTIMPL;
3958 static HRESULT WINAPI bytestream_SetCurrentPosition(IMFByteStream *iface, QWORD position)
3960 struct bytestream *stream = impl_from_IMFByteStream(iface);
3962 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
3964 EnterCriticalSection(&stream->cs);
3965 stream->position = position;
3966 LeaveCriticalSection(&stream->cs);
3968 return S_OK;
3971 static const IMFByteStreamVtbl bytestream_file_vtbl =
3973 bytestream_QueryInterface,
3974 bytestream_AddRef,
3975 bytestream_Release,
3976 bytestream_GetCapabilities,
3977 bytestream_file_GetLength,
3978 mfbytestream_SetLength,
3979 bytestream_file_GetCurrentPosition,
3980 bytestream_SetCurrentPosition,
3981 bytestream_file_IsEndOfStream,
3982 bytestream_file_Read,
3983 bytestream_BeginRead,
3984 bytestream_EndRead,
3985 mfbytestream_Write,
3986 bytestream_BeginWrite,
3987 bytestream_EndWrite,
3988 mfbytestream_Seek,
3989 mfbytestream_Flush,
3990 mfbytestream_Close
3993 static HRESULT WINAPI bytestream_stream_GetLength(IMFByteStream *iface, QWORD *length)
3995 struct bytestream *stream = impl_from_IMFByteStream(iface);
3996 STATSTG statstg;
3997 HRESULT hr;
3999 TRACE("%p, %p.\n", iface, length);
4001 if (FAILED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4002 return hr;
4004 *length = statstg.cbSize.QuadPart;
4006 return S_OK;
4009 static HRESULT WINAPI bytestream_stream_SetLength(IMFByteStream *iface, QWORD length)
4011 struct bytestream *stream = impl_from_IMFByteStream(iface);
4012 ULARGE_INTEGER size;
4013 HRESULT hr;
4015 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4017 EnterCriticalSection(&stream->cs);
4019 size.QuadPart = length;
4020 hr = IStream_SetSize(stream->stream, size);
4022 LeaveCriticalSection(&stream->cs);
4024 return hr;
4027 static HRESULT WINAPI bytestream_stream_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4029 struct bytestream *stream = impl_from_IMFByteStream(iface);
4031 TRACE("%p, %p.\n", iface, position);
4033 *position = stream->position;
4035 return S_OK;
4038 static HRESULT WINAPI bytestream_stream_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
4040 struct bytestream *stream = impl_from_IMFByteStream(iface);
4041 STATSTG statstg;
4042 HRESULT hr;
4044 TRACE("%p, %p.\n", iface, ret);
4046 EnterCriticalSection(&stream->cs);
4048 if (SUCCEEDED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4049 *ret = stream->position >= statstg.cbSize.QuadPart;
4051 LeaveCriticalSection(&stream->cs);
4053 return hr;
4056 static HRESULT WINAPI bytestream_stream_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
4058 struct bytestream *stream = impl_from_IMFByteStream(iface);
4059 LARGE_INTEGER position;
4060 HRESULT hr;
4062 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, read_len);
4064 EnterCriticalSection(&stream->cs);
4066 position.QuadPart = stream->position;
4067 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4069 if (SUCCEEDED(hr = IStream_Read(stream->stream, buffer, size, read_len)))
4070 stream->position += *read_len;
4073 LeaveCriticalSection(&stream->cs);
4075 return hr;
4078 static HRESULT WINAPI bytestream_stream_Write(IMFByteStream *iface, const BYTE *buffer, ULONG size, ULONG *written)
4080 struct bytestream *stream = impl_from_IMFByteStream(iface);
4081 LARGE_INTEGER position;
4082 HRESULT hr;
4084 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, written);
4086 EnterCriticalSection(&stream->cs);
4088 position.QuadPart = stream->position;
4089 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4091 if (SUCCEEDED(hr = IStream_Write(stream->stream, buffer, size, written)))
4092 stream->position += *written;
4095 LeaveCriticalSection(&stream->cs);
4097 return hr;
4100 static HRESULT WINAPI bytestream_stream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN origin, LONGLONG offset,
4101 DWORD flags, QWORD *current)
4103 struct bytestream *stream = impl_from_IMFByteStream(iface);
4104 HRESULT hr = S_OK;
4106 TRACE("%p, %u, %s, %#x, %p.\n", iface, origin, wine_dbgstr_longlong(offset), flags, current);
4108 EnterCriticalSection(&stream->cs);
4110 switch (origin)
4112 case msoBegin:
4113 stream->position = offset;
4114 break;
4115 case msoCurrent:
4116 stream->position += offset;
4117 break;
4118 default:
4119 WARN("Unknown origin mode %d.\n", origin);
4120 hr = E_INVALIDARG;
4123 *current = stream->position;
4125 LeaveCriticalSection(&stream->cs);
4127 return hr;
4130 static HRESULT WINAPI bytestream_stream_Flush(IMFByteStream *iface)
4132 struct bytestream *stream = impl_from_IMFByteStream(iface);
4134 TRACE("%p.\n", iface);
4136 return IStream_Commit(stream->stream, STGC_DEFAULT);
4139 static HRESULT WINAPI bytestream_stream_Close(IMFByteStream *iface)
4141 TRACE("%p.\n", iface);
4143 return S_OK;
4146 static const IMFByteStreamVtbl bytestream_stream_vtbl =
4148 bytestream_QueryInterface,
4149 bytestream_AddRef,
4150 bytestream_Release,
4151 bytestream_stream_GetCapabilities,
4152 bytestream_stream_GetLength,
4153 bytestream_stream_SetLength,
4154 bytestream_stream_GetCurrentPosition,
4155 bytestream_SetCurrentPosition,
4156 bytestream_stream_IsEndOfStream,
4157 bytestream_stream_Read,
4158 bytestream_BeginRead,
4159 bytestream_EndRead,
4160 bytestream_stream_Write,
4161 bytestream_BeginWrite,
4162 bytestream_EndWrite,
4163 bytestream_stream_Seek,
4164 bytestream_stream_Flush,
4165 bytestream_stream_Close,
4168 static inline mfbytestream *impl_from_IMFByteStream_IMFAttributes(IMFAttributes *iface)
4170 return CONTAINING_RECORD(iface, mfbytestream, attributes.IMFAttributes_iface);
4173 static HRESULT WINAPI mfbytestream_attributes_QueryInterface(
4174 IMFAttributes *iface, REFIID riid, void **out)
4176 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4177 return IMFByteStream_QueryInterface(&This->IMFByteStream_iface, riid, out);
4180 static ULONG WINAPI mfbytestream_attributes_AddRef(IMFAttributes *iface)
4182 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4183 return IMFByteStream_AddRef(&This->IMFByteStream_iface);
4186 static ULONG WINAPI mfbytestream_attributes_Release(IMFAttributes *iface)
4188 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4189 return IMFByteStream_Release(&This->IMFByteStream_iface);
4192 static const IMFAttributesVtbl mfbytestream_attributes_vtbl =
4194 mfbytestream_attributes_QueryInterface,
4195 mfbytestream_attributes_AddRef,
4196 mfbytestream_attributes_Release,
4197 mfattributes_GetItem,
4198 mfattributes_GetItemType,
4199 mfattributes_CompareItem,
4200 mfattributes_Compare,
4201 mfattributes_GetUINT32,
4202 mfattributes_GetUINT64,
4203 mfattributes_GetDouble,
4204 mfattributes_GetGUID,
4205 mfattributes_GetStringLength,
4206 mfattributes_GetString,
4207 mfattributes_GetAllocatedString,
4208 mfattributes_GetBlobSize,
4209 mfattributes_GetBlob,
4210 mfattributes_GetAllocatedBlob,
4211 mfattributes_GetUnknown,
4212 mfattributes_SetItem,
4213 mfattributes_DeleteItem,
4214 mfattributes_DeleteAllItems,
4215 mfattributes_SetUINT32,
4216 mfattributes_SetUINT64,
4217 mfattributes_SetDouble,
4218 mfattributes_SetGUID,
4219 mfattributes_SetString,
4220 mfattributes_SetBlob,
4221 mfattributes_SetUnknown,
4222 mfattributes_LockStore,
4223 mfattributes_UnlockStore,
4224 mfattributes_GetCount,
4225 mfattributes_GetItemByIndex,
4226 mfattributes_CopyAllItems
4229 static HRESULT WINAPI bytestream_stream_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4231 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4232 struct async_stream_op *op;
4233 LARGE_INTEGER position;
4234 IUnknown *object;
4235 HRESULT hr;
4237 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4238 return hr;
4240 op = impl_async_stream_op_from_IUnknown(object);
4242 EnterCriticalSection(&stream->cs);
4244 position.QuadPart = op->position;
4245 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4247 if (SUCCEEDED(hr = IStream_Read(stream->stream, op->u.dest, op->requested_length, &op->actual_length)))
4248 stream->position += op->actual_length;
4251 IMFAsyncResult_SetStatus(op->caller, hr);
4252 list_add_tail(&stream->pending, &op->entry);
4254 LeaveCriticalSection(&stream->cs);
4256 MFInvokeCallback(op->caller);
4258 return S_OK;
4261 static HRESULT WINAPI bytestream_stream_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4263 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4264 struct async_stream_op *op;
4265 LARGE_INTEGER position;
4266 IUnknown *object;
4267 HRESULT hr;
4269 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4270 return hr;
4272 op = impl_async_stream_op_from_IUnknown(object);
4274 EnterCriticalSection(&stream->cs);
4276 position.QuadPart = op->position;
4277 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4279 if (SUCCEEDED(hr = IStream_Write(stream->stream, op->u.src, op->requested_length, &op->actual_length)))
4280 stream->position += op->actual_length;
4283 IMFAsyncResult_SetStatus(op->caller, hr);
4284 list_add_tail(&stream->pending, &op->entry);
4286 LeaveCriticalSection(&stream->cs);
4288 MFInvokeCallback(op->caller);
4290 return S_OK;
4293 static const IRtwqAsyncCallbackVtbl bytestream_stream_read_callback_vtbl =
4295 bytestream_callback_QueryInterface,
4296 bytestream_read_callback_AddRef,
4297 bytestream_read_callback_Release,
4298 bytestream_callback_GetParameters,
4299 bytestream_stream_read_callback_Invoke,
4302 static const IRtwqAsyncCallbackVtbl bytestream_stream_write_callback_vtbl =
4304 bytestream_callback_QueryInterface,
4305 bytestream_write_callback_AddRef,
4306 bytestream_write_callback_Release,
4307 bytestream_callback_GetParameters,
4308 bytestream_stream_write_callback_Invoke,
4311 /***********************************************************************
4312 * MFCreateMFByteStreamOnStream (mfplat.@)
4314 HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **bytestream)
4316 struct bytestream *object;
4317 LARGE_INTEGER position;
4318 STATSTG stat;
4319 HRESULT hr;
4321 TRACE("%p, %p.\n", stream, bytestream);
4323 object = heap_alloc_zero(sizeof(*object));
4324 if (!object)
4325 return E_OUTOFMEMORY;
4327 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
4329 heap_free(object);
4330 return hr;
4333 object->IMFByteStream_iface.lpVtbl = &bytestream_stream_vtbl;
4334 object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
4335 object->read_callback.lpVtbl = &bytestream_stream_read_callback_vtbl;
4336 object->write_callback.lpVtbl = &bytestream_stream_write_callback_vtbl;
4337 InitializeCriticalSection(&object->cs);
4338 list_init(&object->pending);
4340 object->stream = stream;
4341 IStream_AddRef(object->stream);
4342 position.QuadPart = 0;
4343 IStream_Seek(object->stream, position, STREAM_SEEK_SET, NULL);
4345 if (SUCCEEDED(IStream_Stat(object->stream, &stat, 0)))
4347 if (stat.pwcsName)
4349 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME,
4350 stat.pwcsName);
4351 CoTaskMemFree(stat.pwcsName);
4355 *bytestream = &object->IMFByteStream_iface;
4357 return S_OK;
4360 static HRESULT WINAPI bytestream_file_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4362 FIXME("%p, %p.\n", iface, result);
4364 return E_NOTIMPL;
4367 static HRESULT WINAPI bytestream_file_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4369 FIXME("%p, %p.\n", iface, result);
4371 return E_NOTIMPL;
4374 static const IRtwqAsyncCallbackVtbl bytestream_file_read_callback_vtbl =
4376 bytestream_callback_QueryInterface,
4377 bytestream_read_callback_AddRef,
4378 bytestream_read_callback_Release,
4379 bytestream_callback_GetParameters,
4380 bytestream_file_read_callback_Invoke,
4383 static const IRtwqAsyncCallbackVtbl bytestream_file_write_callback_vtbl =
4385 bytestream_callback_QueryInterface,
4386 bytestream_write_callback_AddRef,
4387 bytestream_write_callback_Release,
4388 bytestream_callback_GetParameters,
4389 bytestream_file_write_callback_Invoke,
4392 static HRESULT WINAPI bytestream_file_getservice_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
4394 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4395 return IMFByteStream_QueryInterface(&stream->IMFByteStream_iface, riid, obj);
4398 static ULONG WINAPI bytestream_file_getservice_AddRef(IMFGetService *iface)
4400 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4401 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
4404 static ULONG WINAPI bytestream_file_getservice_Release(IMFGetService *iface)
4406 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4407 return IMFByteStream_Release(&stream->IMFByteStream_iface);
4410 static HRESULT WINAPI bytestream_file_getservice_GetService(IMFGetService *iface, REFGUID service,
4411 REFIID riid, void **obj)
4413 FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
4415 return E_NOTIMPL;
4418 static const IMFGetServiceVtbl bytestream_file_getservice_vtbl =
4420 bytestream_file_getservice_QueryInterface,
4421 bytestream_file_getservice_AddRef,
4422 bytestream_file_getservice_Release,
4423 bytestream_file_getservice_GetService,
4426 /***********************************************************************
4427 * MFCreateFile (mfplat.@)
4429 HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4430 LPCWSTR url, IMFByteStream **bytestream)
4432 DWORD capabilities = MFBYTESTREAM_IS_SEEKABLE | MFBYTESTREAM_DOES_NOT_USE_NETWORK;
4433 DWORD filecreation_disposition = 0, fileaccessmode = 0, fileattributes = 0;
4434 DWORD filesharemode = FILE_SHARE_READ;
4435 struct bytestream *object;
4436 FILETIME writetime;
4437 HANDLE file;
4438 HRESULT hr;
4440 TRACE("%d, %d, %#x, %s, %p.\n", accessmode, openmode, flags, debugstr_w(url), bytestream);
4442 switch (accessmode)
4444 case MF_ACCESSMODE_READ:
4445 fileaccessmode = GENERIC_READ;
4446 capabilities |= MFBYTESTREAM_IS_READABLE;
4447 break;
4448 case MF_ACCESSMODE_WRITE:
4449 fileaccessmode = GENERIC_WRITE;
4450 capabilities |= MFBYTESTREAM_IS_WRITABLE;
4451 break;
4452 case MF_ACCESSMODE_READWRITE:
4453 fileaccessmode = GENERIC_READ | GENERIC_WRITE;
4454 capabilities |= (MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_WRITABLE);
4455 break;
4458 switch (openmode)
4460 case MF_OPENMODE_FAIL_IF_NOT_EXIST:
4461 filecreation_disposition = OPEN_EXISTING;
4462 break;
4463 case MF_OPENMODE_FAIL_IF_EXIST:
4464 filecreation_disposition = CREATE_NEW;
4465 break;
4466 case MF_OPENMODE_RESET_IF_EXIST:
4467 filecreation_disposition = TRUNCATE_EXISTING;
4468 break;
4469 case MF_OPENMODE_APPEND_IF_EXIST:
4470 filecreation_disposition = OPEN_ALWAYS;
4471 fileaccessmode |= FILE_APPEND_DATA;
4472 break;
4473 case MF_OPENMODE_DELETE_IF_EXIST:
4474 filecreation_disposition = CREATE_ALWAYS;
4475 break;
4478 if (flags & MF_FILEFLAGS_NOBUFFERING)
4479 fileattributes |= FILE_FLAG_NO_BUFFERING;
4481 /* Open HANDLE to file */
4482 file = CreateFileW(url, fileaccessmode, filesharemode, NULL,
4483 filecreation_disposition, fileattributes, 0);
4485 if(file == INVALID_HANDLE_VALUE)
4486 return HRESULT_FROM_WIN32(GetLastError());
4488 object = heap_alloc_zero(sizeof(*object));
4489 if (!object)
4491 CloseHandle(file);
4492 return E_OUTOFMEMORY;
4495 if (FAILED(hr = init_attributes_object(&object->attributes, 2)))
4497 CloseHandle(file);
4498 heap_free(object);
4499 return hr;
4501 object->IMFByteStream_iface.lpVtbl = &bytestream_file_vtbl;
4502 object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
4503 object->IMFGetService_iface.lpVtbl = &bytestream_file_getservice_vtbl;
4504 object->read_callback.lpVtbl = &bytestream_file_read_callback_vtbl;
4505 object->write_callback.lpVtbl = &bytestream_file_write_callback_vtbl;
4506 InitializeCriticalSection(&object->cs);
4507 list_init(&object->pending);
4508 object->capabilities = capabilities;
4509 object->hfile = file;
4511 if (GetFileTime(file, NULL, NULL, &writetime))
4513 IMFAttributes_SetBlob(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_LAST_MODIFIED_TIME,
4514 (const UINT8 *)&writetime, sizeof(writetime));
4517 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME, url);
4519 *bytestream = &object->IMFByteStream_iface;
4521 return S_OK;
4524 struct bytestream_wrapper
4526 IMFByteStreamCacheControl IMFByteStreamCacheControl_iface;
4527 IMFByteStreamBuffering IMFByteStreamBuffering_iface;
4528 IMFMediaEventGenerator IMFMediaEventGenerator_iface;
4529 IMFByteStreamTimeSeek IMFByteStreamTimeSeek_iface;
4530 IMFSampleOutputStream IMFSampleOutputStream_iface;
4531 IPropertyStore IPropertyStore_iface;
4532 IMFByteStream IMFByteStream_iface;
4533 IMFAttributes IMFAttributes_iface;
4534 LONG refcount;
4536 IMFByteStreamCacheControl *cache_control;
4537 IMFByteStreamBuffering *stream_buffering;
4538 IMFMediaEventGenerator *event_generator;
4539 IMFByteStreamTimeSeek *time_seek;
4540 IMFSampleOutputStream *sample_output;
4541 IPropertyStore *propstore;
4542 IMFByteStream *stream;
4543 IMFAttributes *attributes;
4544 BOOL is_closed;
4547 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStream(IMFByteStream *iface)
4549 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStream_iface);
4552 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamCacheControl(IMFByteStreamCacheControl *iface)
4554 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamCacheControl_iface);
4557 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamBuffering(IMFByteStreamBuffering *iface)
4559 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamBuffering_iface);
4562 static struct bytestream_wrapper *impl_wrapper_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
4564 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFMediaEventGenerator_iface);
4567 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamTimeSeek(IMFByteStreamTimeSeek *iface)
4569 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamTimeSeek_iface);
4572 static struct bytestream_wrapper *impl_wrapper_from_IMFSampleOutputStream(IMFSampleOutputStream *iface)
4574 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFSampleOutputStream_iface);
4577 static struct bytestream_wrapper *impl_wrapper_from_IPropertyStore(IPropertyStore *iface)
4579 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IPropertyStore_iface);
4582 static struct bytestream_wrapper *impl_wrapper_from_IMFAttributes(IMFAttributes *iface)
4584 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFAttributes_iface);
4587 static HRESULT WINAPI bytestream_wrapper_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
4589 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4591 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
4593 if (IsEqualIID(riid, &IID_IMFByteStream) ||
4594 IsEqualIID(riid, &IID_IUnknown))
4596 *out = &wrapper->IMFByteStream_iface;
4598 else if (wrapper->cache_control && IsEqualIID(riid, &IID_IMFByteStreamCacheControl))
4600 *out = &wrapper->IMFByteStreamCacheControl_iface;
4602 else if (wrapper->stream_buffering && IsEqualIID(riid, &IID_IMFByteStreamBuffering))
4604 *out = &wrapper->IMFByteStreamBuffering_iface;
4606 else if (wrapper->event_generator && IsEqualIID(riid, &IID_IMFMediaEventGenerator))
4608 *out = &wrapper->IMFMediaEventGenerator_iface;
4610 else if (wrapper->time_seek && IsEqualIID(riid, &IID_IMFByteStreamTimeSeek))
4612 *out = &wrapper->IMFByteStreamTimeSeek_iface;
4614 else if (wrapper->sample_output && IsEqualIID(riid, &IID_IMFSampleOutputStream))
4616 *out = &wrapper->IMFSampleOutputStream_iface;
4618 else if (wrapper->propstore && IsEqualIID(riid, &IID_IPropertyStore))
4620 *out = &wrapper->IPropertyStore_iface;
4622 else if (wrapper->attributes && IsEqualIID(riid, &IID_IMFAttributes))
4624 *out = &wrapper->IMFAttributes_iface;
4626 else
4628 WARN("Unsupported %s.\n", debugstr_guid(riid));
4629 *out = NULL;
4630 return E_NOINTERFACE;
4633 IUnknown_AddRef((IUnknown *)*out);
4634 return S_OK;
4637 static ULONG WINAPI bytestream_wrapper_AddRef(IMFByteStream *iface)
4639 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4640 ULONG refcount = InterlockedIncrement(&wrapper->refcount);
4642 TRACE("%p, refcount %d.\n", iface, refcount);
4644 return refcount;
4647 static ULONG WINAPI bytestream_wrapper_Release(IMFByteStream *iface)
4649 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4650 ULONG refcount = InterlockedDecrement(&wrapper->refcount);
4652 TRACE("%p, refcount %d.\n", iface, refcount);
4654 if (!refcount)
4656 if (wrapper->cache_control)
4657 IMFByteStreamCacheControl_Release(wrapper->cache_control);
4658 if (wrapper->stream_buffering)
4659 IMFByteStreamBuffering_Release(wrapper->stream_buffering);
4660 if (wrapper->event_generator)
4661 IMFMediaEventGenerator_Release(wrapper->event_generator);
4662 if (wrapper->time_seek)
4663 IMFByteStreamTimeSeek_Release(wrapper->time_seek);
4664 if (wrapper->sample_output)
4665 IMFSampleOutputStream_Release(wrapper->sample_output);
4666 if (wrapper->propstore)
4667 IPropertyStore_Release(wrapper->propstore);
4668 if (wrapper->attributes)
4669 IMFAttributes_Release(wrapper->attributes);
4670 IMFByteStream_Release(wrapper->stream);
4671 heap_free(wrapper);
4674 return refcount;
4677 static HRESULT WINAPI bytestream_wrapper_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
4679 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4681 TRACE("%p, %p.\n", iface, capabilities);
4683 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4684 IMFByteStream_GetCapabilities(wrapper->stream, capabilities);
4687 static HRESULT WINAPI bytestream_wrapper_GetLength(IMFByteStream *iface, QWORD *length)
4689 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4691 TRACE("%p, %p.\n", iface, length);
4693 if (wrapper->is_closed)
4694 return MF_E_INVALIDREQUEST;
4696 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4697 IMFByteStream_GetLength(wrapper->stream, length);
4700 static HRESULT WINAPI bytestream_wrapper_SetLength(IMFByteStream *iface, QWORD length)
4702 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4704 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4706 if (wrapper->is_closed)
4707 return MF_E_INVALIDREQUEST;
4709 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4710 IMFByteStream_SetLength(wrapper->stream, length);
4713 static HRESULT WINAPI bytestream_wrapper_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4715 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4717 TRACE("%p, %p.\n", iface, position);
4719 if (wrapper->is_closed)
4720 return MF_E_INVALIDREQUEST;
4722 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4723 IMFByteStream_GetCurrentPosition(wrapper->stream, position);
4726 static HRESULT WINAPI bytestream_wrapper_SetCurrentPosition(IMFByteStream *iface, QWORD position)
4728 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4730 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4732 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4733 IMFByteStream_SetCurrentPosition(wrapper->stream, position);
4736 static HRESULT WINAPI bytestream_wrapper_IsEndOfStream(IMFByteStream *iface, BOOL *eos)
4738 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4740 TRACE("%p, %p.\n", iface, eos);
4742 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4743 IMFByteStream_IsEndOfStream(wrapper->stream, eos);
4746 static HRESULT WINAPI bytestream_wrapper_Read(IMFByteStream *iface, BYTE *data, ULONG count, ULONG *byte_read)
4748 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4750 TRACE("%p, %p, %u, %p.\n", iface, data, count, byte_read);
4752 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4753 IMFByteStream_Read(wrapper->stream, data, count, byte_read);
4756 static HRESULT WINAPI bytestream_wrapper_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size,
4757 IMFAsyncCallback *callback, IUnknown *state)
4759 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4761 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
4763 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4764 IMFByteStream_BeginRead(wrapper->stream, data, size, callback, state);
4767 static HRESULT WINAPI bytestream_wrapper_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
4769 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4771 TRACE("%p, %p, %p.\n", iface, result, byte_read);
4773 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4774 IMFByteStream_EndRead(wrapper->stream, result, byte_read);
4777 static HRESULT WINAPI bytestream_wrapper_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
4779 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4781 TRACE("%p, %p, %u, %p.\n", iface, data, count, written);
4783 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4784 IMFByteStream_Write(wrapper->stream, data, count, written);
4787 static HRESULT WINAPI bytestream_wrapper_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
4788 IMFAsyncCallback *callback, IUnknown *state)
4790 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4792 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
4794 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4795 IMFByteStream_BeginWrite(wrapper->stream, data, size, callback, state);
4798 static HRESULT WINAPI bytestream_wrapper_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
4800 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4802 TRACE("%p, %p, %p.\n", iface, result, written);
4804 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4805 IMFByteStream_EndWrite(wrapper->stream, result, written);
4808 static HRESULT WINAPI bytestream_wrapper_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
4809 DWORD flags, QWORD *current)
4811 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4813 TRACE("%p, %u, %s, %#x, %p.\n", iface, seek, wine_dbgstr_longlong(offset), flags, current);
4815 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4816 IMFByteStream_Seek(wrapper->stream, seek, offset, flags, current);
4819 static HRESULT WINAPI bytestream_wrapper_Flush(IMFByteStream *iface)
4821 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4823 TRACE("%p\n", iface);
4825 return wrapper->is_closed ? MF_E_INVALIDREQUEST : IMFByteStream_Flush(wrapper->stream);
4828 static HRESULT WINAPI bytestream_wrapper_Close(IMFByteStream *iface)
4830 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4832 TRACE("%p\n", iface);
4834 wrapper->is_closed = TRUE;
4836 return S_OK;
4839 static const IMFByteStreamVtbl bytestream_wrapper_vtbl =
4841 bytestream_wrapper_QueryInterface,
4842 bytestream_wrapper_AddRef,
4843 bytestream_wrapper_Release,
4844 bytestream_wrapper_GetCapabilities,
4845 bytestream_wrapper_GetLength,
4846 bytestream_wrapper_SetLength,
4847 bytestream_wrapper_GetCurrentPosition,
4848 bytestream_wrapper_SetCurrentPosition,
4849 bytestream_wrapper_IsEndOfStream,
4850 bytestream_wrapper_Read,
4851 bytestream_wrapper_BeginRead,
4852 bytestream_wrapper_EndRead,
4853 bytestream_wrapper_Write,
4854 bytestream_wrapper_BeginWrite,
4855 bytestream_wrapper_EndWrite,
4856 bytestream_wrapper_Seek,
4857 bytestream_wrapper_Flush,
4858 bytestream_wrapper_Close,
4861 static HRESULT WINAPI bytestream_wrapper_cache_control_QueryInterface(IMFByteStreamCacheControl *iface,
4862 REFIID riid, void **obj)
4864 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4865 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4868 static ULONG WINAPI bytestream_wrapper_cache_control_AddRef(IMFByteStreamCacheControl *iface)
4870 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4871 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4874 static ULONG WINAPI bytestream_wrapper_cache_control_Release(IMFByteStreamCacheControl *iface)
4876 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4877 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4880 static HRESULT WINAPI bytestream_wrapper_cache_control_StopBackgroundTransfer(IMFByteStreamCacheControl *iface)
4882 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4884 TRACE("%p.\n", iface);
4886 return IMFByteStreamCacheControl_StopBackgroundTransfer(wrapper->cache_control);
4889 static const IMFByteStreamCacheControlVtbl bytestream_wrapper_cache_control_vtbl =
4891 bytestream_wrapper_cache_control_QueryInterface,
4892 bytestream_wrapper_cache_control_AddRef,
4893 bytestream_wrapper_cache_control_Release,
4894 bytestream_wrapper_cache_control_StopBackgroundTransfer,
4897 static HRESULT WINAPI bytestream_wrapper_buffering_QueryInterface(IMFByteStreamBuffering *iface,
4898 REFIID riid, void **obj)
4900 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4901 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4904 static ULONG WINAPI bytestream_wrapper_buffering_AddRef(IMFByteStreamBuffering *iface)
4906 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4907 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4910 static ULONG WINAPI bytestream_wrapper_buffering_Release(IMFByteStreamBuffering *iface)
4912 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4913 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4916 static HRESULT WINAPI bytestream_wrapper_buffering_SetBufferingParams(IMFByteStreamBuffering *iface,
4917 MFBYTESTREAM_BUFFERING_PARAMS *params)
4919 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4921 TRACE("%p, %p.\n", iface, params);
4923 return IMFByteStreamBuffering_SetBufferingParams(wrapper->stream_buffering, params);
4926 static HRESULT WINAPI bytestream_wrapper_buffering_EnableBuffering(IMFByteStreamBuffering *iface,
4927 BOOL enable)
4929 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4931 TRACE("%p, %d.\n", iface, enable);
4933 return IMFByteStreamBuffering_EnableBuffering(wrapper->stream_buffering, enable);
4936 static HRESULT WINAPI bytestream_wrapper_buffering_StopBuffering(IMFByteStreamBuffering *iface)
4938 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4940 TRACE("%p.\n", iface);
4942 return IMFByteStreamBuffering_StopBuffering(wrapper->stream_buffering);
4945 static const IMFByteStreamBufferingVtbl bytestream_wrapper_buffering_vtbl =
4947 bytestream_wrapper_buffering_QueryInterface,
4948 bytestream_wrapper_buffering_AddRef,
4949 bytestream_wrapper_buffering_Release,
4950 bytestream_wrapper_buffering_SetBufferingParams,
4951 bytestream_wrapper_buffering_EnableBuffering,
4952 bytestream_wrapper_buffering_StopBuffering,
4955 static HRESULT WINAPI bytestream_wrapper_timeseek_QueryInterface(IMFByteStreamTimeSeek *iface,
4956 REFIID riid, void **obj)
4958 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4959 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4962 static ULONG WINAPI bytestream_wrapper_timeseek_AddRef(IMFByteStreamTimeSeek *iface)
4964 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4965 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4968 static ULONG WINAPI bytestream_wrapper_timeseek_Release(IMFByteStreamTimeSeek *iface)
4970 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4971 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4974 static HRESULT WINAPI bytestream_wrapper_timeseek_IsTimeSeekSupported(IMFByteStreamTimeSeek *iface, BOOL *result)
4976 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4978 TRACE("%p, %p.\n", iface, result);
4980 return IMFByteStreamTimeSeek_IsTimeSeekSupported(wrapper->time_seek, result);
4983 static HRESULT WINAPI bytestream_wrapper_timeseek_TimeSeek(IMFByteStreamTimeSeek *iface, QWORD position)
4985 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4987 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4989 return IMFByteStreamTimeSeek_TimeSeek(wrapper->time_seek, position);
4992 static HRESULT WINAPI bytestream_wrapper_timeseek_GetTimeSeekResult(IMFByteStreamTimeSeek *iface, QWORD *start_time,
4993 QWORD *stop_time, QWORD *duration)
4995 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4997 TRACE("%p, %p, %p, %p.\n", iface, start_time, stop_time, duration);
4999 return IMFByteStreamTimeSeek_GetTimeSeekResult(wrapper->time_seek, start_time, stop_time, duration);
5002 static const IMFByteStreamTimeSeekVtbl bytestream_wrapper_timeseek_vtbl =
5004 bytestream_wrapper_timeseek_QueryInterface,
5005 bytestream_wrapper_timeseek_AddRef,
5006 bytestream_wrapper_timeseek_Release,
5007 bytestream_wrapper_timeseek_IsTimeSeekSupported,
5008 bytestream_wrapper_timeseek_TimeSeek,
5009 bytestream_wrapper_timeseek_GetTimeSeekResult,
5012 static HRESULT WINAPI bytestream_wrapper_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
5014 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5015 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5018 static ULONG WINAPI bytestream_wrapper_events_AddRef(IMFMediaEventGenerator *iface)
5020 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5021 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5024 static ULONG WINAPI bytestream_wrapper_events_Release(IMFMediaEventGenerator *iface)
5026 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5027 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5030 static HRESULT WINAPI bytestream_wrapper_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
5032 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5034 TRACE("%p, %#x, %p.\n", iface, flags, event);
5036 return IMFMediaEventGenerator_GetEvent(wrapper->event_generator, flags, event);
5039 static HRESULT WINAPI bytestream_wrapper_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback, IUnknown *state)
5041 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5043 TRACE("%p, %p, %p.\n", iface, callback, state);
5045 return IMFMediaEventGenerator_BeginGetEvent(wrapper->event_generator, callback, state);
5048 static HRESULT WINAPI bytestream_wrapper_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result, IMFMediaEvent **event)
5050 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5052 TRACE("%p, %p, %p.\n", iface, result, event);
5054 return IMFMediaEventGenerator_EndGetEvent(wrapper->event_generator, result, event);
5057 static HRESULT WINAPI bytestream_wrapper_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType type,
5058 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
5060 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5062 TRACE("%p, %d, %s, %#x, %s.\n", iface, type, debugstr_guid(ext_type), hr, debugstr_propvar(value));
5064 return IMFMediaEventGenerator_QueueEvent(wrapper->event_generator, type, ext_type, hr, value);
5067 static const IMFMediaEventGeneratorVtbl bytestream_wrapper_events_vtbl =
5069 bytestream_wrapper_events_QueryInterface,
5070 bytestream_wrapper_events_AddRef,
5071 bytestream_wrapper_events_Release,
5072 bytestream_wrapper_events_GetEvent,
5073 bytestream_wrapper_events_BeginGetEvent,
5074 bytestream_wrapper_events_EndGetEvent,
5075 bytestream_wrapper_events_QueueEvent,
5078 static HRESULT WINAPI bytestream_wrapper_sample_output_QueryInterface(IMFSampleOutputStream *iface, REFIID riid, void **obj)
5080 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5081 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5084 static ULONG WINAPI bytestream_wrapper_sample_output_AddRef(IMFSampleOutputStream *iface)
5086 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5087 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5090 static ULONG WINAPI bytestream_wrapper_sample_output_Release(IMFSampleOutputStream *iface)
5092 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5093 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5096 static HRESULT WINAPI bytestream_wrapper_sample_output_BeginWriteSample(IMFSampleOutputStream *iface, IMFSample *sample,
5097 IMFAsyncCallback *callback, IUnknown *state)
5099 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5101 TRACE("%p, %p, %p, %p.\n", iface, sample, callback, state);
5103 return IMFSampleOutputStream_BeginWriteSample(wrapper->sample_output, sample, callback, state);
5106 static HRESULT WINAPI bytestream_wrapper_sample_output_EndWriteSample(IMFSampleOutputStream *iface, IMFAsyncResult *result)
5108 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5110 TRACE("%p, %p.\n", iface, result);
5112 return IMFSampleOutputStream_EndWriteSample(wrapper->sample_output, result);
5115 static HRESULT WINAPI bytestream_wrapper_sample_output_Close(IMFSampleOutputStream *iface)
5117 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5119 TRACE("%p.\n", iface);
5121 return IMFSampleOutputStream_Close(wrapper->sample_output);
5124 static const IMFSampleOutputStreamVtbl bytestream_wrapper_sample_output_vtbl =
5126 bytestream_wrapper_sample_output_QueryInterface,
5127 bytestream_wrapper_sample_output_AddRef,
5128 bytestream_wrapper_sample_output_Release,
5129 bytestream_wrapper_sample_output_BeginWriteSample,
5130 bytestream_wrapper_sample_output_EndWriteSample,
5131 bytestream_wrapper_sample_output_Close,
5134 static HRESULT WINAPI bytestream_wrapper_propstore_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
5136 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5137 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5140 static ULONG WINAPI bytestream_wrapper_propstore_AddRef(IPropertyStore *iface)
5142 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5143 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5146 static ULONG WINAPI bytestream_wrapper_propstore_Release(IPropertyStore *iface)
5148 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5149 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5152 static HRESULT WINAPI bytestream_wrapper_propstore_GetCount(IPropertyStore *iface, DWORD *count)
5154 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5156 TRACE("%p, %p.\n", iface, count);
5158 return IPropertyStore_GetCount(wrapper->propstore, count);
5161 static HRESULT WINAPI bytestream_wrapper_propstore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
5163 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5165 TRACE("%p, %u, %p.\n", iface, prop, key);
5167 return IPropertyStore_GetAt(wrapper->propstore, prop, key);
5170 static HRESULT WINAPI bytestream_wrapper_propstore_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
5172 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5174 TRACE("%p, %p, %p.\n", iface, key, value);
5176 return IPropertyStore_GetValue(wrapper->propstore, key, value);
5179 static HRESULT WINAPI bytestream_wrapper_propstore_SetValue(IPropertyStore *iface, REFPROPERTYKEY key,
5180 const PROPVARIANT *value)
5182 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5184 TRACE("%p, %p, %s.\n", iface, key, debugstr_propvar(value));
5186 return IPropertyStore_SetValue(wrapper->propstore, key, value);
5189 static HRESULT WINAPI bytestream_wrapper_propstore_Commit(IPropertyStore *iface)
5191 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5193 TRACE("%p.\n", iface);
5195 return IPropertyStore_Commit(wrapper->propstore);
5198 static const IPropertyStoreVtbl bytestream_wrapper_propstore_vtbl =
5200 bytestream_wrapper_propstore_QueryInterface,
5201 bytestream_wrapper_propstore_AddRef,
5202 bytestream_wrapper_propstore_Release,
5203 bytestream_wrapper_propstore_GetCount,
5204 bytestream_wrapper_propstore_GetAt,
5205 bytestream_wrapper_propstore_GetValue,
5206 bytestream_wrapper_propstore_SetValue,
5207 bytestream_wrapper_propstore_Commit,
5210 static HRESULT WINAPI bytestream_wrapper_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
5212 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5213 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5216 static ULONG WINAPI bytestream_wrapper_attributes_AddRef(IMFAttributes *iface)
5218 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5219 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5222 static ULONG WINAPI bytestream_wrapper_attributes_Release(IMFAttributes *iface)
5224 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5225 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5228 static HRESULT WINAPI bytestream_wrapper_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
5230 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5232 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5234 return IMFAttributes_GetItem(wrapper->attributes, key, value);
5237 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
5239 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5241 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
5243 return IMFAttributes_GetItemType(wrapper->attributes, key, type);
5246 static HRESULT WINAPI bytestream_wrapper_attributes_CompareItem(IMFAttributes *iface, REFGUID key,
5247 REFPROPVARIANT value, BOOL *result)
5249 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5251 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
5253 return IMFAttributes_CompareItem(wrapper->attributes, key, value, result);
5256 static HRESULT WINAPI bytestream_wrapper_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
5257 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
5259 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5261 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
5263 return IMFAttributes_Compare(wrapper->attributes, theirs, match_type, ret);
5266 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
5268 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5270 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5272 return IMFAttributes_GetUINT32(wrapper->attributes, key, value);
5275 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
5277 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5279 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5281 return IMFAttributes_GetUINT64(wrapper->attributes, key, value);
5284 static HRESULT WINAPI bytestream_wrapper_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
5286 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5288 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5290 return IMFAttributes_GetDouble(wrapper->attributes, key, value);
5293 static HRESULT WINAPI bytestream_wrapper_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
5295 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5297 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5299 return IMFAttributes_GetGUID(wrapper->attributes, key, value);
5302 static HRESULT WINAPI bytestream_wrapper_attributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
5304 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5306 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
5308 return IMFAttributes_GetStringLength(wrapper->attributes, key, length);
5311 static HRESULT WINAPI bytestream_wrapper_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
5312 UINT32 size, UINT32 *length)
5314 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5316 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
5318 return IMFAttributes_GetString(wrapper->attributes, key, value, size, length);
5321 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
5323 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5325 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
5327 return IMFAttributes_GetAllocatedString(wrapper->attributes, key, value, length);
5330 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
5332 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5334 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
5336 return IMFAttributes_GetBlobSize(wrapper->attributes, key, size);
5339 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
5340 UINT32 bufsize, UINT32 *blobsize)
5342 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5344 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
5346 return IMFAttributes_GetBlob(wrapper->attributes, key, buf, bufsize, blobsize);
5349 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
5351 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5353 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
5355 return IMFAttributes_GetAllocatedBlob(wrapper->attributes, key, buf, size);
5358 static HRESULT WINAPI bytestream_wrapper_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **obj)
5360 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5362 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), obj);
5364 return IMFAttributes_GetUnknown(wrapper->attributes, key, riid, obj);
5367 static HRESULT WINAPI bytestream_wrapper_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
5369 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5371 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
5373 return IMFAttributes_SetItem(wrapper->attributes, key, value);
5376 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
5378 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5380 TRACE("%p, %s.\n", iface, debugstr_attr(key));
5382 return IMFAttributes_DeleteItem(wrapper->attributes, key);
5385 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteAllItems(IMFAttributes *iface)
5387 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5389 TRACE("%p.\n", iface);
5391 return IMFAttributes_DeleteAllItems(wrapper->attributes);
5394 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
5396 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5398 TRACE("%p, %s, %d.\n", iface, debugstr_attr(key), value);
5400 return IMFAttributes_SetUINT32(wrapper->attributes, key, value);
5403 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
5405 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5407 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
5409 return IMFAttributes_SetUINT64(wrapper->attributes, key, value);
5412 static HRESULT WINAPI bytestream_wrapper_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
5414 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5416 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
5418 return IMFAttributes_SetDouble(wrapper->attributes, key, value);
5421 static HRESULT WINAPI bytestream_wrapper_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
5423 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5425 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
5427 return IMFAttributes_SetGUID(wrapper->attributes, key, value);
5430 static HRESULT WINAPI bytestream_wrapper_attributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
5432 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5434 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
5436 return IMFAttributes_SetString(wrapper->attributes, key, value);
5439 static HRESULT WINAPI bytestream_wrapper_attributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
5441 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5443 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
5445 return IMFAttributes_SetBlob(wrapper->attributes, key, buf, size);
5448 static HRESULT WINAPI bytestream_wrapper_attributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
5450 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5452 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
5454 return IMFAttributes_SetUnknown(wrapper->attributes, key, unknown);
5457 static HRESULT WINAPI bytestream_wrapper_attributes_LockStore(IMFAttributes *iface)
5459 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5461 TRACE("%p.\n", iface);
5463 return IMFAttributes_LockStore(wrapper->attributes);
5466 static HRESULT WINAPI bytestream_wrapper_attributes_UnlockStore(IMFAttributes *iface)
5468 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5470 TRACE("%p.\n", iface);
5472 return IMFAttributes_UnlockStore(wrapper->attributes);
5475 static HRESULT WINAPI bytestream_wrapper_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
5477 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5479 TRACE("%p, %p.\n", iface, count);
5481 return IMFAttributes_GetCount(wrapper->attributes, count);
5484 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
5486 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5488 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
5490 return IMFAttributes_GetItemByIndex(wrapper->attributes, index, key, value);
5493 static HRESULT WINAPI bytestream_wrapper_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
5495 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5497 TRACE("%p, %p.\n", iface, dest);
5499 return IMFAttributes_CopyAllItems(wrapper->attributes, dest);
5502 static const IMFAttributesVtbl bytestream_wrapper_attributes_vtbl =
5504 bytestream_wrapper_attributes_QueryInterface,
5505 bytestream_wrapper_attributes_AddRef,
5506 bytestream_wrapper_attributes_Release,
5507 bytestream_wrapper_attributes_GetItem,
5508 bytestream_wrapper_attributes_GetItemType,
5509 bytestream_wrapper_attributes_CompareItem,
5510 bytestream_wrapper_attributes_Compare,
5511 bytestream_wrapper_attributes_GetUINT32,
5512 bytestream_wrapper_attributes_GetUINT64,
5513 bytestream_wrapper_attributes_GetDouble,
5514 bytestream_wrapper_attributes_GetGUID,
5515 bytestream_wrapper_attributes_GetStringLength,
5516 bytestream_wrapper_attributes_GetString,
5517 bytestream_wrapper_attributes_GetAllocatedString,
5518 bytestream_wrapper_attributes_GetBlobSize,
5519 bytestream_wrapper_attributes_GetBlob,
5520 bytestream_wrapper_attributes_GetAllocatedBlob,
5521 bytestream_wrapper_attributes_GetUnknown,
5522 bytestream_wrapper_attributes_SetItem,
5523 bytestream_wrapper_attributes_DeleteItem,
5524 bytestream_wrapper_attributes_DeleteAllItems,
5525 bytestream_wrapper_attributes_SetUINT32,
5526 bytestream_wrapper_attributes_SetUINT64,
5527 bytestream_wrapper_attributes_SetDouble,
5528 bytestream_wrapper_attributes_SetGUID,
5529 bytestream_wrapper_attributes_SetString,
5530 bytestream_wrapper_attributes_SetBlob,
5531 bytestream_wrapper_attributes_SetUnknown,
5532 bytestream_wrapper_attributes_LockStore,
5533 bytestream_wrapper_attributes_UnlockStore,
5534 bytestream_wrapper_attributes_GetCount,
5535 bytestream_wrapper_attributes_GetItemByIndex,
5536 bytestream_wrapper_attributes_CopyAllItems
5539 /***********************************************************************
5540 * MFCreateMFByteStreamWrapper (mfplat.@)
5542 HRESULT WINAPI MFCreateMFByteStreamWrapper(IMFByteStream *stream, IMFByteStream **wrapper)
5544 struct bytestream_wrapper *object;
5546 TRACE("%p, %p.\n", stream, wrapper);
5548 object = heap_alloc_zero(sizeof(*object));
5549 if (!object)
5550 return E_OUTOFMEMORY;
5552 object->IMFByteStreamCacheControl_iface.lpVtbl = &bytestream_wrapper_cache_control_vtbl;
5553 object->IMFByteStreamBuffering_iface.lpVtbl = &bytestream_wrapper_buffering_vtbl;
5554 object->IMFMediaEventGenerator_iface.lpVtbl = &bytestream_wrapper_events_vtbl;
5555 object->IMFByteStreamTimeSeek_iface.lpVtbl = &bytestream_wrapper_timeseek_vtbl;
5556 object->IMFSampleOutputStream_iface.lpVtbl = &bytestream_wrapper_sample_output_vtbl;
5557 object->IMFByteStream_iface.lpVtbl = &bytestream_wrapper_vtbl;
5558 object->IPropertyStore_iface.lpVtbl = &bytestream_wrapper_propstore_vtbl;
5559 object->IMFAttributes_iface.lpVtbl = &bytestream_wrapper_attributes_vtbl;
5561 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamCacheControl, (void **)&object->cache_control);
5562 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamBuffering, (void **)&object->stream_buffering);
5563 IMFByteStream_QueryInterface(stream, &IID_IMFMediaEventGenerator, (void **)&object->event_generator);
5564 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamTimeSeek, (void **)&object->time_seek);
5565 IMFByteStream_QueryInterface(stream, &IID_IMFSampleOutputStream, (void **)&object->sample_output);
5566 IMFByteStream_QueryInterface(stream, &IID_IPropertyStore, (void **)&object->propstore);
5567 IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&object->attributes);
5569 object->stream = stream;
5570 IMFByteStream_AddRef(object->stream);
5572 object->refcount = 1;
5574 *wrapper = &object->IMFByteStream_iface;
5576 return S_OK;
5579 static HRESULT WINAPI MFPluginControl_QueryInterface(IMFPluginControl *iface, REFIID riid, void **ppv)
5581 if(IsEqualGUID(riid, &IID_IUnknown)) {
5582 TRACE("(IID_IUnknown %p)\n", ppv);
5583 *ppv = iface;
5584 }else if(IsEqualGUID(riid, &IID_IMFPluginControl)) {
5585 TRACE("(IID_IMFPluginControl %p)\n", ppv);
5586 *ppv = iface;
5587 }else {
5588 FIXME("(%s %p)\n", debugstr_guid(riid), ppv);
5589 *ppv = NULL;
5590 return E_NOINTERFACE;
5593 IUnknown_AddRef((IUnknown*)*ppv);
5594 return S_OK;
5597 static ULONG WINAPI MFPluginControl_AddRef(IMFPluginControl *iface)
5599 TRACE("\n");
5600 return 2;
5603 static ULONG WINAPI MFPluginControl_Release(IMFPluginControl *iface)
5605 TRACE("\n");
5606 return 1;
5609 static HRESULT WINAPI MFPluginControl_GetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5610 const WCHAR *selector, CLSID *clsid)
5612 FIXME("(%d %s %p)\n", plugin_type, debugstr_w(selector), clsid);
5613 return E_NOTIMPL;
5616 static HRESULT WINAPI MFPluginControl_GetPreferredClsidByIndex(IMFPluginControl *iface, DWORD plugin_type,
5617 DWORD index, WCHAR **selector, CLSID *clsid)
5619 FIXME("(%d %d %p %p)\n", plugin_type, index, selector, clsid);
5620 return E_NOTIMPL;
5623 static HRESULT WINAPI MFPluginControl_SetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5624 const WCHAR *selector, const CLSID *clsid)
5626 FIXME("(%d %s %s)\n", plugin_type, debugstr_w(selector), debugstr_guid(clsid));
5627 return E_NOTIMPL;
5630 static HRESULT WINAPI MFPluginControl_IsDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid)
5632 FIXME("(%d %s)\n", plugin_type, debugstr_guid(clsid));
5633 return E_NOTIMPL;
5636 static HRESULT WINAPI MFPluginControl_GetDisabledByIndex(IMFPluginControl *iface, DWORD plugin_type, DWORD index, CLSID *clsid)
5638 FIXME("(%d %d %p)\n", plugin_type, index, clsid);
5639 return E_NOTIMPL;
5642 static HRESULT WINAPI MFPluginControl_SetDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid, BOOL disabled)
5644 FIXME("(%d %s %x)\n", plugin_type, debugstr_guid(clsid), disabled);
5645 return E_NOTIMPL;
5648 static const IMFPluginControlVtbl MFPluginControlVtbl = {
5649 MFPluginControl_QueryInterface,
5650 MFPluginControl_AddRef,
5651 MFPluginControl_Release,
5652 MFPluginControl_GetPreferredClsid,
5653 MFPluginControl_GetPreferredClsidByIndex,
5654 MFPluginControl_SetPreferredClsid,
5655 MFPluginControl_IsDisabled,
5656 MFPluginControl_GetDisabledByIndex,
5657 MFPluginControl_SetDisabled
5660 static IMFPluginControl plugin_control = { &MFPluginControlVtbl };
5662 /***********************************************************************
5663 * MFGetPluginControl (mfplat.@)
5665 HRESULT WINAPI MFGetPluginControl(IMFPluginControl **ret)
5667 TRACE("(%p)\n", ret);
5669 *ret = &plugin_control;
5670 return S_OK;
5673 enum resolved_object_origin
5675 OBJECT_FROM_BYTESTREAM,
5676 OBJECT_FROM_URL,
5679 struct resolver_queued_result
5681 struct list entry;
5682 IUnknown *object;
5683 MF_OBJECT_TYPE obj_type;
5684 HRESULT hr;
5685 IRtwqAsyncResult *inner_result;
5686 enum resolved_object_origin origin;
5689 struct resolver_cancel_object
5691 IUnknown IUnknown_iface;
5692 LONG refcount;
5693 union
5695 IUnknown *handler;
5696 IMFByteStreamHandler *stream_handler;
5697 IMFSchemeHandler *scheme_handler;
5698 } u;
5699 IUnknown *cancel_cookie;
5700 enum resolved_object_origin origin;
5703 struct source_resolver
5705 IMFSourceResolver IMFSourceResolver_iface;
5706 LONG refcount;
5707 IRtwqAsyncCallback stream_callback;
5708 IRtwqAsyncCallback url_callback;
5709 CRITICAL_SECTION cs;
5710 struct list pending;
5713 static struct source_resolver *impl_from_IMFSourceResolver(IMFSourceResolver *iface)
5715 return CONTAINING_RECORD(iface, struct source_resolver, IMFSourceResolver_iface);
5718 static struct source_resolver *impl_from_stream_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5720 return CONTAINING_RECORD(iface, struct source_resolver, stream_callback);
5723 static struct source_resolver *impl_from_url_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5725 return CONTAINING_RECORD(iface, struct source_resolver, url_callback);
5728 static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enum resolved_object_origin origin,
5729 IRtwqAsyncResult *result)
5731 IRtwqAsyncResult *inner_result = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
5732 RTWQASYNCRESULT *data = (RTWQASYNCRESULT *)inner_result;
5733 struct resolver_queued_result *queued_result;
5734 union
5736 IUnknown *handler;
5737 IMFByteStreamHandler *stream_handler;
5738 IMFSchemeHandler *scheme_handler;
5739 } handler;
5741 if (!(queued_result = heap_alloc_zero(sizeof(*queued_result))))
5742 return E_OUTOFMEMORY;
5744 queued_result->origin = origin;
5746 IRtwqAsyncResult_GetObject(inner_result, &handler.handler);
5748 switch (origin)
5750 case OBJECT_FROM_BYTESTREAM:
5751 queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, (IMFAsyncResult *)result,
5752 &queued_result->obj_type, &queued_result->object);
5753 break;
5754 case OBJECT_FROM_URL:
5755 queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, (IMFAsyncResult *)result,
5756 &queued_result->obj_type, &queued_result->object);
5757 break;
5758 default:
5759 queued_result->hr = E_FAIL;
5762 IUnknown_Release(handler.handler);
5764 if (data->hEvent)
5766 queued_result->inner_result = inner_result;
5767 IRtwqAsyncResult_AddRef(queued_result->inner_result);
5770 /* Push resolved object type and created object, so we don't have to guess on End*() call. */
5771 EnterCriticalSection(&resolver->cs);
5772 list_add_tail(&resolver->pending, &queued_result->entry);
5773 LeaveCriticalSection(&resolver->cs);
5775 if (data->hEvent)
5776 SetEvent(data->hEvent);
5777 else
5779 IUnknown *caller_state = IRtwqAsyncResult_GetStateNoAddRef(inner_result);
5780 IRtwqAsyncResult *caller_result;
5782 if (SUCCEEDED(RtwqCreateAsyncResult(queued_result->object, data->pCallback, caller_state, &caller_result)))
5784 RtwqInvokeCallback(caller_result);
5785 IRtwqAsyncResult_Release(caller_result);
5789 return S_OK;
5792 static struct resolver_cancel_object *impl_cancel_obj_from_IUnknown(IUnknown *iface)
5794 return CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface);
5797 static HRESULT WINAPI resolver_cancel_object_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
5799 if (IsEqualIID(riid, &IID_IUnknown))
5801 *obj = iface;
5802 IUnknown_AddRef(iface);
5803 return S_OK;
5806 *obj = NULL;
5807 return E_NOINTERFACE;
5810 static ULONG WINAPI resolver_cancel_object_AddRef(IUnknown *iface)
5812 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5813 return InterlockedIncrement(&object->refcount);
5816 static ULONG WINAPI resolver_cancel_object_Release(IUnknown *iface)
5818 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5819 ULONG refcount = InterlockedDecrement(&object->refcount);
5821 if (!refcount)
5823 if (object->cancel_cookie)
5824 IUnknown_Release(object->cancel_cookie);
5825 IUnknown_Release(object->u.handler);
5826 heap_free(object);
5829 return refcount;
5832 static const IUnknownVtbl resolver_cancel_object_vtbl =
5834 resolver_cancel_object_QueryInterface,
5835 resolver_cancel_object_AddRef,
5836 resolver_cancel_object_Release,
5839 static struct resolver_cancel_object *unsafe_impl_cancel_obj_from_IUnknown(IUnknown *iface)
5841 if (!iface)
5842 return NULL;
5844 return (iface->lpVtbl == &resolver_cancel_object_vtbl) ?
5845 CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface) : NULL;
5848 static HRESULT resolver_create_cancel_object(IUnknown *handler, enum resolved_object_origin origin,
5849 IUnknown *cancel_cookie, IUnknown **cancel_object)
5851 struct resolver_cancel_object *object;
5853 object = heap_alloc_zero(sizeof(*object));
5854 if (!object)
5855 return E_OUTOFMEMORY;
5857 object->IUnknown_iface.lpVtbl = &resolver_cancel_object_vtbl;
5858 object->refcount = 1;
5859 object->u.handler = handler;
5860 IUnknown_AddRef(object->u.handler);
5861 object->cancel_cookie = cancel_cookie;
5862 IUnknown_AddRef(object->cancel_cookie);
5863 object->origin = origin;
5865 *cancel_object = &object->IUnknown_iface;
5867 return S_OK;
5870 static HRESULT WINAPI source_resolver_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
5872 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
5873 IsEqualIID(riid, &IID_IUnknown))
5875 *obj = iface;
5876 IRtwqAsyncCallback_AddRef(iface);
5877 return S_OK;
5880 *obj = NULL;
5881 return E_NOINTERFACE;
5884 static ULONG WINAPI source_resolver_callback_stream_AddRef(IRtwqAsyncCallback *iface)
5886 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5887 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
5890 static ULONG WINAPI source_resolver_callback_stream_Release(IRtwqAsyncCallback *iface)
5892 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5893 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
5896 static HRESULT WINAPI source_resolver_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
5898 return E_NOTIMPL;
5901 static HRESULT WINAPI source_resolver_callback_stream_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
5903 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5905 return resolver_handler_end_create(resolver, OBJECT_FROM_BYTESTREAM, result);
5908 static const IRtwqAsyncCallbackVtbl source_resolver_callback_stream_vtbl =
5910 source_resolver_callback_QueryInterface,
5911 source_resolver_callback_stream_AddRef,
5912 source_resolver_callback_stream_Release,
5913 source_resolver_callback_GetParameters,
5914 source_resolver_callback_stream_Invoke,
5917 static ULONG WINAPI source_resolver_callback_url_AddRef(IRtwqAsyncCallback *iface)
5919 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5920 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
5923 static ULONG WINAPI source_resolver_callback_url_Release(IRtwqAsyncCallback *iface)
5925 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5926 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
5929 static HRESULT WINAPI source_resolver_callback_url_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
5931 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5933 return resolver_handler_end_create(resolver, OBJECT_FROM_URL, result);
5936 static const IRtwqAsyncCallbackVtbl source_resolver_callback_url_vtbl =
5938 source_resolver_callback_QueryInterface,
5939 source_resolver_callback_url_AddRef,
5940 source_resolver_callback_url_Release,
5941 source_resolver_callback_GetParameters,
5942 source_resolver_callback_url_Invoke,
5945 static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void **handler)
5947 unsigned int j = 0, name_length, type;
5948 HRESULT hr = E_FAIL;
5949 WCHAR clsidW[39];
5950 CLSID clsid;
5952 name_length = ARRAY_SIZE(clsidW);
5953 while (!RegEnumValueW(hkey, j++, clsidW, &name_length, NULL, &type, NULL, NULL))
5955 if (type == REG_SZ)
5957 if (SUCCEEDED(CLSIDFromString(clsidW, &clsid)))
5959 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, riid, handler);
5960 if (SUCCEEDED(hr))
5961 break;
5965 name_length = ARRAY_SIZE(clsidW);
5968 return hr;
5971 static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags,
5972 IMFByteStreamHandler **handler)
5974 static const char streamhandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers";
5975 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
5976 IMFAttributes *attributes;
5977 const WCHAR *url_ext;
5978 WCHAR *mimeW = NULL;
5979 HRESULT hr = E_FAIL;
5980 unsigned int i, j;
5981 UINT32 length;
5983 *handler = NULL;
5985 /* MIME type */
5986 if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
5988 IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length);
5989 IMFAttributes_Release(attributes);
5992 /* Extension */
5993 url_ext = url ? wcsrchr(url, '.') : NULL;
5995 if (!url_ext && !mimeW)
5997 CoTaskMemFree(mimeW);
5998 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6001 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6003 struct local_handler *local_handler;
6005 EnterCriticalSection(&local_handlers_section);
6007 LIST_FOR_EACH_ENTRY(local_handler, &local_bytestream_handlers, struct local_handler, entry)
6009 if ((mimeW && !lstrcmpiW(mimeW, local_handler->u.bytestream.mime))
6010 || (url_ext && !lstrcmpiW(url_ext, local_handler->u.bytestream.extension)))
6012 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFByteStreamHandler,
6013 (void **)handler)))
6014 break;
6018 LeaveCriticalSection(&local_handlers_section);
6020 if (*handler)
6021 return hr;
6024 for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i)
6026 const WCHAR *namesW[2] = { mimeW, url_ext };
6027 HKEY hkey, hkey_handler;
6029 if (RegOpenKeyA(hkey_roots[i], streamhandlerspath, &hkey))
6030 continue;
6032 for (j = 0; j < ARRAY_SIZE(namesW); ++j)
6034 if (!namesW[j])
6035 continue;
6037 if (!RegOpenKeyW(hkey, namesW[j], &hkey_handler))
6039 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFByteStreamHandler, (void **)handler);
6040 RegCloseKey(hkey_handler);
6043 if (SUCCEEDED(hr))
6044 break;
6047 RegCloseKey(hkey);
6049 if (SUCCEEDED(hr))
6050 break;
6053 if (FAILED(hr))
6055 static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
6056 hr = CoCreateInstance(&CLSID_GStreamerByteStreamHandler, NULL, CLSCTX_INPROC_SERVER, &IID_IMFByteStreamHandler, (void **)handler);
6059 CoTaskMemFree(mimeW);
6060 return hr;
6063 static HRESULT resolver_create_scheme_handler(const WCHAR *scheme, DWORD flags, IMFSchemeHandler **handler)
6065 static const char schemehandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers";
6066 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6067 HRESULT hr = MF_E_UNSUPPORTED_SCHEME;
6068 unsigned int i;
6070 TRACE("%s, %#x, %p.\n", debugstr_w(scheme), flags, handler);
6072 *handler = NULL;
6074 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6076 struct local_handler *local_handler;
6078 EnterCriticalSection(&local_handlers_section);
6080 LIST_FOR_EACH_ENTRY(local_handler, &local_scheme_handlers, struct local_handler, entry)
6082 if (!lstrcmpiW(scheme, local_handler->u.scheme))
6084 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFSchemeHandler,
6085 (void **)handler)))
6086 break;
6090 LeaveCriticalSection(&local_handlers_section);
6092 if (*handler)
6093 return hr;
6096 for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
6098 HKEY hkey, hkey_handler;
6100 hr = MF_E_UNSUPPORTED_SCHEME;
6102 if (RegOpenKeyA(hkey_roots[i], schemehandlerspath, &hkey))
6103 continue;
6105 if (!RegOpenKeyW(hkey, scheme, &hkey_handler))
6107 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFSchemeHandler, (void **)handler);
6108 RegCloseKey(hkey_handler);
6111 RegCloseKey(hkey);
6113 if (SUCCEEDED(hr))
6114 break;
6117 return hr;
6120 static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSchemeHandler **handler)
6122 static const WCHAR fileschemeW[] = L"file:";
6123 const WCHAR *ptr = url;
6124 unsigned int len;
6125 WCHAR *scheme;
6126 HRESULT hr;
6128 /* RFC 3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
6129 while (*ptr)
6131 WCHAR ch = towlower(*ptr);
6133 if (*ptr == '*' && ptr == url)
6135 ptr++;
6136 break;
6138 else if (!(*ptr >= '0' && *ptr <= '9') &&
6139 !(ch >= 'a' && ch <= 'z') &&
6140 *ptr != '+' && *ptr != '-' && *ptr != '.')
6142 break;
6145 ptr++;
6148 /* Schemes must end with a ':', if not found try "file:" */
6149 if (ptr == url || *ptr != ':')
6151 url = fileschemeW;
6152 ptr = fileschemeW + ARRAY_SIZE(fileschemeW) - 1;
6155 len = ptr - url;
6156 scheme = heap_alloc((len + 1) * sizeof(WCHAR));
6157 if (!scheme)
6158 return E_OUTOFMEMORY;
6160 memcpy(scheme, url, len * sizeof(WCHAR));
6161 scheme[len] = 0;
6163 hr = resolver_create_scheme_handler(scheme, flags, handler);
6164 if (FAILED(hr) && url != fileschemeW)
6165 hr = resolver_create_scheme_handler(fileschemeW, flags, handler);
6167 heap_free(scheme);
6169 return hr;
6172 static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum resolved_object_origin origin,
6173 IRtwqAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out)
6175 struct resolver_queued_result *queued_result = NULL, *iter;
6176 IUnknown *object;
6177 HRESULT hr;
6179 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
6180 return hr;
6182 EnterCriticalSection(&resolver->cs);
6184 LIST_FOR_EACH_ENTRY(iter, &resolver->pending, struct resolver_queued_result, entry)
6186 if (iter->inner_result == result || (iter->object == object && iter->origin == origin))
6188 list_remove(&iter->entry);
6189 queued_result = iter;
6190 break;
6194 LeaveCriticalSection(&resolver->cs);
6196 IUnknown_Release(object);
6198 if (queued_result)
6200 *out = queued_result->object;
6201 *obj_type = queued_result->obj_type;
6202 hr = queued_result->hr;
6203 if (queued_result->inner_result)
6204 IRtwqAsyncResult_Release(queued_result->inner_result);
6205 heap_free(queued_result);
6207 else
6208 hr = E_UNEXPECTED;
6210 return hr;
6213 static HRESULT WINAPI source_resolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj)
6215 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6217 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
6219 if (IsEqualIID(riid, &IID_IMFSourceResolver) ||
6220 IsEqualIID(riid, &IID_IUnknown))
6222 *obj = &resolver->IMFSourceResolver_iface;
6224 else
6226 *obj = NULL;
6227 FIXME("unsupported interface %s\n", debugstr_guid(riid));
6228 return E_NOINTERFACE;
6231 IUnknown_AddRef((IUnknown *)*obj);
6232 return S_OK;
6235 static ULONG WINAPI source_resolver_AddRef(IMFSourceResolver *iface)
6237 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6238 ULONG refcount = InterlockedIncrement(&resolver->refcount);
6240 TRACE("%p, refcount %d.\n", iface, refcount);
6242 return refcount;
6245 static ULONG WINAPI source_resolver_Release(IMFSourceResolver *iface)
6247 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6248 ULONG refcount = InterlockedDecrement(&resolver->refcount);
6249 struct resolver_queued_result *result, *result2;
6251 TRACE("%p, refcount %d.\n", iface, refcount);
6253 if (!refcount)
6255 LIST_FOR_EACH_ENTRY_SAFE(result, result2, &resolver->pending, struct resolver_queued_result, entry)
6257 if (result->object)
6258 IUnknown_Release(result->object);
6259 list_remove(&result->entry);
6260 heap_free(result);
6262 DeleteCriticalSection(&resolver->cs);
6263 heap_free(resolver);
6266 return refcount;
6269 static HRESULT WINAPI source_resolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6270 DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6272 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6273 IMFSchemeHandler *handler;
6274 IRtwqAsyncResult *result;
6275 RTWQASYNCRESULT *data;
6276 HRESULT hr;
6278 TRACE("%p, %s, %#x, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, obj_type, object);
6280 if (!url || !obj_type || !object)
6281 return E_POINTER;
6283 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6284 return hr;
6286 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6287 IMFSchemeHandler_Release(handler);
6288 if (FAILED(hr))
6289 return hr;
6291 data = (RTWQASYNCRESULT *)result;
6292 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6294 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, NULL, (IMFAsyncCallback *)&resolver->url_callback,
6295 (IUnknown *)result);
6296 if (FAILED(hr))
6298 IRtwqAsyncResult_Release(result);
6299 return hr;
6302 WaitForSingleObject(data->hEvent, INFINITE);
6304 hr = resolver_end_create_object(resolver, OBJECT_FROM_URL, result, obj_type, object);
6305 IRtwqAsyncResult_Release(result);
6307 return hr;
6310 static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6311 const WCHAR *url, DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6313 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6314 IMFByteStreamHandler *handler;
6315 IRtwqAsyncResult *result;
6316 RTWQASYNCRESULT *data;
6317 HRESULT hr;
6319 TRACE("%p, %p, %s, %#x, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, obj_type, object);
6321 if (!stream || !obj_type || !object)
6322 return E_POINTER;
6324 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6325 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6327 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6328 IMFByteStreamHandler_Release(handler);
6329 if (FAILED(hr))
6330 return hr;
6332 data = (RTWQASYNCRESULT *)result;
6333 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6335 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props, NULL,
6336 (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6337 if (FAILED(hr))
6339 IRtwqAsyncResult_Release(result);
6340 return hr;
6343 WaitForSingleObject(data->hEvent, INFINITE);
6345 hr = resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, result, obj_type, object);
6346 IRtwqAsyncResult_Release(result);
6348 return hr;
6351 static HRESULT WINAPI source_resolver_BeginCreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6352 DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
6354 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6355 IMFSchemeHandler *handler;
6356 IUnknown *inner_cookie = NULL;
6357 IRtwqAsyncResult *result;
6358 HRESULT hr;
6360 TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
6362 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6363 return hr;
6365 if (cancel_cookie)
6366 *cancel_cookie = NULL;
6368 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6369 IMFSchemeHandler_Release(handler);
6370 if (FAILED(hr))
6371 return hr;
6373 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, cancel_cookie ? &inner_cookie : NULL,
6374 (IMFAsyncCallback *)&resolver->url_callback, (IUnknown *)result);
6376 if (SUCCEEDED(hr) && inner_cookie)
6377 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_URL, inner_cookie, cancel_cookie);
6379 IRtwqAsyncResult_Release(result);
6381 return hr;
6384 static HRESULT WINAPI source_resolver_EndCreateObjectFromURL(IMFSourceResolver *iface, IMFAsyncResult *result,
6385 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6387 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6389 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6391 return resolver_end_create_object(resolver, OBJECT_FROM_URL, (IRtwqAsyncResult *)result, obj_type, object);
6394 static HRESULT WINAPI source_resolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6395 const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback,
6396 IUnknown *state)
6398 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6399 IMFByteStreamHandler *handler;
6400 IUnknown *inner_cookie = NULL;
6401 IRtwqAsyncResult *result;
6402 HRESULT hr;
6404 TRACE("%p, %p, %s, %#x, %p, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, cancel_cookie,
6405 callback, state);
6407 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6408 return hr;
6410 if (cancel_cookie)
6411 *cancel_cookie = NULL;
6413 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6414 IMFByteStreamHandler_Release(handler);
6415 if (FAILED(hr))
6416 return hr;
6418 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props,
6419 cancel_cookie ? &inner_cookie : NULL, (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6421 /* Cancel object wraps underlying handler cancel cookie with context necessary to call CancelObjectCreate(). */
6422 if (SUCCEEDED(hr) && inner_cookie)
6423 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_BYTESTREAM, inner_cookie, cancel_cookie);
6425 IRtwqAsyncResult_Release(result);
6427 return hr;
6430 static HRESULT WINAPI source_resolver_EndCreateObjectFromByteStream(IMFSourceResolver *iface, IMFAsyncResult *result,
6431 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6433 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6435 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6437 return resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, (IRtwqAsyncResult *)result, obj_type, object);
6440 static HRESULT WINAPI source_resolver_CancelObjectCreation(IMFSourceResolver *iface, IUnknown *cancel_cookie)
6442 struct resolver_cancel_object *object;
6443 HRESULT hr;
6445 TRACE("%p, %p.\n", iface, cancel_cookie);
6447 if (!(object = unsafe_impl_cancel_obj_from_IUnknown(cancel_cookie)))
6448 return E_UNEXPECTED;
6450 switch (object->origin)
6452 case OBJECT_FROM_BYTESTREAM:
6453 hr = IMFByteStreamHandler_CancelObjectCreation(object->u.stream_handler, object->cancel_cookie);
6454 break;
6455 case OBJECT_FROM_URL:
6456 hr = IMFSchemeHandler_CancelObjectCreation(object->u.scheme_handler, object->cancel_cookie);
6457 break;
6458 default:
6459 hr = E_UNEXPECTED;
6462 return hr;
6465 static const IMFSourceResolverVtbl mfsourceresolvervtbl =
6467 source_resolver_QueryInterface,
6468 source_resolver_AddRef,
6469 source_resolver_Release,
6470 source_resolver_CreateObjectFromURL,
6471 source_resolver_CreateObjectFromByteStream,
6472 source_resolver_BeginCreateObjectFromURL,
6473 source_resolver_EndCreateObjectFromURL,
6474 source_resolver_BeginCreateObjectFromByteStream,
6475 source_resolver_EndCreateObjectFromByteStream,
6476 source_resolver_CancelObjectCreation,
6479 /***********************************************************************
6480 * MFCreateSourceResolver (mfplat.@)
6482 HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver)
6484 struct source_resolver *object;
6486 TRACE("%p\n", resolver);
6488 if (!resolver)
6489 return E_POINTER;
6491 object = heap_alloc_zero(sizeof(*object));
6492 if (!object)
6493 return E_OUTOFMEMORY;
6495 object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl;
6496 object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl;
6497 object->url_callback.lpVtbl = &source_resolver_callback_url_vtbl;
6498 object->refcount = 1;
6499 list_init(&object->pending);
6500 InitializeCriticalSection(&object->cs);
6502 *resolver = &object->IMFSourceResolver_iface;
6504 return S_OK;
6507 struct media_event
6509 struct attributes attributes;
6510 IMFMediaEvent IMFMediaEvent_iface;
6512 MediaEventType type;
6513 GUID extended_type;
6514 HRESULT status;
6515 PROPVARIANT value;
6518 static inline struct media_event *impl_from_IMFMediaEvent(IMFMediaEvent *iface)
6520 return CONTAINING_RECORD(iface, struct media_event, IMFMediaEvent_iface);
6523 static HRESULT WINAPI mfmediaevent_QueryInterface(IMFMediaEvent *iface, REFIID riid, void **out)
6525 struct media_event *event = impl_from_IMFMediaEvent(iface);
6527 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
6529 if(IsEqualGUID(riid, &IID_IUnknown) ||
6530 IsEqualGUID(riid, &IID_IMFAttributes) ||
6531 IsEqualGUID(riid, &IID_IMFMediaEvent))
6533 *out = &event->IMFMediaEvent_iface;
6535 else
6537 FIXME("%s, %p.\n", debugstr_guid(riid), out);
6538 *out = NULL;
6539 return E_NOINTERFACE;
6542 IUnknown_AddRef((IUnknown*)*out);
6543 return S_OK;
6546 static ULONG WINAPI mfmediaevent_AddRef(IMFMediaEvent *iface)
6548 struct media_event *event = impl_from_IMFMediaEvent(iface);
6549 ULONG refcount = InterlockedIncrement(&event->attributes.ref);
6551 TRACE("%p, refcount %u.\n", iface, refcount);
6553 return refcount;
6556 static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface)
6558 struct media_event *event = impl_from_IMFMediaEvent(iface);
6559 ULONG refcount = InterlockedDecrement(&event->attributes.ref);
6561 TRACE("%p, refcount %u.\n", iface, refcount);
6563 if (!refcount)
6565 clear_attributes_object(&event->attributes);
6566 PropVariantClear(&event->value);
6567 heap_free(event);
6570 return refcount;
6573 static HRESULT WINAPI mfmediaevent_GetItem(IMFMediaEvent *iface, REFGUID key, PROPVARIANT *value)
6575 struct media_event *event = impl_from_IMFMediaEvent(iface);
6577 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6579 return attributes_GetItem(&event->attributes, key, value);
6582 static HRESULT WINAPI mfmediaevent_GetItemType(IMFMediaEvent *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
6584 struct media_event *event = impl_from_IMFMediaEvent(iface);
6586 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
6588 return attributes_GetItemType(&event->attributes, key, type);
6591 static HRESULT WINAPI mfmediaevent_CompareItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
6593 struct media_event *event = impl_from_IMFMediaEvent(iface);
6595 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
6597 return attributes_CompareItem(&event->attributes, key, value, result);
6600 static HRESULT WINAPI mfmediaevent_Compare(IMFMediaEvent *iface, IMFAttributes *attrs, MF_ATTRIBUTES_MATCH_TYPE type,
6601 BOOL *result)
6603 struct media_event *event = impl_from_IMFMediaEvent(iface);
6605 TRACE("%p, %p, %d, %p.\n", iface, attrs, type, result);
6607 return attributes_Compare(&event->attributes, attrs, type, result);
6610 static HRESULT WINAPI mfmediaevent_GetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 *value)
6612 struct media_event *event = impl_from_IMFMediaEvent(iface);
6614 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6616 return attributes_GetUINT32(&event->attributes, key, value);
6619 static HRESULT WINAPI mfmediaevent_GetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 *value)
6621 struct media_event *event = impl_from_IMFMediaEvent(iface);
6623 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6625 return attributes_GetUINT64(&event->attributes, key, value);
6628 static HRESULT WINAPI mfmediaevent_GetDouble(IMFMediaEvent *iface, REFGUID key, double *value)
6630 struct media_event *event = impl_from_IMFMediaEvent(iface);
6632 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6634 return attributes_GetDouble(&event->attributes, key, value);
6637 static HRESULT WINAPI mfmediaevent_GetGUID(IMFMediaEvent *iface, REFGUID key, GUID *value)
6639 struct media_event *event = impl_from_IMFMediaEvent(iface);
6641 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6643 return attributes_GetGUID(&event->attributes, key, value);
6646 static HRESULT WINAPI mfmediaevent_GetStringLength(IMFMediaEvent *iface, REFGUID key, UINT32 *length)
6648 struct media_event *event = impl_from_IMFMediaEvent(iface);
6650 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
6652 return attributes_GetStringLength(&event->attributes, key, length);
6655 static HRESULT WINAPI mfmediaevent_GetString(IMFMediaEvent *iface, REFGUID key, WCHAR *value,
6656 UINT32 size, UINT32 *length)
6658 struct media_event *event = impl_from_IMFMediaEvent(iface);
6660 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), value, size, length);
6662 return attributes_GetString(&event->attributes, key, value, size, length);
6665 static HRESULT WINAPI mfmediaevent_GetAllocatedString(IMFMediaEvent *iface, REFGUID key,
6666 WCHAR **value, UINT32 *length)
6668 struct media_event *event = impl_from_IMFMediaEvent(iface);
6670 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
6672 return attributes_GetAllocatedString(&event->attributes, key, value, length);
6675 static HRESULT WINAPI mfmediaevent_GetBlobSize(IMFMediaEvent *iface, REFGUID key, UINT32 *size)
6677 struct media_event *event = impl_from_IMFMediaEvent(iface);
6679 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
6681 return attributes_GetBlobSize(&event->attributes, key, size);
6684 static HRESULT WINAPI mfmediaevent_GetBlob(IMFMediaEvent *iface, REFGUID key, UINT8 *buf,
6685 UINT32 bufsize, UINT32 *blobsize)
6687 struct media_event *event = impl_from_IMFMediaEvent(iface);
6689 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
6691 return attributes_GetBlob(&event->attributes, key, buf, bufsize, blobsize);
6694 static HRESULT WINAPI mfmediaevent_GetAllocatedBlob(IMFMediaEvent *iface, REFGUID key, UINT8 **buf, UINT32 *size)
6696 struct media_event *event = impl_from_IMFMediaEvent(iface);
6698 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
6700 return attributes_GetAllocatedBlob(&event->attributes, key, buf, size);
6703 static HRESULT WINAPI mfmediaevent_GetUnknown(IMFMediaEvent *iface, REFGUID key, REFIID riid, void **out)
6705 struct media_event *event = impl_from_IMFMediaEvent(iface);
6707 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
6709 return attributes_GetUnknown(&event->attributes, key, riid, out);
6712 static HRESULT WINAPI mfmediaevent_SetItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value)
6714 struct media_event *event = impl_from_IMFMediaEvent(iface);
6716 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
6718 return attributes_SetItem(&event->attributes, key, value);
6721 static HRESULT WINAPI mfmediaevent_DeleteItem(IMFMediaEvent *iface, REFGUID key)
6723 struct media_event *event = impl_from_IMFMediaEvent(iface);
6725 TRACE("%p, %s.\n", iface, debugstr_attr(key));
6727 return attributes_DeleteItem(&event->attributes, key);
6730 static HRESULT WINAPI mfmediaevent_DeleteAllItems(IMFMediaEvent *iface)
6732 struct media_event *event = impl_from_IMFMediaEvent(iface);
6734 TRACE("%p.\n", iface);
6736 return attributes_DeleteAllItems(&event->attributes);
6739 static HRESULT WINAPI mfmediaevent_SetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 value)
6741 struct media_event *event = impl_from_IMFMediaEvent(iface);
6743 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
6745 return attributes_SetUINT32(&event->attributes, key, value);
6748 static HRESULT WINAPI mfmediaevent_SetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 value)
6750 struct media_event *event = impl_from_IMFMediaEvent(iface);
6752 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
6754 return attributes_SetUINT64(&event->attributes, key, value);
6757 static HRESULT WINAPI mfmediaevent_SetDouble(IMFMediaEvent *iface, REFGUID key, double value)
6759 struct media_event *event = impl_from_IMFMediaEvent(iface);
6761 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
6763 return attributes_SetDouble(&event->attributes, key, value);
6766 static HRESULT WINAPI mfmediaevent_SetGUID(IMFMediaEvent *iface, REFGUID key, REFGUID value)
6768 struct media_event *event = impl_from_IMFMediaEvent(iface);
6770 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
6772 return attributes_SetGUID(&event->attributes, key, value);
6775 static HRESULT WINAPI mfmediaevent_SetString(IMFMediaEvent *iface, REFGUID key, const WCHAR *value)
6777 struct media_event *event = impl_from_IMFMediaEvent(iface);
6779 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
6781 return attributes_SetString(&event->attributes, key, value);
6784 static HRESULT WINAPI mfmediaevent_SetBlob(IMFMediaEvent *iface, REFGUID key, const UINT8 *buf, UINT32 size)
6786 struct media_event *event = impl_from_IMFMediaEvent(iface);
6788 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
6790 return attributes_SetBlob(&event->attributes, key, buf, size);
6793 static HRESULT WINAPI mfmediaevent_SetUnknown(IMFMediaEvent *iface, REFGUID key, IUnknown *unknown)
6795 struct media_event *event = impl_from_IMFMediaEvent(iface);
6797 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
6799 return attributes_SetUnknown(&event->attributes, key, unknown);
6802 static HRESULT WINAPI mfmediaevent_LockStore(IMFMediaEvent *iface)
6804 struct media_event *event = impl_from_IMFMediaEvent(iface);
6806 TRACE("%p.\n", iface);
6808 return attributes_LockStore(&event->attributes);
6811 static HRESULT WINAPI mfmediaevent_UnlockStore(IMFMediaEvent *iface)
6813 struct media_event *event = impl_from_IMFMediaEvent(iface);
6815 TRACE("%p.\n", iface);
6817 return attributes_UnlockStore(&event->attributes);
6820 static HRESULT WINAPI mfmediaevent_GetCount(IMFMediaEvent *iface, UINT32 *count)
6822 struct media_event *event = impl_from_IMFMediaEvent(iface);
6824 TRACE("%p, %p.\n", iface, count);
6826 return attributes_GetCount(&event->attributes, count);
6829 static HRESULT WINAPI mfmediaevent_GetItemByIndex(IMFMediaEvent *iface, UINT32 index, GUID *key, PROPVARIANT *value)
6831 struct media_event *event = impl_from_IMFMediaEvent(iface);
6833 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
6835 return attributes_GetItemByIndex(&event->attributes, index, key, value);
6838 static HRESULT WINAPI mfmediaevent_CopyAllItems(IMFMediaEvent *iface, IMFAttributes *dest)
6840 struct media_event *event = impl_from_IMFMediaEvent(iface);
6842 TRACE("%p, %p.\n", iface, dest);
6844 return attributes_CopyAllItems(&event->attributes, dest);
6847 static HRESULT WINAPI mfmediaevent_GetType(IMFMediaEvent *iface, MediaEventType *type)
6849 struct media_event *event = impl_from_IMFMediaEvent(iface);
6851 TRACE("%p, %p.\n", iface, type);
6853 *type = event->type;
6855 return S_OK;
6858 static HRESULT WINAPI mfmediaevent_GetExtendedType(IMFMediaEvent *iface, GUID *extended_type)
6860 struct media_event *event = impl_from_IMFMediaEvent(iface);
6862 TRACE("%p, %p.\n", iface, extended_type);
6864 *extended_type = event->extended_type;
6866 return S_OK;
6869 static HRESULT WINAPI mfmediaevent_GetStatus(IMFMediaEvent *iface, HRESULT *status)
6871 struct media_event *event = impl_from_IMFMediaEvent(iface);
6873 TRACE("%p, %p.\n", iface, status);
6875 *status = event->status;
6877 return S_OK;
6880 static HRESULT WINAPI mfmediaevent_GetValue(IMFMediaEvent *iface, PROPVARIANT *value)
6882 struct media_event *event = impl_from_IMFMediaEvent(iface);
6884 TRACE("%p, %p.\n", iface, value);
6886 PropVariantCopy(value, &event->value);
6888 return S_OK;
6891 static const IMFMediaEventVtbl mfmediaevent_vtbl =
6893 mfmediaevent_QueryInterface,
6894 mfmediaevent_AddRef,
6895 mfmediaevent_Release,
6896 mfmediaevent_GetItem,
6897 mfmediaevent_GetItemType,
6898 mfmediaevent_CompareItem,
6899 mfmediaevent_Compare,
6900 mfmediaevent_GetUINT32,
6901 mfmediaevent_GetUINT64,
6902 mfmediaevent_GetDouble,
6903 mfmediaevent_GetGUID,
6904 mfmediaevent_GetStringLength,
6905 mfmediaevent_GetString,
6906 mfmediaevent_GetAllocatedString,
6907 mfmediaevent_GetBlobSize,
6908 mfmediaevent_GetBlob,
6909 mfmediaevent_GetAllocatedBlob,
6910 mfmediaevent_GetUnknown,
6911 mfmediaevent_SetItem,
6912 mfmediaevent_DeleteItem,
6913 mfmediaevent_DeleteAllItems,
6914 mfmediaevent_SetUINT32,
6915 mfmediaevent_SetUINT64,
6916 mfmediaevent_SetDouble,
6917 mfmediaevent_SetGUID,
6918 mfmediaevent_SetString,
6919 mfmediaevent_SetBlob,
6920 mfmediaevent_SetUnknown,
6921 mfmediaevent_LockStore,
6922 mfmediaevent_UnlockStore,
6923 mfmediaevent_GetCount,
6924 mfmediaevent_GetItemByIndex,
6925 mfmediaevent_CopyAllItems,
6926 mfmediaevent_GetType,
6927 mfmediaevent_GetExtendedType,
6928 mfmediaevent_GetStatus,
6929 mfmediaevent_GetValue,
6932 /***********************************************************************
6933 * MFCreateMediaEvent (mfplat.@)
6935 HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HRESULT status, const PROPVARIANT *value,
6936 IMFMediaEvent **event)
6938 struct media_event *object;
6939 HRESULT hr;
6941 TRACE("%s, %s, %#x, %s, %p.\n", debugstr_eventid(type), debugstr_guid(extended_type), status,
6942 debugstr_propvar(value), event);
6944 object = heap_alloc(sizeof(*object));
6945 if (!object)
6946 return E_OUTOFMEMORY;
6948 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
6950 heap_free(object);
6951 return hr;
6953 object->IMFMediaEvent_iface.lpVtbl = &mfmediaevent_vtbl;
6955 object->type = type;
6956 object->extended_type = *extended_type;
6957 object->status = status;
6959 PropVariantInit(&object->value);
6960 if (value)
6961 PropVariantCopy(&object->value, value);
6963 *event = &object->IMFMediaEvent_iface;
6965 TRACE("Created event %p.\n", *event);
6967 return S_OK;
6970 struct event_queue
6972 IMFMediaEventQueue IMFMediaEventQueue_iface;
6973 LONG refcount;
6975 CRITICAL_SECTION cs;
6976 CONDITION_VARIABLE update_event;
6977 struct list events;
6978 BOOL is_shut_down;
6979 BOOL notified;
6980 IRtwqAsyncResult *subscriber;
6983 struct queued_event
6985 struct list entry;
6986 IMFMediaEvent *event;
6989 static inline struct event_queue *impl_from_IMFMediaEventQueue(IMFMediaEventQueue *iface)
6991 return CONTAINING_RECORD(iface, struct event_queue, IMFMediaEventQueue_iface);
6994 static IMFMediaEvent *queue_pop_event(struct event_queue *queue)
6996 struct list *head = list_head(&queue->events);
6997 struct queued_event *queued_event;
6998 IMFMediaEvent *event;
7000 if (!head)
7001 return NULL;
7003 queued_event = LIST_ENTRY(head, struct queued_event, entry);
7004 event = queued_event->event;
7005 list_remove(&queued_event->entry);
7006 heap_free(queued_event);
7007 return event;
7010 static void event_queue_clear_subscriber(struct event_queue *queue)
7012 if (queue->subscriber)
7013 IRtwqAsyncResult_Release(queue->subscriber);
7014 queue->subscriber = NULL;
7017 static void event_queue_cleanup(struct event_queue *queue)
7019 IMFMediaEvent *event;
7021 while ((event = queue_pop_event(queue)))
7022 IMFMediaEvent_Release(event);
7023 event_queue_clear_subscriber(queue);
7026 static HRESULT WINAPI eventqueue_QueryInterface(IMFMediaEventQueue *iface, REFIID riid, void **out)
7028 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7030 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7032 if (IsEqualIID(riid, &IID_IMFMediaEventQueue) ||
7033 IsEqualIID(riid, &IID_IUnknown))
7035 *out = &queue->IMFMediaEventQueue_iface;
7036 IMFMediaEventQueue_AddRef(iface);
7037 return S_OK;
7040 WARN("Unsupported %s.\n", debugstr_guid(riid));
7041 *out = NULL;
7042 return E_NOINTERFACE;
7045 static ULONG WINAPI eventqueue_AddRef(IMFMediaEventQueue *iface)
7047 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7048 ULONG refcount = InterlockedIncrement(&queue->refcount);
7050 TRACE("%p, refcount %u.\n", iface, refcount);
7052 return refcount;
7055 static ULONG WINAPI eventqueue_Release(IMFMediaEventQueue *iface)
7057 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7058 ULONG refcount = InterlockedDecrement(&queue->refcount);
7060 TRACE("%p, refcount %u.\n", queue, refcount);
7062 if (!refcount)
7064 event_queue_cleanup(queue);
7065 DeleteCriticalSection(&queue->cs);
7066 heap_free(queue);
7069 return refcount;
7072 static HRESULT WINAPI eventqueue_GetEvent(IMFMediaEventQueue *iface, DWORD flags, IMFMediaEvent **event)
7074 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7075 HRESULT hr = S_OK;
7077 TRACE("%p, %p.\n", iface, event);
7079 EnterCriticalSection(&queue->cs);
7081 if (queue->is_shut_down)
7082 hr = MF_E_SHUTDOWN;
7083 else if (queue->subscriber)
7084 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7085 else
7087 if (flags & MF_EVENT_FLAG_NO_WAIT)
7089 if (!(*event = queue_pop_event(queue)))
7090 hr = MF_E_NO_EVENTS_AVAILABLE;
7092 else
7094 while (list_empty(&queue->events) && !queue->is_shut_down)
7096 SleepConditionVariableCS(&queue->update_event, &queue->cs, INFINITE);
7098 *event = queue_pop_event(queue);
7099 if (queue->is_shut_down)
7100 hr = MF_E_SHUTDOWN;
7104 LeaveCriticalSection(&queue->cs);
7106 return hr;
7109 static void queue_notify_subscriber(struct event_queue *queue)
7111 if (list_empty(&queue->events) || !queue->subscriber || queue->notified)
7112 return;
7114 queue->notified = TRUE;
7115 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, queue->subscriber);
7118 static HRESULT WINAPI eventqueue_BeginGetEvent(IMFMediaEventQueue *iface, IMFAsyncCallback *callback, IUnknown *state)
7120 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7121 RTWQASYNCRESULT *result_data;
7122 HRESULT hr;
7124 TRACE("%p, %p, %p.\n", iface, callback, state);
7126 if (!callback)
7127 return E_INVALIDARG;
7129 EnterCriticalSection(&queue->cs);
7131 if (queue->is_shut_down)
7132 hr = MF_E_SHUTDOWN;
7133 else if ((result_data = (RTWQASYNCRESULT *)queue->subscriber))
7135 if (result_data->pCallback == (IRtwqAsyncCallback *)callback)
7136 hr = IRtwqAsyncResult_GetStateNoAddRef(queue->subscriber) == state ?
7137 MF_S_MULTIPLE_BEGIN : MF_E_MULTIPLE_BEGIN;
7138 else
7139 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7141 else
7143 hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &queue->subscriber);
7144 if (SUCCEEDED(hr))
7145 queue_notify_subscriber(queue);
7148 LeaveCriticalSection(&queue->cs);
7150 return hr;
7153 static HRESULT WINAPI eventqueue_EndGetEvent(IMFMediaEventQueue *iface, IMFAsyncResult *result, IMFMediaEvent **event)
7155 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7156 HRESULT hr = E_FAIL;
7158 TRACE("%p, %p, %p.\n", iface, result, event);
7160 EnterCriticalSection(&queue->cs);
7162 if (queue->is_shut_down)
7163 hr = MF_E_SHUTDOWN;
7164 else if (queue->subscriber == (IRtwqAsyncResult *)result)
7166 *event = queue_pop_event(queue);
7167 event_queue_clear_subscriber(queue);
7168 queue->notified = FALSE;
7169 hr = *event ? S_OK : E_FAIL;
7172 LeaveCriticalSection(&queue->cs);
7174 return hr;
7177 static HRESULT eventqueue_queue_event(struct event_queue *queue, IMFMediaEvent *event)
7179 struct queued_event *queued_event;
7180 HRESULT hr = S_OK;
7182 queued_event = heap_alloc(sizeof(*queued_event));
7183 if (!queued_event)
7184 return E_OUTOFMEMORY;
7186 queued_event->event = event;
7188 EnterCriticalSection(&queue->cs);
7190 if (queue->is_shut_down)
7191 hr = MF_E_SHUTDOWN;
7192 else
7194 IMFMediaEvent_AddRef(queued_event->event);
7195 list_add_tail(&queue->events, &queued_event->entry);
7196 queue_notify_subscriber(queue);
7199 LeaveCriticalSection(&queue->cs);
7201 if (FAILED(hr))
7202 heap_free(queued_event);
7204 WakeAllConditionVariable(&queue->update_event);
7206 return hr;
7209 static HRESULT WINAPI eventqueue_QueueEvent(IMFMediaEventQueue *iface, IMFMediaEvent *event)
7211 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7213 TRACE("%p, %p.\n", iface, event);
7215 return eventqueue_queue_event(queue, event);
7218 static HRESULT WINAPI eventqueue_QueueEventParamVar(IMFMediaEventQueue *iface, MediaEventType event_type,
7219 REFGUID extended_type, HRESULT status, const PROPVARIANT *value)
7221 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7222 IMFMediaEvent *event;
7223 HRESULT hr;
7225 TRACE("%p, %s, %s, %#x, %s\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status,
7226 debugstr_propvar(value));
7228 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, value, &event)))
7229 return hr;
7231 hr = eventqueue_queue_event(queue, event);
7232 IMFMediaEvent_Release(event);
7233 return hr;
7236 static HRESULT WINAPI eventqueue_QueueEventParamUnk(IMFMediaEventQueue *iface, MediaEventType event_type,
7237 REFGUID extended_type, HRESULT status, IUnknown *unk)
7239 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7240 IMFMediaEvent *event;
7241 PROPVARIANT value;
7242 HRESULT hr;
7244 TRACE("%p, %s, %s, %#x, %p.\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status, unk);
7246 value.vt = VT_UNKNOWN;
7247 value.punkVal = unk;
7249 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, &value, &event)))
7250 return hr;
7252 hr = eventqueue_queue_event(queue, event);
7253 IMFMediaEvent_Release(event);
7254 return hr;
7257 static HRESULT WINAPI eventqueue_Shutdown(IMFMediaEventQueue *iface)
7259 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7261 TRACE("%p\n", queue);
7263 EnterCriticalSection(&queue->cs);
7265 if (!queue->is_shut_down)
7267 event_queue_cleanup(queue);
7268 queue->is_shut_down = TRUE;
7271 LeaveCriticalSection(&queue->cs);
7273 WakeAllConditionVariable(&queue->update_event);
7275 return S_OK;
7278 static const IMFMediaEventQueueVtbl eventqueuevtbl =
7280 eventqueue_QueryInterface,
7281 eventqueue_AddRef,
7282 eventqueue_Release,
7283 eventqueue_GetEvent,
7284 eventqueue_BeginGetEvent,
7285 eventqueue_EndGetEvent,
7286 eventqueue_QueueEvent,
7287 eventqueue_QueueEventParamVar,
7288 eventqueue_QueueEventParamUnk,
7289 eventqueue_Shutdown
7292 /***********************************************************************
7293 * MFCreateEventQueue (mfplat.@)
7295 HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue)
7297 struct event_queue *object;
7299 TRACE("%p\n", queue);
7301 object = heap_alloc_zero(sizeof(*object));
7302 if (!object)
7303 return E_OUTOFMEMORY;
7305 object->IMFMediaEventQueue_iface.lpVtbl = &eventqueuevtbl;
7306 object->refcount = 1;
7307 list_init(&object->events);
7308 InitializeCriticalSection(&object->cs);
7309 InitializeConditionVariable(&object->update_event);
7311 *queue = &object->IMFMediaEventQueue_iface;
7313 return S_OK;
7316 struct collection
7318 IMFCollection IMFCollection_iface;
7319 LONG refcount;
7320 IUnknown **elements;
7321 size_t capacity;
7322 size_t count;
7325 static struct collection *impl_from_IMFCollection(IMFCollection *iface)
7327 return CONTAINING_RECORD(iface, struct collection, IMFCollection_iface);
7330 static void collection_clear(struct collection *collection)
7332 size_t i;
7334 for (i = 0; i < collection->count; ++i)
7336 if (collection->elements[i])
7337 IUnknown_Release(collection->elements[i]);
7340 heap_free(collection->elements);
7341 collection->elements = NULL;
7342 collection->count = 0;
7343 collection->capacity = 0;
7346 static HRESULT WINAPI collection_QueryInterface(IMFCollection *iface, REFIID riid, void **out)
7348 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7350 if (IsEqualIID(riid, &IID_IMFCollection) ||
7351 IsEqualIID(riid, &IID_IUnknown))
7353 *out = iface;
7354 IMFCollection_AddRef(iface);
7355 return S_OK;
7358 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
7359 *out = NULL;
7360 return E_NOINTERFACE;
7363 static ULONG WINAPI collection_AddRef(IMFCollection *iface)
7365 struct collection *collection = impl_from_IMFCollection(iface);
7366 ULONG refcount = InterlockedIncrement(&collection->refcount);
7368 TRACE("%p, %d.\n", collection, refcount);
7370 return refcount;
7373 static ULONG WINAPI collection_Release(IMFCollection *iface)
7375 struct collection *collection = impl_from_IMFCollection(iface);
7376 ULONG refcount = InterlockedDecrement(&collection->refcount);
7378 TRACE("%p, %d.\n", collection, refcount);
7380 if (!refcount)
7382 collection_clear(collection);
7383 heap_free(collection->elements);
7384 heap_free(collection);
7387 return refcount;
7390 static HRESULT WINAPI collection_GetElementCount(IMFCollection *iface, DWORD *count)
7392 struct collection *collection = impl_from_IMFCollection(iface);
7394 TRACE("%p, %p.\n", iface, count);
7396 if (!count)
7397 return E_POINTER;
7399 *count = collection->count;
7401 return S_OK;
7404 static HRESULT WINAPI collection_GetElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7406 struct collection *collection = impl_from_IMFCollection(iface);
7408 TRACE("%p, %u, %p.\n", iface, idx, element);
7410 if (!element)
7411 return E_POINTER;
7413 if (idx >= collection->count)
7414 return E_INVALIDARG;
7416 *element = collection->elements[idx];
7417 if (*element)
7418 IUnknown_AddRef(*element);
7420 return *element ? S_OK : E_UNEXPECTED;
7423 static HRESULT WINAPI collection_AddElement(IMFCollection *iface, IUnknown *element)
7425 struct collection *collection = impl_from_IMFCollection(iface);
7427 TRACE("%p, %p.\n", iface, element);
7429 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, collection->count + 1,
7430 sizeof(*collection->elements)))
7431 return E_OUTOFMEMORY;
7433 collection->elements[collection->count++] = element;
7434 if (element)
7435 IUnknown_AddRef(element);
7437 return S_OK;
7440 static HRESULT WINAPI collection_RemoveElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7442 struct collection *collection = impl_from_IMFCollection(iface);
7443 size_t count;
7445 TRACE("%p, %u, %p.\n", iface, idx, element);
7447 if (!element)
7448 return E_POINTER;
7450 if (idx >= collection->count)
7451 return E_INVALIDARG;
7453 *element = collection->elements[idx];
7455 count = collection->count - idx - 1;
7456 if (count)
7457 memmove(&collection->elements[idx], &collection->elements[idx + 1], count * sizeof(*collection->elements));
7458 collection->count--;
7460 return S_OK;
7463 static HRESULT WINAPI collection_InsertElementAt(IMFCollection *iface, DWORD idx, IUnknown *element)
7465 struct collection *collection = impl_from_IMFCollection(iface);
7466 size_t i;
7468 TRACE("%p, %u, %p.\n", iface, idx, element);
7470 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, idx + 1,
7471 sizeof(*collection->elements)))
7472 return E_OUTOFMEMORY;
7474 if (idx < collection->count)
7476 memmove(&collection->elements[idx + 1], &collection->elements[idx],
7477 (collection->count - idx) * sizeof(*collection->elements));
7478 collection->count++;
7480 else
7482 for (i = collection->count; i < idx; ++i)
7483 collection->elements[i] = NULL;
7484 collection->count = idx + 1;
7487 collection->elements[idx] = element;
7488 if (collection->elements[idx])
7489 IUnknown_AddRef(collection->elements[idx]);
7491 return S_OK;
7494 static HRESULT WINAPI collection_RemoveAllElements(IMFCollection *iface)
7496 struct collection *collection = impl_from_IMFCollection(iface);
7498 TRACE("%p.\n", iface);
7500 collection_clear(collection);
7502 return S_OK;
7505 static const IMFCollectionVtbl mfcollectionvtbl =
7507 collection_QueryInterface,
7508 collection_AddRef,
7509 collection_Release,
7510 collection_GetElementCount,
7511 collection_GetElement,
7512 collection_AddElement,
7513 collection_RemoveElement,
7514 collection_InsertElementAt,
7515 collection_RemoveAllElements,
7518 /***********************************************************************
7519 * MFCreateCollection (mfplat.@)
7521 HRESULT WINAPI MFCreateCollection(IMFCollection **collection)
7523 struct collection *object;
7525 TRACE("%p\n", collection);
7527 if (!collection)
7528 return E_POINTER;
7530 object = heap_alloc_zero(sizeof(*object));
7531 if (!object)
7532 return E_OUTOFMEMORY;
7534 object->IMFCollection_iface.lpVtbl = &mfcollectionvtbl;
7535 object->refcount = 1;
7537 *collection = &object->IMFCollection_iface;
7539 return S_OK;
7542 /***********************************************************************
7543 * MFHeapAlloc (mfplat.@)
7545 void *WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type)
7547 TRACE("%lu, %#x, %s, %d, %#x.\n", size, flags, debugstr_a(file), line, type);
7548 return HeapAlloc(GetProcessHeap(), flags, size);
7551 /***********************************************************************
7552 * MFHeapFree (mfplat.@)
7554 void WINAPI MFHeapFree(void *p)
7556 TRACE("%p\n", p);
7557 HeapFree(GetProcessHeap(), 0, p);
7560 /***********************************************************************
7561 * MFCreateMFByteStreamOnStreamEx (mfplat.@)
7563 HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream **bytestream)
7565 FIXME("(%p, %p): stub\n", stream, bytestream);
7567 return E_NOTIMPL;
7570 static HRESULT WINAPI system_clock_QueryInterface(IMFClock *iface, REFIID riid, void **obj)
7572 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7574 if (IsEqualIID(riid, &IID_IMFClock) ||
7575 IsEqualIID(riid, &IID_IUnknown))
7577 *obj = iface;
7578 IMFClock_AddRef(iface);
7579 return S_OK;
7582 WARN("Unsupported %s.\n", debugstr_guid(riid));
7583 *obj = NULL;
7584 return E_NOINTERFACE;
7587 static ULONG WINAPI system_clock_AddRef(IMFClock *iface)
7589 struct system_clock *clock = impl_from_IMFClock(iface);
7590 ULONG refcount = InterlockedIncrement(&clock->refcount);
7592 TRACE("%p, refcount %u.\n", iface, refcount);
7594 return refcount;
7597 static ULONG WINAPI system_clock_Release(IMFClock *iface)
7599 struct system_clock *clock = impl_from_IMFClock(iface);
7600 ULONG refcount = InterlockedDecrement(&clock->refcount);
7602 TRACE("%p, refcount %u.\n", iface, refcount);
7604 if (!refcount)
7605 heap_free(clock);
7607 return refcount;
7610 static HRESULT WINAPI system_clock_GetClockCharacteristics(IMFClock *iface, DWORD *flags)
7612 TRACE("%p, %p.\n", iface, flags);
7614 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING |
7615 MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7617 return S_OK;
7620 static HRESULT WINAPI system_clock_GetCorrelatedTime(IMFClock *iface, DWORD reserved, LONGLONG *clock_time,
7621 MFTIME *system_time)
7623 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7625 *clock_time = *system_time = MFGetSystemTime();
7627 return S_OK;
7630 static HRESULT WINAPI system_clock_GetContinuityKey(IMFClock *iface, DWORD *key)
7632 TRACE("%p, %p.\n", iface, key);
7634 *key = 0;
7636 return S_OK;
7639 static HRESULT WINAPI system_clock_GetState(IMFClock *iface, DWORD reserved, MFCLOCK_STATE *state)
7641 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7643 *state = MFCLOCK_STATE_RUNNING;
7645 return S_OK;
7648 static HRESULT WINAPI system_clock_GetProperties(IMFClock *iface, MFCLOCK_PROPERTIES *props)
7650 TRACE("%p, %p.\n", iface, props);
7652 if (!props)
7653 return E_POINTER;
7655 memset(props, 0, sizeof(*props));
7656 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7657 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7658 props->dwClockJitter = 1;
7660 return S_OK;
7663 static const IMFClockVtbl system_clock_vtbl =
7665 system_clock_QueryInterface,
7666 system_clock_AddRef,
7667 system_clock_Release,
7668 system_clock_GetClockCharacteristics,
7669 system_clock_GetCorrelatedTime,
7670 system_clock_GetContinuityKey,
7671 system_clock_GetState,
7672 system_clock_GetProperties,
7675 static HRESULT create_system_clock(IMFClock **clock)
7677 struct system_clock *object;
7679 if (!(object = heap_alloc(sizeof(*object))))
7680 return E_OUTOFMEMORY;
7682 object->IMFClock_iface.lpVtbl = &system_clock_vtbl;
7683 object->refcount = 1;
7685 *clock = &object->IMFClock_iface;
7687 return S_OK;
7690 static HRESULT WINAPI system_time_source_QueryInterface(IMFPresentationTimeSource *iface, REFIID riid, void **obj)
7692 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7694 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7696 if (IsEqualIID(riid, &IID_IMFPresentationTimeSource) ||
7697 IsEqualIID(riid, &IID_IUnknown))
7699 *obj = &source->IMFPresentationTimeSource_iface;
7701 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
7703 *obj = &source->IMFClockStateSink_iface;
7705 else
7707 WARN("Unsupported %s.\n", debugstr_guid(riid));
7708 *obj = NULL;
7709 return E_NOINTERFACE;
7712 IUnknown_AddRef((IUnknown *)*obj);
7713 return S_OK;
7716 static ULONG WINAPI system_time_source_AddRef(IMFPresentationTimeSource *iface)
7718 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7719 ULONG refcount = InterlockedIncrement(&source->refcount);
7721 TRACE("%p, refcount %u.\n", iface, refcount);
7723 return refcount;
7726 static ULONG WINAPI system_time_source_Release(IMFPresentationTimeSource *iface)
7728 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7729 ULONG refcount = InterlockedDecrement(&source->refcount);
7731 TRACE("%p, refcount %u.\n", iface, refcount);
7733 if (!refcount)
7735 if (source->clock)
7736 IMFClock_Release(source->clock);
7737 DeleteCriticalSection(&source->cs);
7738 heap_free(source);
7741 return refcount;
7744 static HRESULT WINAPI system_time_source_GetClockCharacteristics(IMFPresentationTimeSource *iface, DWORD *flags)
7746 TRACE("%p, %p.\n", iface, flags);
7748 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7750 return S_OK;
7753 static HRESULT WINAPI system_time_source_GetCorrelatedTime(IMFPresentationTimeSource *iface, DWORD reserved,
7754 LONGLONG *clock_time, MFTIME *system_time)
7756 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7757 HRESULT hr;
7759 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7761 EnterCriticalSection(&source->cs);
7762 if (SUCCEEDED(hr = IMFClock_GetCorrelatedTime(source->clock, 0, clock_time, system_time)))
7764 if (source->state == MFCLOCK_STATE_RUNNING)
7766 system_time_source_apply_rate(source, clock_time);
7767 *clock_time += source->start_offset;
7769 else
7770 *clock_time = source->start_offset;
7772 LeaveCriticalSection(&source->cs);
7774 return hr;
7777 static HRESULT WINAPI system_time_source_GetContinuityKey(IMFPresentationTimeSource *iface, DWORD *key)
7779 TRACE("%p, %p.\n", iface, key);
7781 *key = 0;
7783 return S_OK;
7786 static HRESULT WINAPI system_time_source_GetState(IMFPresentationTimeSource *iface, DWORD reserved,
7787 MFCLOCK_STATE *state)
7789 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7791 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7793 EnterCriticalSection(&source->cs);
7794 *state = source->state;
7795 LeaveCriticalSection(&source->cs);
7797 return S_OK;
7800 static HRESULT WINAPI system_time_source_GetProperties(IMFPresentationTimeSource *iface, MFCLOCK_PROPERTIES *props)
7802 TRACE("%p, %p.\n", iface, props);
7804 if (!props)
7805 return E_POINTER;
7807 memset(props, 0, sizeof(*props));
7808 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7809 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7810 props->dwClockJitter = 1;
7812 return S_OK;
7815 static HRESULT WINAPI system_time_source_GetUnderlyingClock(IMFPresentationTimeSource *iface, IMFClock **clock)
7817 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7819 TRACE("%p, %p.\n", iface, clock);
7821 *clock = source->clock;
7822 IMFClock_AddRef(*clock);
7824 return S_OK;
7827 static const IMFPresentationTimeSourceVtbl systemtimesourcevtbl =
7829 system_time_source_QueryInterface,
7830 system_time_source_AddRef,
7831 system_time_source_Release,
7832 system_time_source_GetClockCharacteristics,
7833 system_time_source_GetCorrelatedTime,
7834 system_time_source_GetContinuityKey,
7835 system_time_source_GetState,
7836 system_time_source_GetProperties,
7837 system_time_source_GetUnderlyingClock,
7840 static HRESULT WINAPI system_time_source_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **out)
7842 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7843 return IMFPresentationTimeSource_QueryInterface(&source->IMFPresentationTimeSource_iface, riid, out);
7846 static ULONG WINAPI system_time_source_sink_AddRef(IMFClockStateSink *iface)
7848 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7849 return IMFPresentationTimeSource_AddRef(&source->IMFPresentationTimeSource_iface);
7852 static ULONG WINAPI system_time_source_sink_Release(IMFClockStateSink *iface)
7854 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7855 return IMFPresentationTimeSource_Release(&source->IMFPresentationTimeSource_iface);
7858 enum clock_command
7860 CLOCK_CMD_START = 0,
7861 CLOCK_CMD_STOP,
7862 CLOCK_CMD_PAUSE,
7863 CLOCK_CMD_RESTART,
7864 CLOCK_CMD_MAX,
7867 static HRESULT system_time_source_change_state(struct system_time_source *source, enum clock_command command)
7869 static const BYTE state_change_is_allowed[MFCLOCK_STATE_PAUSED+1][CLOCK_CMD_MAX] =
7870 { /* S S* P R */
7871 /* INVALID */ { 1, 0, 1, 0 },
7872 /* RUNNING */ { 1, 1, 1, 0 },
7873 /* STOPPED */ { 1, 1, 0, 0 },
7874 /* PAUSED */ { 1, 1, 0, 1 },
7876 static const MFCLOCK_STATE states[CLOCK_CMD_MAX] =
7878 /* CLOCK_CMD_START */ MFCLOCK_STATE_RUNNING,
7879 /* CLOCK_CMD_STOP */ MFCLOCK_STATE_STOPPED,
7880 /* CLOCK_CMD_PAUSE */ MFCLOCK_STATE_PAUSED,
7881 /* CLOCK_CMD_RESTART */ MFCLOCK_STATE_RUNNING,
7884 /* Special case that go against usual state change vs return value behavior. */
7885 if (source->state == MFCLOCK_STATE_INVALID && command == CLOCK_CMD_STOP)
7886 return S_OK;
7888 if (!state_change_is_allowed[source->state][command])
7889 return MF_E_INVALIDREQUEST;
7891 source->state = states[command];
7893 return S_OK;
7896 static HRESULT WINAPI system_time_source_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time,
7897 LONGLONG start_offset)
7899 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7900 MFCLOCK_STATE state;
7901 HRESULT hr;
7903 TRACE("%p, %s, %s.\n", iface, debugstr_time(system_time), debugstr_time(start_offset));
7905 EnterCriticalSection(&source->cs);
7906 state = source->state;
7907 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_START)))
7909 system_time_source_apply_rate(source, &system_time);
7910 if (start_offset == PRESENTATION_CURRENT_POSITION)
7912 switch (state)
7914 case MFCLOCK_STATE_RUNNING:
7915 break;
7916 case MFCLOCK_STATE_PAUSED:
7917 source->start_offset -= system_time;
7918 break;
7919 default:
7920 source->start_offset = -system_time;
7921 break;
7925 else
7927 source->start_offset = -system_time + start_offset;
7930 LeaveCriticalSection(&source->cs);
7932 return hr;
7935 static HRESULT WINAPI system_time_source_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
7937 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7938 HRESULT hr;
7940 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7942 EnterCriticalSection(&source->cs);
7943 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_STOP)))
7944 source->start_offset = 0;
7945 LeaveCriticalSection(&source->cs);
7947 return hr;
7950 static HRESULT WINAPI system_time_source_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
7952 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7953 HRESULT hr;
7955 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7957 EnterCriticalSection(&source->cs);
7958 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_PAUSE)))
7960 system_time_source_apply_rate(source, &system_time);
7961 source->start_offset += system_time;
7963 LeaveCriticalSection(&source->cs);
7965 return hr;
7968 static HRESULT WINAPI system_time_source_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
7970 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7971 HRESULT hr;
7973 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7975 EnterCriticalSection(&source->cs);
7976 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_RESTART)))
7978 system_time_source_apply_rate(source, &system_time);
7979 source->start_offset -= system_time;
7981 LeaveCriticalSection(&source->cs);
7983 return hr;
7986 static HRESULT WINAPI system_time_source_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
7988 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7989 double intpart;
7991 TRACE("%p, %s, %f.\n", iface, debugstr_time(system_time), rate);
7993 if (rate == 0.0f)
7994 return MF_E_UNSUPPORTED_RATE;
7996 modf(rate, &intpart);
7998 EnterCriticalSection(&source->cs);
7999 source->rate = rate;
8000 source->i_rate = rate == intpart ? rate : 0;
8001 LeaveCriticalSection(&source->cs);
8003 return S_OK;
8006 static const IMFClockStateSinkVtbl systemtimesourcesinkvtbl =
8008 system_time_source_sink_QueryInterface,
8009 system_time_source_sink_AddRef,
8010 system_time_source_sink_Release,
8011 system_time_source_sink_OnClockStart,
8012 system_time_source_sink_OnClockStop,
8013 system_time_source_sink_OnClockPause,
8014 system_time_source_sink_OnClockRestart,
8015 system_time_source_sink_OnClockSetRate,
8018 /***********************************************************************
8019 * MFCreateSystemTimeSource (mfplat.@)
8021 HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source)
8023 struct system_time_source *object;
8024 HRESULT hr;
8026 TRACE("%p.\n", time_source);
8028 object = heap_alloc_zero(sizeof(*object));
8029 if (!object)
8030 return E_OUTOFMEMORY;
8032 object->IMFPresentationTimeSource_iface.lpVtbl = &systemtimesourcevtbl;
8033 object->IMFClockStateSink_iface.lpVtbl = &systemtimesourcesinkvtbl;
8034 object->refcount = 1;
8035 object->rate = 1.0f;
8036 object->i_rate = 1;
8037 InitializeCriticalSection(&object->cs);
8039 if (FAILED(hr = create_system_clock(&object->clock)))
8041 IMFPresentationTimeSource_Release(&object->IMFPresentationTimeSource_iface);
8042 return hr;
8045 *time_source = &object->IMFPresentationTimeSource_iface;
8047 return S_OK;
8050 struct async_create_file
8052 IRtwqAsyncCallback IRtwqAsyncCallback_iface;
8053 LONG refcount;
8054 MF_FILE_ACCESSMODE access_mode;
8055 MF_FILE_OPENMODE open_mode;
8056 MF_FILE_FLAGS flags;
8057 WCHAR *path;
8060 struct async_create_file_result
8062 struct list entry;
8063 IRtwqAsyncResult *result;
8064 IMFByteStream *stream;
8067 static struct list async_create_file_results = LIST_INIT(async_create_file_results);
8068 static CRITICAL_SECTION async_create_file_cs = { NULL, -1, 0, 0, 0, 0 };
8070 static struct async_create_file *impl_from_create_file_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
8072 return CONTAINING_RECORD(iface, struct async_create_file, IRtwqAsyncCallback_iface);
8075 static HRESULT WINAPI async_create_file_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
8077 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
8078 IsEqualIID(riid, &IID_IUnknown))
8080 *obj = iface;
8081 IRtwqAsyncCallback_AddRef(iface);
8082 return S_OK;
8085 *obj = NULL;
8086 return E_NOINTERFACE;
8089 static ULONG WINAPI async_create_file_callback_AddRef(IRtwqAsyncCallback *iface)
8091 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8092 ULONG refcount = InterlockedIncrement(&async->refcount);
8094 TRACE("%p, refcount %u.\n", iface, refcount);
8096 return refcount;
8099 static ULONG WINAPI async_create_file_callback_Release(IRtwqAsyncCallback *iface)
8101 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8102 ULONG refcount = InterlockedDecrement(&async->refcount);
8104 TRACE("%p, refcount %u.\n", iface, refcount);
8106 if (!refcount)
8108 heap_free(async->path);
8109 heap_free(async);
8112 return refcount;
8115 static HRESULT WINAPI async_create_file_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
8117 return E_NOTIMPL;
8120 static HRESULT WINAPI async_create_file_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
8122 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8123 IRtwqAsyncResult *caller;
8124 IMFByteStream *stream;
8125 HRESULT hr;
8127 caller = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
8129 hr = MFCreateFile(async->access_mode, async->open_mode, async->flags, async->path, &stream);
8130 if (SUCCEEDED(hr))
8132 struct async_create_file_result *result_item;
8134 result_item = heap_alloc(sizeof(*result_item));
8135 if (result_item)
8137 result_item->result = caller;
8138 IRtwqAsyncResult_AddRef(caller);
8139 result_item->stream = stream;
8140 IMFByteStream_AddRef(stream);
8142 EnterCriticalSection(&async_create_file_cs);
8143 list_add_tail(&async_create_file_results, &result_item->entry);
8144 LeaveCriticalSection(&async_create_file_cs);
8147 IMFByteStream_Release(stream);
8149 else
8150 IRtwqAsyncResult_SetStatus(caller, hr);
8152 RtwqInvokeCallback(caller);
8154 return S_OK;
8157 static const IRtwqAsyncCallbackVtbl async_create_file_callback_vtbl =
8159 async_create_file_callback_QueryInterface,
8160 async_create_file_callback_AddRef,
8161 async_create_file_callback_Release,
8162 async_create_file_callback_GetParameters,
8163 async_create_file_callback_Invoke,
8166 /***********************************************************************
8167 * MFBeginCreateFile (mfplat.@)
8169 HRESULT WINAPI MFBeginCreateFile(MF_FILE_ACCESSMODE access_mode, MF_FILE_OPENMODE open_mode, MF_FILE_FLAGS flags,
8170 const WCHAR *path, IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_cookie)
8172 struct async_create_file *async = NULL;
8173 IRtwqAsyncResult *caller, *item = NULL;
8174 HRESULT hr;
8176 TRACE("%#x, %#x, %#x, %s, %p, %p, %p.\n", access_mode, open_mode, flags, debugstr_w(path), callback, state,
8177 cancel_cookie);
8179 if (cancel_cookie)
8180 *cancel_cookie = NULL;
8182 if (FAILED(hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &caller)))
8183 return hr;
8185 async = heap_alloc(sizeof(*async));
8186 if (!async)
8188 hr = E_OUTOFMEMORY;
8189 goto failed;
8192 async->IRtwqAsyncCallback_iface.lpVtbl = &async_create_file_callback_vtbl;
8193 async->refcount = 1;
8194 async->access_mode = access_mode;
8195 async->open_mode = open_mode;
8196 async->flags = flags;
8197 if (FAILED(hr = heap_strdupW(path, &async->path)))
8198 goto failed;
8200 hr = RtwqCreateAsyncResult(NULL, &async->IRtwqAsyncCallback_iface, (IUnknown *)caller, &item);
8201 if (FAILED(hr))
8202 goto failed;
8204 if (cancel_cookie)
8206 *cancel_cookie = (IUnknown *)caller;
8207 IUnknown_AddRef(*cancel_cookie);
8210 hr = RtwqInvokeCallback(item);
8212 failed:
8213 if (async)
8214 IRtwqAsyncCallback_Release(&async->IRtwqAsyncCallback_iface);
8215 if (item)
8216 IRtwqAsyncResult_Release(item);
8217 if (caller)
8218 IRtwqAsyncResult_Release(caller);
8220 return hr;
8223 static HRESULT async_create_file_pull_result(IUnknown *unk, IMFByteStream **stream)
8225 struct async_create_file_result *item;
8226 HRESULT hr = MF_E_UNEXPECTED;
8227 IRtwqAsyncResult *result;
8229 *stream = NULL;
8231 if (FAILED(IUnknown_QueryInterface(unk, &IID_IRtwqAsyncResult, (void **)&result)))
8232 return hr;
8234 EnterCriticalSection(&async_create_file_cs);
8236 LIST_FOR_EACH_ENTRY(item, &async_create_file_results, struct async_create_file_result, entry)
8238 if (result == item->result)
8240 *stream = item->stream;
8241 IRtwqAsyncResult_Release(item->result);
8242 list_remove(&item->entry);
8243 heap_free(item);
8244 break;
8248 LeaveCriticalSection(&async_create_file_cs);
8250 if (*stream)
8251 hr = IRtwqAsyncResult_GetStatus(result);
8253 IRtwqAsyncResult_Release(result);
8255 return hr;
8258 /***********************************************************************
8259 * MFEndCreateFile (mfplat.@)
8261 HRESULT WINAPI MFEndCreateFile(IMFAsyncResult *result, IMFByteStream **stream)
8263 TRACE("%p, %p.\n", result, stream);
8265 return async_create_file_pull_result((IUnknown *)result, stream);
8268 /***********************************************************************
8269 * MFCancelCreateFile (mfplat.@)
8271 HRESULT WINAPI MFCancelCreateFile(IUnknown *cancel_cookie)
8273 IMFByteStream *stream = NULL;
8274 HRESULT hr;
8276 TRACE("%p.\n", cancel_cookie);
8278 hr = async_create_file_pull_result(cancel_cookie, &stream);
8280 if (stream)
8281 IMFByteStream_Release(stream);
8283 return hr;
8286 /***********************************************************************
8287 * MFRegisterLocalSchemeHandler (mfplat.@)
8289 HRESULT WINAPI MFRegisterLocalSchemeHandler(const WCHAR *scheme, IMFActivate *activate)
8291 struct local_handler *handler;
8292 HRESULT hr;
8294 TRACE("%s, %p.\n", debugstr_w(scheme), activate);
8296 if (!scheme || !activate)
8297 return E_INVALIDARG;
8299 if (!(handler = heap_alloc(sizeof(*handler))))
8300 return E_OUTOFMEMORY;
8302 if (FAILED(hr = heap_strdupW(scheme, &handler->u.scheme)))
8304 heap_free(handler);
8305 return hr;
8307 handler->activate = activate;
8308 IMFActivate_AddRef(handler->activate);
8310 EnterCriticalSection(&local_handlers_section);
8311 list_add_head(&local_scheme_handlers, &handler->entry);
8312 LeaveCriticalSection(&local_handlers_section);
8314 return S_OK;
8317 /***********************************************************************
8318 * MFRegisterLocalByteStreamHandler (mfplat.@)
8320 HRESULT WINAPI MFRegisterLocalByteStreamHandler(const WCHAR *extension, const WCHAR *mime, IMFActivate *activate)
8322 struct local_handler *handler;
8323 HRESULT hr;
8325 TRACE("%s, %s, %p.\n", debugstr_w(extension), debugstr_w(mime), activate);
8327 if ((!extension && !mime) || !activate)
8328 return E_INVALIDARG;
8330 if (!(handler = heap_alloc_zero(sizeof(*handler))))
8331 return E_OUTOFMEMORY;
8333 hr = heap_strdupW(extension, &handler->u.bytestream.extension);
8334 if (SUCCEEDED(hr))
8335 hr = heap_strdupW(mime, &handler->u.bytestream.mime);
8337 if (FAILED(hr))
8338 goto failed;
8340 EnterCriticalSection(&local_handlers_section);
8341 list_add_head(&local_bytestream_handlers, &handler->entry);
8342 LeaveCriticalSection(&local_handlers_section);
8344 return hr;
8346 failed:
8347 heap_free(handler->u.bytestream.extension);
8348 heap_free(handler->u.bytestream.mime);
8349 heap_free(handler);
8351 return hr;
8354 struct property_store
8356 IPropertyStore IPropertyStore_iface;
8357 LONG refcount;
8358 CRITICAL_SECTION cs;
8359 size_t count, capacity;
8360 struct
8362 PROPERTYKEY key;
8363 PROPVARIANT value;
8364 } *values;
8367 static struct property_store *impl_from_IPropertyStore(IPropertyStore *iface)
8369 return CONTAINING_RECORD(iface, struct property_store, IPropertyStore_iface);
8372 static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
8374 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8376 if (IsEqualIID(riid, &IID_IPropertyStore) || IsEqualIID(riid, &IID_IUnknown))
8378 *obj = iface;
8379 IPropertyStore_AddRef(iface);
8380 return S_OK;
8383 *obj = NULL;
8384 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
8385 return E_NOINTERFACE;
8388 static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
8390 struct property_store *store = impl_from_IPropertyStore(iface);
8391 ULONG refcount = InterlockedIncrement(&store->refcount);
8393 TRACE("%p, refcount %d.\n", iface, refcount);
8395 return refcount;
8398 static ULONG WINAPI property_store_Release(IPropertyStore *iface)
8400 struct property_store *store = impl_from_IPropertyStore(iface);
8401 ULONG refcount = InterlockedDecrement(&store->refcount);
8403 TRACE("%p, refcount %d.\n", iface, refcount);
8405 if (!refcount)
8407 DeleteCriticalSection(&store->cs);
8408 heap_free(store->values);
8409 heap_free(store);
8412 return refcount;
8415 static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
8417 struct property_store *store = impl_from_IPropertyStore(iface);
8419 TRACE("%p, %p.\n", iface, count);
8421 if (!count)
8422 return E_INVALIDARG;
8424 EnterCriticalSection(&store->cs);
8425 *count = store->count;
8426 LeaveCriticalSection(&store->cs);
8427 return S_OK;
8430 static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
8432 struct property_store *store = impl_from_IPropertyStore(iface);
8434 TRACE("%p, %u, %p.\n", iface, index, key);
8436 EnterCriticalSection(&store->cs);
8438 if (index >= store->count)
8440 LeaveCriticalSection(&store->cs);
8441 return E_INVALIDARG;
8444 *key = store->values[index].key;
8446 LeaveCriticalSection(&store->cs);
8447 return S_OK;
8450 static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
8452 struct property_store *store = impl_from_IPropertyStore(iface);
8453 unsigned int i;
8455 TRACE("%p, %p, %p.\n", iface, key, value);
8457 if (!value)
8458 return E_INVALIDARG;
8460 if (!key)
8461 return S_FALSE;
8463 EnterCriticalSection(&store->cs);
8465 for (i = 0; i < store->count; ++i)
8467 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8469 PropVariantCopy(value, &store->values[i].value);
8470 LeaveCriticalSection(&store->cs);
8471 return S_OK;
8475 LeaveCriticalSection(&store->cs);
8476 return S_FALSE;
8479 static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
8481 struct property_store *store = impl_from_IPropertyStore(iface);
8482 unsigned int i;
8484 TRACE("%p, %p, %p.\n", iface, key, value);
8486 EnterCriticalSection(&store->cs);
8488 for (i = 0; i < store->count; ++i)
8490 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8492 PropVariantCopy(&store->values[i].value, value);
8493 LeaveCriticalSection(&store->cs);
8494 return S_OK;
8498 if (!mf_array_reserve((void **)&store->values, &store->capacity, store->count + 1, sizeof(*store->values)))
8500 LeaveCriticalSection(&store->cs);
8501 return E_OUTOFMEMORY;
8504 store->values[store->count].key = *key;
8505 PropVariantCopy(&store->values[store->count].value, value);
8506 ++store->count;
8508 LeaveCriticalSection(&store->cs);
8509 return S_OK;
8512 static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
8514 TRACE("%p.\n", iface);
8516 return E_NOTIMPL;
8519 static const IPropertyStoreVtbl property_store_vtbl =
8521 property_store_QueryInterface,
8522 property_store_AddRef,
8523 property_store_Release,
8524 property_store_GetCount,
8525 property_store_GetAt,
8526 property_store_GetValue,
8527 property_store_SetValue,
8528 property_store_Commit,
8531 /***********************************************************************
8532 * CreatePropertyStore (mfplat.@)
8534 HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
8536 struct property_store *object;
8538 TRACE("%p.\n", store);
8540 if (!store)
8541 return E_INVALIDARG;
8543 if (!(object = heap_alloc_zero(sizeof(*object))))
8544 return E_OUTOFMEMORY;
8546 object->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
8547 object->refcount = 1;
8548 InitializeCriticalSection(&object->cs);
8550 TRACE("Created store %p.\n", object);
8551 *store = &object->IPropertyStore_iface;
8553 return S_OK;
8556 struct shared_dxgi_manager
8558 IMFDXGIDeviceManager *manager;
8559 unsigned int token;
8560 unsigned int locks;
8563 static struct shared_dxgi_manager shared_dm;
8564 static CRITICAL_SECTION shared_dm_cs = { NULL, -1, 0, 0, 0, 0 };
8566 enum dxgi_device_handle_flags
8568 DXGI_DEVICE_HANDLE_FLAG_OPEN = 0x1,
8569 DXGI_DEVICE_HANDLE_FLAG_INVALID = 0x2,
8570 DXGI_DEVICE_HANDLE_FLAG_LOCKED = 0x4,
8573 struct dxgi_device_manager
8575 IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
8576 LONG refcount;
8577 UINT token;
8578 IDXGIDevice *device;
8580 unsigned int *handles;
8581 size_t count;
8582 size_t capacity;
8584 unsigned int locks;
8585 unsigned int locking_tid;
8587 CRITICAL_SECTION cs;
8588 CONDITION_VARIABLE lock;
8591 static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
8593 return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface);
8596 static HRESULT dxgi_device_manager_get_handle_index(struct dxgi_device_manager *manager, HANDLE hdevice, size_t *idx)
8598 if (!hdevice || hdevice > ULongToHandle(manager->count))
8599 return E_HANDLE;
8600 *idx = (ULONG_PTR)hdevice - 1;
8601 return S_OK;
8604 static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj)
8606 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8608 if (IsEqualIID(riid, &IID_IMFDXGIDeviceManager) ||
8609 IsEqualGUID(riid, &IID_IUnknown))
8611 *obj = iface;
8612 IMFDXGIDeviceManager_AddRef(iface);
8613 return S_OK;
8616 WARN("Unsupported %s.\n", debugstr_guid(riid));
8617 *obj = NULL;
8618 return E_NOINTERFACE;
8621 static ULONG WINAPI dxgi_device_manager_AddRef(IMFDXGIDeviceManager *iface)
8623 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8624 ULONG refcount = InterlockedIncrement(&manager->refcount);
8626 TRACE("%p, refcount %u.\n", iface, refcount);
8628 return refcount;
8631 static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
8633 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8634 ULONG refcount = InterlockedDecrement(&manager->refcount);
8636 TRACE("%p, refcount %u.\n", iface, refcount);
8638 if (!refcount)
8640 if (manager->device)
8641 IDXGIDevice_Release(manager->device);
8642 DeleteCriticalSection(&manager->cs);
8643 heap_free(manager->handles);
8644 heap_free(manager);
8647 return refcount;
8650 static void dxgi_device_manager_lock_handle(struct dxgi_device_manager *manager, size_t idx)
8652 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED)
8653 return;
8655 manager->handles[idx] |= DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8656 manager->locks++;
8659 static void dxgi_device_manager_unlock_handle(struct dxgi_device_manager *manager, size_t idx)
8661 if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED))
8662 return;
8664 manager->handles[idx] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8665 if (!--manager->locks)
8666 manager->locking_tid = 0;
8669 static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8671 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8672 HRESULT hr;
8673 size_t idx;
8675 TRACE("%p, %p.\n", iface, hdevice);
8677 EnterCriticalSection(&manager->cs);
8679 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8681 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8683 dxgi_device_manager_unlock_handle(manager, idx);
8684 manager->handles[idx] = 0;
8685 if (idx == manager->count - 1)
8686 manager->count--;
8688 else
8689 hr = E_HANDLE;
8692 LeaveCriticalSection(&manager->cs);
8694 WakeAllConditionVariable(&manager->lock);
8696 return hr;
8699 static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8700 REFIID riid, void **service)
8702 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8703 HRESULT hr;
8704 size_t idx;
8706 TRACE("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), service);
8708 EnterCriticalSection(&manager->cs);
8710 if (!manager->device)
8711 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8712 else if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8714 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8715 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8716 else if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8717 hr = IDXGIDevice_QueryInterface(manager->device, riid, service);
8718 else
8719 hr = E_HANDLE;
8722 LeaveCriticalSection(&manager->cs);
8724 return hr;
8727 static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8728 REFIID riid, void **obj, BOOL block)
8730 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8731 HRESULT hr;
8732 size_t idx;
8734 TRACE("%p, %p, %s, %p, %d.\n", iface, hdevice, wine_dbgstr_guid(riid), obj, block);
8736 EnterCriticalSection(&manager->cs);
8738 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8740 if (!manager->device)
8742 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8744 else if (manager->locking_tid == GetCurrentThreadId())
8746 if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
8747 dxgi_device_manager_lock_handle(manager, idx);
8749 else if (manager->locking_tid && !block)
8751 hr = MF_E_DXGI_VIDEO_DEVICE_LOCKED;
8753 else
8755 while (manager->locking_tid)
8757 SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE);
8760 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8762 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8763 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8764 else if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
8766 manager->locking_tid = GetCurrentThreadId();
8767 dxgi_device_manager_lock_handle(manager, idx);
8773 LeaveCriticalSection(&manager->cs);
8775 return hr;
8778 static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *hdevice)
8780 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8781 HRESULT hr = S_OK;
8782 size_t i;
8784 TRACE("%p, %p.\n", iface, hdevice);
8786 *hdevice = NULL;
8788 EnterCriticalSection(&manager->cs);
8790 if (!manager->device)
8791 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8792 else
8794 for (i = 0; i < manager->count; ++i)
8796 if (!(manager->handles[i] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
8798 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_OPEN;
8799 *hdevice = ULongToHandle(i + 1);
8800 break;
8804 if (mf_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1,
8805 sizeof(*manager->handles)))
8807 *hdevice = ULongToHandle(manager->count + 1);
8808 manager->handles[manager->count++] = DXGI_DEVICE_HANDLE_FLAG_OPEN;
8810 else
8811 hr = E_OUTOFMEMORY;
8814 LeaveCriticalSection(&manager->cs);
8816 return hr;
8819 static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
8821 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8822 IDXGIDevice *dxgi_device;
8823 size_t i;
8825 TRACE("%p, %p, %u.\n", iface, device, token);
8827 if (!device || token != manager->token)
8828 return E_INVALIDARG;
8830 if (FAILED(IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device)))
8831 return E_INVALIDARG;
8833 EnterCriticalSection(&manager->cs);
8835 if (manager->device)
8837 for (i = 0; i < manager->count; ++i)
8839 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_INVALID;
8840 manager->handles[i] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8842 manager->locking_tid = 0;
8843 manager->locks = 0;
8844 IDXGIDevice_Release(manager->device);
8846 manager->device = dxgi_device;
8848 LeaveCriticalSection(&manager->cs);
8850 WakeAllConditionVariable(&manager->lock);
8852 return S_OK;
8855 static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8857 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8858 HRESULT hr;
8859 size_t idx;
8861 TRACE("%p, %p.\n", iface, hdevice);
8863 EnterCriticalSection(&manager->cs);
8865 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8867 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8868 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8869 else if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
8870 hr = E_HANDLE;
8873 LeaveCriticalSection(&manager->cs);
8875 return hr;
8878 static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8879 BOOL savestate)
8881 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8882 HRESULT hr = E_FAIL;
8883 size_t idx;
8885 TRACE("%p, %p, %d.\n", iface, hdevice, savestate);
8887 EnterCriticalSection(&manager->cs);
8889 if (SUCCEEDED(dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8891 hr = manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED ? S_OK : E_INVALIDARG;
8892 if (SUCCEEDED(hr))
8893 dxgi_device_manager_unlock_handle(manager, idx);
8896 LeaveCriticalSection(&manager->cs);
8898 WakeAllConditionVariable(&manager->lock);
8900 return hr;
8903 static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
8905 dxgi_device_manager_QueryInterface,
8906 dxgi_device_manager_AddRef,
8907 dxgi_device_manager_Release,
8908 dxgi_device_manager_CloseDeviceHandle,
8909 dxgi_device_manager_GetVideoService,
8910 dxgi_device_manager_LockDevice,
8911 dxgi_device_manager_OpenDeviceHandle,
8912 dxgi_device_manager_ResetDevice,
8913 dxgi_device_manager_TestDevice,
8914 dxgi_device_manager_UnlockDevice,
8917 /***********************************************************************
8918 * MFCreateDXGIDeviceManager (mfplat.@)
8920 HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
8922 struct dxgi_device_manager *object;
8924 TRACE("%p, %p.\n", token, manager);
8926 if (!token || !manager)
8927 return E_POINTER;
8929 if (!(object = heap_alloc_zero(sizeof(*object))))
8930 return E_OUTOFMEMORY;
8932 object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
8933 object->refcount = 1;
8934 object->token = GetTickCount();
8935 InitializeCriticalSection(&object->cs);
8936 InitializeConditionVariable(&object->lock);
8938 TRACE("Created device manager: %p, token: %u.\n", object, object->token);
8940 *token = object->token;
8941 *manager = &object->IMFDXGIDeviceManager_iface;
8943 return S_OK;
8946 /***********************************************************************
8947 * MFLockDXGIDeviceManager (mfplat.@)
8949 HRESULT WINAPI MFLockDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
8951 HRESULT hr = S_OK;
8953 TRACE("%p, %p.\n", token, manager);
8955 EnterCriticalSection(&shared_dm_cs);
8957 if (!shared_dm.manager)
8958 hr = MFCreateDXGIDeviceManager(&shared_dm.token, &shared_dm.manager);
8960 if (SUCCEEDED(hr))
8962 *manager = shared_dm.manager;
8963 IMFDXGIDeviceManager_AddRef(*manager);
8964 shared_dm.locks++;
8966 if (token) *token = shared_dm.token;
8969 LeaveCriticalSection(&shared_dm_cs);
8971 return hr;
8974 /***********************************************************************
8975 * MFUnlockDXGIDeviceManager (mfplat.@)
8977 HRESULT WINAPI MFUnlockDXGIDeviceManager(void)
8979 TRACE("\n");
8981 EnterCriticalSection(&shared_dm_cs);
8983 if (shared_dm.manager)
8985 IMFDXGIDeviceManager_Release(shared_dm.manager);
8986 if (!--shared_dm.locks)
8988 shared_dm.manager = NULL;
8989 shared_dm.token = 0;
8993 LeaveCriticalSection(&shared_dm_cs);
8995 return S_OK;
9000 * MFllMulDiv implementation is derived from gstreamer utility functions code (gstutils.c),
9001 * released under LGPL2. Full authors list follows.
9002 * ===================================================================================
9003 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
9004 * 2000 Wim Taymans <wtay@chello.be>
9005 * 2002 Thomas Vander Stichele <thomas@apestaart.org>
9006 * 2004 Wim Taymans <wim@fluendo.com>
9007 * 2015 Jan Schmidt <jan@centricular.com>
9008 * ===================================================================================
9011 static void llmult128(ULARGE_INTEGER *c1, ULARGE_INTEGER *c0, LONGLONG val, LONGLONG num)
9013 ULARGE_INTEGER a1, b0, v, n;
9015 v.QuadPart = llabs(val);
9016 n.QuadPart = llabs(num);
9018 /* do 128 bits multiply
9019 * nh nl
9020 * * vh vl
9021 * ----------
9022 * a0 = vl * nl
9023 * a1 = vl * nh
9024 * b0 = vh * nl
9025 * b1 = + vh * nh
9026 * -------------------
9027 * c1h c1l c0h c0l
9029 * "a0" is optimized away, result is stored directly in c0. "b1" is
9030 * optimized away, result is stored directly in c1.
9032 c0->QuadPart = (ULONGLONG)v.LowPart * n.LowPart;
9033 a1.QuadPart = (ULONGLONG)v.LowPart * n.HighPart;
9034 b0.QuadPart = (ULONGLONG)v.HighPart * n.LowPart;
9036 /* add the high word of a0 to the low words of a1 and b0 using c1 as
9037 * scrach space to capture the carry. the low word of the result becomes
9038 * the final high word of c0 */
9039 c1->QuadPart = (ULONGLONG)c0->HighPart + a1.LowPart + b0.LowPart;
9040 c0->HighPart = c1->LowPart;
9042 /* add the carry from the result above (found in the high word of c1) and
9043 * the high words of a1 and b0 to b1, the result is c1. */
9044 c1->QuadPart = (ULONGLONG)v.HighPart * n.HighPart + c1->HighPart + a1.HighPart + b0.HighPart;
9047 static ULONGLONG lldiv128(ULARGE_INTEGER c1, ULARGE_INTEGER c0, LONGLONG denom)
9049 ULARGE_INTEGER q1, q0, rhat;
9050 ULARGE_INTEGER v, cmp1, cmp2;
9051 unsigned int s = 0;
9053 v.QuadPart = llabs(denom);
9055 /* 64bit numerator */
9056 if (c1.QuadPart == 0)
9057 return c0.QuadPart / v.QuadPart;
9059 /* 96bit numerator, 32bit denominator */
9060 if (v.HighPart == 0 && c1.HighPart == 0)
9062 ULONGLONG low = c0.LowPart, high = c0.HighPart + ((ULONGLONG)c1.LowPart << 32);
9063 low += (high % v.LowPart) << 32;
9064 return ((high / v.LowPart) << 32) + (low / v.LowPart);
9067 /* 128bit numerator, 32bit denominator */
9068 if (v.HighPart == 0)
9069 return UI64_MAX;
9071 /* count number of leading zeroes */
9072 BitScanReverse(&s, v.HighPart);
9073 s = 31 - s;
9075 if (s)
9077 /* normalize divisor and dividend */
9078 v.QuadPart <<= s;
9079 c1.QuadPart = (c1.QuadPart << s) | (c0.HighPart >> (32 - s));
9080 c0.QuadPart <<= s;
9083 q1.QuadPart = c1.QuadPart / v.HighPart;
9084 rhat.QuadPart = c1.QuadPart - q1.QuadPart * v.HighPart;
9086 cmp1.HighPart = rhat.LowPart;
9087 cmp1.LowPart = c0.HighPart;
9088 cmp2.QuadPart = q1.QuadPart * v.LowPart;
9090 while (q1.HighPart || cmp2.QuadPart > cmp1.QuadPart)
9092 q1.QuadPart--;
9093 rhat.QuadPart += v.HighPart;
9094 if (rhat.HighPart)
9095 break;
9096 cmp1.HighPart = rhat.LowPart;
9097 cmp2.QuadPart -= v.LowPart;
9099 c1.HighPart = c1.LowPart;
9100 c1.LowPart = c0.HighPart;
9101 c1.QuadPart -= q1.QuadPart * v.QuadPart;
9102 q0.QuadPart = c1.QuadPart / v.HighPart;
9103 rhat.QuadPart = c1.QuadPart - q0.QuadPart * v.HighPart;
9105 cmp1.HighPart = rhat.LowPart;
9106 cmp1.LowPart = c0.LowPart;
9107 cmp2.QuadPart = q0.QuadPart * v.LowPart;
9109 while (q0.HighPart || cmp2.QuadPart > cmp1.QuadPart)
9111 q0.QuadPart--;
9112 rhat.QuadPart += v.HighPart;
9113 if (rhat.HighPart)
9114 break;
9115 cmp1.HighPart = rhat.LowPart;
9116 cmp2.QuadPart -= v.LowPart;
9118 q0.HighPart += q1.LowPart;
9120 return q0.QuadPart;
9123 /***********************************************************************
9124 * MFllMulDiv (mfplat.@)
9126 LONGLONG WINAPI MFllMulDiv(LONGLONG val, LONGLONG num, LONGLONG denom, LONGLONG factor)
9128 #define LLOVERFLOW (sign ? I64_MIN : I64_MAX)
9129 unsigned int sign, factor_sign, denom_sign;
9130 ULARGE_INTEGER c1, c0;
9131 ULONGLONG ret;
9133 TRACE("%s, %s, %s, %s.\n", wine_dbgstr_longlong(val), wine_dbgstr_longlong(num),
9134 wine_dbgstr_longlong(denom), wine_dbgstr_longlong(factor));
9136 /* compute 128-bit numerator product */
9137 llmult128(&c1, &c0, val, num);
9139 sign = (val < 0) ^ (num < 0);
9140 factor_sign = factor < 0;
9141 denom_sign = denom < 0;
9143 factor = llabs(factor);
9144 if (sign == factor_sign)
9146 if (UI64_MAX - c0.QuadPart < factor)
9148 if (c1.QuadPart == UI64_MAX) return LLOVERFLOW;
9149 c1.QuadPart++;
9151 c0.QuadPart += factor;
9153 else
9155 if (c0.QuadPart >= factor)
9156 c0.QuadPart -= factor;
9157 else
9159 if (c1.QuadPart)
9160 c1.QuadPart--;
9161 else
9162 sign = !sign;
9164 c0.QuadPart = factor - c0.QuadPart;
9168 if (c1.QuadPart >= denom) return LLOVERFLOW;
9170 /* compute quotient, fits in 64 bits */
9171 ret = lldiv128(c1, c0, denom);
9172 sign ^= denom_sign;
9173 if (ret >= I64_MAX) return LLOVERFLOW;
9174 return sign ? -(LONGLONG)ret : ret;
9175 #undef LLOVERFLOW