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.

488 lines
10 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. exatom.c
  5. Abstract:
  6. This file contains functions for manipulating global atom tables
  7. stored in kernel space.
  8. Author:
  9. Steve Wood (stevewo) 13-Dec-1995
  10. Revision History:
  11. --*/
  12. #include "exp.h"
  13. #pragma hdrstop
  14. //
  15. // Local Procedure prototype
  16. //
  17. PVOID
  18. ExpGetGlobalAtomTable (
  19. );
  20. #if defined(ALLOC_PRAGMA)
  21. #pragma alloc_text(PAGE, NtAddAtom)
  22. #pragma alloc_text(PAGE, NtFindAtom)
  23. #pragma alloc_text(PAGE, NtDeleteAtom)
  24. #pragma alloc_text(PAGE, NtQueryInformationAtom)
  25. #pragma alloc_text(PAGE, ExpGetGlobalAtomTable)
  26. #endif
  27. #define COPY_STACK_SIZE 128
  28. NTSYSAPI
  29. NTSTATUS
  30. NTAPI
  31. NtAddAtom (
  32. IN PWSTR AtomName,
  33. IN ULONG Length,
  34. OUT PRTL_ATOM Atom OPTIONAL
  35. )
  36. /*++
  37. Routine Description:
  38. Arguments:
  39. Return Value:
  40. --*/
  41. {
  42. NTSTATUS Status;
  43. RTL_ATOM ReturnAtom;
  44. PVOID AtomTable = ExpGetGlobalAtomTable();
  45. KPROCESSOR_MODE PreviousMode;
  46. PWSTR CapturedAtomNameBuffer;
  47. ULONG AllocLength;
  48. UCHAR StackArray[COPY_STACK_SIZE];
  49. PAGED_CODE();
  50. if (AtomTable == NULL) {
  51. return STATUS_ACCESS_DENIED;
  52. }
  53. if (Length > (RTL_ATOM_MAXIMUM_NAME_LENGTH * sizeof(WCHAR))) {
  54. return STATUS_INVALID_PARAMETER;
  55. }
  56. PreviousMode = KeGetPreviousMode();
  57. CapturedAtomNameBuffer = AtomName;
  58. Status = STATUS_SUCCESS;
  59. if (PreviousMode != KernelMode) {
  60. if (ARGUMENT_PRESENT (Atom)) {
  61. try {
  62. ProbeForWriteUshort( Atom );
  63. } except (EXCEPTION_EXECUTE_HANDLER) {
  64. return GetExceptionCode();
  65. }
  66. }
  67. if (ARGUMENT_PRESENT (AtomName)) {
  68. AllocLength = (Length + sizeof( UNICODE_NULL ))&~(sizeof (WCHAR)-1);
  69. try {
  70. ProbeForRead( AtomName, Length, sizeof( WCHAR ) );
  71. } except (EXCEPTION_EXECUTE_HANDLER) {
  72. return GetExceptionCode();
  73. }
  74. if (AllocLength <= COPY_STACK_SIZE) {
  75. CapturedAtomNameBuffer = (PWSTR) StackArray;
  76. }
  77. else {
  78. CapturedAtomNameBuffer = ExAllocatePoolWithTag (PagedPool, AllocLength, 'motA');
  79. if (CapturedAtomNameBuffer == NULL) {
  80. return STATUS_INSUFFICIENT_RESOURCES;
  81. }
  82. }
  83. try {
  84. RtlCopyMemory( CapturedAtomNameBuffer, AtomName, Length );
  85. } except (EXCEPTION_EXECUTE_HANDLER) {
  86. if (CapturedAtomNameBuffer != (PWSTR) StackArray) {
  87. ExFreePool (CapturedAtomNameBuffer);
  88. }
  89. return GetExceptionCode();
  90. }
  91. CapturedAtomNameBuffer[Length / sizeof (WCHAR)] = '\0';
  92. }
  93. }
  94. if (NT_SUCCESS (Status)) {
  95. Status = RtlAddAtomToAtomTable (AtomTable, CapturedAtomNameBuffer, &ReturnAtom);
  96. if ((ARGUMENT_PRESENT (Atom)) && (NT_SUCCESS (Status))) {
  97. if (PreviousMode != KernelMode) {
  98. try {
  99. *Atom = ReturnAtom;
  100. } except (EXCEPTION_EXECUTE_HANDLER) {
  101. Status = GetExceptionCode();
  102. }
  103. }
  104. else {
  105. *Atom = ReturnAtom;
  106. }
  107. }
  108. }
  109. if ((CapturedAtomNameBuffer != AtomName) &&
  110. (CapturedAtomNameBuffer != (PWSTR) StackArray)) {
  111. ExFreePool (CapturedAtomNameBuffer);
  112. }
  113. return Status;
  114. }
  115. NTSYSAPI
  116. NTSTATUS
  117. NTAPI
  118. NtFindAtom (
  119. IN PWSTR AtomName,
  120. IN ULONG Length,
  121. OUT PRTL_ATOM Atom OPTIONAL
  122. )
  123. /*++
  124. Routine Description:
  125. Arguments:
  126. Return Value:
  127. --*/
  128. {
  129. NTSTATUS Status;
  130. RTL_ATOM ReturnAtom;
  131. PVOID AtomTable = ExpGetGlobalAtomTable();
  132. KPROCESSOR_MODE PreviousMode;
  133. PWSTR CapturedAtomNameBuffer;
  134. ULONG AllocLength;
  135. UCHAR StackArray[COPY_STACK_SIZE];
  136. PAGED_CODE();
  137. if (AtomTable == NULL) {
  138. return STATUS_ACCESS_DENIED;
  139. }
  140. if (Length > (RTL_ATOM_MAXIMUM_NAME_LENGTH * sizeof(WCHAR))) {
  141. return STATUS_INVALID_PARAMETER;
  142. }
  143. PreviousMode = KeGetPreviousMode();
  144. CapturedAtomNameBuffer = AtomName;
  145. Status = STATUS_SUCCESS;
  146. if (PreviousMode != KernelMode) {
  147. if (ARGUMENT_PRESENT (Atom)) {
  148. try {
  149. ProbeForWriteUshort (Atom);
  150. } except (EXCEPTION_EXECUTE_HANDLER) {
  151. return GetExceptionCode();
  152. }
  153. }
  154. if (ARGUMENT_PRESENT (AtomName)) {
  155. AllocLength = (Length + sizeof( UNICODE_NULL ))&~(sizeof (WCHAR)-1);
  156. try {
  157. ProbeForRead (AtomName, Length, sizeof (WCHAR));
  158. } except (EXCEPTION_EXECUTE_HANDLER) {
  159. return GetExceptionCode();
  160. }
  161. if (AllocLength <= COPY_STACK_SIZE) {
  162. CapturedAtomNameBuffer = (PWSTR) StackArray;
  163. }
  164. else {
  165. CapturedAtomNameBuffer = ExAllocatePoolWithTag (PagedPool, AllocLength, 'motA');
  166. if (CapturedAtomNameBuffer == NULL) {
  167. return STATUS_INSUFFICIENT_RESOURCES;
  168. }
  169. }
  170. try {
  171. RtlCopyMemory (CapturedAtomNameBuffer, AtomName, Length);
  172. } except (EXCEPTION_EXECUTE_HANDLER) {
  173. if (CapturedAtomNameBuffer != (PWSTR) StackArray) {
  174. ExFreePool (CapturedAtomNameBuffer);
  175. }
  176. return GetExceptionCode();
  177. }
  178. CapturedAtomNameBuffer[Length / sizeof (WCHAR)] = '\0';
  179. }
  180. }
  181. if (NT_SUCCESS( Status )) {
  182. Status = RtlLookupAtomInAtomTable (AtomTable, CapturedAtomNameBuffer, &ReturnAtom);
  183. if (NT_SUCCESS(Status) && ARGUMENT_PRESENT(Atom)) {
  184. try {
  185. *Atom = ReturnAtom;
  186. } except (EXCEPTION_EXECUTE_HANDLER) {
  187. Status = GetExceptionCode();
  188. }
  189. }
  190. }
  191. if ((CapturedAtomNameBuffer != AtomName) &&
  192. (CapturedAtomNameBuffer != (PWSTR) StackArray)) {
  193. ExFreePool (CapturedAtomNameBuffer);
  194. }
  195. return Status;
  196. }
  197. NTSYSAPI
  198. NTSTATUS
  199. NTAPI
  200. NtDeleteAtom (
  201. IN RTL_ATOM Atom
  202. )
  203. /*++
  204. Routine Description:
  205. Arguments:
  206. Return Value:
  207. --*/
  208. {
  209. NTSTATUS Status;
  210. PVOID AtomTable = ExpGetGlobalAtomTable();
  211. PAGED_CODE();
  212. if (AtomTable == NULL) {
  213. return STATUS_ACCESS_DENIED;
  214. }
  215. Status = RtlDeleteAtomFromAtomTable( AtomTable, Atom );
  216. return Status;
  217. }
  218. NTSYSAPI
  219. NTSTATUS
  220. NTAPI
  221. NtQueryInformationAtom(
  222. IN RTL_ATOM Atom,
  223. IN ATOM_INFORMATION_CLASS AtomInformationClass,
  224. OUT PVOID AtomInformation,
  225. IN ULONG AtomInformationLength,
  226. OUT PULONG ReturnLength OPTIONAL
  227. )
  228. /*++
  229. Routine Description:
  230. Arguments:
  231. Return Value:
  232. --*/
  233. {
  234. NTSTATUS Status;
  235. KPROCESSOR_MODE PreviousMode;
  236. ULONG RequiredLength;
  237. ULONG UsageCount;
  238. ULONG NameLength;
  239. ULONG AtomFlags;
  240. PATOM_BASIC_INFORMATION BasicInfo;
  241. PATOM_TABLE_INFORMATION TableInfo;
  242. PVOID AtomTable = ExpGetGlobalAtomTable();
  243. PAGED_CODE();
  244. if (AtomTable == NULL) {
  245. return STATUS_ACCESS_DENIED;
  246. }
  247. //
  248. // Assume successful completion.
  249. //
  250. Status = STATUS_SUCCESS;
  251. try {
  252. //
  253. // Get previous processor mode and probe output argument if necessary.
  254. //
  255. PreviousMode = KeGetPreviousMode();
  256. if (PreviousMode != KernelMode) {
  257. ProbeForWrite( AtomInformation,
  258. AtomInformationLength,
  259. sizeof( ULONG ));
  260. if (ARGUMENT_PRESENT( ReturnLength )) {
  261. ProbeForWriteUlong( ReturnLength );
  262. }
  263. }
  264. RequiredLength = 0;
  265. switch (AtomInformationClass) {
  266. case AtomBasicInformation:
  267. RequiredLength = FIELD_OFFSET( ATOM_BASIC_INFORMATION, Name );
  268. if (AtomInformationLength < RequiredLength) {
  269. return STATUS_INFO_LENGTH_MISMATCH;
  270. }
  271. BasicInfo = (PATOM_BASIC_INFORMATION)AtomInformation;
  272. UsageCount = 0;
  273. NameLength = AtomInformationLength - RequiredLength;
  274. BasicInfo->Name[ 0 ] = UNICODE_NULL;
  275. Status = RtlQueryAtomInAtomTable( AtomTable,
  276. Atom,
  277. &UsageCount,
  278. &AtomFlags,
  279. &BasicInfo->Name[0],
  280. &NameLength );
  281. if (NT_SUCCESS(Status)) {
  282. BasicInfo->UsageCount = (USHORT)UsageCount;
  283. BasicInfo->Flags = (USHORT)AtomFlags;
  284. BasicInfo->NameLength = (USHORT)NameLength;
  285. RequiredLength += NameLength + sizeof( UNICODE_NULL );
  286. }
  287. break;
  288. case AtomTableInformation:
  289. RequiredLength = FIELD_OFFSET( ATOM_TABLE_INFORMATION, Atoms );
  290. if (AtomInformationLength < RequiredLength) {
  291. return STATUS_INFO_LENGTH_MISMATCH;
  292. }
  293. TableInfo = (PATOM_TABLE_INFORMATION)AtomInformation;
  294. Status = RtlQueryAtomsInAtomTable( AtomTable,
  295. (AtomInformationLength - RequiredLength) / sizeof( RTL_ATOM ),
  296. &TableInfo->NumberOfAtoms,
  297. &TableInfo->Atoms[0] );
  298. if (NT_SUCCESS(Status)) {
  299. RequiredLength += TableInfo->NumberOfAtoms * sizeof( RTL_ATOM );
  300. }
  301. break;
  302. default:
  303. Status = STATUS_INVALID_INFO_CLASS;
  304. break;
  305. }
  306. if (ARGUMENT_PRESENT( ReturnLength )) {
  307. *ReturnLength = RequiredLength;
  308. }
  309. } except (EXCEPTION_EXECUTE_HANDLER) {
  310. Status = GetExceptionCode();
  311. }
  312. return Status;
  313. }
  314. //
  315. // Local support routine
  316. //
  317. PKWIN32_GLOBALATOMTABLE_CALLOUT ExGlobalAtomTableCallout;
  318. PVOID
  319. ExpGetGlobalAtomTable (
  320. )
  321. /*++
  322. Routine Description:
  323. Arguments:
  324. Return Value:
  325. --*/
  326. {
  327. if (ExGlobalAtomTableCallout != NULL) {
  328. return ((*ExGlobalAtomTableCallout)());
  329. }
  330. #if DBG
  331. DbgPrint( "EX: ExpGetGlobalAtomTable is about to return NULL!\n" );
  332. DbgBreakPoint();
  333. #endif
  334. return NULL;
  335. }