Source code of Windows XP (NT5)
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.

639 lines
18 KiB

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