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.

528 lines
14 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. char * DebugObjectRights[] = { "ReadEvent", "ProcessAssign",
  47. "SetInformation", "QueryInformation" };
  48. char * KeyedEventRights[] = { "Wait", "Wake" };
  49. #define GHI_TYPE 0x00000001
  50. #define GHI_BASIC 0x00000002
  51. #define GHI_NAME 0x00000004
  52. #define GHI_SPECIFIC 0x00000008
  53. #define GHI_VERBOSE 0x00000010
  54. #define GHI_NOLOOKUP 0x00000020
  55. #define GHI_SILENT 0x00000100
  56. #define TYPE_NONE 0
  57. #define TYPE_EVENT 1
  58. #define TYPE_SECTION 2
  59. #define TYPE_FILE 3
  60. #define TYPE_PORT 4
  61. #define TYPE_DIRECTORY 5
  62. #define TYPE_LINK 6
  63. #define TYPE_MUTANT 7
  64. #define TYPE_WINSTA 8
  65. #define TYPE_SEM 9
  66. #define TYPE_KEY 10
  67. #define TYPE_TOKEN 11
  68. #define TYPE_PROCESS 12
  69. #define TYPE_THREAD 13
  70. #define TYPE_DESKTOP 14
  71. #define TYPE_COMPLETE 15
  72. #define TYPE_CHANNEL 16
  73. #define TYPE_TIMER 17
  74. #define TYPE_JOB 18
  75. #define TYPE_WPORT 19
  76. #define TYPE_DEBUG_OBJECT 20
  77. #define TYPE_KEYED_EVENT 21
  78. #define TYPE_MAX 22
  79. typedef struct _TYPEINFO
  80. {
  81. PSTR Name;
  82. char * * AccessRights;
  83. DWORD NumberRights;
  84. } TYPEINFO, * PTYPEINFO;
  85. TYPEINFO g_TypeNames[TYPE_MAX] =
  86. {
  87. { "None", NULL, 0 },
  88. { "Event", EventRights, 2 },
  89. { "Section", SectionRights, 5 },
  90. { "File", FileRights, 9 },
  91. { "Port", PortRights, 1 },
  92. { "Directory", DirRights, 4 },
  93. { "SymbolicLink", SymLinkRights, 1 },
  94. { "Mutant", MutantRights, 2 },
  95. { "WindowStation", WinstaRights, 10 },
  96. { "Semaphore", SemaphoreRights, 2 },
  97. { "Key", KeyRights, 6 },
  98. { "Token", TokenRights, 8 },
  99. { "Process", ProcessRights, 12 },
  100. { "Thread", ThreadRights, 10 },
  101. { "Desktop", DesktopRights, 10 },
  102. { "IoCompletion", CompletionRights, 2 },
  103. { "Channel", ChannelRights, 4},
  104. { "Timer", TimerRights, 2 },
  105. { "Job", JobRights, 5 },
  106. { "WaitablePort", PortRights, 1 },
  107. { "DebugObject", DebugObjectRights, 4 },
  108. { "KeyedEvent", KeyedEventRights, 2 }
  109. };
  110. void DisplayFlags( DWORD Flags,
  111. DWORD FlagLimit,
  112. char *flagset[],
  113. PSTR Buffer)
  114. {
  115. char * offset;
  116. DWORD mask, test, i;
  117. DWORD scratch;
  118. if (!Flags)
  119. {
  120. strcpy(Buffer, "None");
  121. return;
  122. }
  123. mask = 0;
  124. offset = Buffer;
  125. test = 1;
  126. for (i = 0 ; i < FlagLimit ; i++ )
  127. {
  128. if (Flags & test)
  129. {
  130. scratch = strlen(flagset[i]);
  131. memcpy(offset, flagset[i], scratch + 1);
  132. offset += scratch;
  133. mask |= test;
  134. if (Flags & (~mask))
  135. {
  136. *offset++ = ',';
  137. }
  138. }
  139. test <<= 1;
  140. }
  141. }
  142. DWORD
  143. GetObjectTypeIndex(
  144. LPCSTR TypeName
  145. )
  146. {
  147. DWORD i;
  148. for ( i = 1 ; i < TYPE_MAX ; i++ )
  149. {
  150. if (_stricmp( g_TypeNames[i].Name, TypeName ) == 0 )
  151. {
  152. return( i );
  153. }
  154. }
  155. return( (DWORD) -1 );
  156. }
  157. DWORD
  158. GetHandleInfo(
  159. ULONG64 hThere,
  160. DWORD Flags,
  161. DWORD * Type)
  162. {
  163. HRESULT Status;
  164. DWORD SuccessCount = 0;
  165. DWORD i;
  166. CHAR Buffer[1024];
  167. CHAR szBuf[256];
  168. if ( (Flags & GHI_SILENT) == 0)
  169. {
  170. dprintf("Handle %p\n", hThere );
  171. }
  172. *Type = 0;
  173. if (Flags & (GHI_TYPE | GHI_NAME))
  174. {
  175. if (g_ExtData->
  176. ReadHandleData(hThere,
  177. DEBUG_HANDLE_DATA_TYPE_TYPE_NAME,
  178. Buffer, sizeof(Buffer), NULL) == S_OK)
  179. {
  180. // We were able to get a type, so count this
  181. // as success even if we can't identify the type name.
  182. if (Flags & GHI_TYPE)
  183. {
  184. SuccessCount++;
  185. }
  186. for (i = 1; i < TYPE_MAX ; i++)
  187. {
  188. if (strcmp(Buffer, g_TypeNames[i].Name) == 0)
  189. {
  190. *Type = i;
  191. break;
  192. }
  193. }
  194. }
  195. else
  196. {
  197. strcpy(Buffer, "<Error retrieving type>");
  198. }
  199. if (Flags & GHI_TYPE)
  200. {
  201. if ((Flags & GHI_SILENT) == 0)
  202. {
  203. dprintf(" Type \t%s\n", Buffer);
  204. }
  205. }
  206. }
  207. if (Flags & GHI_BASIC)
  208. {
  209. DEBUG_HANDLE_DATA_BASIC Basic;
  210. if (g_ExtData->
  211. ReadHandleData(hThere,
  212. DEBUG_HANDLE_DATA_TYPE_BASIC,
  213. &Basic, sizeof(Basic), NULL) == S_OK)
  214. {
  215. dprintf(" Attributes \t%#x\n", Basic.Attributes );
  216. dprintf(" GrantedAccess\t%#x:\n", Basic.GrantedAccess );
  217. DisplayFlags( Basic.GrantedAccess >> 16,
  218. 16,
  219. AccessMask,
  220. szBuf);
  221. dprintf(" %s\n", szBuf);
  222. DisplayFlags( Basic.GrantedAccess & 0xFFFF,
  223. g_TypeNames[ *Type ].NumberRights,
  224. g_TypeNames[ *Type ].AccessRights,
  225. szBuf);
  226. dprintf(" %s\n", szBuf);
  227. dprintf(" HandleCount \t%d\n", Basic.HandleCount );
  228. dprintf(" PointerCount \t%d\n", Basic.PointerCount );
  229. SuccessCount++;
  230. }
  231. else
  232. {
  233. dprintf("unable to query object information\n");
  234. }
  235. }
  236. if ((Flags & GHI_NAME) &&
  237. *Type != TYPE_FILE)
  238. {
  239. if (g_ExtData->
  240. ReadHandleData(hThere,
  241. DEBUG_HANDLE_DATA_TYPE_OBJECT_NAME,
  242. Buffer, sizeof(Buffer), NULL) == S_OK)
  243. {
  244. dprintf(" Name \t%s\n",
  245. Buffer[0] ? Buffer : "<none>" );
  246. SuccessCount++;
  247. }
  248. else
  249. {
  250. dprintf("unable to query object information\n");
  251. }
  252. }
  253. if ( Flags & GHI_SPECIFIC )
  254. {
  255. dprintf(" No object specific information available\n");
  256. }
  257. return( SuccessCount );
  258. }
  259. /*++
  260. Routine Description:
  261. This function is called as an NTSD extension to mimic the !handle
  262. kd command. This will walk through the debuggee's handle table
  263. and duplicate the handle into the ntsd process, then call NtQueryobjectInfo
  264. to find out what it is.
  265. Called as:
  266. !handle [handle [flags [Type]]]
  267. If the handle is 0 or -1, all handles are scanned. If the handle is not
  268. zero, that particular handle is examined. The flags are as follows
  269. (corresponding to secexts.c):
  270. 1 - Get type information (default)
  271. 2 - Get basic information
  272. 4 - Get name information
  273. 8 - Get object specific info (where available)
  274. If Type is specified, only object of that type are scanned. Type is a
  275. standard NT type name, e.g. Event, Semaphore, etc. Case sensitive, of
  276. course.
  277. Examples:
  278. !handle -- dumps the types of all the handles, and a summary table
  279. !handle 0 0 -- dumps a summary table of all the open handles
  280. !handle 0 f -- dumps everything we can find about a handle.
  281. !handle 0 f Event
  282. -- dumps everything we can find about open events
  283. --*/
  284. DECLARE_API( handle )
  285. {
  286. ULONG64 hThere;
  287. DWORD Type;
  288. DWORD Mask;
  289. DWORD HandleCount;
  290. DWORD Total;
  291. DWORD TypeCounts[TYPE_MAX];
  292. DWORD Handle;
  293. DWORD Hits;
  294. DWORD Matches;
  295. DWORD ObjectType;
  296. ULONG SessionType;
  297. ULONG SessionQual;
  298. INIT_API();
  299. //
  300. // This particular implementation is only used for
  301. // dump debug sessions as more information can be
  302. // retrieved on live sessions via the NtQuery APIs.
  303. // If this isn't a dump session let the !handle
  304. // search continue on.
  305. //
  306. if (g_ExtControl == NULL ||
  307. g_ExtControl->
  308. GetDebuggeeType(&SessionType, &SessionQual) != S_OK)
  309. {
  310. SessionType = DEBUG_CLASS_USER_WINDOWS;
  311. SessionQual = DEBUG_USER_WINDOWS_PROCESS;
  312. }
  313. if (SessionType == DEBUG_CLASS_USER_WINDOWS &&
  314. SessionQual == DEBUG_USER_WINDOWS_PROCESS)
  315. {
  316. ExtRelease();
  317. return DEBUG_EXTENSION_CONTINUE_SEARCH;
  318. }
  319. Mask = GHI_TYPE;
  320. hThere = (ULONG64)(LONG_PTR)INVALID_HANDLE_VALUE;
  321. Type = 0;
  322. while (*args == ' ')
  323. {
  324. args++;
  325. }
  326. if ( strcmp( args, "-?" ) == 0 )
  327. {
  328. ExtRelease();
  329. return DEBUG_EXTENSION_CONTINUE_SEARCH;
  330. }
  331. hThere = GetExpression( args );
  332. while (*args && (*args != ' ') )
  333. {
  334. args++;
  335. }
  336. while (*args == ' ')
  337. {
  338. args++;
  339. }
  340. if (*args)
  341. {
  342. Mask = (DWORD)GetExpression( args );
  343. }
  344. while (*args && (*args != ' ') )
  345. {
  346. args++;
  347. }
  348. while (*args == ' ')
  349. {
  350. args++;
  351. }
  352. if (*args)
  353. {
  354. Type = GetObjectTypeIndex( (LPSTR)args );
  355. if (Type == (DWORD) -1)
  356. {
  357. dprintf("Unknown type '%s'\n", args );
  358. goto Exit;
  359. }
  360. }
  361. //
  362. // if they specified 0, they just want the summary. Make sure nothing
  363. // sneaks out.
  364. //
  365. if ( Mask == 0 )
  366. {
  367. Mask = GHI_SILENT;
  368. }
  369. if (g_ExtData->
  370. ReadHandleData(0, DEBUG_HANDLE_DATA_TYPE_HANDLE_COUNT,
  371. &HandleCount, sizeof(HandleCount),
  372. NULL) != S_OK) {
  373. dprintf("Unable to read handle information\n");
  374. goto Exit;
  375. }
  376. //
  377. // hThere of 0 indicates all handles.
  378. //
  379. if ((hThere == 0) || (hThere == (ULONG64)(LONG_PTR)INVALID_HANDLE_VALUE))
  380. {
  381. Hits = 0;
  382. Handle = 0;
  383. Matches = 0;
  384. ZeroMemory( TypeCounts, sizeof(TypeCounts) );
  385. while ( Hits < HandleCount )
  386. {
  387. if (CheckControlC())
  388. {
  389. break;
  390. }
  391. if ( Type )
  392. {
  393. if (GetHandleInfo( Handle,
  394. GHI_TYPE | GHI_SILENT,
  395. &ObjectType ) )
  396. {
  397. Hits++;
  398. if ( ObjectType == Type )
  399. {
  400. GetHandleInfo( Handle,
  401. Mask,
  402. &ObjectType );
  403. Matches ++;
  404. }
  405. }
  406. }
  407. else
  408. {
  409. if (GetHandleInfo( Handle,
  410. GHI_TYPE | GHI_SILENT,
  411. &ObjectType) )
  412. {
  413. Hits++;
  414. TypeCounts[ ObjectType ] ++;
  415. GetHandleInfo( Handle,
  416. Mask,
  417. &ObjectType );
  418. }
  419. }
  420. Handle += 4;
  421. }
  422. if ( Type == 0 )
  423. {
  424. dprintf( "%d Handles\n", Hits );
  425. dprintf( "Type \tCount\n");
  426. for (Type = 0; Type < TYPE_MAX ; Type++ )
  427. {
  428. if (TypeCounts[Type])
  429. {
  430. dprintf("%-15s\t%d\n",
  431. g_TypeNames[Type].Name, TypeCounts[Type]);
  432. }
  433. }
  434. }
  435. else
  436. {
  437. dprintf("%d handles of type %s\n",
  438. Matches, g_TypeNames[Type].Name );
  439. }
  440. }
  441. else
  442. {
  443. GetHandleInfo( hThere, Mask, &Type );
  444. }
  445. Exit:
  446. EXIT_API();
  447. return S_OK;
  448. }