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.

625 lines
17 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: olethk32.cxx
  7. //
  8. // Contents: Main routines for olethk32.dll
  9. //
  10. // History: 22-Feb-94 DrewB Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "headers.cxx"
  14. #include <userapis.h>
  15. #pragma hdrstop
  16. #include <thkmgr.hxx>
  17. #include <stdio.h>
  18. DECLARE_INFOLEVEL(thk);
  19. DECLARE_INFOLEVEL(Stack);
  20. // Interop is disabled at load time
  21. DATA16 gdata16Data;
  22. BOOL gfIteropEnabled;
  23. #if DBG == 1
  24. BOOL fSaveProxy = FALSE; // Used to find apps who call dead proxies
  25. BOOL fStabilizeProxies = TRUE; // Used to easily disable stabilization
  26. BOOL fZapProxy = FALSE; // Used to zap entries in freelist
  27. #ifdef _CHICAGO_
  28. BOOL fSSOn = TRUE;
  29. #endif // _CHICAGO_
  30. #if defined(__cplusplus)
  31. extern "C"
  32. {
  33. #endif
  34. void CallOutputFunctions(const char *buffer);
  35. #if defined(__cplusplus)
  36. }
  37. #endif
  38. #endif
  39. CLIPFORMAT g_cfLinkSourceDescriptor, g_cfObjectDescriptor;
  40. BYTE g_abLeadTable[256];
  41. //+---------------------------------------------------------------------------
  42. //
  43. // Function: DoThreadDetach
  44. //
  45. // Synopsis: When a thread is detaching, cleanup for it.
  46. //
  47. // Effects: This is called during both DLL_THREAD_DETACH, and
  48. // DLL_PROCESS_DETACH.
  49. //
  50. // Arguments: (none)
  51. //
  52. // History: 3-18-95 kevinro Created
  53. //
  54. // Notes:
  55. //
  56. //----------------------------------------------------------------------------
  57. void
  58. DoThreadDetach()
  59. {
  60. thkDebugOut((DEB_DLL,"_IN DoThreadDetach\n"));
  61. //
  62. // If there is thunk data, clean it up now.
  63. //
  64. if (TlsGetValue(dwTlsThkIndex) != NULL)
  65. {
  66. thkDebugOut((DEB_DLL,"DoThreadDetach calling ThkMgrUninitialize\n"));
  67. ThkMgrUninitialize(0, 0, 0);
  68. }
  69. thkDebugOut((DEB_DLL,"OUT DoThreadDetach\n"));
  70. }
  71. //+---------------------------------------------------------------------------
  72. //
  73. // Function: LibMain, public
  74. //
  75. // Synopsis: DLL initialization entry point
  76. //
  77. // History: 23-Feb-94 DrewB Created
  78. //
  79. // Notes:
  80. //
  81. // (KevinRo 19-Mar-95)
  82. //
  83. // Caution needs to be exercised during cleanup. OLE32.DLL has
  84. // a pointer that we pass in during CoInitializeWOW. This pointer
  85. // is used to call back into OLETHK32 for cleanup purposes, as well as
  86. // accessing functions exposed by the 16-bit side. It is important that
  87. // when OLETHK32 unloads, the pointer in OLE32 is marked as invalid.
  88. // There is a call during the DLL_PROCESS_DETACH below that causes
  89. // OLE32 to invalidate its pointer.
  90. //
  91. // In addition, the last thread attached to a DLL will not generate
  92. // a DLL_THREAD_DETACH. Instead, it generates a DLL_PROCESS_DETACH. This
  93. // means that DLL_PROCESS_DETACH should perform all the steps that
  94. // DLL_THREAD_DETACH does in addition to whatever DLL_PROCESS_DETACH work
  95. // that needs to be done.
  96. //
  97. // Lastly, OLETHK32.DLL is statically linked to OLE32.DLL. This means
  98. // that OLETHK32.DLL's DLL_PROCESS_DETACH will be called before OLE32's.
  99. // That is why it is safe for us to call the OLE32 entry point during
  100. // DLL_PROCESS_DETACH
  101. //----------------------------------------------------------------------------
  102. extern "C" BOOL __cdecl LibMain(HANDLE hDll,
  103. DWORD dwReason,
  104. LPVOID lpReserved)
  105. {
  106. switch( dwReason )
  107. {
  108. case DLL_PROCESS_ATTACH:
  109. #if DBG == 1
  110. char achInfoLevel[80];
  111. if(thkInfoLevel == (DEB_ERROR | DEB_WARN) &&
  112. GetProfileStringA("olethk32", "InfoLevel", "3", achInfoLevel,
  113. sizeof(achInfoLevel)) > 0)
  114. {
  115. thkInfoLevel = strtol (achInfoLevel, NULL, 0);
  116. }
  117. #endif
  118. thkDebugOut((DEB_DLL,"_IN DLL_PROCESS_ATTACH\n"));
  119. //
  120. // Save a slot in the thread local storage for our PSTACK (pseudo-
  121. // stack) pointer.
  122. //
  123. if (!TlsThkAlloc())
  124. {
  125. thkDebugOut((DEB_WARN, "TlsThkAlloc failed\n"));
  126. return FALSE;
  127. }
  128. thkDebugOut((DEB_DLL,"OUT DLL_PROCESS_ATTACH\n"));
  129. break;
  130. case DLL_THREAD_ATTACH:
  131. thkDebugOut((DEB_DLL,"_IN DLL_THREAD_ATTACH\n"));
  132. TlsSetValue(dwTlsThkIndex, NULL);
  133. thkDebugOut((DEB_DLL,"OUT DLL_THREAD_ATTACH\n"));
  134. break;
  135. case DLL_THREAD_DETACH:
  136. thkDebugOut((DEB_DLL,"_IN DLL_THREAD_DETACH\n"));
  137. //
  138. // Call OLE32.DLL and tell it to cleanup for this thread. This will
  139. // not mark OLE32's ptr invalid since this is only a thread detach
  140. // and not a process detach. This is a private API between OLE32 and
  141. // OLETHK32.
  142. //
  143. thkDebugOut((DEB_DLL,"Calling Unload WOW for Thread Detach\n"));
  144. CoUnloadingWOW(FALSE);
  145. //
  146. // When the thread for this task goes away, we need to clean out
  147. // the thunk manager.
  148. //
  149. DoThreadDetach();
  150. thkDebugOut((DEB_DLL,"OUT DLL_THREAD_DETACH\n"));
  151. break;
  152. case DLL_PROCESS_DETACH:
  153. thkDebugOut((DEB_DLL,
  154. "IN DLL_PROCESS_DETACH: %s\n",
  155. lpReserved?"Process Exit":"Dll Unload"));
  156. //
  157. // The last threads cleanup needs to be done here.
  158. //
  159. if (lpReserved == NULL)
  160. {
  161. //
  162. // Call OLE32.DLL and tell it to cleanup for this thread, and to
  163. // never call us again, since we are going away. This is a private
  164. // API between OLE32 and OLETHK32. This call will mark OLE32's
  165. // private pointer to us as invalid.
  166. //
  167. thkDebugOut((DEB_DLL,"Calling Unload WOW\n"));
  168. CoUnloadingWOW(TRUE);
  169. //
  170. // lpReserved being NULL means this cleanup is due to
  171. // a FreeLibrary. If it was due to process exit, there
  172. // is no way for us to determine the state of the data
  173. // structures in the system. Other threads may have been
  174. // right smack in the middle of taking apart data structures.
  175. //
  176. //
  177. // Chicago unloads DLL's differently than NT. On Chicago, the
  178. // 32-bit side cleans up first, plus resources allocated on
  179. // the 32-bit side are released when the 16-bit process goes
  180. // away. On NT, the 16-bit process is treated like a thread,
  181. // so we have to cleanup.
  182. //
  183. #ifndef _CHICAGO_
  184. DoThreadDetach();
  185. #endif
  186. //
  187. // Only cleanup the memory if the process is not going away.
  188. // On Windows NT, there are cases when the NTVDM needs to be
  189. // blown away. We shouldn't be calling back to the 16-bit
  190. // side in this case. Therefore, we explicitly call free here
  191. // instead of putting it in the destructor.
  192. //
  193. flFreeList32.FreeMemoryBlocks();
  194. flHolderFreeList.FreeMemoryBlocks();
  195. flRequestFreeList.FreeMemoryBlocks();
  196. }
  197. TlsThkFree();
  198. //
  199. // Call to cleanup 16-bit memory if we are running on Win95.
  200. // This should free up the 16-bit memory associated with this
  201. // process. This is called in IntOpUninitialize on NT, since it
  202. // needs to be called before the 16-bit side goes away.
  203. //
  204. #ifdef _CHICAGO_
  205. flFreeList16.FreeMemoryBlocks();
  206. #endif
  207. thkDebugOut((DEB_DLL,"OUT DLL_PROCESS_DETACH\n"));
  208. break;
  209. }
  210. return TRUE;
  211. }
  212. //+---------------------------------------------------------------------------
  213. //
  214. // Function: IntOpInitialize, public
  215. //
  216. // Synopsis: Initializes the 32-bit interoperability code
  217. //
  218. // Arguments: [lpdata16] - 16-bit call data
  219. // [dw1] - Ignored
  220. // [dw2] - Ignored
  221. //
  222. // Returns: Appropriate status code
  223. //
  224. // History: 22-Feb-94 JohannP Created
  225. //
  226. //----------------------------------------------------------------------------
  227. STDAPI IntOpInitialize(LPDATA16 lpdata16, DWORD dw1, DWORD dw2)
  228. {
  229. int i;
  230. thkDebugOut((DEB_ITRACE | DEB_THUNKMGR, "_IN IntOpInitialize (%08lX)\n",
  231. lpdata16));
  232. thkAssert((THOP_LASTOP & ~THOP_OPMASK) == 0);
  233. #if DBG == 1
  234. char achInfoLevel[80];
  235. #ifdef _CHICAGO_
  236. if (GetProfileStringA("CairOLE InfoLevels",
  237. "Stack", "3", achInfoLevel,
  238. sizeof(achInfoLevel)) > 0)
  239. {
  240. StackInfoLevel = strtol (achInfoLevel, NULL, 0);
  241. }
  242. #endif // _CHICAGO_
  243. if (GetProfileIntA("olethk32", "BreakOnInit", FALSE))
  244. {
  245. // DebugBreak's in WOW are fatal unless the exception
  246. // is handled somehow. If a debugger is hooked up,
  247. // it'll get first crack at the break exception
  248. // If not, our handler will ignore the exception so
  249. // execution can continue
  250. __try
  251. {
  252. DebugBreak();
  253. }
  254. __except(EXCEPTION_EXECUTE_HANDLER)
  255. {
  256. }
  257. }
  258. fSaveProxy = GetProfileIntA("olethk32", "SaveProxy", FALSE);
  259. fZapProxy = GetProfileIntA("olethk32", "ZapProxy", FALSE);
  260. fStabilizeProxies = GetProfileIntA("olethk32", "Stabilize", TRUE);
  261. #endif
  262. // Copy passed parameter from 16-bit world...
  263. memcpy( (LPVOID)&gdata16Data, (LPVOID)lpdata16, sizeof( DATA16 ) );
  264. // Enable interop
  265. gfIteropEnabled = TRUE;
  266. #if defined(_CHICAGO_)
  267. g_cfObjectDescriptor =
  268. RegisterClipboardFormatA("Object Descriptor");
  269. g_cfLinkSourceDescriptor =
  270. RegisterClipboardFormatA("Link Source Descriptor");
  271. #else
  272. g_cfObjectDescriptor =
  273. (CLIPFORMAT) RegisterClipboardFormat(__TEXT("Object Descriptor"));
  274. g_cfLinkSourceDescriptor =
  275. (CLIPFORMAT) RegisterClipboardFormat(__TEXT("Link Source Descriptor"));
  276. #endif
  277. if (g_cfObjectDescriptor == 0 || g_cfLinkSourceDescriptor == 0)
  278. {
  279. thkDebugOut((DEB_WARN, "IntOpInitialize: "
  280. "Unable to register clipboard formats\n"));
  281. return E_UNEXPECTED;
  282. }
  283. // Create a lookup table for lead-byte-ness
  284. // so we can avoid calling IsDBCSLeadByte on every character
  285. // during string validation
  286. for (i = 0; i < 256; i++)
  287. {
  288. g_abLeadTable[i] = (BYTE)IsDBCSLeadByte((BYTE)i);
  289. }
  290. thkDebugOut((DEB_THUNKMGR | DEB_ITRACE, "OUT IntOpInitialize (%08lX)\n",
  291. lpdata16));
  292. return NOERROR;
  293. }
  294. //+---------------------------------------------------------------------------
  295. //
  296. // Function: IntOpUninitialize, public
  297. //
  298. // Synopsis: Cleanup initiated by 16-bit DLL unload
  299. //
  300. // Arguments: [dw1]
  301. // [dw2]
  302. // [dw3]
  303. //
  304. // History: 29-Nov-94 DrewB Created
  305. // 10-20-97 Gopalk Disabled interop as CompObj is no
  306. // longer present after this point
  307. //
  308. // Notes: (KevinRo) This routine is only called by compobj.dll. To make
  309. // things even more interesting, it is only called on Windows/NT. Win95
  310. // does the flFreeList16.FreeMemoryBlocks during PROCESS_DETACH. Cleanup
  311. // of the proxies is not neccessary on Win95, since the 16-bit process will
  312. // clean them up for us.
  313. //
  314. //----------------------------------------------------------------------------
  315. STDAPI IntOpUninitialize(DWORD dw1, DWORD dw2, DWORD dw3)
  316. {
  317. thkDebugOut((DEB_THUNKMGR | DEB_ITRACE, "_IN IntOpUninitialize\n"));
  318. #ifndef _CHICAGO_
  319. // Remove all existing proxies since we're going to free the
  320. // proxy memory in the next step
  321. if (TlsThkGetData() != NULL)
  322. {
  323. CThkMgr *ptm = TlsThkGetThkMgr();
  324. if (ptm)
  325. {
  326. ptm->RemoveAllProxies();
  327. }
  328. }
  329. // Clean up the 16-bit freelist at this time because we know
  330. // that 16-bit code is still active and available for callback
  331. // If we waited for the freelist destructor to be called, 16-bit
  332. // code would already be cleaned up and the WOWGlobalFree calls
  333. // would fail
  334. flFreeList16.FreeMemoryBlocks();
  335. // Disable interop
  336. gfIteropEnabled = FALSE;
  337. #if DBG==1
  338. // In debug builds zero out 16-bit callback function pointer so that
  339. // we fault in the 32-bit code if we call them hereafter
  340. memset( (LPVOID)&gdata16Data, 0, sizeof( DATA16 ) );
  341. #endif
  342. WgtDump();
  343. #else
  344. thkAssert(!"IntOpUninitialize called on Win95");
  345. #endif
  346. thkDebugOut((DEB_THUNKMGR | DEB_ITRACE, "OUT IntOpUninitialize\n"));
  347. return 0;
  348. }
  349. //+---------------------------------------------------------------------------
  350. //
  351. // Function: ConvertHr1632Thunk, public
  352. //
  353. // Synopsis: Trivial function to allow calling HRESULT conversion
  354. // functions from 16-bit
  355. //
  356. // Arguments: [hr] - HRESULT to convert
  357. // [dw1]
  358. // [dw2]
  359. //
  360. // Returns: Appropriate status code
  361. //
  362. // History: 26-Sep-94 DrewB Created
  363. //
  364. // Notes: Required because 16-bit calls to CallProc32W use three
  365. // arguments
  366. //
  367. //----------------------------------------------------------------------------
  368. STDAPI ConvertHr1632Thunk(HRESULT hr, DWORD dw1, DWORD dw2)
  369. {
  370. return TransformHRESULT_1632(hr);
  371. }
  372. //+---------------------------------------------------------------------------
  373. //
  374. // Function: ConvertHr3216Thunk, public
  375. //
  376. // Synopsis: Trivial function to allow calling HRESULT conversion
  377. // functions from 16-bit
  378. //
  379. // Arguments: [hr] - HRESULT to convert
  380. // [dw1]
  381. // [dw2]
  382. //
  383. // Returns: Appropriate status code
  384. //
  385. // History: 26-Sep-94 DrewB Created
  386. //
  387. // Notes: Required because 16-bit calls to CallProc32W use three
  388. // arguments
  389. //
  390. //----------------------------------------------------------------------------
  391. STDAPI ConvertHr3216Thunk(HRESULT hr, DWORD dw1, DWORD dw2)
  392. {
  393. return TransformHRESULT_3216(hr);
  394. }
  395. //+-------------------------------------------------------------------------
  396. //
  397. // Function: ThkAddAppCompatFlag
  398. //
  399. // Synopsis: Takes the given flag and ORs it into the current app
  400. // compatibility flag set
  401. //
  402. // Effects:
  403. //
  404. // Arguments: [dwFlag] -- flag to set
  405. //
  406. // Requires:
  407. //
  408. // Returns: void
  409. //
  410. // Signals:
  411. //
  412. // Modifies:
  413. //
  414. // Algorithm:
  415. //
  416. // History: dd-mmm-yy Author Comment
  417. // 15-Mar-95 alexgo author
  418. //
  419. // Notes: This function exists so that 16bit thunk dll's may
  420. // also set app compatibility flags. olethk32 code typically
  421. // sets the flags directly via TlsThkSetAppCompatFlags
  422. //
  423. //--------------------------------------------------------------------------
  424. STDAPI_(void) ThkAddAppCompatFlag( DWORD dwFlag )
  425. {
  426. DWORD dw;
  427. dw = TlsThkGetAppCompatFlags();
  428. dw |= dwFlag;
  429. TlsThkSetAppCompatFlags(dw);
  430. }
  431. #if DBG == 1
  432. static LONG _wgtAllocated = 0;
  433. //+---------------------------------------------------------------------------
  434. //
  435. // Function: WgtAllocLock, public debug
  436. //
  437. // Synopsis: Tracking for WOWGlobalAllocLock16
  438. //
  439. // History: 29-Nov-94 DrewB Created
  440. //
  441. //----------------------------------------------------------------------------
  442. VPVOID WgtAllocLock(WORD wFlags, DWORD cb, HMEM16 *ph)
  443. {
  444. HMEM16 h;
  445. VPVOID vpv;
  446. vpv = WOWGlobalAllocLock16(wFlags, cb, &h);
  447. if (vpv != 0)
  448. {
  449. #ifdef WGT_TRACK
  450. if (WOWGlobalLockSize16(h, &cb) != 0)
  451. {
  452. _wgtAllocated += cb;
  453. WOWGlobalUnlock16(h);
  454. }
  455. else
  456. {
  457. thkDebugOut((DEB_WARN,
  458. "Unable to get size of allocated block 0x%04lX\n",
  459. h));
  460. // This is a guess at how big a block Win16 will allocate
  461. _wgtAllocated += (cb+31) & 31;
  462. }
  463. #endif
  464. if (ph != NULL)
  465. {
  466. *ph = h;
  467. }
  468. }
  469. else
  470. {
  471. thkDebugOut((DEB_WARN,
  472. "Unable to allocate %d bytes of 16-bit memory\n",
  473. cb));
  474. }
  475. return vpv;
  476. }
  477. //+---------------------------------------------------------------------------
  478. //
  479. // Function: WgtUnlockFree, public
  480. //
  481. // Synopsis: Tracking for WOWGlobalUnlockFree16
  482. //
  483. // History: 29-Nov-94 DrewB Created
  484. //
  485. //----------------------------------------------------------------------------
  486. void WgtUnlockFree(VPVOID vpv)
  487. {
  488. HMEM16 h;
  489. DWORD cb;
  490. if (vpv == 0)
  491. {
  492. thkDebugOut((DEB_WARN, "Attempt to free NULL\n"));
  493. }
  494. else
  495. {
  496. #ifdef WGT_TRACK
  497. // Total hack, incorrect
  498. h = (HMEM16)(vpv >> 16);
  499. if (WOWGlobalLockSize16(h, &cb) != 0)
  500. {
  501. _wgtAllocated -= cb;
  502. WOWGlobalUnlock16(h);
  503. }
  504. else
  505. {
  506. thkDebugOut((DEB_WARN,
  507. "Unable to get size of allocated block 0x%04lX\n",
  508. h));
  509. }
  510. #endif
  511. WOWGlobalUnlockFree16(vpv);
  512. }
  513. }
  514. //+---------------------------------------------------------------------------
  515. //
  516. // Function: WgtDump, public
  517. //
  518. // Synopsis: Dumps global tracking information
  519. //
  520. // History: 29-Nov-94 DrewB Created
  521. //
  522. //----------------------------------------------------------------------------
  523. void WgtDump(void)
  524. {
  525. if (_wgtAllocated != 0)
  526. {
  527. thkDebugOut((DEB_WARN,
  528. "%d bytes of 16-bit memory currently allocated\n",
  529. _wgtAllocated));
  530. }
  531. }
  532. //+---------------------------------------------------------------------------
  533. //
  534. // Function: ThkCallOutputFunctions, public
  535. //
  536. // Synopsis: thunked pass-thru to Ole32 CallOutputFunctions for 16-bit land
  537. //
  538. // History: 23-Jan-95 murthys Created
  539. //
  540. //----------------------------------------------------------------------------
  541. void ThkCallOutputFunctions(const char * buffer, PVOID dummy1, PVOID dummy2)
  542. {
  543. CallOutputFunctions(buffer);
  544. }
  545. #endif // DBG == 1