winevulkan: Update to VK spec version 1.2.188.
[wine.git] / dlls / mfplat / main.c
blob7fd713261fcfb52423041a0b53dc90128ce95f08
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"
47 #undef INITGUID
48 #include "evr.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
52 struct local_handler
54 struct list entry;
55 union
57 WCHAR *scheme;
58 struct
60 WCHAR *extension;
61 WCHAR *mime;
62 } bytestream;
63 } u;
64 IMFActivate *activate;
67 static CRITICAL_SECTION local_handlers_section = { NULL, -1, 0, 0, 0, 0 };
69 static struct list local_scheme_handlers = LIST_INIT(local_scheme_handlers);
70 static struct list local_bytestream_handlers = LIST_INIT(local_bytestream_handlers);
72 struct mft_registration
74 struct list entry;
75 IClassFactory *factory;
76 CLSID clsid;
77 GUID category;
78 WCHAR *name;
79 DWORD flags;
80 MFT_REGISTER_TYPE_INFO *input_types;
81 UINT32 input_types_count;
82 MFT_REGISTER_TYPE_INFO *output_types;
83 UINT32 output_types_count;
84 BOOL local;
87 static CRITICAL_SECTION local_mfts_section = { NULL, -1, 0, 0, 0, 0 };
89 static struct list local_mfts = LIST_INIT(local_mfts);
91 struct transform_activate
93 struct attributes attributes;
94 IMFActivate IMFActivate_iface;
95 IClassFactory *factory;
96 IMFTransform *transform;
99 struct system_clock
101 IMFClock IMFClock_iface;
102 LONG refcount;
105 struct system_time_source
107 IMFPresentationTimeSource IMFPresentationTimeSource_iface;
108 IMFClockStateSink IMFClockStateSink_iface;
109 LONG refcount;
110 MFCLOCK_STATE state;
111 IMFClock *clock;
112 LONGLONG start_offset;
113 float rate;
114 int i_rate;
115 CRITICAL_SECTION cs;
118 static void system_time_source_apply_rate(const struct system_time_source *source, LONGLONG *value)
120 if (source->i_rate)
121 *value *= source->i_rate;
122 else
123 *value *= source->rate;
126 static struct system_time_source *impl_from_IMFPresentationTimeSource(IMFPresentationTimeSource *iface)
128 return CONTAINING_RECORD(iface, struct system_time_source, IMFPresentationTimeSource_iface);
131 static struct system_time_source *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
133 return CONTAINING_RECORD(iface, struct system_time_source, IMFClockStateSink_iface);
136 static struct system_clock *impl_from_IMFClock(IMFClock *iface)
138 return CONTAINING_RECORD(iface, struct system_clock, IMFClock_iface);
141 static struct transform_activate *impl_from_IMFActivate(IMFActivate *iface)
143 return CONTAINING_RECORD(iface, struct transform_activate, IMFActivate_iface);
146 static HRESULT WINAPI transform_activate_QueryInterface(IMFActivate *iface, REFIID riid, void **out)
148 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
150 if (IsEqualIID(riid, &IID_IMFActivate) ||
151 IsEqualIID(riid, &IID_IMFAttributes) ||
152 IsEqualIID(riid, &IID_IUnknown))
154 *out = iface;
155 IMFActivate_AddRef(iface);
156 return S_OK;
159 WARN("Unsupported %s.\n", debugstr_guid(riid));
160 *out = NULL;
161 return E_NOINTERFACE;
164 static ULONG WINAPI transform_activate_AddRef(IMFActivate *iface)
166 struct transform_activate *activate = impl_from_IMFActivate(iface);
167 ULONG refcount = InterlockedIncrement(&activate->attributes.ref);
169 TRACE("%p, refcount %u.\n", iface, refcount);
171 return refcount;
174 static ULONG WINAPI transform_activate_Release(IMFActivate *iface)
176 struct transform_activate *activate = impl_from_IMFActivate(iface);
177 ULONG refcount = InterlockedDecrement(&activate->attributes.ref);
179 TRACE("%p, refcount %u.\n", iface, refcount);
181 if (!refcount)
183 clear_attributes_object(&activate->attributes);
184 if (activate->factory)
185 IClassFactory_Release(activate->factory);
186 if (activate->transform)
187 IMFTransform_Release(activate->transform);
188 free(activate);
191 return refcount;
194 static HRESULT WINAPI transform_activate_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value)
196 struct transform_activate *activate = impl_from_IMFActivate(iface);
198 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
200 return attributes_GetItem(&activate->attributes, key, value);
203 static HRESULT WINAPI transform_activate_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
205 struct transform_activate *activate = impl_from_IMFActivate(iface);
207 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
209 return attributes_GetItemType(&activate->attributes, key, type);
212 static HRESULT WINAPI transform_activate_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value,
213 BOOL *result)
215 struct transform_activate *activate = impl_from_IMFActivate(iface);
217 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
219 return attributes_CompareItem(&activate->attributes, key, value, result);
222 static HRESULT WINAPI transform_activate_Compare(IMFActivate *iface, IMFAttributes *theirs,
223 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
225 struct transform_activate *activate = impl_from_IMFActivate(iface);
227 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
229 return attributes_Compare(&activate->attributes, theirs, match_type, ret);
232 static HRESULT WINAPI transform_activate_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value)
234 struct transform_activate *activate = impl_from_IMFActivate(iface);
236 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
238 return attributes_GetUINT32(&activate->attributes, key, value);
241 static HRESULT WINAPI transform_activate_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value)
243 struct transform_activate *activate = impl_from_IMFActivate(iface);
245 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
247 return attributes_GetUINT64(&activate->attributes, key, value);
250 static HRESULT WINAPI transform_activate_GetDouble(IMFActivate *iface, REFGUID key, double *value)
252 struct transform_activate *activate = impl_from_IMFActivate(iface);
254 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
256 return attributes_GetDouble(&activate->attributes, key, value);
259 static HRESULT WINAPI transform_activate_GetGUID(IMFActivate *iface, REFGUID key, GUID *value)
261 struct transform_activate *activate = impl_from_IMFActivate(iface);
263 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
265 return attributes_GetGUID(&activate->attributes, key, value);
268 static HRESULT WINAPI transform_activate_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length)
270 struct transform_activate *activate = impl_from_IMFActivate(iface);
272 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
274 return attributes_GetStringLength(&activate->attributes, key, length);
277 static HRESULT WINAPI transform_activate_GetString(IMFActivate *iface, REFGUID key, WCHAR *value,
278 UINT32 size, UINT32 *length)
280 struct transform_activate *activate = impl_from_IMFActivate(iface);
282 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
284 return attributes_GetString(&activate->attributes, key, value, size, length);
287 static HRESULT WINAPI transform_activate_GetAllocatedString(IMFActivate *iface, REFGUID key, WCHAR **value,
288 UINT32 *length)
290 struct transform_activate *activate = impl_from_IMFActivate(iface);
292 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
294 return attributes_GetAllocatedString(&activate->attributes, key, value, length);
297 static HRESULT WINAPI transform_activate_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size)
299 struct transform_activate *activate = impl_from_IMFActivate(iface);
301 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
303 return attributes_GetBlobSize(&activate->attributes, key, size);
306 static HRESULT WINAPI transform_activate_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf, UINT32 bufsize,
307 UINT32 *blobsize)
309 struct transform_activate *activate = impl_from_IMFActivate(iface);
311 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
313 return attributes_GetBlob(&activate->attributes, key, buf, bufsize, blobsize);
316 static HRESULT WINAPI transform_activate_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size)
318 struct transform_activate *activate = impl_from_IMFActivate(iface);
320 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
322 return attributes_GetAllocatedBlob(&activate->attributes, key, buf, size);
325 static HRESULT WINAPI transform_activate_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **out)
327 struct transform_activate *activate = impl_from_IMFActivate(iface);
329 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
331 return attributes_GetUnknown(&activate->attributes, key, riid, out);
334 static HRESULT WINAPI transform_activate_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value)
336 struct transform_activate *activate = impl_from_IMFActivate(iface);
338 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
340 return attributes_SetItem(&activate->attributes, key, value);
343 static HRESULT WINAPI transform_activate_DeleteItem(IMFActivate *iface, REFGUID key)
345 struct transform_activate *activate = impl_from_IMFActivate(iface);
347 TRACE("%p, %s.\n", iface, debugstr_attr(key));
349 return attributes_DeleteItem(&activate->attributes, key);
352 static HRESULT WINAPI transform_activate_DeleteAllItems(IMFActivate *iface)
354 struct transform_activate *activate = impl_from_IMFActivate(iface);
356 TRACE("%p.\n", iface);
358 return attributes_DeleteAllItems(&activate->attributes);
361 static HRESULT WINAPI transform_activate_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value)
363 struct transform_activate *activate = impl_from_IMFActivate(iface);
365 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
367 return attributes_SetUINT32(&activate->attributes, key, value);
370 static HRESULT WINAPI transform_activate_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value)
372 struct transform_activate *activate = impl_from_IMFActivate(iface);
374 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
376 return attributes_SetUINT64(&activate->attributes, key, value);
379 static HRESULT WINAPI transform_activate_SetDouble(IMFActivate *iface, REFGUID key, double value)
381 struct transform_activate *activate = impl_from_IMFActivate(iface);
383 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
385 return attributes_SetDouble(&activate->attributes, key, value);
388 static HRESULT WINAPI transform_activate_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value)
390 struct transform_activate *activate = impl_from_IMFActivate(iface);
392 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
394 return attributes_SetGUID(&activate->attributes, key, value);
397 static HRESULT WINAPI transform_activate_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value)
399 struct transform_activate *activate = impl_from_IMFActivate(iface);
401 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
403 return attributes_SetString(&activate->attributes, key, value);
406 static HRESULT WINAPI transform_activate_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size)
408 struct transform_activate *activate = impl_from_IMFActivate(iface);
410 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
412 return attributes_SetBlob(&activate->attributes, key, buf, size);
415 static HRESULT WINAPI transform_activate_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown)
417 struct transform_activate *activate = impl_from_IMFActivate(iface);
419 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
421 return attributes_SetUnknown(&activate->attributes, key, unknown);
424 static HRESULT WINAPI transform_activate_LockStore(IMFActivate *iface)
426 struct transform_activate *activate = impl_from_IMFActivate(iface);
428 TRACE("%p.\n", iface);
430 return attributes_LockStore(&activate->attributes);
433 static HRESULT WINAPI transform_activate_UnlockStore(IMFActivate *iface)
435 struct transform_activate *activate = impl_from_IMFActivate(iface);
437 TRACE("%p.\n", iface);
439 return attributes_UnlockStore(&activate->attributes);
442 static HRESULT WINAPI transform_activate_GetCount(IMFActivate *iface, UINT32 *count)
444 struct transform_activate *activate = impl_from_IMFActivate(iface);
446 TRACE("%p, %p.\n", iface, count);
448 return attributes_GetCount(&activate->attributes, count);
451 static HRESULT WINAPI transform_activate_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key,
452 PROPVARIANT *value)
454 struct transform_activate *activate = impl_from_IMFActivate(iface);
456 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
458 return attributes_GetItemByIndex(&activate->attributes, index, key, value);
461 static HRESULT WINAPI transform_activate_CopyAllItems(IMFActivate *iface, IMFAttributes *dest)
463 struct transform_activate *activate = impl_from_IMFActivate(iface);
465 TRACE("%p, %p.\n", iface, dest);
467 return attributes_CopyAllItems(&activate->attributes, dest);
470 static HRESULT WINAPI transform_activate_ActivateObject(IMFActivate *iface, REFIID riid, void **obj)
472 struct transform_activate *activate = impl_from_IMFActivate(iface);
473 CLSID clsid;
474 HRESULT hr;
476 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
478 EnterCriticalSection(&activate->attributes.cs);
480 if (!activate->transform)
482 if (activate->factory)
484 if (FAILED(hr = IClassFactory_CreateInstance(activate->factory, NULL, &IID_IMFTransform,
485 (void **)&activate->transform)))
487 hr = MF_E_INVALIDREQUEST;
490 else
492 if (SUCCEEDED(hr = attributes_GetGUID(&activate->attributes, &MFT_TRANSFORM_CLSID_Attribute, &clsid)))
494 if (FAILED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform,
495 (void **)&activate->transform)))
497 hr = MF_E_INVALIDREQUEST;
503 if (activate->transform)
504 hr = IMFTransform_QueryInterface(activate->transform, riid, obj);
506 LeaveCriticalSection(&activate->attributes.cs);
508 return hr;
511 static HRESULT WINAPI transform_activate_ShutdownObject(IMFActivate *iface)
513 struct transform_activate *activate = impl_from_IMFActivate(iface);
515 TRACE("%p.\n", iface);
517 EnterCriticalSection(&activate->attributes.cs);
519 if (activate->transform)
521 IMFTransform_Release(activate->transform);
522 activate->transform = NULL;
525 LeaveCriticalSection(&activate->attributes.cs);
527 return S_OK;
530 static HRESULT WINAPI transform_activate_DetachObject(IMFActivate *iface)
532 TRACE("%p.\n", iface);
534 return E_NOTIMPL;
537 static const IMFActivateVtbl transform_activate_vtbl =
539 transform_activate_QueryInterface,
540 transform_activate_AddRef,
541 transform_activate_Release,
542 transform_activate_GetItem,
543 transform_activate_GetItemType,
544 transform_activate_CompareItem,
545 transform_activate_Compare,
546 transform_activate_GetUINT32,
547 transform_activate_GetUINT64,
548 transform_activate_GetDouble,
549 transform_activate_GetGUID,
550 transform_activate_GetStringLength,
551 transform_activate_GetString,
552 transform_activate_GetAllocatedString,
553 transform_activate_GetBlobSize,
554 transform_activate_GetBlob,
555 transform_activate_GetAllocatedBlob,
556 transform_activate_GetUnknown,
557 transform_activate_SetItem,
558 transform_activate_DeleteItem,
559 transform_activate_DeleteAllItems,
560 transform_activate_SetUINT32,
561 transform_activate_SetUINT64,
562 transform_activate_SetDouble,
563 transform_activate_SetGUID,
564 transform_activate_SetString,
565 transform_activate_SetBlob,
566 transform_activate_SetUnknown,
567 transform_activate_LockStore,
568 transform_activate_UnlockStore,
569 transform_activate_GetCount,
570 transform_activate_GetItemByIndex,
571 transform_activate_CopyAllItems,
572 transform_activate_ActivateObject,
573 transform_activate_ShutdownObject,
574 transform_activate_DetachObject,
577 static HRESULT create_transform_activate(IClassFactory *factory, IMFActivate **activate)
579 struct transform_activate *object;
580 HRESULT hr;
582 if (!(object = calloc(1, sizeof(*object))))
583 return E_OUTOFMEMORY;
585 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
587 free(object);
588 return hr;
591 object->IMFActivate_iface.lpVtbl = &transform_activate_vtbl;
592 object->factory = factory;
593 if (object->factory)
594 IClassFactory_AddRef(object->factory);
596 *activate = &object->IMFActivate_iface;
598 return S_OK;
601 HRESULT WINAPI MFCreateTransformActivate(IMFActivate **activate)
603 TRACE("%p.\n", activate);
605 return create_transform_activate(NULL, activate);
608 static const WCHAR transform_keyW[] = L"MediaFoundation\\Transforms";
609 static const WCHAR categories_keyW[] = L"MediaFoundation\\Transforms\\Categories";
611 static const BYTE guid_conv_table[256] =
613 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
614 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
615 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
616 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
617 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
618 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
619 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
622 static WCHAR* GUIDToString(WCHAR *str, REFGUID guid)
624 swprintf(str, 39, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
625 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1],
626 guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5],
627 guid->Data4[6], guid->Data4[7]);
629 return str;
632 static inline BOOL is_valid_hex(WCHAR c)
634 if (!(((c >= '0') && (c <= '9')) ||
635 ((c >= 'a') && (c <= 'f')) ||
636 ((c >= 'A') && (c <= 'F'))))
637 return FALSE;
638 return TRUE;
641 static BOOL GUIDFromString(LPCWSTR s, GUID *id)
643 int i;
645 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
647 id->Data1 = 0;
648 for (i = 0; i < 8; i++)
650 if (!is_valid_hex(s[i])) return FALSE;
651 id->Data1 = (id->Data1 << 4) | guid_conv_table[s[i]];
653 if (s[8]!='-') return FALSE;
655 id->Data2 = 0;
656 for (i = 9; i < 13; i++)
658 if (!is_valid_hex(s[i])) return FALSE;
659 id->Data2 = (id->Data2 << 4) | guid_conv_table[s[i]];
661 if (s[13]!='-') return FALSE;
663 id->Data3 = 0;
664 for (i = 14; i < 18; i++)
666 if (!is_valid_hex(s[i])) return FALSE;
667 id->Data3 = (id->Data3 << 4) | guid_conv_table[s[i]];
669 if (s[18]!='-') return FALSE;
671 for (i = 19; i < 36; i+=2)
673 if (i == 23)
675 if (s[i]!='-') return FALSE;
676 i++;
678 if (!is_valid_hex(s[i]) || !is_valid_hex(s[i+1])) return FALSE;
679 id->Data4[(i-19)/2] = guid_conv_table[s[i]] << 4 | guid_conv_table[s[i+1]];
682 if (!s[36]) return TRUE;
683 return FALSE;
686 static HRESULT register_transform(const CLSID *clsid, const WCHAR *name, UINT32 flags,
687 UINT32 cinput, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
688 const MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
690 HRESULT hr = S_OK;
691 HKEY hclsid = 0;
692 WCHAR buffer[64];
693 DWORD size, ret;
694 WCHAR str[250];
695 UINT8 *blob;
697 GUIDToString(buffer, clsid);
698 swprintf(str, ARRAY_SIZE(str), L"%s\\%s", transform_keyW, buffer);
700 if ((ret = RegCreateKeyW(HKEY_CLASSES_ROOT, str, &hclsid)))
701 hr = HRESULT_FROM_WIN32(ret);
703 if (SUCCEEDED(hr))
705 size = (lstrlenW(name) + 1) * sizeof(WCHAR);
706 if ((ret = RegSetValueExW(hclsid, NULL, 0, REG_SZ, (BYTE *)name, size)))
707 hr = HRESULT_FROM_WIN32(ret);
710 if (SUCCEEDED(hr) && cinput && input_types)
712 size = cinput * sizeof(MFT_REGISTER_TYPE_INFO);
713 if ((ret = RegSetValueExW(hclsid, L"InputTypes", 0, REG_BINARY, (BYTE *)input_types, size)))
714 hr = HRESULT_FROM_WIN32(ret);
717 if (SUCCEEDED(hr) && coutput && output_types)
719 size = coutput * sizeof(MFT_REGISTER_TYPE_INFO);
720 if ((ret = RegSetValueExW(hclsid, L"OutputTypes", 0, REG_BINARY, (BYTE *)output_types, size)))
721 hr = HRESULT_FROM_WIN32(ret);
724 if (SUCCEEDED(hr) && attributes)
726 if (SUCCEEDED(hr = MFGetAttributesAsBlobSize(attributes, &size)))
728 if ((blob = malloc(size)))
730 if (SUCCEEDED(hr = MFGetAttributesAsBlob(attributes, blob, size)))
732 if ((ret = RegSetValueExW(hclsid, L"Attributes", 0, REG_BINARY, blob, size)))
733 hr = HRESULT_FROM_WIN32(ret);
735 free(blob);
737 else
738 hr = E_OUTOFMEMORY;
742 if (SUCCEEDED(hr) && flags)
744 if ((ret = RegSetValueExW(hclsid, L"MFTFlags", 0, REG_DWORD, (BYTE *)&flags, sizeof(flags))))
745 hr = HRESULT_FROM_WIN32(ret);
748 RegCloseKey(hclsid);
749 return hr;
752 static HRESULT register_category(CLSID *clsid, GUID *category)
754 HKEY htmp1;
755 WCHAR guid1[64], guid2[64];
756 WCHAR str[350];
758 GUIDToString(guid1, category);
759 GUIDToString(guid2, clsid);
761 swprintf(str, ARRAY_SIZE(str), L"%s\\%s\\%s", categories_keyW, guid1, guid2);
763 if (RegCreateKeyW(HKEY_CLASSES_ROOT, str, &htmp1))
764 return E_FAIL;
766 RegCloseKey(htmp1);
767 return S_OK;
770 /***********************************************************************
771 * MFTRegister (mfplat.@)
773 HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags, UINT32 cinput,
774 MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
775 MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
777 HRESULT hr;
779 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p, %p.\n", debugstr_guid(&clsid), debugstr_guid(&category),
780 debugstr_w(name), flags, cinput, input_types, coutput, output_types, attributes);
782 hr = register_transform(&clsid, name, flags, cinput, input_types, coutput, output_types, attributes);
783 if(FAILED(hr))
784 ERR("Failed to write register transform\n");
786 if (SUCCEEDED(hr))
787 hr = register_category(&clsid, &category);
789 return hr;
792 static void release_mft_registration(struct mft_registration *mft)
794 if (mft->factory)
795 IClassFactory_Release(mft->factory);
796 free(mft->name);
797 free(mft->input_types);
798 free(mft->output_types);
799 free(mft);
802 static HRESULT mft_register_local(IClassFactory *factory, REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
803 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
804 const MFT_REGISTER_TYPE_INFO *output_types)
806 struct mft_registration *mft, *cur, *unreg_mft = NULL;
807 HRESULT hr = S_OK;
809 if (!factory && !clsid)
811 WARN("Can't register without factory or CLSID.\n");
812 return E_FAIL;
815 if (!(mft = calloc(1, sizeof(*mft))))
816 return E_OUTOFMEMORY;
818 mft->factory = factory;
819 if (mft->factory)
820 IClassFactory_AddRef(mft->factory);
821 if (clsid)
822 mft->clsid = *clsid;
823 mft->category = *category;
824 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
825 flags |= MFT_ENUM_FLAG_SYNCMFT;
826 mft->flags = flags;
827 mft->local = TRUE;
828 if (name && !(mft->name = wcsdup(name)))
830 hr = E_OUTOFMEMORY;
831 goto failed;
834 if (input_count && input_types)
836 mft->input_types_count = input_count;
837 if (!(mft->input_types = calloc(mft->input_types_count, sizeof(*input_types))))
839 hr = E_OUTOFMEMORY;
840 goto failed;
842 memcpy(mft->input_types, input_types, mft->input_types_count * sizeof(*input_types));
845 if (output_count && output_types)
847 mft->output_types_count = output_count;
848 if (!(mft->output_types = calloc(mft->output_types_count, sizeof(*output_types))))
850 hr = E_OUTOFMEMORY;
851 goto failed;
853 memcpy(mft->output_types, output_types, mft->output_types_count * sizeof(*output_types));
856 EnterCriticalSection(&local_mfts_section);
858 LIST_FOR_EACH_ENTRY(cur, &local_mfts, struct mft_registration, entry)
860 if (cur->factory == factory)
862 unreg_mft = cur;
863 list_remove(&cur->entry);
864 break;
867 list_add_tail(&local_mfts, &mft->entry);
869 LeaveCriticalSection(&local_mfts_section);
871 if (unreg_mft)
872 release_mft_registration(unreg_mft);
874 failed:
875 if (FAILED(hr))
876 release_mft_registration(mft);
878 return hr;
881 HRESULT WINAPI MFTRegisterLocal(IClassFactory *factory, REFGUID category, LPCWSTR name, UINT32 flags,
882 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
883 const MFT_REGISTER_TYPE_INFO *output_types)
885 TRACE("%p, %s, %s, %#x, %u, %p, %u, %p.\n", factory, debugstr_guid(category), debugstr_w(name), flags, input_count,
886 input_types, output_count, output_types);
888 return mft_register_local(factory, NULL, category, name, flags, input_count, input_types, output_count, output_types);
891 HRESULT WINAPI MFTRegisterLocalByCLSID(REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
892 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
893 const MFT_REGISTER_TYPE_INFO *output_types)
895 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p.\n", debugstr_guid(clsid), debugstr_guid(category), debugstr_w(name), flags,
896 input_count, input_types, output_count, output_types);
898 return mft_register_local(NULL, clsid, category, name, flags, input_count, input_types, output_count, output_types);
901 static HRESULT mft_unregister_local(IClassFactory *factory, REFCLSID clsid)
903 struct mft_registration *cur, *cur2;
904 BOOL unregister_all = !factory && !clsid;
905 struct list unreg;
907 list_init(&unreg);
909 EnterCriticalSection(&local_mfts_section);
911 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &local_mfts, struct mft_registration, entry)
913 if (!unregister_all)
915 if ((factory && cur->factory == factory) || IsEqualCLSID(&cur->clsid, clsid))
917 list_remove(&cur->entry);
918 list_add_tail(&unreg, &cur->entry);
919 break;
922 else
924 list_remove(&cur->entry);
925 list_add_tail(&unreg, &cur->entry);
929 LeaveCriticalSection(&local_mfts_section);
931 if (!unregister_all && list_empty(&unreg))
932 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
934 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &unreg, struct mft_registration, entry)
936 list_remove(&cur->entry);
937 release_mft_registration(cur);
940 return S_OK;
943 HRESULT WINAPI MFTUnregisterLocalByCLSID(CLSID clsid)
945 TRACE("%s.\n", debugstr_guid(&clsid));
947 return mft_unregister_local(NULL, &clsid);
950 HRESULT WINAPI MFTUnregisterLocal(IClassFactory *factory)
952 TRACE("%p.\n", factory);
954 return mft_unregister_local(factory, NULL);
957 MFTIME WINAPI MFGetSystemTime(void)
959 MFTIME mf;
961 GetSystemTimeAsFileTime( (FILETIME*)&mf );
963 return mf;
966 static BOOL mft_is_type_info_match(struct mft_registration *mft, const GUID *category, UINT32 flags,
967 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
968 const MFT_REGISTER_TYPE_INFO *output_type)
970 BOOL matching = TRUE;
971 DWORD model;
972 int i;
974 if (!IsEqualGUID(category, &mft->category))
975 return FALSE;
977 /* Default model is synchronous. */
978 model = mft->flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE);
979 if (!model)
980 model = MFT_ENUM_FLAG_SYNCMFT;
981 if (!(model & flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
982 return FALSE;
984 /* These flags should be explicitly enabled. */
985 if (mft->flags & ~flags & (MFT_ENUM_FLAG_FIELDOFUSE | MFT_ENUM_FLAG_TRANSCODE_ONLY))
986 return FALSE;
988 if (flags & MFT_ENUM_FLAG_SORTANDFILTER && !mft->factory && plugin_control
989 && IMFPluginControl_IsDisabled(plugin_control, MF_Plugin_Type_MFT, &mft->clsid) == S_OK)
991 return FALSE;
994 if (input_type)
996 for (i = 0, matching = FALSE; input_type && i < mft->input_types_count; ++i)
998 if (!memcmp(&mft->input_types[i], input_type, sizeof(*input_type)))
1000 matching = TRUE;
1001 break;
1006 if (output_type && matching)
1008 for (i = 0, matching = FALSE; i < mft->output_types_count; ++i)
1010 if (!memcmp(&mft->output_types[i], output_type, sizeof(*output_type)))
1012 matching = TRUE;
1013 break;
1018 return matching;
1021 static void mft_get_reg_type_info(const WCHAR *clsidW, const WCHAR *typeW, MFT_REGISTER_TYPE_INFO **type,
1022 UINT32 *count)
1024 HKEY htransform, hfilter;
1025 DWORD reg_type, size;
1027 *type = NULL;
1028 *count = 0;
1030 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1031 return;
1033 if (RegOpenKeyW(htransform, clsidW, &hfilter))
1035 RegCloseKey(htransform);
1036 return;
1039 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, NULL, &size))
1040 goto out;
1042 if (reg_type != REG_BINARY)
1043 goto out;
1045 if (!size || size % sizeof(**type))
1046 goto out;
1048 if (!(*type = malloc(size)))
1049 goto out;
1051 *count = size / sizeof(**type);
1053 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, (BYTE *)*type, &size))
1055 free(*type);
1056 *type = NULL;
1057 *count = 0;
1060 out:
1061 RegCloseKey(hfilter);
1062 RegCloseKey(htransform);
1065 static void mft_get_reg_flags(const WCHAR *clsidW, const WCHAR *nameW, DWORD *flags)
1067 DWORD ret, reg_type, size;
1068 HKEY hroot, hmft;
1070 *flags = 0;
1072 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &hroot))
1073 return;
1075 ret = RegOpenKeyW(hroot, clsidW, &hmft);
1076 RegCloseKey(hroot);
1077 if (ret)
1078 return;
1080 reg_type = 0;
1081 if (!RegQueryValueExW(hmft, nameW, NULL, &reg_type, NULL, &size) && reg_type == REG_DWORD)
1082 RegQueryValueExW(hmft, nameW, NULL, &reg_type, (BYTE *)flags, &size);
1084 RegCloseKey(hmft);
1087 static HRESULT mft_collect_machine_reg(struct list *mfts, const GUID *category, UINT32 flags,
1088 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
1089 const MFT_REGISTER_TYPE_INFO *output_type)
1091 struct mft_registration mft, *cur;
1092 HKEY hcategory, hlist;
1093 WCHAR clsidW[64];
1094 DWORD ret, size;
1095 int index = 0;
1097 if (RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1098 return E_FAIL;
1100 GUIDToString(clsidW, category);
1101 ret = RegOpenKeyW(hcategory, clsidW, &hlist);
1102 RegCloseKey(hcategory);
1103 if (ret)
1104 return E_FAIL;
1106 size = ARRAY_SIZE(clsidW);
1107 while (!RegEnumKeyExW(hlist, index, clsidW, &size, NULL, NULL, NULL, NULL))
1109 memset(&mft, 0, sizeof(mft));
1110 mft.category = *category;
1111 if (!GUIDFromString(clsidW, &mft.clsid))
1112 goto next;
1114 mft_get_reg_flags(clsidW, L"MFTFlags", &mft.flags);
1116 if (output_type)
1117 mft_get_reg_type_info(clsidW, L"OutputTypes", &mft.output_types, &mft.output_types_count);
1119 if (input_type)
1120 mft_get_reg_type_info(clsidW, L"InputTypes", &mft.input_types, &mft.input_types_count);
1122 if (!mft_is_type_info_match(&mft, category, flags, plugin_control, input_type, output_type))
1124 free(mft.input_types);
1125 free(mft.output_types);
1126 goto next;
1129 cur = malloc(sizeof(*cur));
1130 /* Reuse allocated type arrays. */
1131 *cur = mft;
1132 list_add_tail(mfts, &cur->entry);
1134 next:
1135 size = ARRAY_SIZE(clsidW);
1136 index++;
1139 return S_OK;
1142 static BOOL mft_is_preferred(IMFPluginControl *plugin_control, const CLSID *clsid)
1144 CLSID preferred;
1145 WCHAR *selector;
1146 int index = 0;
1148 while (SUCCEEDED(IMFPluginControl_GetPreferredClsidByIndex(plugin_control, MF_Plugin_Type_MFT, index++, &selector,
1149 &preferred)))
1151 CoTaskMemFree(selector);
1153 if (IsEqualGUID(&preferred, clsid))
1154 return TRUE;
1157 return FALSE;
1160 static HRESULT mft_enum(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1161 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1163 IMFPluginControl *plugin_control = NULL;
1164 struct list mfts, mfts_sorted, *result = &mfts;
1165 struct mft_registration *mft, *mft2;
1166 unsigned int obj_count;
1167 HRESULT hr;
1169 *count = 0;
1170 *activate = NULL;
1172 if (!flags)
1173 flags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER;
1175 /* Synchronous processing is default. */
1176 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
1177 flags |= MFT_ENUM_FLAG_SYNCMFT;
1179 if (FAILED(hr = MFGetPluginControl(&plugin_control)))
1181 WARN("Failed to get plugin control instance, hr %#x.\n", hr);
1182 return hr;
1185 list_init(&mfts);
1187 /* Collect from registry */
1188 mft_collect_machine_reg(&mfts, &category, flags, plugin_control, input_type, output_type);
1190 /* Collect locally registered ones. */
1191 if (flags & MFT_ENUM_FLAG_LOCALMFT)
1193 struct mft_registration *local;
1195 EnterCriticalSection(&local_mfts_section);
1197 LIST_FOR_EACH_ENTRY(local, &local_mfts, struct mft_registration, entry)
1199 if (mft_is_type_info_match(local, &category, flags, plugin_control, input_type, output_type))
1201 mft = calloc(1, sizeof(*mft));
1203 mft->clsid = local->clsid;
1204 mft->factory = local->factory;
1205 if (mft->factory)
1206 IClassFactory_AddRef(mft->factory);
1207 mft->flags = local->flags;
1208 mft->local = local->local;
1210 list_add_tail(&mfts, &mft->entry);
1214 LeaveCriticalSection(&local_mfts_section);
1217 list_init(&mfts_sorted);
1219 if (flags & MFT_ENUM_FLAG_SORTANDFILTER)
1221 /* Local registrations. */
1222 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1224 if (mft->local)
1226 list_remove(&mft->entry);
1227 list_add_tail(&mfts_sorted, &mft->entry);
1231 /* FIXME: Sort by merit value, for the ones that got it. Currently not handled. */
1233 /* Preferred transforms. */
1234 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1236 if (!mft->factory && mft_is_preferred(plugin_control, &mft->clsid))
1238 list_remove(&mft->entry);
1239 list_add_tail(&mfts_sorted, &mft->entry);
1243 /* Append the rest. */
1244 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1246 list_remove(&mft->entry);
1247 list_add_tail(&mfts_sorted, &mft->entry);
1250 result = &mfts_sorted;
1253 IMFPluginControl_Release(plugin_control);
1255 /* Create activation objects from CLSID/IClassFactory. */
1257 obj_count = list_count(result);
1259 if (obj_count)
1261 if (!(*activate = CoTaskMemAlloc(obj_count * sizeof(**activate))))
1262 hr = E_OUTOFMEMORY;
1264 obj_count = 0;
1266 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, result, struct mft_registration, entry)
1268 IMFActivate *mft_activate;
1270 if (*activate)
1272 if (SUCCEEDED(create_transform_activate(mft->factory, &mft_activate)))
1274 (*activate)[obj_count] = mft_activate;
1276 if (mft->local)
1278 IMFActivate_SetUINT32(mft_activate, &MFT_PROCESS_LOCAL_Attribute, 1);
1280 else
1282 if (mft->name)
1283 IMFActivate_SetString(mft_activate, &MFT_FRIENDLY_NAME_Attribute, mft->name);
1284 if (mft->input_types)
1285 IMFActivate_SetBlob(mft_activate, &MFT_INPUT_TYPES_Attributes, (const UINT8 *)mft->input_types,
1286 sizeof(*mft->input_types) * mft->input_types_count);
1287 if (mft->output_types)
1288 IMFActivate_SetBlob(mft_activate, &MFT_OUTPUT_TYPES_Attributes, (const UINT8 *)mft->output_types,
1289 sizeof(*mft->output_types) * mft->output_types_count);
1292 if (!mft->factory)
1293 IMFActivate_SetGUID(mft_activate, &MFT_TRANSFORM_CLSID_Attribute, &mft->clsid);
1295 IMFActivate_SetUINT32(mft_activate, &MF_TRANSFORM_FLAGS_Attribute, mft->flags);
1296 IMFActivate_SetGUID(mft_activate, &MF_TRANSFORM_CATEGORY_Attribute, &mft->category);
1298 obj_count++;
1302 list_remove(&mft->entry);
1303 release_mft_registration(mft);
1307 if (!obj_count)
1309 CoTaskMemFree(*activate);
1310 *activate = NULL;
1312 *count = obj_count;
1314 return hr;
1317 /***********************************************************************
1318 * MFTEnum (mfplat.@)
1320 HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type,
1321 MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, CLSID **clsids, UINT32 *count)
1323 struct mft_registration *mft, *mft2;
1324 unsigned int mft_count;
1325 struct list mfts;
1326 HRESULT hr;
1328 TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes,
1329 clsids, count);
1331 if (!clsids || !count)
1332 return E_INVALIDARG;
1334 *count = 0;
1336 list_init(&mfts);
1338 if (FAILED(hr = mft_collect_machine_reg(&mfts, &category, MFT_ENUM_FLAG_SYNCMFT, NULL, input_type, output_type)))
1339 return hr;
1341 mft_count = list_count(&mfts);
1343 if (mft_count)
1345 if (!(*clsids = CoTaskMemAlloc(mft_count * sizeof(**clsids))))
1346 hr = E_OUTOFMEMORY;
1348 mft_count = 0;
1349 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1351 if (*clsids)
1352 (*clsids)[mft_count++] = mft->clsid;
1353 list_remove(&mft->entry);
1354 release_mft_registration(mft);
1358 if (!mft_count)
1360 CoTaskMemFree(*clsids);
1361 *clsids = NULL;
1363 *count = mft_count;
1365 return hr;
1368 /***********************************************************************
1369 * MFTEnumEx (mfplat.@)
1371 HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1372 const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *count)
1374 TRACE("%s, %#x, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, activate, count);
1376 return mft_enum(category, flags, input_type, output_type, NULL, activate, count);
1379 /***********************************************************************
1380 * MFTEnum2 (mfplat.@)
1382 HRESULT WINAPI MFTEnum2(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1383 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1385 TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes,
1386 activate, count);
1388 if (attributes)
1389 FIXME("Ignoring attributes.\n");
1391 return mft_enum(category, flags, input_type, output_type, attributes, activate, count);
1394 /***********************************************************************
1395 * MFTUnregister (mfplat.@)
1397 HRESULT WINAPI MFTUnregister(CLSID clsid)
1399 WCHAR buffer[64], category[MAX_PATH];
1400 HKEY htransform, hcategory, htmp;
1401 DWORD size = MAX_PATH;
1402 DWORD index = 0;
1404 TRACE("(%s)\n", debugstr_guid(&clsid));
1406 GUIDToString(buffer, &clsid);
1408 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1410 RegDeleteKeyW(htransform, buffer);
1411 RegCloseKey(htransform);
1414 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1416 while (RegEnumKeyExW(hcategory, index, category, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
1418 if (!RegOpenKeyW(hcategory, category, &htmp))
1420 RegDeleteKeyW(htmp, buffer);
1421 RegCloseKey(htmp);
1423 size = MAX_PATH;
1424 index++;
1426 RegCloseKey(hcategory);
1429 return S_OK;
1432 /***********************************************************************
1433 * MFStartup (mfplat.@)
1435 HRESULT WINAPI MFStartup(ULONG version, DWORD flags)
1437 #define MF_VERSION_XP MAKELONG( MF_API_VERSION, 1 )
1438 #define MF_VERSION_WIN7 MAKELONG( MF_API_VERSION, 2 )
1440 TRACE("%#x, %#x.\n", version, flags);
1442 if (version != MF_VERSION_XP && version != MF_VERSION_WIN7)
1443 return MF_E_BAD_STARTUP_VERSION;
1445 RtwqStartup();
1447 return S_OK;
1450 /***********************************************************************
1451 * MFShutdown (mfplat.@)
1453 HRESULT WINAPI MFShutdown(void)
1455 TRACE("\n");
1457 RtwqShutdown();
1459 return S_OK;
1462 /***********************************************************************
1463 * MFCopyImage (mfplat.@)
1465 HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines)
1467 TRACE("%p, %d, %p, %d, %u, %u.\n", dest, deststride, src, srcstride, width, lines);
1469 while (lines--)
1471 memcpy(dest, src, width);
1472 dest += deststride;
1473 src += srcstride;
1476 return S_OK;
1479 struct guid_def
1481 const GUID *guid;
1482 const char *name;
1485 static int __cdecl debug_compare_guid(const void *a, const void *b)
1487 const GUID *guid = a;
1488 const struct guid_def *guid_def = b;
1489 return memcmp(guid, guid_def->guid, sizeof(*guid));
1492 const char *debugstr_attr(const GUID *guid)
1494 static const struct guid_def guid_defs[] =
1496 #define X(g) { &(g), #g }
1497 #define MF_READER_WRITER_D3D_MANAGER MF_SOURCE_READER_D3D_MANAGER
1498 X(MF_READWRITE_MMCSS_CLASS),
1499 X(MF_TOPONODE_MARKIN_HERE),
1500 X(MF_MT_H264_SUPPORTED_SYNC_FRAME_TYPES),
1501 X(MF_TOPONODE_MARKOUT_HERE),
1502 X(EVRConfig_ForceBob),
1503 X(MF_TOPONODE_DECODER),
1504 X(EVRConfig_AllowDropToBob),
1505 X(MF_TOPOLOGY_PROJECTSTART),
1506 X(EVRConfig_ForceThrottle),
1507 X(MF_VIDEO_MAX_MB_PER_SEC),
1508 X(MF_TOPOLOGY_PROJECTSTOP),
1509 X(MF_SINK_WRITER_ENCODER_CONFIG),
1510 X(EVRConfig_AllowDropToThrottle),
1511 X(MF_TOPOLOGY_NO_MARKIN_MARKOUT),
1512 X(EVRConfig_ForceHalfInterlace),
1513 X(EVRConfig_AllowDropToHalfInterlace),
1514 X(EVRConfig_ForceScaling),
1515 X(MF_MT_H264_CAPABILITIES),
1516 X(EVRConfig_AllowScaling),
1517 X(MF_SOURCE_READER_ENABLE_TRANSCODE_ONLY_TRANSFORMS),
1518 X(MFT_PREFERRED_ENCODER_PROFILE),
1519 X(EVRConfig_ForceBatching),
1520 X(EVRConfig_AllowBatching),
1521 X(MF_TOPOLOGY_DYNAMIC_CHANGE_NOT_ALLOWED),
1522 X(MF_MT_VIDEO_PROFILE),
1523 X(MF_MT_DV_AAUX_CTRL_PACK_1),
1524 X(MF_MT_ALPHA_MODE),
1525 X(MF_MT_MPEG2_TIMECODE),
1526 X(MF_PMP_SERVER_CONTEXT),
1527 X(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE),
1528 X(MF_MEDIA_ENGINE_TRACK_ID),
1529 X(MF_MT_CUSTOM_VIDEO_PRIMARIES),
1530 X(MF_MT_TIMESTAMP_CAN_BE_DTS),
1531 X(MFT_CODEC_MERIT_Attribute),
1532 X(MF_TOPOLOGY_PLAYBACK_MAX_DIMS),
1533 X(MF_XVP_DISABLE_FRC),
1534 X(MF_LOW_LATENCY),
1535 X(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS),
1536 X(MF_MT_MPEG2_FLAGS),
1537 X(MF_MEDIA_ENGINE_AUDIO_CATEGORY),
1538 X(MF_MT_PIXEL_ASPECT_RATIO),
1539 X(MF_VIDEO_PROCESSOR_ALGORITHM),
1540 X(MF_TOPOLOGY_ENABLE_XVP_FOR_PLAYBACK),
1541 X(MFT_CONNECTED_STREAM_ATTRIBUTE),
1542 X(MF_MT_REALTIME_CONTENT),
1543 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_FLAGS),
1544 X(MF_MT_WRAPPED_TYPE),
1545 X(MF_MT_DRM_FLAGS),
1546 X(MF_MT_AVG_BITRATE),
1547 X(MF_MT_DECODER_USE_MAX_RESOLUTION),
1548 X(MF_MT_MAX_LUMINANCE_LEVEL),
1549 X(MFT_CONNECTED_TO_HW_STREAM),
1550 X(MF_SA_D3D_AWARE),
1551 X(MF_XVP_SAMPLE_LOCK_TIMEOUT),
1552 X(MF_MT_MAX_KEYFRAME_SPACING),
1553 X(MFT_TRANSFORM_CLSID_Attribute),
1554 X(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING),
1555 X(MF_MT_AM_FORMAT_TYPE),
1556 X(MF_SESSION_APPROX_EVENT_OCCURRENCE_TIME),
1557 X(MF_MEDIA_ENGINE_SYNCHRONOUS_CLOSE),
1558 X(MF_MT_H264_MAX_MB_PER_SEC),
1559 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_MAX_BUFFERS),
1560 X(MF_MT_AUDIO_BLOCK_ALIGNMENT),
1561 X(MF_PD_PMPHOST_CONTEXT),
1562 X(MF_PD_APP_CONTEXT),
1563 X(MF_PD_DURATION),
1564 X(MF_PD_TOTAL_FILE_SIZE),
1565 X(MF_PD_AUDIO_ENCODING_BITRATE),
1566 X(MF_PD_VIDEO_ENCODING_BITRATE),
1567 X(MFSampleExtension_TargetGlobalLuminance),
1568 X(MF_PD_MIME_TYPE),
1569 X(MF_MT_H264_SUPPORTED_SLICE_MODES),
1570 X(MF_PD_LAST_MODIFIED_TIME),
1571 X(VIDEO_ZOOM_RECT),
1572 X(MF_PD_PLAYBACK_ELEMENT_ID),
1573 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE9),
1574 X(MF_MT_ALL_SAMPLES_INDEPENDENT),
1575 X(MF_PD_PREFERRED_LANGUAGE),
1576 X(MF_PD_PLAYBACK_BOUNDARY_TIME),
1577 X(MF_MEDIA_ENGINE_TELEMETRY_APPLICATION_ID),
1578 X(MF_ACTIVATE_MFT_LOCKED),
1579 X(MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT),
1580 X(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING),
1581 X(MF_MT_FRAME_SIZE),
1582 X(MF_MT_H264_SIMULCAST_SUPPORT),
1583 X(MF_SINK_WRITER_ASYNC_CALLBACK),
1584 X(MF_TOPOLOGY_START_TIME_ON_PRESENTATION_SWITCH),
1585 X(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER),
1586 X(MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY),
1587 X(MF_MT_FRAME_RATE_RANGE_MAX),
1588 X(MF_MT_PALETTE),
1589 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_PROVIDER_DEVICE_ID),
1590 X(MF_TOPOLOGY_STATIC_PLAYBACK_OPTIMIZATIONS),
1591 X(MF_SA_D3D11_USAGE),
1592 X(MF_MEDIA_ENGINE_NEEDKEY_CALLBACK),
1593 X(MF_MT_GEOMETRIC_APERTURE),
1594 X(MF_MT_ORIGINAL_WAVE_FORMAT_TAG),
1595 X(MF_MT_DV_AAUX_SRC_PACK_1),
1596 X(MF_MEDIA_ENGINE_STREAM_CONTAINS_ALPHA_CHANNEL),
1597 X(MF_MEDIA_ENGINE_MEDIA_PLAYER_MODE),
1598 X(MF_MEDIA_ENGINE_EXTENSION),
1599 X(MF_MT_DEFAULT_STRIDE),
1600 X(MF_MT_ARBITRARY_FORMAT),
1601 X(MF_TRANSFORM_CATEGORY_Attribute),
1602 X(MF_MT_MPEG2_HDCP),
1603 X(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
1604 X(MF_MT_SPATIAL_AUDIO_MAX_DYNAMIC_OBJECTS),
1605 X(MF_MT_DECODER_MAX_DPB_COUNT),
1606 X(MFSampleExtension_ForwardedDecodeUnits),
1607 X(MF_SA_D3D11_SHARED_WITHOUT_MUTEX),
1608 X(MF_MT_DV_AAUX_CTRL_PACK_0),
1609 X(MF_MT_YUV_MATRIX),
1610 X(MF_EVENT_SOURCE_TOPOLOGY_CANCELED),
1611 X(MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY),
1612 X(MF_MT_MAX_FRAME_AVERAGE_LUMINANCE_LEVEL),
1613 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID),
1614 X(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME),
1615 X(MF_MT_VIDEO_ROTATION),
1616 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_SYMBOLIC_LINK),
1617 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE11),
1618 X(MF_MT_USER_DATA),
1619 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID),
1620 X(MF_MT_MIN_MASTERING_LUMINANCE),
1621 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE),
1622 X(MF_SA_REQUIRED_SAMPLE_COUNT),
1623 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS),
1624 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID),
1625 X(MF_EVENT_STREAM_METADATA_SYSTEMID),
1626 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE),
1627 X(MF_MT_AUDIO_CHANNEL_MASK),
1628 X(MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN),
1629 X(MF_READWRITE_DISABLE_CONVERTERS),
1630 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE_EDGE),
1631 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS),
1632 X(MF_MT_MINIMUM_DISPLAY_APERTURE),
1633 X(MFSampleExtension_Token),
1634 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_CATEGORY),
1635 X(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
1636 X(MF_TRANSFORM_ASYNC_UNLOCK),
1637 X(MF_DISABLE_FRAME_CORRUPTION_INFO),
1638 X(MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES),
1639 X(MF_MT_VIDEO_NO_FRAME_ORDERING),
1640 X(MF_MEDIA_ENGINE_PLAYBACK_VISUAL),
1641 X(MF_MT_VIDEO_CHROMA_SITING),
1642 X(MF_AUDIO_RENDERER_ATTRIBUTE_STREAM_CATEGORY),
1643 X(MF_SA_BUFFERS_PER_SAMPLE),
1644 X(MFSampleExtension_3DVideo_SampleFormat),
1645 X(MF_MT_H264_RESOLUTION_SCALING),
1646 X(MF_MT_VIDEO_LEVEL),
1647 X(MF_SAMPLEGRABBERSINK_SAMPLE_TIME_OFFSET),
1648 X(MF_MT_SAMPLE_SIZE),
1649 X(MF_MT_AAC_PAYLOAD_TYPE),
1650 X(MF_TOPOLOGY_PLAYBACK_FRAMERATE),
1651 X(MF_SOURCE_READER_D3D11_BIND_FLAGS),
1652 X(MF_MT_AUDIO_FOLDDOWN_MATRIX),
1653 X(MF_MT_AUDIO_WMADRC_PEAKREF),
1654 X(MF_MT_AUDIO_WMADRC_PEAKTARGET),
1655 X(MF_TRANSFORM_FLAGS_Attribute),
1656 X(MF_MT_H264_SUPPORTED_RATE_CONTROL_MODES),
1657 X(MF_PD_SAMI_STYLELIST),
1658 X(MF_MT_AUDIO_WMADRC_AVGREF),
1659 X(MF_MT_AUDIO_BITS_PER_SAMPLE),
1660 X(MF_SD_LANGUAGE),
1661 X(MF_MT_AUDIO_WMADRC_AVGTARGET),
1662 X(MF_SD_PROTECTED),
1663 X(MF_SESSION_TOPOLOADER),
1664 X(MF_SESSION_GLOBAL_TIME),
1665 X(MF_SESSION_QUALITY_MANAGER),
1666 X(MF_SESSION_CONTENT_PROTECTION_MANAGER),
1667 X(MF_MT_MPEG4_SAMPLE_DESCRIPTION),
1668 X(MF_MT_MPEG_START_TIME_CODE),
1669 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1670 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1671 X(MF_READWRITE_MMCSS_PRIORITY_AUDIO),
1672 X(MF_MT_H264_MAX_CODEC_CONFIG_DELAY),
1673 X(MF_MT_DV_AAUX_SRC_PACK_0),
1674 X(MF_BYTESTREAM_ORIGIN_NAME),
1675 X(MF_BYTESTREAM_CONTENT_TYPE),
1676 X(MF_MT_DEPTH_MEASUREMENT),
1677 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WIN10),
1678 X(MF_MT_VIDEO_3D_NUM_VIEWS),
1679 X(MF_BYTESTREAM_DURATION),
1680 X(MF_SD_SAMI_LANGUAGE),
1681 X(MF_EVENT_OUTPUT_NODE),
1682 X(MF_BYTESTREAM_LAST_MODIFIED_TIME),
1683 X(MFT_ENUM_ADAPTER_LUID),
1684 X(MF_MT_FRAME_RATE_RANGE_MIN),
1685 X(MF_BYTESTREAM_IFO_FILE_URI),
1686 X(MF_EVENT_TOPOLOGY_STATUS),
1687 X(MF_BYTESTREAM_DLNA_PROFILE_ID),
1688 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ROLE),
1689 X(MF_MT_MAJOR_TYPE),
1690 X(MF_SA_REQUIRED_SAMPLE_COUNT_PROGRESSIVE),
1691 X(MF_MT_IN_BAND_PARAMETER_SET),
1692 X(MF_EVENT_SOURCE_CHARACTERISTICS),
1693 X(MF_EVENT_SOURCE_CHARACTERISTICS_OLD),
1694 X(MF_SESSION_SERVER_CONTEXT),
1695 X(MF_MT_VIDEO_3D_FIRST_IS_LEFT),
1696 X(MFT_DECODER_FINAL_VIDEO_RESOLUTION_HINT),
1697 X(MF_PD_ADAPTIVE_STREAMING),
1698 X(MF_MEDIA_ENGINE_SOURCE_RESOLVER_CONFIG_STORE),
1699 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WWA_EDGE),
1700 X(MF_MT_H264_SUPPORTED_USAGES),
1701 X(MFT_PREFERRED_OUTPUTTYPE_Attribute),
1702 X(MFSampleExtension_Timestamp),
1703 X(MF_TOPONODE_PRIMARYOUTPUT),
1704 X(MF_MT_SUBTYPE),
1705 X(MF_TRANSFORM_ASYNC),
1706 X(MF_TOPONODE_STREAMID),
1707 X(MF_MEDIA_ENGINE_PLAYBACK_HWND),
1708 X(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE),
1709 X(MF_MT_VIDEO_LIGHTING),
1710 X(MF_SD_MUTUALLY_EXCLUSIVE),
1711 X(MF_SD_STREAM_NAME),
1712 X(MF_MT_DV_VAUX_SRC_PACK),
1713 X(MF_TOPONODE_RATELESS),
1714 X(MF_EVENT_STREAM_METADATA_CONTENT_KEYIDS),
1715 X(MF_TOPONODE_DISABLE_PREROLL),
1716 X(MF_SA_D3D11_ALLOW_DYNAMIC_YUV_TEXTURE),
1717 X(MF_MT_VIDEO_3D_FORMAT),
1718 X(MF_EVENT_STREAM_METADATA_KEYDATA),
1719 X(MF_READER_WRITER_D3D_MANAGER),
1720 X(MFSampleExtension_3DVideo),
1721 X(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE),
1722 X(MF_MT_H264_USAGE),
1723 X(MF_MEDIA_ENGINE_EME_CALLBACK),
1724 X(MF_EVENT_SOURCE_FAKE_START),
1725 X(MF_EVENT_SOURCE_PROJECTSTART),
1726 X(MF_EVENT_SOURCE_ACTUAL_START),
1727 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_MANAGER),
1728 X(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
1729 X(MFT_ENUM_HARDWARE_URL_Attribute),
1730 X(MF_SOURCE_READER_ASYNC_CALLBACK),
1731 X(MF_MT_OUTPUT_BUFFER_NUM),
1732 X(MF_SA_D3D11_BINDFLAGS),
1733 X(MFT_ENCODER_SUPPORTS_CONFIG_EVENT),
1734 X(MF_MT_AUDIO_FLAC_MAX_BLOCK_SIZE),
1735 X(MFT_FRIENDLY_NAME_Attribute),
1736 X(MF_MT_FIXED_SIZE_SAMPLES),
1737 X(MFT_SUPPORT_3DVIDEO),
1738 X(MFT_SUPPORT_3DVIDEO),
1739 X(MFT_INPUT_TYPES_Attributes),
1740 X(MF_MT_H264_LAYOUT_PER_STREAM),
1741 X(MF_EVENT_SCRUBSAMPLE_TIME),
1742 X(MF_MT_SPATIAL_AUDIO_MAX_METADATA_ITEMS),
1743 X(MF_MT_MPEG2_ONE_FRAME_PER_PACKET),
1744 X(MF_MT_INTERLACE_MODE),
1745 X(MF_MEDIA_ENGINE_CALLBACK),
1746 X(MF_MT_VIDEO_RENDERER_EXTENSION_PROFILE),
1747 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_HW_SOURCE),
1748 X(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
1749 X(MF_XVP_CALLER_ALLOCATES_OUTPUT),
1750 X(MF_MT_H264_SVC_CAPABILITIES),
1751 X(MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY),
1752 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_LENGTH),
1753 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_FORMAT_ID),
1754 X(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK),
1755 X(MF_SA_D3D11_SHARED),
1756 X(MF_MT_PAN_SCAN_ENABLED),
1757 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID),
1758 X(MF_MT_DV_VAUX_CTRL_PACK),
1759 X(MFSampleExtension_ForwardedDecodeUnitType),
1760 X(MF_SA_D3D11_AWARE),
1761 X(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
1762 X(MF_SOURCE_READER_MEDIASOURCE_CHARACTERISTICS),
1763 X(MF_MT_SPATIAL_AUDIO_MIN_METADATA_ITEM_OFFSET_SPACING),
1764 X(MF_TOPONODE_TRANSFORM_OBJECTID),
1765 X(MF_DEVSOURCE_ATTRIBUTE_MEDIA_TYPE),
1766 X(MF_EVENT_MFT_INPUT_STREAM_ID),
1767 X(MF_MT_SOURCE_CONTENT_HINT),
1768 X(MFT_ENUM_HARDWARE_VENDOR_ID_Attribute),
1769 X(MFT_ENUM_TRANSCODE_ONLY_ATTRIBUTE),
1770 X(MF_READWRITE_MMCSS_PRIORITY),
1771 X(MF_MT_VIDEO_3D),
1772 X(MF_EVENT_START_PRESENTATION_TIME),
1773 X(MF_EVENT_SESSIONCAPS),
1774 X(MF_EVENT_PRESENTATION_TIME_OFFSET),
1775 X(MF_MEDIA_ENGINE_AUDIO_ENDPOINT_ROLE),
1776 X(MF_EVENT_SESSIONCAPS_DELTA),
1777 X(MF_EVENT_START_PRESENTATION_TIME_AT_OUTPUT),
1778 X(MFSampleExtension_DecodeTimestamp),
1779 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE),
1780 X(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT),
1781 X(MF_MT_VIDEO_H264_NO_FMOASO),
1782 X(MF_MT_AVG_BIT_ERROR_RATE),
1783 X(MF_MT_VIDEO_PRIMARIES),
1784 X(MF_SINK_WRITER_DISABLE_THROTTLING),
1785 X(MF_MT_H264_RATE_CONTROL_MODES),
1786 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK),
1787 X(MF_READWRITE_D3D_OPTIONAL),
1788 X(MF_SA_D3D11_HW_PROTECTED),
1789 X(MF_MEDIA_ENGINE_DXGI_MANAGER),
1790 X(MF_READWRITE_MMCSS_CLASS_AUDIO),
1791 X(MF_MEDIA_ENGINE_COREWINDOW),
1792 X(MF_SOURCE_READER_DISABLE_CAMERA_PLUGINS),
1793 X(MF_MT_MPEG4_TRACK_TYPE),
1794 X(MF_ACTIVATE_VIDEO_WINDOW),
1795 X(MF_MT_PAN_SCAN_APERTURE),
1796 X(MF_TOPOLOGY_RESOLUTION_STATUS),
1797 X(MF_MT_ORIGINAL_4CC),
1798 X(MF_PD_AUDIO_ISVARIABLEBITRATE),
1799 X(MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS),
1800 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE),
1801 X(MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID),
1802 X(MF_MT_MPEG2_CONTENT_PACKET),
1803 X(MFT_PROCESS_LOCAL_Attribute),
1804 X(MFT_PROCESS_LOCAL_Attribute),
1805 X(MF_MT_PAD_CONTROL_FLAGS),
1806 X(MF_MT_VIDEO_NOMINAL_RANGE),
1807 X(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
1808 X(MF_MT_MPEG_SEQUENCE_HEADER),
1809 X(MF_MEDIA_ENGINE_OPM_HWND),
1810 X(MF_MT_AUDIO_SAMPLES_PER_SECOND),
1811 X(MF_MT_SPATIAL_AUDIO_DATA_PRESENT),
1812 X(MF_MT_FRAME_RATE),
1813 X(MF_TOPONODE_FLUSH),
1814 X(MF_MT_MPEG2_STANDARD),
1815 X(MF_TOPONODE_DRAIN),
1816 X(MF_MT_TRANSFER_FUNCTION),
1817 X(MF_TOPONODE_MEDIASTART),
1818 X(MF_TOPONODE_MEDIASTOP),
1819 X(MF_SOURCE_READER_MEDIASOURCE_CONFIG),
1820 X(MF_TOPONODE_SOURCE),
1821 X(MF_TOPONODE_PRESENTATION_DESCRIPTOR),
1822 X(MF_TOPONODE_D3DAWARE),
1823 X(MF_MT_COMPRESSED),
1824 X(MF_TOPONODE_STREAM_DESCRIPTOR),
1825 X(MF_TOPONODE_ERRORCODE),
1826 X(MF_TOPONODE_SEQUENCE_ELEMENTID),
1827 X(MF_EVENT_MFT_CONTEXT),
1828 X(MF_MT_FORWARD_CUSTOM_SEI),
1829 X(MF_TOPONODE_CONNECT_METHOD),
1830 X(MFT_OUTPUT_TYPES_Attributes),
1831 X(MF_MT_IMAGE_LOSS_TOLERANT),
1832 X(MF_SESSION_REMOTE_SOURCE_MODE),
1833 X(MF_MT_DEPTH_VALUE_UNIT),
1834 X(MF_MT_AUDIO_NUM_CHANNELS),
1835 X(MF_MT_ARBITRARY_HEADER),
1836 X(MF_TOPOLOGY_DXVA_MODE),
1837 X(MF_TOPONODE_LOCKED),
1838 X(MF_TOPONODE_WORKQUEUE_ID),
1839 X(MF_MEDIA_ENGINE_CONTINUE_ON_CODEC_ERROR),
1840 X(MF_TOPONODE_WORKQUEUE_MMCSS_CLASS),
1841 X(MF_TOPONODE_DECRYPTOR),
1842 X(MF_EVENT_DO_THINNING),
1843 X(MF_TOPONODE_DISCARDABLE),
1844 X(MF_TOPOLOGY_HARDWARE_MODE),
1845 X(MF_SOURCE_READER_DISABLE_DXVA),
1846 X(MF_MT_FORWARD_CUSTOM_NALU),
1847 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE10),
1848 X(MF_TOPONODE_ERROR_MAJORTYPE),
1849 X(MF_MT_SECURE),
1850 X(MFT_FIELDOFUSE_UNLOCK_Attribute),
1851 X(MF_TOPONODE_ERROR_SUBTYPE),
1852 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE),
1853 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE),
1854 X(MF_MT_VIDEO_3D_LEFT_IS_BASE),
1855 X(MF_TOPONODE_WORKQUEUE_MMCSS_TASKID),
1856 #undef MF_READER_WRITER_D3D_MANAGER
1857 #undef X
1859 struct guid_def *ret = NULL;
1861 if (guid)
1862 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
1864 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
1867 const char *debugstr_mf_guid(const GUID *guid)
1869 static const struct guid_def guid_defs[] =
1871 #define X(g) { &(g), #g }
1872 X(MFAudioFormat_ADTS),
1873 X(MFAudioFormat_PCM),
1874 X(MFAudioFormat_PCM_HDCP),
1875 X(MFAudioFormat_Float),
1876 X(MFAudioFormat_DTS),
1877 X(MFAudioFormat_DRM),
1878 X(MFAudioFormat_MSP1),
1879 X(MFAudioFormat_Vorbis),
1880 X(MFAudioFormat_AAC),
1881 X(MFVideoFormat_RGB24),
1882 X(MFVideoFormat_ARGB32),
1883 X(MFVideoFormat_RGB32),
1884 X(MFVideoFormat_RGB565),
1885 X(MFVideoFormat_RGB555),
1886 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID),
1887 X(MFVideoFormat_A2R10G10B10),
1888 X(MFMediaType_Script),
1889 X(MFMediaType_Image),
1890 X(MFMediaType_HTML),
1891 X(MFMediaType_Binary),
1892 X(MFVideoFormat_MPEG2),
1893 X(MFMediaType_FileTransfer),
1894 X(MFVideoFormat_RGB8),
1895 X(MFAudioFormat_Dolby_AC3),
1896 X(MFVideoFormat_L8),
1897 X(MFAudioFormat_LPCM),
1898 X(MFVideoFormat_420O),
1899 X(MFVideoFormat_AI44),
1900 X(MFVideoFormat_AV1),
1901 X(MFVideoFormat_AYUV),
1902 X(MFVideoFormat_H263),
1903 X(MFVideoFormat_H264),
1904 X(MFVideoFormat_H265),
1905 X(MFVideoFormat_HEVC),
1906 X(MFVideoFormat_HEVC_ES),
1907 X(MFVideoFormat_I420),
1908 X(MFVideoFormat_IYUV),
1909 X(MFVideoFormat_M4S2),
1910 X(MFVideoFormat_MJPG),
1911 X(MFVideoFormat_MP43),
1912 X(MFVideoFormat_MP4S),
1913 X(MFVideoFormat_MP4V),
1914 X(MFVideoFormat_MPG1),
1915 X(MFVideoFormat_MSS1),
1916 X(MFVideoFormat_MSS2),
1917 X(MFVideoFormat_NV11),
1918 X(MFVideoFormat_NV12),
1919 X(MFVideoFormat_ORAW),
1920 X(MFAudioFormat_Opus),
1921 X(MFVideoFormat_D16),
1922 X(MFAudioFormat_MPEG),
1923 X(MFVideoFormat_P010),
1924 X(MFVideoFormat_P016),
1925 X(MFVideoFormat_P210),
1926 X(MFVideoFormat_P216),
1927 X(MFVideoFormat_L16),
1928 X(MFAudioFormat_MP3),
1929 X(MFVideoFormat_UYVY),
1930 X(MFVideoFormat_VP10),
1931 X(MFVideoFormat_VP80),
1932 X(MFVideoFormat_VP90),
1933 X(MFVideoFormat_WMV1),
1934 X(MFVideoFormat_WMV2),
1935 X(MFVideoFormat_WMV3),
1936 X(MFVideoFormat_WVC1),
1937 X(MFVideoFormat_Y210),
1938 X(MFVideoFormat_Y216),
1939 X(MFVideoFormat_Y410),
1940 X(MFVideoFormat_Y416),
1941 X(MFVideoFormat_Y41P),
1942 X(MFVideoFormat_Y41T),
1943 X(MFVideoFormat_Y42T),
1944 X(MFVideoFormat_YUY2),
1945 X(MFVideoFormat_YV12),
1946 X(MFVideoFormat_YVU9),
1947 X(MFVideoFormat_YVYU),
1948 X(MFAudioFormat_WMAudioV8),
1949 X(MFAudioFormat_ALAC),
1950 X(MFAudioFormat_AMR_NB),
1951 X(MFMediaType_Audio),
1952 X(MFAudioFormat_WMAudioV9),
1953 X(MFAudioFormat_AMR_WB),
1954 X(MFAudioFormat_WMAudio_Lossless),
1955 X(MFAudioFormat_AMR_WP),
1956 X(MFAudioFormat_WMASPDIF),
1957 X(MFVideoFormat_DV25),
1958 X(MFVideoFormat_DV50),
1959 X(MFVideoFormat_DVC),
1960 X(MFVideoFormat_DVH1),
1961 X(MFVideoFormat_DVHD),
1962 X(MFVideoFormat_DVSD),
1963 X(MFVideoFormat_DVSL),
1964 X(MFVideoFormat_A16B16G16R16F),
1965 X(MFVideoFormat_v210),
1966 X(MFVideoFormat_v216),
1967 X(MFVideoFormat_v410),
1968 X(MFMediaType_Video),
1969 X(MFAudioFormat_AAC_HDCP),
1970 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID),
1971 X(MFAudioFormat_Dolby_AC3_HDCP),
1972 X(MFMediaType_Subtitle),
1973 X(MFMediaType_Stream),
1974 X(MFAudioFormat_Dolby_AC3_SPDIF),
1975 X(MFAudioFormat_Float_SpatialObjects),
1976 X(MFMediaType_SAMI),
1977 X(MFAudioFormat_ADTS_HDCP),
1978 X(MFAudioFormat_FLAC),
1979 X(MFAudioFormat_Dolby_DDPlus),
1980 X(MFMediaType_MultiplexedFrames),
1981 X(MFAudioFormat_Base_HDCP),
1982 X(MFVideoFormat_Base_HDCP),
1983 X(MFVideoFormat_H264_HDCP),
1984 X(MFVideoFormat_HEVC_HDCP),
1985 X(MFMediaType_Default),
1986 X(MFMediaType_Protected),
1987 X(MFVideoFormat_H264_ES),
1988 X(MFMediaType_Perception),
1989 #undef X
1991 struct guid_def *ret = NULL;
1993 if (guid)
1994 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
1996 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
1999 struct event_id
2001 DWORD id;
2002 const char *name;
2005 static int __cdecl debug_event_id(const void *a, const void *b)
2007 const DWORD *id = a;
2008 const struct event_id *event_id = b;
2009 return *id - event_id->id;
2012 static const char *debugstr_eventid(DWORD event)
2014 static const struct event_id
2016 DWORD id;
2017 const char *name;
2019 event_ids[] =
2021 #define X(e) { e, #e }
2022 X(MEUnknown),
2023 X(MEError),
2024 X(MEExtendedType),
2025 X(MENonFatalError),
2026 X(MESessionUnknown),
2027 X(MESessionTopologySet),
2028 X(MESessionTopologiesCleared),
2029 X(MESessionStarted),
2030 X(MESessionPaused),
2031 X(MESessionStopped),
2032 X(MESessionClosed),
2033 X(MESessionEnded),
2034 X(MESessionRateChanged),
2035 X(MESessionScrubSampleComplete),
2036 X(MESessionCapabilitiesChanged),
2037 X(MESessionTopologyStatus),
2038 X(MESessionNotifyPresentationTime),
2039 X(MENewPresentation),
2040 X(MELicenseAcquisitionStart),
2041 X(MELicenseAcquisitionCompleted),
2042 X(MEIndividualizationStart),
2043 X(MEIndividualizationCompleted),
2044 X(MEEnablerProgress),
2045 X(MEEnablerCompleted),
2046 X(MEPolicyError),
2047 X(MEPolicyReport),
2048 X(MEBufferingStarted),
2049 X(MEBufferingStopped),
2050 X(MEConnectStart),
2051 X(MEConnectEnd),
2052 X(MEReconnectStart),
2053 X(MEReconnectEnd),
2054 X(MERendererEvent),
2055 X(MESessionStreamSinkFormatChanged),
2056 X(MESourceUnknown),
2057 X(MESourceStarted),
2058 X(MEStreamStarted),
2059 X(MESourceSeeked),
2060 X(MEStreamSeeked),
2061 X(MENewStream),
2062 X(MEUpdatedStream),
2063 X(MESourceStopped),
2064 X(MEStreamStopped),
2065 X(MESourcePaused),
2066 X(MEStreamPaused),
2067 X(MEEndOfPresentation),
2068 X(MEEndOfStream),
2069 X(MEMediaSample),
2070 X(MEStreamTick),
2071 X(MEStreamThinMode),
2072 X(MEStreamFormatChanged),
2073 X(MESourceRateChanged),
2074 X(MEEndOfPresentationSegment),
2075 X(MESourceCharacteristicsChanged),
2076 X(MESourceRateChangeRequested),
2077 X(MESourceMetadataChanged),
2078 X(MESequencerSourceTopologyUpdated),
2079 X(MESinkUnknown),
2080 X(MEStreamSinkStarted),
2081 X(MEStreamSinkStopped),
2082 X(MEStreamSinkPaused),
2083 X(MEStreamSinkRateChanged),
2084 X(MEStreamSinkRequestSample),
2085 X(MEStreamSinkMarker),
2086 X(MEStreamSinkPrerolled),
2087 X(MEStreamSinkScrubSampleComplete),
2088 X(MEStreamSinkFormatChanged),
2089 X(MEStreamSinkDeviceChanged),
2090 X(MEQualityNotify),
2091 X(MESinkInvalidated),
2092 X(MEAudioSessionNameChanged),
2093 X(MEAudioSessionVolumeChanged),
2094 X(MEAudioSessionDeviceRemoved),
2095 X(MEAudioSessionServerShutdown),
2096 X(MEAudioSessionGroupingParamChanged),
2097 X(MEAudioSessionIconChanged),
2098 X(MEAudioSessionFormatChanged),
2099 X(MEAudioSessionDisconnected),
2100 X(MEAudioSessionExclusiveModeOverride),
2101 X(METrustUnknown),
2102 X(MEPolicyChanged),
2103 X(MEContentProtectionMessage),
2104 X(MEPolicySet),
2105 X(MEWMDRMLicenseBackupCompleted),
2106 X(MEWMDRMLicenseBackupProgress),
2107 X(MEWMDRMLicenseRestoreCompleted),
2108 X(MEWMDRMLicenseRestoreProgress),
2109 X(MEWMDRMLicenseAcquisitionCompleted),
2110 X(MEWMDRMIndividualizationCompleted),
2111 X(MEWMDRMIndividualizationProgress),
2112 X(MEWMDRMProximityCompleted),
2113 X(MEWMDRMLicenseStoreCleaned),
2114 X(MEWMDRMRevocationDownloadCompleted),
2115 X(METransformUnknown),
2116 X(METransformNeedInput),
2117 X(METransformHaveOutput),
2118 X(METransformDrainComplete),
2119 X(METransformMarker),
2120 X(METransformInputStreamStateChanged),
2121 X(MEByteStreamCharacteristicsChanged),
2122 X(MEVideoCaptureDeviceRemoved),
2123 X(MEVideoCaptureDevicePreempted),
2124 X(MEStreamSinkFormatInvalidated),
2125 X(MEEncodingParameters),
2126 X(MEContentProtectionMetadata),
2127 X(MEDeviceThermalStateChanged),
2128 #undef X
2131 struct event_id *ret = bsearch(&event, event_ids, ARRAY_SIZE(event_ids), sizeof(*event_ids), debug_event_id);
2132 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbg_sprintf("%u", event);
2135 static inline struct attributes *impl_from_IMFAttributes(IMFAttributes *iface)
2137 return CONTAINING_RECORD(iface, struct attributes, IMFAttributes_iface);
2140 static HRESULT WINAPI mfattributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
2142 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
2144 if (IsEqualIID(riid, &IID_IMFAttributes) ||
2145 IsEqualGUID(riid, &IID_IUnknown))
2147 *out = iface;
2148 IMFAttributes_AddRef(iface);
2149 return S_OK;
2152 WARN("Unsupported %s.\n", debugstr_guid(riid));
2153 *out = NULL;
2154 return E_NOINTERFACE;
2157 static ULONG WINAPI mfattributes_AddRef(IMFAttributes *iface)
2159 struct attributes *attributes = impl_from_IMFAttributes(iface);
2160 ULONG refcount = InterlockedIncrement(&attributes->ref);
2162 TRACE("%p, refcount %d.\n", iface, refcount);
2164 return refcount;
2167 static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
2169 struct attributes *attributes = impl_from_IMFAttributes(iface);
2170 ULONG refcount = InterlockedDecrement(&attributes->ref);
2172 TRACE("%p, refcount %d.\n", iface, refcount);
2174 if (!refcount)
2176 clear_attributes_object(attributes);
2177 free(attributes);
2180 return refcount;
2183 static struct attribute *attributes_find_item(struct attributes *attributes, REFGUID key, size_t *index)
2185 size_t i;
2187 for (i = 0; i < attributes->count; ++i)
2189 if (IsEqualGUID(key, &attributes->attributes[i].key))
2191 if (index)
2192 *index = i;
2193 return &attributes->attributes[i];
2197 return NULL;
2200 static HRESULT attributes_get_item(struct attributes *attributes, const GUID *key, PROPVARIANT *value)
2202 struct attribute *attribute;
2203 HRESULT hr;
2205 EnterCriticalSection(&attributes->cs);
2207 attribute = attributes_find_item(attributes, key, NULL);
2208 if (attribute)
2210 if (attribute->value.vt == value->vt && !(value->vt == VT_UNKNOWN && !attribute->value.punkVal))
2211 hr = PropVariantCopy(value, &attribute->value);
2212 else
2213 hr = MF_E_INVALIDTYPE;
2215 else
2216 hr = MF_E_ATTRIBUTENOTFOUND;
2218 LeaveCriticalSection(&attributes->cs);
2220 return hr;
2223 HRESULT attributes_GetItem(struct attributes *attributes, REFGUID key, PROPVARIANT *value)
2225 struct attribute *attribute;
2226 HRESULT hr;
2228 EnterCriticalSection(&attributes->cs);
2230 if ((attribute = attributes_find_item(attributes, key, NULL)))
2231 hr = value ? PropVariantCopy(value, &attribute->value) : S_OK;
2232 else
2233 hr = MF_E_ATTRIBUTENOTFOUND;
2235 LeaveCriticalSection(&attributes->cs);
2237 return hr;
2240 HRESULT attributes_GetItemType(struct attributes *attributes, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2242 struct attribute *attribute;
2243 HRESULT hr = S_OK;
2245 EnterCriticalSection(&attributes->cs);
2247 if ((attribute = attributes_find_item(attributes, key, NULL)))
2249 *type = attribute->value.vt;
2251 else
2252 hr = MF_E_ATTRIBUTENOTFOUND;
2254 LeaveCriticalSection(&attributes->cs);
2256 return hr;
2259 HRESULT attributes_CompareItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value, BOOL *result)
2261 struct attribute *attribute;
2263 *result = FALSE;
2265 EnterCriticalSection(&attributes->cs);
2267 if ((attribute = attributes_find_item(attributes, key, NULL)))
2269 *result = attribute->value.vt == value->vt &&
2270 !PropVariantCompareEx(&attribute->value, value, PVCU_DEFAULT, PVCF_DEFAULT);
2273 LeaveCriticalSection(&attributes->cs);
2275 return S_OK;
2278 HRESULT attributes_Compare(struct attributes *attributes, IMFAttributes *theirs,
2279 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2281 IMFAttributes *smaller, *other;
2282 MF_ATTRIBUTE_TYPE type;
2283 HRESULT hr = S_OK;
2284 UINT32 count;
2285 BOOL result;
2286 size_t i;
2288 if (FAILED(hr = IMFAttributes_GetCount(theirs, &count)))
2289 return hr;
2291 EnterCriticalSection(&attributes->cs);
2293 result = TRUE;
2295 switch (match_type)
2297 case MF_ATTRIBUTES_MATCH_OUR_ITEMS:
2298 for (i = 0; i < attributes->count; ++i)
2300 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2301 &attributes->attributes[i].value, &result)))
2302 break;
2303 if (!result)
2304 break;
2306 break;
2307 case MF_ATTRIBUTES_MATCH_THEIR_ITEMS:
2308 hr = IMFAttributes_Compare(theirs, &attributes->IMFAttributes_iface, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2309 break;
2310 case MF_ATTRIBUTES_MATCH_ALL_ITEMS:
2311 if (count != attributes->count)
2313 result = FALSE;
2314 break;
2316 for (i = 0; i < count; ++i)
2318 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2319 &attributes->attributes[i].value, &result)))
2320 break;
2321 if (!result)
2322 break;
2324 break;
2325 case MF_ATTRIBUTES_MATCH_INTERSECTION:
2326 for (i = 0; i < attributes->count; ++i)
2328 if (FAILED(IMFAttributes_GetItemType(theirs, &attributes->attributes[i].key, &type)))
2329 continue;
2331 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2332 &attributes->attributes[i].value, &result)))
2333 break;
2335 if (!result)
2336 break;
2338 break;
2339 case MF_ATTRIBUTES_MATCH_SMALLER:
2340 smaller = attributes->count > count ? theirs : &attributes->IMFAttributes_iface;
2341 other = attributes->count > count ? &attributes->IMFAttributes_iface : theirs;
2342 hr = IMFAttributes_Compare(smaller, other, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2343 break;
2344 default:
2345 WARN("Unknown match type %d.\n", match_type);
2346 hr = E_INVALIDARG;
2349 LeaveCriticalSection(&attributes->cs);
2351 if (SUCCEEDED(hr))
2352 *ret = result;
2354 return hr;
2357 HRESULT attributes_GetUINT32(struct attributes *attributes, REFGUID key, UINT32 *value)
2359 PROPVARIANT attrval;
2360 HRESULT hr;
2362 PropVariantInit(&attrval);
2363 attrval.vt = VT_UI4;
2364 hr = attributes_get_item(attributes, key, &attrval);
2365 if (SUCCEEDED(hr))
2366 *value = attrval.ulVal;
2368 return hr;
2371 HRESULT attributes_GetUINT64(struct attributes *attributes, REFGUID key, UINT64 *value)
2373 PROPVARIANT attrval;
2374 HRESULT hr;
2376 PropVariantInit(&attrval);
2377 attrval.vt = VT_UI8;
2378 hr = attributes_get_item(attributes, key, &attrval);
2379 if (SUCCEEDED(hr))
2380 *value = attrval.uhVal.QuadPart;
2382 return hr;
2385 HRESULT attributes_GetDouble(struct attributes *attributes, REFGUID key, double *value)
2387 PROPVARIANT attrval;
2388 HRESULT hr;
2390 PropVariantInit(&attrval);
2391 attrval.vt = VT_R8;
2392 hr = attributes_get_item(attributes, key, &attrval);
2393 if (SUCCEEDED(hr))
2394 *value = attrval.dblVal;
2396 return hr;
2399 HRESULT attributes_GetGUID(struct attributes *attributes, REFGUID key, GUID *value)
2401 struct attribute *attribute;
2402 HRESULT hr = S_OK;
2404 EnterCriticalSection(&attributes->cs);
2406 attribute = attributes_find_item(attributes, key, NULL);
2407 if (attribute)
2409 if (attribute->value.vt == MF_ATTRIBUTE_GUID)
2410 *value = *attribute->value.puuid;
2411 else
2412 hr = MF_E_INVALIDTYPE;
2414 else
2415 hr = MF_E_ATTRIBUTENOTFOUND;
2417 LeaveCriticalSection(&attributes->cs);
2419 return hr;
2422 HRESULT attributes_GetStringLength(struct attributes *attributes, REFGUID key, UINT32 *length)
2424 struct attribute *attribute;
2425 HRESULT hr = S_OK;
2427 EnterCriticalSection(&attributes->cs);
2429 attribute = attributes_find_item(attributes, key, NULL);
2430 if (attribute)
2432 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2433 *length = lstrlenW(attribute->value.pwszVal);
2434 else
2435 hr = MF_E_INVALIDTYPE;
2437 else
2438 hr = MF_E_ATTRIBUTENOTFOUND;
2440 LeaveCriticalSection(&attributes->cs);
2442 return hr;
2445 HRESULT attributes_GetString(struct attributes *attributes, REFGUID key, WCHAR *value,
2446 UINT32 size, UINT32 *length)
2448 struct attribute *attribute;
2449 HRESULT hr = S_OK;
2451 EnterCriticalSection(&attributes->cs);
2453 attribute = attributes_find_item(attributes, key, NULL);
2454 if (attribute)
2456 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2458 int len = lstrlenW(attribute->value.pwszVal);
2460 if (length)
2461 *length = len;
2463 if (size <= len)
2464 hr = STRSAFE_E_INSUFFICIENT_BUFFER;
2465 else
2466 memcpy(value, attribute->value.pwszVal, (len + 1) * sizeof(WCHAR));
2468 else
2469 hr = MF_E_INVALIDTYPE;
2471 else
2472 hr = MF_E_ATTRIBUTENOTFOUND;
2474 LeaveCriticalSection(&attributes->cs);
2476 return hr;
2479 HRESULT attributes_GetAllocatedString(struct attributes *attributes, REFGUID key, WCHAR **value, UINT32 *length)
2481 PROPVARIANT attrval;
2482 HRESULT hr;
2484 PropVariantInit(&attrval);
2485 attrval.vt = VT_LPWSTR;
2486 hr = attributes_get_item(attributes, key, &attrval);
2487 if (SUCCEEDED(hr))
2489 *value = attrval.pwszVal;
2490 *length = lstrlenW(*value);
2493 return hr;
2496 HRESULT attributes_GetBlobSize(struct attributes *attributes, REFGUID key, UINT32 *size)
2498 struct attribute *attribute;
2499 HRESULT hr = S_OK;
2501 EnterCriticalSection(&attributes->cs);
2503 attribute = attributes_find_item(attributes, key, NULL);
2504 if (attribute)
2506 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2507 *size = attribute->value.caub.cElems;
2508 else
2509 hr = MF_E_INVALIDTYPE;
2511 else
2512 hr = MF_E_ATTRIBUTENOTFOUND;
2514 LeaveCriticalSection(&attributes->cs);
2516 return hr;
2519 HRESULT attributes_GetBlob(struct attributes *attributes, REFGUID key, UINT8 *buf, UINT32 bufsize, UINT32 *blobsize)
2521 struct attribute *attribute;
2522 HRESULT hr;
2524 EnterCriticalSection(&attributes->cs);
2526 attribute = attributes_find_item(attributes, key, NULL);
2527 if (attribute)
2529 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2531 UINT32 size = attribute->value.caub.cElems;
2533 if (bufsize >= size)
2534 hr = PropVariantToBuffer(&attribute->value, buf, size);
2535 else
2536 hr = E_NOT_SUFFICIENT_BUFFER;
2538 if (blobsize)
2539 *blobsize = size;
2541 else
2542 hr = MF_E_INVALIDTYPE;
2544 else
2545 hr = MF_E_ATTRIBUTENOTFOUND;
2547 LeaveCriticalSection(&attributes->cs);
2549 return hr;
2552 HRESULT attributes_GetAllocatedBlob(struct attributes *attributes, REFGUID key, UINT8 **buf, UINT32 *size)
2554 PROPVARIANT attrval;
2555 HRESULT hr;
2557 attrval.vt = VT_VECTOR | VT_UI1;
2558 hr = attributes_get_item(attributes, key, &attrval);
2559 if (SUCCEEDED(hr))
2561 *buf = attrval.caub.pElems;
2562 *size = attrval.caub.cElems;
2565 return hr;
2568 HRESULT attributes_GetUnknown(struct attributes *attributes, REFGUID key, REFIID riid, void **out)
2570 PROPVARIANT attrval;
2571 HRESULT hr;
2573 PropVariantInit(&attrval);
2574 attrval.vt = VT_UNKNOWN;
2575 hr = attributes_get_item(attributes, key, &attrval);
2576 if (SUCCEEDED(hr))
2577 hr = IUnknown_QueryInterface(attrval.punkVal, riid, out);
2578 PropVariantClear(&attrval);
2579 return hr;
2582 static HRESULT attributes_set_item(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2584 struct attribute *attribute;
2586 EnterCriticalSection(&attributes->cs);
2588 attribute = attributes_find_item(attributes, key, NULL);
2589 if (!attribute)
2591 if (!mf_array_reserve((void **)&attributes->attributes, &attributes->capacity, attributes->count + 1,
2592 sizeof(*attributes->attributes)))
2594 LeaveCriticalSection(&attributes->cs);
2595 return E_OUTOFMEMORY;
2597 attributes->attributes[attributes->count].key = *key;
2598 attribute = &attributes->attributes[attributes->count++];
2600 else
2601 PropVariantClear(&attribute->value);
2603 PropVariantCopy(&attribute->value, value);
2605 LeaveCriticalSection(&attributes->cs);
2607 return S_OK;
2610 HRESULT attributes_SetItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2612 PROPVARIANT empty;
2614 switch (value->vt)
2616 case MF_ATTRIBUTE_UINT32:
2617 case MF_ATTRIBUTE_UINT64:
2618 case MF_ATTRIBUTE_DOUBLE:
2619 case MF_ATTRIBUTE_GUID:
2620 case MF_ATTRIBUTE_STRING:
2621 case MF_ATTRIBUTE_BLOB:
2622 case MF_ATTRIBUTE_IUNKNOWN:
2623 return attributes_set_item(attributes, key, value);
2624 default:
2625 PropVariantInit(&empty);
2626 attributes_set_item(attributes, key, &empty);
2627 return MF_E_INVALIDTYPE;
2631 HRESULT attributes_DeleteItem(struct attributes *attributes, REFGUID key)
2633 struct attribute *attribute;
2634 size_t index = 0;
2636 EnterCriticalSection(&attributes->cs);
2638 if ((attribute = attributes_find_item(attributes, key, &index)))
2640 size_t count;
2642 PropVariantClear(&attribute->value);
2644 attributes->count--;
2645 count = attributes->count - index;
2646 if (count)
2647 memmove(&attributes->attributes[index], &attributes->attributes[index + 1], count * sizeof(*attributes->attributes));
2650 LeaveCriticalSection(&attributes->cs);
2652 return S_OK;
2655 HRESULT attributes_DeleteAllItems(struct attributes *attributes)
2657 EnterCriticalSection(&attributes->cs);
2659 while (attributes->count)
2661 PropVariantClear(&attributes->attributes[--attributes->count].value);
2663 free(attributes->attributes);
2664 attributes->attributes = NULL;
2665 attributes->capacity = 0;
2667 LeaveCriticalSection(&attributes->cs);
2669 return S_OK;
2672 HRESULT attributes_SetUINT32(struct attributes *attributes, REFGUID key, UINT32 value)
2674 PROPVARIANT attrval;
2676 attrval.vt = VT_UI4;
2677 attrval.ulVal = value;
2678 return attributes_set_item(attributes, key, &attrval);
2681 HRESULT attributes_SetUINT64(struct attributes *attributes, REFGUID key, UINT64 value)
2683 PROPVARIANT attrval;
2685 attrval.vt = VT_UI8;
2686 attrval.uhVal.QuadPart = value;
2687 return attributes_set_item(attributes, key, &attrval);
2690 HRESULT attributes_SetDouble(struct attributes *attributes, REFGUID key, double value)
2692 PROPVARIANT attrval;
2694 attrval.vt = VT_R8;
2695 attrval.dblVal = value;
2696 return attributes_set_item(attributes, key, &attrval);
2699 HRESULT attributes_SetGUID(struct attributes *attributes, REFGUID key, REFGUID value)
2701 PROPVARIANT attrval;
2703 attrval.vt = VT_CLSID;
2704 attrval.puuid = (CLSID *)value;
2705 return attributes_set_item(attributes, key, &attrval);
2708 HRESULT attributes_SetString(struct attributes *attributes, REFGUID key, const WCHAR *value)
2710 PROPVARIANT attrval;
2712 attrval.vt = VT_LPWSTR;
2713 attrval.pwszVal = (WCHAR *)value;
2714 return attributes_set_item(attributes, key, &attrval);
2717 HRESULT attributes_SetBlob(struct attributes *attributes, REFGUID key, const UINT8 *buf, UINT32 size)
2719 PROPVARIANT attrval;
2721 attrval.vt = VT_VECTOR | VT_UI1;
2722 attrval.caub.cElems = size;
2723 attrval.caub.pElems = (UINT8 *)buf;
2724 return attributes_set_item(attributes, key, &attrval);
2727 HRESULT attributes_SetUnknown(struct attributes *attributes, REFGUID key, IUnknown *unknown)
2729 PROPVARIANT attrval;
2731 attrval.vt = VT_UNKNOWN;
2732 attrval.punkVal = unknown;
2733 return attributes_set_item(attributes, key, &attrval);
2736 HRESULT attributes_LockStore(struct attributes *attributes)
2738 EnterCriticalSection(&attributes->cs);
2740 return S_OK;
2743 HRESULT attributes_UnlockStore(struct attributes *attributes)
2745 LeaveCriticalSection(&attributes->cs);
2747 return S_OK;
2750 HRESULT attributes_GetCount(struct attributes *attributes, UINT32 *count)
2752 EnterCriticalSection(&attributes->cs);
2753 *count = attributes->count;
2754 LeaveCriticalSection(&attributes->cs);
2756 return S_OK;
2759 HRESULT attributes_GetItemByIndex(struct attributes *attributes, UINT32 index, GUID *key, PROPVARIANT *value)
2761 HRESULT hr = S_OK;
2763 EnterCriticalSection(&attributes->cs);
2765 if (index < attributes->count)
2767 *key = attributes->attributes[index].key;
2768 if (value)
2769 PropVariantCopy(value, &attributes->attributes[index].value);
2771 else
2772 hr = E_INVALIDARG;
2774 LeaveCriticalSection(&attributes->cs);
2776 return hr;
2779 HRESULT attributes_CopyAllItems(struct attributes *attributes, IMFAttributes *dest)
2781 HRESULT hr = S_OK;
2782 size_t i;
2784 EnterCriticalSection(&attributes->cs);
2786 IMFAttributes_LockStore(dest);
2788 IMFAttributes_DeleteAllItems(dest);
2790 for (i = 0; i < attributes->count; ++i)
2792 hr = IMFAttributes_SetItem(dest, &attributes->attributes[i].key, &attributes->attributes[i].value);
2793 if (FAILED(hr))
2794 break;
2797 IMFAttributes_UnlockStore(dest);
2799 LeaveCriticalSection(&attributes->cs);
2801 return hr;
2804 static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
2806 struct attributes *attributes = impl_from_IMFAttributes(iface);
2808 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2810 return attributes_GetItem(attributes, key, value);
2813 static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2815 struct attributes *attributes = impl_from_IMFAttributes(iface);
2817 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
2819 return attributes_GetItemType(attributes, key, type);
2822 static HRESULT WINAPI mfattributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
2824 struct attributes *attributes = impl_from_IMFAttributes(iface);
2826 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
2828 return attributes_CompareItem(attributes, key, value, result);
2831 static HRESULT WINAPI mfattributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
2832 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2834 struct attributes *attributes = impl_from_IMFAttributes(iface);
2836 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
2838 return attributes_Compare(attributes, theirs, match_type, ret);
2841 static HRESULT WINAPI mfattributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
2843 struct attributes *attributes = impl_from_IMFAttributes(iface);
2845 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2847 return attributes_GetUINT32(attributes, key, value);
2850 static HRESULT WINAPI mfattributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
2852 struct attributes *attributes = impl_from_IMFAttributes(iface);
2854 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2856 return attributes_GetUINT64(attributes, key, value);
2859 static HRESULT WINAPI mfattributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
2861 struct attributes *attributes = impl_from_IMFAttributes(iface);
2863 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2865 return attributes_GetDouble(attributes, key, value);
2868 static HRESULT WINAPI mfattributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
2870 struct attributes *attributes = impl_from_IMFAttributes(iface);
2872 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2874 return attributes_GetGUID(attributes, key, value);
2877 static HRESULT WINAPI mfattributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
2879 struct attributes *attributes = impl_from_IMFAttributes(iface);
2881 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
2883 return attributes_GetStringLength(attributes, key, length);
2886 static HRESULT WINAPI mfattributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
2887 UINT32 size, UINT32 *length)
2889 struct attributes *attributes = impl_from_IMFAttributes(iface);
2891 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
2893 return attributes_GetString(attributes, key, value, size, length);
2896 static HRESULT WINAPI mfattributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
2898 struct attributes *attributes = impl_from_IMFAttributes(iface);
2900 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
2902 return attributes_GetAllocatedString(attributes, key, value, length);
2905 static HRESULT WINAPI mfattributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
2907 struct attributes *attributes = impl_from_IMFAttributes(iface);
2909 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
2911 return attributes_GetBlobSize(attributes, key, size);
2914 static HRESULT WINAPI mfattributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
2915 UINT32 bufsize, UINT32 *blobsize)
2917 struct attributes *attributes = impl_from_IMFAttributes(iface);
2919 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
2921 return attributes_GetBlob(attributes, key, buf, bufsize, blobsize);
2924 static HRESULT WINAPI mfattributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
2926 struct attributes *attributes = impl_from_IMFAttributes(iface);
2928 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
2930 return attributes_GetAllocatedBlob(attributes, key, buf, size);
2933 static HRESULT WINAPI mfattributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
2935 struct attributes *attributes = impl_from_IMFAttributes(iface);
2937 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
2939 return attributes_GetUnknown(attributes, key, riid, out);
2942 static HRESULT WINAPI mfattributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
2944 struct attributes *attributes = impl_from_IMFAttributes(iface);
2946 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
2948 return attributes_SetItem(attributes, key, value);
2951 static HRESULT WINAPI mfattributes_DeleteItem(IMFAttributes *iface, REFGUID key)
2953 struct attributes *attributes = impl_from_IMFAttributes(iface);
2955 TRACE("%p, %s.\n", iface, debugstr_attr(key));
2957 return attributes_DeleteItem(attributes, key);
2960 static HRESULT WINAPI mfattributes_DeleteAllItems(IMFAttributes *iface)
2962 struct attributes *attributes = impl_from_IMFAttributes(iface);
2964 TRACE("%p.\n", iface);
2966 return attributes_DeleteAllItems(attributes);
2969 static HRESULT WINAPI mfattributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
2971 struct attributes *attributes = impl_from_IMFAttributes(iface);
2973 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
2975 return attributes_SetUINT32(attributes, key, value);
2978 static HRESULT WINAPI mfattributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
2980 struct attributes *attributes = impl_from_IMFAttributes(iface);
2982 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
2984 return attributes_SetUINT64(attributes, key, value);
2987 static HRESULT WINAPI mfattributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
2989 struct attributes *attributes = impl_from_IMFAttributes(iface);
2991 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
2993 return attributes_SetDouble(attributes, key, value);
2996 static HRESULT WINAPI mfattributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
2998 struct attributes *attributes = impl_from_IMFAttributes(iface);
3000 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
3002 return attributes_SetGUID(attributes, key, value);
3005 static HRESULT WINAPI mfattributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
3007 struct attributes *attributes = impl_from_IMFAttributes(iface);
3009 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
3011 return attributes_SetString(attributes, key, value);
3014 static HRESULT WINAPI mfattributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
3016 struct attributes *attributes = impl_from_IMFAttributes(iface);
3018 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
3020 return attributes_SetBlob(attributes, key, buf, size);
3023 static HRESULT WINAPI mfattributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
3025 struct attributes *attributes = impl_from_IMFAttributes(iface);
3027 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
3029 return attributes_SetUnknown(attributes, key, unknown);
3032 static HRESULT WINAPI mfattributes_LockStore(IMFAttributes *iface)
3034 struct attributes *attributes = impl_from_IMFAttributes(iface);
3036 TRACE("%p.\n", iface);
3038 return attributes_LockStore(attributes);
3041 static HRESULT WINAPI mfattributes_UnlockStore(IMFAttributes *iface)
3043 struct attributes *attributes = impl_from_IMFAttributes(iface);
3045 TRACE("%p.\n", iface);
3047 return attributes_UnlockStore(attributes);
3050 static HRESULT WINAPI mfattributes_GetCount(IMFAttributes *iface, UINT32 *count)
3052 struct attributes *attributes = impl_from_IMFAttributes(iface);
3054 TRACE("%p, %p.\n", iface, count);
3056 return attributes_GetCount(attributes, count);
3059 static HRESULT WINAPI mfattributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
3061 struct attributes *attributes = impl_from_IMFAttributes(iface);
3063 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
3065 return attributes_GetItemByIndex(attributes, index, key, value);
3068 static HRESULT WINAPI mfattributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
3070 struct attributes *attributes = impl_from_IMFAttributes(iface);
3072 TRACE("%p, %p.\n", iface, dest);
3074 return attributes_CopyAllItems(attributes, dest);
3077 static const IMFAttributesVtbl mfattributes_vtbl =
3079 mfattributes_QueryInterface,
3080 mfattributes_AddRef,
3081 mfattributes_Release,
3082 mfattributes_GetItem,
3083 mfattributes_GetItemType,
3084 mfattributes_CompareItem,
3085 mfattributes_Compare,
3086 mfattributes_GetUINT32,
3087 mfattributes_GetUINT64,
3088 mfattributes_GetDouble,
3089 mfattributes_GetGUID,
3090 mfattributes_GetStringLength,
3091 mfattributes_GetString,
3092 mfattributes_GetAllocatedString,
3093 mfattributes_GetBlobSize,
3094 mfattributes_GetBlob,
3095 mfattributes_GetAllocatedBlob,
3096 mfattributes_GetUnknown,
3097 mfattributes_SetItem,
3098 mfattributes_DeleteItem,
3099 mfattributes_DeleteAllItems,
3100 mfattributes_SetUINT32,
3101 mfattributes_SetUINT64,
3102 mfattributes_SetDouble,
3103 mfattributes_SetGUID,
3104 mfattributes_SetString,
3105 mfattributes_SetBlob,
3106 mfattributes_SetUnknown,
3107 mfattributes_LockStore,
3108 mfattributes_UnlockStore,
3109 mfattributes_GetCount,
3110 mfattributes_GetItemByIndex,
3111 mfattributes_CopyAllItems
3114 HRESULT init_attributes_object(struct attributes *object, UINT32 size)
3116 object->IMFAttributes_iface.lpVtbl = &mfattributes_vtbl;
3117 object->ref = 1;
3118 InitializeCriticalSection(&object->cs);
3120 object->attributes = NULL;
3121 object->count = 0;
3122 object->capacity = 0;
3123 if (!mf_array_reserve((void **)&object->attributes, &object->capacity, size,
3124 sizeof(*object->attributes)))
3126 DeleteCriticalSection(&object->cs);
3127 return E_OUTOFMEMORY;
3130 return S_OK;
3133 void clear_attributes_object(struct attributes *object)
3135 size_t i;
3137 for (i = 0; i < object->count; i++)
3138 PropVariantClear(&object->attributes[i].value);
3139 free(object->attributes);
3141 DeleteCriticalSection(&object->cs);
3144 /***********************************************************************
3145 * MFCreateAttributes (mfplat.@)
3147 HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size)
3149 struct attributes *object;
3150 HRESULT hr;
3152 TRACE("%p, %d\n", attributes, size);
3154 if (!(object = calloc(1, sizeof(*object))))
3155 return E_OUTOFMEMORY;
3157 if (FAILED(hr = init_attributes_object(object, size)))
3159 free(object);
3160 return hr;
3162 *attributes = &object->IMFAttributes_iface;
3164 return S_OK;
3167 #define ATTRIBUTES_STORE_MAGIC 0x494d4641 /* IMFA */
3169 struct attributes_store_header
3171 DWORD magic;
3172 UINT32 count;
3175 struct attributes_store_item
3177 GUID key;
3178 QWORD type;
3179 union
3181 double f;
3182 UINT32 i32;
3183 UINT64 i64;
3184 struct
3186 DWORD size;
3187 DWORD offset;
3188 } subheader;
3189 } u;
3192 /***********************************************************************
3193 * MFGetAttributesAsBlobSize (mfplat.@)
3195 HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size)
3197 unsigned int i, count, length;
3198 HRESULT hr;
3199 GUID key;
3201 TRACE("%p, %p.\n", attributes, size);
3203 IMFAttributes_LockStore(attributes);
3205 hr = IMFAttributes_GetCount(attributes, &count);
3207 *size = sizeof(struct attributes_store_header);
3209 for (i = 0; i < count; ++i)
3211 MF_ATTRIBUTE_TYPE type;
3213 hr = IMFAttributes_GetItemByIndex(attributes, i, &key, NULL);
3214 if (FAILED(hr))
3215 break;
3217 *size += sizeof(struct attributes_store_item);
3219 IMFAttributes_GetItemType(attributes, &key, &type);
3221 switch (type)
3223 case MF_ATTRIBUTE_GUID:
3224 *size += sizeof(GUID);
3225 break;
3226 case MF_ATTRIBUTE_STRING:
3227 IMFAttributes_GetStringLength(attributes, &key, &length);
3228 *size += (length + 1) * sizeof(WCHAR);
3229 break;
3230 case MF_ATTRIBUTE_BLOB:
3231 IMFAttributes_GetBlobSize(attributes, &key, &length);
3232 *size += length;
3233 break;
3234 case MF_ATTRIBUTE_UINT32:
3235 case MF_ATTRIBUTE_UINT64:
3236 case MF_ATTRIBUTE_DOUBLE:
3237 case MF_ATTRIBUTE_IUNKNOWN:
3238 default:
3243 IMFAttributes_UnlockStore(attributes);
3245 return hr;
3248 struct attr_serialize_context
3250 UINT8 *buffer;
3251 UINT8 *ptr;
3252 UINT32 size;
3255 static void attributes_serialize_write(struct attr_serialize_context *context, const void *value, unsigned int size)
3257 memcpy(context->ptr, value, size);
3258 context->ptr += size;
3261 static BOOL attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
3262 const void *value)
3264 switch (item->type)
3266 case MF_ATTRIBUTE_UINT32:
3267 case MF_ATTRIBUTE_UINT64:
3268 case MF_ATTRIBUTE_DOUBLE:
3269 attributes_serialize_write(context, item, sizeof(*item));
3270 break;
3271 case MF_ATTRIBUTE_GUID:
3272 case MF_ATTRIBUTE_STRING:
3273 case MF_ATTRIBUTE_BLOB:
3274 item->u.subheader.offset = context->size - item->u.subheader.size;
3275 attributes_serialize_write(context, item, sizeof(*item));
3276 memcpy(context->buffer + item->u.subheader.offset, value, item->u.subheader.size);
3277 context->size -= item->u.subheader.size;
3278 break;
3279 default:
3280 return FALSE;
3283 return TRUE;
3286 /***********************************************************************
3287 * MFGetAttributesAsBlob (mfplat.@)
3289 HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size)
3291 struct attributes_store_header header;
3292 struct attr_serialize_context context;
3293 unsigned int required_size, i;
3294 PROPVARIANT value;
3295 UINT32 count;
3296 HRESULT hr;
3298 TRACE("%p, %p, %u.\n", attributes, buffer, size);
3300 if (FAILED(hr = MFGetAttributesAsBlobSize(attributes, &required_size)))
3301 return hr;
3303 if (required_size > size)
3304 return MF_E_BUFFERTOOSMALL;
3306 context.buffer = buffer;
3307 context.ptr = buffer;
3308 context.size = required_size;
3310 IMFAttributes_LockStore(attributes);
3312 header.magic = ATTRIBUTES_STORE_MAGIC;
3313 header.count = 0; /* Will be updated later */
3314 IMFAttributes_GetCount(attributes, &count);
3316 attributes_serialize_write(&context, &header, sizeof(header));
3318 for (i = 0; i < count; ++i)
3320 struct attributes_store_item item;
3321 const void *data = NULL;
3323 hr = IMFAttributes_GetItemByIndex(attributes, i, &item.key, &value);
3324 if (FAILED(hr))
3325 break;
3327 item.type = value.vt;
3329 switch (value.vt)
3331 case MF_ATTRIBUTE_UINT32:
3332 case MF_ATTRIBUTE_UINT64:
3333 item.u.i64 = value.uhVal.QuadPart;
3334 break;
3335 case MF_ATTRIBUTE_DOUBLE:
3336 item.u.f = value.dblVal;
3337 break;
3338 case MF_ATTRIBUTE_GUID:
3339 item.u.subheader.size = sizeof(*value.puuid);
3340 data = value.puuid;
3341 break;
3342 case MF_ATTRIBUTE_STRING:
3343 item.u.subheader.size = (lstrlenW(value.pwszVal) + 1) * sizeof(WCHAR);
3344 data = value.pwszVal;
3345 break;
3346 case MF_ATTRIBUTE_BLOB:
3347 item.u.subheader.size = value.caub.cElems;
3348 data = value.caub.pElems;
3349 break;
3350 case MF_ATTRIBUTE_IUNKNOWN:
3351 break;
3352 default:
3353 WARN("Unknown attribute type %#x.\n", value.vt);
3356 if (attributes_serialize_write_item(&context, &item, data))
3357 header.count++;
3359 PropVariantClear(&value);
3362 memcpy(context.buffer, &header, sizeof(header));
3364 IMFAttributes_UnlockStore(attributes);
3366 return S_OK;
3369 static HRESULT attributes_deserialize_read(struct attr_serialize_context *context, void *value, unsigned int size)
3371 if (context->size < (context->ptr - context->buffer) + size)
3372 return E_INVALIDARG;
3374 memcpy(value, context->ptr, size);
3375 context->ptr += size;
3377 return S_OK;
3380 /***********************************************************************
3381 * MFInitAttributesFromBlob (mfplat.@)
3383 HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *dest, const UINT8 *buffer, UINT size)
3385 struct attr_serialize_context context;
3386 struct attributes_store_header header;
3387 struct attributes_store_item item;
3388 IMFAttributes *attributes;
3389 unsigned int i;
3390 HRESULT hr;
3392 TRACE("%p, %p, %u.\n", dest, buffer, size);
3394 context.buffer = (UINT8 *)buffer;
3395 context.ptr = (UINT8 *)buffer;
3396 context.size = size;
3398 /* Validate buffer structure. */
3399 if (FAILED(hr = attributes_deserialize_read(&context, &header, sizeof(header))))
3400 return hr;
3402 if (header.magic != ATTRIBUTES_STORE_MAGIC)
3403 return E_UNEXPECTED;
3405 if (FAILED(hr = MFCreateAttributes(&attributes, header.count)))
3406 return hr;
3408 for (i = 0; i < header.count; ++i)
3410 if (FAILED(hr = attributes_deserialize_read(&context, &item, sizeof(item))))
3411 break;
3413 hr = E_UNEXPECTED;
3415 switch (item.type)
3417 case MF_ATTRIBUTE_UINT32:
3418 hr = IMFAttributes_SetUINT32(attributes, &item.key, item.u.i32);
3419 break;
3420 case MF_ATTRIBUTE_UINT64:
3421 hr = IMFAttributes_SetUINT64(attributes, &item.key, item.u.i64);
3422 break;
3423 case MF_ATTRIBUTE_DOUBLE:
3424 hr = IMFAttributes_SetDouble(attributes, &item.key, item.u.f);
3425 break;
3426 case MF_ATTRIBUTE_GUID:
3427 if (item.u.subheader.size == sizeof(GUID) &&
3428 item.u.subheader.offset + item.u.subheader.size <= context.size)
3430 hr = IMFAttributes_SetGUID(attributes, &item.key,
3431 (const GUID *)(context.buffer + item.u.subheader.offset));
3433 break;
3434 case MF_ATTRIBUTE_STRING:
3435 if (item.u.subheader.size >= sizeof(WCHAR) &&
3436 item.u.subheader.offset + item.u.subheader.size <= context.size)
3438 hr = IMFAttributes_SetString(attributes, &item.key,
3439 (const WCHAR *)(context.buffer + item.u.subheader.offset));
3441 break;
3442 case MF_ATTRIBUTE_BLOB:
3443 if (item.u.subheader.size > 0 && item.u.subheader.offset + item.u.subheader.size <= context.size)
3445 hr = IMFAttributes_SetBlob(attributes, &item.key, context.buffer + item.u.subheader.offset,
3446 item.u.subheader.size);
3448 break;
3449 default:
3453 if (FAILED(hr))
3454 break;
3457 if (SUCCEEDED(hr))
3459 IMFAttributes_DeleteAllItems(dest);
3460 hr = IMFAttributes_CopyAllItems(attributes, dest);
3463 IMFAttributes_Release(attributes);
3465 return hr;
3468 struct bytestream
3470 struct attributes attributes;
3471 IMFByteStream IMFByteStream_iface;
3472 IMFGetService IMFGetService_iface;
3473 IRtwqAsyncCallback read_callback;
3474 IRtwqAsyncCallback write_callback;
3475 IStream *stream;
3476 HANDLE hfile;
3477 QWORD position;
3478 DWORD capabilities;
3479 struct list pending;
3480 CRITICAL_SECTION cs;
3483 static inline struct bytestream *impl_from_IMFByteStream(IMFByteStream *iface)
3485 return CONTAINING_RECORD(iface, struct bytestream, IMFByteStream_iface);
3488 static struct bytestream *impl_bytestream_from_IMFGetService(IMFGetService *iface)
3490 return CONTAINING_RECORD(iface, struct bytestream, IMFGetService_iface);
3493 static struct bytestream *impl_from_read_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3495 return CONTAINING_RECORD(iface, struct bytestream, read_callback);
3498 static struct bytestream *impl_from_write_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3500 return CONTAINING_RECORD(iface, struct bytestream, write_callback);
3503 enum async_stream_op_type
3505 ASYNC_STREAM_OP_READ,
3506 ASYNC_STREAM_OP_WRITE,
3509 struct async_stream_op
3511 IUnknown IUnknown_iface;
3512 LONG refcount;
3513 union
3515 const BYTE *src;
3516 BYTE *dest;
3517 } u;
3518 QWORD position;
3519 ULONG requested_length;
3520 ULONG actual_length;
3521 IMFAsyncResult *caller;
3522 struct list entry;
3523 enum async_stream_op_type type;
3526 static struct async_stream_op *impl_async_stream_op_from_IUnknown(IUnknown *iface)
3528 return CONTAINING_RECORD(iface, struct async_stream_op, IUnknown_iface);
3531 static HRESULT WINAPI async_stream_op_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
3533 if (IsEqualIID(riid, &IID_IUnknown))
3535 *obj = iface;
3536 IUnknown_AddRef(iface);
3537 return S_OK;
3540 WARN("Unsupported %s.\n", debugstr_guid(riid));
3541 *obj = NULL;
3542 return E_NOINTERFACE;
3545 static ULONG WINAPI async_stream_op_AddRef(IUnknown *iface)
3547 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3548 ULONG refcount = InterlockedIncrement(&op->refcount);
3550 TRACE("%p, refcount %d.\n", iface, refcount);
3552 return refcount;
3555 static ULONG WINAPI async_stream_op_Release(IUnknown *iface)
3557 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3558 ULONG refcount = InterlockedDecrement(&op->refcount);
3560 TRACE("%p, refcount %d.\n", iface, refcount);
3562 if (!refcount)
3564 if (op->caller)
3565 IMFAsyncResult_Release(op->caller);
3566 free(op);
3569 return refcount;
3572 static const IUnknownVtbl async_stream_op_vtbl =
3574 async_stream_op_QueryInterface,
3575 async_stream_op_AddRef,
3576 async_stream_op_Release,
3579 static HRESULT bytestream_create_io_request(struct bytestream *stream, enum async_stream_op_type type,
3580 const BYTE *data, ULONG size, IMFAsyncCallback *callback, IUnknown *state)
3582 struct async_stream_op *op;
3583 IRtwqAsyncResult *request;
3584 HRESULT hr;
3586 op = malloc(sizeof(*op));
3587 if (!op)
3588 return E_OUTOFMEMORY;
3590 op->IUnknown_iface.lpVtbl = &async_stream_op_vtbl;
3591 op->refcount = 1;
3592 op->u.src = data;
3593 op->position = stream->position;
3594 op->requested_length = size;
3595 op->type = type;
3596 if (FAILED(hr = RtwqCreateAsyncResult((IUnknown *)&stream->IMFByteStream_iface, (IRtwqAsyncCallback *)callback, state,
3597 (IRtwqAsyncResult **)&op->caller)))
3599 goto failed;
3602 if (FAILED(hr = RtwqCreateAsyncResult(&op->IUnknown_iface, type == ASYNC_STREAM_OP_READ ? &stream->read_callback :
3603 &stream->write_callback, NULL, &request)))
3604 goto failed;
3606 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, request);
3607 IRtwqAsyncResult_Release(request);
3609 failed:
3610 IUnknown_Release(&op->IUnknown_iface);
3611 return hr;
3614 static HRESULT bytestream_complete_io_request(struct bytestream *stream, enum async_stream_op_type type,
3615 IMFAsyncResult *result, ULONG *actual_length)
3617 struct async_stream_op *op = NULL, *cur;
3618 HRESULT hr;
3620 EnterCriticalSection(&stream->cs);
3621 LIST_FOR_EACH_ENTRY(cur, &stream->pending, struct async_stream_op, entry)
3623 if (cur->caller == result && cur->type == type)
3625 op = cur;
3626 list_remove(&cur->entry);
3627 break;
3630 LeaveCriticalSection(&stream->cs);
3632 if (!op)
3633 return E_INVALIDARG;
3635 if (SUCCEEDED(hr = IMFAsyncResult_GetStatus(result)))
3636 *actual_length = op->actual_length;
3638 IUnknown_Release(&op->IUnknown_iface);
3640 return hr;
3643 static HRESULT WINAPI bytestream_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
3645 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
3646 IsEqualIID(riid, &IID_IUnknown))
3648 *obj = iface;
3649 IRtwqAsyncCallback_AddRef(iface);
3650 return S_OK;
3653 WARN("Unsupported %s.\n", debugstr_guid(riid));
3654 *obj = NULL;
3655 return E_NOINTERFACE;
3658 static ULONG WINAPI bytestream_read_callback_AddRef(IRtwqAsyncCallback *iface)
3660 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3661 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3664 static ULONG WINAPI bytestream_read_callback_Release(IRtwqAsyncCallback *iface)
3666 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3667 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3670 static HRESULT WINAPI bytestream_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
3672 return E_NOTIMPL;
3675 static ULONG WINAPI bytestream_write_callback_AddRef(IRtwqAsyncCallback *iface)
3677 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3678 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3681 static ULONG WINAPI bytestream_write_callback_Release(IRtwqAsyncCallback *iface)
3683 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3684 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3687 static HRESULT WINAPI bytestream_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
3689 struct bytestream *stream = impl_from_IMFByteStream(iface);
3691 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
3693 if (IsEqualIID(riid, &IID_IMFByteStream) ||
3694 IsEqualIID(riid, &IID_IUnknown))
3696 *out = &stream->IMFByteStream_iface;
3698 else if (IsEqualIID(riid, &IID_IMFAttributes))
3700 *out = &stream->attributes.IMFAttributes_iface;
3702 else if (stream->IMFGetService_iface.lpVtbl && IsEqualIID(riid, &IID_IMFGetService))
3704 *out = &stream->IMFGetService_iface;
3706 else
3708 WARN("Unsupported %s.\n", debugstr_guid(riid));
3709 *out = NULL;
3710 return E_NOINTERFACE;
3713 IUnknown_AddRef((IUnknown*)*out);
3714 return S_OK;
3717 static ULONG WINAPI bytestream_AddRef(IMFByteStream *iface)
3719 struct bytestream *stream = impl_from_IMFByteStream(iface);
3720 ULONG refcount = InterlockedIncrement(&stream->attributes.ref);
3722 TRACE("%p, refcount %d.\n", iface, refcount);
3724 return refcount;
3727 static ULONG WINAPI bytestream_Release(IMFByteStream *iface)
3729 struct bytestream *stream = impl_from_IMFByteStream(iface);
3730 ULONG refcount = InterlockedDecrement(&stream->attributes.ref);
3731 struct async_stream_op *cur, *cur2;
3733 TRACE("%p, refcount %d.\n", iface, refcount);
3735 if (!refcount)
3737 clear_attributes_object(&stream->attributes);
3738 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &stream->pending, struct async_stream_op, entry)
3740 list_remove(&cur->entry);
3741 IUnknown_Release(&cur->IUnknown_iface);
3743 DeleteCriticalSection(&stream->cs);
3744 if (stream->stream)
3745 IStream_Release(stream->stream);
3746 if (stream->hfile)
3747 CloseHandle(stream->hfile);
3748 free(stream);
3751 return refcount;
3754 static HRESULT WINAPI bytestream_stream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3756 struct bytestream *stream = impl_from_IMFByteStream(iface);
3757 STATSTG stat;
3758 HRESULT hr;
3760 TRACE("%p, %p.\n", iface, capabilities);
3762 if (FAILED(hr = IStream_Stat(stream->stream, &stat, STATFLAG_NONAME)))
3763 return hr;
3765 *capabilities = MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_SEEKABLE;
3766 if (stat.grfMode & (STGM_WRITE | STGM_READWRITE))
3767 *capabilities |= MFBYTESTREAM_IS_WRITABLE;
3769 return S_OK;
3772 static HRESULT WINAPI bytestream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3774 struct bytestream *stream = impl_from_IMFByteStream(iface);
3776 TRACE("%p, %p.\n", iface, capabilities);
3778 *capabilities = stream->capabilities;
3780 return S_OK;
3783 static HRESULT WINAPI bytestream_SetLength(IMFByteStream *iface, QWORD length)
3785 FIXME("%p, %s\n", iface, wine_dbgstr_longlong(length));
3787 return E_NOTIMPL;
3790 static HRESULT WINAPI bytestream_file_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
3792 struct bytestream *stream = impl_from_IMFByteStream(iface);
3794 TRACE("%p, %p.\n", iface, position);
3796 if (!position)
3797 return E_INVALIDARG;
3799 *position = stream->position;
3801 return S_OK;
3804 static HRESULT WINAPI bytestream_file_GetLength(IMFByteStream *iface, QWORD *length)
3806 struct bytestream *stream = impl_from_IMFByteStream(iface);
3807 LARGE_INTEGER li;
3809 TRACE("%p, %p.\n", iface, length);
3811 if (!length)
3812 return E_INVALIDARG;
3814 if (GetFileSizeEx(stream->hfile, &li))
3815 *length = li.QuadPart;
3816 else
3817 return HRESULT_FROM_WIN32(GetLastError());
3819 return S_OK;
3822 static HRESULT WINAPI bytestream_file_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
3824 struct bytestream *stream = impl_from_IMFByteStream(iface);
3825 LARGE_INTEGER position, length;
3826 HRESULT hr = S_OK;
3828 TRACE("%p, %p.\n", iface, ret);
3830 EnterCriticalSection(&stream->cs);
3832 position.QuadPart = 0;
3833 if (SetFilePointerEx(stream->hfile, position, &length, FILE_END))
3834 *ret = stream->position >= length.QuadPart;
3835 else
3836 hr = HRESULT_FROM_WIN32(GetLastError());
3838 LeaveCriticalSection(&stream->cs);
3840 return hr;
3843 static HRESULT WINAPI bytestream_file_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
3845 struct bytestream *stream = impl_from_IMFByteStream(iface);
3846 LARGE_INTEGER position;
3847 HRESULT hr = S_OK;
3848 BOOL ret;
3850 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, read_len);
3852 EnterCriticalSection(&stream->cs);
3854 position.QuadPart = stream->position;
3855 if ((ret = SetFilePointerEx(stream->hfile, position, NULL, FILE_BEGIN)))
3857 if ((ret = ReadFile(stream->hfile, buffer, size, read_len, NULL)))
3858 stream->position += *read_len;
3861 if (!ret)
3862 hr = HRESULT_FROM_WIN32(GetLastError());
3864 LeaveCriticalSection(&stream->cs);
3866 return hr;
3869 static HRESULT WINAPI bytestream_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size, IMFAsyncCallback *callback,
3870 IUnknown *state)
3872 struct bytestream *stream = impl_from_IMFByteStream(iface);
3874 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
3876 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_READ, data, size, callback, state);
3879 static HRESULT WINAPI bytestream_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
3881 struct bytestream *stream = impl_from_IMFByteStream(iface);
3883 TRACE("%p, %p, %p.\n", iface, result, byte_read);
3885 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_READ, result, byte_read);
3888 static HRESULT WINAPI bytestream_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
3890 FIXME("%p, %p, %u, %p\n", iface, data, count, written);
3892 return E_NOTIMPL;
3895 static HRESULT WINAPI bytestream_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
3896 IMFAsyncCallback *callback, IUnknown *state)
3898 struct bytestream *stream = impl_from_IMFByteStream(iface);
3900 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
3902 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_WRITE, data, size, callback, state);
3905 static HRESULT WINAPI bytestream_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
3907 struct bytestream *stream = impl_from_IMFByteStream(iface);
3909 TRACE("%p, %p, %p.\n", iface, result, written);
3911 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_WRITE, result, written);
3914 static HRESULT WINAPI bytestream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
3915 DWORD flags, QWORD *current)
3917 FIXME("%p, %u, %s, 0x%08x, %p\n", iface, seek, wine_dbgstr_longlong(offset), flags, current);
3919 return E_NOTIMPL;
3922 static HRESULT WINAPI bytestream_Flush(IMFByteStream *iface)
3924 FIXME("%p\n", iface);
3926 return E_NOTIMPL;
3929 static HRESULT WINAPI bytestream_Close(IMFByteStream *iface)
3931 FIXME("%p\n", iface);
3933 return E_NOTIMPL;
3936 static HRESULT WINAPI bytestream_SetCurrentPosition(IMFByteStream *iface, QWORD position)
3938 struct bytestream *stream = impl_from_IMFByteStream(iface);
3940 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
3942 EnterCriticalSection(&stream->cs);
3943 stream->position = position;
3944 LeaveCriticalSection(&stream->cs);
3946 return S_OK;
3949 static const IMFByteStreamVtbl bytestream_file_vtbl =
3951 bytestream_QueryInterface,
3952 bytestream_AddRef,
3953 bytestream_Release,
3954 bytestream_GetCapabilities,
3955 bytestream_file_GetLength,
3956 bytestream_SetLength,
3957 bytestream_file_GetCurrentPosition,
3958 bytestream_SetCurrentPosition,
3959 bytestream_file_IsEndOfStream,
3960 bytestream_file_Read,
3961 bytestream_BeginRead,
3962 bytestream_EndRead,
3963 bytestream_Write,
3964 bytestream_BeginWrite,
3965 bytestream_EndWrite,
3966 bytestream_Seek,
3967 bytestream_Flush,
3968 bytestream_Close
3971 static HRESULT WINAPI bytestream_stream_GetLength(IMFByteStream *iface, QWORD *length)
3973 struct bytestream *stream = impl_from_IMFByteStream(iface);
3974 STATSTG statstg;
3975 HRESULT hr;
3977 TRACE("%p, %p.\n", iface, length);
3979 if (FAILED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
3980 return hr;
3982 *length = statstg.cbSize.QuadPart;
3984 return S_OK;
3987 static HRESULT WINAPI bytestream_stream_SetLength(IMFByteStream *iface, QWORD length)
3989 struct bytestream *stream = impl_from_IMFByteStream(iface);
3990 ULARGE_INTEGER size;
3991 HRESULT hr;
3993 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
3995 EnterCriticalSection(&stream->cs);
3997 size.QuadPart = length;
3998 hr = IStream_SetSize(stream->stream, size);
4000 LeaveCriticalSection(&stream->cs);
4002 return hr;
4005 static HRESULT WINAPI bytestream_stream_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4007 struct bytestream *stream = impl_from_IMFByteStream(iface);
4009 TRACE("%p, %p.\n", iface, position);
4011 *position = stream->position;
4013 return S_OK;
4016 static HRESULT WINAPI bytestream_stream_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
4018 struct bytestream *stream = impl_from_IMFByteStream(iface);
4019 STATSTG statstg;
4020 HRESULT hr;
4022 TRACE("%p, %p.\n", iface, ret);
4024 EnterCriticalSection(&stream->cs);
4026 if (SUCCEEDED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4027 *ret = stream->position >= statstg.cbSize.QuadPart;
4029 LeaveCriticalSection(&stream->cs);
4031 return hr;
4034 static HRESULT WINAPI bytestream_stream_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
4036 struct bytestream *stream = impl_from_IMFByteStream(iface);
4037 LARGE_INTEGER position;
4038 HRESULT hr;
4040 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, read_len);
4042 EnterCriticalSection(&stream->cs);
4044 position.QuadPart = stream->position;
4045 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4047 if (SUCCEEDED(hr = IStream_Read(stream->stream, buffer, size, read_len)))
4048 stream->position += *read_len;
4051 LeaveCriticalSection(&stream->cs);
4053 return hr;
4056 static HRESULT WINAPI bytestream_stream_Write(IMFByteStream *iface, const BYTE *buffer, ULONG size, ULONG *written)
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, written);
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_Write(stream->stream, buffer, size, written)))
4070 stream->position += *written;
4073 LeaveCriticalSection(&stream->cs);
4075 return hr;
4078 static HRESULT WINAPI bytestream_stream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN origin, LONGLONG offset,
4079 DWORD flags, QWORD *current)
4081 struct bytestream *stream = impl_from_IMFByteStream(iface);
4082 HRESULT hr = S_OK;
4084 TRACE("%p, %u, %s, %#x, %p.\n", iface, origin, wine_dbgstr_longlong(offset), flags, current);
4086 EnterCriticalSection(&stream->cs);
4088 switch (origin)
4090 case msoBegin:
4091 stream->position = offset;
4092 break;
4093 case msoCurrent:
4094 stream->position += offset;
4095 break;
4096 default:
4097 WARN("Unknown origin mode %d.\n", origin);
4098 hr = E_INVALIDARG;
4101 *current = stream->position;
4103 LeaveCriticalSection(&stream->cs);
4105 return hr;
4108 static HRESULT WINAPI bytestream_stream_Flush(IMFByteStream *iface)
4110 struct bytestream *stream = impl_from_IMFByteStream(iface);
4112 TRACE("%p.\n", iface);
4114 return IStream_Commit(stream->stream, STGC_DEFAULT);
4117 static HRESULT WINAPI bytestream_stream_Close(IMFByteStream *iface)
4119 TRACE("%p.\n", iface);
4121 return S_OK;
4124 static const IMFByteStreamVtbl bytestream_stream_vtbl =
4126 bytestream_QueryInterface,
4127 bytestream_AddRef,
4128 bytestream_Release,
4129 bytestream_stream_GetCapabilities,
4130 bytestream_stream_GetLength,
4131 bytestream_stream_SetLength,
4132 bytestream_stream_GetCurrentPosition,
4133 bytestream_SetCurrentPosition,
4134 bytestream_stream_IsEndOfStream,
4135 bytestream_stream_Read,
4136 bytestream_BeginRead,
4137 bytestream_EndRead,
4138 bytestream_stream_Write,
4139 bytestream_BeginWrite,
4140 bytestream_EndWrite,
4141 bytestream_stream_Seek,
4142 bytestream_stream_Flush,
4143 bytestream_stream_Close,
4146 static inline struct bytestream *impl_from_IMFByteStream_IMFAttributes(IMFAttributes *iface)
4148 return CONTAINING_RECORD(iface, struct bytestream, attributes.IMFAttributes_iface);
4151 static HRESULT WINAPI bytestream_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
4153 struct bytestream *stream = impl_from_IMFByteStream_IMFAttributes(iface);
4154 return IMFByteStream_QueryInterface(&stream->IMFByteStream_iface, riid, out);
4157 static ULONG WINAPI bytestream_attributes_AddRef(IMFAttributes *iface)
4159 struct bytestream *stream = impl_from_IMFByteStream_IMFAttributes(iface);
4160 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
4163 static ULONG WINAPI bytestream_attributes_Release(IMFAttributes *iface)
4165 struct bytestream *stream = impl_from_IMFByteStream_IMFAttributes(iface);
4166 return IMFByteStream_Release(&stream->IMFByteStream_iface);
4169 static const IMFAttributesVtbl bytestream_attributes_vtbl =
4171 bytestream_attributes_QueryInterface,
4172 bytestream_attributes_AddRef,
4173 bytestream_attributes_Release,
4174 mfattributes_GetItem,
4175 mfattributes_GetItemType,
4176 mfattributes_CompareItem,
4177 mfattributes_Compare,
4178 mfattributes_GetUINT32,
4179 mfattributes_GetUINT64,
4180 mfattributes_GetDouble,
4181 mfattributes_GetGUID,
4182 mfattributes_GetStringLength,
4183 mfattributes_GetString,
4184 mfattributes_GetAllocatedString,
4185 mfattributes_GetBlobSize,
4186 mfattributes_GetBlob,
4187 mfattributes_GetAllocatedBlob,
4188 mfattributes_GetUnknown,
4189 mfattributes_SetItem,
4190 mfattributes_DeleteItem,
4191 mfattributes_DeleteAllItems,
4192 mfattributes_SetUINT32,
4193 mfattributes_SetUINT64,
4194 mfattributes_SetDouble,
4195 mfattributes_SetGUID,
4196 mfattributes_SetString,
4197 mfattributes_SetBlob,
4198 mfattributes_SetUnknown,
4199 mfattributes_LockStore,
4200 mfattributes_UnlockStore,
4201 mfattributes_GetCount,
4202 mfattributes_GetItemByIndex,
4203 mfattributes_CopyAllItems
4206 static HRESULT WINAPI bytestream_stream_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4208 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4209 struct async_stream_op *op;
4210 LARGE_INTEGER position;
4211 IUnknown *object;
4212 HRESULT hr;
4214 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4215 return hr;
4217 op = impl_async_stream_op_from_IUnknown(object);
4219 EnterCriticalSection(&stream->cs);
4221 position.QuadPart = op->position;
4222 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4224 if (SUCCEEDED(hr = IStream_Read(stream->stream, op->u.dest, op->requested_length, &op->actual_length)))
4225 stream->position += op->actual_length;
4228 IMFAsyncResult_SetStatus(op->caller, hr);
4229 list_add_tail(&stream->pending, &op->entry);
4231 LeaveCriticalSection(&stream->cs);
4233 MFInvokeCallback(op->caller);
4235 return S_OK;
4238 static HRESULT WINAPI bytestream_stream_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4240 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4241 struct async_stream_op *op;
4242 LARGE_INTEGER position;
4243 IUnknown *object;
4244 HRESULT hr;
4246 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4247 return hr;
4249 op = impl_async_stream_op_from_IUnknown(object);
4251 EnterCriticalSection(&stream->cs);
4253 position.QuadPart = op->position;
4254 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4256 if (SUCCEEDED(hr = IStream_Write(stream->stream, op->u.src, op->requested_length, &op->actual_length)))
4257 stream->position += op->actual_length;
4260 IMFAsyncResult_SetStatus(op->caller, hr);
4261 list_add_tail(&stream->pending, &op->entry);
4263 LeaveCriticalSection(&stream->cs);
4265 MFInvokeCallback(op->caller);
4267 return S_OK;
4270 static const IRtwqAsyncCallbackVtbl bytestream_stream_read_callback_vtbl =
4272 bytestream_callback_QueryInterface,
4273 bytestream_read_callback_AddRef,
4274 bytestream_read_callback_Release,
4275 bytestream_callback_GetParameters,
4276 bytestream_stream_read_callback_Invoke,
4279 static const IRtwqAsyncCallbackVtbl bytestream_stream_write_callback_vtbl =
4281 bytestream_callback_QueryInterface,
4282 bytestream_write_callback_AddRef,
4283 bytestream_write_callback_Release,
4284 bytestream_callback_GetParameters,
4285 bytestream_stream_write_callback_Invoke,
4288 /***********************************************************************
4289 * MFCreateMFByteStreamOnStream (mfplat.@)
4291 HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **bytestream)
4293 struct bytestream *object;
4294 LARGE_INTEGER position;
4295 STATSTG stat;
4296 HRESULT hr;
4298 TRACE("%p, %p.\n", stream, bytestream);
4300 if (!(object = calloc(1, sizeof(*object))))
4301 return E_OUTOFMEMORY;
4303 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
4305 free(object);
4306 return hr;
4309 object->IMFByteStream_iface.lpVtbl = &bytestream_stream_vtbl;
4310 object->attributes.IMFAttributes_iface.lpVtbl = &bytestream_attributes_vtbl;
4311 object->read_callback.lpVtbl = &bytestream_stream_read_callback_vtbl;
4312 object->write_callback.lpVtbl = &bytestream_stream_write_callback_vtbl;
4313 InitializeCriticalSection(&object->cs);
4314 list_init(&object->pending);
4316 object->stream = stream;
4317 IStream_AddRef(object->stream);
4318 position.QuadPart = 0;
4319 IStream_Seek(object->stream, position, STREAM_SEEK_SET, NULL);
4321 if (SUCCEEDED(IStream_Stat(object->stream, &stat, 0)))
4323 if (stat.pwcsName)
4325 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME,
4326 stat.pwcsName);
4327 CoTaskMemFree(stat.pwcsName);
4331 *bytestream = &object->IMFByteStream_iface;
4333 return S_OK;
4336 static HRESULT WINAPI bytestream_file_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4338 FIXME("%p, %p.\n", iface, result);
4340 return E_NOTIMPL;
4343 static HRESULT WINAPI bytestream_file_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4345 FIXME("%p, %p.\n", iface, result);
4347 return E_NOTIMPL;
4350 static const IRtwqAsyncCallbackVtbl bytestream_file_read_callback_vtbl =
4352 bytestream_callback_QueryInterface,
4353 bytestream_read_callback_AddRef,
4354 bytestream_read_callback_Release,
4355 bytestream_callback_GetParameters,
4356 bytestream_file_read_callback_Invoke,
4359 static const IRtwqAsyncCallbackVtbl bytestream_file_write_callback_vtbl =
4361 bytestream_callback_QueryInterface,
4362 bytestream_write_callback_AddRef,
4363 bytestream_write_callback_Release,
4364 bytestream_callback_GetParameters,
4365 bytestream_file_write_callback_Invoke,
4368 static HRESULT WINAPI bytestream_file_getservice_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
4370 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4371 return IMFByteStream_QueryInterface(&stream->IMFByteStream_iface, riid, obj);
4374 static ULONG WINAPI bytestream_file_getservice_AddRef(IMFGetService *iface)
4376 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4377 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
4380 static ULONG WINAPI bytestream_file_getservice_Release(IMFGetService *iface)
4382 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4383 return IMFByteStream_Release(&stream->IMFByteStream_iface);
4386 static HRESULT WINAPI bytestream_file_getservice_GetService(IMFGetService *iface, REFGUID service,
4387 REFIID riid, void **obj)
4389 FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
4391 return E_NOTIMPL;
4394 static const IMFGetServiceVtbl bytestream_file_getservice_vtbl =
4396 bytestream_file_getservice_QueryInterface,
4397 bytestream_file_getservice_AddRef,
4398 bytestream_file_getservice_Release,
4399 bytestream_file_getservice_GetService,
4402 /***********************************************************************
4403 * MFCreateFile (mfplat.@)
4405 HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4406 LPCWSTR url, IMFByteStream **bytestream)
4408 DWORD capabilities = MFBYTESTREAM_IS_SEEKABLE | MFBYTESTREAM_DOES_NOT_USE_NETWORK;
4409 DWORD filecreation_disposition = 0, fileaccessmode = 0, fileattributes = 0;
4410 DWORD filesharemode = FILE_SHARE_READ;
4411 struct bytestream *object;
4412 FILETIME writetime;
4413 HANDLE file;
4414 HRESULT hr;
4416 TRACE("%d, %d, %#x, %s, %p.\n", accessmode, openmode, flags, debugstr_w(url), bytestream);
4418 switch (accessmode)
4420 case MF_ACCESSMODE_READ:
4421 fileaccessmode = GENERIC_READ;
4422 capabilities |= MFBYTESTREAM_IS_READABLE;
4423 break;
4424 case MF_ACCESSMODE_WRITE:
4425 fileaccessmode = GENERIC_WRITE;
4426 capabilities |= MFBYTESTREAM_IS_WRITABLE;
4427 break;
4428 case MF_ACCESSMODE_READWRITE:
4429 fileaccessmode = GENERIC_READ | GENERIC_WRITE;
4430 capabilities |= (MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_WRITABLE);
4431 break;
4434 switch (openmode)
4436 case MF_OPENMODE_FAIL_IF_NOT_EXIST:
4437 filecreation_disposition = OPEN_EXISTING;
4438 break;
4439 case MF_OPENMODE_FAIL_IF_EXIST:
4440 filecreation_disposition = CREATE_NEW;
4441 break;
4442 case MF_OPENMODE_RESET_IF_EXIST:
4443 filecreation_disposition = TRUNCATE_EXISTING;
4444 break;
4445 case MF_OPENMODE_APPEND_IF_EXIST:
4446 filecreation_disposition = OPEN_ALWAYS;
4447 fileaccessmode |= FILE_APPEND_DATA;
4448 break;
4449 case MF_OPENMODE_DELETE_IF_EXIST:
4450 filecreation_disposition = CREATE_ALWAYS;
4451 break;
4454 if (flags & MF_FILEFLAGS_NOBUFFERING)
4455 fileattributes |= FILE_FLAG_NO_BUFFERING;
4457 /* Open HANDLE to file */
4458 file = CreateFileW(url, fileaccessmode, filesharemode, NULL,
4459 filecreation_disposition, fileattributes, 0);
4461 if(file == INVALID_HANDLE_VALUE)
4462 return HRESULT_FROM_WIN32(GetLastError());
4464 if (!(object = calloc(1, sizeof(*object))))
4466 CloseHandle(file);
4467 return E_OUTOFMEMORY;
4470 if (FAILED(hr = init_attributes_object(&object->attributes, 2)))
4472 CloseHandle(file);
4473 free(object);
4474 return hr;
4476 object->IMFByteStream_iface.lpVtbl = &bytestream_file_vtbl;
4477 object->attributes.IMFAttributes_iface.lpVtbl = &bytestream_attributes_vtbl;
4478 object->IMFGetService_iface.lpVtbl = &bytestream_file_getservice_vtbl;
4479 object->read_callback.lpVtbl = &bytestream_file_read_callback_vtbl;
4480 object->write_callback.lpVtbl = &bytestream_file_write_callback_vtbl;
4481 InitializeCriticalSection(&object->cs);
4482 list_init(&object->pending);
4483 object->capabilities = capabilities;
4484 object->hfile = file;
4486 if (GetFileTime(file, NULL, NULL, &writetime))
4488 IMFAttributes_SetBlob(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_LAST_MODIFIED_TIME,
4489 (const UINT8 *)&writetime, sizeof(writetime));
4492 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME, url);
4494 *bytestream = &object->IMFByteStream_iface;
4496 return S_OK;
4499 struct bytestream_wrapper
4501 IMFByteStreamCacheControl IMFByteStreamCacheControl_iface;
4502 IMFByteStreamBuffering IMFByteStreamBuffering_iface;
4503 IMFMediaEventGenerator IMFMediaEventGenerator_iface;
4504 IMFByteStreamTimeSeek IMFByteStreamTimeSeek_iface;
4505 IMFSampleOutputStream IMFSampleOutputStream_iface;
4506 IPropertyStore IPropertyStore_iface;
4507 IMFByteStream IMFByteStream_iface;
4508 IMFAttributes IMFAttributes_iface;
4509 LONG refcount;
4511 IMFByteStreamCacheControl *cache_control;
4512 IMFByteStreamBuffering *stream_buffering;
4513 IMFMediaEventGenerator *event_generator;
4514 IMFByteStreamTimeSeek *time_seek;
4515 IMFSampleOutputStream *sample_output;
4516 IPropertyStore *propstore;
4517 IMFByteStream *stream;
4518 IMFAttributes *attributes;
4519 BOOL is_closed;
4522 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStream(IMFByteStream *iface)
4524 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStream_iface);
4527 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamCacheControl(IMFByteStreamCacheControl *iface)
4529 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamCacheControl_iface);
4532 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamBuffering(IMFByteStreamBuffering *iface)
4534 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamBuffering_iface);
4537 static struct bytestream_wrapper *impl_wrapper_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
4539 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFMediaEventGenerator_iface);
4542 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamTimeSeek(IMFByteStreamTimeSeek *iface)
4544 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamTimeSeek_iface);
4547 static struct bytestream_wrapper *impl_wrapper_from_IMFSampleOutputStream(IMFSampleOutputStream *iface)
4549 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFSampleOutputStream_iface);
4552 static struct bytestream_wrapper *impl_wrapper_from_IPropertyStore(IPropertyStore *iface)
4554 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IPropertyStore_iface);
4557 static struct bytestream_wrapper *impl_wrapper_from_IMFAttributes(IMFAttributes *iface)
4559 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFAttributes_iface);
4562 static HRESULT WINAPI bytestream_wrapper_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
4564 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4566 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
4568 if (IsEqualIID(riid, &IID_IMFByteStream) ||
4569 IsEqualIID(riid, &IID_IUnknown))
4571 *out = &wrapper->IMFByteStream_iface;
4573 else if (wrapper->cache_control && IsEqualIID(riid, &IID_IMFByteStreamCacheControl))
4575 *out = &wrapper->IMFByteStreamCacheControl_iface;
4577 else if (wrapper->stream_buffering && IsEqualIID(riid, &IID_IMFByteStreamBuffering))
4579 *out = &wrapper->IMFByteStreamBuffering_iface;
4581 else if (wrapper->event_generator && IsEqualIID(riid, &IID_IMFMediaEventGenerator))
4583 *out = &wrapper->IMFMediaEventGenerator_iface;
4585 else if (wrapper->time_seek && IsEqualIID(riid, &IID_IMFByteStreamTimeSeek))
4587 *out = &wrapper->IMFByteStreamTimeSeek_iface;
4589 else if (wrapper->sample_output && IsEqualIID(riid, &IID_IMFSampleOutputStream))
4591 *out = &wrapper->IMFSampleOutputStream_iface;
4593 else if (wrapper->propstore && IsEqualIID(riid, &IID_IPropertyStore))
4595 *out = &wrapper->IPropertyStore_iface;
4597 else if (wrapper->attributes && IsEqualIID(riid, &IID_IMFAttributes))
4599 *out = &wrapper->IMFAttributes_iface;
4601 else
4603 WARN("Unsupported %s.\n", debugstr_guid(riid));
4604 *out = NULL;
4605 return E_NOINTERFACE;
4608 IUnknown_AddRef((IUnknown *)*out);
4609 return S_OK;
4612 static ULONG WINAPI bytestream_wrapper_AddRef(IMFByteStream *iface)
4614 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4615 ULONG refcount = InterlockedIncrement(&wrapper->refcount);
4617 TRACE("%p, refcount %d.\n", iface, refcount);
4619 return refcount;
4622 static ULONG WINAPI bytestream_wrapper_Release(IMFByteStream *iface)
4624 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4625 ULONG refcount = InterlockedDecrement(&wrapper->refcount);
4627 TRACE("%p, refcount %d.\n", iface, refcount);
4629 if (!refcount)
4631 if (wrapper->cache_control)
4632 IMFByteStreamCacheControl_Release(wrapper->cache_control);
4633 if (wrapper->stream_buffering)
4634 IMFByteStreamBuffering_Release(wrapper->stream_buffering);
4635 if (wrapper->event_generator)
4636 IMFMediaEventGenerator_Release(wrapper->event_generator);
4637 if (wrapper->time_seek)
4638 IMFByteStreamTimeSeek_Release(wrapper->time_seek);
4639 if (wrapper->sample_output)
4640 IMFSampleOutputStream_Release(wrapper->sample_output);
4641 if (wrapper->propstore)
4642 IPropertyStore_Release(wrapper->propstore);
4643 if (wrapper->attributes)
4644 IMFAttributes_Release(wrapper->attributes);
4645 IMFByteStream_Release(wrapper->stream);
4646 free(wrapper);
4649 return refcount;
4652 static HRESULT WINAPI bytestream_wrapper_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
4654 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4656 TRACE("%p, %p.\n", iface, capabilities);
4658 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4659 IMFByteStream_GetCapabilities(wrapper->stream, capabilities);
4662 static HRESULT WINAPI bytestream_wrapper_GetLength(IMFByteStream *iface, QWORD *length)
4664 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4666 TRACE("%p, %p.\n", iface, length);
4668 if (wrapper->is_closed)
4669 return MF_E_INVALIDREQUEST;
4671 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4672 IMFByteStream_GetLength(wrapper->stream, length);
4675 static HRESULT WINAPI bytestream_wrapper_SetLength(IMFByteStream *iface, QWORD length)
4677 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4679 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4681 if (wrapper->is_closed)
4682 return MF_E_INVALIDREQUEST;
4684 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4685 IMFByteStream_SetLength(wrapper->stream, length);
4688 static HRESULT WINAPI bytestream_wrapper_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4690 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4692 TRACE("%p, %p.\n", iface, position);
4694 if (wrapper->is_closed)
4695 return MF_E_INVALIDREQUEST;
4697 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4698 IMFByteStream_GetCurrentPosition(wrapper->stream, position);
4701 static HRESULT WINAPI bytestream_wrapper_SetCurrentPosition(IMFByteStream *iface, QWORD position)
4703 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4705 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4707 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4708 IMFByteStream_SetCurrentPosition(wrapper->stream, position);
4711 static HRESULT WINAPI bytestream_wrapper_IsEndOfStream(IMFByteStream *iface, BOOL *eos)
4713 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4715 TRACE("%p, %p.\n", iface, eos);
4717 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4718 IMFByteStream_IsEndOfStream(wrapper->stream, eos);
4721 static HRESULT WINAPI bytestream_wrapper_Read(IMFByteStream *iface, BYTE *data, ULONG count, ULONG *byte_read)
4723 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4725 TRACE("%p, %p, %u, %p.\n", iface, data, count, byte_read);
4727 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4728 IMFByteStream_Read(wrapper->stream, data, count, byte_read);
4731 static HRESULT WINAPI bytestream_wrapper_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size,
4732 IMFAsyncCallback *callback, IUnknown *state)
4734 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4736 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
4738 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4739 IMFByteStream_BeginRead(wrapper->stream, data, size, callback, state);
4742 static HRESULT WINAPI bytestream_wrapper_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
4744 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4746 TRACE("%p, %p, %p.\n", iface, result, byte_read);
4748 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4749 IMFByteStream_EndRead(wrapper->stream, result, byte_read);
4752 static HRESULT WINAPI bytestream_wrapper_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
4754 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4756 TRACE("%p, %p, %u, %p.\n", iface, data, count, written);
4758 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4759 IMFByteStream_Write(wrapper->stream, data, count, written);
4762 static HRESULT WINAPI bytestream_wrapper_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
4763 IMFAsyncCallback *callback, IUnknown *state)
4765 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4767 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
4769 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4770 IMFByteStream_BeginWrite(wrapper->stream, data, size, callback, state);
4773 static HRESULT WINAPI bytestream_wrapper_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
4775 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4777 TRACE("%p, %p, %p.\n", iface, result, written);
4779 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4780 IMFByteStream_EndWrite(wrapper->stream, result, written);
4783 static HRESULT WINAPI bytestream_wrapper_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
4784 DWORD flags, QWORD *current)
4786 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4788 TRACE("%p, %u, %s, %#x, %p.\n", iface, seek, wine_dbgstr_longlong(offset), flags, current);
4790 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4791 IMFByteStream_Seek(wrapper->stream, seek, offset, flags, current);
4794 static HRESULT WINAPI bytestream_wrapper_Flush(IMFByteStream *iface)
4796 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4798 TRACE("%p\n", iface);
4800 return wrapper->is_closed ? MF_E_INVALIDREQUEST : IMFByteStream_Flush(wrapper->stream);
4803 static HRESULT WINAPI bytestream_wrapper_Close(IMFByteStream *iface)
4805 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4807 TRACE("%p\n", iface);
4809 wrapper->is_closed = TRUE;
4811 return S_OK;
4814 static const IMFByteStreamVtbl bytestream_wrapper_vtbl =
4816 bytestream_wrapper_QueryInterface,
4817 bytestream_wrapper_AddRef,
4818 bytestream_wrapper_Release,
4819 bytestream_wrapper_GetCapabilities,
4820 bytestream_wrapper_GetLength,
4821 bytestream_wrapper_SetLength,
4822 bytestream_wrapper_GetCurrentPosition,
4823 bytestream_wrapper_SetCurrentPosition,
4824 bytestream_wrapper_IsEndOfStream,
4825 bytestream_wrapper_Read,
4826 bytestream_wrapper_BeginRead,
4827 bytestream_wrapper_EndRead,
4828 bytestream_wrapper_Write,
4829 bytestream_wrapper_BeginWrite,
4830 bytestream_wrapper_EndWrite,
4831 bytestream_wrapper_Seek,
4832 bytestream_wrapper_Flush,
4833 bytestream_wrapper_Close,
4836 static HRESULT WINAPI bytestream_wrapper_cache_control_QueryInterface(IMFByteStreamCacheControl *iface,
4837 REFIID riid, void **obj)
4839 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4840 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4843 static ULONG WINAPI bytestream_wrapper_cache_control_AddRef(IMFByteStreamCacheControl *iface)
4845 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4846 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4849 static ULONG WINAPI bytestream_wrapper_cache_control_Release(IMFByteStreamCacheControl *iface)
4851 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4852 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4855 static HRESULT WINAPI bytestream_wrapper_cache_control_StopBackgroundTransfer(IMFByteStreamCacheControl *iface)
4857 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4859 TRACE("%p.\n", iface);
4861 return IMFByteStreamCacheControl_StopBackgroundTransfer(wrapper->cache_control);
4864 static const IMFByteStreamCacheControlVtbl bytestream_wrapper_cache_control_vtbl =
4866 bytestream_wrapper_cache_control_QueryInterface,
4867 bytestream_wrapper_cache_control_AddRef,
4868 bytestream_wrapper_cache_control_Release,
4869 bytestream_wrapper_cache_control_StopBackgroundTransfer,
4872 static HRESULT WINAPI bytestream_wrapper_buffering_QueryInterface(IMFByteStreamBuffering *iface,
4873 REFIID riid, void **obj)
4875 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4876 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4879 static ULONG WINAPI bytestream_wrapper_buffering_AddRef(IMFByteStreamBuffering *iface)
4881 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4882 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4885 static ULONG WINAPI bytestream_wrapper_buffering_Release(IMFByteStreamBuffering *iface)
4887 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4888 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4891 static HRESULT WINAPI bytestream_wrapper_buffering_SetBufferingParams(IMFByteStreamBuffering *iface,
4892 MFBYTESTREAM_BUFFERING_PARAMS *params)
4894 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4896 TRACE("%p, %p.\n", iface, params);
4898 return IMFByteStreamBuffering_SetBufferingParams(wrapper->stream_buffering, params);
4901 static HRESULT WINAPI bytestream_wrapper_buffering_EnableBuffering(IMFByteStreamBuffering *iface,
4902 BOOL enable)
4904 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4906 TRACE("%p, %d.\n", iface, enable);
4908 return IMFByteStreamBuffering_EnableBuffering(wrapper->stream_buffering, enable);
4911 static HRESULT WINAPI bytestream_wrapper_buffering_StopBuffering(IMFByteStreamBuffering *iface)
4913 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4915 TRACE("%p.\n", iface);
4917 return IMFByteStreamBuffering_StopBuffering(wrapper->stream_buffering);
4920 static const IMFByteStreamBufferingVtbl bytestream_wrapper_buffering_vtbl =
4922 bytestream_wrapper_buffering_QueryInterface,
4923 bytestream_wrapper_buffering_AddRef,
4924 bytestream_wrapper_buffering_Release,
4925 bytestream_wrapper_buffering_SetBufferingParams,
4926 bytestream_wrapper_buffering_EnableBuffering,
4927 bytestream_wrapper_buffering_StopBuffering,
4930 static HRESULT WINAPI bytestream_wrapper_timeseek_QueryInterface(IMFByteStreamTimeSeek *iface,
4931 REFIID riid, void **obj)
4933 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4934 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4937 static ULONG WINAPI bytestream_wrapper_timeseek_AddRef(IMFByteStreamTimeSeek *iface)
4939 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4940 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4943 static ULONG WINAPI bytestream_wrapper_timeseek_Release(IMFByteStreamTimeSeek *iface)
4945 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4946 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4949 static HRESULT WINAPI bytestream_wrapper_timeseek_IsTimeSeekSupported(IMFByteStreamTimeSeek *iface, BOOL *result)
4951 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4953 TRACE("%p, %p.\n", iface, result);
4955 return IMFByteStreamTimeSeek_IsTimeSeekSupported(wrapper->time_seek, result);
4958 static HRESULT WINAPI bytestream_wrapper_timeseek_TimeSeek(IMFByteStreamTimeSeek *iface, QWORD position)
4960 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4962 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4964 return IMFByteStreamTimeSeek_TimeSeek(wrapper->time_seek, position);
4967 static HRESULT WINAPI bytestream_wrapper_timeseek_GetTimeSeekResult(IMFByteStreamTimeSeek *iface, QWORD *start_time,
4968 QWORD *stop_time, QWORD *duration)
4970 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4972 TRACE("%p, %p, %p, %p.\n", iface, start_time, stop_time, duration);
4974 return IMFByteStreamTimeSeek_GetTimeSeekResult(wrapper->time_seek, start_time, stop_time, duration);
4977 static const IMFByteStreamTimeSeekVtbl bytestream_wrapper_timeseek_vtbl =
4979 bytestream_wrapper_timeseek_QueryInterface,
4980 bytestream_wrapper_timeseek_AddRef,
4981 bytestream_wrapper_timeseek_Release,
4982 bytestream_wrapper_timeseek_IsTimeSeekSupported,
4983 bytestream_wrapper_timeseek_TimeSeek,
4984 bytestream_wrapper_timeseek_GetTimeSeekResult,
4987 static HRESULT WINAPI bytestream_wrapper_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
4989 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
4990 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4993 static ULONG WINAPI bytestream_wrapper_events_AddRef(IMFMediaEventGenerator *iface)
4995 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
4996 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4999 static ULONG WINAPI bytestream_wrapper_events_Release(IMFMediaEventGenerator *iface)
5001 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5002 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5005 static HRESULT WINAPI bytestream_wrapper_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
5007 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5009 TRACE("%p, %#x, %p.\n", iface, flags, event);
5011 return IMFMediaEventGenerator_GetEvent(wrapper->event_generator, flags, event);
5014 static HRESULT WINAPI bytestream_wrapper_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback, IUnknown *state)
5016 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5018 TRACE("%p, %p, %p.\n", iface, callback, state);
5020 return IMFMediaEventGenerator_BeginGetEvent(wrapper->event_generator, callback, state);
5023 static HRESULT WINAPI bytestream_wrapper_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result, IMFMediaEvent **event)
5025 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5027 TRACE("%p, %p, %p.\n", iface, result, event);
5029 return IMFMediaEventGenerator_EndGetEvent(wrapper->event_generator, result, event);
5032 static HRESULT WINAPI bytestream_wrapper_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType type,
5033 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
5035 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5037 TRACE("%p, %d, %s, %#x, %s.\n", iface, type, debugstr_guid(ext_type), hr, debugstr_propvar(value));
5039 return IMFMediaEventGenerator_QueueEvent(wrapper->event_generator, type, ext_type, hr, value);
5042 static const IMFMediaEventGeneratorVtbl bytestream_wrapper_events_vtbl =
5044 bytestream_wrapper_events_QueryInterface,
5045 bytestream_wrapper_events_AddRef,
5046 bytestream_wrapper_events_Release,
5047 bytestream_wrapper_events_GetEvent,
5048 bytestream_wrapper_events_BeginGetEvent,
5049 bytestream_wrapper_events_EndGetEvent,
5050 bytestream_wrapper_events_QueueEvent,
5053 static HRESULT WINAPI bytestream_wrapper_sample_output_QueryInterface(IMFSampleOutputStream *iface, REFIID riid, void **obj)
5055 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5056 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5059 static ULONG WINAPI bytestream_wrapper_sample_output_AddRef(IMFSampleOutputStream *iface)
5061 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5062 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5065 static ULONG WINAPI bytestream_wrapper_sample_output_Release(IMFSampleOutputStream *iface)
5067 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5068 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5071 static HRESULT WINAPI bytestream_wrapper_sample_output_BeginWriteSample(IMFSampleOutputStream *iface, IMFSample *sample,
5072 IMFAsyncCallback *callback, IUnknown *state)
5074 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5076 TRACE("%p, %p, %p, %p.\n", iface, sample, callback, state);
5078 return IMFSampleOutputStream_BeginWriteSample(wrapper->sample_output, sample, callback, state);
5081 static HRESULT WINAPI bytestream_wrapper_sample_output_EndWriteSample(IMFSampleOutputStream *iface, IMFAsyncResult *result)
5083 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5085 TRACE("%p, %p.\n", iface, result);
5087 return IMFSampleOutputStream_EndWriteSample(wrapper->sample_output, result);
5090 static HRESULT WINAPI bytestream_wrapper_sample_output_Close(IMFSampleOutputStream *iface)
5092 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5094 TRACE("%p.\n", iface);
5096 return IMFSampleOutputStream_Close(wrapper->sample_output);
5099 static const IMFSampleOutputStreamVtbl bytestream_wrapper_sample_output_vtbl =
5101 bytestream_wrapper_sample_output_QueryInterface,
5102 bytestream_wrapper_sample_output_AddRef,
5103 bytestream_wrapper_sample_output_Release,
5104 bytestream_wrapper_sample_output_BeginWriteSample,
5105 bytestream_wrapper_sample_output_EndWriteSample,
5106 bytestream_wrapper_sample_output_Close,
5109 static HRESULT WINAPI bytestream_wrapper_propstore_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
5111 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5112 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5115 static ULONG WINAPI bytestream_wrapper_propstore_AddRef(IPropertyStore *iface)
5117 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5118 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5121 static ULONG WINAPI bytestream_wrapper_propstore_Release(IPropertyStore *iface)
5123 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5124 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5127 static HRESULT WINAPI bytestream_wrapper_propstore_GetCount(IPropertyStore *iface, DWORD *count)
5129 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5131 TRACE("%p, %p.\n", iface, count);
5133 return IPropertyStore_GetCount(wrapper->propstore, count);
5136 static HRESULT WINAPI bytestream_wrapper_propstore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
5138 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5140 TRACE("%p, %u, %p.\n", iface, prop, key);
5142 return IPropertyStore_GetAt(wrapper->propstore, prop, key);
5145 static HRESULT WINAPI bytestream_wrapper_propstore_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
5147 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5149 TRACE("%p, %p, %p.\n", iface, key, value);
5151 return IPropertyStore_GetValue(wrapper->propstore, key, value);
5154 static HRESULT WINAPI bytestream_wrapper_propstore_SetValue(IPropertyStore *iface, REFPROPERTYKEY key,
5155 const PROPVARIANT *value)
5157 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5159 TRACE("%p, %p, %s.\n", iface, key, debugstr_propvar(value));
5161 return IPropertyStore_SetValue(wrapper->propstore, key, value);
5164 static HRESULT WINAPI bytestream_wrapper_propstore_Commit(IPropertyStore *iface)
5166 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5168 TRACE("%p.\n", iface);
5170 return IPropertyStore_Commit(wrapper->propstore);
5173 static const IPropertyStoreVtbl bytestream_wrapper_propstore_vtbl =
5175 bytestream_wrapper_propstore_QueryInterface,
5176 bytestream_wrapper_propstore_AddRef,
5177 bytestream_wrapper_propstore_Release,
5178 bytestream_wrapper_propstore_GetCount,
5179 bytestream_wrapper_propstore_GetAt,
5180 bytestream_wrapper_propstore_GetValue,
5181 bytestream_wrapper_propstore_SetValue,
5182 bytestream_wrapper_propstore_Commit,
5185 static HRESULT WINAPI bytestream_wrapper_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
5187 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5188 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5191 static ULONG WINAPI bytestream_wrapper_attributes_AddRef(IMFAttributes *iface)
5193 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5194 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5197 static ULONG WINAPI bytestream_wrapper_attributes_Release(IMFAttributes *iface)
5199 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5200 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5203 static HRESULT WINAPI bytestream_wrapper_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
5205 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5207 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5209 return IMFAttributes_GetItem(wrapper->attributes, key, value);
5212 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
5214 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5216 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
5218 return IMFAttributes_GetItemType(wrapper->attributes, key, type);
5221 static HRESULT WINAPI bytestream_wrapper_attributes_CompareItem(IMFAttributes *iface, REFGUID key,
5222 REFPROPVARIANT value, BOOL *result)
5224 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5226 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
5228 return IMFAttributes_CompareItem(wrapper->attributes, key, value, result);
5231 static HRESULT WINAPI bytestream_wrapper_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
5232 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
5234 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5236 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
5238 return IMFAttributes_Compare(wrapper->attributes, theirs, match_type, ret);
5241 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
5243 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5245 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5247 return IMFAttributes_GetUINT32(wrapper->attributes, key, value);
5250 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
5252 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5254 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5256 return IMFAttributes_GetUINT64(wrapper->attributes, key, value);
5259 static HRESULT WINAPI bytestream_wrapper_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
5261 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5263 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5265 return IMFAttributes_GetDouble(wrapper->attributes, key, value);
5268 static HRESULT WINAPI bytestream_wrapper_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
5270 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5272 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5274 return IMFAttributes_GetGUID(wrapper->attributes, key, value);
5277 static HRESULT WINAPI bytestream_wrapper_attributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
5279 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5281 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
5283 return IMFAttributes_GetStringLength(wrapper->attributes, key, length);
5286 static HRESULT WINAPI bytestream_wrapper_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
5287 UINT32 size, UINT32 *length)
5289 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5291 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
5293 return IMFAttributes_GetString(wrapper->attributes, key, value, size, length);
5296 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
5298 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5300 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
5302 return IMFAttributes_GetAllocatedString(wrapper->attributes, key, value, length);
5305 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
5307 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5309 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
5311 return IMFAttributes_GetBlobSize(wrapper->attributes, key, size);
5314 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
5315 UINT32 bufsize, UINT32 *blobsize)
5317 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5319 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
5321 return IMFAttributes_GetBlob(wrapper->attributes, key, buf, bufsize, blobsize);
5324 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
5326 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5328 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
5330 return IMFAttributes_GetAllocatedBlob(wrapper->attributes, key, buf, size);
5333 static HRESULT WINAPI bytestream_wrapper_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **obj)
5335 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5337 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), obj);
5339 return IMFAttributes_GetUnknown(wrapper->attributes, key, riid, obj);
5342 static HRESULT WINAPI bytestream_wrapper_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
5344 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5346 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
5348 return IMFAttributes_SetItem(wrapper->attributes, key, value);
5351 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
5353 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5355 TRACE("%p, %s.\n", iface, debugstr_attr(key));
5357 return IMFAttributes_DeleteItem(wrapper->attributes, key);
5360 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteAllItems(IMFAttributes *iface)
5362 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5364 TRACE("%p.\n", iface);
5366 return IMFAttributes_DeleteAllItems(wrapper->attributes);
5369 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
5371 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5373 TRACE("%p, %s, %d.\n", iface, debugstr_attr(key), value);
5375 return IMFAttributes_SetUINT32(wrapper->attributes, key, value);
5378 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
5380 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5382 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
5384 return IMFAttributes_SetUINT64(wrapper->attributes, key, value);
5387 static HRESULT WINAPI bytestream_wrapper_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
5389 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5391 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
5393 return IMFAttributes_SetDouble(wrapper->attributes, key, value);
5396 static HRESULT WINAPI bytestream_wrapper_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
5398 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5400 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
5402 return IMFAttributes_SetGUID(wrapper->attributes, key, value);
5405 static HRESULT WINAPI bytestream_wrapper_attributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
5407 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5409 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
5411 return IMFAttributes_SetString(wrapper->attributes, key, value);
5414 static HRESULT WINAPI bytestream_wrapper_attributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
5416 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5418 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
5420 return IMFAttributes_SetBlob(wrapper->attributes, key, buf, size);
5423 static HRESULT WINAPI bytestream_wrapper_attributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
5425 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5427 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
5429 return IMFAttributes_SetUnknown(wrapper->attributes, key, unknown);
5432 static HRESULT WINAPI bytestream_wrapper_attributes_LockStore(IMFAttributes *iface)
5434 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5436 TRACE("%p.\n", iface);
5438 return IMFAttributes_LockStore(wrapper->attributes);
5441 static HRESULT WINAPI bytestream_wrapper_attributes_UnlockStore(IMFAttributes *iface)
5443 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5445 TRACE("%p.\n", iface);
5447 return IMFAttributes_UnlockStore(wrapper->attributes);
5450 static HRESULT WINAPI bytestream_wrapper_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
5452 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5454 TRACE("%p, %p.\n", iface, count);
5456 return IMFAttributes_GetCount(wrapper->attributes, count);
5459 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
5461 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5463 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
5465 return IMFAttributes_GetItemByIndex(wrapper->attributes, index, key, value);
5468 static HRESULT WINAPI bytestream_wrapper_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
5470 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5472 TRACE("%p, %p.\n", iface, dest);
5474 return IMFAttributes_CopyAllItems(wrapper->attributes, dest);
5477 static const IMFAttributesVtbl bytestream_wrapper_attributes_vtbl =
5479 bytestream_wrapper_attributes_QueryInterface,
5480 bytestream_wrapper_attributes_AddRef,
5481 bytestream_wrapper_attributes_Release,
5482 bytestream_wrapper_attributes_GetItem,
5483 bytestream_wrapper_attributes_GetItemType,
5484 bytestream_wrapper_attributes_CompareItem,
5485 bytestream_wrapper_attributes_Compare,
5486 bytestream_wrapper_attributes_GetUINT32,
5487 bytestream_wrapper_attributes_GetUINT64,
5488 bytestream_wrapper_attributes_GetDouble,
5489 bytestream_wrapper_attributes_GetGUID,
5490 bytestream_wrapper_attributes_GetStringLength,
5491 bytestream_wrapper_attributes_GetString,
5492 bytestream_wrapper_attributes_GetAllocatedString,
5493 bytestream_wrapper_attributes_GetBlobSize,
5494 bytestream_wrapper_attributes_GetBlob,
5495 bytestream_wrapper_attributes_GetAllocatedBlob,
5496 bytestream_wrapper_attributes_GetUnknown,
5497 bytestream_wrapper_attributes_SetItem,
5498 bytestream_wrapper_attributes_DeleteItem,
5499 bytestream_wrapper_attributes_DeleteAllItems,
5500 bytestream_wrapper_attributes_SetUINT32,
5501 bytestream_wrapper_attributes_SetUINT64,
5502 bytestream_wrapper_attributes_SetDouble,
5503 bytestream_wrapper_attributes_SetGUID,
5504 bytestream_wrapper_attributes_SetString,
5505 bytestream_wrapper_attributes_SetBlob,
5506 bytestream_wrapper_attributes_SetUnknown,
5507 bytestream_wrapper_attributes_LockStore,
5508 bytestream_wrapper_attributes_UnlockStore,
5509 bytestream_wrapper_attributes_GetCount,
5510 bytestream_wrapper_attributes_GetItemByIndex,
5511 bytestream_wrapper_attributes_CopyAllItems
5514 /***********************************************************************
5515 * MFCreateMFByteStreamWrapper (mfplat.@)
5517 HRESULT WINAPI MFCreateMFByteStreamWrapper(IMFByteStream *stream, IMFByteStream **wrapper)
5519 struct bytestream_wrapper *object;
5521 TRACE("%p, %p.\n", stream, wrapper);
5523 if (!(object = calloc(1, sizeof(*object))))
5524 return E_OUTOFMEMORY;
5526 object->IMFByteStreamCacheControl_iface.lpVtbl = &bytestream_wrapper_cache_control_vtbl;
5527 object->IMFByteStreamBuffering_iface.lpVtbl = &bytestream_wrapper_buffering_vtbl;
5528 object->IMFMediaEventGenerator_iface.lpVtbl = &bytestream_wrapper_events_vtbl;
5529 object->IMFByteStreamTimeSeek_iface.lpVtbl = &bytestream_wrapper_timeseek_vtbl;
5530 object->IMFSampleOutputStream_iface.lpVtbl = &bytestream_wrapper_sample_output_vtbl;
5531 object->IMFByteStream_iface.lpVtbl = &bytestream_wrapper_vtbl;
5532 object->IPropertyStore_iface.lpVtbl = &bytestream_wrapper_propstore_vtbl;
5533 object->IMFAttributes_iface.lpVtbl = &bytestream_wrapper_attributes_vtbl;
5535 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamCacheControl, (void **)&object->cache_control);
5536 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamBuffering, (void **)&object->stream_buffering);
5537 IMFByteStream_QueryInterface(stream, &IID_IMFMediaEventGenerator, (void **)&object->event_generator);
5538 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamTimeSeek, (void **)&object->time_seek);
5539 IMFByteStream_QueryInterface(stream, &IID_IMFSampleOutputStream, (void **)&object->sample_output);
5540 IMFByteStream_QueryInterface(stream, &IID_IPropertyStore, (void **)&object->propstore);
5541 IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&object->attributes);
5543 object->stream = stream;
5544 IMFByteStream_AddRef(object->stream);
5546 object->refcount = 1;
5548 *wrapper = &object->IMFByteStream_iface;
5550 return S_OK;
5553 static HRESULT WINAPI MFPluginControl_QueryInterface(IMFPluginControl *iface, REFIID riid, void **ppv)
5555 if(IsEqualGUID(riid, &IID_IUnknown)) {
5556 TRACE("(IID_IUnknown %p)\n", ppv);
5557 *ppv = iface;
5558 }else if(IsEqualGUID(riid, &IID_IMFPluginControl)) {
5559 TRACE("(IID_IMFPluginControl %p)\n", ppv);
5560 *ppv = iface;
5561 }else {
5562 FIXME("(%s %p)\n", debugstr_guid(riid), ppv);
5563 *ppv = NULL;
5564 return E_NOINTERFACE;
5567 IUnknown_AddRef((IUnknown*)*ppv);
5568 return S_OK;
5571 static ULONG WINAPI MFPluginControl_AddRef(IMFPluginControl *iface)
5573 TRACE("\n");
5574 return 2;
5577 static ULONG WINAPI MFPluginControl_Release(IMFPluginControl *iface)
5579 TRACE("\n");
5580 return 1;
5583 static HRESULT WINAPI MFPluginControl_GetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5584 const WCHAR *selector, CLSID *clsid)
5586 FIXME("(%d %s %p)\n", plugin_type, debugstr_w(selector), clsid);
5587 return E_NOTIMPL;
5590 static HRESULT WINAPI MFPluginControl_GetPreferredClsidByIndex(IMFPluginControl *iface, DWORD plugin_type,
5591 DWORD index, WCHAR **selector, CLSID *clsid)
5593 FIXME("(%d %d %p %p)\n", plugin_type, index, selector, clsid);
5594 return E_NOTIMPL;
5597 static HRESULT WINAPI MFPluginControl_SetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5598 const WCHAR *selector, const CLSID *clsid)
5600 FIXME("(%d %s %s)\n", plugin_type, debugstr_w(selector), debugstr_guid(clsid));
5601 return E_NOTIMPL;
5604 static HRESULT WINAPI MFPluginControl_IsDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid)
5606 FIXME("(%d %s)\n", plugin_type, debugstr_guid(clsid));
5607 return E_NOTIMPL;
5610 static HRESULT WINAPI MFPluginControl_GetDisabledByIndex(IMFPluginControl *iface, DWORD plugin_type, DWORD index, CLSID *clsid)
5612 FIXME("(%d %d %p)\n", plugin_type, index, clsid);
5613 return E_NOTIMPL;
5616 static HRESULT WINAPI MFPluginControl_SetDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid, BOOL disabled)
5618 FIXME("(%d %s %x)\n", plugin_type, debugstr_guid(clsid), disabled);
5619 return E_NOTIMPL;
5622 static const IMFPluginControlVtbl MFPluginControlVtbl = {
5623 MFPluginControl_QueryInterface,
5624 MFPluginControl_AddRef,
5625 MFPluginControl_Release,
5626 MFPluginControl_GetPreferredClsid,
5627 MFPluginControl_GetPreferredClsidByIndex,
5628 MFPluginControl_SetPreferredClsid,
5629 MFPluginControl_IsDisabled,
5630 MFPluginControl_GetDisabledByIndex,
5631 MFPluginControl_SetDisabled
5634 static IMFPluginControl plugin_control = { &MFPluginControlVtbl };
5636 /***********************************************************************
5637 * MFGetPluginControl (mfplat.@)
5639 HRESULT WINAPI MFGetPluginControl(IMFPluginControl **ret)
5641 TRACE("(%p)\n", ret);
5643 *ret = &plugin_control;
5644 return S_OK;
5647 enum resolved_object_origin
5649 OBJECT_FROM_BYTESTREAM,
5650 OBJECT_FROM_URL,
5653 struct resolver_queued_result
5655 struct list entry;
5656 IUnknown *object;
5657 MF_OBJECT_TYPE obj_type;
5658 HRESULT hr;
5659 IRtwqAsyncResult *inner_result;
5660 enum resolved_object_origin origin;
5663 struct resolver_cancel_object
5665 IUnknown IUnknown_iface;
5666 LONG refcount;
5667 union
5669 IUnknown *handler;
5670 IMFByteStreamHandler *stream_handler;
5671 IMFSchemeHandler *scheme_handler;
5672 } u;
5673 IUnknown *cancel_cookie;
5674 enum resolved_object_origin origin;
5677 struct source_resolver
5679 IMFSourceResolver IMFSourceResolver_iface;
5680 LONG refcount;
5681 IRtwqAsyncCallback stream_callback;
5682 IRtwqAsyncCallback url_callback;
5683 CRITICAL_SECTION cs;
5684 struct list pending;
5687 static struct source_resolver *impl_from_IMFSourceResolver(IMFSourceResolver *iface)
5689 return CONTAINING_RECORD(iface, struct source_resolver, IMFSourceResolver_iface);
5692 static struct source_resolver *impl_from_stream_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5694 return CONTAINING_RECORD(iface, struct source_resolver, stream_callback);
5697 static struct source_resolver *impl_from_url_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5699 return CONTAINING_RECORD(iface, struct source_resolver, url_callback);
5702 static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enum resolved_object_origin origin,
5703 IRtwqAsyncResult *result)
5705 IRtwqAsyncResult *inner_result = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
5706 RTWQASYNCRESULT *data = (RTWQASYNCRESULT *)inner_result;
5707 struct resolver_queued_result *queued_result;
5708 union
5710 IUnknown *handler;
5711 IMFByteStreamHandler *stream_handler;
5712 IMFSchemeHandler *scheme_handler;
5713 } handler;
5715 if (!(queued_result = calloc(1, sizeof(*queued_result))))
5716 return E_OUTOFMEMORY;
5718 queued_result->origin = origin;
5720 IRtwqAsyncResult_GetObject(inner_result, &handler.handler);
5722 switch (origin)
5724 case OBJECT_FROM_BYTESTREAM:
5725 queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, (IMFAsyncResult *)result,
5726 &queued_result->obj_type, &queued_result->object);
5727 break;
5728 case OBJECT_FROM_URL:
5729 queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, (IMFAsyncResult *)result,
5730 &queued_result->obj_type, &queued_result->object);
5731 break;
5732 default:
5733 queued_result->hr = E_FAIL;
5736 IUnknown_Release(handler.handler);
5738 if (data->hEvent)
5740 queued_result->inner_result = inner_result;
5741 IRtwqAsyncResult_AddRef(queued_result->inner_result);
5744 /* Push resolved object type and created object, so we don't have to guess on End*() call. */
5745 EnterCriticalSection(&resolver->cs);
5746 list_add_tail(&resolver->pending, &queued_result->entry);
5747 LeaveCriticalSection(&resolver->cs);
5749 if (data->hEvent)
5750 SetEvent(data->hEvent);
5751 else
5753 IUnknown *caller_state = IRtwqAsyncResult_GetStateNoAddRef(inner_result);
5754 IRtwqAsyncResult *caller_result;
5756 if (SUCCEEDED(RtwqCreateAsyncResult(queued_result->object, data->pCallback, caller_state, &caller_result)))
5758 RtwqInvokeCallback(caller_result);
5759 IRtwqAsyncResult_Release(caller_result);
5763 return S_OK;
5766 static struct resolver_cancel_object *impl_cancel_obj_from_IUnknown(IUnknown *iface)
5768 return CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface);
5771 static HRESULT WINAPI resolver_cancel_object_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
5773 if (IsEqualIID(riid, &IID_IUnknown))
5775 *obj = iface;
5776 IUnknown_AddRef(iface);
5777 return S_OK;
5780 *obj = NULL;
5781 return E_NOINTERFACE;
5784 static ULONG WINAPI resolver_cancel_object_AddRef(IUnknown *iface)
5786 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5787 return InterlockedIncrement(&object->refcount);
5790 static ULONG WINAPI resolver_cancel_object_Release(IUnknown *iface)
5792 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5793 ULONG refcount = InterlockedDecrement(&object->refcount);
5795 if (!refcount)
5797 if (object->cancel_cookie)
5798 IUnknown_Release(object->cancel_cookie);
5799 IUnknown_Release(object->u.handler);
5800 free(object);
5803 return refcount;
5806 static const IUnknownVtbl resolver_cancel_object_vtbl =
5808 resolver_cancel_object_QueryInterface,
5809 resolver_cancel_object_AddRef,
5810 resolver_cancel_object_Release,
5813 static struct resolver_cancel_object *unsafe_impl_cancel_obj_from_IUnknown(IUnknown *iface)
5815 if (!iface)
5816 return NULL;
5818 return (iface->lpVtbl == &resolver_cancel_object_vtbl) ?
5819 CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface) : NULL;
5822 static HRESULT resolver_create_cancel_object(IUnknown *handler, enum resolved_object_origin origin,
5823 IUnknown *cancel_cookie, IUnknown **cancel_object)
5825 struct resolver_cancel_object *object;
5827 if (!(object = calloc(1, sizeof(*object))))
5828 return E_OUTOFMEMORY;
5830 object->IUnknown_iface.lpVtbl = &resolver_cancel_object_vtbl;
5831 object->refcount = 1;
5832 object->u.handler = handler;
5833 IUnknown_AddRef(object->u.handler);
5834 object->cancel_cookie = cancel_cookie;
5835 IUnknown_AddRef(object->cancel_cookie);
5836 object->origin = origin;
5838 *cancel_object = &object->IUnknown_iface;
5840 return S_OK;
5843 static HRESULT WINAPI source_resolver_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
5845 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
5846 IsEqualIID(riid, &IID_IUnknown))
5848 *obj = iface;
5849 IRtwqAsyncCallback_AddRef(iface);
5850 return S_OK;
5853 *obj = NULL;
5854 return E_NOINTERFACE;
5857 static ULONG WINAPI source_resolver_callback_stream_AddRef(IRtwqAsyncCallback *iface)
5859 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5860 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
5863 static ULONG WINAPI source_resolver_callback_stream_Release(IRtwqAsyncCallback *iface)
5865 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5866 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
5869 static HRESULT WINAPI source_resolver_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
5871 return E_NOTIMPL;
5874 static HRESULT WINAPI source_resolver_callback_stream_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
5876 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5878 return resolver_handler_end_create(resolver, OBJECT_FROM_BYTESTREAM, result);
5881 static const IRtwqAsyncCallbackVtbl source_resolver_callback_stream_vtbl =
5883 source_resolver_callback_QueryInterface,
5884 source_resolver_callback_stream_AddRef,
5885 source_resolver_callback_stream_Release,
5886 source_resolver_callback_GetParameters,
5887 source_resolver_callback_stream_Invoke,
5890 static ULONG WINAPI source_resolver_callback_url_AddRef(IRtwqAsyncCallback *iface)
5892 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5893 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
5896 static ULONG WINAPI source_resolver_callback_url_Release(IRtwqAsyncCallback *iface)
5898 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5899 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
5902 static HRESULT WINAPI source_resolver_callback_url_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
5904 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5906 return resolver_handler_end_create(resolver, OBJECT_FROM_URL, result);
5909 static const IRtwqAsyncCallbackVtbl source_resolver_callback_url_vtbl =
5911 source_resolver_callback_QueryInterface,
5912 source_resolver_callback_url_AddRef,
5913 source_resolver_callback_url_Release,
5914 source_resolver_callback_GetParameters,
5915 source_resolver_callback_url_Invoke,
5918 static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void **handler)
5920 unsigned int j = 0, name_length, type;
5921 HRESULT hr = E_FAIL;
5922 WCHAR clsidW[39];
5923 CLSID clsid;
5925 name_length = ARRAY_SIZE(clsidW);
5926 while (!RegEnumValueW(hkey, j++, clsidW, &name_length, NULL, &type, NULL, NULL))
5928 if (type == REG_SZ)
5930 if (SUCCEEDED(CLSIDFromString(clsidW, &clsid)))
5932 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, riid, handler);
5933 if (SUCCEEDED(hr))
5934 break;
5938 name_length = ARRAY_SIZE(clsidW);
5941 return hr;
5944 static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags,
5945 IMFByteStreamHandler **handler)
5947 static const char streamhandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers";
5948 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
5949 IMFAttributes *attributes;
5950 const WCHAR *url_ext;
5951 WCHAR *mimeW = NULL;
5952 HRESULT hr = E_FAIL;
5953 unsigned int i, j;
5954 UINT32 length;
5956 *handler = NULL;
5958 /* MIME type */
5959 if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
5961 IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length);
5962 IMFAttributes_Release(attributes);
5965 /* Extension */
5966 url_ext = url ? wcsrchr(url, '.') : NULL;
5968 if (!url_ext && !mimeW)
5970 CoTaskMemFree(mimeW);
5971 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
5974 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
5976 struct local_handler *local_handler;
5978 EnterCriticalSection(&local_handlers_section);
5980 LIST_FOR_EACH_ENTRY(local_handler, &local_bytestream_handlers, struct local_handler, entry)
5982 if ((mimeW && !lstrcmpiW(mimeW, local_handler->u.bytestream.mime))
5983 || (url_ext && !lstrcmpiW(url_ext, local_handler->u.bytestream.extension)))
5985 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFByteStreamHandler,
5986 (void **)handler)))
5987 break;
5991 LeaveCriticalSection(&local_handlers_section);
5993 if (*handler)
5994 return hr;
5997 for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i)
5999 const WCHAR *namesW[2] = { mimeW, url_ext };
6000 HKEY hkey, hkey_handler;
6002 if (RegOpenKeyA(hkey_roots[i], streamhandlerspath, &hkey))
6003 continue;
6005 for (j = 0; j < ARRAY_SIZE(namesW); ++j)
6007 if (!namesW[j])
6008 continue;
6010 if (!RegOpenKeyW(hkey, namesW[j], &hkey_handler))
6012 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFByteStreamHandler, (void **)handler);
6013 RegCloseKey(hkey_handler);
6016 if (SUCCEEDED(hr))
6017 break;
6020 RegCloseKey(hkey);
6022 if (SUCCEEDED(hr))
6023 break;
6026 if (FAILED(hr))
6028 static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
6029 hr = CoCreateInstance(&CLSID_GStreamerByteStreamHandler, NULL, CLSCTX_INPROC_SERVER, &IID_IMFByteStreamHandler, (void **)handler);
6032 CoTaskMemFree(mimeW);
6033 return hr;
6036 static HRESULT resolver_create_scheme_handler(const WCHAR *scheme, DWORD flags, IMFSchemeHandler **handler)
6038 static const char schemehandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers";
6039 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6040 HRESULT hr = MF_E_UNSUPPORTED_SCHEME;
6041 unsigned int i;
6043 TRACE("%s, %#x, %p.\n", debugstr_w(scheme), flags, handler);
6045 *handler = NULL;
6047 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6049 struct local_handler *local_handler;
6051 EnterCriticalSection(&local_handlers_section);
6053 LIST_FOR_EACH_ENTRY(local_handler, &local_scheme_handlers, struct local_handler, entry)
6055 if (!lstrcmpiW(scheme, local_handler->u.scheme))
6057 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFSchemeHandler,
6058 (void **)handler)))
6059 break;
6063 LeaveCriticalSection(&local_handlers_section);
6065 if (*handler)
6066 return hr;
6069 for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
6071 HKEY hkey, hkey_handler;
6073 hr = MF_E_UNSUPPORTED_SCHEME;
6075 if (RegOpenKeyA(hkey_roots[i], schemehandlerspath, &hkey))
6076 continue;
6078 if (!RegOpenKeyW(hkey, scheme, &hkey_handler))
6080 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFSchemeHandler, (void **)handler);
6081 RegCloseKey(hkey_handler);
6084 RegCloseKey(hkey);
6086 if (SUCCEEDED(hr))
6087 break;
6090 return hr;
6093 static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSchemeHandler **handler)
6095 static const WCHAR fileschemeW[] = L"file:";
6096 const WCHAR *ptr = url;
6097 unsigned int len;
6098 WCHAR *scheme;
6099 HRESULT hr;
6101 /* RFC 3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
6102 while (*ptr)
6104 WCHAR ch = towlower(*ptr);
6106 if (*ptr == '*' && ptr == url)
6108 ptr++;
6109 break;
6111 else if (!(*ptr >= '0' && *ptr <= '9') &&
6112 !(ch >= 'a' && ch <= 'z') &&
6113 *ptr != '+' && *ptr != '-' && *ptr != '.')
6115 break;
6118 ptr++;
6121 /* Schemes must end with a ':', if not found try "file:" */
6122 if (ptr == url || *ptr != ':')
6124 url = fileschemeW;
6125 ptr = fileschemeW + ARRAY_SIZE(fileschemeW) - 1;
6128 len = ptr - url;
6129 scheme = malloc((len + 1) * sizeof(WCHAR));
6130 if (!scheme)
6131 return E_OUTOFMEMORY;
6133 memcpy(scheme, url, len * sizeof(WCHAR));
6134 scheme[len] = 0;
6136 hr = resolver_create_scheme_handler(scheme, flags, handler);
6137 if (FAILED(hr) && url != fileschemeW)
6138 hr = resolver_create_scheme_handler(fileschemeW, flags, handler);
6140 free(scheme);
6142 return hr;
6145 static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum resolved_object_origin origin,
6146 IRtwqAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out)
6148 struct resolver_queued_result *queued_result = NULL, *iter;
6149 IUnknown *object;
6150 HRESULT hr;
6152 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
6153 return hr;
6155 EnterCriticalSection(&resolver->cs);
6157 LIST_FOR_EACH_ENTRY(iter, &resolver->pending, struct resolver_queued_result, entry)
6159 if (iter->inner_result == result || (iter->object == object && iter->origin == origin))
6161 list_remove(&iter->entry);
6162 queued_result = iter;
6163 break;
6167 LeaveCriticalSection(&resolver->cs);
6169 IUnknown_Release(object);
6171 if (queued_result)
6173 *out = queued_result->object;
6174 *obj_type = queued_result->obj_type;
6175 hr = queued_result->hr;
6176 if (queued_result->inner_result)
6177 IRtwqAsyncResult_Release(queued_result->inner_result);
6178 free(queued_result);
6180 else
6181 hr = E_UNEXPECTED;
6183 return hr;
6186 static HRESULT WINAPI source_resolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj)
6188 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6190 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
6192 if (IsEqualIID(riid, &IID_IMFSourceResolver) ||
6193 IsEqualIID(riid, &IID_IUnknown))
6195 *obj = &resolver->IMFSourceResolver_iface;
6197 else
6199 *obj = NULL;
6200 FIXME("unsupported interface %s\n", debugstr_guid(riid));
6201 return E_NOINTERFACE;
6204 IUnknown_AddRef((IUnknown *)*obj);
6205 return S_OK;
6208 static ULONG WINAPI source_resolver_AddRef(IMFSourceResolver *iface)
6210 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6211 ULONG refcount = InterlockedIncrement(&resolver->refcount);
6213 TRACE("%p, refcount %d.\n", iface, refcount);
6215 return refcount;
6218 static ULONG WINAPI source_resolver_Release(IMFSourceResolver *iface)
6220 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6221 ULONG refcount = InterlockedDecrement(&resolver->refcount);
6222 struct resolver_queued_result *result, *result2;
6224 TRACE("%p, refcount %d.\n", iface, refcount);
6226 if (!refcount)
6228 LIST_FOR_EACH_ENTRY_SAFE(result, result2, &resolver->pending, struct resolver_queued_result, entry)
6230 if (result->object)
6231 IUnknown_Release(result->object);
6232 list_remove(&result->entry);
6233 free(result);
6235 DeleteCriticalSection(&resolver->cs);
6236 free(resolver);
6239 return refcount;
6242 static HRESULT WINAPI source_resolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6243 DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6245 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6246 IMFSchemeHandler *handler;
6247 IRtwqAsyncResult *result;
6248 RTWQASYNCRESULT *data;
6249 HRESULT hr;
6251 TRACE("%p, %s, %#x, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, obj_type, object);
6253 if (!url || !obj_type || !object)
6254 return E_POINTER;
6256 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6257 return hr;
6259 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6260 IMFSchemeHandler_Release(handler);
6261 if (FAILED(hr))
6262 return hr;
6264 data = (RTWQASYNCRESULT *)result;
6265 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6267 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, NULL, (IMFAsyncCallback *)&resolver->url_callback,
6268 (IUnknown *)result);
6269 if (FAILED(hr))
6271 IRtwqAsyncResult_Release(result);
6272 return hr;
6275 WaitForSingleObject(data->hEvent, INFINITE);
6277 hr = resolver_end_create_object(resolver, OBJECT_FROM_URL, result, obj_type, object);
6278 IRtwqAsyncResult_Release(result);
6280 return hr;
6283 static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6284 const WCHAR *url, DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6286 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6287 IMFByteStreamHandler *handler;
6288 IRtwqAsyncResult *result;
6289 RTWQASYNCRESULT *data;
6290 HRESULT hr;
6292 TRACE("%p, %p, %s, %#x, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, obj_type, object);
6294 if (!stream || !obj_type || !object)
6295 return E_POINTER;
6297 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6298 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6300 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6301 IMFByteStreamHandler_Release(handler);
6302 if (FAILED(hr))
6303 return hr;
6305 data = (RTWQASYNCRESULT *)result;
6306 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6308 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props, NULL,
6309 (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6310 if (FAILED(hr))
6312 IRtwqAsyncResult_Release(result);
6313 return hr;
6316 WaitForSingleObject(data->hEvent, INFINITE);
6318 hr = resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, result, obj_type, object);
6319 IRtwqAsyncResult_Release(result);
6321 return hr;
6324 static HRESULT WINAPI source_resolver_BeginCreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6325 DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
6327 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6328 IMFSchemeHandler *handler;
6329 IUnknown *inner_cookie = NULL;
6330 IRtwqAsyncResult *result;
6331 HRESULT hr;
6333 TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
6335 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6336 return hr;
6338 if (cancel_cookie)
6339 *cancel_cookie = NULL;
6341 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6342 IMFSchemeHandler_Release(handler);
6343 if (FAILED(hr))
6344 return hr;
6346 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, cancel_cookie ? &inner_cookie : NULL,
6347 (IMFAsyncCallback *)&resolver->url_callback, (IUnknown *)result);
6349 if (SUCCEEDED(hr) && inner_cookie)
6350 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_URL, inner_cookie, cancel_cookie);
6352 IRtwqAsyncResult_Release(result);
6354 return hr;
6357 static HRESULT WINAPI source_resolver_EndCreateObjectFromURL(IMFSourceResolver *iface, IMFAsyncResult *result,
6358 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6360 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6362 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6364 return resolver_end_create_object(resolver, OBJECT_FROM_URL, (IRtwqAsyncResult *)result, obj_type, object);
6367 static HRESULT WINAPI source_resolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6368 const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback,
6369 IUnknown *state)
6371 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6372 IMFByteStreamHandler *handler;
6373 IUnknown *inner_cookie = NULL;
6374 IRtwqAsyncResult *result;
6375 HRESULT hr;
6377 TRACE("%p, %p, %s, %#x, %p, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, cancel_cookie,
6378 callback, state);
6380 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6381 return hr;
6383 if (cancel_cookie)
6384 *cancel_cookie = NULL;
6386 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6387 IMFByteStreamHandler_Release(handler);
6388 if (FAILED(hr))
6389 return hr;
6391 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props,
6392 cancel_cookie ? &inner_cookie : NULL, (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6394 /* Cancel object wraps underlying handler cancel cookie with context necessary to call CancelObjectCreate(). */
6395 if (SUCCEEDED(hr) && inner_cookie)
6396 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_BYTESTREAM, inner_cookie, cancel_cookie);
6398 IRtwqAsyncResult_Release(result);
6400 return hr;
6403 static HRESULT WINAPI source_resolver_EndCreateObjectFromByteStream(IMFSourceResolver *iface, IMFAsyncResult *result,
6404 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6406 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6408 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6410 return resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, (IRtwqAsyncResult *)result, obj_type, object);
6413 static HRESULT WINAPI source_resolver_CancelObjectCreation(IMFSourceResolver *iface, IUnknown *cancel_cookie)
6415 struct resolver_cancel_object *object;
6416 HRESULT hr;
6418 TRACE("%p, %p.\n", iface, cancel_cookie);
6420 if (!(object = unsafe_impl_cancel_obj_from_IUnknown(cancel_cookie)))
6421 return E_UNEXPECTED;
6423 switch (object->origin)
6425 case OBJECT_FROM_BYTESTREAM:
6426 hr = IMFByteStreamHandler_CancelObjectCreation(object->u.stream_handler, object->cancel_cookie);
6427 break;
6428 case OBJECT_FROM_URL:
6429 hr = IMFSchemeHandler_CancelObjectCreation(object->u.scheme_handler, object->cancel_cookie);
6430 break;
6431 default:
6432 hr = E_UNEXPECTED;
6435 return hr;
6438 static const IMFSourceResolverVtbl mfsourceresolvervtbl =
6440 source_resolver_QueryInterface,
6441 source_resolver_AddRef,
6442 source_resolver_Release,
6443 source_resolver_CreateObjectFromURL,
6444 source_resolver_CreateObjectFromByteStream,
6445 source_resolver_BeginCreateObjectFromURL,
6446 source_resolver_EndCreateObjectFromURL,
6447 source_resolver_BeginCreateObjectFromByteStream,
6448 source_resolver_EndCreateObjectFromByteStream,
6449 source_resolver_CancelObjectCreation,
6452 /***********************************************************************
6453 * MFCreateSourceResolver (mfplat.@)
6455 HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver)
6457 struct source_resolver *object;
6459 TRACE("%p\n", resolver);
6461 if (!resolver)
6462 return E_POINTER;
6464 if (!(object = calloc(1, sizeof(*object))))
6465 return E_OUTOFMEMORY;
6467 object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl;
6468 object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl;
6469 object->url_callback.lpVtbl = &source_resolver_callback_url_vtbl;
6470 object->refcount = 1;
6471 list_init(&object->pending);
6472 InitializeCriticalSection(&object->cs);
6474 *resolver = &object->IMFSourceResolver_iface;
6476 return S_OK;
6479 struct media_event
6481 struct attributes attributes;
6482 IMFMediaEvent IMFMediaEvent_iface;
6484 MediaEventType type;
6485 GUID extended_type;
6486 HRESULT status;
6487 PROPVARIANT value;
6490 static inline struct media_event *impl_from_IMFMediaEvent(IMFMediaEvent *iface)
6492 return CONTAINING_RECORD(iface, struct media_event, IMFMediaEvent_iface);
6495 static HRESULT WINAPI mfmediaevent_QueryInterface(IMFMediaEvent *iface, REFIID riid, void **out)
6497 struct media_event *event = impl_from_IMFMediaEvent(iface);
6499 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
6501 if(IsEqualGUID(riid, &IID_IUnknown) ||
6502 IsEqualGUID(riid, &IID_IMFAttributes) ||
6503 IsEqualGUID(riid, &IID_IMFMediaEvent))
6505 *out = &event->IMFMediaEvent_iface;
6507 else
6509 FIXME("%s, %p.\n", debugstr_guid(riid), out);
6510 *out = NULL;
6511 return E_NOINTERFACE;
6514 IUnknown_AddRef((IUnknown*)*out);
6515 return S_OK;
6518 static ULONG WINAPI mfmediaevent_AddRef(IMFMediaEvent *iface)
6520 struct media_event *event = impl_from_IMFMediaEvent(iface);
6521 ULONG refcount = InterlockedIncrement(&event->attributes.ref);
6523 TRACE("%p, refcount %u.\n", iface, refcount);
6525 return refcount;
6528 static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface)
6530 struct media_event *event = impl_from_IMFMediaEvent(iface);
6531 ULONG refcount = InterlockedDecrement(&event->attributes.ref);
6533 TRACE("%p, refcount %u.\n", iface, refcount);
6535 if (!refcount)
6537 clear_attributes_object(&event->attributes);
6538 PropVariantClear(&event->value);
6539 free(event);
6542 return refcount;
6545 static HRESULT WINAPI mfmediaevent_GetItem(IMFMediaEvent *iface, REFGUID key, PROPVARIANT *value)
6547 struct media_event *event = impl_from_IMFMediaEvent(iface);
6549 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6551 return attributes_GetItem(&event->attributes, key, value);
6554 static HRESULT WINAPI mfmediaevent_GetItemType(IMFMediaEvent *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
6556 struct media_event *event = impl_from_IMFMediaEvent(iface);
6558 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
6560 return attributes_GetItemType(&event->attributes, key, type);
6563 static HRESULT WINAPI mfmediaevent_CompareItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
6565 struct media_event *event = impl_from_IMFMediaEvent(iface);
6567 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
6569 return attributes_CompareItem(&event->attributes, key, value, result);
6572 static HRESULT WINAPI mfmediaevent_Compare(IMFMediaEvent *iface, IMFAttributes *attrs, MF_ATTRIBUTES_MATCH_TYPE type,
6573 BOOL *result)
6575 struct media_event *event = impl_from_IMFMediaEvent(iface);
6577 TRACE("%p, %p, %d, %p.\n", iface, attrs, type, result);
6579 return attributes_Compare(&event->attributes, attrs, type, result);
6582 static HRESULT WINAPI mfmediaevent_GetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 *value)
6584 struct media_event *event = impl_from_IMFMediaEvent(iface);
6586 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6588 return attributes_GetUINT32(&event->attributes, key, value);
6591 static HRESULT WINAPI mfmediaevent_GetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 *value)
6593 struct media_event *event = impl_from_IMFMediaEvent(iface);
6595 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6597 return attributes_GetUINT64(&event->attributes, key, value);
6600 static HRESULT WINAPI mfmediaevent_GetDouble(IMFMediaEvent *iface, REFGUID key, double *value)
6602 struct media_event *event = impl_from_IMFMediaEvent(iface);
6604 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6606 return attributes_GetDouble(&event->attributes, key, value);
6609 static HRESULT WINAPI mfmediaevent_GetGUID(IMFMediaEvent *iface, REFGUID key, GUID *value)
6611 struct media_event *event = impl_from_IMFMediaEvent(iface);
6613 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6615 return attributes_GetGUID(&event->attributes, key, value);
6618 static HRESULT WINAPI mfmediaevent_GetStringLength(IMFMediaEvent *iface, REFGUID key, UINT32 *length)
6620 struct media_event *event = impl_from_IMFMediaEvent(iface);
6622 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
6624 return attributes_GetStringLength(&event->attributes, key, length);
6627 static HRESULT WINAPI mfmediaevent_GetString(IMFMediaEvent *iface, REFGUID key, WCHAR *value,
6628 UINT32 size, UINT32 *length)
6630 struct media_event *event = impl_from_IMFMediaEvent(iface);
6632 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), value, size, length);
6634 return attributes_GetString(&event->attributes, key, value, size, length);
6637 static HRESULT WINAPI mfmediaevent_GetAllocatedString(IMFMediaEvent *iface, REFGUID key,
6638 WCHAR **value, UINT32 *length)
6640 struct media_event *event = impl_from_IMFMediaEvent(iface);
6642 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
6644 return attributes_GetAllocatedString(&event->attributes, key, value, length);
6647 static HRESULT WINAPI mfmediaevent_GetBlobSize(IMFMediaEvent *iface, REFGUID key, UINT32 *size)
6649 struct media_event *event = impl_from_IMFMediaEvent(iface);
6651 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
6653 return attributes_GetBlobSize(&event->attributes, key, size);
6656 static HRESULT WINAPI mfmediaevent_GetBlob(IMFMediaEvent *iface, REFGUID key, UINT8 *buf,
6657 UINT32 bufsize, UINT32 *blobsize)
6659 struct media_event *event = impl_from_IMFMediaEvent(iface);
6661 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
6663 return attributes_GetBlob(&event->attributes, key, buf, bufsize, blobsize);
6666 static HRESULT WINAPI mfmediaevent_GetAllocatedBlob(IMFMediaEvent *iface, REFGUID key, UINT8 **buf, UINT32 *size)
6668 struct media_event *event = impl_from_IMFMediaEvent(iface);
6670 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
6672 return attributes_GetAllocatedBlob(&event->attributes, key, buf, size);
6675 static HRESULT WINAPI mfmediaevent_GetUnknown(IMFMediaEvent *iface, REFGUID key, REFIID riid, void **out)
6677 struct media_event *event = impl_from_IMFMediaEvent(iface);
6679 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
6681 return attributes_GetUnknown(&event->attributes, key, riid, out);
6684 static HRESULT WINAPI mfmediaevent_SetItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value)
6686 struct media_event *event = impl_from_IMFMediaEvent(iface);
6688 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
6690 return attributes_SetItem(&event->attributes, key, value);
6693 static HRESULT WINAPI mfmediaevent_DeleteItem(IMFMediaEvent *iface, REFGUID key)
6695 struct media_event *event = impl_from_IMFMediaEvent(iface);
6697 TRACE("%p, %s.\n", iface, debugstr_attr(key));
6699 return attributes_DeleteItem(&event->attributes, key);
6702 static HRESULT WINAPI mfmediaevent_DeleteAllItems(IMFMediaEvent *iface)
6704 struct media_event *event = impl_from_IMFMediaEvent(iface);
6706 TRACE("%p.\n", iface);
6708 return attributes_DeleteAllItems(&event->attributes);
6711 static HRESULT WINAPI mfmediaevent_SetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 value)
6713 struct media_event *event = impl_from_IMFMediaEvent(iface);
6715 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
6717 return attributes_SetUINT32(&event->attributes, key, value);
6720 static HRESULT WINAPI mfmediaevent_SetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 value)
6722 struct media_event *event = impl_from_IMFMediaEvent(iface);
6724 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
6726 return attributes_SetUINT64(&event->attributes, key, value);
6729 static HRESULT WINAPI mfmediaevent_SetDouble(IMFMediaEvent *iface, REFGUID key, double value)
6731 struct media_event *event = impl_from_IMFMediaEvent(iface);
6733 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
6735 return attributes_SetDouble(&event->attributes, key, value);
6738 static HRESULT WINAPI mfmediaevent_SetGUID(IMFMediaEvent *iface, REFGUID key, REFGUID value)
6740 struct media_event *event = impl_from_IMFMediaEvent(iface);
6742 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
6744 return attributes_SetGUID(&event->attributes, key, value);
6747 static HRESULT WINAPI mfmediaevent_SetString(IMFMediaEvent *iface, REFGUID key, const WCHAR *value)
6749 struct media_event *event = impl_from_IMFMediaEvent(iface);
6751 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
6753 return attributes_SetString(&event->attributes, key, value);
6756 static HRESULT WINAPI mfmediaevent_SetBlob(IMFMediaEvent *iface, REFGUID key, const UINT8 *buf, UINT32 size)
6758 struct media_event *event = impl_from_IMFMediaEvent(iface);
6760 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
6762 return attributes_SetBlob(&event->attributes, key, buf, size);
6765 static HRESULT WINAPI mfmediaevent_SetUnknown(IMFMediaEvent *iface, REFGUID key, IUnknown *unknown)
6767 struct media_event *event = impl_from_IMFMediaEvent(iface);
6769 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
6771 return attributes_SetUnknown(&event->attributes, key, unknown);
6774 static HRESULT WINAPI mfmediaevent_LockStore(IMFMediaEvent *iface)
6776 struct media_event *event = impl_from_IMFMediaEvent(iface);
6778 TRACE("%p.\n", iface);
6780 return attributes_LockStore(&event->attributes);
6783 static HRESULT WINAPI mfmediaevent_UnlockStore(IMFMediaEvent *iface)
6785 struct media_event *event = impl_from_IMFMediaEvent(iface);
6787 TRACE("%p.\n", iface);
6789 return attributes_UnlockStore(&event->attributes);
6792 static HRESULT WINAPI mfmediaevent_GetCount(IMFMediaEvent *iface, UINT32 *count)
6794 struct media_event *event = impl_from_IMFMediaEvent(iface);
6796 TRACE("%p, %p.\n", iface, count);
6798 return attributes_GetCount(&event->attributes, count);
6801 static HRESULT WINAPI mfmediaevent_GetItemByIndex(IMFMediaEvent *iface, UINT32 index, GUID *key, PROPVARIANT *value)
6803 struct media_event *event = impl_from_IMFMediaEvent(iface);
6805 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
6807 return attributes_GetItemByIndex(&event->attributes, index, key, value);
6810 static HRESULT WINAPI mfmediaevent_CopyAllItems(IMFMediaEvent *iface, IMFAttributes *dest)
6812 struct media_event *event = impl_from_IMFMediaEvent(iface);
6814 TRACE("%p, %p.\n", iface, dest);
6816 return attributes_CopyAllItems(&event->attributes, dest);
6819 static HRESULT WINAPI mfmediaevent_GetType(IMFMediaEvent *iface, MediaEventType *type)
6821 struct media_event *event = impl_from_IMFMediaEvent(iface);
6823 TRACE("%p, %p.\n", iface, type);
6825 *type = event->type;
6827 return S_OK;
6830 static HRESULT WINAPI mfmediaevent_GetExtendedType(IMFMediaEvent *iface, GUID *extended_type)
6832 struct media_event *event = impl_from_IMFMediaEvent(iface);
6834 TRACE("%p, %p.\n", iface, extended_type);
6836 *extended_type = event->extended_type;
6838 return S_OK;
6841 static HRESULT WINAPI mfmediaevent_GetStatus(IMFMediaEvent *iface, HRESULT *status)
6843 struct media_event *event = impl_from_IMFMediaEvent(iface);
6845 TRACE("%p, %p.\n", iface, status);
6847 *status = event->status;
6849 return S_OK;
6852 static HRESULT WINAPI mfmediaevent_GetValue(IMFMediaEvent *iface, PROPVARIANT *value)
6854 struct media_event *event = impl_from_IMFMediaEvent(iface);
6856 TRACE("%p, %p.\n", iface, value);
6858 PropVariantCopy(value, &event->value);
6860 return S_OK;
6863 static const IMFMediaEventVtbl mfmediaevent_vtbl =
6865 mfmediaevent_QueryInterface,
6866 mfmediaevent_AddRef,
6867 mfmediaevent_Release,
6868 mfmediaevent_GetItem,
6869 mfmediaevent_GetItemType,
6870 mfmediaevent_CompareItem,
6871 mfmediaevent_Compare,
6872 mfmediaevent_GetUINT32,
6873 mfmediaevent_GetUINT64,
6874 mfmediaevent_GetDouble,
6875 mfmediaevent_GetGUID,
6876 mfmediaevent_GetStringLength,
6877 mfmediaevent_GetString,
6878 mfmediaevent_GetAllocatedString,
6879 mfmediaevent_GetBlobSize,
6880 mfmediaevent_GetBlob,
6881 mfmediaevent_GetAllocatedBlob,
6882 mfmediaevent_GetUnknown,
6883 mfmediaevent_SetItem,
6884 mfmediaevent_DeleteItem,
6885 mfmediaevent_DeleteAllItems,
6886 mfmediaevent_SetUINT32,
6887 mfmediaevent_SetUINT64,
6888 mfmediaevent_SetDouble,
6889 mfmediaevent_SetGUID,
6890 mfmediaevent_SetString,
6891 mfmediaevent_SetBlob,
6892 mfmediaevent_SetUnknown,
6893 mfmediaevent_LockStore,
6894 mfmediaevent_UnlockStore,
6895 mfmediaevent_GetCount,
6896 mfmediaevent_GetItemByIndex,
6897 mfmediaevent_CopyAllItems,
6898 mfmediaevent_GetType,
6899 mfmediaevent_GetExtendedType,
6900 mfmediaevent_GetStatus,
6901 mfmediaevent_GetValue,
6904 /***********************************************************************
6905 * MFCreateMediaEvent (mfplat.@)
6907 HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HRESULT status, const PROPVARIANT *value,
6908 IMFMediaEvent **event)
6910 struct media_event *object;
6911 HRESULT hr;
6913 TRACE("%s, %s, %#x, %s, %p.\n", debugstr_eventid(type), debugstr_guid(extended_type), status,
6914 debugstr_propvar(value), event);
6916 object = malloc(sizeof(*object));
6917 if (!object)
6918 return E_OUTOFMEMORY;
6920 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
6922 free(object);
6923 return hr;
6925 object->IMFMediaEvent_iface.lpVtbl = &mfmediaevent_vtbl;
6927 object->type = type;
6928 object->extended_type = *extended_type;
6929 object->status = status;
6931 PropVariantInit(&object->value);
6932 if (value)
6933 PropVariantCopy(&object->value, value);
6935 *event = &object->IMFMediaEvent_iface;
6937 TRACE("Created event %p.\n", *event);
6939 return S_OK;
6942 struct event_queue
6944 IMFMediaEventQueue IMFMediaEventQueue_iface;
6945 LONG refcount;
6947 CRITICAL_SECTION cs;
6948 CONDITION_VARIABLE update_event;
6949 struct list events;
6950 BOOL is_shut_down;
6951 BOOL notified;
6952 IRtwqAsyncResult *subscriber;
6955 struct queued_event
6957 struct list entry;
6958 IMFMediaEvent *event;
6961 static inline struct event_queue *impl_from_IMFMediaEventQueue(IMFMediaEventQueue *iface)
6963 return CONTAINING_RECORD(iface, struct event_queue, IMFMediaEventQueue_iface);
6966 static IMFMediaEvent *queue_pop_event(struct event_queue *queue)
6968 struct list *head = list_head(&queue->events);
6969 struct queued_event *queued_event;
6970 IMFMediaEvent *event;
6972 if (!head)
6973 return NULL;
6975 queued_event = LIST_ENTRY(head, struct queued_event, entry);
6976 event = queued_event->event;
6977 list_remove(&queued_event->entry);
6978 free(queued_event);
6979 return event;
6982 static void event_queue_clear_subscriber(struct event_queue *queue)
6984 if (queue->subscriber)
6985 IRtwqAsyncResult_Release(queue->subscriber);
6986 queue->subscriber = NULL;
6989 static void event_queue_cleanup(struct event_queue *queue)
6991 IMFMediaEvent *event;
6993 while ((event = queue_pop_event(queue)))
6994 IMFMediaEvent_Release(event);
6995 event_queue_clear_subscriber(queue);
6998 static HRESULT WINAPI eventqueue_QueryInterface(IMFMediaEventQueue *iface, REFIID riid, void **out)
7000 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7002 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7004 if (IsEqualIID(riid, &IID_IMFMediaEventQueue) ||
7005 IsEqualIID(riid, &IID_IUnknown))
7007 *out = &queue->IMFMediaEventQueue_iface;
7008 IMFMediaEventQueue_AddRef(iface);
7009 return S_OK;
7012 WARN("Unsupported %s.\n", debugstr_guid(riid));
7013 *out = NULL;
7014 return E_NOINTERFACE;
7017 static ULONG WINAPI eventqueue_AddRef(IMFMediaEventQueue *iface)
7019 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7020 ULONG refcount = InterlockedIncrement(&queue->refcount);
7022 TRACE("%p, refcount %u.\n", iface, refcount);
7024 return refcount;
7027 static ULONG WINAPI eventqueue_Release(IMFMediaEventQueue *iface)
7029 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7030 ULONG refcount = InterlockedDecrement(&queue->refcount);
7032 TRACE("%p, refcount %u.\n", queue, refcount);
7034 if (!refcount)
7036 event_queue_cleanup(queue);
7037 DeleteCriticalSection(&queue->cs);
7038 free(queue);
7041 return refcount;
7044 static HRESULT WINAPI eventqueue_GetEvent(IMFMediaEventQueue *iface, DWORD flags, IMFMediaEvent **event)
7046 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7047 HRESULT hr = S_OK;
7049 TRACE("%p, %p.\n", iface, event);
7051 EnterCriticalSection(&queue->cs);
7053 if (queue->is_shut_down)
7054 hr = MF_E_SHUTDOWN;
7055 else if (queue->subscriber)
7056 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7057 else
7059 if (flags & MF_EVENT_FLAG_NO_WAIT)
7061 if (!(*event = queue_pop_event(queue)))
7062 hr = MF_E_NO_EVENTS_AVAILABLE;
7064 else
7066 while (list_empty(&queue->events) && !queue->is_shut_down)
7068 SleepConditionVariableCS(&queue->update_event, &queue->cs, INFINITE);
7070 *event = queue_pop_event(queue);
7071 if (queue->is_shut_down)
7072 hr = MF_E_SHUTDOWN;
7076 LeaveCriticalSection(&queue->cs);
7078 return hr;
7081 static void queue_notify_subscriber(struct event_queue *queue)
7083 if (list_empty(&queue->events) || !queue->subscriber || queue->notified)
7084 return;
7086 queue->notified = TRUE;
7087 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, queue->subscriber);
7090 static HRESULT WINAPI eventqueue_BeginGetEvent(IMFMediaEventQueue *iface, IMFAsyncCallback *callback, IUnknown *state)
7092 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7093 RTWQASYNCRESULT *result_data;
7094 HRESULT hr;
7096 TRACE("%p, %p, %p.\n", iface, callback, state);
7098 if (!callback)
7099 return E_INVALIDARG;
7101 EnterCriticalSection(&queue->cs);
7103 if (queue->is_shut_down)
7104 hr = MF_E_SHUTDOWN;
7105 else if ((result_data = (RTWQASYNCRESULT *)queue->subscriber))
7107 if (result_data->pCallback == (IRtwqAsyncCallback *)callback)
7108 hr = IRtwqAsyncResult_GetStateNoAddRef(queue->subscriber) == state ?
7109 MF_S_MULTIPLE_BEGIN : MF_E_MULTIPLE_BEGIN;
7110 else
7111 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7113 else
7115 hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &queue->subscriber);
7116 if (SUCCEEDED(hr))
7117 queue_notify_subscriber(queue);
7120 LeaveCriticalSection(&queue->cs);
7122 return hr;
7125 static HRESULT WINAPI eventqueue_EndGetEvent(IMFMediaEventQueue *iface, IMFAsyncResult *result, IMFMediaEvent **event)
7127 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7128 HRESULT hr = E_FAIL;
7130 TRACE("%p, %p, %p.\n", iface, result, event);
7132 EnterCriticalSection(&queue->cs);
7134 if (queue->is_shut_down)
7135 hr = MF_E_SHUTDOWN;
7136 else if (queue->subscriber == (IRtwqAsyncResult *)result)
7138 *event = queue_pop_event(queue);
7139 event_queue_clear_subscriber(queue);
7140 queue->notified = FALSE;
7141 hr = *event ? S_OK : E_FAIL;
7144 LeaveCriticalSection(&queue->cs);
7146 return hr;
7149 static HRESULT eventqueue_queue_event(struct event_queue *queue, IMFMediaEvent *event)
7151 struct queued_event *queued_event;
7152 HRESULT hr = S_OK;
7154 queued_event = malloc(sizeof(*queued_event));
7155 if (!queued_event)
7156 return E_OUTOFMEMORY;
7158 queued_event->event = event;
7160 EnterCriticalSection(&queue->cs);
7162 if (queue->is_shut_down)
7163 hr = MF_E_SHUTDOWN;
7164 else
7166 IMFMediaEvent_AddRef(queued_event->event);
7167 list_add_tail(&queue->events, &queued_event->entry);
7168 queue_notify_subscriber(queue);
7171 LeaveCriticalSection(&queue->cs);
7173 if (FAILED(hr))
7174 free(queued_event);
7176 WakeAllConditionVariable(&queue->update_event);
7178 return hr;
7181 static HRESULT WINAPI eventqueue_QueueEvent(IMFMediaEventQueue *iface, IMFMediaEvent *event)
7183 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7185 TRACE("%p, %p.\n", iface, event);
7187 return eventqueue_queue_event(queue, event);
7190 static HRESULT WINAPI eventqueue_QueueEventParamVar(IMFMediaEventQueue *iface, MediaEventType event_type,
7191 REFGUID extended_type, HRESULT status, const PROPVARIANT *value)
7193 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7194 IMFMediaEvent *event;
7195 HRESULT hr;
7197 TRACE("%p, %s, %s, %#x, %s\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status,
7198 debugstr_propvar(value));
7200 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, value, &event)))
7201 return hr;
7203 hr = eventqueue_queue_event(queue, event);
7204 IMFMediaEvent_Release(event);
7205 return hr;
7208 static HRESULT WINAPI eventqueue_QueueEventParamUnk(IMFMediaEventQueue *iface, MediaEventType event_type,
7209 REFGUID extended_type, HRESULT status, IUnknown *unk)
7211 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7212 IMFMediaEvent *event;
7213 PROPVARIANT value;
7214 HRESULT hr;
7216 TRACE("%p, %s, %s, %#x, %p.\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status, unk);
7218 value.vt = VT_UNKNOWN;
7219 value.punkVal = unk;
7221 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, &value, &event)))
7222 return hr;
7224 hr = eventqueue_queue_event(queue, event);
7225 IMFMediaEvent_Release(event);
7226 return hr;
7229 static HRESULT WINAPI eventqueue_Shutdown(IMFMediaEventQueue *iface)
7231 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7233 TRACE("%p\n", queue);
7235 EnterCriticalSection(&queue->cs);
7237 if (!queue->is_shut_down)
7239 event_queue_cleanup(queue);
7240 queue->is_shut_down = TRUE;
7243 LeaveCriticalSection(&queue->cs);
7245 WakeAllConditionVariable(&queue->update_event);
7247 return S_OK;
7250 static const IMFMediaEventQueueVtbl eventqueuevtbl =
7252 eventqueue_QueryInterface,
7253 eventqueue_AddRef,
7254 eventqueue_Release,
7255 eventqueue_GetEvent,
7256 eventqueue_BeginGetEvent,
7257 eventqueue_EndGetEvent,
7258 eventqueue_QueueEvent,
7259 eventqueue_QueueEventParamVar,
7260 eventqueue_QueueEventParamUnk,
7261 eventqueue_Shutdown
7264 /***********************************************************************
7265 * MFCreateEventQueue (mfplat.@)
7267 HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue)
7269 struct event_queue *object;
7271 TRACE("%p\n", queue);
7273 if (!(object = calloc(1, sizeof(*object))))
7274 return E_OUTOFMEMORY;
7276 object->IMFMediaEventQueue_iface.lpVtbl = &eventqueuevtbl;
7277 object->refcount = 1;
7278 list_init(&object->events);
7279 InitializeCriticalSection(&object->cs);
7280 InitializeConditionVariable(&object->update_event);
7282 *queue = &object->IMFMediaEventQueue_iface;
7284 return S_OK;
7287 struct collection
7289 IMFCollection IMFCollection_iface;
7290 LONG refcount;
7291 IUnknown **elements;
7292 size_t capacity;
7293 size_t count;
7296 static struct collection *impl_from_IMFCollection(IMFCollection *iface)
7298 return CONTAINING_RECORD(iface, struct collection, IMFCollection_iface);
7301 static void collection_clear(struct collection *collection)
7303 size_t i;
7305 for (i = 0; i < collection->count; ++i)
7307 if (collection->elements[i])
7308 IUnknown_Release(collection->elements[i]);
7311 free(collection->elements);
7312 collection->elements = NULL;
7313 collection->count = 0;
7314 collection->capacity = 0;
7317 static HRESULT WINAPI collection_QueryInterface(IMFCollection *iface, REFIID riid, void **out)
7319 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7321 if (IsEqualIID(riid, &IID_IMFCollection) ||
7322 IsEqualIID(riid, &IID_IUnknown))
7324 *out = iface;
7325 IMFCollection_AddRef(iface);
7326 return S_OK;
7329 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
7330 *out = NULL;
7331 return E_NOINTERFACE;
7334 static ULONG WINAPI collection_AddRef(IMFCollection *iface)
7336 struct collection *collection = impl_from_IMFCollection(iface);
7337 ULONG refcount = InterlockedIncrement(&collection->refcount);
7339 TRACE("%p, %d.\n", collection, refcount);
7341 return refcount;
7344 static ULONG WINAPI collection_Release(IMFCollection *iface)
7346 struct collection *collection = impl_from_IMFCollection(iface);
7347 ULONG refcount = InterlockedDecrement(&collection->refcount);
7349 TRACE("%p, %d.\n", collection, refcount);
7351 if (!refcount)
7353 collection_clear(collection);
7354 free(collection->elements);
7355 free(collection);
7358 return refcount;
7361 static HRESULT WINAPI collection_GetElementCount(IMFCollection *iface, DWORD *count)
7363 struct collection *collection = impl_from_IMFCollection(iface);
7365 TRACE("%p, %p.\n", iface, count);
7367 if (!count)
7368 return E_POINTER;
7370 *count = collection->count;
7372 return S_OK;
7375 static HRESULT WINAPI collection_GetElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7377 struct collection *collection = impl_from_IMFCollection(iface);
7379 TRACE("%p, %u, %p.\n", iface, idx, element);
7381 if (!element)
7382 return E_POINTER;
7384 if (idx >= collection->count)
7385 return E_INVALIDARG;
7387 *element = collection->elements[idx];
7388 if (*element)
7389 IUnknown_AddRef(*element);
7391 return *element ? S_OK : E_UNEXPECTED;
7394 static HRESULT WINAPI collection_AddElement(IMFCollection *iface, IUnknown *element)
7396 struct collection *collection = impl_from_IMFCollection(iface);
7398 TRACE("%p, %p.\n", iface, element);
7400 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, collection->count + 1,
7401 sizeof(*collection->elements)))
7402 return E_OUTOFMEMORY;
7404 collection->elements[collection->count++] = element;
7405 if (element)
7406 IUnknown_AddRef(element);
7408 return S_OK;
7411 static HRESULT WINAPI collection_RemoveElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7413 struct collection *collection = impl_from_IMFCollection(iface);
7414 size_t count;
7416 TRACE("%p, %u, %p.\n", iface, idx, element);
7418 if (!element)
7419 return E_POINTER;
7421 if (idx >= collection->count)
7422 return E_INVALIDARG;
7424 *element = collection->elements[idx];
7426 count = collection->count - idx - 1;
7427 if (count)
7428 memmove(&collection->elements[idx], &collection->elements[idx + 1], count * sizeof(*collection->elements));
7429 collection->count--;
7431 return S_OK;
7434 static HRESULT WINAPI collection_InsertElementAt(IMFCollection *iface, DWORD idx, IUnknown *element)
7436 struct collection *collection = impl_from_IMFCollection(iface);
7437 size_t i;
7439 TRACE("%p, %u, %p.\n", iface, idx, element);
7441 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, idx + 1,
7442 sizeof(*collection->elements)))
7443 return E_OUTOFMEMORY;
7445 if (idx < collection->count)
7447 memmove(&collection->elements[idx + 1], &collection->elements[idx],
7448 (collection->count - idx) * sizeof(*collection->elements));
7449 collection->count++;
7451 else
7453 for (i = collection->count; i < idx; ++i)
7454 collection->elements[i] = NULL;
7455 collection->count = idx + 1;
7458 collection->elements[idx] = element;
7459 if (collection->elements[idx])
7460 IUnknown_AddRef(collection->elements[idx]);
7462 return S_OK;
7465 static HRESULT WINAPI collection_RemoveAllElements(IMFCollection *iface)
7467 struct collection *collection = impl_from_IMFCollection(iface);
7469 TRACE("%p.\n", iface);
7471 collection_clear(collection);
7473 return S_OK;
7476 static const IMFCollectionVtbl mfcollectionvtbl =
7478 collection_QueryInterface,
7479 collection_AddRef,
7480 collection_Release,
7481 collection_GetElementCount,
7482 collection_GetElement,
7483 collection_AddElement,
7484 collection_RemoveElement,
7485 collection_InsertElementAt,
7486 collection_RemoveAllElements,
7489 /***********************************************************************
7490 * MFCreateCollection (mfplat.@)
7492 HRESULT WINAPI MFCreateCollection(IMFCollection **collection)
7494 struct collection *object;
7496 TRACE("%p\n", collection);
7498 if (!collection)
7499 return E_POINTER;
7501 if (!(object = calloc(1, sizeof(*object))))
7502 return E_OUTOFMEMORY;
7504 object->IMFCollection_iface.lpVtbl = &mfcollectionvtbl;
7505 object->refcount = 1;
7507 *collection = &object->IMFCollection_iface;
7509 return S_OK;
7512 /***********************************************************************
7513 * MFHeapAlloc (mfplat.@)
7515 void *WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type)
7517 TRACE("%lu, %#x, %s, %d, %#x.\n", size, flags, debugstr_a(file), line, type);
7518 return HeapAlloc(GetProcessHeap(), flags, size);
7521 /***********************************************************************
7522 * MFHeapFree (mfplat.@)
7524 void WINAPI MFHeapFree(void *p)
7526 TRACE("%p\n", p);
7527 HeapFree(GetProcessHeap(), 0, p);
7530 /***********************************************************************
7531 * MFCreateMFByteStreamOnStreamEx (mfplat.@)
7533 HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream **bytestream)
7535 FIXME("(%p, %p): stub\n", stream, bytestream);
7537 return E_NOTIMPL;
7540 static HRESULT WINAPI system_clock_QueryInterface(IMFClock *iface, REFIID riid, void **obj)
7542 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7544 if (IsEqualIID(riid, &IID_IMFClock) ||
7545 IsEqualIID(riid, &IID_IUnknown))
7547 *obj = iface;
7548 IMFClock_AddRef(iface);
7549 return S_OK;
7552 WARN("Unsupported %s.\n", debugstr_guid(riid));
7553 *obj = NULL;
7554 return E_NOINTERFACE;
7557 static ULONG WINAPI system_clock_AddRef(IMFClock *iface)
7559 struct system_clock *clock = impl_from_IMFClock(iface);
7560 ULONG refcount = InterlockedIncrement(&clock->refcount);
7562 TRACE("%p, refcount %u.\n", iface, refcount);
7564 return refcount;
7567 static ULONG WINAPI system_clock_Release(IMFClock *iface)
7569 struct system_clock *clock = impl_from_IMFClock(iface);
7570 ULONG refcount = InterlockedDecrement(&clock->refcount);
7572 TRACE("%p, refcount %u.\n", iface, refcount);
7574 if (!refcount)
7575 free(clock);
7577 return refcount;
7580 static HRESULT WINAPI system_clock_GetClockCharacteristics(IMFClock *iface, DWORD *flags)
7582 TRACE("%p, %p.\n", iface, flags);
7584 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING |
7585 MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7587 return S_OK;
7590 static HRESULT WINAPI system_clock_GetCorrelatedTime(IMFClock *iface, DWORD reserved, LONGLONG *clock_time,
7591 MFTIME *system_time)
7593 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7595 *clock_time = *system_time = MFGetSystemTime();
7597 return S_OK;
7600 static HRESULT WINAPI system_clock_GetContinuityKey(IMFClock *iface, DWORD *key)
7602 TRACE("%p, %p.\n", iface, key);
7604 *key = 0;
7606 return S_OK;
7609 static HRESULT WINAPI system_clock_GetState(IMFClock *iface, DWORD reserved, MFCLOCK_STATE *state)
7611 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7613 *state = MFCLOCK_STATE_RUNNING;
7615 return S_OK;
7618 static HRESULT WINAPI system_clock_GetProperties(IMFClock *iface, MFCLOCK_PROPERTIES *props)
7620 TRACE("%p, %p.\n", iface, props);
7622 if (!props)
7623 return E_POINTER;
7625 memset(props, 0, sizeof(*props));
7626 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7627 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7628 props->dwClockJitter = 1;
7630 return S_OK;
7633 static const IMFClockVtbl system_clock_vtbl =
7635 system_clock_QueryInterface,
7636 system_clock_AddRef,
7637 system_clock_Release,
7638 system_clock_GetClockCharacteristics,
7639 system_clock_GetCorrelatedTime,
7640 system_clock_GetContinuityKey,
7641 system_clock_GetState,
7642 system_clock_GetProperties,
7645 static HRESULT create_system_clock(IMFClock **clock)
7647 struct system_clock *object;
7649 if (!(object = malloc(sizeof(*object))))
7650 return E_OUTOFMEMORY;
7652 object->IMFClock_iface.lpVtbl = &system_clock_vtbl;
7653 object->refcount = 1;
7655 *clock = &object->IMFClock_iface;
7657 return S_OK;
7660 static HRESULT WINAPI system_time_source_QueryInterface(IMFPresentationTimeSource *iface, REFIID riid, void **obj)
7662 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7664 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7666 if (IsEqualIID(riid, &IID_IMFPresentationTimeSource) ||
7667 IsEqualIID(riid, &IID_IUnknown))
7669 *obj = &source->IMFPresentationTimeSource_iface;
7671 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
7673 *obj = &source->IMFClockStateSink_iface;
7675 else
7677 WARN("Unsupported %s.\n", debugstr_guid(riid));
7678 *obj = NULL;
7679 return E_NOINTERFACE;
7682 IUnknown_AddRef((IUnknown *)*obj);
7683 return S_OK;
7686 static ULONG WINAPI system_time_source_AddRef(IMFPresentationTimeSource *iface)
7688 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7689 ULONG refcount = InterlockedIncrement(&source->refcount);
7691 TRACE("%p, refcount %u.\n", iface, refcount);
7693 return refcount;
7696 static ULONG WINAPI system_time_source_Release(IMFPresentationTimeSource *iface)
7698 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7699 ULONG refcount = InterlockedDecrement(&source->refcount);
7701 TRACE("%p, refcount %u.\n", iface, refcount);
7703 if (!refcount)
7705 if (source->clock)
7706 IMFClock_Release(source->clock);
7707 DeleteCriticalSection(&source->cs);
7708 free(source);
7711 return refcount;
7714 static HRESULT WINAPI system_time_source_GetClockCharacteristics(IMFPresentationTimeSource *iface, DWORD *flags)
7716 TRACE("%p, %p.\n", iface, flags);
7718 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7720 return S_OK;
7723 static HRESULT WINAPI system_time_source_GetCorrelatedTime(IMFPresentationTimeSource *iface, DWORD reserved,
7724 LONGLONG *clock_time, MFTIME *system_time)
7726 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7727 HRESULT hr;
7729 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7731 EnterCriticalSection(&source->cs);
7732 if (SUCCEEDED(hr = IMFClock_GetCorrelatedTime(source->clock, 0, clock_time, system_time)))
7734 if (source->state == MFCLOCK_STATE_RUNNING)
7736 system_time_source_apply_rate(source, clock_time);
7737 *clock_time += source->start_offset;
7739 else
7740 *clock_time = source->start_offset;
7742 LeaveCriticalSection(&source->cs);
7744 return hr;
7747 static HRESULT WINAPI system_time_source_GetContinuityKey(IMFPresentationTimeSource *iface, DWORD *key)
7749 TRACE("%p, %p.\n", iface, key);
7751 *key = 0;
7753 return S_OK;
7756 static HRESULT WINAPI system_time_source_GetState(IMFPresentationTimeSource *iface, DWORD reserved,
7757 MFCLOCK_STATE *state)
7759 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7761 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7763 EnterCriticalSection(&source->cs);
7764 *state = source->state;
7765 LeaveCriticalSection(&source->cs);
7767 return S_OK;
7770 static HRESULT WINAPI system_time_source_GetProperties(IMFPresentationTimeSource *iface, MFCLOCK_PROPERTIES *props)
7772 TRACE("%p, %p.\n", iface, props);
7774 if (!props)
7775 return E_POINTER;
7777 memset(props, 0, sizeof(*props));
7778 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7779 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7780 props->dwClockJitter = 1;
7782 return S_OK;
7785 static HRESULT WINAPI system_time_source_GetUnderlyingClock(IMFPresentationTimeSource *iface, IMFClock **clock)
7787 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7789 TRACE("%p, %p.\n", iface, clock);
7791 *clock = source->clock;
7792 IMFClock_AddRef(*clock);
7794 return S_OK;
7797 static const IMFPresentationTimeSourceVtbl systemtimesourcevtbl =
7799 system_time_source_QueryInterface,
7800 system_time_source_AddRef,
7801 system_time_source_Release,
7802 system_time_source_GetClockCharacteristics,
7803 system_time_source_GetCorrelatedTime,
7804 system_time_source_GetContinuityKey,
7805 system_time_source_GetState,
7806 system_time_source_GetProperties,
7807 system_time_source_GetUnderlyingClock,
7810 static HRESULT WINAPI system_time_source_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **out)
7812 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7813 return IMFPresentationTimeSource_QueryInterface(&source->IMFPresentationTimeSource_iface, riid, out);
7816 static ULONG WINAPI system_time_source_sink_AddRef(IMFClockStateSink *iface)
7818 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7819 return IMFPresentationTimeSource_AddRef(&source->IMFPresentationTimeSource_iface);
7822 static ULONG WINAPI system_time_source_sink_Release(IMFClockStateSink *iface)
7824 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7825 return IMFPresentationTimeSource_Release(&source->IMFPresentationTimeSource_iface);
7828 enum clock_command
7830 CLOCK_CMD_START = 0,
7831 CLOCK_CMD_STOP,
7832 CLOCK_CMD_PAUSE,
7833 CLOCK_CMD_RESTART,
7834 CLOCK_CMD_MAX,
7837 static HRESULT system_time_source_change_state(struct system_time_source *source, enum clock_command command)
7839 static const BYTE state_change_is_allowed[MFCLOCK_STATE_PAUSED+1][CLOCK_CMD_MAX] =
7840 { /* S S* P R */
7841 /* INVALID */ { 1, 0, 1, 0 },
7842 /* RUNNING */ { 1, 1, 1, 0 },
7843 /* STOPPED */ { 1, 1, 0, 0 },
7844 /* PAUSED */ { 1, 1, 0, 1 },
7846 static const MFCLOCK_STATE states[CLOCK_CMD_MAX] =
7848 /* CLOCK_CMD_START */ MFCLOCK_STATE_RUNNING,
7849 /* CLOCK_CMD_STOP */ MFCLOCK_STATE_STOPPED,
7850 /* CLOCK_CMD_PAUSE */ MFCLOCK_STATE_PAUSED,
7851 /* CLOCK_CMD_RESTART */ MFCLOCK_STATE_RUNNING,
7854 /* Special case that go against usual state change vs return value behavior. */
7855 if (source->state == MFCLOCK_STATE_INVALID && command == CLOCK_CMD_STOP)
7856 return S_OK;
7858 if (!state_change_is_allowed[source->state][command])
7859 return MF_E_INVALIDREQUEST;
7861 source->state = states[command];
7863 return S_OK;
7866 static HRESULT WINAPI system_time_source_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time,
7867 LONGLONG start_offset)
7869 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7870 MFCLOCK_STATE state;
7871 HRESULT hr;
7873 TRACE("%p, %s, %s.\n", iface, debugstr_time(system_time), debugstr_time(start_offset));
7875 EnterCriticalSection(&source->cs);
7876 state = source->state;
7877 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_START)))
7879 system_time_source_apply_rate(source, &system_time);
7880 if (start_offset == PRESENTATION_CURRENT_POSITION)
7882 switch (state)
7884 case MFCLOCK_STATE_RUNNING:
7885 break;
7886 case MFCLOCK_STATE_PAUSED:
7887 source->start_offset -= system_time;
7888 break;
7889 default:
7890 source->start_offset = -system_time;
7891 break;
7895 else
7897 source->start_offset = -system_time + start_offset;
7900 LeaveCriticalSection(&source->cs);
7902 return hr;
7905 static HRESULT WINAPI system_time_source_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
7907 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7908 HRESULT hr;
7910 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7912 EnterCriticalSection(&source->cs);
7913 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_STOP)))
7914 source->start_offset = 0;
7915 LeaveCriticalSection(&source->cs);
7917 return hr;
7920 static HRESULT WINAPI system_time_source_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
7922 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7923 HRESULT hr;
7925 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7927 EnterCriticalSection(&source->cs);
7928 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_PAUSE)))
7930 system_time_source_apply_rate(source, &system_time);
7931 source->start_offset += system_time;
7933 LeaveCriticalSection(&source->cs);
7935 return hr;
7938 static HRESULT WINAPI system_time_source_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
7940 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7941 HRESULT hr;
7943 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7945 EnterCriticalSection(&source->cs);
7946 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_RESTART)))
7948 system_time_source_apply_rate(source, &system_time);
7949 source->start_offset -= system_time;
7951 LeaveCriticalSection(&source->cs);
7953 return hr;
7956 static HRESULT WINAPI system_time_source_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
7958 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7959 double intpart;
7961 TRACE("%p, %s, %f.\n", iface, debugstr_time(system_time), rate);
7963 if (rate == 0.0f)
7964 return MF_E_UNSUPPORTED_RATE;
7966 modf(rate, &intpart);
7968 EnterCriticalSection(&source->cs);
7969 source->rate = rate;
7970 source->i_rate = rate == intpart ? rate : 0;
7971 LeaveCriticalSection(&source->cs);
7973 return S_OK;
7976 static const IMFClockStateSinkVtbl systemtimesourcesinkvtbl =
7978 system_time_source_sink_QueryInterface,
7979 system_time_source_sink_AddRef,
7980 system_time_source_sink_Release,
7981 system_time_source_sink_OnClockStart,
7982 system_time_source_sink_OnClockStop,
7983 system_time_source_sink_OnClockPause,
7984 system_time_source_sink_OnClockRestart,
7985 system_time_source_sink_OnClockSetRate,
7988 /***********************************************************************
7989 * MFCreateSystemTimeSource (mfplat.@)
7991 HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source)
7993 struct system_time_source *object;
7994 HRESULT hr;
7996 TRACE("%p.\n", time_source);
7998 object = calloc(1, sizeof(*object));
7999 if (!object)
8000 return E_OUTOFMEMORY;
8002 object->IMFPresentationTimeSource_iface.lpVtbl = &systemtimesourcevtbl;
8003 object->IMFClockStateSink_iface.lpVtbl = &systemtimesourcesinkvtbl;
8004 object->refcount = 1;
8005 object->rate = 1.0f;
8006 object->i_rate = 1;
8007 InitializeCriticalSection(&object->cs);
8009 if (FAILED(hr = create_system_clock(&object->clock)))
8011 IMFPresentationTimeSource_Release(&object->IMFPresentationTimeSource_iface);
8012 return hr;
8015 *time_source = &object->IMFPresentationTimeSource_iface;
8017 return S_OK;
8020 struct async_create_file
8022 IRtwqAsyncCallback IRtwqAsyncCallback_iface;
8023 LONG refcount;
8024 MF_FILE_ACCESSMODE access_mode;
8025 MF_FILE_OPENMODE open_mode;
8026 MF_FILE_FLAGS flags;
8027 WCHAR *path;
8030 struct async_create_file_result
8032 struct list entry;
8033 IRtwqAsyncResult *result;
8034 IMFByteStream *stream;
8037 static struct list async_create_file_results = LIST_INIT(async_create_file_results);
8038 static CRITICAL_SECTION async_create_file_cs = { NULL, -1, 0, 0, 0, 0 };
8040 static struct async_create_file *impl_from_create_file_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
8042 return CONTAINING_RECORD(iface, struct async_create_file, IRtwqAsyncCallback_iface);
8045 static HRESULT WINAPI async_create_file_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
8047 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
8048 IsEqualIID(riid, &IID_IUnknown))
8050 *obj = iface;
8051 IRtwqAsyncCallback_AddRef(iface);
8052 return S_OK;
8055 *obj = NULL;
8056 return E_NOINTERFACE;
8059 static ULONG WINAPI async_create_file_callback_AddRef(IRtwqAsyncCallback *iface)
8061 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8062 ULONG refcount = InterlockedIncrement(&async->refcount);
8064 TRACE("%p, refcount %u.\n", iface, refcount);
8066 return refcount;
8069 static ULONG WINAPI async_create_file_callback_Release(IRtwqAsyncCallback *iface)
8071 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8072 ULONG refcount = InterlockedDecrement(&async->refcount);
8074 TRACE("%p, refcount %u.\n", iface, refcount);
8076 if (!refcount)
8078 free(async->path);
8079 free(async);
8082 return refcount;
8085 static HRESULT WINAPI async_create_file_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
8087 return E_NOTIMPL;
8090 static HRESULT WINAPI async_create_file_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
8092 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8093 IRtwqAsyncResult *caller;
8094 IMFByteStream *stream;
8095 HRESULT hr;
8097 caller = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
8099 hr = MFCreateFile(async->access_mode, async->open_mode, async->flags, async->path, &stream);
8100 if (SUCCEEDED(hr))
8102 struct async_create_file_result *result_item;
8104 result_item = malloc(sizeof(*result_item));
8105 if (result_item)
8107 result_item->result = caller;
8108 IRtwqAsyncResult_AddRef(caller);
8109 result_item->stream = stream;
8110 IMFByteStream_AddRef(stream);
8112 EnterCriticalSection(&async_create_file_cs);
8113 list_add_tail(&async_create_file_results, &result_item->entry);
8114 LeaveCriticalSection(&async_create_file_cs);
8117 IMFByteStream_Release(stream);
8119 else
8120 IRtwqAsyncResult_SetStatus(caller, hr);
8122 RtwqInvokeCallback(caller);
8124 return S_OK;
8127 static const IRtwqAsyncCallbackVtbl async_create_file_callback_vtbl =
8129 async_create_file_callback_QueryInterface,
8130 async_create_file_callback_AddRef,
8131 async_create_file_callback_Release,
8132 async_create_file_callback_GetParameters,
8133 async_create_file_callback_Invoke,
8136 /***********************************************************************
8137 * MFBeginCreateFile (mfplat.@)
8139 HRESULT WINAPI MFBeginCreateFile(MF_FILE_ACCESSMODE access_mode, MF_FILE_OPENMODE open_mode, MF_FILE_FLAGS flags,
8140 const WCHAR *path, IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_cookie)
8142 struct async_create_file *async = NULL;
8143 IRtwqAsyncResult *caller, *item = NULL;
8144 HRESULT hr;
8146 TRACE("%#x, %#x, %#x, %s, %p, %p, %p.\n", access_mode, open_mode, flags, debugstr_w(path), callback, state,
8147 cancel_cookie);
8149 if (cancel_cookie)
8150 *cancel_cookie = NULL;
8152 if (FAILED(hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &caller)))
8153 return hr;
8155 if (!(async = malloc(sizeof(*async))))
8157 hr = E_OUTOFMEMORY;
8158 goto failed;
8161 async->IRtwqAsyncCallback_iface.lpVtbl = &async_create_file_callback_vtbl;
8162 async->refcount = 1;
8163 async->access_mode = access_mode;
8164 async->open_mode = open_mode;
8165 async->flags = flags;
8166 if (!(async->path = wcsdup(path)))
8168 hr = E_OUTOFMEMORY;
8169 goto failed;
8172 hr = RtwqCreateAsyncResult(NULL, &async->IRtwqAsyncCallback_iface, (IUnknown *)caller, &item);
8173 if (FAILED(hr))
8174 goto failed;
8176 if (cancel_cookie)
8178 *cancel_cookie = (IUnknown *)caller;
8179 IUnknown_AddRef(*cancel_cookie);
8182 hr = RtwqInvokeCallback(item);
8184 failed:
8185 if (async)
8186 IRtwqAsyncCallback_Release(&async->IRtwqAsyncCallback_iface);
8187 if (item)
8188 IRtwqAsyncResult_Release(item);
8189 if (caller)
8190 IRtwqAsyncResult_Release(caller);
8192 return hr;
8195 static HRESULT async_create_file_pull_result(IUnknown *unk, IMFByteStream **stream)
8197 struct async_create_file_result *item;
8198 HRESULT hr = MF_E_UNEXPECTED;
8199 IRtwqAsyncResult *result;
8201 *stream = NULL;
8203 if (FAILED(IUnknown_QueryInterface(unk, &IID_IRtwqAsyncResult, (void **)&result)))
8204 return hr;
8206 EnterCriticalSection(&async_create_file_cs);
8208 LIST_FOR_EACH_ENTRY(item, &async_create_file_results, struct async_create_file_result, entry)
8210 if (result == item->result)
8212 *stream = item->stream;
8213 IRtwqAsyncResult_Release(item->result);
8214 list_remove(&item->entry);
8215 free(item);
8216 break;
8220 LeaveCriticalSection(&async_create_file_cs);
8222 if (*stream)
8223 hr = IRtwqAsyncResult_GetStatus(result);
8225 IRtwqAsyncResult_Release(result);
8227 return hr;
8230 /***********************************************************************
8231 * MFEndCreateFile (mfplat.@)
8233 HRESULT WINAPI MFEndCreateFile(IMFAsyncResult *result, IMFByteStream **stream)
8235 TRACE("%p, %p.\n", result, stream);
8237 return async_create_file_pull_result((IUnknown *)result, stream);
8240 /***********************************************************************
8241 * MFCancelCreateFile (mfplat.@)
8243 HRESULT WINAPI MFCancelCreateFile(IUnknown *cancel_cookie)
8245 IMFByteStream *stream = NULL;
8246 HRESULT hr;
8248 TRACE("%p.\n", cancel_cookie);
8250 hr = async_create_file_pull_result(cancel_cookie, &stream);
8252 if (stream)
8253 IMFByteStream_Release(stream);
8255 return hr;
8258 /***********************************************************************
8259 * MFRegisterLocalSchemeHandler (mfplat.@)
8261 HRESULT WINAPI MFRegisterLocalSchemeHandler(const WCHAR *scheme, IMFActivate *activate)
8263 struct local_handler *handler;
8265 TRACE("%s, %p.\n", debugstr_w(scheme), activate);
8267 if (!scheme || !activate)
8268 return E_INVALIDARG;
8270 if (!(handler = malloc(sizeof(*handler))))
8271 return E_OUTOFMEMORY;
8273 if (!(handler->u.scheme = wcsdup(scheme)))
8275 free(handler);
8276 return E_OUTOFMEMORY;
8278 handler->activate = activate;
8279 IMFActivate_AddRef(handler->activate);
8281 EnterCriticalSection(&local_handlers_section);
8282 list_add_head(&local_scheme_handlers, &handler->entry);
8283 LeaveCriticalSection(&local_handlers_section);
8285 return S_OK;
8288 /***********************************************************************
8289 * MFRegisterLocalByteStreamHandler (mfplat.@)
8291 HRESULT WINAPI MFRegisterLocalByteStreamHandler(const WCHAR *extension, const WCHAR *mime, IMFActivate *activate)
8293 struct local_handler *handler;
8295 TRACE("%s, %s, %p.\n", debugstr_w(extension), debugstr_w(mime), activate);
8297 if ((!extension && !mime) || !activate)
8298 return E_INVALIDARG;
8300 if (!(handler = calloc(1, sizeof(*handler))))
8301 return E_OUTOFMEMORY;
8303 if (extension && !(handler->u.bytestream.extension = wcsdup(extension)))
8304 goto failed;
8305 if (mime && !(handler->u.bytestream.mime = wcsdup(mime)))
8306 goto failed;
8308 EnterCriticalSection(&local_handlers_section);
8309 list_add_head(&local_bytestream_handlers, &handler->entry);
8310 LeaveCriticalSection(&local_handlers_section);
8312 return S_OK;
8314 failed:
8315 free(handler->u.bytestream.extension);
8316 free(handler->u.bytestream.mime);
8317 free(handler);
8319 return E_OUTOFMEMORY;
8322 struct property_store
8324 IPropertyStore IPropertyStore_iface;
8325 LONG refcount;
8326 CRITICAL_SECTION cs;
8327 size_t count, capacity;
8328 struct
8330 PROPERTYKEY key;
8331 PROPVARIANT value;
8332 } *values;
8335 static struct property_store *impl_from_IPropertyStore(IPropertyStore *iface)
8337 return CONTAINING_RECORD(iface, struct property_store, IPropertyStore_iface);
8340 static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
8342 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8344 if (IsEqualIID(riid, &IID_IPropertyStore) || IsEqualIID(riid, &IID_IUnknown))
8346 *obj = iface;
8347 IPropertyStore_AddRef(iface);
8348 return S_OK;
8351 *obj = NULL;
8352 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
8353 return E_NOINTERFACE;
8356 static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
8358 struct property_store *store = impl_from_IPropertyStore(iface);
8359 ULONG refcount = InterlockedIncrement(&store->refcount);
8361 TRACE("%p, refcount %d.\n", iface, refcount);
8363 return refcount;
8366 static ULONG WINAPI property_store_Release(IPropertyStore *iface)
8368 struct property_store *store = impl_from_IPropertyStore(iface);
8369 ULONG refcount = InterlockedDecrement(&store->refcount);
8371 TRACE("%p, refcount %d.\n", iface, refcount);
8373 if (!refcount)
8375 DeleteCriticalSection(&store->cs);
8376 free(store->values);
8377 free(store);
8380 return refcount;
8383 static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
8385 struct property_store *store = impl_from_IPropertyStore(iface);
8387 TRACE("%p, %p.\n", iface, count);
8389 if (!count)
8390 return E_INVALIDARG;
8392 EnterCriticalSection(&store->cs);
8393 *count = store->count;
8394 LeaveCriticalSection(&store->cs);
8395 return S_OK;
8398 static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
8400 struct property_store *store = impl_from_IPropertyStore(iface);
8402 TRACE("%p, %u, %p.\n", iface, index, key);
8404 EnterCriticalSection(&store->cs);
8406 if (index >= store->count)
8408 LeaveCriticalSection(&store->cs);
8409 return E_INVALIDARG;
8412 *key = store->values[index].key;
8414 LeaveCriticalSection(&store->cs);
8415 return S_OK;
8418 static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
8420 struct property_store *store = impl_from_IPropertyStore(iface);
8421 unsigned int i;
8423 TRACE("%p, %p, %p.\n", iface, key, value);
8425 if (!value)
8426 return E_INVALIDARG;
8428 if (!key)
8429 return S_FALSE;
8431 EnterCriticalSection(&store->cs);
8433 for (i = 0; i < store->count; ++i)
8435 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8437 PropVariantCopy(value, &store->values[i].value);
8438 LeaveCriticalSection(&store->cs);
8439 return S_OK;
8443 LeaveCriticalSection(&store->cs);
8444 return S_FALSE;
8447 static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
8449 struct property_store *store = impl_from_IPropertyStore(iface);
8450 unsigned int i;
8452 TRACE("%p, %p, %p.\n", iface, key, value);
8454 EnterCriticalSection(&store->cs);
8456 for (i = 0; i < store->count; ++i)
8458 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8460 PropVariantCopy(&store->values[i].value, value);
8461 LeaveCriticalSection(&store->cs);
8462 return S_OK;
8466 if (!mf_array_reserve((void **)&store->values, &store->capacity, store->count + 1, sizeof(*store->values)))
8468 LeaveCriticalSection(&store->cs);
8469 return E_OUTOFMEMORY;
8472 store->values[store->count].key = *key;
8473 PropVariantCopy(&store->values[store->count].value, value);
8474 ++store->count;
8476 LeaveCriticalSection(&store->cs);
8477 return S_OK;
8480 static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
8482 TRACE("%p.\n", iface);
8484 return E_NOTIMPL;
8487 static const IPropertyStoreVtbl property_store_vtbl =
8489 property_store_QueryInterface,
8490 property_store_AddRef,
8491 property_store_Release,
8492 property_store_GetCount,
8493 property_store_GetAt,
8494 property_store_GetValue,
8495 property_store_SetValue,
8496 property_store_Commit,
8499 /***********************************************************************
8500 * CreatePropertyStore (mfplat.@)
8502 HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
8504 struct property_store *object;
8506 TRACE("%p.\n", store);
8508 if (!store)
8509 return E_INVALIDARG;
8511 if (!(object = calloc(1, sizeof(*object))))
8512 return E_OUTOFMEMORY;
8514 object->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
8515 object->refcount = 1;
8516 InitializeCriticalSection(&object->cs);
8518 TRACE("Created store %p.\n", object);
8519 *store = &object->IPropertyStore_iface;
8521 return S_OK;
8524 struct shared_dxgi_manager
8526 IMFDXGIDeviceManager *manager;
8527 unsigned int token;
8528 unsigned int locks;
8531 static struct shared_dxgi_manager shared_dm;
8532 static CRITICAL_SECTION shared_dm_cs = { NULL, -1, 0, 0, 0, 0 };
8534 enum dxgi_device_handle_flags
8536 DXGI_DEVICE_HANDLE_FLAG_OPEN = 0x1,
8537 DXGI_DEVICE_HANDLE_FLAG_INVALID = 0x2,
8538 DXGI_DEVICE_HANDLE_FLAG_LOCKED = 0x4,
8541 struct dxgi_device_manager
8543 IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
8544 LONG refcount;
8545 UINT token;
8546 IDXGIDevice *device;
8548 unsigned int *handles;
8549 size_t count;
8550 size_t capacity;
8552 unsigned int locks;
8553 unsigned int locking_tid;
8555 CRITICAL_SECTION cs;
8556 CONDITION_VARIABLE lock;
8559 static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
8561 return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface);
8564 static HRESULT dxgi_device_manager_get_handle_index(struct dxgi_device_manager *manager, HANDLE hdevice, size_t *idx)
8566 if (!hdevice || hdevice > ULongToHandle(manager->count))
8567 return E_HANDLE;
8568 *idx = (ULONG_PTR)hdevice - 1;
8569 return S_OK;
8572 static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj)
8574 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8576 if (IsEqualIID(riid, &IID_IMFDXGIDeviceManager) ||
8577 IsEqualGUID(riid, &IID_IUnknown))
8579 *obj = iface;
8580 IMFDXGIDeviceManager_AddRef(iface);
8581 return S_OK;
8584 WARN("Unsupported %s.\n", debugstr_guid(riid));
8585 *obj = NULL;
8586 return E_NOINTERFACE;
8589 static ULONG WINAPI dxgi_device_manager_AddRef(IMFDXGIDeviceManager *iface)
8591 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8592 ULONG refcount = InterlockedIncrement(&manager->refcount);
8594 TRACE("%p, refcount %u.\n", iface, refcount);
8596 return refcount;
8599 static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
8601 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8602 ULONG refcount = InterlockedDecrement(&manager->refcount);
8604 TRACE("%p, refcount %u.\n", iface, refcount);
8606 if (!refcount)
8608 if (manager->device)
8609 IDXGIDevice_Release(manager->device);
8610 DeleteCriticalSection(&manager->cs);
8611 free(manager->handles);
8612 free(manager);
8615 return refcount;
8618 static void dxgi_device_manager_lock_handle(struct dxgi_device_manager *manager, size_t idx)
8620 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED)
8621 return;
8623 manager->handles[idx] |= DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8624 manager->locks++;
8627 static void dxgi_device_manager_unlock_handle(struct dxgi_device_manager *manager, size_t idx)
8629 if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED))
8630 return;
8632 manager->handles[idx] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8633 if (!--manager->locks)
8634 manager->locking_tid = 0;
8637 static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8639 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8640 HRESULT hr;
8641 size_t idx;
8643 TRACE("%p, %p.\n", iface, hdevice);
8645 EnterCriticalSection(&manager->cs);
8647 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8649 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8651 dxgi_device_manager_unlock_handle(manager, idx);
8652 manager->handles[idx] = 0;
8653 if (idx == manager->count - 1)
8654 manager->count--;
8656 else
8657 hr = E_HANDLE;
8660 LeaveCriticalSection(&manager->cs);
8662 WakeAllConditionVariable(&manager->lock);
8664 return hr;
8667 static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8668 REFIID riid, void **service)
8670 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8671 HRESULT hr;
8672 size_t idx;
8674 TRACE("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), service);
8676 EnterCriticalSection(&manager->cs);
8678 if (!manager->device)
8679 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8680 else if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8682 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8683 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8684 else if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8685 hr = IDXGIDevice_QueryInterface(manager->device, riid, service);
8686 else
8687 hr = E_HANDLE;
8690 LeaveCriticalSection(&manager->cs);
8692 return hr;
8695 static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8696 REFIID riid, void **obj, BOOL block)
8698 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8699 HRESULT hr;
8700 size_t idx;
8702 TRACE("%p, %p, %s, %p, %d.\n", iface, hdevice, wine_dbgstr_guid(riid), obj, block);
8704 EnterCriticalSection(&manager->cs);
8706 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8708 if (!manager->device)
8710 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8712 else if (manager->locking_tid == GetCurrentThreadId())
8714 if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
8715 dxgi_device_manager_lock_handle(manager, idx);
8717 else if (manager->locking_tid && !block)
8719 hr = MF_E_DXGI_VIDEO_DEVICE_LOCKED;
8721 else
8723 while (manager->locking_tid)
8725 SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE);
8728 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8730 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8731 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8732 else if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
8734 manager->locking_tid = GetCurrentThreadId();
8735 dxgi_device_manager_lock_handle(manager, idx);
8741 LeaveCriticalSection(&manager->cs);
8743 return hr;
8746 static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *hdevice)
8748 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8749 HRESULT hr = S_OK;
8750 size_t i;
8752 TRACE("%p, %p.\n", iface, hdevice);
8754 *hdevice = NULL;
8756 EnterCriticalSection(&manager->cs);
8758 if (!manager->device)
8759 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8760 else
8762 for (i = 0; i < manager->count; ++i)
8764 if (!(manager->handles[i] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
8766 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_OPEN;
8767 *hdevice = ULongToHandle(i + 1);
8768 break;
8772 if (mf_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1,
8773 sizeof(*manager->handles)))
8775 *hdevice = ULongToHandle(manager->count + 1);
8776 manager->handles[manager->count++] = DXGI_DEVICE_HANDLE_FLAG_OPEN;
8778 else
8779 hr = E_OUTOFMEMORY;
8782 LeaveCriticalSection(&manager->cs);
8784 return hr;
8787 static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
8789 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8790 IDXGIDevice *dxgi_device;
8791 size_t i;
8793 TRACE("%p, %p, %u.\n", iface, device, token);
8795 if (!device || token != manager->token)
8796 return E_INVALIDARG;
8798 if (FAILED(IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device)))
8799 return E_INVALIDARG;
8801 EnterCriticalSection(&manager->cs);
8803 if (manager->device)
8805 for (i = 0; i < manager->count; ++i)
8807 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_INVALID;
8808 manager->handles[i] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8810 manager->locking_tid = 0;
8811 manager->locks = 0;
8812 IDXGIDevice_Release(manager->device);
8814 manager->device = dxgi_device;
8816 LeaveCriticalSection(&manager->cs);
8818 WakeAllConditionVariable(&manager->lock);
8820 return S_OK;
8823 static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8825 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8826 HRESULT hr;
8827 size_t idx;
8829 TRACE("%p, %p.\n", iface, hdevice);
8831 EnterCriticalSection(&manager->cs);
8833 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8835 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8836 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8837 else if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
8838 hr = E_HANDLE;
8841 LeaveCriticalSection(&manager->cs);
8843 return hr;
8846 static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8847 BOOL savestate)
8849 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8850 HRESULT hr = E_FAIL;
8851 size_t idx;
8853 TRACE("%p, %p, %d.\n", iface, hdevice, savestate);
8855 EnterCriticalSection(&manager->cs);
8857 if (SUCCEEDED(dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8859 hr = manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED ? S_OK : E_INVALIDARG;
8860 if (SUCCEEDED(hr))
8861 dxgi_device_manager_unlock_handle(manager, idx);
8864 LeaveCriticalSection(&manager->cs);
8866 WakeAllConditionVariable(&manager->lock);
8868 return hr;
8871 static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
8873 dxgi_device_manager_QueryInterface,
8874 dxgi_device_manager_AddRef,
8875 dxgi_device_manager_Release,
8876 dxgi_device_manager_CloseDeviceHandle,
8877 dxgi_device_manager_GetVideoService,
8878 dxgi_device_manager_LockDevice,
8879 dxgi_device_manager_OpenDeviceHandle,
8880 dxgi_device_manager_ResetDevice,
8881 dxgi_device_manager_TestDevice,
8882 dxgi_device_manager_UnlockDevice,
8885 /***********************************************************************
8886 * MFCreateDXGIDeviceManager (mfplat.@)
8888 HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
8890 struct dxgi_device_manager *object;
8892 TRACE("%p, %p.\n", token, manager);
8894 if (!token || !manager)
8895 return E_POINTER;
8897 if (!(object = calloc(1, sizeof(*object))))
8898 return E_OUTOFMEMORY;
8900 object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
8901 object->refcount = 1;
8902 object->token = GetTickCount();
8903 InitializeCriticalSection(&object->cs);
8904 InitializeConditionVariable(&object->lock);
8906 TRACE("Created device manager: %p, token: %u.\n", object, object->token);
8908 *token = object->token;
8909 *manager = &object->IMFDXGIDeviceManager_iface;
8911 return S_OK;
8914 /***********************************************************************
8915 * MFLockDXGIDeviceManager (mfplat.@)
8917 HRESULT WINAPI MFLockDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
8919 HRESULT hr = S_OK;
8921 TRACE("%p, %p.\n", token, manager);
8923 EnterCriticalSection(&shared_dm_cs);
8925 if (!shared_dm.manager)
8926 hr = MFCreateDXGIDeviceManager(&shared_dm.token, &shared_dm.manager);
8928 if (SUCCEEDED(hr))
8930 *manager = shared_dm.manager;
8931 IMFDXGIDeviceManager_AddRef(*manager);
8932 shared_dm.locks++;
8934 if (token) *token = shared_dm.token;
8937 LeaveCriticalSection(&shared_dm_cs);
8939 return hr;
8942 /***********************************************************************
8943 * MFUnlockDXGIDeviceManager (mfplat.@)
8945 HRESULT WINAPI MFUnlockDXGIDeviceManager(void)
8947 TRACE("\n");
8949 EnterCriticalSection(&shared_dm_cs);
8951 if (shared_dm.manager)
8953 IMFDXGIDeviceManager_Release(shared_dm.manager);
8954 if (!--shared_dm.locks)
8956 shared_dm.manager = NULL;
8957 shared_dm.token = 0;
8961 LeaveCriticalSection(&shared_dm_cs);
8963 return S_OK;
8968 * MFllMulDiv implementation is derived from gstreamer utility functions code (gstutils.c),
8969 * released under LGPL2. Full authors list follows.
8970 * ===================================================================================
8971 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
8972 * 2000 Wim Taymans <wtay@chello.be>
8973 * 2002 Thomas Vander Stichele <thomas@apestaart.org>
8974 * 2004 Wim Taymans <wim@fluendo.com>
8975 * 2015 Jan Schmidt <jan@centricular.com>
8976 * ===================================================================================
8979 static void llmult128(ULARGE_INTEGER *c1, ULARGE_INTEGER *c0, LONGLONG val, LONGLONG num)
8981 ULARGE_INTEGER a1, b0, v, n;
8983 v.QuadPart = llabs(val);
8984 n.QuadPart = llabs(num);
8986 /* do 128 bits multiply
8987 * nh nl
8988 * * vh vl
8989 * ----------
8990 * a0 = vl * nl
8991 * a1 = vl * nh
8992 * b0 = vh * nl
8993 * b1 = + vh * nh
8994 * -------------------
8995 * c1h c1l c0h c0l
8997 * "a0" is optimized away, result is stored directly in c0. "b1" is
8998 * optimized away, result is stored directly in c1.
9000 c0->QuadPart = (ULONGLONG)v.LowPart * n.LowPart;
9001 a1.QuadPart = (ULONGLONG)v.LowPart * n.HighPart;
9002 b0.QuadPart = (ULONGLONG)v.HighPart * n.LowPart;
9004 /* add the high word of a0 to the low words of a1 and b0 using c1 as
9005 * scratch space to capture the carry. the low word of the result becomes
9006 * the final high word of c0 */
9007 c1->QuadPart = (ULONGLONG)c0->HighPart + a1.LowPart + b0.LowPart;
9008 c0->HighPart = c1->LowPart;
9010 /* add the carry from the result above (found in the high word of c1) and
9011 * the high words of a1 and b0 to b1, the result is c1. */
9012 c1->QuadPart = (ULONGLONG)v.HighPart * n.HighPart + c1->HighPart + a1.HighPart + b0.HighPart;
9015 static ULONGLONG lldiv128(ULARGE_INTEGER c1, ULARGE_INTEGER c0, LONGLONG denom)
9017 ULARGE_INTEGER q1, q0, rhat;
9018 ULARGE_INTEGER v, cmp1, cmp2;
9019 unsigned int s = 0;
9021 v.QuadPart = llabs(denom);
9023 /* 64bit numerator */
9024 if (c1.QuadPart == 0)
9025 return c0.QuadPart / v.QuadPart;
9027 /* 96bit numerator, 32bit denominator */
9028 if (v.HighPart == 0 && c1.HighPart == 0)
9030 ULONGLONG low = c0.LowPart, high = c0.HighPart + ((ULONGLONG)c1.LowPart << 32);
9031 low += (high % v.LowPart) << 32;
9032 return ((high / v.LowPart) << 32) + (low / v.LowPart);
9035 /* 128bit numerator, 32bit denominator */
9036 if (v.HighPart == 0)
9037 return UI64_MAX;
9039 /* count number of leading zeroes */
9040 BitScanReverse(&s, v.HighPart);
9041 s = 31 - s;
9043 if (s)
9045 /* normalize divisor and dividend */
9046 v.QuadPart <<= s;
9047 c1.QuadPart = (c1.QuadPart << s) | (c0.HighPart >> (32 - s));
9048 c0.QuadPart <<= s;
9051 q1.QuadPart = c1.QuadPart / v.HighPart;
9052 rhat.QuadPart = c1.QuadPart - q1.QuadPart * v.HighPart;
9054 cmp1.HighPart = rhat.LowPart;
9055 cmp1.LowPart = c0.HighPart;
9056 cmp2.QuadPart = q1.QuadPart * v.LowPart;
9058 while (q1.HighPart || cmp2.QuadPart > cmp1.QuadPart)
9060 q1.QuadPart--;
9061 rhat.QuadPart += v.HighPart;
9062 if (rhat.HighPart)
9063 break;
9064 cmp1.HighPart = rhat.LowPart;
9065 cmp2.QuadPart -= v.LowPart;
9067 c1.HighPart = c1.LowPart;
9068 c1.LowPart = c0.HighPart;
9069 c1.QuadPart -= q1.QuadPart * v.QuadPart;
9070 q0.QuadPart = c1.QuadPart / v.HighPart;
9071 rhat.QuadPart = c1.QuadPart - q0.QuadPart * v.HighPart;
9073 cmp1.HighPart = rhat.LowPart;
9074 cmp1.LowPart = c0.LowPart;
9075 cmp2.QuadPart = q0.QuadPart * v.LowPart;
9077 while (q0.HighPart || cmp2.QuadPart > cmp1.QuadPart)
9079 q0.QuadPart--;
9080 rhat.QuadPart += v.HighPart;
9081 if (rhat.HighPart)
9082 break;
9083 cmp1.HighPart = rhat.LowPart;
9084 cmp2.QuadPart -= v.LowPart;
9086 q0.HighPart += q1.LowPart;
9088 return q0.QuadPart;
9091 /***********************************************************************
9092 * MFllMulDiv (mfplat.@)
9094 LONGLONG WINAPI MFllMulDiv(LONGLONG val, LONGLONG num, LONGLONG denom, LONGLONG factor)
9096 #define LLOVERFLOW (sign ? I64_MIN : I64_MAX)
9097 unsigned int sign, factor_sign, denom_sign;
9098 ULARGE_INTEGER c1, c0;
9099 ULONGLONG ret;
9101 TRACE("%s, %s, %s, %s.\n", wine_dbgstr_longlong(val), wine_dbgstr_longlong(num),
9102 wine_dbgstr_longlong(denom), wine_dbgstr_longlong(factor));
9104 /* compute 128-bit numerator product */
9105 llmult128(&c1, &c0, val, num);
9107 sign = (val < 0) ^ (num < 0);
9108 factor_sign = factor < 0;
9109 denom_sign = denom < 0;
9111 factor = llabs(factor);
9112 if (sign == factor_sign)
9114 if (UI64_MAX - c0.QuadPart < factor)
9116 if (c1.QuadPart == UI64_MAX) return LLOVERFLOW;
9117 c1.QuadPart++;
9119 c0.QuadPart += factor;
9121 else
9123 if (c0.QuadPart >= factor)
9124 c0.QuadPart -= factor;
9125 else
9127 if (c1.QuadPart)
9128 c1.QuadPart--;
9129 else
9130 sign = !sign;
9132 c0.QuadPart = factor - c0.QuadPart;
9136 if (c1.QuadPart >= denom) return LLOVERFLOW;
9138 /* compute quotient, fits in 64 bits */
9139 ret = lldiv128(c1, c0, denom);
9140 sign ^= denom_sign;
9141 if (ret >= I64_MAX) return LLOVERFLOW;
9142 return sign ? -(LONGLONG)ret : ret;
9143 #undef LLOVERFLOW