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.

663 lines
17 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. win32.c
  5. Abstract:
  6. This module implements the definition of the executive Win32 objects.
  7. Functions to manage these objects are implemented in win32k.sys.
  8. Author:
  9. James I. Anderson (jima) 14-June-1995
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "exp.h"
  15. //
  16. // Address of windowstation and desktop object type descriptors.
  17. //
  18. POBJECT_TYPE ExWindowStationObjectType;
  19. POBJECT_TYPE ExDesktopObjectType;
  20. PKWIN32_CLOSEMETHOD_CALLOUT ExDesktopCloseProcedureCallout;
  21. PKWIN32_CLOSEMETHOD_CALLOUT ExWindowStationCloseProcedureCallout;
  22. PKWIN32_OPENMETHOD_CALLOUT ExDesktopOpenProcedureCallout;
  23. PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExDesktopOkToCloseProcedureCallout;
  24. PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExWindowStationOkToCloseProcedureCallout;
  25. PKWIN32_DELETEMETHOD_CALLOUT ExDesktopDeleteProcedureCallout;
  26. PKWIN32_DELETEMETHOD_CALLOUT ExWindowStationDeleteProcedureCallout;
  27. PKWIN32_PARSEMETHOD_CALLOUT ExWindowStationParseProcedureCallout;
  28. PKWIN32_OPENMETHOD_CALLOUT ExWindowStationOpenProcedureCallout;
  29. //
  30. // common types for above win32 callouts and parameters
  31. //
  32. typedef PVOID PKWIN32_CALLOUT_PARAMETERS;
  33. typedef
  34. NTSTATUS
  35. (*PKWIN32_CALLOUT) (
  36. IN PKWIN32_CALLOUT_PARAMETERS
  37. );
  38. NTSTATUS
  39. ExpWin32SessionCallout(
  40. IN PKWIN32_CALLOUT CalloutRoutine,
  41. IN PKWIN32_CALLOUT_PARAMETERS Parameters,
  42. IN ULONG SessionId,
  43. OUT PNTSTATUS CalloutStatus OPTIONAL
  44. );
  45. VOID
  46. ExpWin32CloseProcedure(
  47. IN PEPROCESS Process OPTIONAL,
  48. IN PVOID Object,
  49. IN ACCESS_MASK GrantedAccess,
  50. IN ULONG ProcessHandleCount,
  51. IN ULONG SystemHandleCount );
  52. BOOLEAN
  53. ExpWin32OkayToCloseProcedure(
  54. IN PEPROCESS Process OPTIONAL,
  55. IN PVOID Object,
  56. IN HANDLE Handle,
  57. IN KPROCESSOR_MODE PreviousMode
  58. );
  59. VOID
  60. ExpWin32DeleteProcedure(
  61. IN PVOID Object
  62. );
  63. NTSTATUS
  64. ExpWin32ParseProcedure (
  65. IN PVOID ParseObject,
  66. IN PVOID ObjectType,
  67. IN OUT PACCESS_STATE AccessState,
  68. IN KPROCESSOR_MODE AccessMode,
  69. IN ULONG Attributes,
  70. IN OUT PUNICODE_STRING CompleteName,
  71. IN OUT PUNICODE_STRING RemainingName,
  72. IN OUT PVOID Context OPTIONAL,
  73. IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
  74. OUT PVOID *Object
  75. );
  76. NTSTATUS
  77. ExpWin32OpenProcedure(
  78. IN OB_OPEN_REASON OpenReason,
  79. IN PEPROCESS Process OPTIONAL,
  80. IN PVOID Object,
  81. IN ACCESS_MASK GrantedAccess,
  82. IN ULONG HandleCount
  83. );
  84. #ifdef ALLOC_PRAGMA
  85. #pragma alloc_text (INIT, ExpWin32Initialization)
  86. #pragma alloc_text (PAGE, ExpWin32CloseProcedure)
  87. #pragma alloc_text (PAGE, ExpWin32OkayToCloseProcedure)
  88. #pragma alloc_text (PAGE, ExpWin32DeleteProcedure)
  89. #pragma alloc_text (PAGE, ExpWin32OpenProcedure)
  90. #pragma alloc_text (PAGE, ExpWin32ParseProcedure)
  91. #pragma alloc_text (PAGE, ExpWin32SessionCallout)
  92. #endif
  93. /*
  94. * windowstation generic mapping
  95. */
  96. #ifdef ALLOC_DATA_PRAGMA
  97. #pragma const_seg("INITCONST")
  98. #endif
  99. const GENERIC_MAPPING ExpWindowStationMapping = {
  100. STANDARD_RIGHTS_READ,
  101. STANDARD_RIGHTS_WRITE,
  102. STANDARD_RIGHTS_EXECUTE,
  103. STANDARD_RIGHTS_REQUIRED
  104. };
  105. /*
  106. * desktop generic mapping
  107. */
  108. const GENERIC_MAPPING ExpDesktopMapping = {
  109. STANDARD_RIGHTS_READ,
  110. STANDARD_RIGHTS_WRITE,
  111. STANDARD_RIGHTS_EXECUTE,
  112. STANDARD_RIGHTS_REQUIRED
  113. };
  114. #ifdef ALLOC_DATA_PRAGMA
  115. #pragma const_seg()
  116. #endif
  117. /*++
  118. Routine Description:
  119. Close Procedure for Win32k windostation and desktop objects
  120. Arguments:
  121. Defined by OB_CLOSE_METHOD
  122. Return Value:
  123. --*/
  124. VOID ExpWin32CloseProcedure(
  125. IN PEPROCESS Process OPTIONAL,
  126. IN PVOID Object,
  127. IN ACCESS_MASK GrantedAccess,
  128. IN ULONG ProcessHandleCount,
  129. IN ULONG SystemHandleCount )
  130. {
  131. //
  132. // SessionId is the first field in the Win32k Object structure
  133. //
  134. ULONG SessionId = *((PULONG)Object);
  135. WIN32_CLOSEMETHOD_PARAMETERS CloseParams;
  136. NTSTATUS Status;
  137. CloseParams.Process = Process;
  138. CloseParams.Object = Object;
  139. CloseParams.GrantedAccess = GrantedAccess;
  140. CloseParams.ProcessHandleCount = ProcessHandleCount;
  141. CloseParams.SystemHandleCount = SystemHandleCount;
  142. if ((OBJECT_TO_OBJECT_HEADER(Object)->Type) == ExDesktopObjectType) {
  143. Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExDesktopCloseProcedureCallout,
  144. (PKWIN32_CALLOUT_PARAMETERS)&CloseParams,
  145. SessionId,
  146. NULL);
  147. ASSERT(NT_SUCCESS(Status));
  148. } else if ((OBJECT_TO_OBJECT_HEADER(Object)->Type) == ExWindowStationObjectType) {
  149. Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExWindowStationCloseProcedureCallout,
  150. (PKWIN32_CALLOUT_PARAMETERS)&CloseParams,
  151. SessionId,
  152. NULL);
  153. ASSERT(NT_SUCCESS(Status));
  154. } else {
  155. ASSERT((OBJECT_TO_OBJECT_HEADER(Object)->Type) == ExDesktopObjectType || (OBJECT_TO_OBJECT_HEADER(Object)->Type == ExWindowStationObjectType));
  156. }
  157. }
  158. /*++
  159. Routine Description:
  160. OkayToClose Procedure for Win32k windostation and desktop objects
  161. Arguments:
  162. Defined by OB_OKAYTOCLOSE_METHOD
  163. Return Value:
  164. --*/
  165. BOOLEAN ExpWin32OkayToCloseProcedure(
  166. IN PEPROCESS Process OPTIONAL,
  167. IN PVOID Object,
  168. IN HANDLE Handle,
  169. IN KPROCESSOR_MODE PreviousMode
  170. )
  171. {
  172. //
  173. // SessionId is the first field in the Win32k Object structure
  174. //
  175. ULONG SessionId = *((PULONG)Object);
  176. WIN32_OKAYTOCLOSEMETHOD_PARAMETERS OKToCloseParams;
  177. NTSTATUS Status, CallStatus = STATUS_UNSUCCESSFUL;
  178. OKToCloseParams.Process = Process;
  179. OKToCloseParams.Object = Object;
  180. OKToCloseParams.Handle = Handle;
  181. OKToCloseParams.PreviousMode = PreviousMode;
  182. if (OBJECT_TO_OBJECT_HEADER(Object)->Type == ExDesktopObjectType) {
  183. Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExDesktopOkToCloseProcedureCallout,
  184. (PKWIN32_CALLOUT_PARAMETERS)&OKToCloseParams,
  185. SessionId,
  186. &CallStatus);
  187. ASSERT(NT_SUCCESS(Status));
  188. } else if (OBJECT_TO_OBJECT_HEADER(Object)->Type == ExWindowStationObjectType) {
  189. Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExWindowStationOkToCloseProcedureCallout,
  190. (PKWIN32_CALLOUT_PARAMETERS)&OKToCloseParams,
  191. SessionId,
  192. &CallStatus);
  193. ASSERT(NT_SUCCESS(Status));
  194. } else {
  195. ASSERT(OBJECT_TO_OBJECT_HEADER(Object)->Type == ExDesktopObjectType ||
  196. OBJECT_TO_OBJECT_HEADER(Object)->Type == ExWindowStationObjectType);
  197. }
  198. return (BOOLEAN)(NT_SUCCESS(CallStatus));
  199. }
  200. /*++
  201. Routine Description:
  202. Delete Procedure for Win32k windostation and desktop objects
  203. Arguments:
  204. Defined by OB_DELETE_METHOD
  205. Return Value:
  206. --*/
  207. VOID ExpWin32DeleteProcedure(
  208. IN PVOID Object
  209. )
  210. {
  211. //
  212. // SessionId is the first field in the Win32k Object structure
  213. //
  214. ULONG SessionId = *((PULONG)Object);
  215. WIN32_DELETEMETHOD_PARAMETERS DeleteParams;
  216. NTSTATUS Status;
  217. DeleteParams.Object = Object;
  218. if (OBJECT_TO_OBJECT_HEADER(Object)->Type == ExDesktopObjectType) {
  219. Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExDesktopDeleteProcedureCallout,
  220. (PKWIN32_CALLOUT_PARAMETERS)&DeleteParams,
  221. SessionId,
  222. NULL);
  223. ASSERT(NT_SUCCESS(Status));
  224. } else if (OBJECT_TO_OBJECT_HEADER(Object)->Type == ExWindowStationObjectType) {
  225. Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExWindowStationDeleteProcedureCallout,
  226. (PKWIN32_CALLOUT_PARAMETERS)&DeleteParams,
  227. SessionId,
  228. NULL);
  229. ASSERT(NT_SUCCESS(Status));
  230. } else {
  231. ASSERT(OBJECT_TO_OBJECT_HEADER(Object)->Type == ExDesktopObjectType ||
  232. OBJECT_TO_OBJECT_HEADER(Object)->Type == ExWindowStationObjectType);
  233. }
  234. }
  235. /*++
  236. Routine Description:
  237. Open Procedure for Win32k desktop objects
  238. Arguments:
  239. Defined by OB_OPEN_METHOD
  240. Return Value:
  241. --*/
  242. NTSTATUS
  243. ExpWin32OpenProcedure(
  244. IN OB_OPEN_REASON OpenReason,
  245. IN PEPROCESS Process OPTIONAL,
  246. IN PVOID Object,
  247. IN ACCESS_MASK GrantedAccess,
  248. IN ULONG HandleCount
  249. )
  250. {
  251. //
  252. // SessionId is the first field in the Win32k Object structure
  253. //
  254. ULONG SessionId = *((PULONG)Object);
  255. WIN32_OPENMETHOD_PARAMETERS OpenParams;
  256. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  257. OpenParams.OpenReason = OpenReason;
  258. OpenParams.Process = Process;
  259. OpenParams.Object = Object;
  260. OpenParams.GrantedAccess = GrantedAccess;
  261. OpenParams.HandleCount = HandleCount;
  262. if ((OBJECT_TO_OBJECT_HEADER(Object)->Type) == ExDesktopObjectType) {
  263. Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExDesktopOpenProcedureCallout,
  264. (PKWIN32_CALLOUT_PARAMETERS)&OpenParams,
  265. SessionId,
  266. NULL);
  267. ASSERT(NT_SUCCESS(Status));
  268. } else if ((OBJECT_TO_OBJECT_HEADER(Object)->Type) == ExWindowStationObjectType) {
  269. Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExWindowStationOpenProcedureCallout,
  270. (PKWIN32_CALLOUT_PARAMETERS)&OpenParams,
  271. SessionId,
  272. NULL);
  273. ASSERT(NT_SUCCESS(Status));
  274. } else {
  275. ASSERT((OBJECT_TO_OBJECT_HEADER(Object)->Type) == ExDesktopObjectType || (OBJECT_TO_OBJECT_HEADER(Object)->Type == ExWindowStationObjectType));
  276. }
  277. return Status;
  278. }
  279. /*++
  280. Routine Description:
  281. Parse Procedure for Win32k windostation objects
  282. Arguments:
  283. Defined by OB_PARSE_METHOD
  284. Return Value:
  285. --*/
  286. NTSTATUS ExpWin32ParseProcedure (
  287. IN PVOID ParseObject,
  288. IN PVOID ObjectType,
  289. IN OUT PACCESS_STATE AccessState,
  290. IN KPROCESSOR_MODE AccessMode,
  291. IN ULONG Attributes,
  292. IN OUT PUNICODE_STRING CompleteName,
  293. IN OUT PUNICODE_STRING RemainingName,
  294. IN OUT PVOID Context OPTIONAL,
  295. IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
  296. OUT PVOID *Object
  297. )
  298. {
  299. //
  300. // SessionId is the first field in the Win32k Object structure
  301. //
  302. ULONG SessionId = *((PULONG)ParseObject);
  303. WIN32_PARSEMETHOD_PARAMETERS ParseParams;
  304. NTSTATUS Status, CallStatus = STATUS_UNSUCCESSFUL;
  305. ParseParams.ParseObject = ParseObject;
  306. ParseParams.ObjectType = ObjectType;
  307. ParseParams.AccessState = AccessState;
  308. ParseParams.AccessMode = AccessMode;
  309. ParseParams.Attributes = Attributes;
  310. ParseParams.CompleteName = CompleteName;
  311. ParseParams.RemainingName = RemainingName;
  312. ParseParams.Context = Context;
  313. ParseParams.SecurityQos = SecurityQos;
  314. ParseParams.Object = Object;
  315. //
  316. // Parse Procedure is only provided for WindowStation objects
  317. //
  318. Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExWindowStationParseProcedureCallout,
  319. (PKWIN32_CALLOUT_PARAMETERS)&ParseParams,
  320. SessionId,
  321. &CallStatus);
  322. ASSERT(NT_SUCCESS(Status));
  323. return CallStatus;
  324. }
  325. BOOLEAN
  326. ExpWin32Initialization (
  327. )
  328. /*++
  329. Routine Description:
  330. This function creates the Win32 object type descriptors at system
  331. initialization and stores the address of the object type descriptor
  332. in local static storage.
  333. Arguments:
  334. None.
  335. Return Value:
  336. A value of TRUE is returned if the Win32 object type descriptors are
  337. successfully created. Otherwise a value of FALSE is returned.
  338. --*/
  339. {
  340. OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
  341. NTSTATUS Status;
  342. UNICODE_STRING TypeName;
  343. //
  344. // Initialize string descriptor.
  345. //
  346. RtlInitUnicodeString(&TypeName, L"WindowStation");
  347. //
  348. // Create windowstation object type descriptor.
  349. //
  350. RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
  351. ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
  352. ObjectTypeInitializer.GenericMapping = ExpWindowStationMapping;
  353. ObjectTypeInitializer.SecurityRequired = TRUE;
  354. ObjectTypeInitializer.PoolType = NonPagedPool;
  355. ObjectTypeInitializer.CloseProcedure = ExpWin32CloseProcedure;
  356. ObjectTypeInitializer.DeleteProcedure = ExpWin32DeleteProcedure;
  357. ObjectTypeInitializer.OkayToCloseProcedure = ExpWin32OkayToCloseProcedure;
  358. ObjectTypeInitializer.ParseProcedure = ExpWin32ParseProcedure;
  359. ObjectTypeInitializer.OpenProcedure = ExpWin32OpenProcedure;
  360. ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK |
  361. OBJ_PERMANENT |
  362. OBJ_EXCLUSIVE;
  363. ObjectTypeInitializer.ValidAccessMask = STANDARD_RIGHTS_REQUIRED;
  364. Status = ObCreateObjectType(&TypeName,
  365. &ObjectTypeInitializer,
  366. (PSECURITY_DESCRIPTOR)NULL,
  367. &ExWindowStationObjectType);
  368. //
  369. // If the windowstation object type descriptor was not successfully
  370. // created, then return a value of FALSE.
  371. //
  372. if (!NT_SUCCESS(Status))
  373. return FALSE;
  374. //
  375. // Initialize string descriptor.
  376. //
  377. RtlInitUnicodeString(&TypeName, L"Desktop");
  378. ObjectTypeInitializer.ParseProcedure = NULL; //Desktop has no Parse Procedure
  379. //
  380. // Create windowstation object type descriptor.
  381. //
  382. ObjectTypeInitializer.GenericMapping = ExpDesktopMapping;
  383. Status = ObCreateObjectType(&TypeName,
  384. &ObjectTypeInitializer,
  385. (PSECURITY_DESCRIPTOR)NULL,
  386. &ExDesktopObjectType);
  387. //
  388. // If the desktop object type descriptor was successfully created, then
  389. // return a value of TRUE. Otherwise return a value of FALSE.
  390. //
  391. return (BOOLEAN)(NT_SUCCESS(Status));
  392. }
  393. NTSTATUS
  394. ExpWin32SessionCallout(
  395. IN PKWIN32_CALLOUT CalloutRoutine,
  396. IN PKWIN32_CALLOUT_PARAMETERS Parameters,
  397. IN ULONG SessionId,
  398. OUT PNTSTATUS CalloutStatus OPTIONAL
  399. )
  400. /*++
  401. Routine Description:
  402. This routine calls the specified callout routine in session space, for the
  403. specified session.
  404. Parameters:
  405. CalloutRoutine - Callout routine in session space.
  406. Parameters - Parameters to pass the callout routine.
  407. SessionId - Specifies the ID of the session in which the specified
  408. callout routine is to be called.
  409. CalloutStatus - Optionally, supplies the address of a variable to receive
  410. the NTSTATUS code returned by the callout routine.
  411. Return Value:
  412. Status code that indicates whether or not the function was successful.
  413. Notes:
  414. Returns STATUS_NOT_FOUND if the specified session was not found.
  415. --*/
  416. {
  417. NTSTATUS Status, CallStatus;
  418. PVOID OpaqueSession;
  419. KAPC_STATE ApcState;
  420. PAGED_CODE();
  421. //
  422. // Make sure we have all the information we need to deliver notification.
  423. //
  424. if (CalloutRoutine == NULL) {
  425. return STATUS_INVALID_PARAMETER;
  426. }
  427. //
  428. // Make sure the callout routine in session space.
  429. //
  430. ASSERT(MmIsSessionAddress((PVOID)CalloutRoutine));
  431. if ((PsGetCurrentProcess()->Flags & PS_PROCESS_FLAGS_IN_SESSION) &&
  432. (SessionId == PsGetCurrentProcessSessionId())) {
  433. //
  434. // If the call is from a user mode process, and we are asked to call the
  435. // current session, call directly.
  436. //
  437. CallStatus = (CalloutRoutine)(Parameters);
  438. //
  439. // Return the callout status.
  440. //
  441. if (ARGUMENT_PRESENT(CalloutStatus)) {
  442. *CalloutStatus = CallStatus;
  443. }
  444. Status = STATUS_SUCCESS;
  445. } else {
  446. //
  447. // Reference the session object for the specified session.
  448. //
  449. OpaqueSession = MmGetSessionById(SessionId);
  450. if (OpaqueSession == NULL) {
  451. return STATUS_NOT_FOUND;
  452. }
  453. //
  454. // Attach to the specified session.
  455. //
  456. Status = MmAttachSession(OpaqueSession, &ApcState);
  457. if (!NT_SUCCESS(Status)) {
  458. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_WARNING_LEVEL,
  459. "ExpWin32SessionCallout: "
  460. "could not attach to 0x%p, session %d for registered notification callout @ 0x%p\n",
  461. OpaqueSession,
  462. SessionId,
  463. CalloutRoutine));
  464. MmQuitNextSession(OpaqueSession);
  465. return Status;
  466. }
  467. //
  468. // Dispatch notification to the callout routine.
  469. //
  470. CallStatus = (CalloutRoutine)(Parameters);
  471. //
  472. // Return the callout status.
  473. //
  474. if (ARGUMENT_PRESENT(CalloutStatus)) {
  475. *CalloutStatus = CallStatus;
  476. }
  477. //
  478. // Detach from the session.
  479. //
  480. Status = MmDetachSession(OpaqueSession, &ApcState);
  481. ASSERT(NT_SUCCESS(Status));
  482. //
  483. // Dereference the session object.
  484. //
  485. Status = MmQuitNextSession(OpaqueSession);
  486. ASSERT(NT_SUCCESS(Status));
  487. }
  488. return Status;
  489. }