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.

672 lines
20 KiB

  1. /* object.c -
  2. *
  3. * Handles display of object attributes
  4. */
  5. #include <nt.h>
  6. #include <ntrtl.h>
  7. #include <nturtl.h>
  8. #include <stdio.h>
  9. #include "winfile.h"
  10. #include "object.h"
  11. INT_PTR APIENTRY ObjectAttributesDlgProc(HWND, UINT, WPARAM, LPARAM);
  12. BOOL ObjectInformationDlgInit(HWND, LPSTR);
  13. HANDLE OpenObject(HWND, LPSTR);
  14. BOOL GetObjectInfo(HWND, HANDLE);
  15. VOID CloseObject(HANDLE);
  16. VOID StripObjectPath(LPSTR lpszPath);
  17. VOID StripObjectSpec(LPSTR lpszPath);
  18. // Define known object type names
  19. #define DIRECTORYTYPE L"Directory"
  20. #define SYMLINKTYPE L"SymbolicLink"
  21. #define ADAPTERTYPE L"Adapter"
  22. #define CONTROLLERTYPE L"Controller"
  23. #define DEVICETYPE L"Device"
  24. #define DRIVERTYPE L"Driver"
  25. #define EVENTTYPE L"Event"
  26. #define EVENTPAIRTYPE L"EventPair"
  27. #define FILETYPE L"File"
  28. #define MUTANTTYPE L"Mutant"
  29. #define PORTTYPE L"Port"
  30. #define PROFILETYPE L"Profile"
  31. #define SECTIONTYPE L"Section"
  32. #define SEMAPHORETYPE L"Semaphore"
  33. #define TIMERTYPE L"Timer"
  34. #define TYPETYPE L"Type"
  35. #define PROCESSTYPE L"Process"
  36. VOID
  37. DisplayObjectInformation(
  38. HWND hwndParent,
  39. LPSTR lpstrObject
  40. )
  41. {
  42. WNDPROC lpProc;
  43. HANDLE hInst = hAppInstance;
  44. DialogBoxParam(hInst,(LPSTR)IDD_OBJATTRS, hwndParent, ObjectAttributesDlgProc, (LPARAM)lpstrObject);
  45. }
  46. INT_PTR
  47. APIENTRY
  48. ObjectAttributesDlgProc(
  49. HWND hDlg,
  50. UINT message,
  51. WPARAM wParam,
  52. LPARAM lParam
  53. )
  54. {
  55. switch (message) {
  56. case WM_INITDIALOG:
  57. if (!ObjectInformationDlgInit(hDlg, (HANDLE)lParam)) {
  58. // Failed to initialize dialog, get out
  59. EndDialog(hDlg, FALSE);
  60. }
  61. return (TRUE);
  62. case WM_COMMAND:
  63. switch (LOWORD(wParam)) {
  64. case IDOK:
  65. // we're done, drop through to quit dialog....
  66. case IDCANCEL:
  67. //MainDlgEnd(hDlg, LOWORD(wParam) == IDOK);
  68. EndDialog(hDlg, TRUE);
  69. return TRUE;
  70. break;
  71. default:
  72. // We didn't process this message
  73. return FALSE;
  74. break;
  75. }
  76. break;
  77. default:
  78. // We didn't process this message
  79. return FALSE;
  80. }
  81. // We processed the message
  82. return TRUE;
  83. }
  84. BOOL
  85. ObjectInformationDlgInit(
  86. HWND hwnd,
  87. LPSTR lpstrObject
  88. )
  89. {
  90. HANDLE ObjectHandle;
  91. BOOL Result;
  92. ObjectHandle = OpenObject(hwnd, lpstrObject);
  93. if (ObjectHandle == NULL) {
  94. return(FALSE);
  95. }
  96. Result = GetObjectInfo(hwnd, ObjectHandle);
  97. CloseObject(ObjectHandle);
  98. return(Result);
  99. }
  100. /* Open the object given only its name.
  101. * First find the object type by enumerating the directory entries.
  102. * Then call the type-specific open routine to get a handle
  103. */
  104. HANDLE
  105. OpenObject(
  106. HWND hwnd,
  107. LPSTR lpstrObject
  108. )
  109. {
  110. #define BUFFER_SIZE 1024
  111. NTSTATUS Status;
  112. HANDLE DirectoryHandle;
  113. ULONG Context = 0;
  114. ULONG ReturnedLength;
  115. CHAR Buffer[BUFFER_SIZE];
  116. ANSI_STRING AnsiString;
  117. POBJECT_DIRECTORY_INFORMATION DirInfo;
  118. WCHAR ObjectNameBuf[MAX_PATH];
  119. UNICODE_STRING ObjectName;
  120. WCHAR ObjectTypeBuf[MAX_PATH];
  121. UNICODE_STRING ObjectType;
  122. HANDLE ObjectHandle;
  123. OBJECT_ATTRIBUTES Attributes;
  124. UNICODE_STRING DirectoryName;
  125. IO_STATUS_BLOCK IOStatusBlock;
  126. //DbgPrint("Open object: raw full name = <%s>\n", lpstrObject);
  127. // Remove drive letter
  128. while ((*lpstrObject != 0) && (*lpstrObject != '\\')) {
  129. lpstrObject ++;
  130. }
  131. //DbgPrint("Open object: full name = <%s>\n", lpstrObject);
  132. // Initialize the object type buffer
  133. ObjectType.Buffer = ObjectTypeBuf;
  134. ObjectType.MaximumLength = sizeof(ObjectTypeBuf);
  135. // Initialize the object name string
  136. strcpy(Buffer, lpstrObject);
  137. StripObjectPath(Buffer);
  138. RtlInitAnsiString(&AnsiString, Buffer);
  139. ObjectName.Buffer = ObjectNameBuf;
  140. ObjectName.MaximumLength = sizeof(ObjectNameBuf);
  141. Status = RtlAnsiStringToUnicodeString(&ObjectName, &AnsiString, FALSE);
  142. ASSERT(NT_SUCCESS(Status));
  143. //DbgPrint("Open object: name only = <%wZ>\n", &ObjectName);
  144. //
  145. // Open the directory for list directory access
  146. //
  147. strcpy(Buffer, lpstrObject);
  148. StripObjectSpec(Buffer);
  149. RtlInitAnsiString(&AnsiString, Buffer);
  150. Status = RtlAnsiStringToUnicodeString( &DirectoryName, &AnsiString, TRUE);
  151. ASSERT(NT_SUCCESS(Status));
  152. InitializeObjectAttributes( &Attributes,
  153. &DirectoryName,
  154. OBJ_CASE_INSENSITIVE,
  155. NULL,
  156. NULL );
  157. //DbgPrint("Open object: dir only = <%wZ>\n", &DirectoryName);
  158. if (!NT_SUCCESS( Status = NtOpenDirectoryObject( &DirectoryHandle,
  159. STANDARD_RIGHTS_READ |
  160. DIRECTORY_QUERY |
  161. DIRECTORY_TRAVERSE,
  162. &Attributes ) )) {
  163. if (Status == STATUS_OBJECT_TYPE_MISMATCH) {
  164. DbgPrint( "%wZ is not a valid Object Directory Object name\n",
  165. &DirectoryName );
  166. } else {
  167. DbgPrint("OpenObject: failed to open directory, status = 0x%lx\n\r", Status);
  168. }
  169. RtlFreeUnicodeString(&DirectoryName);
  170. MessageBox(hwnd, "Unable to open object", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
  171. return NULL;
  172. }
  173. RtlFreeUnicodeString(&DirectoryName);
  174. //
  175. // Query the entire directory in one sweep
  176. //
  177. ObjectType.Length = 0;
  178. for (Status = NtQueryDirectoryObject( DirectoryHandle,
  179. Buffer,
  180. sizeof(Buffer),
  181. // LATER FALSE,
  182. TRUE, // one entry at a time for now
  183. TRUE,
  184. &Context,
  185. &ReturnedLength );
  186. ObjectType.Length == 0;
  187. Status = NtQueryDirectoryObject( DirectoryHandle,
  188. Buffer,
  189. sizeof(Buffer),
  190. // LATER FALSE,
  191. TRUE, // one entry at a time for now
  192. FALSE,
  193. &Context,
  194. &ReturnedLength ) ) {
  195. //
  196. // Check the status of the operation.
  197. //
  198. if (!NT_SUCCESS( Status )) {
  199. if (Status != STATUS_NO_MORE_ENTRIES) {
  200. DbgPrint("OpenObject: failed to query directory object, status = 0x%lx\n\r", Status);
  201. }
  202. break;
  203. }
  204. //
  205. // For every record in the buffer compare name with the one we're
  206. // looking for
  207. //
  208. //
  209. // Point to the first record in the buffer, we are guaranteed to have
  210. // one otherwise Status would have been No More Files
  211. //
  212. DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer;
  213. while (DirInfo->Name.Length != 0) {
  214. //
  215. // Compare with object we're searching for
  216. //
  217. //DbgPrint("Found object <%wZ>\n", &(DirInfo->Name));
  218. if (RtlEqualString((PSTRING)&ObjectName, (PSTRING)&(DirInfo->Name), TRUE)) {
  219. RtlCopyString((PSTRING)&ObjectType, (PSTRING)&DirInfo->TypeName);
  220. break;
  221. }
  222. //
  223. // Advance DirInfo to the next entry
  224. //
  225. DirInfo ++;
  226. }
  227. }
  228. if (ObjectType.Length == 0) {
  229. DbgPrint("Object not found in directory\n\r");
  230. MessageBox(hwnd, "Unable to open object", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
  231. return(NULL);
  232. }
  233. // We now have the type of the object in ObjectType
  234. // We still have the full object name in lpstrObject
  235. // Use the appropriate open routine to get a handle
  236. ObjectHandle = NULL;
  237. RtlInitString(&AnsiString, lpstrObject);
  238. Status = RtlAnsiStringToUnicodeString(&ObjectName, &AnsiString, TRUE);
  239. ASSERT(NT_SUCCESS(Status));
  240. InitializeObjectAttributes(&Attributes,
  241. &ObjectName,
  242. OBJ_CASE_INSENSITIVE,
  243. NULL,
  244. NULL
  245. );
  246. switch (CalcAttributes(&ObjectType)) {
  247. case ATTR_SYMLINK:
  248. Status = NtOpenSymbolicLinkObject(&ObjectHandle,
  249. READ_CONTROL | SYMBOLIC_LINK_QUERY,
  250. &Attributes);
  251. break;
  252. case ATTR_EVENT:
  253. Status = NtOpenEvent(&ObjectHandle,
  254. READ_CONTROL,
  255. &Attributes);
  256. break;
  257. case ATTR_EVENTPAIR:
  258. Status = NtOpenEventPair(&ObjectHandle,
  259. READ_CONTROL,
  260. &Attributes);
  261. break;
  262. case ATTR_FILE:
  263. Status = NtOpenFile(&ObjectHandle,
  264. READ_CONTROL,
  265. &Attributes,
  266. &IOStatusBlock,
  267. FILE_SHARE_VALID_FLAGS,
  268. 0);
  269. break;
  270. case ATTR_MUTANT:
  271. Status = NtOpenMutant(&ObjectHandle,
  272. READ_CONTROL,
  273. &Attributes);
  274. break;
  275. case ATTR_SECTION:
  276. Status = NtOpenSection(&ObjectHandle,
  277. READ_CONTROL,
  278. &Attributes);
  279. break;
  280. case ATTR_SEMAPHORE:
  281. Status = NtOpenSemaphore(&ObjectHandle,
  282. READ_CONTROL,
  283. &Attributes);
  284. break;
  285. case ATTR_TIMER:
  286. Status = NtOpenTimer(&ObjectHandle,
  287. READ_CONTROL,
  288. &Attributes);
  289. break;
  290. case ATTR_PROCESS:
  291. Status = NtOpenProcess(&ObjectHandle,
  292. READ_CONTROL,
  293. &Attributes,
  294. NULL);
  295. break;
  296. default:
  297. DbgPrint("No open routine for this object type\n\r");
  298. MessageBox(hwnd, "I don't know how to open an object of this type", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
  299. Status = 0;
  300. break;
  301. }
  302. if (!NT_SUCCESS(Status)) {
  303. DbgPrint("Type specific open failed, status = 0x%lx\n\r", Status);
  304. MessageBox(hwnd, "Object open failed", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
  305. ObjectHandle = NULL;
  306. }
  307. RtlFreeUnicodeString(&ObjectName);
  308. return(ObjectHandle);
  309. }
  310. VOID
  311. CloseObject(
  312. HANDLE ObjectHandle
  313. )
  314. {
  315. NtClose(ObjectHandle);
  316. }
  317. BOOL
  318. GetObjectInfo(
  319. HWND hwnd,
  320. HANDLE ObjectHandle
  321. )
  322. {
  323. NTSTATUS Status;
  324. OBJECT_BASIC_INFORMATION BasicInfo;
  325. OBJECT_TYPE_INFORMATION TypeInfo;
  326. WCHAR TypeName[ 64 ];
  327. #define BUFFER_SIZE 1024
  328. CHAR Buffer[BUFFER_SIZE];
  329. STRING String;
  330. TIME_FIELDS TimeFields;
  331. WCHAR UnicodeBuffer[BUFFER_SIZE];
  332. UNICODE_STRING UnicodeString;
  333. //
  334. // Name
  335. //
  336. Status = NtQueryObject(ObjectHandle, ObjectNameInformation,
  337. (PVOID)Buffer, sizeof(Buffer), NULL);
  338. if (!NT_SUCCESS(Status)) {
  339. DbgPrint("GetObjectInfo: Failed to get name info, status = 0x%lx\n\r", Status);
  340. return(FALSE);
  341. }
  342. Status = RtlUnicodeStringToAnsiString(&String, &(((POBJECT_NAME_INFORMATION)Buffer)->Name), TRUE);
  343. ASSERT(NT_SUCCESS(Status));
  344. SetDlgItemText(hwnd, IDS_NAME, String.Buffer);
  345. RtlFreeAnsiString(&String);
  346. //
  347. // Type
  348. //
  349. Status = NtQueryObject(ObjectHandle, ObjectTypeInformation,
  350. (PVOID)Buffer, sizeof(Buffer), NULL);
  351. if (!NT_SUCCESS(Status)) {
  352. DbgPrint("GetObjectInfo: Failed to get type info, status = 0x%lx\n\r", Status);
  353. return(FALSE);
  354. }
  355. Status = RtlUnicodeStringToAnsiString(&String, &(((POBJECT_TYPE_INFORMATION)Buffer)->TypeName), TRUE);
  356. ASSERT(NT_SUCCESS(Status));
  357. SetDlgItemText(hwnd, IDS_TYPE, String.Buffer);
  358. RtlFreeAnsiString(&String);
  359. //
  360. // Symbolic link target if this is a symlink
  361. //
  362. RtlInitUnicodeString(&UnicodeString, SYMLINKTYPE);
  363. if (RtlEqualString((PSTRING)&UnicodeString,
  364. (PSTRING)&(((POBJECT_TYPE_INFORMATION)Buffer)->TypeName), TRUE)) {
  365. ShowWindow(GetDlgItem(hwnd, IDS_OTHERLABEL), SW_SHOWNOACTIVATE);
  366. ShowWindow(GetDlgItem(hwnd, IDS_OTHERTEXT), SW_SHOWNOACTIVATE);
  367. UnicodeString.Buffer = UnicodeBuffer;
  368. UnicodeString.MaximumLength = sizeof(UnicodeBuffer);
  369. Status = NtQuerySymbolicLinkObject(ObjectHandle, &UnicodeString, NULL);
  370. if (!NT_SUCCESS(Status)) {
  371. DbgPrint("GetObjectInfo: Failed to query symbolic link target, status = 0x%lx\n\r", Status);
  372. return(FALSE);
  373. }
  374. RtlUnicodeStringToAnsiString(&String, &UnicodeString, TRUE);
  375. SetDlgItemText(hwnd, IDS_OTHERTEXT, String.Buffer);
  376. RtlFreeAnsiString(&String);
  377. }
  378. //
  379. // Basic info
  380. //
  381. Status = NtQueryObject(ObjectHandle, ObjectBasicInformation,
  382. (PVOID)&BasicInfo, sizeof(BasicInfo), NULL);
  383. if (!NT_SUCCESS(Status)) {
  384. DbgPrint("GetObjectInfo: Failed to get basic info, status = 0x%lx\n\r", Status);
  385. return(FALSE);
  386. }
  387. TypeInfo.TypeName.Buffer = TypeName;
  388. TypeInfo.TypeName.MaximumLength = sizeof( TypeName );
  389. Status = NtQueryObject(ObjectHandle, ObjectTypeInformation,
  390. (PVOID)&TypeInfo, sizeof(TypeInfo) + TypeInfo.TypeName.MaximumLength, NULL);
  391. if (!NT_SUCCESS(Status)) {
  392. DbgPrint("GetObjectInfo: Failed to get type info, status = 0x%lx\n\r", Status);
  393. return(FALSE);
  394. }
  395. CheckDlgButton(hwnd, IDCB_INHERIT, (BasicInfo.Attributes & OBJ_INHERIT) != 0);
  396. CheckDlgButton(hwnd, IDCB_PERMANENT, (BasicInfo.Attributes & OBJ_PERMANENT) != 0);
  397. CheckDlgButton(hwnd, IDCB_EXCLUSIVE, (BasicInfo.Attributes & OBJ_EXCLUSIVE) != 0);
  398. SetDlgItemInt(hwnd, IDS_PAGEDCHARGE, BasicInfo.PagedPoolCharge, FALSE);
  399. SetDlgItemInt(hwnd, IDS_NONPAGEDCHARGE, BasicInfo.NonPagedPoolCharge, FALSE);
  400. SetDlgItemInt(hwnd, IDS_HANDLES, BasicInfo.HandleCount, FALSE);
  401. SetDlgItemInt(hwnd, IDS_TOTALHANDLES, TypeInfo.TotalNumberOfHandles, FALSE);
  402. SetDlgItemInt(hwnd, IDS_POINTERS, BasicInfo.PointerCount, FALSE);
  403. SetDlgItemInt(hwnd, IDS_TOTALPOINTERS, 0, FALSE);
  404. SetDlgItemInt(hwnd, IDS_COUNT, TypeInfo.TotalNumberOfObjects, FALSE);
  405. RtlTimeToTimeFields(&BasicInfo.CreationTime, &TimeFields);
  406. sprintf(Buffer, "%hd/%hd/%hd @ %02hd:%02hd:%02hd",
  407. TimeFields.Year, TimeFields.Month, TimeFields.Day,
  408. TimeFields.Hour, TimeFields.Minute, TimeFields.Second);
  409. SetDlgItemText(hwnd, IDS_CREATIONTIME, Buffer);
  410. return(TRUE);
  411. }
  412. /* Converts the type-name into an attribute value */
  413. LONG
  414. CalcAttributes(
  415. PUNICODE_STRING Type
  416. )
  417. {
  418. UNICODE_STRING TypeName;
  419. RtlInitUnicodeString(&TypeName, DIRECTORYTYPE);
  420. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  421. return ATTR_DIR;
  422. }
  423. RtlInitUnicodeString(&TypeName, SYMLINKTYPE);
  424. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  425. return ATTR_SYMLINK;
  426. }
  427. RtlInitUnicodeString(&TypeName, ADAPTERTYPE);
  428. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  429. return ATTR_ADAPTER;
  430. }
  431. RtlInitUnicodeString(&TypeName, CONTROLLERTYPE);
  432. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  433. return ATTR_CONTROLLER;
  434. }
  435. RtlInitUnicodeString(&TypeName, DEVICETYPE);
  436. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  437. return ATTR_DEVICE;
  438. }
  439. RtlInitUnicodeString(&TypeName, DRIVERTYPE);
  440. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  441. return ATTR_DRIVER;
  442. }
  443. RtlInitUnicodeString(&TypeName, EVENTTYPE);
  444. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  445. return ATTR_EVENT;
  446. }
  447. RtlInitUnicodeString(&TypeName, EVENTPAIRTYPE);
  448. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  449. return ATTR_EVENTPAIR;
  450. }
  451. RtlInitUnicodeString(&TypeName, FILETYPE);
  452. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  453. return ATTR_FILE;
  454. }
  455. RtlInitUnicodeString(&TypeName, MUTANTTYPE);
  456. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  457. return ATTR_MUTANT;
  458. }
  459. RtlInitUnicodeString(&TypeName, PORTTYPE);
  460. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  461. return ATTR_PORT;
  462. }
  463. RtlInitUnicodeString(&TypeName, PROFILETYPE);
  464. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  465. return ATTR_PROFILE;
  466. }
  467. RtlInitUnicodeString(&TypeName, SECTIONTYPE);
  468. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  469. return ATTR_SECTION;
  470. }
  471. RtlInitUnicodeString(&TypeName, SEMAPHORETYPE);
  472. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  473. return ATTR_SEMAPHORE;
  474. }
  475. RtlInitUnicodeString(&TypeName, TIMERTYPE);
  476. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  477. return ATTR_TIMER;
  478. }
  479. RtlInitUnicodeString(&TypeName, TYPETYPE);
  480. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  481. return ATTR_TYPE;
  482. }
  483. RtlInitUnicodeString(&TypeName, PROCESSTYPE);
  484. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  485. return ATTR_PROCESS;
  486. }
  487. return(0);
  488. }
  489. /*--------------------------------------------------------------------------*/
  490. /* */
  491. /* StripObjectSpec() - */
  492. /* */
  493. /*--------------------------------------------------------------------------*/
  494. /* Remove the filespec portion from a path (including the backslash). */
  495. VOID
  496. StripObjectSpec(
  497. LPSTR lpszPath
  498. )
  499. {
  500. LPSTR p;
  501. p = lpszPath + lstrlen(lpszPath);
  502. while ((*p != '\\') && (p != lpszPath))
  503. p = AnsiPrev(lpszPath, p);
  504. /* Don't strip backslash from root directory entry. */
  505. if ((p == lpszPath) && (*p == '\\')) {
  506. p++;
  507. }
  508. *p = '\000';
  509. }
  510. /*--------------------------------------------------------------------------*/
  511. /* */
  512. /* StripObjectPath() - */
  513. /* */
  514. /*--------------------------------------------------------------------------*/
  515. /* Extract only the filespec portion from a path. */
  516. VOID
  517. StripObjectPath(
  518. LPSTR lpszPath
  519. )
  520. {
  521. LPSTR p;
  522. p = lpszPath + lstrlen(lpszPath);
  523. while ((*p != '\\') && (p != lpszPath))
  524. p = AnsiPrev(lpszPath, p);
  525. if (*p == '\\')
  526. p++;
  527. if (p != lpszPath)
  528. lstrcpy(lpszPath, p);
  529. }