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.

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