Windows NT 4.0 source code leak
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.

576 lines
17 KiB

4 years ago
  1. /****************************************************************************
  2. *
  3. * capinit.c
  4. *
  5. * Initialization code.
  6. *
  7. * Microsoft Video for Windows Sample Capture Class
  8. *
  9. * Copyright (c) 1992 - 1995 Microsoft Corporation. All Rights Reserved.
  10. *
  11. * You have a royalty-free right to use, modify, reproduce and
  12. * distribute the Sample Files (and/or any modified version) in
  13. * any way you find useful, provided that you agree that
  14. * Microsoft has no warranty obligations or liability for any
  15. * Sample Application Files which are modified.
  16. *
  17. ***************************************************************************/
  18. #define INC_OLE2
  19. #pragma warning(disable:4103)
  20. #include <windows.h>
  21. #include <windowsx.h>
  22. #include <win32.h>
  23. #define MODULE_DEBUG_PREFIX "AVICAP32\\"
  24. #define _INC_MMDEBUG_CODE_ TRUE
  25. #include "MMDEBUG.H"
  26. #if !defined CHICAGO
  27. #include <ntverp.h>
  28. #endif
  29. #include <mmsystem.h>
  30. #include <msvideo.h>
  31. #include "ivideo32.h"
  32. #include <drawdib.h>
  33. #include "avicap.h"
  34. #include "avicapi.h"
  35. HINSTANCE ghInstDll;
  36. TCHAR szCaptureWindowClass[] = TEXT("ClsCapWin");
  37. #if !defined CHICAGO
  38. typedef struct tagVS_VERSION
  39. {
  40. WORD wTotLen;
  41. WORD wValLen;
  42. TCHAR szSig[16];
  43. VS_FIXEDFILEINFO vffInfo;
  44. } VS_VERSION;
  45. typedef struct tagLANGANDCP
  46. {
  47. WORD wLanguage;
  48. WORD wCodePage;
  49. } LANGANDCP;
  50. #endif
  51. BOOL gfIsRTL;
  52. BOOL FAR PASCAL RegisterCaptureClass (HINSTANCE hInst)
  53. {
  54. WNDCLASS cls;
  55. // If we're already registered, we're OK
  56. if (GetClassInfo(hInst, szCaptureWindowClass, &cls))
  57. return TRUE;
  58. cls.hCursor = LoadCursor(NULL, IDC_ARROW);
  59. cls.hIcon = NULL;
  60. cls.lpszMenuName = NULL;
  61. cls.lpszClassName = szCaptureWindowClass;
  62. cls.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
  63. cls.hInstance = hInst;
  64. cls.style = CS_HREDRAW|CS_VREDRAW | CS_BYTEALIGNCLIENT |
  65. CS_GLOBALCLASS | CS_DBLCLKS;
  66. cls.lpfnWndProc = (WNDPROC) CapWndProc;
  67. cls.cbClsExtra = 0;
  68. // Kludge, VB Status and Error GlobalAlloc'd ptrs + room to grow...
  69. cls.cbWndExtra = sizeof (LPCAPSTREAM) + sizeof (DWORD) * 4;
  70. RegisterClass(&cls);
  71. return TRUE;
  72. }
  73. //
  74. // Internal version
  75. // Get the name and version of the video device
  76. //
  77. BOOL capInternalGetDriverDesc (UINT wDriverIndex,
  78. LPTSTR lpszName, int cbName,
  79. LPTSTR lpszVer, int cbVer)
  80. {
  81. #ifdef CHICAGO
  82. // This calls into 16-bit AVICAP via a thunk
  83. return (BOOL) capxGetDriverDescription ((WORD) wDriverIndex,
  84. lpszName, (WORD) cbName,
  85. lpszVer, (WORD) cbVer);
  86. #else
  87. LPTSTR lpVersion;
  88. UINT wVersionLen;
  89. BOOL bRetCode;
  90. TCHAR szGetName[MAX_PATH];
  91. DWORD dwVerInfoSize;
  92. DWORD dwVerHnd;
  93. TCHAR szBuf[MAX_PATH];
  94. BOOL fGetName;
  95. BOOL fGetVersion;
  96. const static TCHAR szNull[] = TEXT("");
  97. const static TCHAR szVideo[] = TEXT("msvideo");
  98. const static TCHAR szSystemIni[] = TEXT("system.ini");
  99. const static TCHAR szDrivers[] = TEXT("Drivers32");
  100. static TCHAR szKey[sizeof(szVideo)/sizeof(TCHAR) + 2];
  101. fGetName = lpszName != NULL && cbName != 0;
  102. fGetVersion = lpszVer != NULL && cbVer != 0;
  103. if (fGetName)
  104. lpszName[0] = TEXT('\0');
  105. if (fGetVersion)
  106. lpszVer [0] = TEXT('\0');
  107. lstrcpy(szKey, szVideo);
  108. szKey[sizeof(szVideo)/sizeof(TCHAR) - 1] = TEXT('\0');
  109. if( wDriverIndex > 0 ) {
  110. szKey[sizeof(szVideo)/sizeof(TCHAR)] = TEXT('\0');
  111. szKey[(sizeof(szVideo)/sizeof(TCHAR))-1] = (TCHAR)(TEXT('1') + (wDriverIndex-1) ); // driver ordinal
  112. }
  113. if (GetPrivateProfileString(szDrivers, szKey, szNull,
  114. szBuf, sizeof(szBuf)/sizeof(TCHAR), szSystemIni) < 2)
  115. return FALSE;
  116. // Copy in the driver name initially, just in case the driver
  117. // has omitted a description field.
  118. if (fGetName)
  119. lstrcpyn(lpszName, szBuf, cbName);
  120. // You must find the size first before getting any file info
  121. dwVerInfoSize = GetFileVersionInfoSize(szBuf, &dwVerHnd);
  122. if (dwVerInfoSize) {
  123. LPTSTR lpstrVffInfo; // Pointer to block to hold info
  124. HANDLE hMem; // handle to mem alloc'ed
  125. // Get a block big enough to hold version info
  126. hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
  127. lpstrVffInfo = GlobalLock(hMem);
  128. // Get the File Version first
  129. if (GetFileVersionInfo(szBuf, 0L, dwVerInfoSize, lpstrVffInfo)) {
  130. VS_VERSION FAR *pVerInfo = (VS_VERSION FAR *) lpstrVffInfo;
  131. // fill in the file version
  132. wsprintf(szBuf,
  133. TEXT("Version: %d.%d.%d.%d"),
  134. HIWORD(pVerInfo->vffInfo.dwFileVersionMS),
  135. LOWORD(pVerInfo->vffInfo.dwFileVersionMS),
  136. HIWORD(pVerInfo->vffInfo.dwFileVersionLS),
  137. LOWORD(pVerInfo->vffInfo.dwFileVersionLS));
  138. if (fGetVersion)
  139. lstrcpyn (lpszVer, szBuf, cbVer);
  140. }
  141. // Now try to get the FileDescription
  142. // First try this for the "Translation" entry, and then
  143. // try the American english translation.
  144. // Keep track of the string length for easy updating.
  145. // 040904E4 represents the language ID and the four
  146. // least significant digits represent the codepage for
  147. // which the data is formatted. The language ID is
  148. // composed of two parts: the low ten bits represent
  149. // the major language and the high six bits represent
  150. // the sub language.
  151. lstrcpy(szGetName, TEXT("\\StringFileInfo\\040904E4\\FileDescription"));
  152. wVersionLen = 0;
  153. lpVersion = NULL;
  154. // Look for the corresponding string.
  155. bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
  156. (LPTSTR)szGetName,
  157. (void FAR* FAR*)&lpVersion,
  158. (UINT FAR *) &wVersionLen);
  159. if (fGetName && bRetCode && wVersionLen && lpVersion)
  160. lstrcpyn (lpszName, lpVersion, cbName);
  161. // Let go of the memory
  162. GlobalUnlock(hMem);
  163. GlobalFree(hMem);
  164. }
  165. return TRUE;
  166. #endif
  167. }
  168. #ifdef UNICODE
  169. // ansi thunk for above (called from ansi thunk functions
  170. // for capGetDriverDescriptionA, and WM_GET_DRIVER_NAMEA etc)
  171. BOOL capInternalGetDriverDescA(UINT wDriverIndex,
  172. LPSTR lpszName, int cbName,
  173. LPSTR lpszVer, int cbVer)
  174. {
  175. LPWSTR pName = NULL, pVer = NULL;
  176. BOOL bRet;
  177. if (lpszName) {
  178. pName = LocalAlloc(LPTR, cbName * sizeof(WCHAR));
  179. }
  180. if (lpszVer) {
  181. pVer = LocalAlloc(LPTR, cbVer * sizeof(WCHAR));
  182. }
  183. bRet = capInternalGetDriverDesc(
  184. wDriverIndex,
  185. pName, cbName,
  186. pVer, cbVer);
  187. if (lpszName) {
  188. WideToAnsi(lpszName, pName, cbName);
  189. }
  190. if (lpszVer) {
  191. WideToAnsi(lpszVer, pVer, cbVer);
  192. }
  193. if (pVer) {
  194. LocalFree(pVer);
  195. }
  196. if (pName) {
  197. LocalFree(pName);
  198. }
  199. return bRet;
  200. }
  201. #endif
  202. //
  203. // Exported version
  204. // Get the name and version of the video device
  205. //
  206. // unicode and win-16 version - see ansi thunk below
  207. BOOL VFWAPI capGetDriverDescription (UINT wDriverIndex,
  208. LPTSTR lpszName, int cbName,
  209. LPTSTR lpszVer, int cbVer)
  210. {
  211. return (capInternalGetDriverDesc (wDriverIndex,
  212. lpszName, cbName,
  213. lpszVer, cbVer));
  214. }
  215. #ifdef UNICODE
  216. // ansi thunk for above
  217. BOOL VFWAPI capGetDriverDescriptionA(UINT wDriverIndex,
  218. LPSTR lpszName, int cbName,
  219. LPSTR lpszVer, int cbVer)
  220. {
  221. return capInternalGetDriverDescA(wDriverIndex,
  222. lpszName, cbName, lpszVer, cbVer);
  223. }
  224. #endif
  225. //
  226. // Disconnect from hardware resources
  227. //
  228. BOOL CapWinDisconnectHardware(LPCAPSTREAM lpcs)
  229. {
  230. if( lpcs->hVideoCapture ) {
  231. videoStreamFini (lpcs->hVideoCapture);
  232. videoClose( lpcs->hVideoCapture );
  233. }
  234. if( lpcs->hVideoDisplay ) {
  235. videoStreamFini (lpcs->hVideoDisplay);
  236. videoClose( lpcs->hVideoDisplay );
  237. }
  238. if( lpcs->hVideoIn ) {
  239. videoClose( lpcs->hVideoIn );
  240. }
  241. lpcs->fHardwareConnected = FALSE;
  242. lpcs->hVideoCapture = NULL;
  243. lpcs->hVideoDisplay = NULL;
  244. lpcs->hVideoIn = NULL;
  245. lpcs->sCapDrvCaps.fHasDlgVideoSource = FALSE;
  246. lpcs->sCapDrvCaps.fHasDlgVideoFormat = FALSE;
  247. lpcs->sCapDrvCaps.fHasDlgVideoDisplay = FALSE;
  248. lpcs->sCapDrvCaps.fHasDlgVideoDisplay = FALSE;
  249. lpcs->sCapDrvCaps.fHasOverlay = FALSE;
  250. lpcs->sCapDrvCaps.fDriverSuppliesPalettes = FALSE;
  251. lpcs->sCapDrvCaps.hVideoIn = NULL;
  252. lpcs->sCapDrvCaps.hVideoOut = NULL;
  253. lpcs->sCapDrvCaps.hVideoExtIn = NULL;
  254. lpcs->sCapDrvCaps.hVideoExtOut = NULL;
  255. return TRUE;
  256. }
  257. //
  258. // Connect to hardware resources
  259. // Return: TRUE if hardware connected to the stream
  260. //
  261. BOOL CapWinConnectHardware (LPCAPSTREAM lpcs, UINT wDeviceIndex)
  262. {
  263. DWORD dwError;
  264. CHANNEL_CAPS VideoCapsExternalOut;
  265. TCHAR ach1[MAX_PATH];
  266. TCHAR ach2[MAX_PATH * 3];
  267. CAPINFOCHUNK cic;
  268. HINSTANCE hInstT;
  269. lpcs->hVideoCapture = NULL;
  270. lpcs->hVideoDisplay = NULL;
  271. lpcs->hVideoIn = NULL;
  272. lpcs->fHardwareConnected = FALSE;
  273. lpcs->fUsingDefaultPalette = TRUE;
  274. lpcs->sCapDrvCaps.fHasDlgVideoSource = FALSE;
  275. lpcs->sCapDrvCaps.fHasDlgVideoFormat = FALSE;
  276. lpcs->sCapDrvCaps.fHasDlgVideoDisplay = FALSE;
  277. lpcs->sCapDrvCaps.wDeviceIndex = wDeviceIndex;
  278. // Clear any existing capture device name chunk
  279. cic.fccInfoID = mmioFOURCC ('I','S','F','T');
  280. cic.lpData = NULL;
  281. cic.cbData = 0;
  282. SetInfoChunk (lpcs, &cic);
  283. // try and open the video hardware!!!
  284. if( !(dwError = videoOpen( &lpcs->hVideoIn, wDeviceIndex, VIDEO_IN ) ) ) {
  285. if( !(dwError = videoOpen( &lpcs->hVideoCapture, wDeviceIndex, VIDEO_EXTERNALIN ) ) ) {
  286. // We don't require the EXTERNALOUT channel,
  287. // but do require EXTERNALIN and IN
  288. videoOpen( &lpcs->hVideoDisplay, wDeviceIndex, VIDEO_EXTERNALOUT );
  289. if( (!dwError) && lpcs->hVideoCapture && lpcs->hVideoIn ) {
  290. lpcs->fHardwareConnected = TRUE;
  291. capInternalGetDriverDesc (wDeviceIndex,
  292. ach1, sizeof (ach1) / sizeof(TCHAR),
  293. ach2, sizeof (ach2) / sizeof(TCHAR));
  294. lstrcat (ach1, TEXT(", "));
  295. lstrcat (ach1, ach2);
  296. statusUpdateStatus (lpcs, IDS_CAP_INFO, (LPTSTR) ach1);
  297. // Make a string of the current task and capture driver
  298. ach2[0] = '\0';
  299. if (hInstT = GetWindowInstance (GetParent(lpcs->hwnd)))
  300. GetModuleFileName (hInstT, ach2, sizeof (ach2)/sizeof(TCHAR));
  301. lstrcat (ach2, TEXT(" -AVICAP32- "));
  302. lstrcat (ach2, ach1);
  303. // Set software chunk with name of capture device
  304. if (*ach2) {
  305. #ifdef UNICODE
  306. // INFO chunks must be ASCII data
  307. CHAR achA[MAX_PATH*3];
  308. cic.cbData = lstrlen(ach2) + 1; // set the number of characters
  309. WideToAnsi(achA, ach2, cic.cbData);
  310. cic.lpData = achA;
  311. #else
  312. cic.lpData = ach2;
  313. cic.cbData = lstrlen(ach2) + 1;
  314. #endif
  315. SetInfoChunk (lpcs, &cic);
  316. }
  317. }
  318. }
  319. }
  320. if (dwError)
  321. errorDriverID (lpcs, dwError);
  322. if(!lpcs->fHardwareConnected) {
  323. CapWinDisconnectHardware(lpcs);
  324. }
  325. else {
  326. if (lpcs->hVideoDisplay && videoGetChannelCaps (lpcs->hVideoDisplay,
  327. &VideoCapsExternalOut,
  328. sizeof (CHANNEL_CAPS)) == DV_ERR_OK) {
  329. lpcs->sCapDrvCaps.fHasOverlay = (BOOL)(VideoCapsExternalOut.dwFlags &
  330. (DWORD)VCAPS_OVERLAY);
  331. }
  332. else
  333. lpcs->sCapDrvCaps.fHasOverlay = FALSE;
  334. // if the hardware doesn't support it, make sure we don't enable
  335. if (!lpcs->sCapDrvCaps.fHasOverlay)
  336. lpcs->fOverlayWindow = FALSE;
  337. // Start the external in channel streaming continuously
  338. videoStreamInit (lpcs->hVideoCapture, 0L, 0L, 0L, 0L);
  339. } // end if hardware is available
  340. #if 0
  341. // if we don't have a powerful machine, disable capture
  342. if (GetWinFlags() & (DWORD) WF_CPU286)
  343. CapWinDisconnectHardware(lpcs);
  344. #endif
  345. if (!lpcs->fHardwareConnected){
  346. lpcs->fLiveWindow = FALSE;
  347. lpcs->fOverlayWindow = FALSE;
  348. }
  349. if (lpcs->hVideoIn)
  350. lpcs->sCapDrvCaps.fHasDlgVideoFormat = !videoDialog (lpcs->hVideoIn,
  351. lpcs->hwnd, VIDEO_DLG_QUERY);
  352. if (lpcs->hVideoCapture)
  353. lpcs->sCapDrvCaps.fHasDlgVideoSource = !videoDialog (lpcs->hVideoCapture,
  354. lpcs->hwnd, VIDEO_DLG_QUERY);
  355. if (lpcs->hVideoDisplay)
  356. lpcs->sCapDrvCaps.fHasDlgVideoDisplay = !videoDialog (lpcs->hVideoDisplay,
  357. lpcs->hwnd, VIDEO_DLG_QUERY);
  358. // these handles are not supported on WIN32 for the good reason that
  359. // the videoXXX api set is not published for 32-bit
  360. // we might want to make use of the handles ourselves...???
  361. lpcs->sCapDrvCaps.hVideoIn = NULL;
  362. lpcs->sCapDrvCaps.hVideoOut = NULL;
  363. lpcs->sCapDrvCaps.hVideoExtIn = NULL;
  364. lpcs->sCapDrvCaps.hVideoExtOut = NULL;
  365. return lpcs->fHardwareConnected;
  366. }
  367. //
  368. // Creates a child window of the capture class
  369. // Normally:
  370. // Set lpszWindowName to NULL
  371. // Set dwStyle to WS_CHILD | WS_VISIBLE
  372. // Set hmenu to a unique child id
  373. // Unicode and Win-16 version. See ansi thunk below
  374. HWND VFWAPI capCreateCaptureWindow (
  375. LPCTSTR lpszWindowName,
  376. DWORD dwStyle,
  377. int x, int y, int nWidth, int nHeight,
  378. HWND hwndParent, int nID)
  379. {
  380. DWORD dwExStyle;
  381. dwExStyle = gfIsRTL ? WS_EX_LEFTSCROLLBAR | WS_EX_RIGHT | WS_EX_RTLREADING : 0;
  382. RegisterCaptureClass(ghInstDll);
  383. #ifdef USE_AVIFILE
  384. AVIFileInit();
  385. #endif
  386. return CreateWindowEx(dwExStyle,
  387. szCaptureWindowClass,
  388. lpszWindowName,
  389. dwStyle,
  390. x, y, nWidth, nHeight,
  391. hwndParent, (HMENU) nID,
  392. ghInstDll,
  393. NULL);
  394. }
  395. #ifdef UNICODE
  396. // ansi thunk
  397. HWND VFWAPI capCreateCaptureWindowA (
  398. LPCSTR lpszWindowName,
  399. DWORD dwStyle,
  400. int x, int y, int nWidth, int nHeight,
  401. HWND hwndParent, int nID)
  402. {
  403. LPWSTR pw;
  404. int chsize;
  405. HWND hwnd;
  406. if (lpszWindowName == NULL) {
  407. pw = NULL;
  408. } else {
  409. // remember the null
  410. chsize = lstrlenA(lpszWindowName) + 1;
  411. pw = LocalLock(LocalAlloc(LPTR, chsize * sizeof(WCHAR)));
  412. AnsiToWide(pw, lpszWindowName, chsize);
  413. }
  414. hwnd = capCreateCaptureWindowW(pw, dwStyle, x, y, nWidth, nHeight,
  415. hwndParent, nID);
  416. if (pw != NULL) {
  417. LocalFree(LocalHandle(pw));
  418. }
  419. return(hwnd);
  420. }
  421. #endif
  422. #ifdef CHICAGO
  423. static char pszDll16[] = "AVICAP.DLL";
  424. static char pszDll32[] = "AVICAP32.DLL";
  425. BOOL PASCAL avicapf_ThunkConnect32(LPCSTR pszDll16, LPCSTR pszDll32, HINSTANCE hinst, DWORD dwReason);
  426. BOOL WINAPI DllMain(
  427. HANDLE hInstance,
  428. DWORD dwReason,
  429. LPVOID reserved)
  430. {
  431. #if defined DEBUG || defined DEBUG_RETAIL
  432. DebugSetOutputLevel (GetProfileInt ("Debug", "Avicap32", 0));
  433. AuxDebugEx (1, DEBUGLINE "DllEntryPoint, %08x,%08x,%08x\r\n", hInstance, dwReason, reserved);
  434. #endif
  435. if (dwReason == DLL_PROCESS_ATTACH)
  436. {
  437. char ach[2];
  438. ghInstDll = hInstance;
  439. LoadString(ghInstDll, IDS_CAP_RTL, ach, sizeof(ach));
  440. gfIsRTL = ach[0] == TEXT('1');
  441. // INLINE_BREAK;
  442. if (!avicapf_ThunkConnect32(pszDll16, pszDll32, hInstance, dwReason))
  443. return FALSE;
  444. #if defined _WIN32 && defined CHICAGO
  445. // we do this so that we can Get LinPageLock & PageAllocate services
  446. //
  447. ;
  448. // OpenMMDEVLDR();
  449. #endif
  450. }
  451. else if (dwReason == DLL_PROCESS_DETACH)
  452. {
  453. #if defined _WIN32 && defined CHICAGO
  454. ;
  455. // CloseMMDEVLDR();
  456. #endif
  457. return avicapf_ThunkConnect32(pszDll16, pszDll32, hInstance, dwReason);
  458. }
  459. return TRUE;
  460. }
  461. #else // this is the NT dll entry point
  462. BOOL DllInstanceInit(HANDLE hInstance, DWORD dwReason, LPVOID reserved)
  463. {
  464. if (dwReason == DLL_PROCESS_ATTACH) {
  465. TCHAR ach[2];
  466. ghInstDll = hInstance;
  467. DisableThreadLibraryCalls(hInstance);
  468. LoadString(ghInstDll, IDS_CAP_RTL, ach, NUMELMS(ach));
  469. gfIsRTL = ach[0] == TEXT('1');
  470. DebugSetOutputLevel (GetProfileIntA("Debug", "Avicap32", 0));
  471. videoInitHandleList();
  472. } else if (dwReason == DLL_PROCESS_DETACH) {
  473. videoDeleteHandleList();
  474. }
  475. return TRUE;
  476. }
  477. #endif // CHICAGO / NT dll entry point