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