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.

527 lines
12 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. atom.c
  5. Abstract:
  6. This module contains the Win32 Atom Management APIs
  7. Author:
  8. Steve Wood (stevewo) 24-Sep-1990
  9. Revision History:
  10. --*/
  11. #include "basedll.h"
  12. typedef ATOM *PATOM;
  13. BOOL
  14. InternalGetIntAtom(
  15. PUNICODE_STRING UnicodeAtomName,
  16. PATOM Atom
  17. );
  18. ATOM
  19. InternalAddAtom(
  20. BOOLEAN UseLocalAtomTable,
  21. BOOLEAN IsUnicodeAtomName,
  22. LPCSTR AtomName
  23. );
  24. ATOM
  25. InternalFindAtom(
  26. BOOLEAN UseLocalAtomTable,
  27. BOOLEAN IsUnicodeAtomName,
  28. LPCSTR AtomName
  29. );
  30. ATOM
  31. InternalDeleteAtom(
  32. BOOLEAN UseLocalAtomTable,
  33. ATOM nAtom
  34. );
  35. UINT
  36. InternalGetAtomName(
  37. BOOLEAN UseLocalAtomTable,
  38. BOOLEAN IsUnicodeAtomName,
  39. ATOM nAtom,
  40. LPSTR AtomName,
  41. DWORD nSize
  42. );
  43. ATOM
  44. GlobalAddAtomA(
  45. LPCSTR lpString
  46. )
  47. {
  48. return( InternalAddAtom( FALSE, FALSE, lpString ) );
  49. }
  50. ATOM
  51. GlobalFindAtomA(
  52. LPCSTR lpString
  53. )
  54. {
  55. return( InternalFindAtom( FALSE, FALSE, lpString) );
  56. }
  57. ATOM
  58. GlobalDeleteAtom(
  59. ATOM nAtom
  60. )
  61. {
  62. return( InternalDeleteAtom( FALSE, nAtom ) );
  63. }
  64. UINT
  65. GlobalGetAtomNameA(
  66. ATOM nAtom,
  67. LPSTR lpBuffer,
  68. int nSize
  69. )
  70. {
  71. return( InternalGetAtomName( FALSE, FALSE, nAtom, lpBuffer, (DWORD)nSize ) );
  72. }
  73. ATOM
  74. APIENTRY
  75. GlobalAddAtomW(
  76. LPCWSTR lpString
  77. )
  78. {
  79. return( InternalAddAtom( FALSE, TRUE, (LPSTR)lpString ) );
  80. }
  81. ATOM
  82. APIENTRY
  83. GlobalFindAtomW(
  84. LPCWSTR lpString
  85. )
  86. {
  87. return( InternalFindAtom( FALSE, TRUE, (LPSTR)lpString) );
  88. }
  89. UINT
  90. APIENTRY
  91. GlobalGetAtomNameW(
  92. ATOM nAtom,
  93. LPWSTR lpBuffer,
  94. int nSize
  95. )
  96. {
  97. return( InternalGetAtomName( FALSE, TRUE, nAtom, (LPSTR)lpBuffer, (DWORD)nSize ) );
  98. }
  99. PVOID BaseLocalAtomTable;
  100. BOOL
  101. APIENTRY
  102. InitAtomTable(
  103. DWORD nSize
  104. )
  105. {
  106. if (nSize < 4 || nSize > 511) {
  107. nSize = 37;
  108. }
  109. return RtlCreateAtomTable( nSize, &BaseLocalAtomTable ) == STATUS_SUCCESS;
  110. }
  111. ATOM
  112. AddAtomA(
  113. LPCSTR lpString
  114. )
  115. {
  116. return( InternalAddAtom( TRUE, FALSE, lpString ) );
  117. }
  118. ATOM
  119. FindAtomA(
  120. LPCSTR lpString
  121. )
  122. {
  123. return( InternalFindAtom( TRUE, FALSE, lpString ) );
  124. }
  125. ATOM
  126. DeleteAtom(
  127. ATOM nAtom
  128. )
  129. {
  130. return( InternalDeleteAtom( TRUE, nAtom ) );
  131. }
  132. UINT
  133. GetAtomNameA(
  134. ATOM nAtom,
  135. LPSTR lpBuffer,
  136. int nSize
  137. )
  138. {
  139. return( InternalGetAtomName( TRUE, FALSE, nAtom, lpBuffer, (DWORD)nSize ) );
  140. }
  141. ATOM
  142. APIENTRY
  143. AddAtomW(
  144. LPCWSTR lpString
  145. )
  146. {
  147. return( InternalAddAtom( TRUE, TRUE, (LPSTR)lpString ) );
  148. }
  149. ATOM
  150. APIENTRY
  151. FindAtomW(
  152. LPCWSTR lpString
  153. )
  154. {
  155. return( InternalFindAtom( TRUE, TRUE, (LPSTR)lpString ) );
  156. }
  157. UINT
  158. APIENTRY
  159. GetAtomNameW(
  160. ATOM nAtom,
  161. LPWSTR lpBuffer,
  162. int nSize
  163. )
  164. {
  165. return( InternalGetAtomName( TRUE, TRUE, nAtom, (LPSTR)lpBuffer, (DWORD)nSize ) );
  166. }
  167. PVOID
  168. InternalInitAtomTable( void )
  169. {
  170. NTSTATUS Status;
  171. if (BaseLocalAtomTable == NULL) {
  172. Status = RtlCreateAtomTable( 0, &BaseLocalAtomTable );
  173. }
  174. return BaseLocalAtomTable;
  175. }
  176. ATOM
  177. InternalAddAtom(
  178. BOOLEAN UseLocalAtomTable,
  179. BOOLEAN IsUnicodeAtomName,
  180. LPCSTR AtomName
  181. )
  182. {
  183. NTSTATUS Status;
  184. ANSI_STRING AnsiString;
  185. UNICODE_STRING UnicodeString;
  186. PUNICODE_STRING UnicodeAtomName;
  187. ATOM Atom;
  188. if ( (ULONG_PTR)AtomName <= 0xFFFF ) {
  189. Atom = (ATOM)PtrToShort((PVOID)AtomName);
  190. if (Atom >= MAXINTATOM) {
  191. BaseSetLastNTError( STATUS_INVALID_PARAMETER );
  192. return( INVALID_ATOM );
  193. }
  194. else {
  195. return( (ATOM)Atom );
  196. }
  197. }
  198. else {
  199. try {
  200. if (IsUnicodeAtomName) {
  201. UnicodeAtomName = &UnicodeString;
  202. RtlInitUnicodeString( UnicodeAtomName, (PWSTR)AtomName );
  203. Status = STATUS_SUCCESS;
  204. }
  205. else {
  206. RtlInitAnsiString( &AnsiString, AtomName );
  207. if (AnsiString.MaximumLength > STATIC_UNICODE_BUFFER_LENGTH) {
  208. UnicodeAtomName = &UnicodeString;
  209. Status = RtlAnsiStringToUnicodeString( UnicodeAtomName, &AnsiString, TRUE );
  210. }
  211. else {
  212. UnicodeAtomName = &NtCurrentTeb()->StaticUnicodeString;
  213. Status = RtlAnsiStringToUnicodeString( UnicodeAtomName, &AnsiString, FALSE );
  214. }
  215. }
  216. }
  217. except (EXCEPTION_EXECUTE_HANDLER) {
  218. Status = GetExceptionCode();
  219. }
  220. if ( !NT_SUCCESS(Status) ) {
  221. BaseSetLastNTError( Status );
  222. return( INVALID_ATOM );
  223. }
  224. }
  225. Atom = INVALID_ATOM;
  226. try {
  227. if (UseLocalAtomTable) {
  228. Status = RtlAddAtomToAtomTable( InternalInitAtomTable(),
  229. UnicodeAtomName->Buffer,
  230. &Atom
  231. );
  232. }
  233. else {
  234. Status = NtAddAtom( UnicodeAtomName->Buffer,
  235. UnicodeAtomName->Length,
  236. &Atom
  237. );
  238. }
  239. if (!NT_SUCCESS( Status )) {
  240. BaseSetLastNTError( Status );
  241. Atom = INVALID_ATOM;
  242. }
  243. }
  244. finally {
  245. if (!IsUnicodeAtomName && UnicodeAtomName == &UnicodeString) {
  246. RtlFreeUnicodeString( UnicodeAtomName );
  247. }
  248. }
  249. return( (ATOM)Atom );
  250. }
  251. ATOM
  252. InternalFindAtom(
  253. BOOLEAN UseLocalAtomTable,
  254. BOOLEAN IsUnicodeAtomName,
  255. LPCSTR AtomName
  256. )
  257. {
  258. NTSTATUS Status;
  259. ANSI_STRING AnsiString;
  260. UNICODE_STRING UnicodeString;
  261. PUNICODE_STRING UnicodeAtomName;
  262. ATOM Atom;
  263. if ( (ULONG_PTR)AtomName <= 0xFFFF ) {
  264. Atom = (ATOM)PtrToShort((PVOID)AtomName);
  265. if (Atom >= MAXINTATOM) {
  266. BaseSetLastNTError( STATUS_INVALID_PARAMETER );
  267. return( INVALID_ATOM );
  268. }
  269. else {
  270. return( (ATOM)Atom );
  271. }
  272. }
  273. else {
  274. try {
  275. if (IsUnicodeAtomName) {
  276. UnicodeAtomName = &UnicodeString;
  277. RtlInitUnicodeString( UnicodeAtomName, (PWSTR)AtomName );
  278. Status = STATUS_SUCCESS;
  279. }
  280. else {
  281. RtlInitAnsiString( &AnsiString, AtomName );
  282. if (AnsiString.MaximumLength > STATIC_UNICODE_BUFFER_LENGTH) {
  283. UnicodeAtomName = &UnicodeString;
  284. Status = RtlAnsiStringToUnicodeString( UnicodeAtomName, &AnsiString, TRUE );
  285. }
  286. else {
  287. UnicodeAtomName = &NtCurrentTeb()->StaticUnicodeString;
  288. Status = RtlAnsiStringToUnicodeString( UnicodeAtomName, &AnsiString, FALSE );
  289. }
  290. }
  291. }
  292. except (EXCEPTION_EXECUTE_HANDLER) {
  293. Status = GetExceptionCode();
  294. }
  295. if ( !NT_SUCCESS(Status) ) {
  296. BaseSetLastNTError( Status );
  297. return( INVALID_ATOM );
  298. }
  299. }
  300. Atom = INVALID_ATOM;
  301. try {
  302. if (UseLocalAtomTable) {
  303. Status = RtlLookupAtomInAtomTable( InternalInitAtomTable(),
  304. UnicodeAtomName->Buffer,
  305. &Atom
  306. );
  307. }
  308. else {
  309. if (UnicodeAtomName->Length == 0) {
  310. SetLastError( ERROR_INVALID_NAME );
  311. leave;
  312. }
  313. Status = NtFindAtom( UnicodeAtomName->Buffer,
  314. UnicodeAtomName->Length,
  315. &Atom
  316. );
  317. }
  318. if (!NT_SUCCESS( Status )) {
  319. BaseSetLastNTError( Status );
  320. Atom = INVALID_ATOM;
  321. leave;
  322. }
  323. }
  324. finally {
  325. if (!IsUnicodeAtomName && UnicodeAtomName == &UnicodeString) {
  326. RtlFreeUnicodeString( UnicodeAtomName );
  327. }
  328. }
  329. return( (ATOM)Atom );
  330. }
  331. ATOM
  332. InternalDeleteAtom(
  333. BOOLEAN UseLocalAtomTable,
  334. ATOM nAtom
  335. )
  336. {
  337. NTSTATUS Status;
  338. if (nAtom >= MAXINTATOM) {
  339. if (UseLocalAtomTable) {
  340. Status = RtlDeleteAtomFromAtomTable( InternalInitAtomTable(), nAtom );
  341. }
  342. else {
  343. Status = NtDeleteAtom( nAtom );
  344. }
  345. if (!NT_SUCCESS( Status )) {
  346. BaseSetLastNTError( Status );
  347. return( INVALID_ATOM );
  348. }
  349. }
  350. return( 0 );
  351. }
  352. UINT
  353. InternalGetAtomName(
  354. BOOLEAN UseLocalAtomTable,
  355. BOOLEAN IsUnicodeAtomName,
  356. ATOM nAtom,
  357. LPSTR AtomName,
  358. DWORD nSize
  359. )
  360. {
  361. NTSTATUS Status;
  362. PVOID FreeBuffer = NULL;
  363. ANSI_STRING AnsiString;
  364. UNICODE_STRING UnicodeString;
  365. PWSTR UnicodeAtomName;
  366. ULONG AtomInfoLength, AtomNameLength;
  367. DWORD ReturnValue;
  368. PATOM_BASIC_INFORMATION AtomInfo;
  369. //
  370. // Trim nSize so that it will not overflow the 16-bit unicode string
  371. // maximum length field. This prevents people that call us with a >=32KB
  372. // query buffer from stubbing their toes when they call the Ansi version
  373. // of the GetAtomName API
  374. //
  375. if (!IsUnicodeAtomName && nSize > 0x7000) {
  376. nSize = 0x7000;
  377. }
  378. if (nSize == 0) {
  379. BaseSetLastNTError( STATUS_BUFFER_OVERFLOW );
  380. return( 0 );
  381. }
  382. if (UseLocalAtomTable) {
  383. if (IsUnicodeAtomName) {
  384. UnicodeAtomName = (PWSTR)AtomName;
  385. }
  386. else {
  387. FreeBuffer = RtlAllocateHeap( RtlProcessHeap(),
  388. MAKE_TAG( TMP_TAG ),
  389. nSize * sizeof( WCHAR )
  390. );
  391. if (FreeBuffer == NULL) {
  392. BaseSetLastNTError( STATUS_NO_MEMORY );
  393. return( 0 );
  394. }
  395. UnicodeAtomName = (PWSTR)FreeBuffer;
  396. }
  397. AtomNameLength = nSize * sizeof( WCHAR );
  398. Status = RtlQueryAtomInAtomTable( InternalInitAtomTable(),
  399. nAtom,
  400. NULL,
  401. NULL,
  402. UnicodeAtomName,
  403. &AtomNameLength
  404. );
  405. }
  406. else {
  407. AtomInfoLength = sizeof( *AtomInfo ) + (nSize * sizeof( WCHAR ));
  408. FreeBuffer = RtlAllocateHeap( RtlProcessHeap(),
  409. MAKE_TAG( TMP_TAG ),
  410. AtomInfoLength
  411. );
  412. if (FreeBuffer == NULL) {
  413. BaseSetLastNTError( STATUS_NO_MEMORY );
  414. return( 0 );
  415. }
  416. AtomInfo = (PATOM_BASIC_INFORMATION)FreeBuffer;
  417. Status = NtQueryInformationAtom( nAtom,
  418. AtomBasicInformation,
  419. AtomInfo,
  420. AtomInfoLength,
  421. &AtomInfoLength
  422. );
  423. if (NT_SUCCESS( Status )) {
  424. AtomNameLength = (ULONG)AtomInfo->NameLength;
  425. UnicodeAtomName = AtomInfo->Name;
  426. }
  427. }
  428. if (NT_SUCCESS( Status )) {
  429. if (IsUnicodeAtomName) {
  430. ReturnValue = AtomNameLength / sizeof( WCHAR );
  431. if (UnicodeAtomName != (PWSTR)AtomName) {
  432. RtlMoveMemory( AtomName, UnicodeAtomName, AtomNameLength );
  433. }
  434. if (ReturnValue < nSize) {
  435. *((PWSTR)AtomName + ReturnValue) = UNICODE_NULL;
  436. }
  437. }
  438. else {
  439. UnicodeString.Buffer = UnicodeAtomName;
  440. UnicodeString.Length = (USHORT)AtomNameLength;
  441. UnicodeString.MaximumLength = (USHORT)(UnicodeString.Length + sizeof( UNICODE_NULL ));
  442. AnsiString.Buffer = AtomName;
  443. AnsiString.Length = 0;
  444. AnsiString.MaximumLength = (USHORT)nSize;
  445. Status = RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeString, FALSE );
  446. if (NT_SUCCESS( Status )) {
  447. ReturnValue = AnsiString.Length;
  448. }
  449. }
  450. }
  451. if (FreeBuffer != NULL) {
  452. RtlFreeHeap( RtlProcessHeap(), 0, FreeBuffer );
  453. }
  454. if (!NT_SUCCESS( Status )) {
  455. BaseSetLastNTError( Status );
  456. return( 0 );
  457. }
  458. else {
  459. return( ReturnValue );
  460. }
  461. }