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