xref: /reactos/dll/directx/ksproxy/ksproxy.cpp (revision 9393fc32)
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
KsSynchronousDeviceControl(HANDLE Handle,ULONG IoControl,PVOID InBuffer,ULONG InLength,PVOID OutBuffer,ULONG OutLength,PULONG BytesReturned)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
KsResolveRequiredAttributes(PKSDATARANGE DataRange,KSMULTIPLE_ITEM * Attributes OPTIONAL)90 KsResolveRequiredAttributes(
91     PKSDATARANGE     DataRange,
92     KSMULTIPLE_ITEM  *Attributes OPTIONAL)
93 {
94     //UNIMPLEMENTED
95     return NOERROR;
96 }
97 
98 KSDDKAPI
99 HRESULT
100 WINAPI
KsOpenDefaultDevice(REFGUID Category,ACCESS_MASK Access,PHANDLE DeviceHandle)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
KsGetMultiplePinFactoryItems(HANDLE FilterHandle,ULONG PinFactoryId,ULONG PropertyId,PVOID * Items)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
KsGetMediaTypeCount(HANDLE FilterHandle,ULONG PinFactoryId,ULONG * MediaTypeCount)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
KsGetMediaType(int Position,AM_MEDIA_TYPE * AmMediaType,HANDLE FilterHandle,ULONG PinFactoryId)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
DllUnregisterServer(void)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
DllRegisterServer(void)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
DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID * ppv)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
DllCanUnloadNow(void)441 DllCanUnloadNow(void)
442 {
443     return S_OK;
444 }
445 
446