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.

408 lines
10 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1994, Microsoft Corporation
  6. *
  7. * WOLE2.C
  8. * WOW32 Support for OLE2 stuff
  9. *
  10. * History:
  11. * Created 03-May-1994 by Bob Day (bobday)
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. MODNAME(wole.c);
  16. /*
  17. ** Under OLE 2.0, the IMessageFilter interface passes HTASKs/THREADIDs. It
  18. ** passes HTASKs in the 16-bit world, and THREADIDs in the 32-bit world. The
  19. ** OLE 2.0 16 <-> 32 interoperability DLLs need a way of converting the
  20. ** HTASK into an appropriate THREADID and back.
  21. **
  22. ** Really the only place the 16-bit code uses the HTASK is in ole2's BUSY.C
  23. ** module, wherein they take the HTASK and use TOOLHELP's TaskFindHandle
  24. ** to determine a HINST. Then they take the HINST and try and find its
  25. ** module name, and a top-level window handle. Using this, they bring up
  26. ** a nice dialog describing the task.
  27. **
  28. ** In the case when a 32-bit process's THREADID needs to be given into the
  29. ** 16-bit world as an htask, we create an htask alias (a GDT selector).
  30. ** We check for it in TaskFindHandle and return an HINST of exactly the
  31. ** same value (same GDT selector). We also check for this value in
  32. ** GetModuleFileName. Then, later, we make sure that any window operated on
  33. ** with GetWindowWord( GWW_HINST, ...) maps to exactly the same value if it
  34. ** is from a 32-bit process AND from the process which we created an alias
  35. ** for.
  36. **
  37. ** I've tried to make these routines general, so that later we might be able
  38. ** to really maintain HTASK aliases whenever we see a 32-bit THREADID, but
  39. ** it is too late before shipping to be able to test a general fix.
  40. **
  41. ** -BobDay
  42. **
  43. */
  44. #define MAP_SLOT_HTASK(slot) ((HTASK16)((WORD)0xffe0 - (8 * (slot))))
  45. #define MAP_HTASK_SLOT(htask) ((UINT)(((WORD)0xffe0 - (htask16))/8))
  46. typedef struct tagHTASKALIAS {
  47. DWORD dwThreadID32;
  48. DWORD dwProcessID32;
  49. union {
  50. FILETIME ftCreationTime;
  51. ULONGLONG ullCreationTime;
  52. };
  53. } HTASKALIAS;
  54. #define MAX_HTASKALIAS_SIZE 32 // 32 should be plenty
  55. HTASKALIAS *lphtaskalias = NULL;
  56. UINT cHtaskAliasCount = 0;
  57. BOOL GetThreadIDHTASKALIAS(
  58. DWORD dwThreadID32,
  59. HTASKALIAS *ha
  60. ) {
  61. OBJECT_ATTRIBUTES obja;
  62. THREAD_BASIC_INFORMATION ThreadInfo;
  63. HANDLE hThread;
  64. NTSTATUS Status;
  65. FILETIME ftDummy;
  66. CLIENT_ID cid;
  67. InitializeObjectAttributes(
  68. &obja,
  69. NULL,
  70. 0,
  71. NULL,
  72. 0 );
  73. cid.UniqueProcess = 0; // Don't know it, 0 means any process
  74. cid.UniqueThread = (HANDLE)dwThreadID32;
  75. Status = NtOpenThread(
  76. &hThread,
  77. THREAD_QUERY_INFORMATION,
  78. &obja,
  79. &cid );
  80. if ( !NT_SUCCESS(Status) ) {
  81. #if DBG
  82. DbgPrint("WOW32: Could not get open thread handle\n");
  83. #endif
  84. return( FALSE );
  85. }
  86. Status = NtQueryInformationThread(
  87. hThread,
  88. ThreadBasicInformation,
  89. (PVOID)&ThreadInfo,
  90. sizeof(THREAD_BASIC_INFORMATION),
  91. NULL
  92. );
  93. ha->dwProcessID32 = (DWORD)ThreadInfo.ClientId.UniqueProcess;
  94. ha->dwThreadID32 = dwThreadID32;
  95. GetThreadTimes( hThread,
  96. &ha->ftCreationTime,
  97. &ftDummy,
  98. &ftDummy,
  99. &ftDummy );
  100. Status = NtClose( hThread );
  101. if ( !NT_SUCCESS(Status) ) {
  102. #if DBG
  103. DbgPrint("WOW32: Could not close thread handle\n");
  104. DbgBreakPoint();
  105. #endif
  106. return( FALSE );
  107. }
  108. return( TRUE );
  109. }
  110. HTASK16 AddHtaskAlias(
  111. DWORD ThreadID32
  112. ) {
  113. UINT iSlot;
  114. UINT iUsable;
  115. HTASKALIAS ha;
  116. ULONGLONG ullOldest;
  117. if ( !GetThreadIDHTASKALIAS( ThreadID32, &ha ) ) {
  118. return( 0 );
  119. }
  120. //
  121. // Need to allocate the alias table?
  122. //
  123. if ( lphtaskalias == NULL ) {
  124. lphtaskalias = (HTASKALIAS *) malloc_w( MAX_HTASKALIAS_SIZE * sizeof(HTASKALIAS) );
  125. if ( lphtaskalias == NULL ) {
  126. LOGDEBUG(LOG_ALWAYS,("WOW::AddHtaskAlias : Failed to allocate memory\n"));
  127. WOW32ASSERT(FALSE);
  128. return( 0 );
  129. }
  130. // Zero them out initially
  131. memset( lphtaskalias, 0, MAX_HTASKALIAS_SIZE * sizeof(HTASKALIAS) );
  132. }
  133. //
  134. // Now iterate through the alias table, either finding an available slot,
  135. // or finding the oldest one there to overwrite.
  136. //
  137. iSlot = 0;
  138. iUsable = 0;
  139. ullOldest = -1;
  140. while ( iSlot < MAX_HTASKALIAS_SIZE ) {
  141. //
  142. // Did we find an available slot?
  143. //
  144. if ( lphtaskalias[iSlot].dwThreadID32 == 0 ) {
  145. cHtaskAliasCount++; // Using an available slot
  146. iUsable = iSlot;
  147. break;
  148. }
  149. //
  150. // Remember the oldest guy
  151. //
  152. if ( lphtaskalias[iSlot].ullCreationTime < ullOldest ) {
  153. ullOldest = lphtaskalias[iSlot].ullCreationTime;
  154. iUsable = iSlot;
  155. }
  156. iSlot++;
  157. }
  158. //
  159. // If the above loop is exitted due to not enough space, then
  160. // iUsable will be the oldest one. If it was exitted because we found
  161. // an empty slot, then iUsable will be the slot.
  162. //
  163. lphtaskalias[iUsable] = ha;
  164. return( MAP_SLOT_HTASK(iUsable) );
  165. }
  166. HTASK16 FindHtaskAlias(
  167. DWORD ThreadID32
  168. ) {
  169. UINT iSlot;
  170. if ( lphtaskalias == NULL || ThreadID32 == 0 ) {
  171. return( 0 );
  172. }
  173. iSlot = MAX_HTASKALIAS_SIZE;
  174. while ( iSlot > 0 ) {
  175. --iSlot;
  176. //
  177. // Did we find the appropriate guy?
  178. //
  179. if ( lphtaskalias[iSlot].dwThreadID32 == ThreadID32 ) {
  180. return( MAP_SLOT_HTASK(iSlot) );
  181. }
  182. }
  183. return( 0 );
  184. }
  185. void RemoveHtaskAlias(
  186. HTASK16 htask16
  187. ) {
  188. UINT iSlot;
  189. //
  190. // Get out early if we haven't any aliases
  191. //
  192. if ( lphtaskalias == NULL || (!htask16)) {
  193. return;
  194. }
  195. iSlot = MAP_HTASK_SLOT(htask16);
  196. if (iSlot >= MAX_HTASKALIAS_SIZE) {
  197. LOGDEBUG(LOG_ALWAYS, ("WOW::RemoveHtaskAlias : iSlot >= MAX_TASK_ALIAS_SIZE\n"));
  198. WOW32ASSERT(FALSE);
  199. return;
  200. }
  201. //
  202. // Zap the entry from the list
  203. //
  204. if (lphtaskalias[iSlot].dwThreadID32) {
  205. lphtaskalias[iSlot].dwThreadID32 = 0;
  206. lphtaskalias[iSlot].dwProcessID32 = 0;
  207. lphtaskalias[iSlot].ullCreationTime = 0;
  208. --cHtaskAliasCount;
  209. }
  210. }
  211. DWORD GetHtaskAlias(
  212. HTASK16 htask16,
  213. LPDWORD lpProcessID32
  214. ) {
  215. UINT iSlot;
  216. DWORD ThreadID32;
  217. HTASKALIAS ha;
  218. ha.dwProcessID32 = 0;
  219. ThreadID32 = 0;
  220. if ( ! ISTASKALIAS(htask16) ) {
  221. goto Done;
  222. }
  223. iSlot = MAP_HTASK_SLOT(htask16);
  224. if ( iSlot >= MAX_HTASKALIAS_SIZE ) {
  225. WOW32ASSERTMSGF(FALSE, ("WOW::GetHtaskAlias : iSlot >= MAX_TASK_ALIAS_SIZE\n"));
  226. goto Done;
  227. }
  228. ThreadID32 = lphtaskalias[iSlot].dwThreadID32;
  229. //
  230. // Make sure the thread still exists in the system
  231. //
  232. if ( ! GetThreadIDHTASKALIAS( ThreadID32, &ha ) ||
  233. ha.ullCreationTime != lphtaskalias[iSlot].ullCreationTime ||
  234. ha.dwProcessID32 != lphtaskalias[iSlot].dwProcessID32 ) {
  235. RemoveHtaskAlias( htask16 );
  236. ha.dwProcessID32 = 0;
  237. ThreadID32 = 0;
  238. }
  239. if ( lpProcessID32 ) {
  240. *lpProcessID32 = ha.dwProcessID32;
  241. }
  242. Done:
  243. return ThreadID32;
  244. }
  245. UINT GetHtaskAliasProcessName(
  246. HTASK16 htask16,
  247. LPSTR lpNameBuffer,
  248. UINT cNameBufferSize
  249. ) {
  250. DWORD dwThreadID32;
  251. DWORD dwProcessID32;
  252. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  253. PUCHAR pucLargeBuffer;
  254. ULONG LargeBufferSize = 32*1024;
  255. NTSTATUS status = STATUS_INFO_LENGTH_MISMATCH;
  256. ULONG TotalOffset;
  257. dwThreadID32 = GetHtaskAlias(htask16, &dwProcessID32);
  258. if ( dwThreadID32 == 0 ||
  259. cNameBufferSize == 0 ||
  260. lpNameBuffer == NULL ) {
  261. return 0;
  262. }
  263. while(status == STATUS_INFO_LENGTH_MISMATCH) {
  264. pucLargeBuffer = VirtualAlloc(NULL,
  265. LargeBufferSize,
  266. MEM_COMMIT,
  267. PAGE_READWRITE);
  268. if (pucLargeBuffer == NULL) {
  269. WOW32ASSERTMSGF((FALSE),
  270. ("WOW::GetHtaskAliasProcessName: VirtualAlloc(%x) failed %x.\n",
  271. LargeBufferSize));
  272. return 0;
  273. }
  274. status = NtQuerySystemInformation(SystemProcessInformation,
  275. pucLargeBuffer,
  276. LargeBufferSize,
  277. &TotalOffset);
  278. if (NT_SUCCESS(status)) {
  279. break;
  280. }
  281. else if (status == STATUS_INFO_LENGTH_MISMATCH) {
  282. LargeBufferSize += 8192;
  283. VirtualFree (pucLargeBuffer, 0, MEM_RELEASE);
  284. pucLargeBuffer = NULL;
  285. }
  286. else {
  287. WOW32ASSERTMSGF((NT_SUCCESS(status)),
  288. ("WOW::GetHtaskAliasProcessName: NtQuerySystemInformation failed %x.\n",
  289. status));
  290. if(pucLargeBuffer) {
  291. VirtualFree (pucLargeBuffer, 0, MEM_RELEASE);
  292. }
  293. return 0;
  294. }
  295. }
  296. //
  297. // Iterate through the returned list of process information structures,
  298. // trying to find the one with the right process id.
  299. //
  300. TotalOffset = 0;
  301. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)pucLargeBuffer;
  302. while (TRUE) {
  303. if ( (DWORD)ProcessInfo->UniqueProcessId == dwProcessID32 ) {
  304. //
  305. // Found it, return the name.
  306. //
  307. if ( ProcessInfo->ImageName.Buffer ) {
  308. cNameBufferSize =
  309. WideCharToMultiByte(
  310. CP_ACP,
  311. 0,
  312. ProcessInfo->ImageName.Buffer, // src
  313. ProcessInfo->ImageName.Length,
  314. lpNameBuffer, // dest
  315. cNameBufferSize,
  316. NULL,
  317. NULL
  318. );
  319. lpNameBuffer[cNameBufferSize] = '\0';
  320. return cNameBufferSize;
  321. } else {
  322. //
  323. // Don't let them get the name of a system process
  324. //
  325. return 0;
  326. }
  327. }
  328. if (ProcessInfo->NextEntryOffset == 0) {
  329. break;
  330. }
  331. TotalOffset += ProcessInfo->NextEntryOffset;
  332. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&pucLargeBuffer[TotalOffset];
  333. }
  334. return 0;
  335. }