xref: /reactos/dll/directx/ksproxy/ksproxy.cpp (revision 9d33a205)
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
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
90 KsResolveRequiredAttributes(
91     PKSDATARANGE     DataRange,
92     KSMULTIPLE_ITEM  *Attributes OPTIONAL)
93 {
94     //UNIMPLEMENTED
95     return NOERROR;
96 }
97 
98 KSDDKAPI
99 HRESULT
100 WINAPI
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
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
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
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
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
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
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
441 DllCanUnloadNow(void)
442 {
443     return S_OK;
444 }
445 
446