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
14 const GUID CLSID_KsClockForwarder = {0x877e4351, 0x6fea, 0x11d0, {0xb8, 0x63, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}};
15 const GUID CLSID_KsQualityForwarder = {0xe05592e4, 0xc0b5, 0x11d0, {0xa4, 0x39, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96}};
16 const GUID CLSID_KsIBasicAudioInterfaceHandler = {0xb9f8ac3e, 0x0f71, 0x11d2, {0xb7, 0x2c, 0x00, 0xc0, 0x4f, 0xb6, 0xbd, 0x3d}};
17
18 static 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
31 KSDDKAPI
32 HRESULT
33 WINAPI
KsSynchronousDeviceControl(HANDLE Handle,ULONG IoControl,PVOID InBuffer,ULONG InLength,PVOID OutBuffer,ULONG OutLength,PULONG BytesReturned)34 KsSynchronousDeviceControl(
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
87 KSDDKAPI
88 HRESULT
89 WINAPI
KsResolveRequiredAttributes(PKSDATARANGE DataRange,KSMULTIPLE_ITEM * Attributes OPTIONAL)90 KsResolveRequiredAttributes(
91 PKSDATARANGE DataRange,
92 KSMULTIPLE_ITEM *Attributes OPTIONAL)
93 {
94 //UNIMPLEMENTED
95 return NOERROR;
96 }
97
98 KSDDKAPI
99 HRESULT
100 WINAPI
KsOpenDefaultDevice(REFGUID Category,ACCESS_MASK Access,PHANDLE DeviceHandle)101 KsOpenDefaultDevice(
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
151 KSDDKAPI
152 HRESULT
153 WINAPI
KsGetMultiplePinFactoryItems(HANDLE FilterHandle,ULONG PinFactoryId,ULONG PropertyId,PVOID * Items)154 KsGetMultiplePinFactoryItems(
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
213 KSDDKAPI
214 HRESULT
215 WINAPI
KsGetMediaTypeCount(HANDLE FilterHandle,ULONG PinFactoryId,ULONG * MediaTypeCount)216 KsGetMediaTypeCount(
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
247 KSDDKAPI
248 HRESULT
249 WINAPI
KsGetMediaType(int Position,AM_MEDIA_TYPE * AmMediaType,HANDLE FilterHandle,ULONG PinFactoryId)250 KsGetMediaType(
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
331 extern "C"
332 KSDDKAPI
333 HRESULT
334 WINAPI
DllUnregisterServer(void)335 DllUnregisterServer(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
360 extern "C"
361 KSDDKAPI
362 HRESULT
363 WINAPI
DllRegisterServer(void)364 DllRegisterServer(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
401 KSDDKAPI
402 HRESULT
403 WINAPI
DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID * ppv)404 DllGetClassObject(
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
438 KSDDKAPI
439 HRESULT
440 WINAPI
DllCanUnloadNow(void)441 DllCanUnloadNow(void)
442 {
443 return S_OK;
444 }
445
446