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