include: Make sure __int64 is correctly defined on PPC64.
[wine.git] / dlls / mfplat / main.c
blobb78cfc33e600422414710f294869b3c814b5cd80
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>
23 #define COBJMACROS
24 #define NONAMELESSUNION
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winreg.h"
31 #include "initguid.h"
32 #include "rtworkq.h"
33 #include "ole2.h"
34 #include "propsys.h"
35 #include "d3d11.h"
36 #include "uuids.h"
38 #include "wine/debug.h"
39 #include "wine/list.h"
41 #include "mfplat_private.h"
42 #include "mfreadwrite.h"
43 #include "mfmediaengine.h"
44 #include "propvarutil.h"
45 #include "strsafe.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
49 static HRESULT heap_strdupW(const WCHAR *str, WCHAR **dest)
51 HRESULT hr = S_OK;
53 if (str)
55 unsigned int size;
57 size = (lstrlenW(str) + 1) * sizeof(WCHAR);
58 *dest = heap_alloc(size);
59 if (*dest)
60 memcpy(*dest, str, size);
61 else
62 hr = E_OUTOFMEMORY;
64 else
65 *dest = NULL;
67 return hr;
70 struct local_handler
72 struct list entry;
73 union
75 WCHAR *scheme;
76 struct
78 WCHAR *extension;
79 WCHAR *mime;
80 } bytestream;
81 } u;
82 IMFActivate *activate;
85 static CRITICAL_SECTION local_handlers_section = { NULL, -1, 0, 0, 0, 0 };
87 static struct list local_scheme_handlers = LIST_INIT(local_scheme_handlers);
88 static struct list local_bytestream_handlers = LIST_INIT(local_bytestream_handlers);
90 struct mft_registration
92 struct list entry;
93 IClassFactory *factory;
94 CLSID clsid;
95 GUID category;
96 WCHAR *name;
97 DWORD flags;
98 MFT_REGISTER_TYPE_INFO *input_types;
99 UINT32 input_types_count;
100 MFT_REGISTER_TYPE_INFO *output_types;
101 UINT32 output_types_count;
102 BOOL local;
105 static CRITICAL_SECTION local_mfts_section = { NULL, -1, 0, 0, 0, 0 };
107 static struct list local_mfts = LIST_INIT(local_mfts);
109 struct transform_activate
111 struct attributes attributes;
112 IMFActivate IMFActivate_iface;
113 IClassFactory *factory;
114 IMFTransform *transform;
117 struct system_clock
119 IMFClock IMFClock_iface;
120 LONG refcount;
123 struct system_time_source
125 IMFPresentationTimeSource IMFPresentationTimeSource_iface;
126 IMFClockStateSink IMFClockStateSink_iface;
127 LONG refcount;
128 MFCLOCK_STATE state;
129 IMFClock *clock;
130 LONGLONG start_offset;
131 float rate;
132 int i_rate;
133 CRITICAL_SECTION cs;
136 static void system_time_source_apply_rate(const struct system_time_source *source, LONGLONG *value)
138 if (source->i_rate)
139 *value *= source->i_rate;
140 else
141 *value *= source->rate;
144 static struct system_time_source *impl_from_IMFPresentationTimeSource(IMFPresentationTimeSource *iface)
146 return CONTAINING_RECORD(iface, struct system_time_source, IMFPresentationTimeSource_iface);
149 static struct system_time_source *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
151 return CONTAINING_RECORD(iface, struct system_time_source, IMFClockStateSink_iface);
154 static struct system_clock *impl_from_IMFClock(IMFClock *iface)
156 return CONTAINING_RECORD(iface, struct system_clock, IMFClock_iface);
159 static struct transform_activate *impl_from_IMFActivate(IMFActivate *iface)
161 return CONTAINING_RECORD(iface, struct transform_activate, IMFActivate_iface);
164 static HRESULT WINAPI transform_activate_QueryInterface(IMFActivate *iface, REFIID riid, void **out)
166 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
168 if (IsEqualIID(riid, &IID_IMFActivate) ||
169 IsEqualIID(riid, &IID_IMFAttributes) ||
170 IsEqualIID(riid, &IID_IUnknown))
172 *out = iface;
173 IMFActivate_AddRef(iface);
174 return S_OK;
177 WARN("Unsupported %s.\n", debugstr_guid(riid));
178 *out = NULL;
179 return E_NOINTERFACE;
182 static ULONG WINAPI transform_activate_AddRef(IMFActivate *iface)
184 struct transform_activate *activate = impl_from_IMFActivate(iface);
185 ULONG refcount = InterlockedIncrement(&activate->attributes.ref);
187 TRACE("%p, refcount %u.\n", iface, refcount);
189 return refcount;
192 static ULONG WINAPI transform_activate_Release(IMFActivate *iface)
194 struct transform_activate *activate = impl_from_IMFActivate(iface);
195 ULONG refcount = InterlockedDecrement(&activate->attributes.ref);
197 TRACE("%p, refcount %u.\n", iface, refcount);
199 if (!refcount)
201 clear_attributes_object(&activate->attributes);
202 if (activate->factory)
203 IClassFactory_Release(activate->factory);
204 if (activate->transform)
205 IMFTransform_Release(activate->transform);
206 heap_free(activate);
209 return refcount;
212 static HRESULT WINAPI transform_activate_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value)
214 struct transform_activate *activate = impl_from_IMFActivate(iface);
216 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
218 return attributes_GetItem(&activate->attributes, key, value);
221 static HRESULT WINAPI transform_activate_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
223 struct transform_activate *activate = impl_from_IMFActivate(iface);
225 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
227 return attributes_GetItemType(&activate->attributes, key, type);
230 static HRESULT WINAPI transform_activate_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value,
231 BOOL *result)
233 struct transform_activate *activate = impl_from_IMFActivate(iface);
235 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
237 return attributes_CompareItem(&activate->attributes, key, value, result);
240 static HRESULT WINAPI transform_activate_Compare(IMFActivate *iface, IMFAttributes *theirs,
241 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
243 struct transform_activate *activate = impl_from_IMFActivate(iface);
245 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
247 return attributes_Compare(&activate->attributes, theirs, match_type, ret);
250 static HRESULT WINAPI transform_activate_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value)
252 struct transform_activate *activate = impl_from_IMFActivate(iface);
254 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
256 return attributes_GetUINT32(&activate->attributes, key, value);
259 static HRESULT WINAPI transform_activate_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value)
261 struct transform_activate *activate = impl_from_IMFActivate(iface);
263 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
265 return attributes_GetUINT64(&activate->attributes, key, value);
268 static HRESULT WINAPI transform_activate_GetDouble(IMFActivate *iface, REFGUID key, double *value)
270 struct transform_activate *activate = impl_from_IMFActivate(iface);
272 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
274 return attributes_GetDouble(&activate->attributes, key, value);
277 static HRESULT WINAPI transform_activate_GetGUID(IMFActivate *iface, REFGUID key, GUID *value)
279 struct transform_activate *activate = impl_from_IMFActivate(iface);
281 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
283 return attributes_GetGUID(&activate->attributes, key, value);
286 static HRESULT WINAPI transform_activate_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length)
288 struct transform_activate *activate = impl_from_IMFActivate(iface);
290 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
292 return attributes_GetStringLength(&activate->attributes, key, length);
295 static HRESULT WINAPI transform_activate_GetString(IMFActivate *iface, REFGUID key, WCHAR *value,
296 UINT32 size, UINT32 *length)
298 struct transform_activate *activate = impl_from_IMFActivate(iface);
300 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
302 return attributes_GetString(&activate->attributes, key, value, size, length);
305 static HRESULT WINAPI transform_activate_GetAllocatedString(IMFActivate *iface, REFGUID key, WCHAR **value,
306 UINT32 *length)
308 struct transform_activate *activate = impl_from_IMFActivate(iface);
310 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
312 return attributes_GetAllocatedString(&activate->attributes, key, value, length);
315 static HRESULT WINAPI transform_activate_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size)
317 struct transform_activate *activate = impl_from_IMFActivate(iface);
319 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
321 return attributes_GetBlobSize(&activate->attributes, key, size);
324 static HRESULT WINAPI transform_activate_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf, UINT32 bufsize,
325 UINT32 *blobsize)
327 struct transform_activate *activate = impl_from_IMFActivate(iface);
329 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
331 return attributes_GetBlob(&activate->attributes, key, buf, bufsize, blobsize);
334 static HRESULT WINAPI transform_activate_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size)
336 struct transform_activate *activate = impl_from_IMFActivate(iface);
338 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
340 return attributes_GetAllocatedBlob(&activate->attributes, key, buf, size);
343 static HRESULT WINAPI transform_activate_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **out)
345 struct transform_activate *activate = impl_from_IMFActivate(iface);
347 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
349 return attributes_GetUnknown(&activate->attributes, key, riid, out);
352 static HRESULT WINAPI transform_activate_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value)
354 struct transform_activate *activate = impl_from_IMFActivate(iface);
356 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
358 return attributes_SetItem(&activate->attributes, key, value);
361 static HRESULT WINAPI transform_activate_DeleteItem(IMFActivate *iface, REFGUID key)
363 struct transform_activate *activate = impl_from_IMFActivate(iface);
365 TRACE("%p, %s.\n", iface, debugstr_attr(key));
367 return attributes_DeleteItem(&activate->attributes, key);
370 static HRESULT WINAPI transform_activate_DeleteAllItems(IMFActivate *iface)
372 struct transform_activate *activate = impl_from_IMFActivate(iface);
374 TRACE("%p.\n", iface);
376 return attributes_DeleteAllItems(&activate->attributes);
379 static HRESULT WINAPI transform_activate_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value)
381 struct transform_activate *activate = impl_from_IMFActivate(iface);
383 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
385 return attributes_SetUINT32(&activate->attributes, key, value);
388 static HRESULT WINAPI transform_activate_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value)
390 struct transform_activate *activate = impl_from_IMFActivate(iface);
392 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
394 return attributes_SetUINT64(&activate->attributes, key, value);
397 static HRESULT WINAPI transform_activate_SetDouble(IMFActivate *iface, REFGUID key, double value)
399 struct transform_activate *activate = impl_from_IMFActivate(iface);
401 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
403 return attributes_SetDouble(&activate->attributes, key, value);
406 static HRESULT WINAPI transform_activate_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value)
408 struct transform_activate *activate = impl_from_IMFActivate(iface);
410 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
412 return attributes_SetGUID(&activate->attributes, key, value);
415 static HRESULT WINAPI transform_activate_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value)
417 struct transform_activate *activate = impl_from_IMFActivate(iface);
419 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
421 return attributes_SetString(&activate->attributes, key, value);
424 static HRESULT WINAPI transform_activate_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size)
426 struct transform_activate *activate = impl_from_IMFActivate(iface);
428 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
430 return attributes_SetBlob(&activate->attributes, key, buf, size);
433 static HRESULT WINAPI transform_activate_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown)
435 struct transform_activate *activate = impl_from_IMFActivate(iface);
437 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
439 return attributes_SetUnknown(&activate->attributes, key, unknown);
442 static HRESULT WINAPI transform_activate_LockStore(IMFActivate *iface)
444 struct transform_activate *activate = impl_from_IMFActivate(iface);
446 TRACE("%p.\n", iface);
448 return attributes_LockStore(&activate->attributes);
451 static HRESULT WINAPI transform_activate_UnlockStore(IMFActivate *iface)
453 struct transform_activate *activate = impl_from_IMFActivate(iface);
455 TRACE("%p.\n", iface);
457 return attributes_UnlockStore(&activate->attributes);
460 static HRESULT WINAPI transform_activate_GetCount(IMFActivate *iface, UINT32 *count)
462 struct transform_activate *activate = impl_from_IMFActivate(iface);
464 TRACE("%p, %p.\n", iface, count);
466 return attributes_GetCount(&activate->attributes, count);
469 static HRESULT WINAPI transform_activate_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key,
470 PROPVARIANT *value)
472 struct transform_activate *activate = impl_from_IMFActivate(iface);
474 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
476 return attributes_GetItemByIndex(&activate->attributes, index, key, value);
479 static HRESULT WINAPI transform_activate_CopyAllItems(IMFActivate *iface, IMFAttributes *dest)
481 struct transform_activate *activate = impl_from_IMFActivate(iface);
483 TRACE("%p, %p.\n", iface, dest);
485 return attributes_CopyAllItems(&activate->attributes, dest);
488 static HRESULT WINAPI transform_activate_ActivateObject(IMFActivate *iface, REFIID riid, void **obj)
490 struct transform_activate *activate = impl_from_IMFActivate(iface);
491 CLSID clsid;
492 HRESULT hr;
494 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
496 EnterCriticalSection(&activate->attributes.cs);
498 if (!activate->transform)
500 if (activate->factory)
502 if (FAILED(hr = IClassFactory_CreateInstance(activate->factory, NULL, &IID_IMFTransform,
503 (void **)&activate->transform)))
505 hr = MF_E_INVALIDREQUEST;
508 else
510 if (SUCCEEDED(hr = attributes_GetGUID(&activate->attributes, &MFT_TRANSFORM_CLSID_Attribute, &clsid)))
512 if (FAILED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform,
513 (void **)&activate->transform)))
515 hr = MF_E_INVALIDREQUEST;
521 if (activate->transform)
522 hr = IMFTransform_QueryInterface(activate->transform, riid, obj);
524 LeaveCriticalSection(&activate->attributes.cs);
526 return hr;
529 static HRESULT WINAPI transform_activate_ShutdownObject(IMFActivate *iface)
531 struct transform_activate *activate = impl_from_IMFActivate(iface);
533 TRACE("%p.\n", iface);
535 EnterCriticalSection(&activate->attributes.cs);
537 if (activate->transform)
539 IMFTransform_Release(activate->transform);
540 activate->transform = NULL;
543 LeaveCriticalSection(&activate->attributes.cs);
545 return S_OK;
548 static HRESULT WINAPI transform_activate_DetachObject(IMFActivate *iface)
550 TRACE("%p.\n", iface);
552 return E_NOTIMPL;
555 static const IMFActivateVtbl transform_activate_vtbl =
557 transform_activate_QueryInterface,
558 transform_activate_AddRef,
559 transform_activate_Release,
560 transform_activate_GetItem,
561 transform_activate_GetItemType,
562 transform_activate_CompareItem,
563 transform_activate_Compare,
564 transform_activate_GetUINT32,
565 transform_activate_GetUINT64,
566 transform_activate_GetDouble,
567 transform_activate_GetGUID,
568 transform_activate_GetStringLength,
569 transform_activate_GetString,
570 transform_activate_GetAllocatedString,
571 transform_activate_GetBlobSize,
572 transform_activate_GetBlob,
573 transform_activate_GetAllocatedBlob,
574 transform_activate_GetUnknown,
575 transform_activate_SetItem,
576 transform_activate_DeleteItem,
577 transform_activate_DeleteAllItems,
578 transform_activate_SetUINT32,
579 transform_activate_SetUINT64,
580 transform_activate_SetDouble,
581 transform_activate_SetGUID,
582 transform_activate_SetString,
583 transform_activate_SetBlob,
584 transform_activate_SetUnknown,
585 transform_activate_LockStore,
586 transform_activate_UnlockStore,
587 transform_activate_GetCount,
588 transform_activate_GetItemByIndex,
589 transform_activate_CopyAllItems,
590 transform_activate_ActivateObject,
591 transform_activate_ShutdownObject,
592 transform_activate_DetachObject,
595 static HRESULT create_transform_activate(IClassFactory *factory, IMFActivate **activate)
597 struct transform_activate *object;
598 HRESULT hr;
600 object = heap_alloc_zero(sizeof(*object));
601 if (!object)
602 return E_OUTOFMEMORY;
604 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
606 heap_free(object);
607 return hr;
610 object->IMFActivate_iface.lpVtbl = &transform_activate_vtbl;
611 object->factory = factory;
612 if (object->factory)
613 IClassFactory_AddRef(object->factory);
615 *activate = &object->IMFActivate_iface;
617 return S_OK;
620 HRESULT WINAPI MFCreateTransformActivate(IMFActivate **activate)
622 TRACE("%p.\n", activate);
624 return create_transform_activate(NULL, activate);
627 static const WCHAR transform_keyW[] = L"MediaFoundation\\Transforms";
628 static const WCHAR categories_keyW[] = L"MediaFoundation\\Transforms\\Categories";
630 static const BYTE guid_conv_table[256] =
632 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
633 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
634 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
635 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
636 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
637 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
638 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
641 static WCHAR* GUIDToString(WCHAR *str, REFGUID guid)
643 swprintf(str, 39, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
644 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1],
645 guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5],
646 guid->Data4[6], guid->Data4[7]);
648 return str;
651 static inline BOOL is_valid_hex(WCHAR c)
653 if (!(((c >= '0') && (c <= '9')) ||
654 ((c >= 'a') && (c <= 'f')) ||
655 ((c >= 'A') && (c <= 'F'))))
656 return FALSE;
657 return TRUE;
660 static BOOL GUIDFromString(LPCWSTR s, GUID *id)
662 int i;
664 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
666 id->Data1 = 0;
667 for (i = 0; i < 8; i++)
669 if (!is_valid_hex(s[i])) return FALSE;
670 id->Data1 = (id->Data1 << 4) | guid_conv_table[s[i]];
672 if (s[8]!='-') return FALSE;
674 id->Data2 = 0;
675 for (i = 9; i < 13; i++)
677 if (!is_valid_hex(s[i])) return FALSE;
678 id->Data2 = (id->Data2 << 4) | guid_conv_table[s[i]];
680 if (s[13]!='-') return FALSE;
682 id->Data3 = 0;
683 for (i = 14; i < 18; i++)
685 if (!is_valid_hex(s[i])) return FALSE;
686 id->Data3 = (id->Data3 << 4) | guid_conv_table[s[i]];
688 if (s[18]!='-') return FALSE;
690 for (i = 19; i < 36; i+=2)
692 if (i == 23)
694 if (s[i]!='-') return FALSE;
695 i++;
697 if (!is_valid_hex(s[i]) || !is_valid_hex(s[i+1])) return FALSE;
698 id->Data4[(i-19)/2] = guid_conv_table[s[i]] << 4 | guid_conv_table[s[i+1]];
701 if (!s[36]) return TRUE;
702 return FALSE;
705 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
707 switch (reason)
709 case DLL_WINE_PREATTACH:
710 return FALSE; /* prefer native version */
711 case DLL_PROCESS_ATTACH:
712 DisableThreadLibraryCalls(instance);
713 break;
716 return TRUE;
719 static HRESULT register_transform(const CLSID *clsid, const WCHAR *name, UINT32 flags,
720 UINT32 cinput, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
721 const MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
723 HRESULT hr = S_OK;
724 HKEY hclsid = 0;
725 WCHAR buffer[64];
726 DWORD size, ret;
727 WCHAR str[250];
728 UINT8 *blob;
730 GUIDToString(buffer, clsid);
731 swprintf(str, ARRAY_SIZE(str), L"%s\\%s", transform_keyW, buffer);
733 if ((ret = RegCreateKeyW(HKEY_CLASSES_ROOT, str, &hclsid)))
734 hr = HRESULT_FROM_WIN32(ret);
736 if (SUCCEEDED(hr))
738 size = (lstrlenW(name) + 1) * sizeof(WCHAR);
739 if ((ret = RegSetValueExW(hclsid, NULL, 0, REG_SZ, (BYTE *)name, size)))
740 hr = HRESULT_FROM_WIN32(ret);
743 if (SUCCEEDED(hr) && cinput && input_types)
745 size = cinput * sizeof(MFT_REGISTER_TYPE_INFO);
746 if ((ret = RegSetValueExW(hclsid, L"InputTypes", 0, REG_BINARY, (BYTE *)input_types, size)))
747 hr = HRESULT_FROM_WIN32(ret);
750 if (SUCCEEDED(hr) && coutput && output_types)
752 size = coutput * sizeof(MFT_REGISTER_TYPE_INFO);
753 if ((ret = RegSetValueExW(hclsid, L"OutputTypes", 0, REG_BINARY, (BYTE *)output_types, size)))
754 hr = HRESULT_FROM_WIN32(ret);
757 if (SUCCEEDED(hr) && attributes)
759 if (SUCCEEDED(hr = MFGetAttributesAsBlobSize(attributes, &size)))
761 if ((blob = heap_alloc(size)))
763 if (SUCCEEDED(hr = MFGetAttributesAsBlob(attributes, blob, size)))
765 if ((ret = RegSetValueExW(hclsid, L"Attributes", 0, REG_BINARY, blob, size)))
766 hr = HRESULT_FROM_WIN32(ret);
768 heap_free(blob);
770 else
771 hr = E_OUTOFMEMORY;
775 if (SUCCEEDED(hr) && flags)
777 if ((ret = RegSetValueExW(hclsid, L"MFTFlags", 0, REG_DWORD, (BYTE *)&flags, sizeof(flags))))
778 hr = HRESULT_FROM_WIN32(ret);
781 RegCloseKey(hclsid);
782 return hr;
785 static HRESULT register_category(CLSID *clsid, GUID *category)
787 HKEY htmp1;
788 WCHAR guid1[64], guid2[64];
789 WCHAR str[350];
791 GUIDToString(guid1, category);
792 GUIDToString(guid2, clsid);
794 swprintf(str, ARRAY_SIZE(str), L"%s\\%s\\%s", categories_keyW, guid1, guid2);
796 if (RegCreateKeyW(HKEY_CLASSES_ROOT, str, &htmp1))
797 return E_FAIL;
799 RegCloseKey(htmp1);
800 return S_OK;
803 /***********************************************************************
804 * MFTRegister (mfplat.@)
806 HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags, UINT32 cinput,
807 MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
808 MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
810 HRESULT hr;
812 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p, %p.\n", debugstr_guid(&clsid), debugstr_guid(&category),
813 debugstr_w(name), flags, cinput, input_types, coutput, output_types, attributes);
815 hr = register_transform(&clsid, name, flags, cinput, input_types, coutput, output_types, attributes);
816 if(FAILED(hr))
817 ERR("Failed to write register transform\n");
819 if (SUCCEEDED(hr))
820 hr = register_category(&clsid, &category);
822 return hr;
825 static void release_mft_registration(struct mft_registration *mft)
827 if (mft->factory)
828 IClassFactory_Release(mft->factory);
829 heap_free(mft->name);
830 heap_free(mft->input_types);
831 heap_free(mft->output_types);
832 heap_free(mft);
835 static HRESULT mft_register_local(IClassFactory *factory, REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
836 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
837 const MFT_REGISTER_TYPE_INFO *output_types)
839 struct mft_registration *mft, *cur, *unreg_mft = NULL;
840 HRESULT hr;
842 if (!factory && !clsid)
844 WARN("Can't register without factory or CLSID.\n");
845 return E_FAIL;
848 mft = heap_alloc_zero(sizeof(*mft));
849 if (!mft)
850 return E_OUTOFMEMORY;
852 mft->factory = factory;
853 if (mft->factory)
854 IClassFactory_AddRef(mft->factory);
855 if (clsid)
856 mft->clsid = *clsid;
857 mft->category = *category;
858 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
859 flags |= MFT_ENUM_FLAG_SYNCMFT;
860 mft->flags = flags;
861 mft->local = TRUE;
862 if (FAILED(hr = heap_strdupW(name, &mft->name)))
863 goto failed;
865 if (input_count && input_types)
867 mft->input_types_count = input_count;
868 if (!(mft->input_types = heap_calloc(mft->input_types_count, sizeof(*input_types))))
870 hr = E_OUTOFMEMORY;
871 goto failed;
873 memcpy(mft->input_types, input_types, mft->input_types_count * sizeof(*input_types));
876 if (output_count && output_types)
878 mft->output_types_count = output_count;
879 if (!(mft->output_types = heap_calloc(mft->output_types_count, sizeof(*output_types))))
881 hr = E_OUTOFMEMORY;
882 goto failed;
884 memcpy(mft->output_types, output_types, mft->output_types_count * sizeof(*output_types));
887 EnterCriticalSection(&local_mfts_section);
889 LIST_FOR_EACH_ENTRY(cur, &local_mfts, struct mft_registration, entry)
891 if (cur->factory == factory)
893 unreg_mft = cur;
894 list_remove(&cur->entry);
895 break;
898 list_add_tail(&local_mfts, &mft->entry);
900 LeaveCriticalSection(&local_mfts_section);
902 if (unreg_mft)
903 release_mft_registration(unreg_mft);
905 failed:
906 if (FAILED(hr))
907 release_mft_registration(mft);
909 return hr;
912 HRESULT WINAPI MFTRegisterLocal(IClassFactory *factory, REFGUID category, LPCWSTR name, UINT32 flags,
913 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
914 const MFT_REGISTER_TYPE_INFO *output_types)
916 TRACE("%p, %s, %s, %#x, %u, %p, %u, %p.\n", factory, debugstr_guid(category), debugstr_w(name), flags, input_count,
917 input_types, output_count, output_types);
919 return mft_register_local(factory, NULL, category, name, flags, input_count, input_types, output_count, output_types);
922 HRESULT WINAPI MFTRegisterLocalByCLSID(REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
923 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
924 const MFT_REGISTER_TYPE_INFO *output_types)
926 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p.\n", debugstr_guid(clsid), debugstr_guid(category), debugstr_w(name), flags,
927 input_count, input_types, output_count, output_types);
929 return mft_register_local(NULL, clsid, category, name, flags, input_count, input_types, output_count, output_types);
932 static HRESULT mft_unregister_local(IClassFactory *factory, REFCLSID clsid)
934 struct mft_registration *cur, *cur2;
935 BOOL unregister_all = !factory && !clsid;
936 struct list unreg;
938 list_init(&unreg);
940 EnterCriticalSection(&local_mfts_section);
942 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &local_mfts, struct mft_registration, entry)
944 if (!unregister_all)
946 if ((factory && cur->factory == factory) || IsEqualCLSID(&cur->clsid, clsid))
948 list_remove(&cur->entry);
949 list_add_tail(&unreg, &cur->entry);
950 break;
953 else
955 list_remove(&cur->entry);
956 list_add_tail(&unreg, &cur->entry);
960 LeaveCriticalSection(&local_mfts_section);
962 if (!unregister_all && list_empty(&unreg))
963 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
965 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &unreg, struct mft_registration, entry)
967 list_remove(&cur->entry);
968 release_mft_registration(cur);
971 return S_OK;
974 HRESULT WINAPI MFTUnregisterLocalByCLSID(CLSID clsid)
976 TRACE("%s.\n", debugstr_guid(&clsid));
978 return mft_unregister_local(NULL, &clsid);
981 HRESULT WINAPI MFTUnregisterLocal(IClassFactory *factory)
983 TRACE("%p.\n", factory);
985 return mft_unregister_local(factory, NULL);
988 MFTIME WINAPI MFGetSystemTime(void)
990 MFTIME mf;
992 GetSystemTimeAsFileTime( (FILETIME*)&mf );
994 return mf;
997 static BOOL mft_is_type_info_match(struct mft_registration *mft, const GUID *category, UINT32 flags,
998 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
999 const MFT_REGISTER_TYPE_INFO *output_type)
1001 BOOL matching = TRUE;
1002 DWORD model;
1003 int i;
1005 if (!IsEqualGUID(category, &mft->category))
1006 return FALSE;
1008 /* Default model is synchronous. */
1009 model = mft->flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE);
1010 if (!model)
1011 model = MFT_ENUM_FLAG_SYNCMFT;
1012 if (!(model & flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
1013 return FALSE;
1015 /* These flags should be explicitly enabled. */
1016 if (mft->flags & ~flags & (MFT_ENUM_FLAG_FIELDOFUSE | MFT_ENUM_FLAG_TRANSCODE_ONLY))
1017 return FALSE;
1019 if (flags & MFT_ENUM_FLAG_SORTANDFILTER && !mft->factory && plugin_control
1020 && IMFPluginControl_IsDisabled(plugin_control, MF_Plugin_Type_MFT, &mft->clsid) == S_OK)
1022 return FALSE;
1025 if (input_type)
1027 for (i = 0, matching = FALSE; input_type && i < mft->input_types_count; ++i)
1029 if (!memcmp(&mft->input_types[i], input_type, sizeof(*input_type)))
1031 matching = TRUE;
1032 break;
1037 if (output_type && matching)
1039 for (i = 0, matching = FALSE; i < mft->output_types_count; ++i)
1041 if (!memcmp(&mft->output_types[i], output_type, sizeof(*output_type)))
1043 matching = TRUE;
1044 break;
1049 return matching;
1052 static void mft_get_reg_type_info(const WCHAR *clsidW, const WCHAR *typeW, MFT_REGISTER_TYPE_INFO **type,
1053 UINT32 *count)
1055 HKEY htransform, hfilter;
1056 DWORD reg_type, size;
1058 *type = NULL;
1059 *count = 0;
1061 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1062 return;
1064 if (RegOpenKeyW(htransform, clsidW, &hfilter))
1066 RegCloseKey(htransform);
1067 return;
1070 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, NULL, &size))
1071 goto out;
1073 if (reg_type != REG_BINARY)
1074 goto out;
1076 if (!size || size % sizeof(**type))
1077 goto out;
1079 if (!(*type = heap_alloc(size)))
1080 goto out;
1082 *count = size / sizeof(**type);
1084 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, (BYTE *)*type, &size))
1086 heap_free(*type);
1087 *type = NULL;
1088 *count = 0;
1091 out:
1092 RegCloseKey(hfilter);
1093 RegCloseKey(htransform);
1096 static void mft_get_reg_flags(const WCHAR *clsidW, const WCHAR *nameW, DWORD *flags)
1098 DWORD ret, reg_type, size;
1099 HKEY hroot, hmft;
1101 *flags = 0;
1103 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &hroot))
1104 return;
1106 ret = RegOpenKeyW(hroot, clsidW, &hmft);
1107 RegCloseKey(hroot);
1108 if (ret)
1109 return;
1111 reg_type = 0;
1112 if (!RegQueryValueExW(hmft, nameW, NULL, &reg_type, NULL, &size) && reg_type == REG_DWORD)
1113 RegQueryValueExW(hmft, nameW, NULL, &reg_type, (BYTE *)flags, &size);
1115 RegCloseKey(hmft);
1118 static HRESULT mft_collect_machine_reg(struct list *mfts, const GUID *category, UINT32 flags,
1119 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
1120 const MFT_REGISTER_TYPE_INFO *output_type)
1122 struct mft_registration mft, *cur;
1123 HKEY hcategory, hlist;
1124 WCHAR clsidW[64];
1125 DWORD ret, size;
1126 int index = 0;
1128 if (RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1129 return E_FAIL;
1131 GUIDToString(clsidW, category);
1132 ret = RegOpenKeyW(hcategory, clsidW, &hlist);
1133 RegCloseKey(hcategory);
1134 if (ret)
1135 return E_FAIL;
1137 size = ARRAY_SIZE(clsidW);
1138 while (!RegEnumKeyExW(hlist, index, clsidW, &size, NULL, NULL, NULL, NULL))
1140 memset(&mft, 0, sizeof(mft));
1141 mft.category = *category;
1142 if (!GUIDFromString(clsidW, &mft.clsid))
1143 goto next;
1145 mft_get_reg_flags(clsidW, L"MFTFlags", &mft.flags);
1147 if (output_type)
1148 mft_get_reg_type_info(clsidW, L"OutputTypes", &mft.output_types, &mft.output_types_count);
1150 if (input_type)
1151 mft_get_reg_type_info(clsidW, L"InputTypes", &mft.input_types, &mft.input_types_count);
1153 if (!mft_is_type_info_match(&mft, category, flags, plugin_control, input_type, output_type))
1155 heap_free(mft.input_types);
1156 heap_free(mft.output_types);
1157 goto next;
1160 cur = heap_alloc(sizeof(*cur));
1161 /* Reuse allocated type arrays. */
1162 *cur = mft;
1163 list_add_tail(mfts, &cur->entry);
1165 next:
1166 size = ARRAY_SIZE(clsidW);
1167 index++;
1170 return S_OK;
1173 static BOOL mft_is_preferred(IMFPluginControl *plugin_control, const CLSID *clsid)
1175 CLSID preferred;
1176 WCHAR *selector;
1177 int index = 0;
1179 while (SUCCEEDED(IMFPluginControl_GetPreferredClsidByIndex(plugin_control, MF_Plugin_Type_MFT, index++, &selector,
1180 &preferred)))
1182 CoTaskMemFree(selector);
1184 if (IsEqualGUID(&preferred, clsid))
1185 return TRUE;
1188 return FALSE;
1191 static HRESULT mft_enum(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1192 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1194 IMFPluginControl *plugin_control = NULL;
1195 struct list mfts, mfts_sorted, *result = &mfts;
1196 struct mft_registration *mft, *mft2;
1197 unsigned int obj_count;
1198 HRESULT hr;
1200 *count = 0;
1201 *activate = NULL;
1203 if (!flags)
1204 flags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER;
1206 /* Synchronous processing is default. */
1207 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
1208 flags |= MFT_ENUM_FLAG_SYNCMFT;
1210 if (FAILED(hr = MFGetPluginControl(&plugin_control)))
1212 WARN("Failed to get plugin control instance, hr %#x.\n", hr);
1213 return hr;
1216 list_init(&mfts);
1218 /* Collect from registry */
1219 mft_collect_machine_reg(&mfts, &category, flags, plugin_control, input_type, output_type);
1221 /* Collect locally registered ones. */
1222 if (flags & MFT_ENUM_FLAG_LOCALMFT)
1224 struct mft_registration *local;
1226 EnterCriticalSection(&local_mfts_section);
1228 LIST_FOR_EACH_ENTRY(local, &local_mfts, struct mft_registration, entry)
1230 if (mft_is_type_info_match(local, &category, flags, plugin_control, input_type, output_type))
1232 mft = heap_alloc_zero(sizeof(*mft));
1234 mft->clsid = local->clsid;
1235 mft->factory = local->factory;
1236 if (mft->factory)
1237 IClassFactory_AddRef(mft->factory);
1238 mft->flags = local->flags;
1239 mft->local = local->local;
1241 list_add_tail(&mfts, &mft->entry);
1245 LeaveCriticalSection(&local_mfts_section);
1248 list_init(&mfts_sorted);
1250 if (flags & MFT_ENUM_FLAG_SORTANDFILTER)
1252 /* Local registrations. */
1253 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1255 if (mft->local)
1257 list_remove(&mft->entry);
1258 list_add_tail(&mfts_sorted, &mft->entry);
1262 /* FIXME: Sort by merit value, for the ones that got it. Currently not handled. */
1264 /* Preferred transforms. */
1265 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1267 if (!mft->factory && mft_is_preferred(plugin_control, &mft->clsid))
1269 list_remove(&mft->entry);
1270 list_add_tail(&mfts_sorted, &mft->entry);
1274 /* Append the rest. */
1275 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1277 list_remove(&mft->entry);
1278 list_add_tail(&mfts_sorted, &mft->entry);
1281 result = &mfts_sorted;
1284 IMFPluginControl_Release(plugin_control);
1286 /* Create activation objects from CLSID/IClassFactory. */
1288 obj_count = list_count(result);
1290 if (obj_count)
1292 if (!(*activate = CoTaskMemAlloc(obj_count * sizeof(**activate))))
1293 hr = E_OUTOFMEMORY;
1295 obj_count = 0;
1297 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, result, struct mft_registration, entry)
1299 IMFActivate *mft_activate;
1301 if (*activate)
1303 if (SUCCEEDED(create_transform_activate(mft->factory, &mft_activate)))
1305 (*activate)[obj_count] = mft_activate;
1307 if (mft->local)
1309 IMFActivate_SetUINT32(mft_activate, &MFT_PROCESS_LOCAL_Attribute, 1);
1311 else
1313 if (mft->name)
1314 IMFActivate_SetString(mft_activate, &MFT_FRIENDLY_NAME_Attribute, mft->name);
1315 if (mft->input_types)
1316 IMFActivate_SetBlob(mft_activate, &MFT_INPUT_TYPES_Attributes, (const UINT8 *)mft->input_types,
1317 sizeof(*mft->input_types) * mft->input_types_count);
1318 if (mft->output_types)
1319 IMFActivate_SetBlob(mft_activate, &MFT_OUTPUT_TYPES_Attributes, (const UINT8 *)mft->output_types,
1320 sizeof(*mft->output_types) * mft->output_types_count);
1323 if (!mft->factory)
1324 IMFActivate_SetGUID(mft_activate, &MFT_TRANSFORM_CLSID_Attribute, &mft->clsid);
1326 IMFActivate_SetUINT32(mft_activate, &MF_TRANSFORM_FLAGS_Attribute, mft->flags);
1327 IMFActivate_SetGUID(mft_activate, &MF_TRANSFORM_CATEGORY_Attribute, &mft->category);
1329 obj_count++;
1333 list_remove(&mft->entry);
1334 release_mft_registration(mft);
1338 if (!obj_count)
1340 CoTaskMemFree(*activate);
1341 *activate = NULL;
1343 *count = obj_count;
1345 return hr;
1348 /***********************************************************************
1349 * MFTEnum (mfplat.@)
1351 HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type,
1352 MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, CLSID **clsids, UINT32 *count)
1354 struct mft_registration *mft, *mft2;
1355 unsigned int mft_count;
1356 struct list mfts;
1357 HRESULT hr;
1359 TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes,
1360 clsids, count);
1362 if (!clsids || !count)
1363 return E_INVALIDARG;
1365 *count = 0;
1367 list_init(&mfts);
1369 if (FAILED(hr = mft_collect_machine_reg(&mfts, &category, MFT_ENUM_FLAG_SYNCMFT, NULL, input_type, output_type)))
1370 return hr;
1372 mft_count = list_count(&mfts);
1374 if (mft_count)
1376 if (!(*clsids = CoTaskMemAlloc(mft_count * sizeof(**clsids))))
1377 hr = E_OUTOFMEMORY;
1379 mft_count = 0;
1380 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1382 if (*clsids)
1383 (*clsids)[mft_count++] = mft->clsid;
1384 list_remove(&mft->entry);
1385 release_mft_registration(mft);
1389 if (!mft_count)
1391 CoTaskMemFree(*clsids);
1392 *clsids = NULL;
1394 *count = mft_count;
1396 return hr;
1399 /***********************************************************************
1400 * MFTEnumEx (mfplat.@)
1402 HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1403 const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *count)
1405 TRACE("%s, %#x, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, activate, count);
1407 return mft_enum(category, flags, input_type, output_type, NULL, activate, count);
1410 /***********************************************************************
1411 * MFTEnum2 (mfplat.@)
1413 HRESULT WINAPI MFTEnum2(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1414 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1416 TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes,
1417 activate, count);
1419 if (attributes)
1420 FIXME("Ignoring attributes.\n");
1422 return mft_enum(category, flags, input_type, output_type, attributes, activate, count);
1425 /***********************************************************************
1426 * MFTUnregister (mfplat.@)
1428 HRESULT WINAPI MFTUnregister(CLSID clsid)
1430 WCHAR buffer[64], category[MAX_PATH];
1431 HKEY htransform, hcategory, htmp;
1432 DWORD size = MAX_PATH;
1433 DWORD index = 0;
1435 TRACE("(%s)\n", debugstr_guid(&clsid));
1437 GUIDToString(buffer, &clsid);
1439 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1441 RegDeleteKeyW(htransform, buffer);
1442 RegCloseKey(htransform);
1445 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1447 while (RegEnumKeyExW(hcategory, index, category, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
1449 if (!RegOpenKeyW(hcategory, category, &htmp))
1451 RegDeleteKeyW(htmp, buffer);
1452 RegCloseKey(htmp);
1454 size = MAX_PATH;
1455 index++;
1457 RegCloseKey(hcategory);
1460 return S_OK;
1463 /***********************************************************************
1464 * MFStartup (mfplat.@)
1466 HRESULT WINAPI MFStartup(ULONG version, DWORD flags)
1468 #define MF_VERSION_XP MAKELONG( MF_API_VERSION, 1 )
1469 #define MF_VERSION_WIN7 MAKELONG( MF_API_VERSION, 2 )
1471 TRACE("%#x, %#x.\n", version, flags);
1473 if (version != MF_VERSION_XP && version != MF_VERSION_WIN7)
1474 return MF_E_BAD_STARTUP_VERSION;
1476 RtwqStartup();
1478 return S_OK;
1481 /***********************************************************************
1482 * MFShutdown (mfplat.@)
1484 HRESULT WINAPI MFShutdown(void)
1486 TRACE("\n");
1488 RtwqShutdown();
1490 return S_OK;
1493 /***********************************************************************
1494 * MFCopyImage (mfplat.@)
1496 HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines)
1498 TRACE("%p, %d, %p, %d, %u, %u.\n", dest, deststride, src, srcstride, width, lines);
1500 while (lines--)
1502 memcpy(dest, src, width);
1503 dest += deststride;
1504 src += srcstride;
1507 return S_OK;
1510 struct guid_def
1512 const GUID *guid;
1513 const char *name;
1516 static int __cdecl debug_compare_guid(const void *a, const void *b)
1518 const GUID *guid = a;
1519 const struct guid_def *guid_def = b;
1520 return memcmp(guid, guid_def->guid, sizeof(*guid));
1523 const char *debugstr_attr(const GUID *guid)
1525 static const struct guid_def guid_defs[] =
1527 #define X(g) { &(g), #g }
1528 X(MF_READWRITE_MMCSS_CLASS),
1529 X(MF_TOPONODE_MARKIN_HERE),
1530 X(MF_MT_H264_SUPPORTED_SYNC_FRAME_TYPES),
1531 X(MF_TOPONODE_MARKOUT_HERE),
1532 X(EVRConfig_ForceBob),
1533 X(MF_TOPONODE_DECODER),
1534 X(EVRConfig_AllowDropToBob),
1535 X(MF_TOPOLOGY_PROJECTSTART),
1536 X(EVRConfig_ForceThrottle),
1537 X(MF_VIDEO_MAX_MB_PER_SEC),
1538 X(MF_TOPOLOGY_PROJECTSTOP),
1539 X(MF_SINK_WRITER_ENCODER_CONFIG),
1540 X(EVRConfig_AllowDropToThrottle),
1541 X(MF_TOPOLOGY_NO_MARKIN_MARKOUT),
1542 X(EVRConfig_ForceHalfInterlace),
1543 X(EVRConfig_AllowDropToHalfInterlace),
1544 X(EVRConfig_ForceScaling),
1545 X(MF_MT_H264_CAPABILITIES),
1546 X(EVRConfig_AllowScaling),
1547 X(MF_SOURCE_READER_ENABLE_TRANSCODE_ONLY_TRANSFORMS),
1548 X(MFT_PREFERRED_ENCODER_PROFILE),
1549 X(EVRConfig_ForceBatching),
1550 X(EVRConfig_AllowBatching),
1551 X(MF_TOPOLOGY_DYNAMIC_CHANGE_NOT_ALLOWED),
1552 X(MF_MT_VIDEO_PROFILE),
1553 X(MF_MT_MPEG2_PROFILE),
1554 X(MF_MT_DV_AAUX_CTRL_PACK_1),
1555 X(MF_MT_ALPHA_MODE),
1556 X(MF_MT_MPEG2_TIMECODE),
1557 X(MF_PMP_SERVER_CONTEXT),
1558 X(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE),
1559 X(MF_MEDIA_ENGINE_TRACK_ID),
1560 X(MF_MT_CUSTOM_VIDEO_PRIMARIES),
1561 X(MF_MT_TIMESTAMP_CAN_BE_DTS),
1562 X(MFT_CODEC_MERIT_Attribute),
1563 X(MF_TOPOLOGY_PLAYBACK_MAX_DIMS),
1564 X(MF_LOW_LATENCY),
1565 X(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS),
1566 X(MF_MT_MPEG2_FLAGS),
1567 X(MF_MEDIA_ENGINE_AUDIO_CATEGORY),
1568 X(MF_MT_PIXEL_ASPECT_RATIO),
1569 X(MF_TOPOLOGY_ENABLE_XVP_FOR_PLAYBACK),
1570 X(MFT_CONNECTED_STREAM_ATTRIBUTE),
1571 X(MF_MT_REALTIME_CONTENT),
1572 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_FLAGS),
1573 X(MF_MT_WRAPPED_TYPE),
1574 X(MF_MT_DRM_FLAGS),
1575 X(MF_MT_AVG_BITRATE),
1576 X(MF_MT_DECODER_USE_MAX_RESOLUTION),
1577 X(MF_MT_MAX_LUMINANCE_LEVEL),
1578 X(MFT_CONNECTED_TO_HW_STREAM),
1579 X(MF_SA_D3D_AWARE),
1580 X(MF_MT_MAX_KEYFRAME_SPACING),
1581 X(MFT_TRANSFORM_CLSID_Attribute),
1582 X(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING),
1583 X(MF_MT_AM_FORMAT_TYPE),
1584 X(MF_SESSION_APPROX_EVENT_OCCURRENCE_TIME),
1585 X(MF_MEDIA_ENGINE_SYNCHRONOUS_CLOSE),
1586 X(MF_MT_H264_MAX_MB_PER_SEC),
1587 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_MAX_BUFFERS),
1588 X(MF_MT_AUDIO_BLOCK_ALIGNMENT),
1589 X(MF_PD_PMPHOST_CONTEXT),
1590 X(MF_PD_APP_CONTEXT),
1591 X(MF_PD_DURATION),
1592 X(MF_PD_TOTAL_FILE_SIZE),
1593 X(MF_PD_AUDIO_ENCODING_BITRATE),
1594 X(MF_PD_VIDEO_ENCODING_BITRATE),
1595 X(MFSampleExtension_TargetGlobalLuminance),
1596 X(MF_PD_MIME_TYPE),
1597 X(MF_MT_H264_SUPPORTED_SLICE_MODES),
1598 X(MF_PD_LAST_MODIFIED_TIME),
1599 X(MF_PD_PLAYBACK_ELEMENT_ID),
1600 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE9),
1601 X(MF_MT_ALL_SAMPLES_INDEPENDENT),
1602 X(MF_PD_PREFERRED_LANGUAGE),
1603 X(MF_PD_PLAYBACK_BOUNDARY_TIME),
1604 X(MF_MEDIA_ENGINE_TELEMETRY_APPLICATION_ID),
1605 X(MF_ACTIVATE_MFT_LOCKED),
1606 X(MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT),
1607 X(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING),
1608 X(MF_MT_FRAME_SIZE),
1609 X(MF_MT_H264_SIMULCAST_SUPPORT),
1610 X(MF_SINK_WRITER_ASYNC_CALLBACK),
1611 X(MF_TOPOLOGY_START_TIME_ON_PRESENTATION_SWITCH),
1612 X(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER),
1613 X(MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY),
1614 X(MF_MT_FRAME_RATE_RANGE_MAX),
1615 X(MF_MT_PALETTE),
1616 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_PROVIDER_DEVICE_ID),
1617 X(MF_TOPOLOGY_STATIC_PLAYBACK_OPTIMIZATIONS),
1618 X(MF_SA_D3D11_USAGE),
1619 X(MF_MEDIA_ENGINE_NEEDKEY_CALLBACK),
1620 X(MF_MT_GEOMETRIC_APERTURE),
1621 X(MF_MT_ORIGINAL_WAVE_FORMAT_TAG),
1622 X(MF_MT_DV_AAUX_SRC_PACK_1),
1623 X(MF_MEDIA_ENGINE_STREAM_CONTAINS_ALPHA_CHANNEL),
1624 X(MF_MEDIA_ENGINE_MEDIA_PLAYER_MODE),
1625 X(MF_MEDIA_ENGINE_EXTENSION),
1626 X(MF_MT_DEFAULT_STRIDE),
1627 X(MF_MT_ARBITRARY_FORMAT),
1628 X(MF_TRANSFORM_CATEGORY_Attribute),
1629 X(MF_MT_MPEG2_HDCP),
1630 X(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
1631 X(MF_MT_SPATIAL_AUDIO_MAX_DYNAMIC_OBJECTS),
1632 X(MF_MT_DECODER_MAX_DPB_COUNT),
1633 X(MFSampleExtension_ForwardedDecodeUnits),
1634 X(MF_SA_D3D11_SHARED_WITHOUT_MUTEX),
1635 X(MF_MT_DV_AAUX_CTRL_PACK_0),
1636 X(MF_MT_YUV_MATRIX),
1637 X(MF_EVENT_SOURCE_TOPOLOGY_CANCELED),
1638 X(MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY),
1639 X(MF_MT_MAX_FRAME_AVERAGE_LUMINANCE_LEVEL),
1640 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID),
1641 X(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME),
1642 X(MF_MT_VIDEO_ROTATION),
1643 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_SYMBOLIC_LINK),
1644 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE11),
1645 X(MF_MT_USER_DATA),
1646 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID),
1647 X(MF_MT_MIN_MASTERING_LUMINANCE),
1648 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE),
1649 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS),
1650 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID),
1651 X(MF_EVENT_STREAM_METADATA_SYSTEMID),
1652 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE),
1653 X(MF_MT_AUDIO_CHANNEL_MASK),
1654 X(MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN),
1655 X(MF_READWRITE_DISABLE_CONVERTERS),
1656 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE_EDGE),
1657 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS),
1658 X(MF_MT_MINIMUM_DISPLAY_APERTURE),
1659 X(MFSampleExtension_Token),
1660 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_CATEGORY),
1661 X(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
1662 X(MF_TRANSFORM_ASYNC_UNLOCK),
1663 X(MF_DISABLE_FRAME_CORRUPTION_INFO),
1664 X(MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES),
1665 X(MF_MT_VIDEO_NO_FRAME_ORDERING),
1666 X(MF_MEDIA_ENGINE_PLAYBACK_VISUAL),
1667 X(MF_MT_VIDEO_CHROMA_SITING),
1668 X(MF_AUDIO_RENDERER_ATTRIBUTE_STREAM_CATEGORY),
1669 X(MF_SA_BUFFERS_PER_SAMPLE),
1670 X(MFSampleExtension_3DVideo_SampleFormat),
1671 X(MF_MT_H264_RESOLUTION_SCALING),
1672 X(MF_MT_VIDEO_LEVEL),
1673 X(MF_MT_MPEG2_LEVEL),
1674 X(MF_SAMPLEGRABBERSINK_SAMPLE_TIME_OFFSET),
1675 X(MF_MT_SAMPLE_SIZE),
1676 X(MF_MT_AAC_PAYLOAD_TYPE),
1677 X(MF_TOPOLOGY_PLAYBACK_FRAMERATE),
1678 X(MF_SOURCE_READER_D3D11_BIND_FLAGS),
1679 X(MF_MT_AUDIO_FOLDDOWN_MATRIX),
1680 X(MF_MT_AUDIO_WMADRC_PEAKREF),
1681 X(MF_MT_AUDIO_WMADRC_PEAKTARGET),
1682 X(MF_TRANSFORM_FLAGS_Attribute),
1683 X(MF_MT_H264_SUPPORTED_RATE_CONTROL_MODES),
1684 X(MF_PD_SAMI_STYLELIST),
1685 X(MF_MT_AUDIO_WMADRC_AVGREF),
1686 X(MF_MT_AUDIO_BITS_PER_SAMPLE),
1687 X(MF_SD_LANGUAGE),
1688 X(MF_MT_AUDIO_WMADRC_AVGTARGET),
1689 X(MF_SD_PROTECTED),
1690 X(MF_SESSION_TOPOLOADER),
1691 X(MF_SESSION_GLOBAL_TIME),
1692 X(MF_SESSION_QUALITY_MANAGER),
1693 X(MF_SESSION_CONTENT_PROTECTION_MANAGER),
1694 X(MF_MT_MPEG4_SAMPLE_DESCRIPTION),
1695 X(MF_MT_MPEG_START_TIME_CODE),
1696 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1697 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1698 X(MF_READWRITE_MMCSS_PRIORITY_AUDIO),
1699 X(MF_MT_H264_MAX_CODEC_CONFIG_DELAY),
1700 X(MF_MT_DV_AAUX_SRC_PACK_0),
1701 X(MF_BYTESTREAM_ORIGIN_NAME),
1702 X(MF_BYTESTREAM_CONTENT_TYPE),
1703 X(MF_MT_DEPTH_MEASUREMENT),
1704 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WIN10),
1705 X(MF_MT_VIDEO_3D_NUM_VIEWS),
1706 X(MF_BYTESTREAM_DURATION),
1707 X(MF_SD_SAMI_LANGUAGE),
1708 X(MF_EVENT_OUTPUT_NODE),
1709 X(MF_BYTESTREAM_LAST_MODIFIED_TIME),
1710 X(MFT_ENUM_ADAPTER_LUID),
1711 X(MF_MT_FRAME_RATE_RANGE_MIN),
1712 X(MF_BYTESTREAM_IFO_FILE_URI),
1713 X(MF_EVENT_TOPOLOGY_STATUS),
1714 X(MF_BYTESTREAM_DLNA_PROFILE_ID),
1715 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ROLE),
1716 X(MF_MT_MAJOR_TYPE),
1717 X(MF_MT_IN_BAND_PARAMETER_SET),
1718 X(MF_EVENT_SOURCE_CHARACTERISTICS),
1719 X(MF_EVENT_SOURCE_CHARACTERISTICS_OLD),
1720 X(MF_SESSION_SERVER_CONTEXT),
1721 X(MF_MT_VIDEO_3D_FIRST_IS_LEFT),
1722 X(MFT_DECODER_FINAL_VIDEO_RESOLUTION_HINT),
1723 X(MF_PD_ADAPTIVE_STREAMING),
1724 X(MF_MEDIA_ENGINE_SOURCE_RESOLVER_CONFIG_STORE),
1725 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WWA_EDGE),
1726 X(MF_MT_H264_SUPPORTED_USAGES),
1727 X(MFT_PREFERRED_OUTPUTTYPE_Attribute),
1728 X(MFSampleExtension_Timestamp),
1729 X(MF_TOPONODE_PRIMARYOUTPUT),
1730 X(MF_MT_SUBTYPE),
1731 X(MF_TRANSFORM_ASYNC),
1732 X(MF_TOPONODE_STREAMID),
1733 X(MF_MEDIA_ENGINE_PLAYBACK_HWND),
1734 X(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE),
1735 X(MF_MT_VIDEO_LIGHTING),
1736 X(MF_SD_MUTUALLY_EXCLUSIVE),
1737 X(MF_SD_STREAM_NAME),
1738 X(MF_MT_DV_VAUX_SRC_PACK),
1739 X(MF_TOPONODE_RATELESS),
1740 X(MF_EVENT_STREAM_METADATA_CONTENT_KEYIDS),
1741 X(MF_TOPONODE_DISABLE_PREROLL),
1742 X(MF_SA_D3D11_ALLOW_DYNAMIC_YUV_TEXTURE),
1743 X(MF_MT_VIDEO_3D_FORMAT),
1744 X(MF_EVENT_STREAM_METADATA_KEYDATA),
1745 X(MF_SINK_WRITER_D3D_MANAGER),
1746 X(MF_SOURCE_READER_D3D_MANAGER),
1747 X(MFSampleExtension_3DVideo),
1748 X(MF_MT_H264_USAGE),
1749 X(MF_MEDIA_ENGINE_EME_CALLBACK),
1750 X(MF_EVENT_SOURCE_FAKE_START),
1751 X(MF_EVENT_SOURCE_PROJECTSTART),
1752 X(MF_EVENT_SOURCE_ACTUAL_START),
1753 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_MANAGER),
1754 X(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
1755 X(MFT_ENUM_HARDWARE_URL_Attribute),
1756 X(MF_SOURCE_READER_ASYNC_CALLBACK),
1757 X(MF_MT_OUTPUT_BUFFER_NUM),
1758 X(MF_SA_D3D11_BINDFLAGS),
1759 X(MFT_ENCODER_SUPPORTS_CONFIG_EVENT),
1760 X(MF_MT_AUDIO_FLAC_MAX_BLOCK_SIZE),
1761 X(MFT_FRIENDLY_NAME_Attribute),
1762 X(MF_MT_FIXED_SIZE_SAMPLES),
1763 X(MFT_SUPPORT_3DVIDEO),
1764 X(MFT_SUPPORT_3DVIDEO),
1765 X(MFT_INPUT_TYPES_Attributes),
1766 X(MF_MT_H264_LAYOUT_PER_STREAM),
1767 X(MF_EVENT_SCRUBSAMPLE_TIME),
1768 X(MF_MT_SPATIAL_AUDIO_MAX_METADATA_ITEMS),
1769 X(MF_MT_MPEG2_ONE_FRAME_PER_PACKET),
1770 X(MF_MT_INTERLACE_MODE),
1771 X(MF_MEDIA_ENGINE_CALLBACK),
1772 X(MF_MT_VIDEO_RENDERER_EXTENSION_PROFILE),
1773 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_HW_SOURCE),
1774 X(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
1775 X(MF_MT_H264_SVC_CAPABILITIES),
1776 X(MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY),
1777 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_LENGTH),
1778 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_FORMAT_ID),
1779 X(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK),
1780 X(MF_SA_D3D11_SHARED),
1781 X(MF_MT_PAN_SCAN_ENABLED),
1782 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID),
1783 X(MF_MT_DV_VAUX_CTRL_PACK),
1784 X(MFSampleExtension_ForwardedDecodeUnitType),
1785 X(MF_SA_D3D11_AWARE),
1786 X(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
1787 X(MF_SOURCE_READER_MEDIASOURCE_CHARACTERISTICS),
1788 X(MF_MT_SPATIAL_AUDIO_MIN_METADATA_ITEM_OFFSET_SPACING),
1789 X(MF_TOPONODE_TRANSFORM_OBJECTID),
1790 X(MF_DEVSOURCE_ATTRIBUTE_MEDIA_TYPE),
1791 X(MF_EVENT_MFT_INPUT_STREAM_ID),
1792 X(MF_MT_SOURCE_CONTENT_HINT),
1793 X(MFT_ENUM_HARDWARE_VENDOR_ID_Attribute),
1794 X(MFT_ENUM_TRANSCODE_ONLY_ATTRIBUTE),
1795 X(MF_READWRITE_MMCSS_PRIORITY),
1796 X(MF_MT_VIDEO_3D),
1797 X(MF_EVENT_START_PRESENTATION_TIME),
1798 X(MF_EVENT_SESSIONCAPS),
1799 X(MF_EVENT_PRESENTATION_TIME_OFFSET),
1800 X(MF_MEDIA_ENGINE_AUDIO_ENDPOINT_ROLE),
1801 X(MF_EVENT_SESSIONCAPS_DELTA),
1802 X(MF_EVENT_START_PRESENTATION_TIME_AT_OUTPUT),
1803 X(MFSampleExtension_DecodeTimestamp),
1804 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE),
1805 X(MF_MT_VIDEO_H264_NO_FMOASO),
1806 X(MF_MT_AVG_BIT_ERROR_RATE),
1807 X(MF_MT_VIDEO_PRIMARIES),
1808 X(MF_SINK_WRITER_DISABLE_THROTTLING),
1809 X(MF_MT_H264_RATE_CONTROL_MODES),
1810 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK),
1811 X(MF_READWRITE_D3D_OPTIONAL),
1812 X(MF_SA_D3D11_HW_PROTECTED),
1813 X(MF_MEDIA_ENGINE_DXGI_MANAGER),
1814 X(MF_READWRITE_MMCSS_CLASS_AUDIO),
1815 X(MF_MEDIA_ENGINE_COREWINDOW),
1816 X(MF_SOURCE_READER_DISABLE_CAMERA_PLUGINS),
1817 X(MF_MT_MPEG4_TRACK_TYPE),
1818 X(MF_ACTIVATE_VIDEO_WINDOW),
1819 X(MF_MT_PAN_SCAN_APERTURE),
1820 X(MF_TOPOLOGY_RESOLUTION_STATUS),
1821 X(MF_MT_ORIGINAL_4CC),
1822 X(MF_PD_AUDIO_ISVARIABLEBITRATE),
1823 X(MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS),
1824 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE),
1825 X(MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID),
1826 X(MF_MT_MPEG2_CONTENT_PACKET),
1827 X(MFT_PROCESS_LOCAL_Attribute),
1828 X(MFT_PROCESS_LOCAL_Attribute),
1829 X(MF_MT_PAD_CONTROL_FLAGS),
1830 X(MF_MT_VIDEO_NOMINAL_RANGE),
1831 X(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
1832 X(MF_MT_MPEG_SEQUENCE_HEADER),
1833 X(MF_MEDIA_ENGINE_OPM_HWND),
1834 X(MF_MT_AUDIO_SAMPLES_PER_SECOND),
1835 X(MF_MT_SPATIAL_AUDIO_DATA_PRESENT),
1836 X(MF_MT_FRAME_RATE),
1837 X(MF_TOPONODE_FLUSH),
1838 X(MF_MT_MPEG2_STANDARD),
1839 X(MF_TOPONODE_DRAIN),
1840 X(MF_MT_TRANSFER_FUNCTION),
1841 X(MF_TOPONODE_MEDIASTART),
1842 X(MF_TOPONODE_MEDIASTOP),
1843 X(MF_SOURCE_READER_MEDIASOURCE_CONFIG),
1844 X(MF_TOPONODE_SOURCE),
1845 X(MF_TOPONODE_PRESENTATION_DESCRIPTOR),
1846 X(MF_TOPONODE_D3DAWARE),
1847 X(MF_MT_COMPRESSED),
1848 X(MF_TOPONODE_STREAM_DESCRIPTOR),
1849 X(MF_TOPONODE_ERRORCODE),
1850 X(MF_TOPONODE_SEQUENCE_ELEMENTID),
1851 X(MF_EVENT_MFT_CONTEXT),
1852 X(MF_MT_FORWARD_CUSTOM_SEI),
1853 X(MF_TOPONODE_CONNECT_METHOD),
1854 X(MFT_OUTPUT_TYPES_Attributes),
1855 X(MF_MT_IMAGE_LOSS_TOLERANT),
1856 X(MF_SESSION_REMOTE_SOURCE_MODE),
1857 X(MF_MT_DEPTH_VALUE_UNIT),
1858 X(MF_MT_AUDIO_NUM_CHANNELS),
1859 X(MF_MT_ARBITRARY_HEADER),
1860 X(MF_TOPOLOGY_DXVA_MODE),
1861 X(MF_TOPONODE_LOCKED),
1862 X(MF_TOPONODE_WORKQUEUE_ID),
1863 X(MF_MEDIA_ENGINE_CONTINUE_ON_CODEC_ERROR),
1864 X(MF_TOPONODE_WORKQUEUE_MMCSS_CLASS),
1865 X(MF_TOPONODE_DECRYPTOR),
1866 X(MF_EVENT_DO_THINNING),
1867 X(MF_TOPONODE_DISCARDABLE),
1868 X(MF_TOPOLOGY_HARDWARE_MODE),
1869 X(MF_SOURCE_READER_DISABLE_DXVA),
1870 X(MF_MT_FORWARD_CUSTOM_NALU),
1871 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE10),
1872 X(MF_TOPONODE_ERROR_MAJORTYPE),
1873 X(MF_MT_SECURE),
1874 X(MFT_FIELDOFUSE_UNLOCK_Attribute),
1875 X(MF_TOPONODE_ERROR_SUBTYPE),
1876 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE),
1877 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE),
1878 X(MF_MT_VIDEO_3D_LEFT_IS_BASE),
1879 X(MF_TOPONODE_WORKQUEUE_MMCSS_TASKID),
1880 #undef X
1882 struct guid_def *ret = NULL;
1884 if (guid)
1885 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
1887 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
1890 const char *debugstr_mf_guid(const GUID *guid)
1892 static const struct guid_def guid_defs[] =
1894 #define X(g) { &(g), #g }
1895 X(MFAudioFormat_ADTS),
1896 X(MFAudioFormat_PCM),
1897 X(MFAudioFormat_PCM_HDCP),
1898 X(MFAudioFormat_Float),
1899 X(MFAudioFormat_DTS),
1900 X(MFAudioFormat_DRM),
1901 X(MFAudioFormat_MSP1),
1902 X(MFAudioFormat_Vorbis),
1903 X(MFAudioFormat_AAC),
1904 X(MFVideoFormat_RGB24),
1905 X(MFVideoFormat_ARGB32),
1906 X(MFVideoFormat_RGB32),
1907 X(MFVideoFormat_RGB565),
1908 X(MFVideoFormat_RGB555),
1909 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID),
1910 X(MFVideoFormat_A2R10G10B10),
1911 X(MFMediaType_Script),
1912 X(MFMediaType_Image),
1913 X(MFMediaType_HTML),
1914 X(MFMediaType_Binary),
1915 X(MFVideoFormat_MPEG2),
1916 X(MFMediaType_FileTransfer),
1917 X(MFVideoFormat_RGB8),
1918 X(MFAudioFormat_Dolby_AC3),
1919 X(MFVideoFormat_L8),
1920 X(MFAudioFormat_LPCM),
1921 X(MFVideoFormat_420O),
1922 X(MFVideoFormat_AI44),
1923 X(MFVideoFormat_AV1),
1924 X(MFVideoFormat_AYUV),
1925 X(MFVideoFormat_H263),
1926 X(MFVideoFormat_H264),
1927 X(MFVideoFormat_H265),
1928 X(MFVideoFormat_HEVC),
1929 X(MFVideoFormat_HEVC_ES),
1930 X(MFVideoFormat_I420),
1931 X(MFVideoFormat_IYUV),
1932 X(MFVideoFormat_M4S2),
1933 X(MFVideoFormat_MJPG),
1934 X(MFVideoFormat_MP43),
1935 X(MFVideoFormat_MP4S),
1936 X(MFVideoFormat_MP4V),
1937 X(MFVideoFormat_MPG1),
1938 X(MFVideoFormat_MSS1),
1939 X(MFVideoFormat_MSS2),
1940 X(MFVideoFormat_NV11),
1941 X(MFVideoFormat_NV12),
1942 X(MFVideoFormat_ORAW),
1943 X(MFAudioFormat_Opus),
1944 X(MFVideoFormat_D16),
1945 X(MFAudioFormat_MPEG),
1946 X(MFVideoFormat_P010),
1947 X(MFVideoFormat_P016),
1948 X(MFVideoFormat_P210),
1949 X(MFVideoFormat_P216),
1950 X(MFVideoFormat_L16),
1951 X(MFAudioFormat_MP3),
1952 X(MFVideoFormat_UYVY),
1953 X(MFVideoFormat_VP10),
1954 X(MFVideoFormat_VP80),
1955 X(MFVideoFormat_VP90),
1956 X(MFVideoFormat_WMV1),
1957 X(MFVideoFormat_WMV2),
1958 X(MFVideoFormat_WMV3),
1959 X(MFVideoFormat_WVC1),
1960 X(MFVideoFormat_Y210),
1961 X(MFVideoFormat_Y216),
1962 X(MFVideoFormat_Y410),
1963 X(MFVideoFormat_Y416),
1964 X(MFVideoFormat_Y41P),
1965 X(MFVideoFormat_Y41T),
1966 X(MFVideoFormat_Y42T),
1967 X(MFVideoFormat_YUY2),
1968 X(MFVideoFormat_YV12),
1969 X(MFVideoFormat_YVU9),
1970 X(MFVideoFormat_YVYU),
1971 X(MFAudioFormat_WMAudioV8),
1972 X(MFAudioFormat_ALAC),
1973 X(MFAudioFormat_AMR_NB),
1974 X(MFMediaType_Audio),
1975 X(MFAudioFormat_WMAudioV9),
1976 X(MFAudioFormat_AMR_WB),
1977 X(MFAudioFormat_WMAudio_Lossless),
1978 X(MFAudioFormat_AMR_WP),
1979 X(MFAudioFormat_WMASPDIF),
1980 X(MFVideoFormat_DV25),
1981 X(MFVideoFormat_DV50),
1982 X(MFVideoFormat_DVC),
1983 X(MFVideoFormat_DVH1),
1984 X(MFVideoFormat_DVHD),
1985 X(MFVideoFormat_DVSD),
1986 X(MFVideoFormat_DVSL),
1987 X(MFVideoFormat_A16B16G16R16F),
1988 X(MFVideoFormat_v210),
1989 X(MFVideoFormat_v216),
1990 X(MFVideoFormat_v410),
1991 X(MFMediaType_Video),
1992 X(MFAudioFormat_AAC_HDCP),
1993 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID),
1994 X(MFAudioFormat_Dolby_AC3_HDCP),
1995 X(MFMediaType_Subtitle),
1996 X(MFMediaType_Stream),
1997 X(MFAudioFormat_Dolby_AC3_SPDIF),
1998 X(MFAudioFormat_Float_SpatialObjects),
1999 X(MFMediaType_SAMI),
2000 X(MFAudioFormat_ADTS_HDCP),
2001 X(MFAudioFormat_FLAC),
2002 X(MFAudioFormat_Dolby_DDPlus),
2003 X(MFMediaType_MultiplexedFrames),
2004 X(MFAudioFormat_Base_HDCP),
2005 X(MFVideoFormat_Base_HDCP),
2006 X(MFVideoFormat_H264_HDCP),
2007 X(MFVideoFormat_HEVC_HDCP),
2008 X(MFMediaType_Default),
2009 X(MFMediaType_Protected),
2010 X(MFVideoFormat_H264_ES),
2011 X(MFMediaType_Perception),
2012 #undef X
2014 struct guid_def *ret = NULL;
2016 if (guid)
2017 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
2019 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
2022 struct event_id
2024 DWORD id;
2025 const char *name;
2028 static int __cdecl debug_event_id(const void *a, const void *b)
2030 const DWORD *id = a;
2031 const struct event_id *event_id = b;
2032 return *id - event_id->id;
2035 static const char *debugstr_eventid(DWORD event)
2037 static const struct event_id
2039 DWORD id;
2040 const char *name;
2042 event_ids[] =
2044 #define X(e) { e, #e }
2045 X(MEUnknown),
2046 X(MEError),
2047 X(MEExtendedType),
2048 X(MENonFatalError),
2049 X(MESessionUnknown),
2050 X(MESessionTopologySet),
2051 X(MESessionTopologiesCleared),
2052 X(MESessionStarted),
2053 X(MESessionPaused),
2054 X(MESessionStopped),
2055 X(MESessionClosed),
2056 X(MESessionEnded),
2057 X(MESessionRateChanged),
2058 X(MESessionScrubSampleComplete),
2059 X(MESessionCapabilitiesChanged),
2060 X(MESessionTopologyStatus),
2061 X(MESessionNotifyPresentationTime),
2062 X(MENewPresentation),
2063 X(MELicenseAcquisitionStart),
2064 X(MELicenseAcquisitionCompleted),
2065 X(MEIndividualizationStart),
2066 X(MEIndividualizationCompleted),
2067 X(MEEnablerProgress),
2068 X(MEEnablerCompleted),
2069 X(MEPolicyError),
2070 X(MEPolicyReport),
2071 X(MEBufferingStarted),
2072 X(MEBufferingStopped),
2073 X(MEConnectStart),
2074 X(MEConnectEnd),
2075 X(MEReconnectStart),
2076 X(MEReconnectEnd),
2077 X(MERendererEvent),
2078 X(MESessionStreamSinkFormatChanged),
2079 X(MESourceUnknown),
2080 X(MESourceStarted),
2081 X(MEStreamStarted),
2082 X(MESourceSeeked),
2083 X(MEStreamSeeked),
2084 X(MENewStream),
2085 X(MEUpdatedStream),
2086 X(MESourceStopped),
2087 X(MEStreamStopped),
2088 X(MESourcePaused),
2089 X(MEStreamPaused),
2090 X(MEEndOfPresentation),
2091 X(MEEndOfStream),
2092 X(MEMediaSample),
2093 X(MEStreamTick),
2094 X(MEStreamThinMode),
2095 X(MEStreamFormatChanged),
2096 X(MESourceRateChanged),
2097 X(MEEndOfPresentationSegment),
2098 X(MESourceCharacteristicsChanged),
2099 X(MESourceRateChangeRequested),
2100 X(MESourceMetadataChanged),
2101 X(MESequencerSourceTopologyUpdated),
2102 X(MESinkUnknown),
2103 X(MEStreamSinkStarted),
2104 X(MEStreamSinkStopped),
2105 X(MEStreamSinkPaused),
2106 X(MEStreamSinkRateChanged),
2107 X(MEStreamSinkRequestSample),
2108 X(MEStreamSinkMarker),
2109 X(MEStreamSinkPrerolled),
2110 X(MEStreamSinkScrubSampleComplete),
2111 X(MEStreamSinkFormatChanged),
2112 X(MEStreamSinkDeviceChanged),
2113 X(MEQualityNotify),
2114 X(MESinkInvalidated),
2115 X(MEAudioSessionNameChanged),
2116 X(MEAudioSessionVolumeChanged),
2117 X(MEAudioSessionDeviceRemoved),
2118 X(MEAudioSessionServerShutdown),
2119 X(MEAudioSessionGroupingParamChanged),
2120 X(MEAudioSessionIconChanged),
2121 X(MEAudioSessionFormatChanged),
2122 X(MEAudioSessionDisconnected),
2123 X(MEAudioSessionExclusiveModeOverride),
2124 X(METrustUnknown),
2125 X(MEPolicyChanged),
2126 X(MEContentProtectionMessage),
2127 X(MEPolicySet),
2128 X(MEWMDRMLicenseBackupCompleted),
2129 X(MEWMDRMLicenseBackupProgress),
2130 X(MEWMDRMLicenseRestoreCompleted),
2131 X(MEWMDRMLicenseRestoreProgress),
2132 X(MEWMDRMLicenseAcquisitionCompleted),
2133 X(MEWMDRMIndividualizationCompleted),
2134 X(MEWMDRMIndividualizationProgress),
2135 X(MEWMDRMProximityCompleted),
2136 X(MEWMDRMLicenseStoreCleaned),
2137 X(MEWMDRMRevocationDownloadCompleted),
2138 X(METransformUnknown),
2139 X(METransformNeedInput),
2140 X(METransformHaveOutput),
2141 X(METransformDrainComplete),
2142 X(METransformMarker),
2143 X(METransformInputStreamStateChanged),
2144 X(MEByteStreamCharacteristicsChanged),
2145 X(MEVideoCaptureDeviceRemoved),
2146 X(MEVideoCaptureDevicePreempted),
2147 X(MEStreamSinkFormatInvalidated),
2148 X(MEEncodingParameters),
2149 X(MEContentProtectionMetadata),
2150 X(MEDeviceThermalStateChanged),
2151 #undef X
2154 struct event_id *ret = bsearch(&event, event_ids, ARRAY_SIZE(event_ids), sizeof(*event_ids), debug_event_id);
2155 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbg_sprintf("%u", event);
2158 static inline struct attributes *impl_from_IMFAttributes(IMFAttributes *iface)
2160 return CONTAINING_RECORD(iface, struct attributes, IMFAttributes_iface);
2163 static HRESULT WINAPI mfattributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
2165 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
2167 if (IsEqualIID(riid, &IID_IMFAttributes) ||
2168 IsEqualGUID(riid, &IID_IUnknown))
2170 *out = iface;
2171 IMFAttributes_AddRef(iface);
2172 return S_OK;
2175 WARN("Unsupported %s.\n", debugstr_guid(riid));
2176 *out = NULL;
2177 return E_NOINTERFACE;
2180 static ULONG WINAPI mfattributes_AddRef(IMFAttributes *iface)
2182 struct attributes *attributes = impl_from_IMFAttributes(iface);
2183 ULONG refcount = InterlockedIncrement(&attributes->ref);
2185 TRACE("%p, refcount %d.\n", iface, refcount);
2187 return refcount;
2190 static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
2192 struct attributes *attributes = impl_from_IMFAttributes(iface);
2193 ULONG refcount = InterlockedDecrement(&attributes->ref);
2195 TRACE("%p, refcount %d.\n", iface, refcount);
2197 if (!refcount)
2199 clear_attributes_object(attributes);
2200 heap_free(attributes);
2203 return refcount;
2206 static struct attribute *attributes_find_item(struct attributes *attributes, REFGUID key, size_t *index)
2208 size_t i;
2210 for (i = 0; i < attributes->count; ++i)
2212 if (IsEqualGUID(key, &attributes->attributes[i].key))
2214 if (index)
2215 *index = i;
2216 return &attributes->attributes[i];
2220 return NULL;
2223 static HRESULT attributes_get_item(struct attributes *attributes, const GUID *key, PROPVARIANT *value)
2225 struct attribute *attribute;
2226 HRESULT hr;
2228 EnterCriticalSection(&attributes->cs);
2230 attribute = attributes_find_item(attributes, key, NULL);
2231 if (attribute)
2233 if (attribute->value.vt == value->vt && !(value->vt == VT_UNKNOWN && !attribute->value.u.punkVal))
2234 hr = PropVariantCopy(value, &attribute->value);
2235 else
2236 hr = MF_E_INVALIDTYPE;
2238 else
2239 hr = MF_E_ATTRIBUTENOTFOUND;
2241 LeaveCriticalSection(&attributes->cs);
2243 return hr;
2246 HRESULT attributes_GetItem(struct attributes *attributes, REFGUID key, PROPVARIANT *value)
2248 struct attribute *attribute;
2249 HRESULT hr;
2251 EnterCriticalSection(&attributes->cs);
2253 if ((attribute = attributes_find_item(attributes, key, NULL)))
2254 hr = value ? PropVariantCopy(value, &attribute->value) : S_OK;
2255 else
2256 hr = MF_E_ATTRIBUTENOTFOUND;
2258 LeaveCriticalSection(&attributes->cs);
2260 return hr;
2263 HRESULT attributes_GetItemType(struct attributes *attributes, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2265 struct attribute *attribute;
2266 HRESULT hr = S_OK;
2268 EnterCriticalSection(&attributes->cs);
2270 if ((attribute = attributes_find_item(attributes, key, NULL)))
2272 *type = attribute->value.vt;
2274 else
2275 hr = MF_E_ATTRIBUTENOTFOUND;
2277 LeaveCriticalSection(&attributes->cs);
2279 return hr;
2282 HRESULT attributes_CompareItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value, BOOL *result)
2284 struct attribute *attribute;
2286 *result = FALSE;
2288 EnterCriticalSection(&attributes->cs);
2290 if ((attribute = attributes_find_item(attributes, key, NULL)))
2292 *result = attribute->value.vt == value->vt &&
2293 !PropVariantCompareEx(&attribute->value, value, PVCU_DEFAULT, PVCF_DEFAULT);
2296 LeaveCriticalSection(&attributes->cs);
2298 return S_OK;
2301 HRESULT attributes_Compare(struct attributes *attributes, IMFAttributes *theirs,
2302 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2304 IMFAttributes *smaller, *other;
2305 MF_ATTRIBUTE_TYPE type;
2306 HRESULT hr = S_OK;
2307 UINT32 count;
2308 BOOL result;
2309 size_t i;
2311 if (FAILED(hr = IMFAttributes_GetCount(theirs, &count)))
2312 return hr;
2314 EnterCriticalSection(&attributes->cs);
2316 result = TRUE;
2318 switch (match_type)
2320 case MF_ATTRIBUTES_MATCH_OUR_ITEMS:
2321 for (i = 0; i < attributes->count; ++i)
2323 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2324 &attributes->attributes[i].value, &result)))
2325 break;
2326 if (!result)
2327 break;
2329 break;
2330 case MF_ATTRIBUTES_MATCH_THEIR_ITEMS:
2331 hr = IMFAttributes_Compare(theirs, &attributes->IMFAttributes_iface, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2332 break;
2333 case MF_ATTRIBUTES_MATCH_ALL_ITEMS:
2334 if (count != attributes->count)
2336 result = FALSE;
2337 break;
2339 for (i = 0; i < count; ++i)
2341 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2342 &attributes->attributes[i].value, &result)))
2343 break;
2344 if (!result)
2345 break;
2347 break;
2348 case MF_ATTRIBUTES_MATCH_INTERSECTION:
2349 for (i = 0; i < attributes->count; ++i)
2351 if (FAILED(IMFAttributes_GetItemType(theirs, &attributes->attributes[i].key, &type)))
2352 continue;
2354 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2355 &attributes->attributes[i].value, &result)))
2356 break;
2358 if (!result)
2359 break;
2361 break;
2362 case MF_ATTRIBUTES_MATCH_SMALLER:
2363 smaller = attributes->count > count ? theirs : &attributes->IMFAttributes_iface;
2364 other = attributes->count > count ? &attributes->IMFAttributes_iface : theirs;
2365 hr = IMFAttributes_Compare(smaller, other, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2366 break;
2367 default:
2368 WARN("Unknown match type %d.\n", match_type);
2369 hr = E_INVALIDARG;
2372 LeaveCriticalSection(&attributes->cs);
2374 if (SUCCEEDED(hr))
2375 *ret = result;
2377 return hr;
2380 HRESULT attributes_GetUINT32(struct attributes *attributes, REFGUID key, UINT32 *value)
2382 PROPVARIANT attrval;
2383 HRESULT hr;
2385 PropVariantInit(&attrval);
2386 attrval.vt = VT_UI4;
2387 hr = attributes_get_item(attributes, key, &attrval);
2388 if (SUCCEEDED(hr))
2389 *value = attrval.u.ulVal;
2391 return hr;
2394 HRESULT attributes_GetUINT64(struct attributes *attributes, REFGUID key, UINT64 *value)
2396 PROPVARIANT attrval;
2397 HRESULT hr;
2399 PropVariantInit(&attrval);
2400 attrval.vt = VT_UI8;
2401 hr = attributes_get_item(attributes, key, &attrval);
2402 if (SUCCEEDED(hr))
2403 *value = attrval.u.uhVal.QuadPart;
2405 return hr;
2408 HRESULT attributes_GetDouble(struct attributes *attributes, REFGUID key, double *value)
2410 PROPVARIANT attrval;
2411 HRESULT hr;
2413 PropVariantInit(&attrval);
2414 attrval.vt = VT_R8;
2415 hr = attributes_get_item(attributes, key, &attrval);
2416 if (SUCCEEDED(hr))
2417 *value = attrval.u.dblVal;
2419 return hr;
2422 HRESULT attributes_GetGUID(struct attributes *attributes, REFGUID key, GUID *value)
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_GUID)
2433 *value = *attribute->value.u.puuid;
2434 else
2435 hr = MF_E_INVALIDTYPE;
2437 else
2438 hr = MF_E_ATTRIBUTENOTFOUND;
2440 LeaveCriticalSection(&attributes->cs);
2442 return hr;
2445 HRESULT attributes_GetStringLength(struct attributes *attributes, REFGUID key, UINT32 *length)
2447 struct attribute *attribute;
2448 HRESULT hr = S_OK;
2450 EnterCriticalSection(&attributes->cs);
2452 attribute = attributes_find_item(attributes, key, NULL);
2453 if (attribute)
2455 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2456 *length = lstrlenW(attribute->value.u.pwszVal);
2457 else
2458 hr = MF_E_INVALIDTYPE;
2460 else
2461 hr = MF_E_ATTRIBUTENOTFOUND;
2463 LeaveCriticalSection(&attributes->cs);
2465 return hr;
2468 HRESULT attributes_GetString(struct attributes *attributes, REFGUID key, WCHAR *value,
2469 UINT32 size, UINT32 *length)
2471 struct attribute *attribute;
2472 HRESULT hr = S_OK;
2474 EnterCriticalSection(&attributes->cs);
2476 attribute = attributes_find_item(attributes, key, NULL);
2477 if (attribute)
2479 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2481 int len = lstrlenW(attribute->value.u.pwszVal);
2483 if (length)
2484 *length = len;
2486 if (size <= len)
2487 hr = STRSAFE_E_INSUFFICIENT_BUFFER;
2488 else
2489 memcpy(value, attribute->value.u.pwszVal, (len + 1) * sizeof(WCHAR));
2491 else
2492 hr = MF_E_INVALIDTYPE;
2494 else
2495 hr = MF_E_ATTRIBUTENOTFOUND;
2497 LeaveCriticalSection(&attributes->cs);
2499 return hr;
2502 HRESULT attributes_GetAllocatedString(struct attributes *attributes, REFGUID key, WCHAR **value, UINT32 *length)
2504 PROPVARIANT attrval;
2505 HRESULT hr;
2507 PropVariantInit(&attrval);
2508 attrval.vt = VT_LPWSTR;
2509 hr = attributes_get_item(attributes, key, &attrval);
2510 if (SUCCEEDED(hr))
2512 *value = attrval.u.pwszVal;
2513 *length = lstrlenW(*value);
2516 return hr;
2519 HRESULT attributes_GetBlobSize(struct attributes *attributes, REFGUID key, UINT32 *size)
2521 struct attribute *attribute;
2522 HRESULT hr = S_OK;
2524 EnterCriticalSection(&attributes->cs);
2526 attribute = attributes_find_item(attributes, key, NULL);
2527 if (attribute)
2529 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2530 *size = attribute->value.u.caub.cElems;
2531 else
2532 hr = MF_E_INVALIDTYPE;
2534 else
2535 hr = MF_E_ATTRIBUTENOTFOUND;
2537 LeaveCriticalSection(&attributes->cs);
2539 return hr;
2542 HRESULT attributes_GetBlob(struct attributes *attributes, REFGUID key, UINT8 *buf, UINT32 bufsize, UINT32 *blobsize)
2544 struct attribute *attribute;
2545 HRESULT hr;
2547 EnterCriticalSection(&attributes->cs);
2549 attribute = attributes_find_item(attributes, key, NULL);
2550 if (attribute)
2552 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2554 UINT32 size = attribute->value.u.caub.cElems;
2556 if (bufsize >= size)
2557 hr = PropVariantToBuffer(&attribute->value, buf, size);
2558 else
2559 hr = E_NOT_SUFFICIENT_BUFFER;
2561 if (blobsize)
2562 *blobsize = size;
2564 else
2565 hr = MF_E_INVALIDTYPE;
2567 else
2568 hr = MF_E_ATTRIBUTENOTFOUND;
2570 LeaveCriticalSection(&attributes->cs);
2572 return hr;
2575 HRESULT attributes_GetAllocatedBlob(struct attributes *attributes, REFGUID key, UINT8 **buf, UINT32 *size)
2577 PROPVARIANT attrval;
2578 HRESULT hr;
2580 attrval.vt = VT_VECTOR | VT_UI1;
2581 hr = attributes_get_item(attributes, key, &attrval);
2582 if (SUCCEEDED(hr))
2584 *buf = attrval.u.caub.pElems;
2585 *size = attrval.u.caub.cElems;
2588 return hr;
2591 HRESULT attributes_GetUnknown(struct attributes *attributes, REFGUID key, REFIID riid, void **out)
2593 PROPVARIANT attrval;
2594 HRESULT hr;
2596 PropVariantInit(&attrval);
2597 attrval.vt = VT_UNKNOWN;
2598 hr = attributes_get_item(attributes, key, &attrval);
2599 if (SUCCEEDED(hr))
2600 hr = IUnknown_QueryInterface(attrval.u.punkVal, riid, out);
2601 PropVariantClear(&attrval);
2602 return hr;
2605 static HRESULT attributes_set_item(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2607 struct attribute *attribute;
2609 EnterCriticalSection(&attributes->cs);
2611 attribute = attributes_find_item(attributes, key, NULL);
2612 if (!attribute)
2614 if (!mf_array_reserve((void **)&attributes->attributes, &attributes->capacity, attributes->count + 1,
2615 sizeof(*attributes->attributes)))
2617 LeaveCriticalSection(&attributes->cs);
2618 return E_OUTOFMEMORY;
2620 attributes->attributes[attributes->count].key = *key;
2621 attribute = &attributes->attributes[attributes->count++];
2623 else
2624 PropVariantClear(&attribute->value);
2626 PropVariantCopy(&attribute->value, value);
2628 LeaveCriticalSection(&attributes->cs);
2630 return S_OK;
2633 HRESULT attributes_SetItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2635 PROPVARIANT empty;
2637 switch (value->vt)
2639 case MF_ATTRIBUTE_UINT32:
2640 case MF_ATTRIBUTE_UINT64:
2641 case MF_ATTRIBUTE_DOUBLE:
2642 case MF_ATTRIBUTE_GUID:
2643 case MF_ATTRIBUTE_STRING:
2644 case MF_ATTRIBUTE_BLOB:
2645 case MF_ATTRIBUTE_IUNKNOWN:
2646 return attributes_set_item(attributes, key, value);
2647 default:
2648 PropVariantInit(&empty);
2649 attributes_set_item(attributes, key, &empty);
2650 return MF_E_INVALIDTYPE;
2654 HRESULT attributes_DeleteItem(struct attributes *attributes, REFGUID key)
2656 struct attribute *attribute;
2657 size_t index = 0;
2659 EnterCriticalSection(&attributes->cs);
2661 if ((attribute = attributes_find_item(attributes, key, &index)))
2663 size_t count;
2665 PropVariantClear(&attribute->value);
2667 attributes->count--;
2668 count = attributes->count - index;
2669 if (count)
2670 memmove(&attributes->attributes[index], &attributes->attributes[index + 1], count * sizeof(*attributes->attributes));
2673 LeaveCriticalSection(&attributes->cs);
2675 return S_OK;
2678 HRESULT attributes_DeleteAllItems(struct attributes *attributes)
2680 EnterCriticalSection(&attributes->cs);
2682 while (attributes->count)
2684 PropVariantClear(&attributes->attributes[--attributes->count].value);
2686 heap_free(attributes->attributes);
2687 attributes->attributes = NULL;
2688 attributes->capacity = 0;
2690 LeaveCriticalSection(&attributes->cs);
2692 return S_OK;
2695 HRESULT attributes_SetUINT32(struct attributes *attributes, REFGUID key, UINT32 value)
2697 PROPVARIANT attrval;
2699 attrval.vt = VT_UI4;
2700 attrval.u.ulVal = value;
2701 return attributes_set_item(attributes, key, &attrval);
2704 HRESULT attributes_SetUINT64(struct attributes *attributes, REFGUID key, UINT64 value)
2706 PROPVARIANT attrval;
2708 attrval.vt = VT_UI8;
2709 attrval.u.uhVal.QuadPart = value;
2710 return attributes_set_item(attributes, key, &attrval);
2713 HRESULT attributes_SetDouble(struct attributes *attributes, REFGUID key, double value)
2715 PROPVARIANT attrval;
2717 attrval.vt = VT_R8;
2718 attrval.u.dblVal = value;
2719 return attributes_set_item(attributes, key, &attrval);
2722 HRESULT attributes_SetGUID(struct attributes *attributes, REFGUID key, REFGUID value)
2724 PROPVARIANT attrval;
2726 attrval.vt = VT_CLSID;
2727 attrval.u.puuid = (CLSID *)value;
2728 return attributes_set_item(attributes, key, &attrval);
2731 HRESULT attributes_SetString(struct attributes *attributes, REFGUID key, const WCHAR *value)
2733 PROPVARIANT attrval;
2735 attrval.vt = VT_LPWSTR;
2736 attrval.u.pwszVal = (WCHAR *)value;
2737 return attributes_set_item(attributes, key, &attrval);
2740 HRESULT attributes_SetBlob(struct attributes *attributes, REFGUID key, const UINT8 *buf, UINT32 size)
2742 PROPVARIANT attrval;
2744 attrval.vt = VT_VECTOR | VT_UI1;
2745 attrval.u.caub.cElems = size;
2746 attrval.u.caub.pElems = (UINT8 *)buf;
2747 return attributes_set_item(attributes, key, &attrval);
2750 HRESULT attributes_SetUnknown(struct attributes *attributes, REFGUID key, IUnknown *unknown)
2752 PROPVARIANT attrval;
2754 attrval.vt = VT_UNKNOWN;
2755 attrval.u.punkVal = unknown;
2756 return attributes_set_item(attributes, key, &attrval);
2759 HRESULT attributes_LockStore(struct attributes *attributes)
2761 EnterCriticalSection(&attributes->cs);
2763 return S_OK;
2766 HRESULT attributes_UnlockStore(struct attributes *attributes)
2768 LeaveCriticalSection(&attributes->cs);
2770 return S_OK;
2773 HRESULT attributes_GetCount(struct attributes *attributes, UINT32 *count)
2775 EnterCriticalSection(&attributes->cs);
2776 *count = attributes->count;
2777 LeaveCriticalSection(&attributes->cs);
2779 return S_OK;
2782 HRESULT attributes_GetItemByIndex(struct attributes *attributes, UINT32 index, GUID *key, PROPVARIANT *value)
2784 HRESULT hr = S_OK;
2786 EnterCriticalSection(&attributes->cs);
2788 if (index < attributes->count)
2790 *key = attributes->attributes[index].key;
2791 if (value)
2792 PropVariantCopy(value, &attributes->attributes[index].value);
2794 else
2795 hr = E_INVALIDARG;
2797 LeaveCriticalSection(&attributes->cs);
2799 return hr;
2802 HRESULT attributes_CopyAllItems(struct attributes *attributes, IMFAttributes *dest)
2804 HRESULT hr = S_OK;
2805 size_t i;
2807 EnterCriticalSection(&attributes->cs);
2809 IMFAttributes_LockStore(dest);
2811 IMFAttributes_DeleteAllItems(dest);
2813 for (i = 0; i < attributes->count; ++i)
2815 hr = IMFAttributes_SetItem(dest, &attributes->attributes[i].key, &attributes->attributes[i].value);
2816 if (FAILED(hr))
2817 break;
2820 IMFAttributes_UnlockStore(dest);
2822 LeaveCriticalSection(&attributes->cs);
2824 return hr;
2827 static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
2829 struct attributes *attributes = impl_from_IMFAttributes(iface);
2831 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2833 return attributes_GetItem(attributes, key, value);
2836 static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2838 struct attributes *attributes = impl_from_IMFAttributes(iface);
2840 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
2842 return attributes_GetItemType(attributes, key, type);
2845 static HRESULT WINAPI mfattributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
2847 struct attributes *attributes = impl_from_IMFAttributes(iface);
2849 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
2851 return attributes_CompareItem(attributes, key, value, result);
2854 static HRESULT WINAPI mfattributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
2855 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2857 struct attributes *attributes = impl_from_IMFAttributes(iface);
2859 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
2861 return attributes_Compare(attributes, theirs, match_type, ret);
2864 static HRESULT WINAPI mfattributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
2866 struct attributes *attributes = impl_from_IMFAttributes(iface);
2868 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2870 return attributes_GetUINT32(attributes, key, value);
2873 static HRESULT WINAPI mfattributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
2875 struct attributes *attributes = impl_from_IMFAttributes(iface);
2877 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2879 return attributes_GetUINT64(attributes, key, value);
2882 static HRESULT WINAPI mfattributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
2884 struct attributes *attributes = impl_from_IMFAttributes(iface);
2886 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2888 return attributes_GetDouble(attributes, key, value);
2891 static HRESULT WINAPI mfattributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
2893 struct attributes *attributes = impl_from_IMFAttributes(iface);
2895 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2897 return attributes_GetGUID(attributes, key, value);
2900 static HRESULT WINAPI mfattributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
2902 struct attributes *attributes = impl_from_IMFAttributes(iface);
2904 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
2906 return attributes_GetStringLength(attributes, key, length);
2909 static HRESULT WINAPI mfattributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
2910 UINT32 size, UINT32 *length)
2912 struct attributes *attributes = impl_from_IMFAttributes(iface);
2914 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
2916 return attributes_GetString(attributes, key, value, size, length);
2919 static HRESULT WINAPI mfattributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
2921 struct attributes *attributes = impl_from_IMFAttributes(iface);
2923 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
2925 return attributes_GetAllocatedString(attributes, key, value, length);
2928 static HRESULT WINAPI mfattributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
2930 struct attributes *attributes = impl_from_IMFAttributes(iface);
2932 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
2934 return attributes_GetBlobSize(attributes, key, size);
2937 static HRESULT WINAPI mfattributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
2938 UINT32 bufsize, UINT32 *blobsize)
2940 struct attributes *attributes = impl_from_IMFAttributes(iface);
2942 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
2944 return attributes_GetBlob(attributes, key, buf, bufsize, blobsize);
2947 static HRESULT WINAPI mfattributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
2949 struct attributes *attributes = impl_from_IMFAttributes(iface);
2951 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
2953 return attributes_GetAllocatedBlob(attributes, key, buf, size);
2956 static HRESULT WINAPI mfattributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
2958 struct attributes *attributes = impl_from_IMFAttributes(iface);
2960 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
2962 return attributes_GetUnknown(attributes, key, riid, out);
2965 static HRESULT WINAPI mfattributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
2967 struct attributes *attributes = impl_from_IMFAttributes(iface);
2969 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
2971 return attributes_SetItem(attributes, key, value);
2974 static HRESULT WINAPI mfattributes_DeleteItem(IMFAttributes *iface, REFGUID key)
2976 struct attributes *attributes = impl_from_IMFAttributes(iface);
2978 TRACE("%p, %s.\n", iface, debugstr_attr(key));
2980 return attributes_DeleteItem(attributes, key);
2983 static HRESULT WINAPI mfattributes_DeleteAllItems(IMFAttributes *iface)
2985 struct attributes *attributes = impl_from_IMFAttributes(iface);
2987 TRACE("%p.\n", iface);
2989 return attributes_DeleteAllItems(attributes);
2992 static HRESULT WINAPI mfattributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
2994 struct attributes *attributes = impl_from_IMFAttributes(iface);
2996 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
2998 return attributes_SetUINT32(attributes, key, value);
3001 static HRESULT WINAPI mfattributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
3003 struct attributes *attributes = impl_from_IMFAttributes(iface);
3005 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
3007 return attributes_SetUINT64(attributes, key, value);
3010 static HRESULT WINAPI mfattributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
3012 struct attributes *attributes = impl_from_IMFAttributes(iface);
3014 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
3016 return attributes_SetDouble(attributes, key, value);
3019 static HRESULT WINAPI mfattributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
3021 struct attributes *attributes = impl_from_IMFAttributes(iface);
3023 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
3025 return attributes_SetGUID(attributes, key, value);
3028 static HRESULT WINAPI mfattributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
3030 struct attributes *attributes = impl_from_IMFAttributes(iface);
3032 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
3034 return attributes_SetString(attributes, key, value);
3037 static HRESULT WINAPI mfattributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
3039 struct attributes *attributes = impl_from_IMFAttributes(iface);
3041 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
3043 return attributes_SetBlob(attributes, key, buf, size);
3046 static HRESULT WINAPI mfattributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
3048 struct attributes *attributes = impl_from_IMFAttributes(iface);
3050 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
3052 return attributes_SetUnknown(attributes, key, unknown);
3055 static HRESULT WINAPI mfattributes_LockStore(IMFAttributes *iface)
3057 struct attributes *attributes = impl_from_IMFAttributes(iface);
3059 TRACE("%p.\n", iface);
3061 return attributes_LockStore(attributes);
3064 static HRESULT WINAPI mfattributes_UnlockStore(IMFAttributes *iface)
3066 struct attributes *attributes = impl_from_IMFAttributes(iface);
3068 TRACE("%p.\n", iface);
3070 return attributes_UnlockStore(attributes);
3073 static HRESULT WINAPI mfattributes_GetCount(IMFAttributes *iface, UINT32 *count)
3075 struct attributes *attributes = impl_from_IMFAttributes(iface);
3077 TRACE("%p, %p.\n", iface, count);
3079 return attributes_GetCount(attributes, count);
3082 static HRESULT WINAPI mfattributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
3084 struct attributes *attributes = impl_from_IMFAttributes(iface);
3086 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
3088 return attributes_GetItemByIndex(attributes, index, key, value);
3091 static HRESULT WINAPI mfattributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
3093 struct attributes *attributes = impl_from_IMFAttributes(iface);
3095 TRACE("%p, %p.\n", iface, dest);
3097 return attributes_CopyAllItems(attributes, dest);
3100 static const IMFAttributesVtbl mfattributes_vtbl =
3102 mfattributes_QueryInterface,
3103 mfattributes_AddRef,
3104 mfattributes_Release,
3105 mfattributes_GetItem,
3106 mfattributes_GetItemType,
3107 mfattributes_CompareItem,
3108 mfattributes_Compare,
3109 mfattributes_GetUINT32,
3110 mfattributes_GetUINT64,
3111 mfattributes_GetDouble,
3112 mfattributes_GetGUID,
3113 mfattributes_GetStringLength,
3114 mfattributes_GetString,
3115 mfattributes_GetAllocatedString,
3116 mfattributes_GetBlobSize,
3117 mfattributes_GetBlob,
3118 mfattributes_GetAllocatedBlob,
3119 mfattributes_GetUnknown,
3120 mfattributes_SetItem,
3121 mfattributes_DeleteItem,
3122 mfattributes_DeleteAllItems,
3123 mfattributes_SetUINT32,
3124 mfattributes_SetUINT64,
3125 mfattributes_SetDouble,
3126 mfattributes_SetGUID,
3127 mfattributes_SetString,
3128 mfattributes_SetBlob,
3129 mfattributes_SetUnknown,
3130 mfattributes_LockStore,
3131 mfattributes_UnlockStore,
3132 mfattributes_GetCount,
3133 mfattributes_GetItemByIndex,
3134 mfattributes_CopyAllItems
3137 HRESULT init_attributes_object(struct attributes *object, UINT32 size)
3139 object->IMFAttributes_iface.lpVtbl = &mfattributes_vtbl;
3140 object->ref = 1;
3141 InitializeCriticalSection(&object->cs);
3143 object->attributes = NULL;
3144 object->count = 0;
3145 object->capacity = 0;
3146 if (!mf_array_reserve((void **)&object->attributes, &object->capacity, size,
3147 sizeof(*object->attributes)))
3149 DeleteCriticalSection(&object->cs);
3150 return E_OUTOFMEMORY;
3153 return S_OK;
3156 void clear_attributes_object(struct attributes *object)
3158 size_t i;
3160 for (i = 0; i < object->count; i++)
3161 PropVariantClear(&object->attributes[i].value);
3162 heap_free(object->attributes);
3164 DeleteCriticalSection(&object->cs);
3167 /***********************************************************************
3168 * MFCreateAttributes (mfplat.@)
3170 HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size)
3172 struct attributes *object;
3173 HRESULT hr;
3175 TRACE("%p, %d\n", attributes, size);
3177 object = heap_alloc_zero(sizeof(*object));
3178 if (!object)
3179 return E_OUTOFMEMORY;
3181 if (FAILED(hr = init_attributes_object(object, size)))
3183 heap_free(object);
3184 return hr;
3186 *attributes = &object->IMFAttributes_iface;
3188 return S_OK;
3191 #define ATTRIBUTES_STORE_MAGIC 0x494d4641 /* IMFA */
3193 struct attributes_store_header
3195 DWORD magic;
3196 UINT32 count;
3199 struct attributes_store_item
3201 GUID key;
3202 QWORD type;
3203 union
3205 double f;
3206 UINT32 i32;
3207 UINT64 i64;
3208 struct
3210 DWORD size;
3211 DWORD offset;
3212 } subheader;
3213 } u;
3216 /***********************************************************************
3217 * MFGetAttributesAsBlobSize (mfplat.@)
3219 HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size)
3221 unsigned int i, count, length;
3222 HRESULT hr;
3223 GUID key;
3225 TRACE("%p, %p.\n", attributes, size);
3227 IMFAttributes_LockStore(attributes);
3229 hr = IMFAttributes_GetCount(attributes, &count);
3231 *size = sizeof(struct attributes_store_header);
3233 for (i = 0; i < count; ++i)
3235 MF_ATTRIBUTE_TYPE type;
3237 hr = IMFAttributes_GetItemByIndex(attributes, i, &key, NULL);
3238 if (FAILED(hr))
3239 break;
3241 *size += sizeof(struct attributes_store_item);
3243 IMFAttributes_GetItemType(attributes, &key, &type);
3245 switch (type)
3247 case MF_ATTRIBUTE_GUID:
3248 *size += sizeof(GUID);
3249 break;
3250 case MF_ATTRIBUTE_STRING:
3251 IMFAttributes_GetStringLength(attributes, &key, &length);
3252 *size += (length + 1) * sizeof(WCHAR);
3253 break;
3254 case MF_ATTRIBUTE_BLOB:
3255 IMFAttributes_GetBlobSize(attributes, &key, &length);
3256 *size += length;
3257 break;
3258 case MF_ATTRIBUTE_UINT32:
3259 case MF_ATTRIBUTE_UINT64:
3260 case MF_ATTRIBUTE_DOUBLE:
3261 case MF_ATTRIBUTE_IUNKNOWN:
3262 default:
3267 IMFAttributes_UnlockStore(attributes);
3269 return hr;
3272 struct attr_serialize_context
3274 UINT8 *buffer;
3275 UINT8 *ptr;
3276 UINT32 size;
3279 static void attributes_serialize_write(struct attr_serialize_context *context, const void *value, unsigned int size)
3281 memcpy(context->ptr, value, size);
3282 context->ptr += size;
3285 static BOOL attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
3286 const void *value)
3288 switch (item->type)
3290 case MF_ATTRIBUTE_UINT32:
3291 case MF_ATTRIBUTE_UINT64:
3292 case MF_ATTRIBUTE_DOUBLE:
3293 attributes_serialize_write(context, item, sizeof(*item));
3294 break;
3295 case MF_ATTRIBUTE_GUID:
3296 case MF_ATTRIBUTE_STRING:
3297 case MF_ATTRIBUTE_BLOB:
3298 item->u.subheader.offset = context->size - item->u.subheader.size;
3299 attributes_serialize_write(context, item, sizeof(*item));
3300 memcpy(context->buffer + item->u.subheader.offset, value, item->u.subheader.size);
3301 context->size -= item->u.subheader.size;
3302 break;
3303 default:
3304 return FALSE;
3307 return TRUE;
3310 /***********************************************************************
3311 * MFGetAttributesAsBlob (mfplat.@)
3313 HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size)
3315 struct attributes_store_header header;
3316 struct attr_serialize_context context;
3317 unsigned int required_size, i;
3318 PROPVARIANT value;
3319 UINT32 count;
3320 HRESULT hr;
3322 TRACE("%p, %p, %u.\n", attributes, buffer, size);
3324 if (FAILED(hr = MFGetAttributesAsBlobSize(attributes, &required_size)))
3325 return hr;
3327 if (required_size > size)
3328 return MF_E_BUFFERTOOSMALL;
3330 context.buffer = buffer;
3331 context.ptr = buffer;
3332 context.size = required_size;
3334 IMFAttributes_LockStore(attributes);
3336 header.magic = ATTRIBUTES_STORE_MAGIC;
3337 header.count = 0; /* Will be updated later */
3338 IMFAttributes_GetCount(attributes, &count);
3340 attributes_serialize_write(&context, &header, sizeof(header));
3342 for (i = 0; i < count; ++i)
3344 struct attributes_store_item item;
3345 const void *data = NULL;
3347 hr = IMFAttributes_GetItemByIndex(attributes, i, &item.key, &value);
3348 if (FAILED(hr))
3349 break;
3351 item.type = value.vt;
3353 switch (value.vt)
3355 case MF_ATTRIBUTE_UINT32:
3356 case MF_ATTRIBUTE_UINT64:
3357 item.u.i64 = value.u.uhVal.QuadPart;
3358 break;
3359 case MF_ATTRIBUTE_DOUBLE:
3360 item.u.f = value.u.dblVal;
3361 break;
3362 case MF_ATTRIBUTE_GUID:
3363 item.u.subheader.size = sizeof(*value.u.puuid);
3364 data = value.u.puuid;
3365 break;
3366 case MF_ATTRIBUTE_STRING:
3367 item.u.subheader.size = (lstrlenW(value.u.pwszVal) + 1) * sizeof(WCHAR);
3368 data = value.u.pwszVal;
3369 break;
3370 case MF_ATTRIBUTE_BLOB:
3371 item.u.subheader.size = value.u.caub.cElems;
3372 data = value.u.caub.pElems;
3373 break;
3374 case MF_ATTRIBUTE_IUNKNOWN:
3375 break;
3376 default:
3377 WARN("Unknown attribute type %#x.\n", value.vt);
3380 if (attributes_serialize_write_item(&context, &item, data))
3381 header.count++;
3383 PropVariantClear(&value);
3386 memcpy(context.buffer, &header, sizeof(header));
3388 IMFAttributes_UnlockStore(attributes);
3390 return S_OK;
3393 static HRESULT attributes_deserialize_read(struct attr_serialize_context *context, void *value, unsigned int size)
3395 if (context->size < (context->ptr - context->buffer) + size)
3396 return E_INVALIDARG;
3398 memcpy(value, context->ptr, size);
3399 context->ptr += size;
3401 return S_OK;
3404 /***********************************************************************
3405 * MFInitAttributesFromBlob (mfplat.@)
3407 HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *dest, const UINT8 *buffer, UINT size)
3409 struct attr_serialize_context context;
3410 struct attributes_store_header header;
3411 struct attributes_store_item item;
3412 IMFAttributes *attributes;
3413 unsigned int i;
3414 HRESULT hr;
3416 TRACE("%p, %p, %u.\n", dest, buffer, size);
3418 context.buffer = (UINT8 *)buffer;
3419 context.ptr = (UINT8 *)buffer;
3420 context.size = size;
3422 /* Validate buffer structure. */
3423 if (FAILED(hr = attributes_deserialize_read(&context, &header, sizeof(header))))
3424 return hr;
3426 if (header.magic != ATTRIBUTES_STORE_MAGIC)
3427 return E_UNEXPECTED;
3429 if (FAILED(hr = MFCreateAttributes(&attributes, header.count)))
3430 return hr;
3432 for (i = 0; i < header.count; ++i)
3434 if (FAILED(hr = attributes_deserialize_read(&context, &item, sizeof(item))))
3435 break;
3437 hr = E_UNEXPECTED;
3439 switch (item.type)
3441 case MF_ATTRIBUTE_UINT32:
3442 hr = IMFAttributes_SetUINT32(attributes, &item.key, item.u.i32);
3443 break;
3444 case MF_ATTRIBUTE_UINT64:
3445 hr = IMFAttributes_SetUINT64(attributes, &item.key, item.u.i64);
3446 break;
3447 case MF_ATTRIBUTE_DOUBLE:
3448 hr = IMFAttributes_SetDouble(attributes, &item.key, item.u.f);
3449 break;
3450 case MF_ATTRIBUTE_GUID:
3451 if (item.u.subheader.size == sizeof(GUID) &&
3452 item.u.subheader.offset + item.u.subheader.size <= context.size)
3454 hr = IMFAttributes_SetGUID(attributes, &item.key,
3455 (const GUID *)(context.buffer + item.u.subheader.offset));
3457 break;
3458 case MF_ATTRIBUTE_STRING:
3459 if (item.u.subheader.size >= sizeof(WCHAR) &&
3460 item.u.subheader.offset + item.u.subheader.size <= context.size)
3462 hr = IMFAttributes_SetString(attributes, &item.key,
3463 (const WCHAR *)(context.buffer + item.u.subheader.offset));
3465 break;
3466 case MF_ATTRIBUTE_BLOB:
3467 if (item.u.subheader.size > 0 && item.u.subheader.offset + item.u.subheader.size <= context.size)
3469 hr = IMFAttributes_SetBlob(attributes, &item.key, context.buffer + item.u.subheader.offset,
3470 item.u.subheader.size);
3472 break;
3473 default:
3477 if (FAILED(hr))
3478 break;
3481 if (SUCCEEDED(hr))
3483 IMFAttributes_DeleteAllItems(dest);
3484 hr = IMFAttributes_CopyAllItems(attributes, dest);
3487 IMFAttributes_Release(attributes);
3489 return hr;
3492 typedef struct bytestream
3494 struct attributes attributes;
3495 IMFByteStream IMFByteStream_iface;
3496 IMFGetService IMFGetService_iface;
3497 IRtwqAsyncCallback read_callback;
3498 IRtwqAsyncCallback write_callback;
3499 IStream *stream;
3500 HANDLE hfile;
3501 QWORD position;
3502 DWORD capabilities;
3503 struct list pending;
3504 CRITICAL_SECTION cs;
3505 } mfbytestream;
3507 static inline mfbytestream *impl_from_IMFByteStream(IMFByteStream *iface)
3509 return CONTAINING_RECORD(iface, mfbytestream, IMFByteStream_iface);
3512 static struct bytestream *impl_bytestream_from_IMFGetService(IMFGetService *iface)
3514 return CONTAINING_RECORD(iface, struct bytestream, IMFGetService_iface);
3517 static struct bytestream *impl_from_read_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3519 return CONTAINING_RECORD(iface, struct bytestream, read_callback);
3522 static struct bytestream *impl_from_write_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3524 return CONTAINING_RECORD(iface, struct bytestream, write_callback);
3527 enum async_stream_op_type
3529 ASYNC_STREAM_OP_READ,
3530 ASYNC_STREAM_OP_WRITE,
3533 struct async_stream_op
3535 IUnknown IUnknown_iface;
3536 LONG refcount;
3537 union
3539 const BYTE *src;
3540 BYTE *dest;
3541 } u;
3542 QWORD position;
3543 ULONG requested_length;
3544 ULONG actual_length;
3545 IMFAsyncResult *caller;
3546 struct list entry;
3547 enum async_stream_op_type type;
3550 static struct async_stream_op *impl_async_stream_op_from_IUnknown(IUnknown *iface)
3552 return CONTAINING_RECORD(iface, struct async_stream_op, IUnknown_iface);
3555 static HRESULT WINAPI async_stream_op_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
3557 if (IsEqualIID(riid, &IID_IUnknown))
3559 *obj = iface;
3560 IUnknown_AddRef(iface);
3561 return S_OK;
3564 WARN("Unsupported %s.\n", debugstr_guid(riid));
3565 *obj = NULL;
3566 return E_NOINTERFACE;
3569 static ULONG WINAPI async_stream_op_AddRef(IUnknown *iface)
3571 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3572 ULONG refcount = InterlockedIncrement(&op->refcount);
3574 TRACE("%p, refcount %d.\n", iface, refcount);
3576 return refcount;
3579 static ULONG WINAPI async_stream_op_Release(IUnknown *iface)
3581 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3582 ULONG refcount = InterlockedDecrement(&op->refcount);
3584 TRACE("%p, refcount %d.\n", iface, refcount);
3586 if (!refcount)
3588 if (op->caller)
3589 IMFAsyncResult_Release(op->caller);
3590 heap_free(op);
3593 return refcount;
3596 static const IUnknownVtbl async_stream_op_vtbl =
3598 async_stream_op_QueryInterface,
3599 async_stream_op_AddRef,
3600 async_stream_op_Release,
3603 static HRESULT bytestream_create_io_request(struct bytestream *stream, enum async_stream_op_type type,
3604 const BYTE *data, ULONG size, IMFAsyncCallback *callback, IUnknown *state)
3606 struct async_stream_op *op;
3607 IRtwqAsyncResult *request;
3608 HRESULT hr;
3610 op = heap_alloc(sizeof(*op));
3611 if (!op)
3612 return E_OUTOFMEMORY;
3614 op->IUnknown_iface.lpVtbl = &async_stream_op_vtbl;
3615 op->refcount = 1;
3616 op->u.src = data;
3617 op->position = stream->position;
3618 op->requested_length = size;
3619 op->type = type;
3620 if (FAILED(hr = RtwqCreateAsyncResult((IUnknown *)&stream->IMFByteStream_iface, (IRtwqAsyncCallback *)callback, state,
3621 (IRtwqAsyncResult **)&op->caller)))
3623 goto failed;
3626 if (FAILED(hr = RtwqCreateAsyncResult(&op->IUnknown_iface, type == ASYNC_STREAM_OP_READ ? &stream->read_callback :
3627 &stream->write_callback, NULL, &request)))
3628 goto failed;
3630 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, request);
3631 IRtwqAsyncResult_Release(request);
3633 failed:
3634 IUnknown_Release(&op->IUnknown_iface);
3635 return hr;
3638 static HRESULT bytestream_complete_io_request(struct bytestream *stream, enum async_stream_op_type type,
3639 IMFAsyncResult *result, ULONG *actual_length)
3641 struct async_stream_op *op = NULL, *cur;
3642 HRESULT hr;
3644 EnterCriticalSection(&stream->cs);
3645 LIST_FOR_EACH_ENTRY(cur, &stream->pending, struct async_stream_op, entry)
3647 if (cur->caller == result && cur->type == type)
3649 op = cur;
3650 list_remove(&cur->entry);
3651 break;
3654 LeaveCriticalSection(&stream->cs);
3656 if (!op)
3657 return E_INVALIDARG;
3659 if (SUCCEEDED(hr = IMFAsyncResult_GetStatus(result)))
3660 *actual_length = op->actual_length;
3662 IUnknown_Release(&op->IUnknown_iface);
3664 return hr;
3667 static HRESULT WINAPI bytestream_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
3669 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
3670 IsEqualIID(riid, &IID_IUnknown))
3672 *obj = iface;
3673 IRtwqAsyncCallback_AddRef(iface);
3674 return S_OK;
3677 WARN("Unsupported %s.\n", debugstr_guid(riid));
3678 *obj = NULL;
3679 return E_NOINTERFACE;
3682 static ULONG WINAPI bytestream_read_callback_AddRef(IRtwqAsyncCallback *iface)
3684 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3685 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3688 static ULONG WINAPI bytestream_read_callback_Release(IRtwqAsyncCallback *iface)
3690 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3691 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3694 static HRESULT WINAPI bytestream_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
3696 return E_NOTIMPL;
3699 static ULONG WINAPI bytestream_write_callback_AddRef(IRtwqAsyncCallback *iface)
3701 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3702 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3705 static ULONG WINAPI bytestream_write_callback_Release(IRtwqAsyncCallback *iface)
3707 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3708 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3711 static HRESULT WINAPI bytestream_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
3713 struct bytestream *stream = impl_from_IMFByteStream(iface);
3715 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
3717 if (IsEqualIID(riid, &IID_IMFByteStream) ||
3718 IsEqualIID(riid, &IID_IUnknown))
3720 *out = &stream->IMFByteStream_iface;
3722 else if (IsEqualIID(riid, &IID_IMFAttributes))
3724 *out = &stream->attributes.IMFAttributes_iface;
3726 else if (stream->IMFGetService_iface.lpVtbl && IsEqualIID(riid, &IID_IMFGetService))
3728 *out = &stream->IMFGetService_iface;
3730 else
3732 WARN("Unsupported %s.\n", debugstr_guid(riid));
3733 *out = NULL;
3734 return E_NOINTERFACE;
3737 IUnknown_AddRef((IUnknown*)*out);
3738 return S_OK;
3741 static ULONG WINAPI bytestream_AddRef(IMFByteStream *iface)
3743 struct bytestream *stream = impl_from_IMFByteStream(iface);
3744 ULONG refcount = InterlockedIncrement(&stream->attributes.ref);
3746 TRACE("%p, refcount %d.\n", iface, refcount);
3748 return refcount;
3751 static ULONG WINAPI bytestream_Release(IMFByteStream *iface)
3753 struct bytestream *stream = impl_from_IMFByteStream(iface);
3754 ULONG refcount = InterlockedDecrement(&stream->attributes.ref);
3755 struct async_stream_op *cur, *cur2;
3757 TRACE("%p, refcount %d.\n", iface, refcount);
3759 if (!refcount)
3761 clear_attributes_object(&stream->attributes);
3762 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &stream->pending, struct async_stream_op, entry)
3764 list_remove(&cur->entry);
3765 IUnknown_Release(&cur->IUnknown_iface);
3767 DeleteCriticalSection(&stream->cs);
3768 if (stream->stream)
3769 IStream_Release(stream->stream);
3770 if (stream->hfile)
3771 CloseHandle(stream->hfile);
3772 heap_free(stream);
3775 return refcount;
3778 static HRESULT WINAPI bytestream_stream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3780 struct bytestream *stream = impl_from_IMFByteStream(iface);
3781 STATSTG stat;
3782 HRESULT hr;
3784 TRACE("%p, %p.\n", iface, capabilities);
3786 if (FAILED(hr = IStream_Stat(stream->stream, &stat, STATFLAG_NONAME)))
3787 return hr;
3789 *capabilities = MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_SEEKABLE;
3790 if (stat.grfMode & (STGM_WRITE | STGM_READWRITE))
3791 *capabilities |= MFBYTESTREAM_IS_WRITABLE;
3793 return S_OK;
3796 static HRESULT WINAPI bytestream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3798 struct bytestream *stream = impl_from_IMFByteStream(iface);
3800 TRACE("%p, %p.\n", iface, capabilities);
3802 *capabilities = stream->capabilities;
3804 return S_OK;
3807 static HRESULT WINAPI mfbytestream_SetLength(IMFByteStream *iface, QWORD length)
3809 mfbytestream *This = impl_from_IMFByteStream(iface);
3811 FIXME("%p, %s\n", This, wine_dbgstr_longlong(length));
3813 return E_NOTIMPL;
3816 static HRESULT WINAPI bytestream_file_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
3818 struct bytestream *stream = impl_from_IMFByteStream(iface);
3820 TRACE("%p, %p.\n", iface, position);
3822 if (!position)
3823 return E_INVALIDARG;
3825 *position = stream->position;
3827 return S_OK;
3830 static HRESULT WINAPI bytestream_file_GetLength(IMFByteStream *iface, QWORD *length)
3832 struct bytestream *stream = impl_from_IMFByteStream(iface);
3833 LARGE_INTEGER li;
3835 TRACE("%p, %p.\n", iface, length);
3837 if (!length)
3838 return E_INVALIDARG;
3840 if (GetFileSizeEx(stream->hfile, &li))
3841 *length = li.QuadPart;
3842 else
3843 return HRESULT_FROM_WIN32(GetLastError());
3845 return S_OK;
3848 static HRESULT WINAPI bytestream_file_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
3850 struct bytestream *stream = impl_from_IMFByteStream(iface);
3851 LARGE_INTEGER position, length;
3852 HRESULT hr = S_OK;
3854 TRACE("%p, %p.\n", iface, ret);
3856 EnterCriticalSection(&stream->cs);
3858 position.QuadPart = 0;
3859 if (SetFilePointerEx(stream->hfile, position, &length, FILE_END))
3860 *ret = stream->position >= length.QuadPart;
3861 else
3862 hr = HRESULT_FROM_WIN32(GetLastError());
3864 LeaveCriticalSection(&stream->cs);
3866 return hr;
3869 static HRESULT WINAPI bytestream_file_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
3871 struct bytestream *stream = impl_from_IMFByteStream(iface);
3872 LARGE_INTEGER position;
3873 HRESULT hr = S_OK;
3874 BOOL ret;
3876 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, read_len);
3878 EnterCriticalSection(&stream->cs);
3880 position.QuadPart = stream->position;
3881 if ((ret = SetFilePointerEx(stream->hfile, position, NULL, FILE_BEGIN)))
3883 if ((ret = ReadFile(stream->hfile, buffer, size, read_len, NULL)))
3884 stream->position += *read_len;
3887 if (!ret)
3888 hr = HRESULT_FROM_WIN32(GetLastError());
3890 LeaveCriticalSection(&stream->cs);
3892 return hr;
3895 static HRESULT WINAPI bytestream_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size, IMFAsyncCallback *callback,
3896 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_READ, data, size, callback, state);
3905 static HRESULT WINAPI bytestream_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
3907 struct bytestream *stream = impl_from_IMFByteStream(iface);
3909 TRACE("%p, %p, %p.\n", iface, result, byte_read);
3911 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_READ, result, byte_read);
3914 static HRESULT WINAPI mfbytestream_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
3916 mfbytestream *This = impl_from_IMFByteStream(iface);
3918 FIXME("%p, %p, %u, %p\n", This, data, count, written);
3920 return E_NOTIMPL;
3923 static HRESULT WINAPI bytestream_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
3924 IMFAsyncCallback *callback, IUnknown *state)
3926 struct bytestream *stream = impl_from_IMFByteStream(iface);
3928 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
3930 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_WRITE, data, size, callback, state);
3933 static HRESULT WINAPI bytestream_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
3935 struct bytestream *stream = impl_from_IMFByteStream(iface);
3937 TRACE("%p, %p, %p.\n", iface, result, written);
3939 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_WRITE, result, written);
3942 static HRESULT WINAPI mfbytestream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
3943 DWORD flags, QWORD *current)
3945 mfbytestream *This = impl_from_IMFByteStream(iface);
3947 FIXME("%p, %u, %s, 0x%08x, %p\n", This, seek, wine_dbgstr_longlong(offset), flags, current);
3949 return E_NOTIMPL;
3952 static HRESULT WINAPI mfbytestream_Flush(IMFByteStream *iface)
3954 mfbytestream *This = impl_from_IMFByteStream(iface);
3956 FIXME("%p\n", This);
3958 return E_NOTIMPL;
3961 static HRESULT WINAPI mfbytestream_Close(IMFByteStream *iface)
3963 mfbytestream *This = impl_from_IMFByteStream(iface);
3965 FIXME("%p\n", This);
3967 return E_NOTIMPL;
3970 static HRESULT WINAPI bytestream_SetCurrentPosition(IMFByteStream *iface, QWORD position)
3972 struct bytestream *stream = impl_from_IMFByteStream(iface);
3974 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
3976 EnterCriticalSection(&stream->cs);
3977 stream->position = position;
3978 LeaveCriticalSection(&stream->cs);
3980 return S_OK;
3983 static const IMFByteStreamVtbl bytestream_file_vtbl =
3985 bytestream_QueryInterface,
3986 bytestream_AddRef,
3987 bytestream_Release,
3988 bytestream_GetCapabilities,
3989 bytestream_file_GetLength,
3990 mfbytestream_SetLength,
3991 bytestream_file_GetCurrentPosition,
3992 bytestream_SetCurrentPosition,
3993 bytestream_file_IsEndOfStream,
3994 bytestream_file_Read,
3995 bytestream_BeginRead,
3996 bytestream_EndRead,
3997 mfbytestream_Write,
3998 bytestream_BeginWrite,
3999 bytestream_EndWrite,
4000 mfbytestream_Seek,
4001 mfbytestream_Flush,
4002 mfbytestream_Close
4005 static HRESULT WINAPI bytestream_stream_GetLength(IMFByteStream *iface, QWORD *length)
4007 struct bytestream *stream = impl_from_IMFByteStream(iface);
4008 STATSTG statstg;
4009 HRESULT hr;
4011 TRACE("%p, %p.\n", iface, length);
4013 if (FAILED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4014 return hr;
4016 *length = statstg.cbSize.QuadPart;
4018 return S_OK;
4021 static HRESULT WINAPI bytestream_stream_SetLength(IMFByteStream *iface, QWORD length)
4023 struct bytestream *stream = impl_from_IMFByteStream(iface);
4024 ULARGE_INTEGER size;
4025 HRESULT hr;
4027 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4029 EnterCriticalSection(&stream->cs);
4031 size.QuadPart = length;
4032 hr = IStream_SetSize(stream->stream, size);
4034 LeaveCriticalSection(&stream->cs);
4036 return hr;
4039 static HRESULT WINAPI bytestream_stream_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4041 struct bytestream *stream = impl_from_IMFByteStream(iface);
4043 TRACE("%p, %p.\n", iface, position);
4045 *position = stream->position;
4047 return S_OK;
4050 static HRESULT WINAPI bytestream_stream_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
4052 struct bytestream *stream = impl_from_IMFByteStream(iface);
4053 STATSTG statstg;
4054 HRESULT hr;
4056 TRACE("%p, %p.\n", iface, ret);
4058 EnterCriticalSection(&stream->cs);
4060 if (SUCCEEDED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4061 *ret = stream->position >= statstg.cbSize.QuadPart;
4063 LeaveCriticalSection(&stream->cs);
4065 return hr;
4068 static HRESULT WINAPI bytestream_stream_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
4070 struct bytestream *stream = impl_from_IMFByteStream(iface);
4071 LARGE_INTEGER position;
4072 HRESULT hr;
4074 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, read_len);
4076 EnterCriticalSection(&stream->cs);
4078 position.QuadPart = stream->position;
4079 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4081 if (SUCCEEDED(hr = IStream_Read(stream->stream, buffer, size, read_len)))
4082 stream->position += *read_len;
4085 LeaveCriticalSection(&stream->cs);
4087 return hr;
4090 static HRESULT WINAPI bytestream_stream_Write(IMFByteStream *iface, const BYTE *buffer, ULONG size, ULONG *written)
4092 struct bytestream *stream = impl_from_IMFByteStream(iface);
4093 LARGE_INTEGER position;
4094 HRESULT hr;
4096 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, written);
4098 EnterCriticalSection(&stream->cs);
4100 position.QuadPart = stream->position;
4101 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4103 if (SUCCEEDED(hr = IStream_Write(stream->stream, buffer, size, written)))
4104 stream->position += *written;
4107 LeaveCriticalSection(&stream->cs);
4109 return hr;
4112 static HRESULT WINAPI bytestream_stream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN origin, LONGLONG offset,
4113 DWORD flags, QWORD *current)
4115 struct bytestream *stream = impl_from_IMFByteStream(iface);
4116 HRESULT hr = S_OK;
4118 TRACE("%p, %u, %s, %#x, %p.\n", iface, origin, wine_dbgstr_longlong(offset), flags, current);
4120 EnterCriticalSection(&stream->cs);
4122 switch (origin)
4124 case msoBegin:
4125 stream->position = offset;
4126 break;
4127 case msoCurrent:
4128 stream->position += offset;
4129 break;
4130 default:
4131 WARN("Unknown origin mode %d.\n", origin);
4132 hr = E_INVALIDARG;
4135 *current = stream->position;
4137 LeaveCriticalSection(&stream->cs);
4139 return hr;
4142 static HRESULT WINAPI bytestream_stream_Flush(IMFByteStream *iface)
4144 struct bytestream *stream = impl_from_IMFByteStream(iface);
4146 TRACE("%p.\n", iface);
4148 return IStream_Commit(stream->stream, STGC_DEFAULT);
4151 static HRESULT WINAPI bytestream_stream_Close(IMFByteStream *iface)
4153 TRACE("%p.\n", iface);
4155 return S_OK;
4158 static const IMFByteStreamVtbl bytestream_stream_vtbl =
4160 bytestream_QueryInterface,
4161 bytestream_AddRef,
4162 bytestream_Release,
4163 bytestream_stream_GetCapabilities,
4164 bytestream_stream_GetLength,
4165 bytestream_stream_SetLength,
4166 bytestream_stream_GetCurrentPosition,
4167 bytestream_SetCurrentPosition,
4168 bytestream_stream_IsEndOfStream,
4169 bytestream_stream_Read,
4170 bytestream_BeginRead,
4171 bytestream_EndRead,
4172 bytestream_stream_Write,
4173 bytestream_BeginWrite,
4174 bytestream_EndWrite,
4175 bytestream_stream_Seek,
4176 bytestream_stream_Flush,
4177 bytestream_stream_Close,
4180 static inline mfbytestream *impl_from_IMFByteStream_IMFAttributes(IMFAttributes *iface)
4182 return CONTAINING_RECORD(iface, mfbytestream, attributes.IMFAttributes_iface);
4185 static HRESULT WINAPI mfbytestream_attributes_QueryInterface(
4186 IMFAttributes *iface, REFIID riid, void **out)
4188 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4189 return IMFByteStream_QueryInterface(&This->IMFByteStream_iface, riid, out);
4192 static ULONG WINAPI mfbytestream_attributes_AddRef(IMFAttributes *iface)
4194 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4195 return IMFByteStream_AddRef(&This->IMFByteStream_iface);
4198 static ULONG WINAPI mfbytestream_attributes_Release(IMFAttributes *iface)
4200 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4201 return IMFByteStream_Release(&This->IMFByteStream_iface);
4204 static const IMFAttributesVtbl mfbytestream_attributes_vtbl =
4206 mfbytestream_attributes_QueryInterface,
4207 mfbytestream_attributes_AddRef,
4208 mfbytestream_attributes_Release,
4209 mfattributes_GetItem,
4210 mfattributes_GetItemType,
4211 mfattributes_CompareItem,
4212 mfattributes_Compare,
4213 mfattributes_GetUINT32,
4214 mfattributes_GetUINT64,
4215 mfattributes_GetDouble,
4216 mfattributes_GetGUID,
4217 mfattributes_GetStringLength,
4218 mfattributes_GetString,
4219 mfattributes_GetAllocatedString,
4220 mfattributes_GetBlobSize,
4221 mfattributes_GetBlob,
4222 mfattributes_GetAllocatedBlob,
4223 mfattributes_GetUnknown,
4224 mfattributes_SetItem,
4225 mfattributes_DeleteItem,
4226 mfattributes_DeleteAllItems,
4227 mfattributes_SetUINT32,
4228 mfattributes_SetUINT64,
4229 mfattributes_SetDouble,
4230 mfattributes_SetGUID,
4231 mfattributes_SetString,
4232 mfattributes_SetBlob,
4233 mfattributes_SetUnknown,
4234 mfattributes_LockStore,
4235 mfattributes_UnlockStore,
4236 mfattributes_GetCount,
4237 mfattributes_GetItemByIndex,
4238 mfattributes_CopyAllItems
4241 static HRESULT WINAPI bytestream_stream_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4243 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4244 struct async_stream_op *op;
4245 LARGE_INTEGER position;
4246 IUnknown *object;
4247 HRESULT hr;
4249 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4250 return hr;
4252 op = impl_async_stream_op_from_IUnknown(object);
4254 EnterCriticalSection(&stream->cs);
4256 position.QuadPart = op->position;
4257 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4259 if (SUCCEEDED(hr = IStream_Read(stream->stream, op->u.dest, op->requested_length, &op->actual_length)))
4260 stream->position += op->actual_length;
4263 IMFAsyncResult_SetStatus(op->caller, hr);
4264 list_add_tail(&stream->pending, &op->entry);
4266 LeaveCriticalSection(&stream->cs);
4268 MFInvokeCallback(op->caller);
4270 return S_OK;
4273 static HRESULT WINAPI bytestream_stream_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4275 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4276 struct async_stream_op *op;
4277 LARGE_INTEGER position;
4278 IUnknown *object;
4279 HRESULT hr;
4281 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4282 return hr;
4284 op = impl_async_stream_op_from_IUnknown(object);
4286 EnterCriticalSection(&stream->cs);
4288 position.QuadPart = op->position;
4289 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4291 if (SUCCEEDED(hr = IStream_Write(stream->stream, op->u.src, op->requested_length, &op->actual_length)))
4292 stream->position += op->actual_length;
4295 IMFAsyncResult_SetStatus(op->caller, hr);
4296 list_add_tail(&stream->pending, &op->entry);
4298 LeaveCriticalSection(&stream->cs);
4300 MFInvokeCallback(op->caller);
4302 return S_OK;
4305 static const IRtwqAsyncCallbackVtbl bytestream_stream_read_callback_vtbl =
4307 bytestream_callback_QueryInterface,
4308 bytestream_read_callback_AddRef,
4309 bytestream_read_callback_Release,
4310 bytestream_callback_GetParameters,
4311 bytestream_stream_read_callback_Invoke,
4314 static const IRtwqAsyncCallbackVtbl bytestream_stream_write_callback_vtbl =
4316 bytestream_callback_QueryInterface,
4317 bytestream_write_callback_AddRef,
4318 bytestream_write_callback_Release,
4319 bytestream_callback_GetParameters,
4320 bytestream_stream_write_callback_Invoke,
4323 /***********************************************************************
4324 * MFCreateMFByteStreamOnStream (mfplat.@)
4326 HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **bytestream)
4328 struct bytestream *object;
4329 LARGE_INTEGER position;
4330 STATSTG stat;
4331 HRESULT hr;
4333 TRACE("%p, %p.\n", stream, bytestream);
4335 object = heap_alloc_zero(sizeof(*object));
4336 if (!object)
4337 return E_OUTOFMEMORY;
4339 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
4341 heap_free(object);
4342 return hr;
4345 object->IMFByteStream_iface.lpVtbl = &bytestream_stream_vtbl;
4346 object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
4347 object->read_callback.lpVtbl = &bytestream_stream_read_callback_vtbl;
4348 object->write_callback.lpVtbl = &bytestream_stream_write_callback_vtbl;
4349 InitializeCriticalSection(&object->cs);
4350 list_init(&object->pending);
4352 object->stream = stream;
4353 IStream_AddRef(object->stream);
4354 position.QuadPart = 0;
4355 IStream_Seek(object->stream, position, STREAM_SEEK_SET, NULL);
4357 if (SUCCEEDED(IStream_Stat(object->stream, &stat, 0)))
4359 if (stat.pwcsName)
4361 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME,
4362 stat.pwcsName);
4363 CoTaskMemFree(stat.pwcsName);
4367 *bytestream = &object->IMFByteStream_iface;
4369 return S_OK;
4372 static HRESULT WINAPI bytestream_file_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4374 FIXME("%p, %p.\n", iface, result);
4376 return E_NOTIMPL;
4379 static HRESULT WINAPI bytestream_file_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4381 FIXME("%p, %p.\n", iface, result);
4383 return E_NOTIMPL;
4386 static const IRtwqAsyncCallbackVtbl bytestream_file_read_callback_vtbl =
4388 bytestream_callback_QueryInterface,
4389 bytestream_read_callback_AddRef,
4390 bytestream_read_callback_Release,
4391 bytestream_callback_GetParameters,
4392 bytestream_file_read_callback_Invoke,
4395 static const IRtwqAsyncCallbackVtbl bytestream_file_write_callback_vtbl =
4397 bytestream_callback_QueryInterface,
4398 bytestream_write_callback_AddRef,
4399 bytestream_write_callback_Release,
4400 bytestream_callback_GetParameters,
4401 bytestream_file_write_callback_Invoke,
4404 static HRESULT WINAPI bytestream_file_getservice_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
4406 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4407 return IMFByteStream_QueryInterface(&stream->IMFByteStream_iface, riid, obj);
4410 static ULONG WINAPI bytestream_file_getservice_AddRef(IMFGetService *iface)
4412 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4413 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
4416 static ULONG WINAPI bytestream_file_getservice_Release(IMFGetService *iface)
4418 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4419 return IMFByteStream_Release(&stream->IMFByteStream_iface);
4422 static HRESULT WINAPI bytestream_file_getservice_GetService(IMFGetService *iface, REFGUID service,
4423 REFIID riid, void **obj)
4425 FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
4427 return E_NOTIMPL;
4430 static const IMFGetServiceVtbl bytestream_file_getservice_vtbl =
4432 bytestream_file_getservice_QueryInterface,
4433 bytestream_file_getservice_AddRef,
4434 bytestream_file_getservice_Release,
4435 bytestream_file_getservice_GetService,
4438 /***********************************************************************
4439 * MFCreateFile (mfplat.@)
4441 HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4442 LPCWSTR url, IMFByteStream **bytestream)
4444 DWORD capabilities = MFBYTESTREAM_IS_SEEKABLE | MFBYTESTREAM_DOES_NOT_USE_NETWORK;
4445 DWORD filecreation_disposition = 0, fileaccessmode = 0, fileattributes = 0;
4446 DWORD filesharemode = FILE_SHARE_READ;
4447 struct bytestream *object;
4448 FILETIME writetime;
4449 HANDLE file;
4450 HRESULT hr;
4452 TRACE("%d, %d, %#x, %s, %p.\n", accessmode, openmode, flags, debugstr_w(url), bytestream);
4454 switch (accessmode)
4456 case MF_ACCESSMODE_READ:
4457 fileaccessmode = GENERIC_READ;
4458 capabilities |= MFBYTESTREAM_IS_READABLE;
4459 break;
4460 case MF_ACCESSMODE_WRITE:
4461 fileaccessmode = GENERIC_WRITE;
4462 capabilities |= MFBYTESTREAM_IS_WRITABLE;
4463 break;
4464 case MF_ACCESSMODE_READWRITE:
4465 fileaccessmode = GENERIC_READ | GENERIC_WRITE;
4466 capabilities |= (MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_WRITABLE);
4467 break;
4470 switch (openmode)
4472 case MF_OPENMODE_FAIL_IF_NOT_EXIST:
4473 filecreation_disposition = OPEN_EXISTING;
4474 break;
4475 case MF_OPENMODE_FAIL_IF_EXIST:
4476 filecreation_disposition = CREATE_NEW;
4477 break;
4478 case MF_OPENMODE_RESET_IF_EXIST:
4479 filecreation_disposition = TRUNCATE_EXISTING;
4480 break;
4481 case MF_OPENMODE_APPEND_IF_EXIST:
4482 filecreation_disposition = OPEN_ALWAYS;
4483 fileaccessmode |= FILE_APPEND_DATA;
4484 break;
4485 case MF_OPENMODE_DELETE_IF_EXIST:
4486 filecreation_disposition = CREATE_ALWAYS;
4487 break;
4490 if (flags & MF_FILEFLAGS_NOBUFFERING)
4491 fileattributes |= FILE_FLAG_NO_BUFFERING;
4493 /* Open HANDLE to file */
4494 file = CreateFileW(url, fileaccessmode, filesharemode, NULL,
4495 filecreation_disposition, fileattributes, 0);
4497 if(file == INVALID_HANDLE_VALUE)
4498 return HRESULT_FROM_WIN32(GetLastError());
4500 object = heap_alloc_zero(sizeof(*object));
4501 if (!object)
4503 CloseHandle(file);
4504 return E_OUTOFMEMORY;
4507 if (FAILED(hr = init_attributes_object(&object->attributes, 2)))
4509 CloseHandle(file);
4510 heap_free(object);
4511 return hr;
4513 object->IMFByteStream_iface.lpVtbl = &bytestream_file_vtbl;
4514 object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
4515 object->IMFGetService_iface.lpVtbl = &bytestream_file_getservice_vtbl;
4516 object->read_callback.lpVtbl = &bytestream_file_read_callback_vtbl;
4517 object->write_callback.lpVtbl = &bytestream_file_write_callback_vtbl;
4518 InitializeCriticalSection(&object->cs);
4519 list_init(&object->pending);
4520 object->capabilities = capabilities;
4521 object->hfile = file;
4523 if (GetFileTime(file, NULL, NULL, &writetime))
4525 IMFAttributes_SetBlob(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_LAST_MODIFIED_TIME,
4526 (const UINT8 *)&writetime, sizeof(writetime));
4529 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME, url);
4531 *bytestream = &object->IMFByteStream_iface;
4533 return S_OK;
4536 struct bytestream_wrapper
4538 IMFByteStreamCacheControl IMFByteStreamCacheControl_iface;
4539 IMFByteStreamBuffering IMFByteStreamBuffering_iface;
4540 IMFMediaEventGenerator IMFMediaEventGenerator_iface;
4541 IMFByteStreamTimeSeek IMFByteStreamTimeSeek_iface;
4542 IMFSampleOutputStream IMFSampleOutputStream_iface;
4543 IPropertyStore IPropertyStore_iface;
4544 IMFByteStream IMFByteStream_iface;
4545 IMFAttributes IMFAttributes_iface;
4546 LONG refcount;
4548 IMFByteStreamCacheControl *cache_control;
4549 IMFByteStreamBuffering *stream_buffering;
4550 IMFMediaEventGenerator *event_generator;
4551 IMFByteStreamTimeSeek *time_seek;
4552 IMFSampleOutputStream *sample_output;
4553 IPropertyStore *propstore;
4554 IMFByteStream *stream;
4555 IMFAttributes *attributes;
4556 BOOL is_closed;
4559 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStream(IMFByteStream *iface)
4561 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStream_iface);
4564 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamCacheControl(IMFByteStreamCacheControl *iface)
4566 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamCacheControl_iface);
4569 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamBuffering(IMFByteStreamBuffering *iface)
4571 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamBuffering_iface);
4574 static struct bytestream_wrapper *impl_wrapper_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
4576 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFMediaEventGenerator_iface);
4579 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamTimeSeek(IMFByteStreamTimeSeek *iface)
4581 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamTimeSeek_iface);
4584 static struct bytestream_wrapper *impl_wrapper_from_IMFSampleOutputStream(IMFSampleOutputStream *iface)
4586 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFSampleOutputStream_iface);
4589 static struct bytestream_wrapper *impl_wrapper_from_IPropertyStore(IPropertyStore *iface)
4591 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IPropertyStore_iface);
4594 static struct bytestream_wrapper *impl_wrapper_from_IMFAttributes(IMFAttributes *iface)
4596 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFAttributes_iface);
4599 static HRESULT WINAPI bytestream_wrapper_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
4601 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4603 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
4605 if (IsEqualIID(riid, &IID_IMFByteStream) ||
4606 IsEqualIID(riid, &IID_IUnknown))
4608 *out = &wrapper->IMFByteStream_iface;
4610 else if (wrapper->cache_control && IsEqualIID(riid, &IID_IMFByteStreamCacheControl))
4612 *out = &wrapper->IMFByteStreamCacheControl_iface;
4614 else if (wrapper->stream_buffering && IsEqualIID(riid, &IID_IMFByteStreamBuffering))
4616 *out = &wrapper->IMFByteStreamBuffering_iface;
4618 else if (wrapper->event_generator && IsEqualIID(riid, &IID_IMFMediaEventGenerator))
4620 *out = &wrapper->IMFMediaEventGenerator_iface;
4622 else if (wrapper->time_seek && IsEqualIID(riid, &IID_IMFByteStreamTimeSeek))
4624 *out = &wrapper->IMFByteStreamTimeSeek_iface;
4626 else if (wrapper->sample_output && IsEqualIID(riid, &IID_IMFSampleOutputStream))
4628 *out = &wrapper->IMFSampleOutputStream_iface;
4630 else if (wrapper->propstore && IsEqualIID(riid, &IID_IPropertyStore))
4632 *out = &wrapper->IPropertyStore_iface;
4634 else if (wrapper->attributes && IsEqualIID(riid, &IID_IMFAttributes))
4636 *out = &wrapper->IMFAttributes_iface;
4638 else
4640 WARN("Unsupported %s.\n", debugstr_guid(riid));
4641 *out = NULL;
4642 return E_NOINTERFACE;
4645 IUnknown_AddRef((IUnknown *)*out);
4646 return S_OK;
4649 static ULONG WINAPI bytestream_wrapper_AddRef(IMFByteStream *iface)
4651 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4652 ULONG refcount = InterlockedIncrement(&wrapper->refcount);
4654 TRACE("%p, refcount %d.\n", iface, refcount);
4656 return refcount;
4659 static ULONG WINAPI bytestream_wrapper_Release(IMFByteStream *iface)
4661 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4662 ULONG refcount = InterlockedDecrement(&wrapper->refcount);
4664 TRACE("%p, refcount %d.\n", iface, refcount);
4666 if (!refcount)
4668 if (wrapper->cache_control)
4669 IMFByteStreamCacheControl_Release(wrapper->cache_control);
4670 if (wrapper->stream_buffering)
4671 IMFByteStreamBuffering_Release(wrapper->stream_buffering);
4672 if (wrapper->event_generator)
4673 IMFMediaEventGenerator_Release(wrapper->event_generator);
4674 if (wrapper->time_seek)
4675 IMFByteStreamTimeSeek_Release(wrapper->time_seek);
4676 if (wrapper->sample_output)
4677 IMFSampleOutputStream_Release(wrapper->sample_output);
4678 if (wrapper->propstore)
4679 IPropertyStore_Release(wrapper->propstore);
4680 if (wrapper->attributes)
4681 IMFAttributes_Release(wrapper->attributes);
4682 IMFByteStream_Release(wrapper->stream);
4683 heap_free(wrapper);
4686 return refcount;
4689 static HRESULT WINAPI bytestream_wrapper_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
4691 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4693 TRACE("%p, %p.\n", iface, capabilities);
4695 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4696 IMFByteStream_GetCapabilities(wrapper->stream, capabilities);
4699 static HRESULT WINAPI bytestream_wrapper_GetLength(IMFByteStream *iface, QWORD *length)
4701 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4703 TRACE("%p, %p.\n", iface, length);
4705 if (wrapper->is_closed)
4706 return MF_E_INVALIDREQUEST;
4708 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4709 IMFByteStream_GetLength(wrapper->stream, length);
4712 static HRESULT WINAPI bytestream_wrapper_SetLength(IMFByteStream *iface, QWORD length)
4714 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4716 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4718 if (wrapper->is_closed)
4719 return MF_E_INVALIDREQUEST;
4721 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4722 IMFByteStream_SetLength(wrapper->stream, length);
4725 static HRESULT WINAPI bytestream_wrapper_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4727 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4729 TRACE("%p, %p.\n", iface, position);
4731 if (wrapper->is_closed)
4732 return MF_E_INVALIDREQUEST;
4734 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4735 IMFByteStream_GetCurrentPosition(wrapper->stream, position);
4738 static HRESULT WINAPI bytestream_wrapper_SetCurrentPosition(IMFByteStream *iface, QWORD position)
4740 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4742 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4744 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4745 IMFByteStream_SetCurrentPosition(wrapper->stream, position);
4748 static HRESULT WINAPI bytestream_wrapper_IsEndOfStream(IMFByteStream *iface, BOOL *eos)
4750 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4752 TRACE("%p, %p.\n", iface, eos);
4754 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4755 IMFByteStream_IsEndOfStream(wrapper->stream, eos);
4758 static HRESULT WINAPI bytestream_wrapper_Read(IMFByteStream *iface, BYTE *data, ULONG count, ULONG *byte_read)
4760 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4762 TRACE("%p, %p, %u, %p.\n", iface, data, count, byte_read);
4764 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4765 IMFByteStream_Read(wrapper->stream, data, count, byte_read);
4768 static HRESULT WINAPI bytestream_wrapper_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size,
4769 IMFAsyncCallback *callback, IUnknown *state)
4771 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4773 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
4775 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4776 IMFByteStream_BeginRead(wrapper->stream, data, size, callback, state);
4779 static HRESULT WINAPI bytestream_wrapper_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
4781 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4783 TRACE("%p, %p, %p.\n", iface, result, byte_read);
4785 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4786 IMFByteStream_EndRead(wrapper->stream, result, byte_read);
4789 static HRESULT WINAPI bytestream_wrapper_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
4791 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4793 TRACE("%p, %p, %u, %p.\n", iface, data, count, written);
4795 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4796 IMFByteStream_Write(wrapper->stream, data, count, written);
4799 static HRESULT WINAPI bytestream_wrapper_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
4800 IMFAsyncCallback *callback, IUnknown *state)
4802 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4804 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
4806 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4807 IMFByteStream_BeginWrite(wrapper->stream, data, size, callback, state);
4810 static HRESULT WINAPI bytestream_wrapper_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
4812 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4814 TRACE("%p, %p, %p.\n", iface, result, written);
4816 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4817 IMFByteStream_EndWrite(wrapper->stream, result, written);
4820 static HRESULT WINAPI bytestream_wrapper_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
4821 DWORD flags, QWORD *current)
4823 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4825 TRACE("%p, %u, %s, %#x, %p.\n", iface, seek, wine_dbgstr_longlong(offset), flags, current);
4827 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4828 IMFByteStream_Seek(wrapper->stream, seek, offset, flags, current);
4831 static HRESULT WINAPI bytestream_wrapper_Flush(IMFByteStream *iface)
4833 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4835 TRACE("%p\n", iface);
4837 return wrapper->is_closed ? MF_E_INVALIDREQUEST : IMFByteStream_Flush(wrapper->stream);
4840 static HRESULT WINAPI bytestream_wrapper_Close(IMFByteStream *iface)
4842 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4844 TRACE("%p\n", iface);
4846 wrapper->is_closed = TRUE;
4848 return S_OK;
4851 static const IMFByteStreamVtbl bytestream_wrapper_vtbl =
4853 bytestream_wrapper_QueryInterface,
4854 bytestream_wrapper_AddRef,
4855 bytestream_wrapper_Release,
4856 bytestream_wrapper_GetCapabilities,
4857 bytestream_wrapper_GetLength,
4858 bytestream_wrapper_SetLength,
4859 bytestream_wrapper_GetCurrentPosition,
4860 bytestream_wrapper_SetCurrentPosition,
4861 bytestream_wrapper_IsEndOfStream,
4862 bytestream_wrapper_Read,
4863 bytestream_wrapper_BeginRead,
4864 bytestream_wrapper_EndRead,
4865 bytestream_wrapper_Write,
4866 bytestream_wrapper_BeginWrite,
4867 bytestream_wrapper_EndWrite,
4868 bytestream_wrapper_Seek,
4869 bytestream_wrapper_Flush,
4870 bytestream_wrapper_Close,
4873 static HRESULT WINAPI bytestream_wrapper_cache_control_QueryInterface(IMFByteStreamCacheControl *iface,
4874 REFIID riid, void **obj)
4876 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4877 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4880 static ULONG WINAPI bytestream_wrapper_cache_control_AddRef(IMFByteStreamCacheControl *iface)
4882 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4883 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4886 static ULONG WINAPI bytestream_wrapper_cache_control_Release(IMFByteStreamCacheControl *iface)
4888 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4889 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4892 static HRESULT WINAPI bytestream_wrapper_cache_control_StopBackgroundTransfer(IMFByteStreamCacheControl *iface)
4894 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4896 TRACE("%p.\n", iface);
4898 return IMFByteStreamCacheControl_StopBackgroundTransfer(wrapper->cache_control);
4901 static const IMFByteStreamCacheControlVtbl bytestream_wrapper_cache_control_vtbl =
4903 bytestream_wrapper_cache_control_QueryInterface,
4904 bytestream_wrapper_cache_control_AddRef,
4905 bytestream_wrapper_cache_control_Release,
4906 bytestream_wrapper_cache_control_StopBackgroundTransfer,
4909 static HRESULT WINAPI bytestream_wrapper_buffering_QueryInterface(IMFByteStreamBuffering *iface,
4910 REFIID riid, void **obj)
4912 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4913 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4916 static ULONG WINAPI bytestream_wrapper_buffering_AddRef(IMFByteStreamBuffering *iface)
4918 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4919 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4922 static ULONG WINAPI bytestream_wrapper_buffering_Release(IMFByteStreamBuffering *iface)
4924 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4925 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4928 static HRESULT WINAPI bytestream_wrapper_buffering_SetBufferingParams(IMFByteStreamBuffering *iface,
4929 MFBYTESTREAM_BUFFERING_PARAMS *params)
4931 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4933 TRACE("%p, %p.\n", iface, params);
4935 return IMFByteStreamBuffering_SetBufferingParams(wrapper->stream_buffering, params);
4938 static HRESULT WINAPI bytestream_wrapper_buffering_EnableBuffering(IMFByteStreamBuffering *iface,
4939 BOOL enable)
4941 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4943 TRACE("%p, %d.\n", iface, enable);
4945 return IMFByteStreamBuffering_EnableBuffering(wrapper->stream_buffering, enable);
4948 static HRESULT WINAPI bytestream_wrapper_buffering_StopBuffering(IMFByteStreamBuffering *iface)
4950 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4952 TRACE("%p.\n", iface);
4954 return IMFByteStreamBuffering_StopBuffering(wrapper->stream_buffering);
4957 static const IMFByteStreamBufferingVtbl bytestream_wrapper_buffering_vtbl =
4959 bytestream_wrapper_buffering_QueryInterface,
4960 bytestream_wrapper_buffering_AddRef,
4961 bytestream_wrapper_buffering_Release,
4962 bytestream_wrapper_buffering_SetBufferingParams,
4963 bytestream_wrapper_buffering_EnableBuffering,
4964 bytestream_wrapper_buffering_StopBuffering,
4967 static HRESULT WINAPI bytestream_wrapper_timeseek_QueryInterface(IMFByteStreamTimeSeek *iface,
4968 REFIID riid, void **obj)
4970 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4971 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4974 static ULONG WINAPI bytestream_wrapper_timeseek_AddRef(IMFByteStreamTimeSeek *iface)
4976 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4977 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4980 static ULONG WINAPI bytestream_wrapper_timeseek_Release(IMFByteStreamTimeSeek *iface)
4982 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4983 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4986 static HRESULT WINAPI bytestream_wrapper_timeseek_IsTimeSeekSupported(IMFByteStreamTimeSeek *iface, BOOL *result)
4988 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4990 TRACE("%p, %p.\n", iface, result);
4992 return IMFByteStreamTimeSeek_IsTimeSeekSupported(wrapper->time_seek, result);
4995 static HRESULT WINAPI bytestream_wrapper_timeseek_TimeSeek(IMFByteStreamTimeSeek *iface, QWORD position)
4997 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4999 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
5001 return IMFByteStreamTimeSeek_TimeSeek(wrapper->time_seek, position);
5004 static HRESULT WINAPI bytestream_wrapper_timeseek_GetTimeSeekResult(IMFByteStreamTimeSeek *iface, QWORD *start_time,
5005 QWORD *stop_time, QWORD *duration)
5007 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5009 TRACE("%p, %p, %p, %p.\n", iface, start_time, stop_time, duration);
5011 return IMFByteStreamTimeSeek_GetTimeSeekResult(wrapper->time_seek, start_time, stop_time, duration);
5014 static const IMFByteStreamTimeSeekVtbl bytestream_wrapper_timeseek_vtbl =
5016 bytestream_wrapper_timeseek_QueryInterface,
5017 bytestream_wrapper_timeseek_AddRef,
5018 bytestream_wrapper_timeseek_Release,
5019 bytestream_wrapper_timeseek_IsTimeSeekSupported,
5020 bytestream_wrapper_timeseek_TimeSeek,
5021 bytestream_wrapper_timeseek_GetTimeSeekResult,
5024 static HRESULT WINAPI bytestream_wrapper_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
5026 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5027 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5030 static ULONG WINAPI bytestream_wrapper_events_AddRef(IMFMediaEventGenerator *iface)
5032 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5033 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5036 static ULONG WINAPI bytestream_wrapper_events_Release(IMFMediaEventGenerator *iface)
5038 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5039 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5042 static HRESULT WINAPI bytestream_wrapper_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
5044 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5046 TRACE("%p, %#x, %p.\n", iface, flags, event);
5048 return IMFMediaEventGenerator_GetEvent(wrapper->event_generator, flags, event);
5051 static HRESULT WINAPI bytestream_wrapper_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback, IUnknown *state)
5053 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5055 TRACE("%p, %p, %p.\n", iface, callback, state);
5057 return IMFMediaEventGenerator_BeginGetEvent(wrapper->event_generator, callback, state);
5060 static HRESULT WINAPI bytestream_wrapper_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result, IMFMediaEvent **event)
5062 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5064 TRACE("%p, %p, %p.\n", iface, result, event);
5066 return IMFMediaEventGenerator_EndGetEvent(wrapper->event_generator, result, event);
5069 static HRESULT WINAPI bytestream_wrapper_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType type,
5070 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
5072 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5074 TRACE("%p, %d, %s, %#x, %s.\n", iface, type, debugstr_guid(ext_type), hr, debugstr_propvar(value));
5076 return IMFMediaEventGenerator_QueueEvent(wrapper->event_generator, type, ext_type, hr, value);
5079 static const IMFMediaEventGeneratorVtbl bytestream_wrapper_events_vtbl =
5081 bytestream_wrapper_events_QueryInterface,
5082 bytestream_wrapper_events_AddRef,
5083 bytestream_wrapper_events_Release,
5084 bytestream_wrapper_events_GetEvent,
5085 bytestream_wrapper_events_BeginGetEvent,
5086 bytestream_wrapper_events_EndGetEvent,
5087 bytestream_wrapper_events_QueueEvent,
5090 static HRESULT WINAPI bytestream_wrapper_sample_output_QueryInterface(IMFSampleOutputStream *iface, REFIID riid, void **obj)
5092 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5093 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5096 static ULONG WINAPI bytestream_wrapper_sample_output_AddRef(IMFSampleOutputStream *iface)
5098 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5099 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5102 static ULONG WINAPI bytestream_wrapper_sample_output_Release(IMFSampleOutputStream *iface)
5104 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5105 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5108 static HRESULT WINAPI bytestream_wrapper_sample_output_BeginWriteSample(IMFSampleOutputStream *iface, IMFSample *sample,
5109 IMFAsyncCallback *callback, IUnknown *state)
5111 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5113 TRACE("%p, %p, %p, %p.\n", iface, sample, callback, state);
5115 return IMFSampleOutputStream_BeginWriteSample(wrapper->sample_output, sample, callback, state);
5118 static HRESULT WINAPI bytestream_wrapper_sample_output_EndWriteSample(IMFSampleOutputStream *iface, IMFAsyncResult *result)
5120 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5122 TRACE("%p, %p.\n", iface, result);
5124 return IMFSampleOutputStream_EndWriteSample(wrapper->sample_output, result);
5127 static HRESULT WINAPI bytestream_wrapper_sample_output_Close(IMFSampleOutputStream *iface)
5129 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5131 TRACE("%p.\n", iface);
5133 return IMFSampleOutputStream_Close(wrapper->sample_output);
5136 static const IMFSampleOutputStreamVtbl bytestream_wrapper_sample_output_vtbl =
5138 bytestream_wrapper_sample_output_QueryInterface,
5139 bytestream_wrapper_sample_output_AddRef,
5140 bytestream_wrapper_sample_output_Release,
5141 bytestream_wrapper_sample_output_BeginWriteSample,
5142 bytestream_wrapper_sample_output_EndWriteSample,
5143 bytestream_wrapper_sample_output_Close,
5146 static HRESULT WINAPI bytestream_wrapper_propstore_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
5148 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5149 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5152 static ULONG WINAPI bytestream_wrapper_propstore_AddRef(IPropertyStore *iface)
5154 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5155 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5158 static ULONG WINAPI bytestream_wrapper_propstore_Release(IPropertyStore *iface)
5160 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5161 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5164 static HRESULT WINAPI bytestream_wrapper_propstore_GetCount(IPropertyStore *iface, DWORD *count)
5166 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5168 TRACE("%p, %p.\n", iface, count);
5170 return IPropertyStore_GetCount(wrapper->propstore, count);
5173 static HRESULT WINAPI bytestream_wrapper_propstore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
5175 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5177 TRACE("%p, %u, %p.\n", iface, prop, key);
5179 return IPropertyStore_GetAt(wrapper->propstore, prop, key);
5182 static HRESULT WINAPI bytestream_wrapper_propstore_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
5184 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5186 TRACE("%p, %p, %p.\n", iface, key, value);
5188 return IPropertyStore_GetValue(wrapper->propstore, key, value);
5191 static HRESULT WINAPI bytestream_wrapper_propstore_SetValue(IPropertyStore *iface, REFPROPERTYKEY key,
5192 const PROPVARIANT *value)
5194 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5196 TRACE("%p, %p, %s.\n", iface, key, debugstr_propvar(value));
5198 return IPropertyStore_SetValue(wrapper->propstore, key, value);
5201 static HRESULT WINAPI bytestream_wrapper_propstore_Commit(IPropertyStore *iface)
5203 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5205 TRACE("%p.\n", iface);
5207 return IPropertyStore_Commit(wrapper->propstore);
5210 static const IPropertyStoreVtbl bytestream_wrapper_propstore_vtbl =
5212 bytestream_wrapper_propstore_QueryInterface,
5213 bytestream_wrapper_propstore_AddRef,
5214 bytestream_wrapper_propstore_Release,
5215 bytestream_wrapper_propstore_GetCount,
5216 bytestream_wrapper_propstore_GetAt,
5217 bytestream_wrapper_propstore_GetValue,
5218 bytestream_wrapper_propstore_SetValue,
5219 bytestream_wrapper_propstore_Commit,
5222 static HRESULT WINAPI bytestream_wrapper_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
5224 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5225 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5228 static ULONG WINAPI bytestream_wrapper_attributes_AddRef(IMFAttributes *iface)
5230 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5231 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5234 static ULONG WINAPI bytestream_wrapper_attributes_Release(IMFAttributes *iface)
5236 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5237 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5240 static HRESULT WINAPI bytestream_wrapper_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
5242 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5244 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5246 return IMFAttributes_GetItem(wrapper->attributes, key, value);
5249 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
5251 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5253 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
5255 return IMFAttributes_GetItemType(wrapper->attributes, key, type);
5258 static HRESULT WINAPI bytestream_wrapper_attributes_CompareItem(IMFAttributes *iface, REFGUID key,
5259 REFPROPVARIANT value, BOOL *result)
5261 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5263 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
5265 return IMFAttributes_CompareItem(wrapper->attributes, key, value, result);
5268 static HRESULT WINAPI bytestream_wrapper_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
5269 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
5271 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5273 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
5275 return IMFAttributes_Compare(wrapper->attributes, theirs, match_type, ret);
5278 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
5280 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5282 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5284 return IMFAttributes_GetUINT32(wrapper->attributes, key, value);
5287 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
5289 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5291 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5293 return IMFAttributes_GetUINT64(wrapper->attributes, key, value);
5296 static HRESULT WINAPI bytestream_wrapper_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
5298 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5300 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5302 return IMFAttributes_GetDouble(wrapper->attributes, key, value);
5305 static HRESULT WINAPI bytestream_wrapper_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
5307 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5309 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5311 return IMFAttributes_GetGUID(wrapper->attributes, key, value);
5314 static HRESULT WINAPI bytestream_wrapper_attributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
5316 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5318 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
5320 return IMFAttributes_GetStringLength(wrapper->attributes, key, length);
5323 static HRESULT WINAPI bytestream_wrapper_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
5324 UINT32 size, UINT32 *length)
5326 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5328 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
5330 return IMFAttributes_GetString(wrapper->attributes, key, value, size, length);
5333 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
5335 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5337 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
5339 return IMFAttributes_GetAllocatedString(wrapper->attributes, key, value, length);
5342 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
5344 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5346 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
5348 return IMFAttributes_GetBlobSize(wrapper->attributes, key, size);
5351 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
5352 UINT32 bufsize, UINT32 *blobsize)
5354 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5356 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
5358 return IMFAttributes_GetBlob(wrapper->attributes, key, buf, bufsize, blobsize);
5361 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
5363 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5365 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
5367 return IMFAttributes_GetAllocatedBlob(wrapper->attributes, key, buf, size);
5370 static HRESULT WINAPI bytestream_wrapper_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **obj)
5372 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5374 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), obj);
5376 return IMFAttributes_GetUnknown(wrapper->attributes, key, riid, obj);
5379 static HRESULT WINAPI bytestream_wrapper_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
5381 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5383 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
5385 return IMFAttributes_SetItem(wrapper->attributes, key, value);
5388 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
5390 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5392 TRACE("%p, %s.\n", iface, debugstr_attr(key));
5394 return IMFAttributes_DeleteItem(wrapper->attributes, key);
5397 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteAllItems(IMFAttributes *iface)
5399 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5401 TRACE("%p.\n", iface);
5403 return IMFAttributes_DeleteAllItems(wrapper->attributes);
5406 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
5408 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5410 TRACE("%p, %s, %d.\n", iface, debugstr_attr(key), value);
5412 return IMFAttributes_SetUINT32(wrapper->attributes, key, value);
5415 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
5417 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5419 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
5421 return IMFAttributes_SetUINT64(wrapper->attributes, key, value);
5424 static HRESULT WINAPI bytestream_wrapper_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
5426 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5428 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
5430 return IMFAttributes_SetDouble(wrapper->attributes, key, value);
5433 static HRESULT WINAPI bytestream_wrapper_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
5435 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5437 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
5439 return IMFAttributes_SetGUID(wrapper->attributes, key, value);
5442 static HRESULT WINAPI bytestream_wrapper_attributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
5444 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5446 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
5448 return IMFAttributes_SetString(wrapper->attributes, key, value);
5451 static HRESULT WINAPI bytestream_wrapper_attributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
5453 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5455 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
5457 return IMFAttributes_SetBlob(wrapper->attributes, key, buf, size);
5460 static HRESULT WINAPI bytestream_wrapper_attributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
5462 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5464 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
5466 return IMFAttributes_SetUnknown(wrapper->attributes, key, unknown);
5469 static HRESULT WINAPI bytestream_wrapper_attributes_LockStore(IMFAttributes *iface)
5471 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5473 TRACE("%p.\n", iface);
5475 return IMFAttributes_LockStore(wrapper->attributes);
5478 static HRESULT WINAPI bytestream_wrapper_attributes_UnlockStore(IMFAttributes *iface)
5480 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5482 TRACE("%p.\n", iface);
5484 return IMFAttributes_UnlockStore(wrapper->attributes);
5487 static HRESULT WINAPI bytestream_wrapper_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
5489 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5491 TRACE("%p, %p.\n", iface, count);
5493 return IMFAttributes_GetCount(wrapper->attributes, count);
5496 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
5498 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5500 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
5502 return IMFAttributes_GetItemByIndex(wrapper->attributes, index, key, value);
5505 static HRESULT WINAPI bytestream_wrapper_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
5507 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5509 TRACE("%p, %p.\n", iface, dest);
5511 return IMFAttributes_CopyAllItems(wrapper->attributes, dest);
5514 static const IMFAttributesVtbl bytestream_wrapper_attributes_vtbl =
5516 bytestream_wrapper_attributes_QueryInterface,
5517 bytestream_wrapper_attributes_AddRef,
5518 bytestream_wrapper_attributes_Release,
5519 bytestream_wrapper_attributes_GetItem,
5520 bytestream_wrapper_attributes_GetItemType,
5521 bytestream_wrapper_attributes_CompareItem,
5522 bytestream_wrapper_attributes_Compare,
5523 bytestream_wrapper_attributes_GetUINT32,
5524 bytestream_wrapper_attributes_GetUINT64,
5525 bytestream_wrapper_attributes_GetDouble,
5526 bytestream_wrapper_attributes_GetGUID,
5527 bytestream_wrapper_attributes_GetStringLength,
5528 bytestream_wrapper_attributes_GetString,
5529 bytestream_wrapper_attributes_GetAllocatedString,
5530 bytestream_wrapper_attributes_GetBlobSize,
5531 bytestream_wrapper_attributes_GetBlob,
5532 bytestream_wrapper_attributes_GetAllocatedBlob,
5533 bytestream_wrapper_attributes_GetUnknown,
5534 bytestream_wrapper_attributes_SetItem,
5535 bytestream_wrapper_attributes_DeleteItem,
5536 bytestream_wrapper_attributes_DeleteAllItems,
5537 bytestream_wrapper_attributes_SetUINT32,
5538 bytestream_wrapper_attributes_SetUINT64,
5539 bytestream_wrapper_attributes_SetDouble,
5540 bytestream_wrapper_attributes_SetGUID,
5541 bytestream_wrapper_attributes_SetString,
5542 bytestream_wrapper_attributes_SetBlob,
5543 bytestream_wrapper_attributes_SetUnknown,
5544 bytestream_wrapper_attributes_LockStore,
5545 bytestream_wrapper_attributes_UnlockStore,
5546 bytestream_wrapper_attributes_GetCount,
5547 bytestream_wrapper_attributes_GetItemByIndex,
5548 bytestream_wrapper_attributes_CopyAllItems
5551 /***********************************************************************
5552 * MFCreateMFByteStreamWrapper (mfplat.@)
5554 HRESULT WINAPI MFCreateMFByteStreamWrapper(IMFByteStream *stream, IMFByteStream **wrapper)
5556 struct bytestream_wrapper *object;
5558 TRACE("%p, %p.\n", stream, wrapper);
5560 object = heap_alloc_zero(sizeof(*object));
5561 if (!object)
5562 return E_OUTOFMEMORY;
5564 object->IMFByteStreamCacheControl_iface.lpVtbl = &bytestream_wrapper_cache_control_vtbl;
5565 object->IMFByteStreamBuffering_iface.lpVtbl = &bytestream_wrapper_buffering_vtbl;
5566 object->IMFMediaEventGenerator_iface.lpVtbl = &bytestream_wrapper_events_vtbl;
5567 object->IMFByteStreamTimeSeek_iface.lpVtbl = &bytestream_wrapper_timeseek_vtbl;
5568 object->IMFSampleOutputStream_iface.lpVtbl = &bytestream_wrapper_sample_output_vtbl;
5569 object->IMFByteStream_iface.lpVtbl = &bytestream_wrapper_vtbl;
5570 object->IPropertyStore_iface.lpVtbl = &bytestream_wrapper_propstore_vtbl;
5571 object->IMFAttributes_iface.lpVtbl = &bytestream_wrapper_attributes_vtbl;
5573 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamCacheControl, (void **)&object->cache_control);
5574 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamBuffering, (void **)&object->stream_buffering);
5575 IMFByteStream_QueryInterface(stream, &IID_IMFMediaEventGenerator, (void **)&object->event_generator);
5576 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamTimeSeek, (void **)&object->time_seek);
5577 IMFByteStream_QueryInterface(stream, &IID_IMFSampleOutputStream, (void **)&object->sample_output);
5578 IMFByteStream_QueryInterface(stream, &IID_IPropertyStore, (void **)&object->propstore);
5579 IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&object->attributes);
5581 object->stream = stream;
5582 IMFByteStream_AddRef(object->stream);
5584 object->refcount = 1;
5586 *wrapper = &object->IMFByteStream_iface;
5588 return S_OK;
5591 static HRESULT WINAPI MFPluginControl_QueryInterface(IMFPluginControl *iface, REFIID riid, void **ppv)
5593 if(IsEqualGUID(riid, &IID_IUnknown)) {
5594 TRACE("(IID_IUnknown %p)\n", ppv);
5595 *ppv = iface;
5596 }else if(IsEqualGUID(riid, &IID_IMFPluginControl)) {
5597 TRACE("(IID_IMFPluginControl %p)\n", ppv);
5598 *ppv = iface;
5599 }else {
5600 FIXME("(%s %p)\n", debugstr_guid(riid), ppv);
5601 *ppv = NULL;
5602 return E_NOINTERFACE;
5605 IUnknown_AddRef((IUnknown*)*ppv);
5606 return S_OK;
5609 static ULONG WINAPI MFPluginControl_AddRef(IMFPluginControl *iface)
5611 TRACE("\n");
5612 return 2;
5615 static ULONG WINAPI MFPluginControl_Release(IMFPluginControl *iface)
5617 TRACE("\n");
5618 return 1;
5621 static HRESULT WINAPI MFPluginControl_GetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5622 const WCHAR *selector, CLSID *clsid)
5624 FIXME("(%d %s %p)\n", plugin_type, debugstr_w(selector), clsid);
5625 return E_NOTIMPL;
5628 static HRESULT WINAPI MFPluginControl_GetPreferredClsidByIndex(IMFPluginControl *iface, DWORD plugin_type,
5629 DWORD index, WCHAR **selector, CLSID *clsid)
5631 FIXME("(%d %d %p %p)\n", plugin_type, index, selector, clsid);
5632 return E_NOTIMPL;
5635 static HRESULT WINAPI MFPluginControl_SetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5636 const WCHAR *selector, const CLSID *clsid)
5638 FIXME("(%d %s %s)\n", plugin_type, debugstr_w(selector), debugstr_guid(clsid));
5639 return E_NOTIMPL;
5642 static HRESULT WINAPI MFPluginControl_IsDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid)
5644 FIXME("(%d %s)\n", plugin_type, debugstr_guid(clsid));
5645 return E_NOTIMPL;
5648 static HRESULT WINAPI MFPluginControl_GetDisabledByIndex(IMFPluginControl *iface, DWORD plugin_type, DWORD index, CLSID *clsid)
5650 FIXME("(%d %d %p)\n", plugin_type, index, clsid);
5651 return E_NOTIMPL;
5654 static HRESULT WINAPI MFPluginControl_SetDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid, BOOL disabled)
5656 FIXME("(%d %s %x)\n", plugin_type, debugstr_guid(clsid), disabled);
5657 return E_NOTIMPL;
5660 static const IMFPluginControlVtbl MFPluginControlVtbl = {
5661 MFPluginControl_QueryInterface,
5662 MFPluginControl_AddRef,
5663 MFPluginControl_Release,
5664 MFPluginControl_GetPreferredClsid,
5665 MFPluginControl_GetPreferredClsidByIndex,
5666 MFPluginControl_SetPreferredClsid,
5667 MFPluginControl_IsDisabled,
5668 MFPluginControl_GetDisabledByIndex,
5669 MFPluginControl_SetDisabled
5672 static IMFPluginControl plugin_control = { &MFPluginControlVtbl };
5674 /***********************************************************************
5675 * MFGetPluginControl (mfplat.@)
5677 HRESULT WINAPI MFGetPluginControl(IMFPluginControl **ret)
5679 TRACE("(%p)\n", ret);
5681 *ret = &plugin_control;
5682 return S_OK;
5685 enum resolved_object_origin
5687 OBJECT_FROM_BYTESTREAM,
5688 OBJECT_FROM_URL,
5691 struct resolver_queued_result
5693 struct list entry;
5694 IUnknown *object;
5695 MF_OBJECT_TYPE obj_type;
5696 HRESULT hr;
5697 IRtwqAsyncResult *inner_result;
5698 enum resolved_object_origin origin;
5701 struct resolver_cancel_object
5703 IUnknown IUnknown_iface;
5704 LONG refcount;
5705 union
5707 IUnknown *handler;
5708 IMFByteStreamHandler *stream_handler;
5709 IMFSchemeHandler *scheme_handler;
5710 } u;
5711 IUnknown *cancel_cookie;
5712 enum resolved_object_origin origin;
5715 struct source_resolver
5717 IMFSourceResolver IMFSourceResolver_iface;
5718 LONG refcount;
5719 IRtwqAsyncCallback stream_callback;
5720 IRtwqAsyncCallback url_callback;
5721 CRITICAL_SECTION cs;
5722 struct list pending;
5725 static struct source_resolver *impl_from_IMFSourceResolver(IMFSourceResolver *iface)
5727 return CONTAINING_RECORD(iface, struct source_resolver, IMFSourceResolver_iface);
5730 static struct source_resolver *impl_from_stream_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5732 return CONTAINING_RECORD(iface, struct source_resolver, stream_callback);
5735 static struct source_resolver *impl_from_url_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5737 return CONTAINING_RECORD(iface, struct source_resolver, url_callback);
5740 static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enum resolved_object_origin origin,
5741 IRtwqAsyncResult *result)
5743 IRtwqAsyncResult *inner_result = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
5744 RTWQASYNCRESULT *data = (RTWQASYNCRESULT *)inner_result;
5745 struct resolver_queued_result *queued_result;
5746 union
5748 IUnknown *handler;
5749 IMFByteStreamHandler *stream_handler;
5750 IMFSchemeHandler *scheme_handler;
5751 } handler;
5753 if (!(queued_result = heap_alloc_zero(sizeof(*queued_result))))
5754 return E_OUTOFMEMORY;
5756 queued_result->origin = origin;
5758 IRtwqAsyncResult_GetObject(inner_result, &handler.handler);
5760 switch (origin)
5762 case OBJECT_FROM_BYTESTREAM:
5763 queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, (IMFAsyncResult *)result,
5764 &queued_result->obj_type, &queued_result->object);
5765 break;
5766 case OBJECT_FROM_URL:
5767 queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, (IMFAsyncResult *)result,
5768 &queued_result->obj_type, &queued_result->object);
5769 break;
5770 default:
5771 queued_result->hr = E_FAIL;
5774 IUnknown_Release(handler.handler);
5776 if (data->hEvent)
5778 queued_result->inner_result = inner_result;
5779 IRtwqAsyncResult_AddRef(queued_result->inner_result);
5782 /* Push resolved object type and created object, so we don't have to guess on End*() call. */
5783 EnterCriticalSection(&resolver->cs);
5784 list_add_tail(&resolver->pending, &queued_result->entry);
5785 LeaveCriticalSection(&resolver->cs);
5787 if (data->hEvent)
5788 SetEvent(data->hEvent);
5789 else
5791 IUnknown *caller_state = IRtwqAsyncResult_GetStateNoAddRef(inner_result);
5792 IRtwqAsyncResult *caller_result;
5794 if (SUCCEEDED(RtwqCreateAsyncResult(queued_result->object, data->pCallback, caller_state, &caller_result)))
5796 RtwqInvokeCallback(caller_result);
5797 IRtwqAsyncResult_Release(caller_result);
5801 return S_OK;
5804 static struct resolver_cancel_object *impl_cancel_obj_from_IUnknown(IUnknown *iface)
5806 return CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface);
5809 static HRESULT WINAPI resolver_cancel_object_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
5811 if (IsEqualIID(riid, &IID_IUnknown))
5813 *obj = iface;
5814 IUnknown_AddRef(iface);
5815 return S_OK;
5818 *obj = NULL;
5819 return E_NOINTERFACE;
5822 static ULONG WINAPI resolver_cancel_object_AddRef(IUnknown *iface)
5824 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5825 return InterlockedIncrement(&object->refcount);
5828 static ULONG WINAPI resolver_cancel_object_Release(IUnknown *iface)
5830 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5831 ULONG refcount = InterlockedDecrement(&object->refcount);
5833 if (!refcount)
5835 if (object->cancel_cookie)
5836 IUnknown_Release(object->cancel_cookie);
5837 IUnknown_Release(object->u.handler);
5838 heap_free(object);
5841 return refcount;
5844 static const IUnknownVtbl resolver_cancel_object_vtbl =
5846 resolver_cancel_object_QueryInterface,
5847 resolver_cancel_object_AddRef,
5848 resolver_cancel_object_Release,
5851 static struct resolver_cancel_object *unsafe_impl_cancel_obj_from_IUnknown(IUnknown *iface)
5853 if (!iface)
5854 return NULL;
5856 return (iface->lpVtbl == &resolver_cancel_object_vtbl) ?
5857 CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface) : NULL;
5860 static HRESULT resolver_create_cancel_object(IUnknown *handler, enum resolved_object_origin origin,
5861 IUnknown *cancel_cookie, IUnknown **cancel_object)
5863 struct resolver_cancel_object *object;
5865 object = heap_alloc_zero(sizeof(*object));
5866 if (!object)
5867 return E_OUTOFMEMORY;
5869 object->IUnknown_iface.lpVtbl = &resolver_cancel_object_vtbl;
5870 object->refcount = 1;
5871 object->u.handler = handler;
5872 IUnknown_AddRef(object->u.handler);
5873 object->cancel_cookie = cancel_cookie;
5874 IUnknown_AddRef(object->cancel_cookie);
5875 object->origin = origin;
5877 *cancel_object = &object->IUnknown_iface;
5879 return S_OK;
5882 static HRESULT WINAPI source_resolver_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
5884 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
5885 IsEqualIID(riid, &IID_IUnknown))
5887 *obj = iface;
5888 IRtwqAsyncCallback_AddRef(iface);
5889 return S_OK;
5892 *obj = NULL;
5893 return E_NOINTERFACE;
5896 static ULONG WINAPI source_resolver_callback_stream_AddRef(IRtwqAsyncCallback *iface)
5898 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5899 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
5902 static ULONG WINAPI source_resolver_callback_stream_Release(IRtwqAsyncCallback *iface)
5904 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5905 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
5908 static HRESULT WINAPI source_resolver_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
5910 return E_NOTIMPL;
5913 static HRESULT WINAPI source_resolver_callback_stream_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
5915 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5917 return resolver_handler_end_create(resolver, OBJECT_FROM_BYTESTREAM, result);
5920 static const IRtwqAsyncCallbackVtbl source_resolver_callback_stream_vtbl =
5922 source_resolver_callback_QueryInterface,
5923 source_resolver_callback_stream_AddRef,
5924 source_resolver_callback_stream_Release,
5925 source_resolver_callback_GetParameters,
5926 source_resolver_callback_stream_Invoke,
5929 static ULONG WINAPI source_resolver_callback_url_AddRef(IRtwqAsyncCallback *iface)
5931 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5932 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
5935 static ULONG WINAPI source_resolver_callback_url_Release(IRtwqAsyncCallback *iface)
5937 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5938 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
5941 static HRESULT WINAPI source_resolver_callback_url_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
5943 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5945 return resolver_handler_end_create(resolver, OBJECT_FROM_URL, result);
5948 static const IRtwqAsyncCallbackVtbl source_resolver_callback_url_vtbl =
5950 source_resolver_callback_QueryInterface,
5951 source_resolver_callback_url_AddRef,
5952 source_resolver_callback_url_Release,
5953 source_resolver_callback_GetParameters,
5954 source_resolver_callback_url_Invoke,
5957 static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void **handler)
5959 unsigned int j = 0, name_length, type;
5960 HRESULT hr = E_FAIL;
5961 WCHAR clsidW[39];
5962 CLSID clsid;
5964 name_length = ARRAY_SIZE(clsidW);
5965 while (!RegEnumValueW(hkey, j++, clsidW, &name_length, NULL, &type, NULL, NULL))
5967 if (type == REG_SZ)
5969 if (SUCCEEDED(CLSIDFromString(clsidW, &clsid)))
5971 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, riid, handler);
5972 if (SUCCEEDED(hr))
5973 break;
5977 name_length = ARRAY_SIZE(clsidW);
5980 return hr;
5983 static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags,
5984 IMFByteStreamHandler **handler)
5986 static const char streamhandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers";
5987 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
5988 IMFAttributes *attributes;
5989 const WCHAR *url_ext;
5990 WCHAR *mimeW = NULL;
5991 HRESULT hr = E_FAIL;
5992 unsigned int i, j;
5993 UINT32 length;
5995 *handler = NULL;
5997 /* MIME type */
5998 if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
6000 IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length);
6001 IMFAttributes_Release(attributes);
6004 /* Extension */
6005 url_ext = url ? wcsrchr(url, '.') : NULL;
6007 if (!url_ext && !mimeW)
6009 CoTaskMemFree(mimeW);
6010 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6013 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6015 struct local_handler *local_handler;
6017 EnterCriticalSection(&local_handlers_section);
6019 LIST_FOR_EACH_ENTRY(local_handler, &local_bytestream_handlers, struct local_handler, entry)
6021 if ((mimeW && !lstrcmpiW(mimeW, local_handler->u.bytestream.mime))
6022 || (url_ext && !lstrcmpiW(url_ext, local_handler->u.bytestream.extension)))
6024 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFByteStreamHandler,
6025 (void **)handler)))
6026 break;
6030 LeaveCriticalSection(&local_handlers_section);
6032 if (*handler)
6033 return hr;
6036 for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i)
6038 const WCHAR *namesW[2] = { mimeW, url_ext };
6039 HKEY hkey, hkey_handler;
6041 if (RegOpenKeyA(hkey_roots[i], streamhandlerspath, &hkey))
6042 continue;
6044 for (j = 0; j < ARRAY_SIZE(namesW); ++j)
6046 if (!namesW[j])
6047 continue;
6049 if (!RegOpenKeyW(hkey, namesW[j], &hkey_handler))
6051 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFByteStreamHandler, (void **)handler);
6052 RegCloseKey(hkey_handler);
6055 if (SUCCEEDED(hr))
6056 break;
6059 RegCloseKey(hkey);
6061 if (SUCCEEDED(hr))
6062 break;
6065 if (FAILED(hr))
6067 static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
6068 hr = CoCreateInstance(&CLSID_GStreamerByteStreamHandler, NULL, CLSCTX_INPROC_SERVER, &IID_IMFByteStreamHandler, (void **)handler);
6071 CoTaskMemFree(mimeW);
6072 return hr;
6075 static HRESULT resolver_create_scheme_handler(const WCHAR *scheme, DWORD flags, IMFSchemeHandler **handler)
6077 static const char schemehandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers";
6078 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6079 HRESULT hr = MF_E_UNSUPPORTED_SCHEME;
6080 unsigned int i;
6082 TRACE("%s, %#x, %p.\n", debugstr_w(scheme), flags, handler);
6084 *handler = NULL;
6086 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6088 struct local_handler *local_handler;
6090 EnterCriticalSection(&local_handlers_section);
6092 LIST_FOR_EACH_ENTRY(local_handler, &local_scheme_handlers, struct local_handler, entry)
6094 if (!lstrcmpiW(scheme, local_handler->u.scheme))
6096 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFSchemeHandler,
6097 (void **)handler)))
6098 break;
6102 LeaveCriticalSection(&local_handlers_section);
6104 if (*handler)
6105 return hr;
6108 for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
6110 HKEY hkey, hkey_handler;
6112 hr = MF_E_UNSUPPORTED_SCHEME;
6114 if (RegOpenKeyA(hkey_roots[i], schemehandlerspath, &hkey))
6115 continue;
6117 if (!RegOpenKeyW(hkey, scheme, &hkey_handler))
6119 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFSchemeHandler, (void **)handler);
6120 RegCloseKey(hkey_handler);
6123 RegCloseKey(hkey);
6125 if (SUCCEEDED(hr))
6126 break;
6129 return hr;
6132 static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSchemeHandler **handler)
6134 static const WCHAR fileschemeW[] = L"file:";
6135 const WCHAR *ptr = url;
6136 unsigned int len;
6137 WCHAR *scheme;
6138 HRESULT hr;
6140 /* RFC 3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
6141 while (*ptr)
6143 WCHAR ch = towlower(*ptr);
6145 if (*ptr == '*' && ptr == url)
6147 ptr++;
6148 break;
6150 else if (!(*ptr >= '0' && *ptr <= '9') &&
6151 !(ch >= 'a' && ch <= 'z') &&
6152 *ptr != '+' && *ptr != '-' && *ptr != '.')
6154 break;
6157 ptr++;
6160 /* Schemes must end with a ':', if not found try "file:" */
6161 if (ptr == url || *ptr != ':')
6163 url = fileschemeW;
6164 ptr = fileschemeW + ARRAY_SIZE(fileschemeW) - 1;
6167 len = ptr - url;
6168 scheme = heap_alloc((len + 1) * sizeof(WCHAR));
6169 if (!scheme)
6170 return E_OUTOFMEMORY;
6172 memcpy(scheme, url, len * sizeof(WCHAR));
6173 scheme[len] = 0;
6175 hr = resolver_create_scheme_handler(scheme, flags, handler);
6176 if (FAILED(hr) && url != fileschemeW)
6177 hr = resolver_create_scheme_handler(fileschemeW, flags, handler);
6179 heap_free(scheme);
6181 return hr;
6184 static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum resolved_object_origin origin,
6185 IRtwqAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out)
6187 struct resolver_queued_result *queued_result = NULL, *iter;
6188 IUnknown *object;
6189 HRESULT hr;
6191 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
6192 return hr;
6194 EnterCriticalSection(&resolver->cs);
6196 LIST_FOR_EACH_ENTRY(iter, &resolver->pending, struct resolver_queued_result, entry)
6198 if (iter->inner_result == result || (iter->object == object && iter->origin == origin))
6200 list_remove(&iter->entry);
6201 queued_result = iter;
6202 break;
6206 LeaveCriticalSection(&resolver->cs);
6208 IUnknown_Release(object);
6210 if (queued_result)
6212 *out = queued_result->object;
6213 *obj_type = queued_result->obj_type;
6214 hr = queued_result->hr;
6215 if (queued_result->inner_result)
6216 IRtwqAsyncResult_Release(queued_result->inner_result);
6217 heap_free(queued_result);
6219 else
6220 hr = E_UNEXPECTED;
6222 return hr;
6225 static HRESULT WINAPI source_resolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj)
6227 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6229 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
6231 if (IsEqualIID(riid, &IID_IMFSourceResolver) ||
6232 IsEqualIID(riid, &IID_IUnknown))
6234 *obj = &resolver->IMFSourceResolver_iface;
6236 else
6238 *obj = NULL;
6239 FIXME("unsupported interface %s\n", debugstr_guid(riid));
6240 return E_NOINTERFACE;
6243 IUnknown_AddRef((IUnknown *)*obj);
6244 return S_OK;
6247 static ULONG WINAPI source_resolver_AddRef(IMFSourceResolver *iface)
6249 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6250 ULONG refcount = InterlockedIncrement(&resolver->refcount);
6252 TRACE("%p, refcount %d.\n", iface, refcount);
6254 return refcount;
6257 static ULONG WINAPI source_resolver_Release(IMFSourceResolver *iface)
6259 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6260 ULONG refcount = InterlockedDecrement(&resolver->refcount);
6261 struct resolver_queued_result *result, *result2;
6263 TRACE("%p, refcount %d.\n", iface, refcount);
6265 if (!refcount)
6267 LIST_FOR_EACH_ENTRY_SAFE(result, result2, &resolver->pending, struct resolver_queued_result, entry)
6269 if (result->object)
6270 IUnknown_Release(result->object);
6271 list_remove(&result->entry);
6272 heap_free(result);
6274 DeleteCriticalSection(&resolver->cs);
6275 heap_free(resolver);
6278 return refcount;
6281 static HRESULT WINAPI source_resolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6282 DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6284 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6285 IMFSchemeHandler *handler;
6286 IRtwqAsyncResult *result;
6287 RTWQASYNCRESULT *data;
6288 HRESULT hr;
6290 TRACE("%p, %s, %#x, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, obj_type, object);
6292 if (!url || !obj_type || !object)
6293 return E_POINTER;
6295 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6296 return hr;
6298 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6299 IMFSchemeHandler_Release(handler);
6300 if (FAILED(hr))
6301 return hr;
6303 data = (RTWQASYNCRESULT *)result;
6304 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6306 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, NULL, (IMFAsyncCallback *)&resolver->url_callback,
6307 (IUnknown *)result);
6308 if (FAILED(hr))
6310 IRtwqAsyncResult_Release(result);
6311 return hr;
6314 WaitForSingleObject(data->hEvent, INFINITE);
6316 hr = resolver_end_create_object(resolver, OBJECT_FROM_URL, result, obj_type, object);
6317 IRtwqAsyncResult_Release(result);
6319 return hr;
6322 static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6323 const WCHAR *url, DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6325 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6326 IMFByteStreamHandler *handler;
6327 IRtwqAsyncResult *result;
6328 RTWQASYNCRESULT *data;
6329 HRESULT hr;
6331 TRACE("%p, %p, %s, %#x, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, obj_type, object);
6333 if (!stream || !obj_type || !object)
6334 return E_POINTER;
6336 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6337 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6339 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6340 IMFByteStreamHandler_Release(handler);
6341 if (FAILED(hr))
6342 return hr;
6344 data = (RTWQASYNCRESULT *)result;
6345 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6347 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props, NULL,
6348 (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6349 if (FAILED(hr))
6351 IRtwqAsyncResult_Release(result);
6352 return hr;
6355 WaitForSingleObject(data->hEvent, INFINITE);
6357 hr = resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, result, obj_type, object);
6358 IRtwqAsyncResult_Release(result);
6360 return hr;
6363 static HRESULT WINAPI source_resolver_BeginCreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6364 DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
6366 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6367 IMFSchemeHandler *handler;
6368 IUnknown *inner_cookie = NULL;
6369 IRtwqAsyncResult *result;
6370 HRESULT hr;
6372 TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
6374 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6375 return hr;
6377 if (cancel_cookie)
6378 *cancel_cookie = NULL;
6380 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6381 IMFSchemeHandler_Release(handler);
6382 if (FAILED(hr))
6383 return hr;
6385 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, cancel_cookie ? &inner_cookie : NULL,
6386 (IMFAsyncCallback *)&resolver->url_callback, (IUnknown *)result);
6388 if (SUCCEEDED(hr) && inner_cookie)
6389 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_URL, inner_cookie, cancel_cookie);
6391 IRtwqAsyncResult_Release(result);
6393 return hr;
6396 static HRESULT WINAPI source_resolver_EndCreateObjectFromURL(IMFSourceResolver *iface, IMFAsyncResult *result,
6397 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6399 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6401 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6403 return resolver_end_create_object(resolver, OBJECT_FROM_URL, (IRtwqAsyncResult *)result, obj_type, object);
6406 static HRESULT WINAPI source_resolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6407 const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback,
6408 IUnknown *state)
6410 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6411 IMFByteStreamHandler *handler;
6412 IUnknown *inner_cookie = NULL;
6413 IRtwqAsyncResult *result;
6414 HRESULT hr;
6416 TRACE("%p, %p, %s, %#x, %p, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, cancel_cookie,
6417 callback, state);
6419 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6420 return hr;
6422 if (cancel_cookie)
6423 *cancel_cookie = NULL;
6425 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6426 IMFByteStreamHandler_Release(handler);
6427 if (FAILED(hr))
6428 return hr;
6430 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props,
6431 cancel_cookie ? &inner_cookie : NULL, (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6433 /* Cancel object wraps underlying handler cancel cookie with context necessary to call CancelObjectCreate(). */
6434 if (SUCCEEDED(hr) && inner_cookie)
6435 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_BYTESTREAM, inner_cookie, cancel_cookie);
6437 IRtwqAsyncResult_Release(result);
6439 return hr;
6442 static HRESULT WINAPI source_resolver_EndCreateObjectFromByteStream(IMFSourceResolver *iface, IMFAsyncResult *result,
6443 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6445 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6447 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6449 return resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, (IRtwqAsyncResult *)result, obj_type, object);
6452 static HRESULT WINAPI source_resolver_CancelObjectCreation(IMFSourceResolver *iface, IUnknown *cancel_cookie)
6454 struct resolver_cancel_object *object;
6455 HRESULT hr;
6457 TRACE("%p, %p.\n", iface, cancel_cookie);
6459 if (!(object = unsafe_impl_cancel_obj_from_IUnknown(cancel_cookie)))
6460 return E_UNEXPECTED;
6462 switch (object->origin)
6464 case OBJECT_FROM_BYTESTREAM:
6465 hr = IMFByteStreamHandler_CancelObjectCreation(object->u.stream_handler, object->cancel_cookie);
6466 break;
6467 case OBJECT_FROM_URL:
6468 hr = IMFSchemeHandler_CancelObjectCreation(object->u.scheme_handler, object->cancel_cookie);
6469 break;
6470 default:
6471 hr = E_UNEXPECTED;
6474 return hr;
6477 static const IMFSourceResolverVtbl mfsourceresolvervtbl =
6479 source_resolver_QueryInterface,
6480 source_resolver_AddRef,
6481 source_resolver_Release,
6482 source_resolver_CreateObjectFromURL,
6483 source_resolver_CreateObjectFromByteStream,
6484 source_resolver_BeginCreateObjectFromURL,
6485 source_resolver_EndCreateObjectFromURL,
6486 source_resolver_BeginCreateObjectFromByteStream,
6487 source_resolver_EndCreateObjectFromByteStream,
6488 source_resolver_CancelObjectCreation,
6491 /***********************************************************************
6492 * MFCreateSourceResolver (mfplat.@)
6494 HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver)
6496 struct source_resolver *object;
6498 TRACE("%p\n", resolver);
6500 if (!resolver)
6501 return E_POINTER;
6503 object = heap_alloc_zero(sizeof(*object));
6504 if (!object)
6505 return E_OUTOFMEMORY;
6507 object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl;
6508 object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl;
6509 object->url_callback.lpVtbl = &source_resolver_callback_url_vtbl;
6510 object->refcount = 1;
6511 list_init(&object->pending);
6512 InitializeCriticalSection(&object->cs);
6514 *resolver = &object->IMFSourceResolver_iface;
6516 return S_OK;
6519 struct media_event
6521 struct attributes attributes;
6522 IMFMediaEvent IMFMediaEvent_iface;
6524 MediaEventType type;
6525 GUID extended_type;
6526 HRESULT status;
6527 PROPVARIANT value;
6530 static inline struct media_event *impl_from_IMFMediaEvent(IMFMediaEvent *iface)
6532 return CONTAINING_RECORD(iface, struct media_event, IMFMediaEvent_iface);
6535 static HRESULT WINAPI mfmediaevent_QueryInterface(IMFMediaEvent *iface, REFIID riid, void **out)
6537 struct media_event *event = impl_from_IMFMediaEvent(iface);
6539 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
6541 if(IsEqualGUID(riid, &IID_IUnknown) ||
6542 IsEqualGUID(riid, &IID_IMFAttributes) ||
6543 IsEqualGUID(riid, &IID_IMFMediaEvent))
6545 *out = &event->IMFMediaEvent_iface;
6547 else
6549 FIXME("%s, %p.\n", debugstr_guid(riid), out);
6550 *out = NULL;
6551 return E_NOINTERFACE;
6554 IUnknown_AddRef((IUnknown*)*out);
6555 return S_OK;
6558 static ULONG WINAPI mfmediaevent_AddRef(IMFMediaEvent *iface)
6560 struct media_event *event = impl_from_IMFMediaEvent(iface);
6561 ULONG refcount = InterlockedIncrement(&event->attributes.ref);
6563 TRACE("%p, refcount %u.\n", iface, refcount);
6565 return refcount;
6568 static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface)
6570 struct media_event *event = impl_from_IMFMediaEvent(iface);
6571 ULONG refcount = InterlockedDecrement(&event->attributes.ref);
6573 TRACE("%p, refcount %u.\n", iface, refcount);
6575 if (!refcount)
6577 clear_attributes_object(&event->attributes);
6578 PropVariantClear(&event->value);
6579 heap_free(event);
6582 return refcount;
6585 static HRESULT WINAPI mfmediaevent_GetItem(IMFMediaEvent *iface, REFGUID key, PROPVARIANT *value)
6587 struct media_event *event = impl_from_IMFMediaEvent(iface);
6589 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6591 return attributes_GetItem(&event->attributes, key, value);
6594 static HRESULT WINAPI mfmediaevent_GetItemType(IMFMediaEvent *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
6596 struct media_event *event = impl_from_IMFMediaEvent(iface);
6598 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
6600 return attributes_GetItemType(&event->attributes, key, type);
6603 static HRESULT WINAPI mfmediaevent_CompareItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
6605 struct media_event *event = impl_from_IMFMediaEvent(iface);
6607 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
6609 return attributes_CompareItem(&event->attributes, key, value, result);
6612 static HRESULT WINAPI mfmediaevent_Compare(IMFMediaEvent *iface, IMFAttributes *attrs, MF_ATTRIBUTES_MATCH_TYPE type,
6613 BOOL *result)
6615 struct media_event *event = impl_from_IMFMediaEvent(iface);
6617 TRACE("%p, %p, %d, %p.\n", iface, attrs, type, result);
6619 return attributes_Compare(&event->attributes, attrs, type, result);
6622 static HRESULT WINAPI mfmediaevent_GetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 *value)
6624 struct media_event *event = impl_from_IMFMediaEvent(iface);
6626 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6628 return attributes_GetUINT32(&event->attributes, key, value);
6631 static HRESULT WINAPI mfmediaevent_GetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 *value)
6633 struct media_event *event = impl_from_IMFMediaEvent(iface);
6635 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6637 return attributes_GetUINT64(&event->attributes, key, value);
6640 static HRESULT WINAPI mfmediaevent_GetDouble(IMFMediaEvent *iface, REFGUID key, double *value)
6642 struct media_event *event = impl_from_IMFMediaEvent(iface);
6644 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6646 return attributes_GetDouble(&event->attributes, key, value);
6649 static HRESULT WINAPI mfmediaevent_GetGUID(IMFMediaEvent *iface, REFGUID key, GUID *value)
6651 struct media_event *event = impl_from_IMFMediaEvent(iface);
6653 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6655 return attributes_GetGUID(&event->attributes, key, value);
6658 static HRESULT WINAPI mfmediaevent_GetStringLength(IMFMediaEvent *iface, REFGUID key, UINT32 *length)
6660 struct media_event *event = impl_from_IMFMediaEvent(iface);
6662 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
6664 return attributes_GetStringLength(&event->attributes, key, length);
6667 static HRESULT WINAPI mfmediaevent_GetString(IMFMediaEvent *iface, REFGUID key, WCHAR *value,
6668 UINT32 size, UINT32 *length)
6670 struct media_event *event = impl_from_IMFMediaEvent(iface);
6672 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), value, size, length);
6674 return attributes_GetString(&event->attributes, key, value, size, length);
6677 static HRESULT WINAPI mfmediaevent_GetAllocatedString(IMFMediaEvent *iface, REFGUID key,
6678 WCHAR **value, UINT32 *length)
6680 struct media_event *event = impl_from_IMFMediaEvent(iface);
6682 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
6684 return attributes_GetAllocatedString(&event->attributes, key, value, length);
6687 static HRESULT WINAPI mfmediaevent_GetBlobSize(IMFMediaEvent *iface, REFGUID key, UINT32 *size)
6689 struct media_event *event = impl_from_IMFMediaEvent(iface);
6691 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
6693 return attributes_GetBlobSize(&event->attributes, key, size);
6696 static HRESULT WINAPI mfmediaevent_GetBlob(IMFMediaEvent *iface, REFGUID key, UINT8 *buf,
6697 UINT32 bufsize, UINT32 *blobsize)
6699 struct media_event *event = impl_from_IMFMediaEvent(iface);
6701 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
6703 return attributes_GetBlob(&event->attributes, key, buf, bufsize, blobsize);
6706 static HRESULT WINAPI mfmediaevent_GetAllocatedBlob(IMFMediaEvent *iface, REFGUID key, UINT8 **buf, UINT32 *size)
6708 struct media_event *event = impl_from_IMFMediaEvent(iface);
6710 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
6712 return attributes_GetAllocatedBlob(&event->attributes, key, buf, size);
6715 static HRESULT WINAPI mfmediaevent_GetUnknown(IMFMediaEvent *iface, REFGUID key, REFIID riid, void **out)
6717 struct media_event *event = impl_from_IMFMediaEvent(iface);
6719 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
6721 return attributes_GetUnknown(&event->attributes, key, riid, out);
6724 static HRESULT WINAPI mfmediaevent_SetItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value)
6726 struct media_event *event = impl_from_IMFMediaEvent(iface);
6728 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
6730 return attributes_SetItem(&event->attributes, key, value);
6733 static HRESULT WINAPI mfmediaevent_DeleteItem(IMFMediaEvent *iface, REFGUID key)
6735 struct media_event *event = impl_from_IMFMediaEvent(iface);
6737 TRACE("%p, %s.\n", iface, debugstr_attr(key));
6739 return attributes_DeleteItem(&event->attributes, key);
6742 static HRESULT WINAPI mfmediaevent_DeleteAllItems(IMFMediaEvent *iface)
6744 struct media_event *event = impl_from_IMFMediaEvent(iface);
6746 TRACE("%p.\n", iface);
6748 return attributes_DeleteAllItems(&event->attributes);
6751 static HRESULT WINAPI mfmediaevent_SetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 value)
6753 struct media_event *event = impl_from_IMFMediaEvent(iface);
6755 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
6757 return attributes_SetUINT32(&event->attributes, key, value);
6760 static HRESULT WINAPI mfmediaevent_SetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 value)
6762 struct media_event *event = impl_from_IMFMediaEvent(iface);
6764 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
6766 return attributes_SetUINT64(&event->attributes, key, value);
6769 static HRESULT WINAPI mfmediaevent_SetDouble(IMFMediaEvent *iface, REFGUID key, double value)
6771 struct media_event *event = impl_from_IMFMediaEvent(iface);
6773 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
6775 return attributes_SetDouble(&event->attributes, key, value);
6778 static HRESULT WINAPI mfmediaevent_SetGUID(IMFMediaEvent *iface, REFGUID key, REFGUID value)
6780 struct media_event *event = impl_from_IMFMediaEvent(iface);
6782 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
6784 return attributes_SetGUID(&event->attributes, key, value);
6787 static HRESULT WINAPI mfmediaevent_SetString(IMFMediaEvent *iface, REFGUID key, const WCHAR *value)
6789 struct media_event *event = impl_from_IMFMediaEvent(iface);
6791 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
6793 return attributes_SetString(&event->attributes, key, value);
6796 static HRESULT WINAPI mfmediaevent_SetBlob(IMFMediaEvent *iface, REFGUID key, const UINT8 *buf, UINT32 size)
6798 struct media_event *event = impl_from_IMFMediaEvent(iface);
6800 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
6802 return attributes_SetBlob(&event->attributes, key, buf, size);
6805 static HRESULT WINAPI mfmediaevent_SetUnknown(IMFMediaEvent *iface, REFGUID key, IUnknown *unknown)
6807 struct media_event *event = impl_from_IMFMediaEvent(iface);
6809 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
6811 return attributes_SetUnknown(&event->attributes, key, unknown);
6814 static HRESULT WINAPI mfmediaevent_LockStore(IMFMediaEvent *iface)
6816 struct media_event *event = impl_from_IMFMediaEvent(iface);
6818 TRACE("%p.\n", iface);
6820 return attributes_LockStore(&event->attributes);
6823 static HRESULT WINAPI mfmediaevent_UnlockStore(IMFMediaEvent *iface)
6825 struct media_event *event = impl_from_IMFMediaEvent(iface);
6827 TRACE("%p.\n", iface);
6829 return attributes_UnlockStore(&event->attributes);
6832 static HRESULT WINAPI mfmediaevent_GetCount(IMFMediaEvent *iface, UINT32 *count)
6834 struct media_event *event = impl_from_IMFMediaEvent(iface);
6836 TRACE("%p, %p.\n", iface, count);
6838 return attributes_GetCount(&event->attributes, count);
6841 static HRESULT WINAPI mfmediaevent_GetItemByIndex(IMFMediaEvent *iface, UINT32 index, GUID *key, PROPVARIANT *value)
6843 struct media_event *event = impl_from_IMFMediaEvent(iface);
6845 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
6847 return attributes_GetItemByIndex(&event->attributes, index, key, value);
6850 static HRESULT WINAPI mfmediaevent_CopyAllItems(IMFMediaEvent *iface, IMFAttributes *dest)
6852 struct media_event *event = impl_from_IMFMediaEvent(iface);
6854 TRACE("%p, %p.\n", iface, dest);
6856 return attributes_CopyAllItems(&event->attributes, dest);
6859 static HRESULT WINAPI mfmediaevent_GetType(IMFMediaEvent *iface, MediaEventType *type)
6861 struct media_event *event = impl_from_IMFMediaEvent(iface);
6863 TRACE("%p, %p.\n", iface, type);
6865 *type = event->type;
6867 return S_OK;
6870 static HRESULT WINAPI mfmediaevent_GetExtendedType(IMFMediaEvent *iface, GUID *extended_type)
6872 struct media_event *event = impl_from_IMFMediaEvent(iface);
6874 TRACE("%p, %p.\n", iface, extended_type);
6876 *extended_type = event->extended_type;
6878 return S_OK;
6881 static HRESULT WINAPI mfmediaevent_GetStatus(IMFMediaEvent *iface, HRESULT *status)
6883 struct media_event *event = impl_from_IMFMediaEvent(iface);
6885 TRACE("%p, %p.\n", iface, status);
6887 *status = event->status;
6889 return S_OK;
6892 static HRESULT WINAPI mfmediaevent_GetValue(IMFMediaEvent *iface, PROPVARIANT *value)
6894 struct media_event *event = impl_from_IMFMediaEvent(iface);
6896 TRACE("%p, %p.\n", iface, value);
6898 PropVariantCopy(value, &event->value);
6900 return S_OK;
6903 static const IMFMediaEventVtbl mfmediaevent_vtbl =
6905 mfmediaevent_QueryInterface,
6906 mfmediaevent_AddRef,
6907 mfmediaevent_Release,
6908 mfmediaevent_GetItem,
6909 mfmediaevent_GetItemType,
6910 mfmediaevent_CompareItem,
6911 mfmediaevent_Compare,
6912 mfmediaevent_GetUINT32,
6913 mfmediaevent_GetUINT64,
6914 mfmediaevent_GetDouble,
6915 mfmediaevent_GetGUID,
6916 mfmediaevent_GetStringLength,
6917 mfmediaevent_GetString,
6918 mfmediaevent_GetAllocatedString,
6919 mfmediaevent_GetBlobSize,
6920 mfmediaevent_GetBlob,
6921 mfmediaevent_GetAllocatedBlob,
6922 mfmediaevent_GetUnknown,
6923 mfmediaevent_SetItem,
6924 mfmediaevent_DeleteItem,
6925 mfmediaevent_DeleteAllItems,
6926 mfmediaevent_SetUINT32,
6927 mfmediaevent_SetUINT64,
6928 mfmediaevent_SetDouble,
6929 mfmediaevent_SetGUID,
6930 mfmediaevent_SetString,
6931 mfmediaevent_SetBlob,
6932 mfmediaevent_SetUnknown,
6933 mfmediaevent_LockStore,
6934 mfmediaevent_UnlockStore,
6935 mfmediaevent_GetCount,
6936 mfmediaevent_GetItemByIndex,
6937 mfmediaevent_CopyAllItems,
6938 mfmediaevent_GetType,
6939 mfmediaevent_GetExtendedType,
6940 mfmediaevent_GetStatus,
6941 mfmediaevent_GetValue,
6944 /***********************************************************************
6945 * MFCreateMediaEvent (mfplat.@)
6947 HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HRESULT status, const PROPVARIANT *value,
6948 IMFMediaEvent **event)
6950 struct media_event *object;
6951 HRESULT hr;
6953 TRACE("%s, %s, %#x, %s, %p.\n", debugstr_eventid(type), debugstr_guid(extended_type), status,
6954 debugstr_propvar(value), event);
6956 object = heap_alloc(sizeof(*object));
6957 if (!object)
6958 return E_OUTOFMEMORY;
6960 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
6962 heap_free(object);
6963 return hr;
6965 object->IMFMediaEvent_iface.lpVtbl = &mfmediaevent_vtbl;
6967 object->type = type;
6968 object->extended_type = *extended_type;
6969 object->status = status;
6971 PropVariantInit(&object->value);
6972 if (value)
6973 PropVariantCopy(&object->value, value);
6975 *event = &object->IMFMediaEvent_iface;
6977 TRACE("Created event %p.\n", *event);
6979 return S_OK;
6982 struct event_queue
6984 IMFMediaEventQueue IMFMediaEventQueue_iface;
6985 LONG refcount;
6987 CRITICAL_SECTION cs;
6988 CONDITION_VARIABLE update_event;
6989 struct list events;
6990 BOOL is_shut_down;
6991 BOOL notified;
6992 IRtwqAsyncResult *subscriber;
6995 struct queued_event
6997 struct list entry;
6998 IMFMediaEvent *event;
7001 static inline struct event_queue *impl_from_IMFMediaEventQueue(IMFMediaEventQueue *iface)
7003 return CONTAINING_RECORD(iface, struct event_queue, IMFMediaEventQueue_iface);
7006 static IMFMediaEvent *queue_pop_event(struct event_queue *queue)
7008 struct list *head = list_head(&queue->events);
7009 struct queued_event *queued_event;
7010 IMFMediaEvent *event;
7012 if (!head)
7013 return NULL;
7015 queued_event = LIST_ENTRY(head, struct queued_event, entry);
7016 event = queued_event->event;
7017 list_remove(&queued_event->entry);
7018 heap_free(queued_event);
7019 return event;
7022 static void event_queue_cleanup(struct event_queue *queue)
7024 IMFMediaEvent *event;
7026 while ((event = queue_pop_event(queue)))
7027 IMFMediaEvent_Release(event);
7030 static HRESULT WINAPI eventqueue_QueryInterface(IMFMediaEventQueue *iface, REFIID riid, void **out)
7032 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7034 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7036 if (IsEqualIID(riid, &IID_IMFMediaEventQueue) ||
7037 IsEqualIID(riid, &IID_IUnknown))
7039 *out = &queue->IMFMediaEventQueue_iface;
7040 IMFMediaEventQueue_AddRef(iface);
7041 return S_OK;
7044 WARN("Unsupported %s.\n", debugstr_guid(riid));
7045 *out = NULL;
7046 return E_NOINTERFACE;
7049 static ULONG WINAPI eventqueue_AddRef(IMFMediaEventQueue *iface)
7051 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7052 ULONG refcount = InterlockedIncrement(&queue->refcount);
7054 TRACE("%p, refcount %u.\n", iface, refcount);
7056 return refcount;
7059 static ULONG WINAPI eventqueue_Release(IMFMediaEventQueue *iface)
7061 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7062 ULONG refcount = InterlockedDecrement(&queue->refcount);
7064 TRACE("%p, refcount %u.\n", queue, refcount);
7066 if (!refcount)
7068 event_queue_cleanup(queue);
7069 DeleteCriticalSection(&queue->cs);
7070 heap_free(queue);
7073 return refcount;
7076 static HRESULT WINAPI eventqueue_GetEvent(IMFMediaEventQueue *iface, DWORD flags, IMFMediaEvent **event)
7078 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7079 HRESULT hr = S_OK;
7081 TRACE("%p, %p.\n", iface, event);
7083 EnterCriticalSection(&queue->cs);
7085 if (queue->is_shut_down)
7086 hr = MF_E_SHUTDOWN;
7087 else if (queue->subscriber)
7088 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7089 else
7091 if (flags & MF_EVENT_FLAG_NO_WAIT)
7093 if (!(*event = queue_pop_event(queue)))
7094 hr = MF_E_NO_EVENTS_AVAILABLE;
7096 else
7098 while (list_empty(&queue->events) && !queue->is_shut_down)
7100 SleepConditionVariableCS(&queue->update_event, &queue->cs, INFINITE);
7102 *event = queue_pop_event(queue);
7103 if (queue->is_shut_down)
7104 hr = MF_E_SHUTDOWN;
7108 LeaveCriticalSection(&queue->cs);
7110 return hr;
7113 static void queue_notify_subscriber(struct event_queue *queue)
7115 if (list_empty(&queue->events) || !queue->subscriber || queue->notified)
7116 return;
7118 queue->notified = TRUE;
7119 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, queue->subscriber);
7122 static HRESULT WINAPI eventqueue_BeginGetEvent(IMFMediaEventQueue *iface, IMFAsyncCallback *callback, IUnknown *state)
7124 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7125 MFASYNCRESULT *result_data = (MFASYNCRESULT *)queue->subscriber;
7126 HRESULT hr;
7128 TRACE("%p, %p, %p.\n", iface, callback, state);
7130 if (!callback)
7131 return E_INVALIDARG;
7133 EnterCriticalSection(&queue->cs);
7135 if (queue->is_shut_down)
7136 hr = MF_E_SHUTDOWN;
7137 else if (result_data)
7139 if (result_data->pCallback == callback)
7140 hr = IRtwqAsyncResult_GetStateNoAddRef(queue->subscriber) == state ?
7141 MF_S_MULTIPLE_BEGIN : MF_E_MULTIPLE_BEGIN;
7142 else
7143 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7145 else
7147 hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &queue->subscriber);
7148 if (SUCCEEDED(hr))
7149 queue_notify_subscriber(queue);
7152 LeaveCriticalSection(&queue->cs);
7154 return hr;
7157 static HRESULT WINAPI eventqueue_EndGetEvent(IMFMediaEventQueue *iface, IMFAsyncResult *result, IMFMediaEvent **event)
7159 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7160 HRESULT hr = E_FAIL;
7162 TRACE("%p, %p, %p.\n", iface, result, event);
7164 EnterCriticalSection(&queue->cs);
7166 if (queue->is_shut_down)
7167 hr = MF_E_SHUTDOWN;
7168 else if (queue->subscriber == (IRtwqAsyncResult *)result)
7170 *event = queue_pop_event(queue);
7171 if (queue->subscriber)
7172 IRtwqAsyncResult_Release(queue->subscriber);
7173 queue->subscriber = NULL;
7174 queue->notified = FALSE;
7175 hr = *event ? S_OK : E_FAIL;
7178 LeaveCriticalSection(&queue->cs);
7180 return hr;
7183 static HRESULT eventqueue_queue_event(struct event_queue *queue, IMFMediaEvent *event)
7185 struct queued_event *queued_event;
7186 HRESULT hr = S_OK;
7188 queued_event = heap_alloc(sizeof(*queued_event));
7189 if (!queued_event)
7190 return E_OUTOFMEMORY;
7192 queued_event->event = event;
7194 EnterCriticalSection(&queue->cs);
7196 if (queue->is_shut_down)
7197 hr = MF_E_SHUTDOWN;
7198 else
7200 IMFMediaEvent_AddRef(queued_event->event);
7201 list_add_tail(&queue->events, &queued_event->entry);
7202 queue_notify_subscriber(queue);
7205 LeaveCriticalSection(&queue->cs);
7207 if (FAILED(hr))
7208 heap_free(queued_event);
7210 WakeAllConditionVariable(&queue->update_event);
7212 return hr;
7215 static HRESULT WINAPI eventqueue_QueueEvent(IMFMediaEventQueue *iface, IMFMediaEvent *event)
7217 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7219 TRACE("%p, %p.\n", iface, event);
7221 return eventqueue_queue_event(queue, event);
7224 static HRESULT WINAPI eventqueue_QueueEventParamVar(IMFMediaEventQueue *iface, MediaEventType event_type,
7225 REFGUID extended_type, HRESULT status, const PROPVARIANT *value)
7227 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7228 IMFMediaEvent *event;
7229 HRESULT hr;
7231 TRACE("%p, %s, %s, %#x, %s\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status,
7232 debugstr_propvar(value));
7234 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, value, &event)))
7235 return hr;
7237 hr = eventqueue_queue_event(queue, event);
7238 IMFMediaEvent_Release(event);
7239 return hr;
7242 static HRESULT WINAPI eventqueue_QueueEventParamUnk(IMFMediaEventQueue *iface, MediaEventType event_type,
7243 REFGUID extended_type, HRESULT status, IUnknown *unk)
7245 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7246 IMFMediaEvent *event;
7247 PROPVARIANT value;
7248 HRESULT hr;
7250 TRACE("%p, %s, %s, %#x, %p.\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status, unk);
7252 value.vt = VT_UNKNOWN;
7253 value.u.punkVal = unk;
7255 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, &value, &event)))
7256 return hr;
7258 hr = eventqueue_queue_event(queue, event);
7259 IMFMediaEvent_Release(event);
7260 return hr;
7263 static HRESULT WINAPI eventqueue_Shutdown(IMFMediaEventQueue *iface)
7265 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7267 TRACE("%p\n", queue);
7269 EnterCriticalSection(&queue->cs);
7271 if (!queue->is_shut_down)
7273 event_queue_cleanup(queue);
7274 queue->is_shut_down = TRUE;
7277 LeaveCriticalSection(&queue->cs);
7279 WakeAllConditionVariable(&queue->update_event);
7281 return S_OK;
7284 static const IMFMediaEventQueueVtbl eventqueuevtbl =
7286 eventqueue_QueryInterface,
7287 eventqueue_AddRef,
7288 eventqueue_Release,
7289 eventqueue_GetEvent,
7290 eventqueue_BeginGetEvent,
7291 eventqueue_EndGetEvent,
7292 eventqueue_QueueEvent,
7293 eventqueue_QueueEventParamVar,
7294 eventqueue_QueueEventParamUnk,
7295 eventqueue_Shutdown
7298 /***********************************************************************
7299 * MFCreateEventQueue (mfplat.@)
7301 HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue)
7303 struct event_queue *object;
7305 TRACE("%p\n", queue);
7307 object = heap_alloc_zero(sizeof(*object));
7308 if (!object)
7309 return E_OUTOFMEMORY;
7311 object->IMFMediaEventQueue_iface.lpVtbl = &eventqueuevtbl;
7312 object->refcount = 1;
7313 list_init(&object->events);
7314 InitializeCriticalSection(&object->cs);
7315 InitializeConditionVariable(&object->update_event);
7317 *queue = &object->IMFMediaEventQueue_iface;
7319 return S_OK;
7322 struct collection
7324 IMFCollection IMFCollection_iface;
7325 LONG refcount;
7326 IUnknown **elements;
7327 size_t capacity;
7328 size_t count;
7331 static struct collection *impl_from_IMFCollection(IMFCollection *iface)
7333 return CONTAINING_RECORD(iface, struct collection, IMFCollection_iface);
7336 static void collection_clear(struct collection *collection)
7338 size_t i;
7340 for (i = 0; i < collection->count; ++i)
7342 if (collection->elements[i])
7343 IUnknown_Release(collection->elements[i]);
7346 heap_free(collection->elements);
7347 collection->elements = NULL;
7348 collection->count = 0;
7349 collection->capacity = 0;
7352 static HRESULT WINAPI collection_QueryInterface(IMFCollection *iface, REFIID riid, void **out)
7354 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7356 if (IsEqualIID(riid, &IID_IMFCollection) ||
7357 IsEqualIID(riid, &IID_IUnknown))
7359 *out = iface;
7360 IMFCollection_AddRef(iface);
7361 return S_OK;
7364 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
7365 *out = NULL;
7366 return E_NOINTERFACE;
7369 static ULONG WINAPI collection_AddRef(IMFCollection *iface)
7371 struct collection *collection = impl_from_IMFCollection(iface);
7372 ULONG refcount = InterlockedIncrement(&collection->refcount);
7374 TRACE("%p, %d.\n", collection, refcount);
7376 return refcount;
7379 static ULONG WINAPI collection_Release(IMFCollection *iface)
7381 struct collection *collection = impl_from_IMFCollection(iface);
7382 ULONG refcount = InterlockedDecrement(&collection->refcount);
7384 TRACE("%p, %d.\n", collection, refcount);
7386 if (!refcount)
7388 collection_clear(collection);
7389 heap_free(collection->elements);
7390 heap_free(collection);
7393 return refcount;
7396 static HRESULT WINAPI collection_GetElementCount(IMFCollection *iface, DWORD *count)
7398 struct collection *collection = impl_from_IMFCollection(iface);
7400 TRACE("%p, %p.\n", iface, count);
7402 if (!count)
7403 return E_POINTER;
7405 *count = collection->count;
7407 return S_OK;
7410 static HRESULT WINAPI collection_GetElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7412 struct collection *collection = impl_from_IMFCollection(iface);
7414 TRACE("%p, %u, %p.\n", iface, idx, element);
7416 if (!element)
7417 return E_POINTER;
7419 if (idx >= collection->count)
7420 return E_INVALIDARG;
7422 *element = collection->elements[idx];
7423 if (*element)
7424 IUnknown_AddRef(*element);
7426 return *element ? S_OK : E_UNEXPECTED;
7429 static HRESULT WINAPI collection_AddElement(IMFCollection *iface, IUnknown *element)
7431 struct collection *collection = impl_from_IMFCollection(iface);
7433 TRACE("%p, %p.\n", iface, element);
7435 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, collection->count + 1,
7436 sizeof(*collection->elements)))
7437 return E_OUTOFMEMORY;
7439 collection->elements[collection->count++] = element;
7440 if (element)
7441 IUnknown_AddRef(element);
7443 return S_OK;
7446 static HRESULT WINAPI collection_RemoveElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7448 struct collection *collection = impl_from_IMFCollection(iface);
7449 size_t count;
7451 TRACE("%p, %u, %p.\n", iface, idx, element);
7453 if (!element)
7454 return E_POINTER;
7456 if (idx >= collection->count)
7457 return E_INVALIDARG;
7459 *element = collection->elements[idx];
7461 count = collection->count - idx - 1;
7462 if (count)
7463 memmove(&collection->elements[idx], &collection->elements[idx + 1], count * sizeof(*collection->elements));
7464 collection->count--;
7466 return S_OK;
7469 static HRESULT WINAPI collection_InsertElementAt(IMFCollection *iface, DWORD idx, IUnknown *element)
7471 struct collection *collection = impl_from_IMFCollection(iface);
7472 size_t i;
7474 TRACE("%p, %u, %p.\n", iface, idx, element);
7476 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, idx + 1,
7477 sizeof(*collection->elements)))
7478 return E_OUTOFMEMORY;
7480 if (idx < collection->count)
7482 memmove(&collection->elements[idx + 1], &collection->elements[idx],
7483 (collection->count - idx) * sizeof(*collection->elements));
7484 collection->count++;
7486 else
7488 for (i = collection->count; i < idx; ++i)
7489 collection->elements[i] = NULL;
7490 collection->count = idx + 1;
7493 collection->elements[idx] = element;
7494 if (collection->elements[idx])
7495 IUnknown_AddRef(collection->elements[idx]);
7497 return S_OK;
7500 static HRESULT WINAPI collection_RemoveAllElements(IMFCollection *iface)
7502 struct collection *collection = impl_from_IMFCollection(iface);
7504 TRACE("%p.\n", iface);
7506 collection_clear(collection);
7508 return S_OK;
7511 static const IMFCollectionVtbl mfcollectionvtbl =
7513 collection_QueryInterface,
7514 collection_AddRef,
7515 collection_Release,
7516 collection_GetElementCount,
7517 collection_GetElement,
7518 collection_AddElement,
7519 collection_RemoveElement,
7520 collection_InsertElementAt,
7521 collection_RemoveAllElements,
7524 /***********************************************************************
7525 * MFCreateCollection (mfplat.@)
7527 HRESULT WINAPI MFCreateCollection(IMFCollection **collection)
7529 struct collection *object;
7531 TRACE("%p\n", collection);
7533 if (!collection)
7534 return E_POINTER;
7536 object = heap_alloc_zero(sizeof(*object));
7537 if (!object)
7538 return E_OUTOFMEMORY;
7540 object->IMFCollection_iface.lpVtbl = &mfcollectionvtbl;
7541 object->refcount = 1;
7543 *collection = &object->IMFCollection_iface;
7545 return S_OK;
7548 /***********************************************************************
7549 * MFHeapAlloc (mfplat.@)
7551 void *WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type)
7553 TRACE("%lu, %#x, %s, %d, %#x.\n", size, flags, debugstr_a(file), line, type);
7554 return HeapAlloc(GetProcessHeap(), flags, size);
7557 /***********************************************************************
7558 * MFHeapFree (mfplat.@)
7560 void WINAPI MFHeapFree(void *p)
7562 TRACE("%p\n", p);
7563 HeapFree(GetProcessHeap(), 0, p);
7566 /***********************************************************************
7567 * MFCreateMFByteStreamOnStreamEx (mfplat.@)
7569 HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream **bytestream)
7571 FIXME("(%p, %p): stub\n", stream, bytestream);
7573 return E_NOTIMPL;
7576 static HRESULT WINAPI system_clock_QueryInterface(IMFClock *iface, REFIID riid, void **obj)
7578 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7580 if (IsEqualIID(riid, &IID_IMFClock) ||
7581 IsEqualIID(riid, &IID_IUnknown))
7583 *obj = iface;
7584 IMFClock_AddRef(iface);
7585 return S_OK;
7588 WARN("Unsupported %s.\n", debugstr_guid(riid));
7589 *obj = NULL;
7590 return E_NOINTERFACE;
7593 static ULONG WINAPI system_clock_AddRef(IMFClock *iface)
7595 struct system_clock *clock = impl_from_IMFClock(iface);
7596 ULONG refcount = InterlockedIncrement(&clock->refcount);
7598 TRACE("%p, refcount %u.\n", iface, refcount);
7600 return refcount;
7603 static ULONG WINAPI system_clock_Release(IMFClock *iface)
7605 struct system_clock *clock = impl_from_IMFClock(iface);
7606 ULONG refcount = InterlockedDecrement(&clock->refcount);
7608 TRACE("%p, refcount %u.\n", iface, refcount);
7610 if (!refcount)
7611 heap_free(clock);
7613 return refcount;
7616 static HRESULT WINAPI system_clock_GetClockCharacteristics(IMFClock *iface, DWORD *flags)
7618 TRACE("%p, %p.\n", iface, flags);
7620 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING |
7621 MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7623 return S_OK;
7626 static HRESULT WINAPI system_clock_GetCorrelatedTime(IMFClock *iface, DWORD reserved, LONGLONG *clock_time,
7627 MFTIME *system_time)
7629 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7631 *clock_time = *system_time = MFGetSystemTime();
7633 return S_OK;
7636 static HRESULT WINAPI system_clock_GetContinuityKey(IMFClock *iface, DWORD *key)
7638 TRACE("%p, %p.\n", iface, key);
7640 *key = 0;
7642 return S_OK;
7645 static HRESULT WINAPI system_clock_GetState(IMFClock *iface, DWORD reserved, MFCLOCK_STATE *state)
7647 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7649 *state = MFCLOCK_STATE_RUNNING;
7651 return S_OK;
7654 static HRESULT WINAPI system_clock_GetProperties(IMFClock *iface, MFCLOCK_PROPERTIES *props)
7656 TRACE("%p, %p.\n", iface, props);
7658 if (!props)
7659 return E_POINTER;
7661 memset(props, 0, sizeof(*props));
7662 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7663 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7664 props->dwClockJitter = 1;
7666 return S_OK;
7669 static const IMFClockVtbl system_clock_vtbl =
7671 system_clock_QueryInterface,
7672 system_clock_AddRef,
7673 system_clock_Release,
7674 system_clock_GetClockCharacteristics,
7675 system_clock_GetCorrelatedTime,
7676 system_clock_GetContinuityKey,
7677 system_clock_GetState,
7678 system_clock_GetProperties,
7681 static HRESULT create_system_clock(IMFClock **clock)
7683 struct system_clock *object;
7685 if (!(object = heap_alloc(sizeof(*object))))
7686 return E_OUTOFMEMORY;
7688 object->IMFClock_iface.lpVtbl = &system_clock_vtbl;
7689 object->refcount = 1;
7691 *clock = &object->IMFClock_iface;
7693 return S_OK;
7696 static HRESULT WINAPI system_time_source_QueryInterface(IMFPresentationTimeSource *iface, REFIID riid, void **obj)
7698 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7700 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7702 if (IsEqualIID(riid, &IID_IMFPresentationTimeSource) ||
7703 IsEqualIID(riid, &IID_IUnknown))
7705 *obj = &source->IMFPresentationTimeSource_iface;
7707 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
7709 *obj = &source->IMFClockStateSink_iface;
7711 else
7713 WARN("Unsupported %s.\n", debugstr_guid(riid));
7714 *obj = NULL;
7715 return E_NOINTERFACE;
7718 IUnknown_AddRef((IUnknown *)*obj);
7719 return S_OK;
7722 static ULONG WINAPI system_time_source_AddRef(IMFPresentationTimeSource *iface)
7724 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7725 ULONG refcount = InterlockedIncrement(&source->refcount);
7727 TRACE("%p, refcount %u.\n", iface, refcount);
7729 return refcount;
7732 static ULONG WINAPI system_time_source_Release(IMFPresentationTimeSource *iface)
7734 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7735 ULONG refcount = InterlockedDecrement(&source->refcount);
7737 TRACE("%p, refcount %u.\n", iface, refcount);
7739 if (!refcount)
7741 if (source->clock)
7742 IMFClock_Release(source->clock);
7743 DeleteCriticalSection(&source->cs);
7744 heap_free(source);
7747 return refcount;
7750 static HRESULT WINAPI system_time_source_GetClockCharacteristics(IMFPresentationTimeSource *iface, DWORD *flags)
7752 TRACE("%p, %p.\n", iface, flags);
7754 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7756 return S_OK;
7759 static HRESULT WINAPI system_time_source_GetCorrelatedTime(IMFPresentationTimeSource *iface, DWORD reserved,
7760 LONGLONG *clock_time, MFTIME *system_time)
7762 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7763 HRESULT hr;
7765 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7767 EnterCriticalSection(&source->cs);
7768 if (SUCCEEDED(hr = IMFClock_GetCorrelatedTime(source->clock, 0, clock_time, system_time)))
7770 if (source->state == MFCLOCK_STATE_RUNNING)
7772 system_time_source_apply_rate(source, clock_time);
7773 *clock_time += source->start_offset;
7775 else
7776 *clock_time = source->start_offset;
7778 LeaveCriticalSection(&source->cs);
7780 return hr;
7783 static HRESULT WINAPI system_time_source_GetContinuityKey(IMFPresentationTimeSource *iface, DWORD *key)
7785 TRACE("%p, %p.\n", iface, key);
7787 *key = 0;
7789 return S_OK;
7792 static HRESULT WINAPI system_time_source_GetState(IMFPresentationTimeSource *iface, DWORD reserved,
7793 MFCLOCK_STATE *state)
7795 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7797 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7799 EnterCriticalSection(&source->cs);
7800 *state = source->state;
7801 LeaveCriticalSection(&source->cs);
7803 return S_OK;
7806 static HRESULT WINAPI system_time_source_GetProperties(IMFPresentationTimeSource *iface, MFCLOCK_PROPERTIES *props)
7808 TRACE("%p, %p.\n", iface, props);
7810 if (!props)
7811 return E_POINTER;
7813 memset(props, 0, sizeof(*props));
7814 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7815 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7816 props->dwClockJitter = 1;
7818 return S_OK;
7821 static HRESULT WINAPI system_time_source_GetUnderlyingClock(IMFPresentationTimeSource *iface, IMFClock **clock)
7823 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7825 TRACE("%p, %p.\n", iface, clock);
7827 *clock = source->clock;
7828 IMFClock_AddRef(*clock);
7830 return S_OK;
7833 static const IMFPresentationTimeSourceVtbl systemtimesourcevtbl =
7835 system_time_source_QueryInterface,
7836 system_time_source_AddRef,
7837 system_time_source_Release,
7838 system_time_source_GetClockCharacteristics,
7839 system_time_source_GetCorrelatedTime,
7840 system_time_source_GetContinuityKey,
7841 system_time_source_GetState,
7842 system_time_source_GetProperties,
7843 system_time_source_GetUnderlyingClock,
7846 static HRESULT WINAPI system_time_source_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **out)
7848 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7849 return IMFPresentationTimeSource_QueryInterface(&source->IMFPresentationTimeSource_iface, riid, out);
7852 static ULONG WINAPI system_time_source_sink_AddRef(IMFClockStateSink *iface)
7854 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7855 return IMFPresentationTimeSource_AddRef(&source->IMFPresentationTimeSource_iface);
7858 static ULONG WINAPI system_time_source_sink_Release(IMFClockStateSink *iface)
7860 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7861 return IMFPresentationTimeSource_Release(&source->IMFPresentationTimeSource_iface);
7864 enum clock_command
7866 CLOCK_CMD_START = 0,
7867 CLOCK_CMD_STOP,
7868 CLOCK_CMD_PAUSE,
7869 CLOCK_CMD_RESTART,
7870 CLOCK_CMD_MAX,
7873 static HRESULT system_time_source_change_state(struct system_time_source *source, enum clock_command command)
7875 static const BYTE state_change_is_allowed[MFCLOCK_STATE_PAUSED+1][CLOCK_CMD_MAX] =
7876 { /* S S* P R */
7877 /* INVALID */ { 1, 0, 1, 0 },
7878 /* RUNNING */ { 1, 1, 1, 0 },
7879 /* STOPPED */ { 1, 1, 0, 0 },
7880 /* PAUSED */ { 1, 1, 0, 1 },
7882 static const MFCLOCK_STATE states[CLOCK_CMD_MAX] =
7884 /* CLOCK_CMD_START */ MFCLOCK_STATE_RUNNING,
7885 /* CLOCK_CMD_STOP */ MFCLOCK_STATE_STOPPED,
7886 /* CLOCK_CMD_PAUSE */ MFCLOCK_STATE_PAUSED,
7887 /* CLOCK_CMD_RESTART */ MFCLOCK_STATE_RUNNING,
7890 /* Special case that go against usual state change vs return value behavior. */
7891 if (source->state == MFCLOCK_STATE_INVALID && command == CLOCK_CMD_STOP)
7892 return S_OK;
7894 if (!state_change_is_allowed[source->state][command])
7895 return MF_E_INVALIDREQUEST;
7897 source->state = states[command];
7899 return S_OK;
7902 static HRESULT WINAPI system_time_source_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time,
7903 LONGLONG start_offset)
7905 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7906 MFCLOCK_STATE state;
7907 HRESULT hr;
7909 TRACE("%p, %s, %s.\n", iface, debugstr_time(system_time), debugstr_time(start_offset));
7911 EnterCriticalSection(&source->cs);
7912 state = source->state;
7913 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_START)))
7915 system_time_source_apply_rate(source, &system_time);
7916 if (start_offset == PRESENTATION_CURRENT_POSITION)
7918 switch (state)
7920 case MFCLOCK_STATE_RUNNING:
7921 break;
7922 case MFCLOCK_STATE_PAUSED:
7923 source->start_offset -= system_time;
7924 break;
7925 default:
7926 source->start_offset = -system_time;
7927 break;
7931 else
7933 source->start_offset = -system_time + start_offset;
7936 LeaveCriticalSection(&source->cs);
7938 return hr;
7941 static HRESULT WINAPI system_time_source_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
7943 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7944 HRESULT hr;
7946 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7948 EnterCriticalSection(&source->cs);
7949 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_STOP)))
7950 source->start_offset = 0;
7951 LeaveCriticalSection(&source->cs);
7953 return hr;
7956 static HRESULT WINAPI system_time_source_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
7958 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7959 HRESULT hr;
7961 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7963 EnterCriticalSection(&source->cs);
7964 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_PAUSE)))
7966 system_time_source_apply_rate(source, &system_time);
7967 source->start_offset += system_time;
7969 LeaveCriticalSection(&source->cs);
7971 return hr;
7974 static HRESULT WINAPI system_time_source_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
7976 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7977 HRESULT hr;
7979 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7981 EnterCriticalSection(&source->cs);
7982 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_RESTART)))
7984 system_time_source_apply_rate(source, &system_time);
7985 source->start_offset -= system_time;
7987 LeaveCriticalSection(&source->cs);
7989 return hr;
7992 static HRESULT WINAPI system_time_source_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
7994 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7995 double intpart;
7997 TRACE("%p, %s, %f.\n", iface, debugstr_time(system_time), rate);
7999 if (rate == 0.0f)
8000 return MF_E_UNSUPPORTED_RATE;
8002 modf(rate, &intpart);
8004 EnterCriticalSection(&source->cs);
8005 source->rate = rate;
8006 source->i_rate = rate == intpart ? rate : 0;
8007 LeaveCriticalSection(&source->cs);
8009 return S_OK;
8012 static const IMFClockStateSinkVtbl systemtimesourcesinkvtbl =
8014 system_time_source_sink_QueryInterface,
8015 system_time_source_sink_AddRef,
8016 system_time_source_sink_Release,
8017 system_time_source_sink_OnClockStart,
8018 system_time_source_sink_OnClockStop,
8019 system_time_source_sink_OnClockPause,
8020 system_time_source_sink_OnClockRestart,
8021 system_time_source_sink_OnClockSetRate,
8024 /***********************************************************************
8025 * MFCreateSystemTimeSource (mfplat.@)
8027 HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source)
8029 struct system_time_source *object;
8030 HRESULT hr;
8032 TRACE("%p.\n", time_source);
8034 object = heap_alloc_zero(sizeof(*object));
8035 if (!object)
8036 return E_OUTOFMEMORY;
8038 object->IMFPresentationTimeSource_iface.lpVtbl = &systemtimesourcevtbl;
8039 object->IMFClockStateSink_iface.lpVtbl = &systemtimesourcesinkvtbl;
8040 object->refcount = 1;
8041 object->rate = 1.0f;
8042 object->i_rate = 1;
8043 InitializeCriticalSection(&object->cs);
8045 if (FAILED(hr = create_system_clock(&object->clock)))
8047 IMFPresentationTimeSource_Release(&object->IMFPresentationTimeSource_iface);
8048 return hr;
8051 *time_source = &object->IMFPresentationTimeSource_iface;
8053 return S_OK;
8056 struct async_create_file
8058 IRtwqAsyncCallback IRtwqAsyncCallback_iface;
8059 LONG refcount;
8060 MF_FILE_ACCESSMODE access_mode;
8061 MF_FILE_OPENMODE open_mode;
8062 MF_FILE_FLAGS flags;
8063 WCHAR *path;
8066 struct async_create_file_result
8068 struct list entry;
8069 IRtwqAsyncResult *result;
8070 IMFByteStream *stream;
8073 static struct list async_create_file_results = LIST_INIT(async_create_file_results);
8074 static CRITICAL_SECTION async_create_file_cs = { NULL, -1, 0, 0, 0, 0 };
8076 static struct async_create_file *impl_from_create_file_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
8078 return CONTAINING_RECORD(iface, struct async_create_file, IRtwqAsyncCallback_iface);
8081 static HRESULT WINAPI async_create_file_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
8083 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
8084 IsEqualIID(riid, &IID_IUnknown))
8086 *obj = iface;
8087 IRtwqAsyncCallback_AddRef(iface);
8088 return S_OK;
8091 *obj = NULL;
8092 return E_NOINTERFACE;
8095 static ULONG WINAPI async_create_file_callback_AddRef(IRtwqAsyncCallback *iface)
8097 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8098 ULONG refcount = InterlockedIncrement(&async->refcount);
8100 TRACE("%p, refcount %u.\n", iface, refcount);
8102 return refcount;
8105 static ULONG WINAPI async_create_file_callback_Release(IRtwqAsyncCallback *iface)
8107 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8108 ULONG refcount = InterlockedDecrement(&async->refcount);
8110 TRACE("%p, refcount %u.\n", iface, refcount);
8112 if (!refcount)
8114 heap_free(async->path);
8115 heap_free(async);
8118 return refcount;
8121 static HRESULT WINAPI async_create_file_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
8123 return E_NOTIMPL;
8126 static HRESULT WINAPI async_create_file_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
8128 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8129 IRtwqAsyncResult *caller;
8130 IMFByteStream *stream;
8131 HRESULT hr;
8133 caller = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
8135 hr = MFCreateFile(async->access_mode, async->open_mode, async->flags, async->path, &stream);
8136 if (SUCCEEDED(hr))
8138 struct async_create_file_result *result_item;
8140 result_item = heap_alloc(sizeof(*result_item));
8141 if (result_item)
8143 result_item->result = caller;
8144 IRtwqAsyncResult_AddRef(caller);
8145 result_item->stream = stream;
8146 IMFByteStream_AddRef(stream);
8148 EnterCriticalSection(&async_create_file_cs);
8149 list_add_tail(&async_create_file_results, &result_item->entry);
8150 LeaveCriticalSection(&async_create_file_cs);
8153 IMFByteStream_Release(stream);
8155 else
8156 IRtwqAsyncResult_SetStatus(caller, hr);
8158 RtwqInvokeCallback(caller);
8160 return S_OK;
8163 static const IRtwqAsyncCallbackVtbl async_create_file_callback_vtbl =
8165 async_create_file_callback_QueryInterface,
8166 async_create_file_callback_AddRef,
8167 async_create_file_callback_Release,
8168 async_create_file_callback_GetParameters,
8169 async_create_file_callback_Invoke,
8172 /***********************************************************************
8173 * MFBeginCreateFile (mfplat.@)
8175 HRESULT WINAPI MFBeginCreateFile(MF_FILE_ACCESSMODE access_mode, MF_FILE_OPENMODE open_mode, MF_FILE_FLAGS flags,
8176 const WCHAR *path, IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_cookie)
8178 struct async_create_file *async = NULL;
8179 IRtwqAsyncResult *caller, *item = NULL;
8180 HRESULT hr;
8182 TRACE("%#x, %#x, %#x, %s, %p, %p, %p.\n", access_mode, open_mode, flags, debugstr_w(path), callback, state,
8183 cancel_cookie);
8185 if (cancel_cookie)
8186 *cancel_cookie = NULL;
8188 if (FAILED(hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &caller)))
8189 return hr;
8191 async = heap_alloc(sizeof(*async));
8192 if (!async)
8194 hr = E_OUTOFMEMORY;
8195 goto failed;
8198 async->IRtwqAsyncCallback_iface.lpVtbl = &async_create_file_callback_vtbl;
8199 async->refcount = 1;
8200 async->access_mode = access_mode;
8201 async->open_mode = open_mode;
8202 async->flags = flags;
8203 if (FAILED(hr = heap_strdupW(path, &async->path)))
8204 goto failed;
8206 hr = RtwqCreateAsyncResult(NULL, &async->IRtwqAsyncCallback_iface, (IUnknown *)caller, &item);
8207 if (FAILED(hr))
8208 goto failed;
8210 if (cancel_cookie)
8212 *cancel_cookie = (IUnknown *)caller;
8213 IUnknown_AddRef(*cancel_cookie);
8216 hr = RtwqInvokeCallback(item);
8218 failed:
8219 if (async)
8220 IRtwqAsyncCallback_Release(&async->IRtwqAsyncCallback_iface);
8221 if (item)
8222 IRtwqAsyncResult_Release(item);
8223 if (caller)
8224 IRtwqAsyncResult_Release(caller);
8226 return hr;
8229 static HRESULT async_create_file_pull_result(IUnknown *unk, IMFByteStream **stream)
8231 struct async_create_file_result *item;
8232 HRESULT hr = MF_E_UNEXPECTED;
8233 IRtwqAsyncResult *result;
8235 *stream = NULL;
8237 if (FAILED(IUnknown_QueryInterface(unk, &IID_IRtwqAsyncResult, (void **)&result)))
8238 return hr;
8240 EnterCriticalSection(&async_create_file_cs);
8242 LIST_FOR_EACH_ENTRY(item, &async_create_file_results, struct async_create_file_result, entry)
8244 if (result == item->result)
8246 *stream = item->stream;
8247 IRtwqAsyncResult_Release(item->result);
8248 list_remove(&item->entry);
8249 heap_free(item);
8250 break;
8254 LeaveCriticalSection(&async_create_file_cs);
8256 if (*stream)
8257 hr = IRtwqAsyncResult_GetStatus(result);
8259 IRtwqAsyncResult_Release(result);
8261 return hr;
8264 /***********************************************************************
8265 * MFEndCreateFile (mfplat.@)
8267 HRESULT WINAPI MFEndCreateFile(IMFAsyncResult *result, IMFByteStream **stream)
8269 TRACE("%p, %p.\n", result, stream);
8271 return async_create_file_pull_result((IUnknown *)result, stream);
8274 /***********************************************************************
8275 * MFCancelCreateFile (mfplat.@)
8277 HRESULT WINAPI MFCancelCreateFile(IUnknown *cancel_cookie)
8279 IMFByteStream *stream = NULL;
8280 HRESULT hr;
8282 TRACE("%p.\n", cancel_cookie);
8284 hr = async_create_file_pull_result(cancel_cookie, &stream);
8286 if (stream)
8287 IMFByteStream_Release(stream);
8289 return hr;
8292 /***********************************************************************
8293 * MFRegisterLocalSchemeHandler (mfplat.@)
8295 HRESULT WINAPI MFRegisterLocalSchemeHandler(const WCHAR *scheme, IMFActivate *activate)
8297 struct local_handler *handler;
8298 HRESULT hr;
8300 TRACE("%s, %p.\n", debugstr_w(scheme), activate);
8302 if (!scheme || !activate)
8303 return E_INVALIDARG;
8305 if (!(handler = heap_alloc(sizeof(*handler))))
8306 return E_OUTOFMEMORY;
8308 if (FAILED(hr = heap_strdupW(scheme, &handler->u.scheme)))
8310 heap_free(handler);
8311 return hr;
8313 handler->activate = activate;
8314 IMFActivate_AddRef(handler->activate);
8316 EnterCriticalSection(&local_handlers_section);
8317 list_add_head(&local_scheme_handlers, &handler->entry);
8318 LeaveCriticalSection(&local_handlers_section);
8320 return S_OK;
8323 /***********************************************************************
8324 * MFRegisterLocalByteStreamHandler (mfplat.@)
8326 HRESULT WINAPI MFRegisterLocalByteStreamHandler(const WCHAR *extension, const WCHAR *mime, IMFActivate *activate)
8328 struct local_handler *handler;
8329 HRESULT hr;
8331 TRACE("%s, %s, %p.\n", debugstr_w(extension), debugstr_w(mime), activate);
8333 if ((!extension && !mime) || !activate)
8334 return E_INVALIDARG;
8336 if (!(handler = heap_alloc_zero(sizeof(*handler))))
8337 return E_OUTOFMEMORY;
8339 hr = heap_strdupW(extension, &handler->u.bytestream.extension);
8340 if (SUCCEEDED(hr))
8341 hr = heap_strdupW(mime, &handler->u.bytestream.mime);
8343 if (FAILED(hr))
8344 goto failed;
8346 EnterCriticalSection(&local_handlers_section);
8347 list_add_head(&local_bytestream_handlers, &handler->entry);
8348 LeaveCriticalSection(&local_handlers_section);
8350 return hr;
8352 failed:
8353 heap_free(handler->u.bytestream.extension);
8354 heap_free(handler->u.bytestream.mime);
8355 heap_free(handler);
8357 return hr;
8360 struct property_store
8362 IPropertyStore IPropertyStore_iface;
8363 LONG refcount;
8364 CRITICAL_SECTION cs;
8365 size_t count, capacity;
8366 struct
8368 PROPERTYKEY key;
8369 PROPVARIANT value;
8370 } *values;
8373 static struct property_store *impl_from_IPropertyStore(IPropertyStore *iface)
8375 return CONTAINING_RECORD(iface, struct property_store, IPropertyStore_iface);
8378 static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
8380 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8382 if (IsEqualIID(riid, &IID_IPropertyStore) || IsEqualIID(riid, &IID_IUnknown))
8384 *obj = iface;
8385 IPropertyStore_AddRef(iface);
8386 return S_OK;
8389 *obj = NULL;
8390 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
8391 return E_NOINTERFACE;
8394 static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
8396 struct property_store *store = impl_from_IPropertyStore(iface);
8397 ULONG refcount = InterlockedIncrement(&store->refcount);
8399 TRACE("%p, refcount %d.\n", iface, refcount);
8401 return refcount;
8404 static ULONG WINAPI property_store_Release(IPropertyStore *iface)
8406 struct property_store *store = impl_from_IPropertyStore(iface);
8407 ULONG refcount = InterlockedDecrement(&store->refcount);
8409 TRACE("%p, refcount %d.\n", iface, refcount);
8411 if (!refcount)
8413 DeleteCriticalSection(&store->cs);
8414 heap_free(store->values);
8415 heap_free(store);
8418 return refcount;
8421 static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
8423 struct property_store *store = impl_from_IPropertyStore(iface);
8425 TRACE("%p, %p.\n", iface, count);
8427 if (!count)
8428 return E_INVALIDARG;
8430 EnterCriticalSection(&store->cs);
8431 *count = store->count;
8432 LeaveCriticalSection(&store->cs);
8433 return S_OK;
8436 static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
8438 struct property_store *store = impl_from_IPropertyStore(iface);
8440 TRACE("%p, %u, %p.\n", iface, index, key);
8442 EnterCriticalSection(&store->cs);
8444 if (index >= store->count)
8446 LeaveCriticalSection(&store->cs);
8447 return E_INVALIDARG;
8450 *key = store->values[index].key;
8452 LeaveCriticalSection(&store->cs);
8453 return S_OK;
8456 static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
8458 struct property_store *store = impl_from_IPropertyStore(iface);
8459 unsigned int i;
8461 TRACE("%p, %p, %p.\n", iface, key, value);
8463 if (!value)
8464 return E_INVALIDARG;
8466 if (!key)
8467 return S_FALSE;
8469 EnterCriticalSection(&store->cs);
8471 for (i = 0; i < store->count; ++i)
8473 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8475 PropVariantCopy(value, &store->values[i].value);
8476 LeaveCriticalSection(&store->cs);
8477 return S_OK;
8481 LeaveCriticalSection(&store->cs);
8482 return S_FALSE;
8485 static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
8487 struct property_store *store = impl_from_IPropertyStore(iface);
8488 unsigned int i;
8490 TRACE("%p, %p, %p.\n", iface, key, value);
8492 EnterCriticalSection(&store->cs);
8494 for (i = 0; i < store->count; ++i)
8496 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8498 PropVariantCopy(&store->values[i].value, value);
8499 LeaveCriticalSection(&store->cs);
8500 return S_OK;
8504 if (!mf_array_reserve((void **)&store->values, &store->capacity, store->count + 1, sizeof(*store->values)))
8506 LeaveCriticalSection(&store->cs);
8507 return E_OUTOFMEMORY;
8510 store->values[store->count].key = *key;
8511 PropVariantCopy(&store->values[store->count].value, value);
8512 ++store->count;
8514 LeaveCriticalSection(&store->cs);
8515 return S_OK;
8518 static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
8520 TRACE("%p.\n", iface);
8522 return E_NOTIMPL;
8525 static const IPropertyStoreVtbl property_store_vtbl =
8527 property_store_QueryInterface,
8528 property_store_AddRef,
8529 property_store_Release,
8530 property_store_GetCount,
8531 property_store_GetAt,
8532 property_store_GetValue,
8533 property_store_SetValue,
8534 property_store_Commit,
8537 /***********************************************************************
8538 * CreatePropertyStore (mfplat.@)
8540 HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
8542 struct property_store *object;
8544 TRACE("%p.\n", store);
8546 if (!store)
8547 return E_INVALIDARG;
8549 if (!(object = heap_alloc_zero(sizeof(*object))))
8550 return E_OUTOFMEMORY;
8552 object->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
8553 object->refcount = 1;
8554 InitializeCriticalSection(&object->cs);
8556 TRACE("Created store %p.\n", object);
8557 *store = &object->IPropertyStore_iface;
8559 return S_OK;
8562 enum dxgi_device_handle_flags
8564 DXGI_DEVICE_HANDLE_FLAG_OPEN = 0x1,
8565 DXGI_DEVICE_HANDLE_FLAG_INVALID = 0x2,
8566 DXGI_DEVICE_HANDLE_FLAG_LOCKED = 0x4,
8569 struct dxgi_device_manager
8571 IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
8572 LONG refcount;
8573 UINT token;
8574 IDXGIDevice *device;
8576 unsigned int *handles;
8577 size_t count;
8578 size_t capacity;
8580 unsigned int locks;
8581 unsigned int locking_tid;
8583 CRITICAL_SECTION cs;
8584 CONDITION_VARIABLE lock;
8587 static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
8589 return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface);
8592 static HRESULT dxgi_device_manager_get_handle_index(struct dxgi_device_manager *manager, HANDLE hdevice, size_t *idx)
8594 if (!hdevice || hdevice > ULongToHandle(manager->count))
8595 return E_HANDLE;
8596 *idx = (ULONG_PTR)hdevice - 1;
8597 return S_OK;
8600 static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj)
8602 TRACE("(%p, %s, %p).\n", iface, debugstr_guid(riid), obj);
8604 if (IsEqualIID(riid, &IID_IMFDXGIDeviceManager) ||
8605 IsEqualGUID(riid, &IID_IUnknown))
8607 *obj = iface;
8608 IMFDXGIDeviceManager_AddRef(iface);
8609 return S_OK;
8612 WARN("Unsupported %s.\n", debugstr_guid(riid));
8613 *obj = NULL;
8614 return E_NOINTERFACE;
8617 static ULONG WINAPI dxgi_device_manager_AddRef(IMFDXGIDeviceManager *iface)
8619 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8620 ULONG refcount = InterlockedIncrement(&manager->refcount);
8622 TRACE("(%p) ref=%u.\n", iface, refcount);
8624 return refcount;
8627 static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
8629 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8630 ULONG refcount = InterlockedDecrement(&manager->refcount);
8632 TRACE("(%p) ref=%u.\n", iface, refcount);
8634 if (!refcount)
8636 if (manager->device)
8637 IDXGIDevice_Release(manager->device);
8638 DeleteCriticalSection(&manager->cs);
8639 heap_free(manager->handles);
8640 heap_free(manager);
8643 return refcount;
8646 static void dxgi_device_manager_lock_handle(struct dxgi_device_manager *manager, size_t idx)
8648 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED)
8649 return;
8651 manager->handles[idx] |= DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8652 manager->locks++;
8655 static void dxgi_device_manager_unlock_handle(struct dxgi_device_manager *manager, size_t idx)
8657 if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED))
8658 return;
8660 manager->handles[idx] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8661 if (!--manager->locks)
8662 manager->locking_tid = 0;
8665 static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8667 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8668 HRESULT hr;
8669 size_t idx;
8671 TRACE("%p, %p.\n", iface, hdevice);
8673 EnterCriticalSection(&manager->cs);
8675 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8677 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8679 dxgi_device_manager_unlock_handle(manager, idx);
8680 manager->handles[idx] = 0;
8681 if (idx == manager->count - 1)
8682 manager->count--;
8684 else
8685 hr = E_HANDLE;
8688 LeaveCriticalSection(&manager->cs);
8690 WakeAllConditionVariable(&manager->lock);
8692 return hr;
8695 static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8696 REFIID riid, void **service)
8698 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8699 HRESULT hr;
8700 size_t idx;
8702 TRACE("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), service);
8704 EnterCriticalSection(&manager->cs);
8706 if (!manager->device)
8707 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8708 else if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8710 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8711 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8712 else if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8713 hr = IDXGIDevice_QueryInterface(manager->device, riid, service);
8714 else
8715 hr = E_HANDLE;
8718 LeaveCriticalSection(&manager->cs);
8720 return hr;
8723 static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8724 REFIID riid, void **obj, BOOL block)
8726 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8727 HRESULT hr;
8728 size_t idx;
8730 TRACE("%p, %p, %s, %p, %d.\n", iface, hdevice, wine_dbgstr_guid(riid), obj, block);
8732 EnterCriticalSection(&manager->cs);
8734 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8736 if (!manager->device)
8738 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8740 else if (manager->locking_tid == GetCurrentThreadId())
8742 if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
8743 dxgi_device_manager_lock_handle(manager, idx);
8745 else if (manager->locking_tid && !block)
8747 hr = MF_E_DXGI_VIDEO_DEVICE_LOCKED;
8749 else
8751 while (manager->locking_tid)
8753 SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE);
8756 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8758 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8759 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8760 else if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
8762 manager->locking_tid = GetCurrentThreadId();
8763 dxgi_device_manager_lock_handle(manager, idx);
8769 LeaveCriticalSection(&manager->cs);
8771 return hr;
8774 static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *hdevice)
8776 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8777 HRESULT hr = S_OK;
8778 size_t i;
8780 TRACE("%p, %p.\n", iface, hdevice);
8782 *hdevice = NULL;
8784 EnterCriticalSection(&manager->cs);
8786 if (!manager->device)
8787 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8788 else
8790 for (i = 0; i < manager->count; ++i)
8792 if (!(manager->handles[i] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
8794 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_OPEN;
8795 *hdevice = ULongToHandle(i + 1);
8796 break;
8800 if (mf_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1,
8801 sizeof(*manager->handles)))
8803 *hdevice = ULongToHandle(manager->count + 1);
8804 manager->handles[manager->count++] = DXGI_DEVICE_HANDLE_FLAG_OPEN;
8806 else
8807 hr = E_OUTOFMEMORY;
8810 LeaveCriticalSection(&manager->cs);
8812 return hr;
8815 static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
8817 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8818 IDXGIDevice *dxgi_device;
8819 size_t i;
8821 TRACE("%p, %p, %u.\n", iface, device, token);
8823 if (!device || token != manager->token)
8824 return E_INVALIDARG;
8826 if (FAILED(IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device)))
8827 return E_INVALIDARG;
8829 EnterCriticalSection(&manager->cs);
8831 if (manager->device)
8833 for (i = 0; i < manager->count; ++i)
8835 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_INVALID;
8836 manager->handles[i] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8838 manager->locking_tid = 0;
8839 manager->locks = 0;
8840 IDXGIDevice_Release(manager->device);
8842 manager->device = dxgi_device;
8844 LeaveCriticalSection(&manager->cs);
8846 WakeAllConditionVariable(&manager->lock);
8848 return S_OK;
8851 static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8853 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8854 HRESULT hr;
8855 size_t idx;
8857 TRACE("%p, %p.\n", iface, hdevice);
8859 EnterCriticalSection(&manager->cs);
8861 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8863 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8864 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8865 else if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
8866 hr = E_HANDLE;
8869 LeaveCriticalSection(&manager->cs);
8871 return hr;
8874 static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8875 BOOL savestate)
8877 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8878 HRESULT hr = E_FAIL;
8879 size_t idx;
8881 TRACE("%p, %p, %d.\n", iface, hdevice, savestate);
8883 EnterCriticalSection(&manager->cs);
8885 if (SUCCEEDED(dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8887 hr = manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED ? S_OK : E_INVALIDARG;
8888 if (SUCCEEDED(hr))
8889 dxgi_device_manager_unlock_handle(manager, idx);
8892 LeaveCriticalSection(&manager->cs);
8894 WakeAllConditionVariable(&manager->lock);
8896 return hr;
8899 static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
8901 dxgi_device_manager_QueryInterface,
8902 dxgi_device_manager_AddRef,
8903 dxgi_device_manager_Release,
8904 dxgi_device_manager_CloseDeviceHandle,
8905 dxgi_device_manager_GetVideoService,
8906 dxgi_device_manager_LockDevice,
8907 dxgi_device_manager_OpenDeviceHandle,
8908 dxgi_device_manager_ResetDevice,
8909 dxgi_device_manager_TestDevice,
8910 dxgi_device_manager_UnlockDevice,
8913 HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
8915 struct dxgi_device_manager *object;
8917 TRACE("%p, %p.\n", token, manager);
8919 if (!token || !manager)
8920 return E_POINTER;
8922 if (!(object = heap_alloc_zero(sizeof(*object))))
8923 return E_OUTOFMEMORY;
8925 object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
8926 object->refcount = 1;
8927 object->token = GetTickCount();
8928 InitializeCriticalSection(&object->cs);
8929 InitializeConditionVariable(&object->lock);
8931 TRACE("Created device manager: %p, token: %u.\n", object, object->token);
8933 *token = object->token;
8934 *manager = &object->IMFDXGIDeviceManager_iface;
8936 return S_OK;