Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

550 lines
18 KiB

  1. /****************************************************************************
  2. * @doc INTERNAL WDMDRIVER
  3. *
  4. * @module WDMDrivr.cpp | Include file for <c CWDMDriver> class used to
  5. * access the streaming class driver using IOctls.
  6. *
  7. * @comm This code is based on the VfW to WDM mapper code written by
  8. * FelixA and E-zu Wu. The original code can be found on
  9. * \\redrum\slmro\proj\wdm10\\src\image\vfw\win9x\raytube.
  10. *
  11. * Documentation by George Shaw on kernel streaming can be found in
  12. * \\popcorn\razzle1\src\spec\ks\ks.doc.
  13. *
  14. * WDM streaming capture is discussed by Jay Borseth in
  15. * \\blues\public\jaybo\WDMVCap.doc.
  16. ***************************************************************************/
  17. #include "Precomp.h"
  18. /****************************************************************************
  19. * @doc INTERNAL CWDMDRIVERMETHOD
  20. *
  21. * @mfunc void | CWDMDriver | CWDMDriver | Driver class constructor.
  22. *
  23. * @parm DWORD | dwDeviceID | Capture device ID.
  24. ***************************************************************************/
  25. CWDMDriver::CWDMDriver(DWORD dwDeviceID)
  26. {
  27. m_hDriver = (HANDLE)NULL;
  28. m_pDataRanges = (PDATA_RANGES)NULL;
  29. m_dwDeviceID = dwDeviceID;
  30. }
  31. /****************************************************************************
  32. * @doc INTERNAL CWDMDRIVERMETHOD
  33. *
  34. * @mfunc void | CWDMDriver | ~CWDMDriver | Driver class destructor. Closes
  35. * the driver file handle and releases the video data range memory.
  36. ***************************************************************************/
  37. CWDMDriver::~CWDMDriver()
  38. {
  39. if (m_hDriver)
  40. CloseDriver();
  41. if (m_pDataRanges)
  42. {
  43. delete [] m_pDataRanges;
  44. m_pDataRanges = (PDATA_RANGES)NULL;
  45. }
  46. }
  47. /****************************************************************************
  48. * @doc INTERNAL CWDMDRIVERMETHOD
  49. *
  50. * @mfunc DWORD | CWDMDriver | CreateDriverSupportedDataRanges | This
  51. * function builds the list of video data ranges supported by the capture
  52. * device.
  53. *
  54. * @rdesc Returns the number of valid data ranges in the list.
  55. ***************************************************************************/
  56. DWORD CWDMDriver::CreateDriverSupportedDataRanges()
  57. {
  58. FX_ENTRY("CWDMDriver::CreateDriverSupportedDataRanges");
  59. DWORD cbReturned;
  60. DWORD dwSize = 0UL;
  61. // Initialize property structure to get data ranges
  62. KSP_PIN KsProperty = {0};
  63. KsProperty.PinId = 0; // m_iPinNumber;
  64. KsProperty.Property.Set = KSPROPSETID_Pin;
  65. KsProperty.Property.Id = KSPROPERTY_PIN_DATARANGES ;
  66. KsProperty.Property.Flags = KSPROPERTY_TYPE_GET;
  67. // Get the size of the data range structure
  68. if (DeviceIoControl(m_hDriver, IOCTL_KS_PROPERTY, &KsProperty, sizeof(KsProperty), &dwSize, sizeof(dwSize), &cbReturned) == FALSE)
  69. {
  70. ERRORMESSAGE(("%s: Couldn't get the size for the data ranges\r\n", _fx_));
  71. return 0UL;
  72. }
  73. DEBUGMSG(ZONE_INIT, ("%s: GetData ranges needs %d bytes\r\n", _fx_, dwSize));
  74. // Allocate memory to hold data ranges
  75. if (m_pDataRanges)
  76. delete [] m_pDataRanges;
  77. m_pDataRanges = (PDATA_RANGES) new BYTE[dwSize];
  78. if (!m_pDataRanges)
  79. {
  80. ERRORMESSAGE(("%s: Couldn't allocate memory for the data ranges\r\n", _fx_));
  81. return 0UL;
  82. }
  83. // Really get the data ranges
  84. if (DeviceIoControl(m_hDriver, IOCTL_KS_PROPERTY, &KsProperty, sizeof(KsProperty), m_pDataRanges, dwSize, &cbReturned) == 0)
  85. {
  86. ERRORMESSAGE(("%s: Problem getting the data ranges themselves\r\n", _fx_));
  87. goto MyError1;
  88. }
  89. // Sanity check
  90. if (cbReturned < m_pDataRanges->Size || m_pDataRanges->Count == 0)
  91. {
  92. ERRORMESSAGE(("%s: cbReturned < m_pDataRanges->Size || m_pDataRanges->Count == 0\r\n", _fx_));
  93. goto MyError1;
  94. }
  95. return m_pDataRanges->Count;
  96. MyError1:
  97. delete [] m_pDataRanges;
  98. m_pDataRanges = (PDATA_RANGES)NULL;
  99. return 0UL;
  100. }
  101. /****************************************************************************
  102. * @doc INTERNAL CWDMDRIVERMETHOD
  103. *
  104. * @mfunc DWORD | CWDMDriver | OpenDriver | This function opens a driver
  105. * file handle to the capture device.
  106. *
  107. * @rdesc Returns TRUE if successful, or FALSE otherwise.
  108. ***************************************************************************/
  109. BOOL CWDMDriver::OpenDriver()
  110. {
  111. FX_ENTRY("CWDMDriver::OpenDriver");
  112. // Don't re-open the driver
  113. if (m_hDriver)
  114. {
  115. DEBUGMSG(ZONE_INIT, ("%s: Class driver already opened\r\n", _fx_));
  116. return TRUE;
  117. }
  118. // Validate driver path
  119. if (lstrlen(g_aCapDevices[m_dwDeviceID]->szDeviceName) == 0)
  120. {
  121. ERRORMESSAGE(("%s: Invalid driver path\r\n", _fx_));
  122. return FALSE;
  123. }
  124. DEBUGMSG(ZONE_INIT, ("%s: Opening class driver '%s'\r\n", _fx_, g_aCapDevices[m_dwDeviceID]->szDeviceName));
  125. // All we care is to wet the hInheritHanle = TRUE;
  126. SECURITY_ATTRIBUTES SecurityAttributes;
  127. SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); // use pointers
  128. SecurityAttributes.bInheritHandle = TRUE;
  129. SecurityAttributes.lpSecurityDescriptor = NULL; // GetInitializedSecurityDescriptor();
  130. // Really open the driver
  131. if ((m_hDriver = CreateFile(g_aCapDevices[m_dwDeviceID]->szDeviceName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &SecurityAttributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL)) == INVALID_HANDLE_VALUE)
  132. {
  133. ERRORMESSAGE(("%s: CreateFile failed with Path=%s GetLastError()=%d\r\n", _fx_, g_aCapDevices[m_dwDeviceID]->szDeviceName, GetLastError()));
  134. m_hDriver = (HANDLE)NULL;
  135. return FALSE;
  136. }
  137. // If there is no valid data range, we cannot stream
  138. if (!CreateDriverSupportedDataRanges())
  139. {
  140. CloseDriver();
  141. return FALSE;
  142. }
  143. else
  144. return TRUE;
  145. }
  146. /****************************************************************************
  147. * @doc INTERNAL CWDMDRIVERMETHOD
  148. *
  149. * @mfunc DWORD | CWDMDriver | CloseDriver | This function closes a driver
  150. * file handle to the capture device.
  151. *
  152. * @rdesc Returns TRUE if successful, or FALSE otherwise.
  153. ***************************************************************************/
  154. BOOL CWDMDriver::CloseDriver()
  155. {
  156. FX_ENTRY("CWDMDriver::CloseDriver");
  157. BOOL bRet = TRUE;
  158. if (m_hDriver && (m_hDriver != INVALID_HANDLE_VALUE))
  159. {
  160. if (!(bRet = CloseHandle(m_hDriver)))
  161. {
  162. ERRORMESSAGE(("%s: CloseHandle() failed with GetLastError()=%d\r\n", _fx_, GetLastError()));
  163. }
  164. }
  165. else
  166. {
  167. DEBUGMSG(ZONE_INIT, ("%s: Nothing to close\r\n", _fx_));
  168. }
  169. m_hDriver = (HANDLE)NULL;
  170. return bRet;
  171. }
  172. /****************************************************************************
  173. * @doc INTERNAL CWDMDRIVERMETHOD
  174. *
  175. * @mfunc BOOL | CWDMDriver | DeviceIoControl | This function wraps around
  176. * ::DeviceIOControl.
  177. *
  178. * @parm HANDLE | hFile | Handle to the device that is to perform the
  179. * operation.
  180. *
  181. * @parm DWORD | dwIoControlCode | Specifies the control code for the
  182. * operation.
  183. *
  184. * @parm LPVOID | lpInBuffer | Pointer to a buffer that contains the data
  185. * required to perform the operation.
  186. *
  187. * @parm DWORD | nInBufferSize | Specifies the size, in bytes, of the buffer
  188. * pointed to by <p lpInBuffer>.
  189. *
  190. * @parm LPVOID | lpOutBuffer | Pointer to a buffer that receives the
  191. * operation's output data.
  192. *
  193. * @parm DWORD | nOutBufferSize | Specifies the size, in bytes, of the
  194. * buffer pointed to by <p lpOutBuffer>.
  195. *
  196. * @parm LPDWORD | lpBytesReturned | Pointer to a variable that receives the
  197. * size, in bytes, of the data stored into the buffer pointed to by
  198. * <p lpOutBuffer>.
  199. *
  200. * @parm BOOL | bOverlapped | If TRUE, the operation is performed
  201. * asynchronously, if FALSE, the operation is synchronous.
  202. *
  203. * @rdesc Returns TRUE if successful, or FALSE otherwise.
  204. ***************************************************************************/
  205. BOOL CWDMDriver::DeviceIoControl(HANDLE hFile, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, BOOL bOverlapped)
  206. {
  207. FX_ENTRY("CWDMDriver::DeviceIoControl");
  208. if (hFile && (hFile != INVALID_HANDLE_VALUE))
  209. {
  210. LPOVERLAPPED lpOverlapped=NULL;
  211. BOOL bRet;
  212. OVERLAPPED ov;
  213. DWORD dwErr;
  214. if (bOverlapped)
  215. {
  216. ov.Offset = 0;
  217. ov.OffsetHigh = 0;
  218. ov.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  219. if (ov.hEvent == (HANDLE) 0)
  220. {
  221. ERRORMESSAGE(("%s: CreateEvent has failed\r\n", _fx_));
  222. }
  223. lpOverlapped =&ov;
  224. }
  225. bRet = ::DeviceIoControl(hFile, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
  226. if (bOverlapped)
  227. {
  228. BOOL bShouldBlock=FALSE;
  229. if (!bRet)
  230. {
  231. dwErr=GetLastError();
  232. switch (dwErr)
  233. {
  234. case ERROR_IO_PENDING: // the overlapped IO is going to take place.
  235. bShouldBlock=TRUE;
  236. break;
  237. default: // some other strange error has happened.
  238. ERRORMESSAGE(("%s: DevIoControl failed with GetLastError=%d\r\n", _fx_, dwErr));
  239. break;
  240. }
  241. }
  242. if (bShouldBlock)
  243. {
  244. #ifdef _DEBUG
  245. DWORD tmStart, tmEnd, tmDelta;
  246. tmStart = timeGetTime();
  247. #endif
  248. DWORD dwRtn = WaitForSingleObject( ov.hEvent, 1000 * 10); // USB has a max of 5 SEC bus reset
  249. #ifdef _DEBUG
  250. tmEnd = timeGetTime();
  251. tmDelta = tmEnd - tmStart;
  252. if (tmDelta >= 1000)
  253. {
  254. ERRORMESSAGE(("%s: WaitObj waited %d msec\r\n", _fx_, tmDelta));
  255. }
  256. #endif
  257. switch (dwRtn)
  258. {
  259. case WAIT_ABANDONED:
  260. ERRORMESSAGE(("%s: WaitObj: non-signaled ! WAIT_ABANDONED!\r\n", _fx_));
  261. bRet = FALSE;
  262. break;
  263. case WAIT_OBJECT_0:
  264. bRet = TRUE;
  265. break;
  266. case WAIT_TIMEOUT:
  267. #ifdef _DEBUG
  268. ERRORMESSAGE(("%s: WaitObj: TIMEOUT after %d msec! rtn FALSE\r\n", _fx_, tmDelta));
  269. #endif
  270. bRet = FALSE;
  271. break;
  272. default:
  273. ERRORMESSAGE(("%s: WaitObj: unknown return ! rtn FALSE\r\n", _fx_));
  274. bRet = FALSE;
  275. break;
  276. }
  277. }
  278. CloseHandle(ov.hEvent);
  279. }
  280. return bRet;
  281. }
  282. return FALSE;
  283. }
  284. /****************************************************************************
  285. * @doc INTERNAL CWDMDRIVERMETHOD
  286. *
  287. * @mfunc BOOL | CWDMDriver | GetPropertyValue | This function gets the
  288. * current value of a video property of a capture device.
  289. *
  290. * @parm GUID | guidPropertySet | GUID of the KS property set we are touching. It
  291. * is either PROPSETID_VIDCAP_VIDEOPROCAMP or PROPSETID_VIDCAP_CAMERACONTROL.
  292. *
  293. * @parm ULONG | ulPropertyId | ID of the property we are touching. It is
  294. * either KSPROPERTY_VIDEOPROCAMP_* or KSPROPERTY_CAMERACONTROL_*.
  295. *
  296. * @parm PLONG | plValue | Pointer to a LONG to receive the current value.
  297. *
  298. * @parm PULONG | pulFlags | Pointer to a ULONG to receive the current
  299. * flags. We only care about KSPROPERTY_*_FLAGS_MANUAL or
  300. * KSPROPERTY_*_FLAGS_AUTO.
  301. *
  302. * @parm PULONG | pulCapabilities | Pointer to a ULONG to receive the
  303. * capabilities. We only care about KSPROPERTY_*_FLAGS_MANUAL or
  304. * KSPROPERTY_*_FLAGS_AUTO.
  305. *
  306. * @rdesc Returns TRUE if successful, or FALSE otherwise.
  307. *
  308. * @devnote KSPROPERTY_VIDEOPROCAMP_S == KSPROPERTY_CAMERACONTROL_S.
  309. ***************************************************************************/
  310. BOOL CWDMDriver::GetPropertyValue(GUID guidPropertySet, ULONG ulPropertyId, PLONG plValue, PULONG pulFlags, PULONG pulCapabilities)
  311. {
  312. FX_ENTRY("CWDMDriver::GetPropertyValue");
  313. ULONG cbReturned;
  314. // Inititalize video property structure
  315. KSPROPERTY_VIDEOPROCAMP_S VideoProperty;
  316. ZeroMemory(&VideoProperty, sizeof(KSPROPERTY_VIDEOPROCAMP_S));
  317. VideoProperty.Property.Set = guidPropertySet; // KSPROPERTY_VIDEOPROCAMP_S/CAMERACONTRO_S
  318. VideoProperty.Property.Id = ulPropertyId; // KSPROPERTY_VIDEOPROCAMP_BRIGHTNESS
  319. VideoProperty.Property.Flags = KSPROPERTY_TYPE_GET;
  320. VideoProperty.Flags = 0;
  321. // Get property value from driver
  322. if (DeviceIoControl(m_hDriver, IOCTL_KS_PROPERTY, &VideoProperty, sizeof(VideoProperty), &VideoProperty, sizeof(VideoProperty), &cbReturned, TRUE) == 0)
  323. {
  324. ERRORMESSAGE(("%s: This property is not supported by this minidriver/device\r\n", _fx_));
  325. return FALSE;
  326. }
  327. *plValue = VideoProperty.Value;
  328. *pulFlags = VideoProperty.Flags;
  329. *pulCapabilities = VideoProperty.Capabilities;
  330. return TRUE;
  331. }
  332. /****************************************************************************
  333. * @doc INTERNAL CWDMDRIVERMETHOD
  334. *
  335. * @mfunc BOOL | CWDMDriver | GetDefaultValue | This function gets the
  336. * default value of a video property of a capture device.
  337. *
  338. * @parm GUID | guidPropertySet | GUID of the KS property set we are touching. It
  339. * is either PROPSETID_VIDCAP_VIDEOPROCAMP or PROPSETID_VIDCAP_CAMERACONTROL.
  340. *
  341. * @parm ULONG | ulPropertyId | ID of the property we are touching. It is
  342. * either KSPROPERTY_VIDEOPROCAMP_* or KSPROPERTY_CAMERACONTROL_*.
  343. *
  344. * @parm PLONG | plDefValue | Pointer to a LONG to receive the default value.
  345. *
  346. * @rdesc Returns TRUE if successful, or FALSE otherwise.
  347. ***************************************************************************/
  348. BOOL CWDMDriver::GetDefaultValue(GUID guidPropertySet, ULONG ulPropertyId, PLONG plDefValue)
  349. {
  350. FX_ENTRY("CWDMDriver::GetDefaultValue");
  351. ULONG cbReturned;
  352. KSPROPERTY Property;
  353. PROCAMP_MEMBERSLIST proList;
  354. // Initialize property structures
  355. ZeroMemory(&Property, sizeof(KSPROPERTY));
  356. ZeroMemory(&proList, sizeof(PROCAMP_MEMBERSLIST));
  357. Property.Set = guidPropertySet;
  358. Property.Id = ulPropertyId; // e.g. KSPROPERTY_VIDEOPROCAMP_BRIGHTNESS
  359. Property.Flags = KSPROPERTY_TYPE_DEFAULTVALUES;
  360. // Get the default values from the driver
  361. if (DeviceIoControl(m_hDriver, IOCTL_KS_PROPERTY, &(Property), sizeof(Property), &proList, sizeof(proList), &cbReturned, TRUE) == 0)
  362. {
  363. ERRORMESSAGE(("%s: Couldn't *get* the current property of the control\r\n", _fx_));
  364. return FALSE;
  365. }
  366. // Sanity check
  367. if (proList.proDesc.DescriptionSize < sizeof(KSPROPERTY_DESCRIPTION))
  368. return FALSE;
  369. else
  370. {
  371. *plDefValue = proList.ulData;
  372. return TRUE;
  373. }
  374. }
  375. /****************************************************************************
  376. * @doc INTERNAL CWDMDRIVERMETHOD
  377. *
  378. * @mfunc BOOL | CWDMDriver | GetRangeValues | This function gets the
  379. * range values of a video property of a capture device.
  380. *
  381. * @parm GUID | guidPropertySet | GUID of the KS property set we are touching. It
  382. * is either PROPSETID_VIDCAP_VIDEOPROCAMP or PROPSETID_VIDCAP_CAMERACONTROL.
  383. *
  384. * @parm ULONG | ulPropertyId | ID of the property we are touching. It is
  385. * either KSPROPERTY_VIDEOPROCAMP_* or KSPROPERTY_CAMERACONTROL_*.
  386. *
  387. * @parm PLONG | plMin | Pointer to a LONG to receive the minimum value.
  388. *
  389. * @parm PLONG | plMax | Pointer to a LONG to receive the maximum value.
  390. *
  391. * @parm PLONG | plStep | Pointer to a LONG to receive the step value.
  392. *
  393. * @rdesc Returns TRUE if successful, or FALSE otherwise.
  394. ***************************************************************************/
  395. BOOL CWDMDriver::GetRangeValues(GUID guidPropertySet, ULONG ulPropertyId, PLONG plMin, PLONG plMax, PLONG plStep)
  396. {
  397. FX_ENTRY("CWDMDriver::GetRangeValues");
  398. ULONG cbReturned;
  399. KSPROPERTY Property;
  400. PROCAMP_MEMBERSLIST proList;
  401. // Initialize property structures
  402. ZeroMemory(&Property, sizeof(KSPROPERTY));
  403. ZeroMemory(&proList, sizeof(PROCAMP_MEMBERSLIST));
  404. Property.Set = guidPropertySet;
  405. Property.Id = ulPropertyId; // e.g. KSPROPERTY_VIDEOPROCAMP_BRIGHTNESS
  406. Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT;
  407. // Get range values from the driver
  408. if (DeviceIoControl(m_hDriver, IOCTL_KS_PROPERTY, &(Property), sizeof(Property), &proList, sizeof(proList), &cbReturned, TRUE) == 0)
  409. {
  410. ERRORMESSAGE(("%s: Couldn't *get* the current property of the control\r\n", _fx_));
  411. return FALSE;
  412. }
  413. *plMin = proList.proData.Bounds.SignedMinimum;
  414. *plMax = proList.proData.Bounds.SignedMaximum;
  415. *plStep = proList.proData.SteppingDelta;
  416. return TRUE;
  417. }
  418. /****************************************************************************
  419. * @doc INTERNAL CWDMDRIVERMETHOD
  420. *
  421. * @mfunc BOOL | CWDMDriver | SetPropertyValue | This function sets the
  422. * current value of a video property of a capture device.
  423. *
  424. * @parm GUID | guidPropertySet | GUID of the KS property set we are touching. It
  425. * is either PROPSETID_VIDCAP_VIDEOPROCAMP or PROPSETID_VIDCAP_CAMERACONTROL.
  426. *
  427. * @parm ULONG | ulPropertyId | ID of the property we are touching. It is
  428. * either KSPROPERTY_VIDEOPROCAMP_* or KSPROPERTY_CAMERACONTROL_*.
  429. *
  430. * @parm LONG | lValue | New value.
  431. *
  432. * @parm ULONG | ulFlags | New flags. We only care about KSPROPERTY_*_FLAGS_MANUAL
  433. * or KSPROPERTY_*_FLAGS_AUTO.
  434. *
  435. * @parm ULONG | ulCapabilities | New capabilities. We only care about
  436. * KSPROPERTY_*_FLAGS_MANUAL or KSPROPERTY_*_FLAGS_AUTO.
  437. *
  438. * @rdesc Returns TRUE if successful, or FALSE otherwise.
  439. *
  440. * @devnote KSPROPERTY_VIDEOPROCAMP_S == KSPROPERTY_CAMERACONTROL_S.
  441. ***************************************************************************/
  442. BOOL CWDMDriver::SetPropertyValue(GUID guidPropertySet, ULONG ulPropertyId, LONG lValue, ULONG ulFlags, ULONG ulCapabilities)
  443. {
  444. FX_ENTRY("CWDMDriver::SetPropertyValue");
  445. ULONG cbReturned;
  446. // Initialize property structure
  447. KSPROPERTY_VIDEOPROCAMP_S VideoProperty;
  448. ZeroMemory(&VideoProperty, sizeof(KSPROPERTY_VIDEOPROCAMP_S) );
  449. VideoProperty.Property.Set = guidPropertySet; // KSPROPERTY_VIDEOPROCAMP_S/CAMERACONTRO_S
  450. VideoProperty.Property.Id = ulPropertyId; // KSPROPERTY_VIDEOPROCAMP_BRIGHTNESS
  451. VideoProperty.Property.Flags = KSPROPERTY_TYPE_SET;
  452. VideoProperty.Flags = ulFlags;
  453. VideoProperty.Value = lValue;
  454. VideoProperty.Capabilities = ulCapabilities;
  455. // Set the property value on the driver
  456. if (DeviceIoControl(m_hDriver, IOCTL_KS_PROPERTY, &VideoProperty, sizeof(VideoProperty), &VideoProperty, sizeof(VideoProperty), &cbReturned, TRUE) == 0)
  457. {
  458. ERRORMESSAGE(("%s: Couldn't *set* the current property of the control\r\n", _fx_));
  459. return FALSE;
  460. }
  461. return TRUE;
  462. }