* Bring back rbuild build to be used until bug 6372 is fixed.
[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 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 ULONG Index = 0;
347 LPOLESTR pStr;
348 HRESULT hr = S_OK;
349 HKEY hClass;
350
351 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_SET_VALUE, &hClass) != ERROR_SUCCESS)
352 return E_FAIL;
353
354 do
355 {
356 hr = StringFromCLSID(*InterfaceTable[Index].riid, &pStr);
357 if (FAILED(hr))
358 break;
359
360 RegDeleteKeyW(hClass, pStr);
361 CoTaskMemFree(pStr);
362 Index++;
363 }while(InterfaceTable[Index].lpfnCI != 0);
364
365 RegCloseKey(hClass);
366 return hr;
367 }
368
369 extern "C"
370 KSDDKAPI
371 HRESULT
372 WINAPI
373 DllRegisterServer(void)
374 {
375 ULONG Index = 0;
376 LPOLESTR pStr;
377 HRESULT hr = S_OK;
378 HKEY hClass, hKey, hSubKey;
379 static LPCWSTR ModuleName = L"ksproxy.ax";
380 static LPCWSTR ThreadingModel = L"Both";
381
382 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_WRITE, &hClass) != ERROR_SUCCESS)
383 return E_FAIL;
384
385 do
386 {
387 hr = StringFromCLSID(*InterfaceTable[Index].riid, &pStr);
388 if (FAILED(hr))
389 break;
390
391 if (RegCreateKeyExW(hClass, pStr, 0, 0, 0, KEY_WRITE, NULL, &hKey, 0) == ERROR_SUCCESS)
392 {
393 if (RegCreateKeyExW(hKey, L"InprocServer32", 0, 0, 0, KEY_WRITE, NULL, &hSubKey, 0) == ERROR_SUCCESS)
394 {
395 RegSetValueExW(hSubKey, 0, 0, REG_SZ, (const BYTE*)ModuleName, (wcslen(ModuleName) + 1) * sizeof(WCHAR));
396 RegSetValueExW(hSubKey, L"ThreadingModel", 0, REG_SZ, (const BYTE*)ThreadingModel, (wcslen(ThreadingModel) + 1) * sizeof(WCHAR));
397 RegCloseKey(hSubKey);
398 }
399 RegCloseKey(hKey);
400 }
401
402 CoTaskMemFree(pStr);
403 Index++;
404 }while(InterfaceTable[Index].lpfnCI != 0);
405
406 RegCloseKey(hClass);
407 return hr;
408 }
409
410 KSDDKAPI
411 HRESULT
412 WINAPI
413 DllGetClassObject(
414 REFCLSID rclsid,
415 REFIID riid,
416 LPVOID *ppv)
417 {
418 UINT i;
419 HRESULT hres = E_OUTOFMEMORY;
420 IClassFactory * pcf = NULL;
421
422 if (!ppv)
423 return E_INVALIDARG;
424
425 *ppv = NULL;
426
427 for (i = 0; InterfaceTable[i].riid; i++)
428 {
429 if (IsEqualIID(*InterfaceTable[i].riid, rclsid))
430 {
431 pcf = CClassFactory_fnConstructor(InterfaceTable[i].lpfnCI, NULL, NULL);
432 break;
433 }
434 }
435
436 if (!pcf)
437 {
438 return CLASS_E_CLASSNOTAVAILABLE;
439 }
440
441 hres = pcf->QueryInterface(riid, ppv);
442 pcf->Release();
443
444 return hres;
445 }
446
447 KSDDKAPI
448 HRESULT
449 WINAPI
450 DllCanUnloadNow(void)
451 {
452 return S_OK;
453 }
454