Reactos
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
4 * FILE: dll/directx/ksproxy/ksproxy.cpp
5 * PURPOSE: ActiveMovie Proxy functions
6 *
7 * PROGRAMMERS: Dmitry Chapyshev
8 Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11#include "precomp.h"
12
13
14const GUID CLSID_KsClockForwarder = {0x877e4351, 0x6fea, 0x11d0, {0xb8, 0x63, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}};
15const GUID CLSID_KsQualityForwarder = {0xe05592e4, 0xc0b5, 0x11d0, {0xa4, 0x39, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96}};
16const GUID CLSID_KsIBasicAudioInterfaceHandler = {0xb9f8ac3e, 0x0f71, 0x11d2, {0xb7, 0x2c, 0x00, 0xc0, 0x4f, 0xb6, 0xbd, 0x3d}};
17
18static INTERFACE_TABLE InterfaceTable[] =
19{
20 {&MEDIATYPE_Audio, CKsDataTypeHandler_Constructor},
21 {&KSINTERFACESETID_Standard, CKsInterfaceHandler_Constructor},
22 {&CLSID_KsClockForwarder, CKsClockForwarder_Constructor},
23 {&CLSID_KsQualityForwarder, CKsQualityForwarder_Constructor},
24 {&IID_IVPConfig, CVPConfig_Constructor},
25 {&IID_IVPVBIConfig, CVPVBIConfig_Constructor},
26 {&CLSID_KsIBasicAudioInterfaceHandler, CKsBasicAudio_Constructor},
27 {&CLSID_Proxy, CKsProxy_Constructor},
28 {NULL, NULL}
29};
30
31KSDDKAPI
32HRESULT
33WINAPI
34KsSynchronousDeviceControl(
35 HANDLE Handle,
36 ULONG IoControl,
37 PVOID InBuffer,
38 ULONG InLength,
39 PVOID OutBuffer,
40 ULONG OutLength,
41 PULONG BytesReturned)
42{
43 OVERLAPPED Overlapped;
44 DWORD Transferred;
45
46 /* zero overlapped */
47 RtlZeroMemory(&Overlapped, sizeof(OVERLAPPED));
48
49 /* create notification event */
50 Overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
51
52 if (!Overlapped.hEvent)
53 {
54 /* failed */
55 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
56 }
57
58 if (!DeviceIoControl(Handle, IoControl, InBuffer, InLength, OutBuffer, OutLength, BytesReturned, &Overlapped))
59 {
60 /* operation failed */
61 if (GetLastError() != ERROR_IO_PENDING)
62 {
63 /* failed */
64 CloseHandle(Overlapped.hEvent);
65 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
66 }
67 }
68
69 /* get result of pending operation */
70 if (!GetOverlappedResult(Handle, &Overlapped, &Transferred, TRUE))
71 {
72 /* failed */
73 CloseHandle(Overlapped.hEvent);
74 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
75 }
76
77 /* store number of bytes transferred */
78 *BytesReturned = Transferred;
79
80 /* close event object */
81 CloseHandle(Overlapped.hEvent);
82
83 /* done */
84 return NOERROR;
85}
86
87KSDDKAPI
88HRESULT
89WINAPI
90KsResolveRequiredAttributes(
91 PKSDATARANGE DataRange,
92 KSMULTIPLE_ITEM *Attributes OPTIONAL)
93{
94 //UNIMPLEMENTED
95 return NOERROR;
96}
97
98KSDDKAPI
99HRESULT
100WINAPI
101KsOpenDefaultDevice(
102 REFGUID Category,
103 ACCESS_MASK Access,
104 PHANDLE DeviceHandle)
105{
106 HDEVINFO hList;
107 SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
108 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData;
109 WCHAR Path[MAX_PATH+sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)];
110
111 /* open device list */
112 hList = SetupDiGetClassDevsW(&Category, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
113
114 if (hList == INVALID_HANDLE_VALUE)
115 {
116 /* failed */
117 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
118 }
119
120 /* setup parameters */
121 DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
122
123 if (SetupDiEnumDeviceInterfaces(hList, NULL, &Category, 0, &DeviceInterfaceData))
124 {
125 /* setup interface data struct */
126 DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)Path;
127 DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
128
129 /* get device interface details */
130 if (SetupDiGetDeviceInterfaceDetailW(hList, &DeviceInterfaceData, DeviceInterfaceDetailData, sizeof(Path), NULL, NULL))
131 {
132 /* open device */
133 *DeviceHandle = CreateFileW(DeviceInterfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL, NULL);
134
135 if (*DeviceHandle != INVALID_HANDLE_VALUE)
136 {
137 /* operation succeeded */
138 SetupDiDestroyDeviceInfoList(hList);
139 return NOERROR;
140 }
141 }
142 }
143
144 /* free device list */
145 SetupDiDestroyDeviceInfoList(hList);
146
147 /* failed */
148 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
149}
150
151KSDDKAPI
152HRESULT
153WINAPI
154KsGetMultiplePinFactoryItems(
155 HANDLE FilterHandle,
156 ULONG PinFactoryId,
157 ULONG PropertyId,
158 PVOID *Items)
159{
160 KSP_PIN Property;
161 ULONG BytesReturned, NumData;
162 HRESULT hResult;
163
164 /* zero pin property */
165 RtlZeroMemory(&Property, sizeof(KSP_PIN));
166 Property.Property.Set = KSPROPSETID_Pin;
167 Property.Property.Id = PropertyId;
168 Property.Property.Flags = KSPROPERTY_TYPE_GET;
169 Property.PinId = PinFactoryId;
170
171 /* query pin factory */
172 hResult = KsSynchronousDeviceControl(FilterHandle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
173
174 if (hResult == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_INSUFFICIENT_BUFFER))
175 {
176 /* buffer too small */
177 hResult = KsSynchronousDeviceControl(FilterHandle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)&NumData, sizeof(ULONG), &BytesReturned);
178
179 if (SUCCEEDED(hResult))
180 {
181 /* store required data size */
182 BytesReturned = NumData;
183 hResult = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA);
184 }
185 }
186
187 if (hResult == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
188 {
189 /* allocate data */
190 *Items = CoTaskMemAlloc(BytesReturned);
191
192 if (!*Items)
193 {
194 /* no memory */
195 return E_OUTOFMEMORY;
196 }
197
198 /* retry querying property */
199 hResult = KsSynchronousDeviceControl(FilterHandle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)*Items, BytesReturned, &BytesReturned);
200
201 /* check for success */
202 if (FAILED(hResult))
203 {
204 /* free memory */
205 CoTaskMemFree(*Items);
206 }
207 }
208
209 /* done */
210 return hResult;
211}
212
213KSDDKAPI
214HRESULT
215WINAPI
216KsGetMediaTypeCount(
217 HANDLE FilterHandle,
218 ULONG PinFactoryId,
219 ULONG *MediaTypeCount)
220{
221 PKSMULTIPLE_ITEM MultipleItem;
222 HRESULT hr;
223
224 /* try get constrained data ranges */
225 hr = KsGetMultiplePinFactoryItems(FilterHandle, PinFactoryId, KSPROPERTY_PIN_CONSTRAINEDDATARANGES, (PVOID*)&MultipleItem);
226
227 /* check for failure*/
228 if (FAILED(hr))
229 {
230 /* try getting default data ranges */
231 hr = KsGetMultiplePinFactoryItems(FilterHandle, PinFactoryId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem);
232 }
233
234 if (SUCCEEDED(hr))
235 {
236 /* store number of media types */
237 *MediaTypeCount = MultipleItem->Count;
238
239 /* free memory */
240 CoTaskMemFree(MultipleItem);
241 }
242
243 /* done */
244 return hr;
245}
246
247KSDDKAPI
248HRESULT
249WINAPI
250KsGetMediaType(
251 int Position,
252 AM_MEDIA_TYPE *AmMediaType,
253 HANDLE FilterHandle,
254 ULONG PinFactoryId)
255{
256 HRESULT hr;
257 PKSMULTIPLE_ITEM ItemList;
258 int i = 0;
259 PKSDATAFORMAT DataFormat;
260
261 if (Position < 0)
262 return E_INVALIDARG;
263
264 // get current supported ranges
265 hr = KsGetMultiplePinFactoryItems(FilterHandle, PinFactoryId, KSPROPERTY_PIN_CONSTRAINEDDATARANGES, (PVOID*)&ItemList);
266 if (FAILED(hr))
267 {
268 // get standard dataranges
269 hr = KsGetMultiplePinFactoryItems(FilterHandle, PinFactoryId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&ItemList);
270
271 //check for success
272 if (FAILED(hr))
273 return hr;
274 }
275
276 if ((ULONG)Position >= ItemList->Count)
277 {
278 // out of bounds
279 CoTaskMemFree(ItemList);
280 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NO_MORE_ITEMS);
281 }
282
283 // goto first datarange
284 DataFormat = (PKSDATAFORMAT)(ItemList + 1);
285
286 while(i != Position)
287 {
288 // goto next format;
289 DataFormat = (PKSDATAFORMAT)(ULONG_PTR)(DataFormat + DataFormat->FormatSize);
290 i++;
291 }
292
293
294 DataFormat->FormatSize -= sizeof(KSDATAFORMAT);
295 if (DataFormat->FormatSize)
296 {
297 // copy extra format buffer
298 AmMediaType->pbFormat = (BYTE*)CoTaskMemAlloc(DataFormat->FormatSize);
299 if (!AmMediaType->pbFormat)
300 {
301 // not enough memory
302 CoTaskMemFree(ItemList);
303 return E_OUTOFMEMORY;
304 }
305 // copy format buffer
306 CopyMemory(AmMediaType->pbFormat, (DataFormat + 1), DataFormat->FormatSize);
307 AmMediaType->cbFormat = DataFormat->FormatSize;
308 }
309 else
310 {
311 // no format buffer
312 AmMediaType->pbFormat = NULL;
313 AmMediaType->cbFormat = 0;
314 }
315
316 // copy type info
317 CopyMemory(&AmMediaType->majortype, &DataFormat->MajorFormat, sizeof(GUID));
318 CopyMemory(&AmMediaType->subtype, &DataFormat->SubFormat, sizeof(GUID));
319 CopyMemory(&AmMediaType->formattype, &DataFormat->Specifier, sizeof(GUID));
320 AmMediaType->bTemporalCompression = FALSE; //FIXME verify
321 AmMediaType->pUnk = NULL; //FIXME
322 AmMediaType->lSampleSize = DataFormat->SampleSize;
323 AmMediaType->bFixedSizeSamples = (AmMediaType->lSampleSize) ? TRUE : FALSE;
324
325 // free dataformat list
326 CoTaskMemFree(ItemList);
327
328 return NOERROR;
329}
330
331extern "C"
332KSDDKAPI
333HRESULT
334WINAPI
335DllUnregisterServer(void)
336{
337 ULONG Index = 0;
338 LPOLESTR pStr;
339 HRESULT hr = S_OK;
340 HKEY hClass;
341
342 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_SET_VALUE, &hClass) != ERROR_SUCCESS)
343 return E_FAIL;
344
345 do
346 {
347 hr = StringFromCLSID(*InterfaceTable[Index].riid, &pStr);
348 if (FAILED(hr))
349 break;
350
351 RegDeleteKeyW(hClass, pStr);
352 CoTaskMemFree(pStr);
353 Index++;
354 }while(InterfaceTable[Index].lpfnCI != 0);
355
356 RegCloseKey(hClass);
357 return hr;
358}
359
360extern "C"
361KSDDKAPI
362HRESULT
363WINAPI
364DllRegisterServer(void)
365{
366 ULONG Index = 0;
367 LPOLESTR pStr;
368 HRESULT hr = S_OK;
369 HKEY hClass, hKey, hSubKey;
370 static LPCWSTR ModuleName = L"ksproxy.ax";
371 static LPCWSTR ThreadingModel = L"Both";
372
373 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_WRITE, &hClass) != ERROR_SUCCESS)
374 return E_FAIL;
375
376 do
377 {
378 hr = StringFromCLSID(*InterfaceTable[Index].riid, &pStr);
379 if (FAILED(hr))
380 break;
381
382 if (RegCreateKeyExW(hClass, pStr, 0, 0, 0, KEY_WRITE, NULL, &hKey, 0) == ERROR_SUCCESS)
383 {
384 if (RegCreateKeyExW(hKey, L"InprocServer32", 0, 0, 0, KEY_WRITE, NULL, &hSubKey, 0) == ERROR_SUCCESS)
385 {
386 RegSetValueExW(hSubKey, 0, 0, REG_SZ, (const BYTE*)ModuleName, (wcslen(ModuleName) + 1) * sizeof(WCHAR));
387 RegSetValueExW(hSubKey, L"ThreadingModel", 0, REG_SZ, (const BYTE*)ThreadingModel, (wcslen(ThreadingModel) + 1) * sizeof(WCHAR));
388 RegCloseKey(hSubKey);
389 }
390 RegCloseKey(hKey);
391 }
392
393 CoTaskMemFree(pStr);
394 Index++;
395 }while(InterfaceTable[Index].lpfnCI != 0);
396
397 RegCloseKey(hClass);
398 return hr;
399}
400
401KSDDKAPI
402HRESULT
403WINAPI
404DllGetClassObject(
405 REFCLSID rclsid,
406 REFIID riid,
407 LPVOID *ppv)
408{
409 UINT i;
410 HRESULT hres = E_OUTOFMEMORY;
411 IClassFactory * pcf = NULL;
412
413 if (!ppv)
414 return E_INVALIDARG;
415
416 *ppv = NULL;
417
418 for (i = 0; InterfaceTable[i].riid; i++)
419 {
420 if (IsEqualIID(*InterfaceTable[i].riid, rclsid))
421 {
422 pcf = CClassFactory_fnConstructor(InterfaceTable[i].lpfnCI, NULL, NULL);
423 break;
424 }
425 }
426
427 if (!pcf)
428 {
429 return CLASS_E_CLASSNOTAVAILABLE;
430 }
431
432 hres = pcf->QueryInterface(riid, ppv);
433 pcf->Release();
434
435 return hres;
436}
437
438KSDDKAPI
439HRESULT
440WINAPI
441DllCanUnloadNow(void)
442{
443 return S_OK;
444}
445