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.

1075 lines
30 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. atom.c
  5. Abstract:
  6. This file contains the common code to implement atom tables. It is called
  7. by both the user mode Win32 Atom API functions (Local/GlobalxxxAtom) and
  8. by the kernel mode window manager code to access global atoms.
  9. Author:
  10. Steve Wood (stevewo) 26-Oct-1990
  11. Revision History:
  12. --*/
  13. #include "ntrtlp.h"
  14. #include "atom.h"
  15. #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  16. PVOID
  17. RtlpAllocateAtom(
  18. IN ULONG NumberOfBytes,
  19. IN ULONG Tag
  20. );
  21. void
  22. RtlpFreeAtom(
  23. IN PVOID p
  24. );
  25. void
  26. RtlpInitializeLockAtomTable(
  27. IN OUT PRTL_ATOM_TABLE AtomTable
  28. );
  29. BOOLEAN
  30. RtlpLockAtomTable(
  31. IN PRTL_ATOM_TABLE AtomTable
  32. );
  33. void
  34. RtlpUnlockAtomTable(
  35. IN PRTL_ATOM_TABLE AtomTable
  36. );
  37. void
  38. RtlpDestroyLockAtomTable(
  39. IN OUT PRTL_ATOM_TABLE AtomTable
  40. );
  41. BOOLEAN
  42. RtlpInitializeHandleTableForAtomTable(
  43. PRTL_ATOM_TABLE AtomTable
  44. );
  45. void
  46. RtlpDestroyHandleTableForAtomTable(
  47. PRTL_ATOM_TABLE AtomTable
  48. );
  49. PRTL_ATOM_TABLE_ENTRY
  50. RtlpAtomMapAtomToHandleEntry(
  51. IN PRTL_ATOM_TABLE AtomTable,
  52. IN ULONG HandleIndex
  53. );
  54. BOOLEAN
  55. RtlpCreateHandleForAtom(
  56. PRTL_ATOM_TABLE p,
  57. PRTL_ATOM_TABLE_ENTRY a
  58. );
  59. void
  60. RtlpFreeHandleForAtom(
  61. PRTL_ATOM_TABLE p,
  62. PRTL_ATOM_TABLE_ENTRY a
  63. );
  64. BOOLEAN
  65. RtlpGetIntegerAtom(
  66. PWSTR Name,
  67. PRTL_ATOM Atom OPTIONAL
  68. );
  69. PRTL_ATOM_TABLE_ENTRY
  70. RtlpHashStringToAtom(
  71. IN PRTL_ATOM_TABLE p,
  72. IN PWSTR Name,
  73. OUT PRTL_ATOM_TABLE_ENTRY **PreviousAtom OPTIONAL,
  74. OUT PULONG NameLength
  75. );
  76. #pragma alloc_text(PAGE,RtlpAllocateAtom)
  77. #pragma alloc_text(PAGE,RtlpFreeAtom)
  78. #pragma alloc_text(PAGE,RtlpInitializeLockAtomTable)
  79. #pragma alloc_text(PAGE,RtlInitializeAtomPackage)
  80. #pragma alloc_text(PAGE,RtlpLockAtomTable)
  81. #pragma alloc_text(PAGE,RtlpUnlockAtomTable)
  82. #pragma alloc_text(PAGE,RtlpDestroyLockAtomTable)
  83. #pragma alloc_text(PAGE,RtlpInitializeHandleTableForAtomTable)
  84. #pragma alloc_text(PAGE,RtlpDestroyHandleTableForAtomTable)
  85. #pragma alloc_text(PAGE,RtlpAtomMapAtomToHandleEntry)
  86. #pragma alloc_text(PAGE,RtlpCreateHandleForAtom)
  87. #pragma alloc_text(PAGE,RtlpFreeHandleForAtom)
  88. #pragma alloc_text(PAGE,RtlInitializeAtomPackage)
  89. #pragma alloc_text(PAGE,RtlCreateAtomTable)
  90. #pragma alloc_text(PAGE,RtlDestroyAtomTable)
  91. #pragma alloc_text(PAGE,RtlEmptyAtomTable)
  92. #pragma alloc_text(PAGE,RtlpGetIntegerAtom)
  93. #pragma alloc_text(PAGE,RtlpHashStringToAtom)
  94. #pragma alloc_text(PAGE,RtlAddAtomToAtomTable)
  95. #pragma alloc_text(PAGE,RtlLookupAtomInAtomTable)
  96. #pragma alloc_text(PAGE,RtlDeleteAtomFromAtomTable)
  97. #pragma alloc_text(PAGE,RtlPinAtomInAtomTable)
  98. #pragma alloc_text(PAGE,RtlQueryAtomInAtomTable)
  99. #pragma alloc_text(PAGE,RtlQueryAtomsInAtomTable)
  100. #endif
  101. #if defined(ALLOC_DATA_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  102. #pragma data_seg("PAGEDATA")
  103. #endif
  104. ULONG RtlpAtomAllocateTag;
  105. #if defined(NTOS_KERNEL_RUNTIME)
  106. typedef struct _RTLP_ATOM_QUOTA {
  107. PEPROCESS_QUOTA_BLOCK QuotaBlock;
  108. SIZE_T PagedAmount;
  109. } RTLP_ATOM_QUOTA, *PRTLP_ATOM_QUOTA;
  110. #endif
  111. PVOID
  112. RtlpAllocateAtom(
  113. IN ULONG NumberOfBytes,
  114. IN ULONG Tag
  115. )
  116. {
  117. #if defined(NTOS_KERNEL_RUNTIME)
  118. PRTLP_ATOM_QUOTA AllocatedBlock;
  119. NumberOfBytes += sizeof(RTLP_ATOM_QUOTA);
  120. AllocatedBlock = ExAllocatePoolWithTag( PagedPool,
  121. NumberOfBytes,
  122. Tag );
  123. if (AllocatedBlock) {
  124. AllocatedBlock->QuotaBlock
  125. = PsChargeSharedPoolQuota( PsGetCurrentProcess(),
  126. NumberOfBytes,
  127. 0 );
  128. if (! AllocatedBlock->QuotaBlock) {
  129. ExFreePoolWithTag( AllocatedBlock, Tag );
  130. AllocatedBlock = NULL;
  131. } else {
  132. AllocatedBlock->PagedAmount = NumberOfBytes;
  133. AllocatedBlock++;
  134. }
  135. }
  136. return AllocatedBlock;
  137. #else
  138. return RtlAllocateHeap( RtlProcessHeap(),
  139. RtlpAtomAllocateTag,
  140. NumberOfBytes );
  141. #endif
  142. }
  143. void
  144. RtlpFreeAtom(
  145. IN PVOID p
  146. )
  147. {
  148. #if defined(NTOS_KERNEL_RUNTIME)
  149. PRTLP_ATOM_QUOTA AllocatedBlock = (PRTLP_ATOM_QUOTA) p;
  150. ASSERT( AllocatedBlock );
  151. AllocatedBlock--;
  152. ASSERT( AllocatedBlock );
  153. ASSERT( AllocatedBlock->QuotaBlock );
  154. ASSERT( AllocatedBlock->PagedAmount );
  155. PsReturnSharedPoolQuota( AllocatedBlock->QuotaBlock,
  156. AllocatedBlock->PagedAmount,
  157. 0 );
  158. ExFreePool( AllocatedBlock );
  159. #else
  160. RtlFreeHeap( RtlProcessHeap(), 0, p );
  161. #endif
  162. return;
  163. }
  164. void
  165. RtlpInitializeLockAtomTable(
  166. IN OUT PRTL_ATOM_TABLE AtomTable
  167. )
  168. {
  169. #if defined(NTOS_KERNEL_RUNTIME)
  170. // ExInitializeFastMutex( &AtomTable->FastMutex );
  171. ExInitializePushLock( &AtomTable->PushLock );
  172. #else
  173. RtlInitializeCriticalSection( &AtomTable->CriticalSection );
  174. #endif
  175. return;
  176. }
  177. BOOLEAN
  178. RtlpLockAtomTable(
  179. IN PRTL_ATOM_TABLE AtomTable
  180. )
  181. {
  182. if (AtomTable == NULL || AtomTable->Signature != RTL_ATOM_TABLE_SIGNATURE) {
  183. return FALSE;
  184. }
  185. #if defined(NTOS_KERNEL_RUNTIME)
  186. KeEnterCriticalRegion ();
  187. ExAcquirePushLockExclusive( &AtomTable->PushLock );
  188. #else
  189. RtlEnterCriticalSection( &AtomTable->CriticalSection );
  190. #endif
  191. return TRUE;
  192. }
  193. void
  194. RtlpUnlockAtomTable(
  195. IN PRTL_ATOM_TABLE AtomTable
  196. )
  197. {
  198. #if defined(NTOS_KERNEL_RUNTIME)
  199. ExReleasePushLockExclusive( &AtomTable->PushLock );
  200. KeLeaveCriticalRegion ();
  201. #else
  202. RtlLeaveCriticalSection( &AtomTable->CriticalSection );
  203. #endif
  204. }
  205. void
  206. RtlpDestroyLockAtomTable(
  207. IN OUT PRTL_ATOM_TABLE AtomTable
  208. )
  209. {
  210. #if defined(NTOS_KERNEL_RUNTIME)
  211. #else
  212. RtlDeleteCriticalSection( &AtomTable->CriticalSection );
  213. #endif
  214. }
  215. BOOLEAN
  216. RtlpInitializeHandleTableForAtomTable(
  217. PRTL_ATOM_TABLE AtomTable
  218. )
  219. {
  220. #if defined(NTOS_KERNEL_RUNTIME)
  221. AtomTable->ExHandleTable = ExCreateHandleTable( NULL );
  222. if (AtomTable->ExHandleTable != NULL) {
  223. //
  224. // Make sure atom handle tables are NOT part of object handle enumeration
  225. //
  226. ExRemoveHandleTable( AtomTable->ExHandleTable );
  227. return TRUE;
  228. }
  229. else {
  230. return FALSE;
  231. }
  232. #else
  233. RtlInitializeHandleTable( (ULONG)(USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM,
  234. sizeof( RTL_ATOM_HANDLE_TABLE_ENTRY ),
  235. &AtomTable->RtlHandleTable
  236. );
  237. return TRUE;
  238. #endif
  239. }
  240. void
  241. RtlpDestroyHandleTableForAtomTable(
  242. PRTL_ATOM_TABLE AtomTable
  243. )
  244. {
  245. #if defined(NTOS_KERNEL_RUNTIME)
  246. ExDestroyHandleTable( AtomTable->ExHandleTable, NULL );
  247. #else
  248. RtlDestroyHandleTable( &AtomTable->RtlHandleTable );
  249. #endif
  250. return;
  251. }
  252. PRTL_ATOM_TABLE_ENTRY
  253. RtlpAtomMapAtomToHandleEntry(
  254. IN PRTL_ATOM_TABLE AtomTable,
  255. IN ULONG HandleIndex
  256. )
  257. {
  258. #if defined(NTOS_KERNEL_RUNTIME)
  259. PHANDLE_TABLE_ENTRY ExHandleEntry;
  260. PRTL_ATOM_TABLE_ENTRY a;
  261. EXHANDLE ExHandle;
  262. ExHandle.GenericHandleOverlay = 0;
  263. ExHandle.Index = HandleIndex;
  264. ExHandleEntry = ExMapHandleToPointer( AtomTable->ExHandleTable,
  265. ExHandle.GenericHandleOverlay
  266. );
  267. if (ExHandleEntry != NULL) {
  268. a = ExHandleEntry->Object;
  269. ExUnlockHandleTableEntry( AtomTable->ExHandleTable, ExHandleEntry );
  270. return a;
  271. }
  272. #else
  273. PRTL_ATOM_HANDLE_TABLE_ENTRY HandleEntry;
  274. if (RtlIsValidIndexHandle( &AtomTable->RtlHandleTable,
  275. HandleIndex,
  276. (PRTL_HANDLE_TABLE_ENTRY *)&HandleEntry
  277. )
  278. ) {
  279. return HandleEntry->Atom;
  280. }
  281. #endif
  282. return NULL;
  283. }
  284. BOOLEAN
  285. RtlpCreateHandleForAtom(
  286. PRTL_ATOM_TABLE p,
  287. PRTL_ATOM_TABLE_ENTRY a
  288. )
  289. {
  290. #if defined(NTOS_KERNEL_RUNTIME)
  291. EXHANDLE ExHandle;
  292. HANDLE_TABLE_ENTRY ExHandleEntry;
  293. ExHandleEntry.Object = a;
  294. ExHandleEntry.GrantedAccess = 0;
  295. ExHandle.GenericHandleOverlay = ExCreateHandle( p->ExHandleTable, &ExHandleEntry );
  296. if (ExHandle.GenericHandleOverlay != NULL) {
  297. a->HandleIndex = (USHORT)ExHandle.Index;
  298. a->Atom = (RTL_ATOM)((USHORT)a->HandleIndex | RTL_ATOM_MAXIMUM_INTEGER_ATOM);
  299. return TRUE;
  300. }
  301. #else
  302. PRTL_ATOM_HANDLE_TABLE_ENTRY HandleEntry;
  303. ULONG HandleIndex;
  304. HandleEntry = (PRTL_ATOM_HANDLE_TABLE_ENTRY)RtlAllocateHandle( &p->RtlHandleTable,
  305. &HandleIndex
  306. );
  307. if (HandleEntry != NULL) {
  308. if (HandleIndex < RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
  309. a->HandleIndex = (USHORT)HandleIndex;
  310. a->Atom = (RTL_ATOM)((USHORT)HandleIndex | RTL_ATOM_MAXIMUM_INTEGER_ATOM);
  311. HandleEntry->Atom = a;
  312. HandleEntry->LockCount = 0;
  313. HandleEntry->Flags = RTL_HANDLE_ALLOCATED;
  314. return TRUE;
  315. }
  316. RtlFreeHandle( &p->RtlHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry );
  317. }
  318. #endif
  319. return FALSE;
  320. }
  321. void
  322. RtlpFreeHandleForAtom(
  323. PRTL_ATOM_TABLE p,
  324. PRTL_ATOM_TABLE_ENTRY a
  325. )
  326. {
  327. #if defined(NTOS_KERNEL_RUNTIME)
  328. EXHANDLE ExHandle;
  329. ExHandle.GenericHandleOverlay = 0;
  330. ExHandle.Index = a->HandleIndex;
  331. ExDestroyHandle( p->ExHandleTable, ExHandle.GenericHandleOverlay, NULL );
  332. #else
  333. PRTL_ATOM_HANDLE_TABLE_ENTRY HandleEntry;
  334. if (RtlIsValidIndexHandle( &p->RtlHandleTable,
  335. a->HandleIndex,
  336. (PRTL_HANDLE_TABLE_ENTRY *)&HandleEntry
  337. )
  338. ) {
  339. RtlFreeHandle( &p->RtlHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry );
  340. }
  341. #endif
  342. return;
  343. }
  344. NTSTATUS
  345. RtlInitializeAtomPackage(
  346. IN ULONG AllocationTag
  347. )
  348. {
  349. RTL_PAGED_CODE();
  350. RtlpAtomAllocateTag = AllocationTag;
  351. return STATUS_SUCCESS;
  352. }
  353. NTSTATUS
  354. RtlCreateAtomTable(
  355. IN ULONG NumberOfBuckets,
  356. OUT PVOID *AtomTableHandle
  357. )
  358. {
  359. NTSTATUS Status;
  360. PRTL_ATOM_TABLE p;
  361. ULONG Size;
  362. RTL_PAGED_CODE();
  363. Status = STATUS_SUCCESS;
  364. if (*AtomTableHandle == NULL) {
  365. if (NumberOfBuckets <= 1) {
  366. NumberOfBuckets = RTL_ATOM_TABLE_DEFAULT_NUMBER_OF_BUCKETS;
  367. }
  368. Size = sizeof( RTL_ATOM_TABLE ) +
  369. (sizeof( RTL_ATOM_TABLE_ENTRY ) * (NumberOfBuckets-1));
  370. p = (PRTL_ATOM_TABLE)RtlpAllocateAtom( Size, 'TmtA' );
  371. if (p == NULL) {
  372. Status = STATUS_NO_MEMORY;
  373. }
  374. else {
  375. RtlZeroMemory( p, Size );
  376. p->NumberOfBuckets = NumberOfBuckets;
  377. if (RtlpInitializeHandleTableForAtomTable( p )) {
  378. RtlpInitializeLockAtomTable( p );
  379. p->Signature = RTL_ATOM_TABLE_SIGNATURE;
  380. *AtomTableHandle = p;
  381. }
  382. else {
  383. Status = STATUS_NO_MEMORY;
  384. RtlpFreeAtom( p );
  385. }
  386. }
  387. }
  388. return Status;
  389. }
  390. NTSTATUS
  391. RtlDestroyAtomTable(
  392. IN PVOID AtomTableHandle
  393. )
  394. {
  395. NTSTATUS Status;
  396. PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
  397. PRTL_ATOM_TABLE_ENTRY a, aNext, *pa;
  398. ULONG i;
  399. RTL_PAGED_CODE();
  400. Status = STATUS_SUCCESS;
  401. if (!RtlpLockAtomTable( p )) {
  402. return STATUS_INVALID_PARAMETER;
  403. }
  404. try {
  405. pa = &p->Buckets[ 0 ];
  406. for (i=0; i<p->NumberOfBuckets; i++) {
  407. aNext = *pa;
  408. *pa++ = NULL;
  409. while ((a = aNext) != NULL) {
  410. aNext = a->HashLink;
  411. a->HashLink = NULL;
  412. RtlpFreeAtom( a );
  413. }
  414. }
  415. p->Signature = 0;
  416. RtlpUnlockAtomTable( p );
  417. RtlpDestroyHandleTableForAtomTable( p );
  418. RtlpDestroyLockAtomTable( p );
  419. RtlZeroMemory( p, sizeof( RTL_ATOM_TABLE ) );
  420. RtlpFreeAtom( p );
  421. }
  422. except (EXCEPTION_EXECUTE_HANDLER) {
  423. Status = GetExceptionCode();
  424. }
  425. return Status;
  426. }
  427. NTSTATUS
  428. RtlEmptyAtomTable(
  429. IN PVOID AtomTableHandle,
  430. IN BOOLEAN IncludePinnedAtoms
  431. )
  432. {
  433. NTSTATUS Status;
  434. PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
  435. PRTL_ATOM_TABLE_ENTRY a, aNext, *pa, *pa1;
  436. ULONG i;
  437. RTL_PAGED_CODE();
  438. Status = STATUS_SUCCESS;
  439. if (!RtlpLockAtomTable( p )) {
  440. return STATUS_INVALID_PARAMETER;
  441. }
  442. try {
  443. pa = &p->Buckets[ 0 ];
  444. for (i=0; i<p->NumberOfBuckets; i++) {
  445. pa1 = pa++;
  446. while ((a = *pa1) != NULL) {
  447. if (IncludePinnedAtoms || !(a->Flags & RTL_ATOM_PINNED)) {
  448. *pa1 = a->HashLink;
  449. a->HashLink = NULL;
  450. RtlpFreeHandleForAtom( p, a );
  451. RtlpFreeAtom( a );
  452. }
  453. else {
  454. pa1 = &a->HashLink;
  455. }
  456. }
  457. }
  458. RtlpUnlockAtomTable( p );
  459. }
  460. except (EXCEPTION_EXECUTE_HANDLER) {
  461. Status = GetExceptionCode();
  462. }
  463. return Status;
  464. }
  465. BOOLEAN
  466. RtlpGetIntegerAtom(
  467. PWSTR Name,
  468. PRTL_ATOM Atom OPTIONAL
  469. )
  470. {
  471. NTSTATUS Status;
  472. UNICODE_STRING UnicodeString;
  473. PWSTR s;
  474. ULONG n;
  475. RTL_ATOM Temp;
  476. if (((ULONG_PTR)Name & -0x10000) == 0) {
  477. Temp = (RTL_ATOM)(USHORT)PtrToUlong(Name);
  478. if (Temp >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
  479. return FALSE;
  480. }
  481. else {
  482. if (Temp == RTL_ATOM_INVALID_ATOM) {
  483. Temp = RTL_ATOM_MAXIMUM_INTEGER_ATOM;
  484. }
  485. if (ARGUMENT_PRESENT( Atom )) {
  486. *Atom = Temp;
  487. }
  488. return TRUE;
  489. }
  490. }
  491. else
  492. if (*Name != L'#') {
  493. return FALSE;
  494. }
  495. s = ++Name;
  496. while (*s != UNICODE_NULL) {
  497. if (*s < L'0' || *s > L'9') {
  498. return FALSE;
  499. }
  500. else {
  501. s++;
  502. }
  503. }
  504. n = 0;
  505. UnicodeString.Buffer = Name;
  506. UnicodeString.Length = (USHORT)((PCHAR)s - (PCHAR)Name);
  507. UnicodeString.MaximumLength = UnicodeString.Length;
  508. Status = RtlUnicodeStringToInteger( &UnicodeString, 10, &n );
  509. if (NT_SUCCESS( Status )) {
  510. if (ARGUMENT_PRESENT( Atom )) {
  511. if (n == 0 || n > RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
  512. *Atom = RTL_ATOM_MAXIMUM_INTEGER_ATOM;
  513. }
  514. else {
  515. *Atom = (RTL_ATOM)n;
  516. }
  517. }
  518. return TRUE;
  519. }
  520. else {
  521. return FALSE;
  522. }
  523. }
  524. PRTL_ATOM_TABLE_ENTRY
  525. RtlpHashStringToAtom(
  526. IN PRTL_ATOM_TABLE p,
  527. IN PWSTR Name,
  528. OUT PRTL_ATOM_TABLE_ENTRY **PreviousAtom OPTIONAL,
  529. OUT PULONG NameLength
  530. )
  531. {
  532. ULONG Length, Hash;
  533. WCHAR c;
  534. PWCH s;
  535. RTL_ATOM Atom;
  536. PRTL_ATOM_TABLE_ENTRY *pa, a;
  537. if (((ULONG_PTR)Name & -0x10000) == 0) {
  538. Atom = (RTL_ATOM)(USHORT)PtrToUlong(Name);
  539. a = NULL;
  540. if (Atom >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
  541. a = RtlpAtomMapAtomToHandleEntry( p,
  542. (ULONG)(Atom & (USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM)
  543. );
  544. }
  545. if (ARGUMENT_PRESENT( PreviousAtom )) {
  546. *PreviousAtom = NULL;
  547. }
  548. return a;
  549. }
  550. s = Name;
  551. Hash = 0;
  552. while (*s != UNICODE_NULL) {
  553. c = RtlUpcaseUnicodeChar( *s++ );
  554. Hash = Hash + (c << 1) + (c >> 1) + c;
  555. }
  556. Length = (ULONG) (s - Name);
  557. if (Length > RTL_ATOM_MAXIMUM_NAME_LENGTH) {
  558. pa = NULL;
  559. a = NULL;
  560. }
  561. else {
  562. pa = &p->Buckets[ Hash % p->NumberOfBuckets ];
  563. while (a = *pa) {
  564. if (a->NameLength == Length && !_wcsicmp( a->Name, Name )) {
  565. break;
  566. }
  567. else {
  568. pa = &a->HashLink;
  569. }
  570. }
  571. }
  572. if (ARGUMENT_PRESENT( PreviousAtom )) {
  573. *PreviousAtom = pa;
  574. }
  575. if (a == NULL && ARGUMENT_PRESENT( NameLength )) {
  576. *NameLength = Length * sizeof( WCHAR );
  577. }
  578. return a;
  579. }
  580. NTSTATUS
  581. RtlAddAtomToAtomTable(
  582. IN PVOID AtomTableHandle,
  583. IN PWSTR AtomName OPTIONAL,
  584. IN OUT PRTL_ATOM Atom OPTIONAL
  585. )
  586. {
  587. NTSTATUS Status;
  588. PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
  589. PRTL_ATOM_TABLE_ENTRY a, *pa;
  590. ULONG NameLength;
  591. RTL_ATOM Temp;
  592. RTL_PAGED_CODE();
  593. if (!RtlpLockAtomTable( p )) {
  594. return STATUS_INVALID_PARAMETER;
  595. }
  596. try {
  597. if (RtlpGetIntegerAtom( AtomName, &Temp )) {
  598. if (Temp >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
  599. Temp = RTL_ATOM_INVALID_ATOM;
  600. Status = STATUS_INVALID_PARAMETER;
  601. }
  602. else {
  603. Status = STATUS_SUCCESS;
  604. }
  605. if (ARGUMENT_PRESENT( Atom )) {
  606. *Atom = Temp;
  607. }
  608. }
  609. else
  610. if (*AtomName == UNICODE_NULL) {
  611. Status = STATUS_OBJECT_NAME_INVALID;
  612. }
  613. else {
  614. a = RtlpHashStringToAtom( p, AtomName, &pa, &NameLength );
  615. if (a == NULL) {
  616. if (pa != NULL) {
  617. Status = STATUS_NO_MEMORY;
  618. a = RtlpAllocateAtom( FIELD_OFFSET( RTL_ATOM_TABLE_ENTRY, Name ) +
  619. NameLength + sizeof( UNICODE_NULL ),
  620. 'AmtA'
  621. );
  622. if (a != NULL) {
  623. a->HashLink = NULL;
  624. a->ReferenceCount = 1;
  625. a->Flags = 0;
  626. RtlCopyMemory( a->Name, AtomName, NameLength );
  627. a->NameLength = (UCHAR)(NameLength / sizeof( WCHAR ));
  628. a->Name[ a->NameLength ] = UNICODE_NULL;
  629. if (RtlpCreateHandleForAtom( p, a )) {
  630. a->Atom = (RTL_ATOM)a->HandleIndex | RTL_ATOM_MAXIMUM_INTEGER_ATOM;
  631. *pa = a;
  632. if (ARGUMENT_PRESENT( Atom )) {
  633. *Atom = a->Atom;
  634. }
  635. Status = STATUS_SUCCESS;
  636. }
  637. else {
  638. RtlpFreeAtom( a );
  639. }
  640. }
  641. }
  642. else {
  643. Status = STATUS_INVALID_PARAMETER;
  644. }
  645. }
  646. else {
  647. if (!(a->Flags & RTL_ATOM_PINNED)) {
  648. if (a->ReferenceCount == 0xFFFF) {
  649. KdPrint(( "RTL: Pinning atom (%x) as reference count about to wrap\n", Atom ));
  650. a->Flags |= RTL_ATOM_PINNED;
  651. }
  652. else {
  653. a->ReferenceCount += 1;
  654. }
  655. }
  656. if (ARGUMENT_PRESENT( Atom )) {
  657. *Atom = a->Atom;
  658. }
  659. Status = STATUS_SUCCESS;
  660. }
  661. }
  662. }
  663. except (EXCEPTION_EXECUTE_HANDLER) {
  664. Status = GetExceptionCode();
  665. }
  666. RtlpUnlockAtomTable( p );
  667. return Status;
  668. }
  669. NTSTATUS
  670. RtlLookupAtomInAtomTable(
  671. IN PVOID AtomTableHandle,
  672. IN PWSTR AtomName,
  673. OUT PRTL_ATOM Atom OPTIONAL
  674. )
  675. {
  676. NTSTATUS Status;
  677. PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
  678. PRTL_ATOM_TABLE_ENTRY a;
  679. RTL_ATOM Temp;
  680. RTL_PAGED_CODE();
  681. if (!RtlpLockAtomTable( p )) {
  682. return STATUS_INVALID_PARAMETER;
  683. }
  684. try {
  685. if (RtlpGetIntegerAtom( AtomName, &Temp )) {
  686. if (Temp >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
  687. Temp = RTL_ATOM_INVALID_ATOM;
  688. Status = STATUS_INVALID_PARAMETER;
  689. }
  690. else {
  691. Status = STATUS_SUCCESS;
  692. }
  693. if (ARGUMENT_PRESENT( Atom )) {
  694. *Atom = Temp;
  695. }
  696. }
  697. else
  698. if (*AtomName == UNICODE_NULL) {
  699. Status = STATUS_OBJECT_NAME_INVALID;
  700. }
  701. else {
  702. a = RtlpHashStringToAtom( p, AtomName, NULL, NULL );
  703. if (a == NULL) {
  704. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  705. }
  706. else {
  707. if (RtlpAtomMapAtomToHandleEntry( p, (ULONG)a->HandleIndex ) != NULL) {
  708. Status = STATUS_SUCCESS;
  709. if (ARGUMENT_PRESENT( Atom )) {
  710. *Atom = a->Atom;
  711. }
  712. }
  713. else {
  714. Status = STATUS_INVALID_HANDLE;
  715. }
  716. }
  717. }
  718. }
  719. except (EXCEPTION_EXECUTE_HANDLER) {
  720. Status = GetExceptionCode();
  721. }
  722. RtlpUnlockAtomTable( p );
  723. return Status;
  724. }
  725. NTSTATUS
  726. RtlDeleteAtomFromAtomTable(
  727. IN PVOID AtomTableHandle,
  728. IN RTL_ATOM Atom
  729. )
  730. {
  731. NTSTATUS Status;
  732. PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
  733. PRTL_ATOM_TABLE_ENTRY a, *pa;
  734. RTL_PAGED_CODE();
  735. if (!RtlpLockAtomTable( p )) {
  736. return STATUS_INVALID_PARAMETER;
  737. }
  738. try {
  739. Status = STATUS_INVALID_HANDLE;
  740. if (Atom >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
  741. a = RtlpAtomMapAtomToHandleEntry( p,
  742. (ULONG)(Atom & (USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM)
  743. );
  744. if (a != NULL && a->Atom == Atom) {
  745. Status = STATUS_SUCCESS;
  746. if (a->Flags & RTL_ATOM_PINNED) {
  747. KdPrint(( "RTL: Ignoring attempt to delete a pinned atom (%x)\n", Atom ));
  748. Status = STATUS_WAS_LOCKED; // This is a success status code!
  749. }
  750. else
  751. if (--a->ReferenceCount == 0) {
  752. a = RtlpHashStringToAtom( p, a->Name, &pa, NULL );
  753. if (a != NULL) {
  754. if (pa != NULL) {
  755. *pa = a->HashLink;
  756. }
  757. RtlpFreeHandleForAtom( p, a );
  758. RtlpFreeAtom( a );
  759. }
  760. }
  761. }
  762. }
  763. else
  764. if (Atom != RTL_ATOM_INVALID_ATOM) {
  765. Status = STATUS_SUCCESS;
  766. }
  767. }
  768. except (EXCEPTION_EXECUTE_HANDLER) {
  769. Status = GetExceptionCode();
  770. }
  771. RtlpUnlockAtomTable( p );
  772. return Status;
  773. }
  774. NTSTATUS
  775. RtlPinAtomInAtomTable(
  776. IN PVOID AtomTableHandle,
  777. IN RTL_ATOM Atom
  778. )
  779. {
  780. NTSTATUS Status;
  781. PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
  782. PRTL_ATOM_TABLE_ENTRY a, *pa;
  783. RTL_PAGED_CODE();
  784. if (!RtlpLockAtomTable( p )) {
  785. return STATUS_INVALID_PARAMETER;
  786. }
  787. try {
  788. Status = STATUS_INVALID_HANDLE;
  789. if (Atom >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
  790. a = RtlpAtomMapAtomToHandleEntry( p,
  791. (ULONG)(Atom & (USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM)
  792. );
  793. if (a != NULL && a->Atom == Atom) {
  794. Status = STATUS_SUCCESS;
  795. a->Flags |= RTL_ATOM_PINNED;
  796. }
  797. }
  798. else
  799. if (Atom != RTL_ATOM_INVALID_ATOM) {
  800. Status = STATUS_SUCCESS;
  801. }
  802. }
  803. except (EXCEPTION_EXECUTE_HANDLER) {
  804. Status = GetExceptionCode();
  805. }
  806. RtlpUnlockAtomTable( p );
  807. return Status;
  808. }
  809. NTSTATUS
  810. RtlQueryAtomInAtomTable(
  811. IN PVOID AtomTableHandle,
  812. IN RTL_ATOM Atom,
  813. OUT PULONG AtomUsage OPTIONAL,
  814. OUT PULONG AtomFlags OPTIONAL,
  815. IN OUT PWSTR AtomName OPTIONAL,
  816. IN OUT PULONG AtomNameLength OPTIONAL
  817. )
  818. {
  819. NTSTATUS Status;
  820. PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
  821. PRTL_ATOM_TABLE_ENTRY a;
  822. WCHAR AtomNameBuffer[ 16 ];
  823. ULONG CopyLength;
  824. RTL_PAGED_CODE();
  825. if (!RtlpLockAtomTable( p )) {
  826. return STATUS_INVALID_PARAMETER;
  827. }
  828. try {
  829. if (Atom < RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
  830. if (Atom == RTL_ATOM_INVALID_ATOM) {
  831. Status = STATUS_INVALID_PARAMETER;
  832. }
  833. else {
  834. Status = STATUS_SUCCESS;
  835. if (ARGUMENT_PRESENT( AtomUsage )) {
  836. *AtomUsage = 1;
  837. }
  838. if (ARGUMENT_PRESENT( AtomFlags )) {
  839. *AtomFlags = RTL_ATOM_PINNED;
  840. }
  841. if (ARGUMENT_PRESENT( AtomName )) {
  842. CopyLength = _snwprintf( AtomNameBuffer,
  843. sizeof( AtomNameBuffer ) / sizeof( WCHAR ),
  844. L"#%u",
  845. Atom
  846. ) * sizeof( WCHAR );
  847. if (CopyLength >= *AtomNameLength) {
  848. if (*AtomNameLength >= sizeof( UNICODE_NULL )) {
  849. CopyLength = *AtomNameLength - sizeof( UNICODE_NULL );
  850. }
  851. else {
  852. CopyLength = 0;
  853. }
  854. }
  855. if (CopyLength != 0) {
  856. RtlCopyMemory( AtomName, AtomNameBuffer, CopyLength );
  857. AtomName[ CopyLength / sizeof( WCHAR ) ] = UNICODE_NULL;
  858. *AtomNameLength = CopyLength;
  859. }
  860. else {
  861. Status = STATUS_BUFFER_TOO_SMALL;
  862. }
  863. }
  864. }
  865. }
  866. else {
  867. a = RtlpAtomMapAtomToHandleEntry( p,
  868. (ULONG)(Atom & (USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM)
  869. );
  870. if (a != NULL && a->Atom == Atom) {
  871. Status = STATUS_SUCCESS;
  872. if (ARGUMENT_PRESENT( AtomUsage )) {
  873. *AtomUsage = a->ReferenceCount;
  874. }
  875. if (ARGUMENT_PRESENT( AtomFlags )) {
  876. *AtomFlags = a->Flags;
  877. }
  878. if (ARGUMENT_PRESENT( AtomName )) {
  879. //
  880. // Fill in as much of the atom string as possible, and
  881. // always zero terminate. This is what win3.1 does.
  882. //
  883. CopyLength = a->NameLength * sizeof( WCHAR );
  884. if (CopyLength >= *AtomNameLength) {
  885. if (*AtomNameLength >= sizeof( UNICODE_NULL )) {
  886. CopyLength = *AtomNameLength - sizeof( UNICODE_NULL );
  887. }
  888. else {
  889. *AtomNameLength = CopyLength;
  890. CopyLength = 0;
  891. }
  892. }
  893. if (CopyLength != 0) {
  894. RtlCopyMemory( AtomName, a->Name, CopyLength );
  895. AtomName[ CopyLength / sizeof( WCHAR ) ] = UNICODE_NULL;
  896. *AtomNameLength = CopyLength;
  897. }
  898. else {
  899. Status = STATUS_BUFFER_TOO_SMALL;
  900. }
  901. }
  902. }
  903. else {
  904. Status = STATUS_INVALID_HANDLE;
  905. }
  906. }
  907. }
  908. except (EXCEPTION_EXECUTE_HANDLER) {
  909. Status = GetExceptionCode();
  910. }
  911. RtlpUnlockAtomTable( p );
  912. return Status;
  913. }
  914. NTSTATUS
  915. RtlQueryAtomsInAtomTable(
  916. IN PVOID AtomTableHandle,
  917. IN ULONG MaximumNumberOfAtoms,
  918. OUT PULONG NumberOfAtoms,
  919. OUT PRTL_ATOM Atoms
  920. )
  921. {
  922. NTSTATUS Status;
  923. PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
  924. PRTL_ATOM_TABLE_ENTRY a;
  925. ULONG i;
  926. ULONG CurrentAtomIndex;
  927. RTL_PAGED_CODE();
  928. if (!RtlpLockAtomTable( p )) {
  929. return STATUS_INVALID_PARAMETER;
  930. }
  931. Status = STATUS_SUCCESS;
  932. try {
  933. CurrentAtomIndex = 0;
  934. for (i=0; i<p->NumberOfBuckets; i++) {
  935. a = p->Buckets[ i ];
  936. while (a) {
  937. if (CurrentAtomIndex < MaximumNumberOfAtoms) {
  938. Atoms[ CurrentAtomIndex ] = a->Atom;
  939. }
  940. else {
  941. Status = STATUS_INFO_LENGTH_MISMATCH;
  942. }
  943. CurrentAtomIndex += 1;
  944. a = a->HashLink;
  945. }
  946. }
  947. *NumberOfAtoms = CurrentAtomIndex;
  948. }
  949. except (EXCEPTION_EXECUTE_HANDLER) {
  950. Status = GetExceptionCode();
  951. }
  952. RtlpUnlockAtomTable( p );
  953. return Status;
  954. }
  955. #if defined(ALLOC_DATA_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  956. #pragma data_seg()
  957. #endif