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.

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