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.

496 lines
13 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. handle.cpp
  5. Abstract:
  6. !handle using the debug engine handle query interface.
  7. --*/
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. char * AccessMask[] = { "Delete", "ReadControl", "WriteDac", "WriteOwner",
  11. "Synch", "", "", "",
  12. "Sacl", "MaxAllowed", "", "",
  13. "GenericAll", "GenericExec", "GenericWrite", "GenericRead"};
  14. char * TokenRights[] = {"AssignPrimary", "Duplicate", "Impersonate", "Query",
  15. "QuerySource", "AdjustPriv", "AdjustGroup", "AdjustDef"};
  16. char * KeyRights[] = { "QueryValue", "SetValue", "CreateSubKey", "EnumSubKey",
  17. "Notify", "CreateLink", "", "" };
  18. char * EventRights[] = {"QueryState", "ModifyState" };
  19. char * MutantRights[]={ "QueryState" };
  20. char * SemaphoreRights[] = { "QueryState", "ModifyState" };
  21. char * TimerRights[] = {"QueryState", "ModifyState" };
  22. char * ProfileRights[]={"Control"};
  23. char * ProcessRights[]={"Terminate", "CreateThread", "", "VMOp",
  24. "VMRead", "VMWrite", "DupHandle", "CreateProcess",
  25. "SetQuota", "SetInfo", "QueryInfo", "SetPort" };
  26. char * ThreadRights[] ={"Terminate", "Suspend", "Alert", "GetContext",
  27. "SetContext", "SetInfo", "QueryInfo", "SetToken",
  28. "Impersonate", "DirectImpersonate" };
  29. char * SectionRights[]={"Query", "MapWrite", "MapRead", "MapExecute",
  30. "Extend"};
  31. char * FileRights[] = { "Read/List", "Write/Add", "Append/SubDir/CreatePipe", "ReadEA",
  32. "WriteEA", "Execute/Traverse", "DelChild", "ReadAttr",
  33. "WriteAttr"};
  34. char * PortRights[] = { "Connect" };
  35. char * DirRights[] = { "Query", "Traverse", "Create", "CreateSubdir" };
  36. char * SymLinkRights[]={"Query" };
  37. char * WinstaRights[]={ "EnumDesktops", "ReadAttr", "Clipboard", "CreateDesktop",
  38. "WriteAttr", "GlobalAtom", "ExitWindows", "",
  39. "Enumerate", "ReadScreen" };
  40. char * DesktopRights[]={"ReadObjects", "CreateWindow", "CreateMenu", "HookControl",
  41. "JournalRecord", "JournalPlayback", "Enumerate", "WriteObjects",
  42. "SwitchDesktop" };
  43. char * CompletionRights[] = { "Query", "Modify" };
  44. char * ChannelRights[] = { "ReadMessage", "WriteMessage", "Query", "SetInfo" };
  45. char * JobRights[] = { "AssignProcess", "SetAttr", "Query", "Terminate", "SetSecAttr" };
  46. #define GHI_TYPE 0x00000001
  47. #define GHI_BASIC 0x00000002
  48. #define GHI_NAME 0x00000004
  49. #define GHI_SPECIFIC 0x00000008
  50. #define GHI_VERBOSE 0x00000010
  51. #define GHI_NOLOOKUP 0x00000020
  52. #define GHI_SILENT 0x00000100
  53. #define TYPE_NONE 0
  54. #define TYPE_EVENT 1
  55. #define TYPE_SECTION 2
  56. #define TYPE_FILE 3
  57. #define TYPE_PORT 4
  58. #define TYPE_DIRECTORY 5
  59. #define TYPE_LINK 6
  60. #define TYPE_MUTANT 7
  61. #define TYPE_WINSTA 8
  62. #define TYPE_SEM 9
  63. #define TYPE_KEY 10
  64. #define TYPE_TOKEN 11
  65. #define TYPE_PROCESS 12
  66. #define TYPE_THREAD 13
  67. #define TYPE_DESKTOP 14
  68. #define TYPE_COMPLETE 15
  69. #define TYPE_CHANNEL 16
  70. #define TYPE_TIMER 17
  71. #define TYPE_JOB 18
  72. #define TYPE_WPORT 19
  73. #define TYPE_MAX 20
  74. typedef struct _TYPEINFO
  75. {
  76. PSTR Name;
  77. char * * AccessRights;
  78. DWORD NumberRights;
  79. } TYPEINFO, * PTYPEINFO;
  80. TYPEINFO g_TypeNames[TYPE_MAX] =
  81. {
  82. { "None", NULL, 0 },
  83. { "Event", EventRights, 2 },
  84. { "Section", SectionRights, 5 },
  85. { "File", FileRights, 9 },
  86. { "Port", PortRights, 1 },
  87. { "Directory", DirRights, 4 },
  88. { "SymbolicLink", SymLinkRights, 1 },
  89. { "Mutant", MutantRights, 2 },
  90. { "WindowStation", WinstaRights, 10 },
  91. { "Semaphore", SemaphoreRights, 2 },
  92. { "Key", KeyRights, 6 },
  93. { "Token", TokenRights, 8 },
  94. { "Process", ProcessRights, 12 },
  95. { "Thread", ThreadRights, 10 },
  96. { "Desktop", DesktopRights, 10 },
  97. { "IoCompletion", CompletionRights, 2 },
  98. { "Channel", ChannelRights, 4},
  99. { "Timer", TimerRights, 2 },
  100. { "Job", JobRights, 5 },
  101. { "WaitablePort", PortRights, 1 }
  102. };
  103. void DisplayFlags( DWORD Flags,
  104. DWORD FlagLimit,
  105. char *flagset[],
  106. PSTR Buffer)
  107. {
  108. char * offset;
  109. DWORD mask, test, i;
  110. DWORD scratch;
  111. if (!Flags)
  112. {
  113. strcpy(Buffer, "None");
  114. return;
  115. }
  116. mask = 0;
  117. offset = Buffer;
  118. test = 1;
  119. for (i = 0 ; i < FlagLimit ; i++ )
  120. {
  121. if (Flags & test)
  122. {
  123. scratch = sprintf(offset, "%s", flagset[i]);
  124. offset += scratch;
  125. mask |= test;
  126. if (Flags & (~mask))
  127. {
  128. *offset++ = ',';
  129. }
  130. }
  131. test <<= 1;
  132. }
  133. }
  134. DWORD
  135. GetObjectTypeIndex(
  136. LPCSTR TypeName
  137. )
  138. {
  139. DWORD i;
  140. for ( i = 1 ; i < TYPE_MAX ; i++ )
  141. {
  142. if (_stricmp( g_TypeNames[i].Name, TypeName ) == 0 )
  143. {
  144. return( i );
  145. }
  146. }
  147. return( (DWORD) -1 );
  148. }
  149. DWORD
  150. GetHandleInfo(
  151. ULONG64 hThere,
  152. DWORD Flags,
  153. DWORD * Type)
  154. {
  155. HRESULT Status;
  156. DWORD SuccessCount = 0;
  157. DWORD i;
  158. UCHAR Buffer[1024];
  159. CHAR szBuf[256];
  160. if ( (Flags & GHI_SILENT) == 0)
  161. {
  162. dprintf("Handle %p\n", hThere );
  163. }
  164. if (Flags & GHI_TYPE)
  165. {
  166. if (g_ExtData->
  167. ReadHandleData(hThere,
  168. DEBUG_HANDLE_DATA_TYPE_TYPE_NAME,
  169. Buffer, sizeof(Buffer), NULL) == S_OK)
  170. {
  171. if ((Flags & GHI_SILENT) == 0)
  172. {
  173. dprintf(" Type \t%s\n", Buffer);
  174. }
  175. for (i = 1; i < TYPE_MAX ; i++)
  176. {
  177. if (strcmp((LPSTR)Buffer, g_TypeNames[i].Name) == 0)
  178. {
  179. *Type = i;
  180. break;
  181. }
  182. }
  183. if (i == TYPE_MAX)
  184. {
  185. *Type = 0;
  186. }
  187. SuccessCount++;
  188. }
  189. }
  190. if (Flags & GHI_BASIC)
  191. {
  192. DEBUG_HANDLE_DATA_BASIC Basic;
  193. if (g_ExtData->
  194. ReadHandleData(hThere,
  195. DEBUG_HANDLE_DATA_TYPE_BASIC,
  196. &Basic, sizeof(Basic), NULL) == S_OK)
  197. {
  198. dprintf(" Attributes \t%#x\n", Basic.Attributes );
  199. dprintf(" GrantedAccess\t%#x:\n", Basic.GrantedAccess );
  200. DisplayFlags( Basic.GrantedAccess >> 16,
  201. 16,
  202. AccessMask,
  203. szBuf);
  204. dprintf(" %s\n", szBuf);
  205. DisplayFlags( Basic.GrantedAccess & 0xFFFF,
  206. g_TypeNames[ *Type ].NumberRights,
  207. g_TypeNames[ *Type ].AccessRights,
  208. szBuf);
  209. dprintf(" %s\n", szBuf);
  210. dprintf(" HandleCount \t%d\n", Basic.HandleCount );
  211. dprintf(" PointerCount \t%d\n", Basic.PointerCount );
  212. SuccessCount++;
  213. }
  214. else
  215. {
  216. dprintf("unable to query object information\n");
  217. }
  218. }
  219. if ( (Flags & GHI_NAME) &&
  220. (*Type != TYPE_FILE ) )
  221. {
  222. if (g_ExtData->
  223. ReadHandleData(hThere,
  224. DEBUG_HANDLE_DATA_TYPE_OBJECT_NAME,
  225. Buffer, sizeof(Buffer), NULL) == S_OK)
  226. {
  227. dprintf(" Name \t%s\n",
  228. Buffer[0] ? (PSTR)Buffer : "<none>" );
  229. SuccessCount++;
  230. }
  231. else
  232. {
  233. dprintf("unable to query object information\n");
  234. }
  235. }
  236. if ( Flags & GHI_SPECIFIC )
  237. {
  238. dprintf(" No object specific information available\n");
  239. }
  240. return( SuccessCount );
  241. }
  242. /*++
  243. Routine Description:
  244. This function is called as an NTSD extension to mimic the !handle
  245. kd command. This will walk through the debuggee's handle table
  246. and duplicate the handle into the ntsd process, then call NtQueryobjectInfo
  247. to find out what it is.
  248. Called as:
  249. !handle [handle [flags [Type]]]
  250. If the handle is 0 or -1, all handles are scanned. If the handle is not
  251. zero, that particular handle is examined. The flags are as follows
  252. (corresponding to secexts.c):
  253. 1 - Get type information (default)
  254. 2 - Get basic information
  255. 4 - Get name information
  256. 8 - Get object specific info (where available)
  257. If Type is specified, only object of that type are scanned. Type is a
  258. standard NT type name, e.g. Event, Semaphore, etc. Case sensitive, of
  259. course.
  260. Examples:
  261. !handle -- dumps the types of all the handles, and a summary table
  262. !handle 0 0 -- dumps a summary table of all the open handles
  263. !handle 0 f -- dumps everything we can find about a handle.
  264. !handle 0 f Event
  265. -- dumps everything we can find about open events
  266. --*/
  267. DECLARE_API( handle )
  268. {
  269. ULONG64 hThere;
  270. DWORD Type;
  271. DWORD Mask;
  272. DWORD HandleCount;
  273. DWORD Total;
  274. DWORD TypeCounts[TYPE_MAX];
  275. DWORD Handle;
  276. DWORD Hits;
  277. DWORD Matches;
  278. DWORD ObjectType;
  279. ULONG SessionType;
  280. ULONG SessionQual;
  281. INIT_API();
  282. //
  283. // This particular implementation is only used for
  284. // dump debug sessions as more information can be
  285. // retrieved on live sessions via the NtQuery APIs.
  286. // If this isn't a dump session let the !handle
  287. // search continue on.
  288. //
  289. if (g_ExtControl == NULL ||
  290. g_ExtControl->
  291. GetDebuggeeType(&SessionType, &SessionQual) != S_OK)
  292. {
  293. SessionType = DEBUG_CLASS_USER_WINDOWS;
  294. SessionQual = DEBUG_USER_WINDOWS_PROCESS;
  295. }
  296. if (SessionType == DEBUG_CLASS_USER_WINDOWS &&
  297. SessionQual == DEBUG_USER_WINDOWS_PROCESS)
  298. {
  299. ExtRelease();
  300. return DEBUG_EXTENSION_CONTINUE_SEARCH;
  301. }
  302. Mask = GHI_TYPE;
  303. hThere = (ULONG64)(LONG_PTR)INVALID_HANDLE_VALUE;
  304. Type = 0;
  305. while (*args == ' ')
  306. {
  307. args++;
  308. }
  309. hThere = GetExpression( args );
  310. while (*args && (*args != ' ') )
  311. {
  312. args++;
  313. }
  314. while (*args == ' ')
  315. {
  316. args++;
  317. }
  318. if (*args)
  319. {
  320. Mask = (DWORD)GetExpression( args );
  321. }
  322. while (*args && (*args != ' ') )
  323. {
  324. args++;
  325. }
  326. while (*args == ' ')
  327. {
  328. args++;
  329. }
  330. if (*args)
  331. {
  332. Type = GetObjectTypeIndex( (LPSTR)args );
  333. if (Type == (DWORD) -1)
  334. {
  335. dprintf("Unknown type '%s'\n", args );
  336. goto Exit;
  337. }
  338. }
  339. //
  340. // if they specified 0, they just want the summary. Make sure nothing
  341. // sneaks out.
  342. //
  343. if ( Mask == 0 )
  344. {
  345. Mask = GHI_SILENT;
  346. }
  347. if (g_ExtData->
  348. ReadHandleData(0, DEBUG_HANDLE_DATA_TYPE_HANDLE_COUNT,
  349. &HandleCount, sizeof(HandleCount),
  350. NULL) != S_OK) {
  351. dprintf("Unable to read handle information\n");
  352. goto Exit;
  353. }
  354. //
  355. // hThere of 0 indicates all handles.
  356. //
  357. if ((hThere == 0) || (hThere == (ULONG64)(LONG_PTR)INVALID_HANDLE_VALUE))
  358. {
  359. Hits = 0;
  360. Handle = 0;
  361. Matches = 0;
  362. ZeroMemory( TypeCounts, sizeof(TypeCounts) );
  363. while ( Hits < HandleCount )
  364. {
  365. if ( Type )
  366. {
  367. if (GetHandleInfo( Handle,
  368. GHI_TYPE | GHI_SILENT,
  369. &ObjectType ) )
  370. {
  371. Hits++;
  372. if ( ObjectType == Type )
  373. {
  374. GetHandleInfo( Handle,
  375. Mask,
  376. &ObjectType );
  377. Matches ++;
  378. }
  379. }
  380. }
  381. else
  382. {
  383. if (GetHandleInfo( Handle,
  384. GHI_TYPE | GHI_SILENT,
  385. &ObjectType) )
  386. {
  387. Hits++;
  388. TypeCounts[ ObjectType ] ++;
  389. GetHandleInfo( Handle,
  390. Mask,
  391. &ObjectType );
  392. }
  393. }
  394. Handle += 4;
  395. }
  396. if ( Type == 0 )
  397. {
  398. dprintf( "%d Handles\n", Hits );
  399. dprintf( "Type \tCount\n");
  400. for (Type = 0; Type < TYPE_MAX ; Type++ )
  401. {
  402. if (TypeCounts[Type])
  403. {
  404. dprintf("%-15s\t%d\n",
  405. g_TypeNames[Type].Name, TypeCounts[Type]);
  406. }
  407. }
  408. }
  409. else
  410. {
  411. dprintf("%d handles of type %s\n",
  412. Matches, g_TypeNames[Type].Name );
  413. }
  414. }
  415. else
  416. {
  417. GetHandleInfo( hThere, Mask, &Type );
  418. }
  419. Exit:
  420. EXIT_API();
  421. return S_OK;
  422. }