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