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.

508 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. } else {
  194. return( (ATOM)Atom );
  195. }
  196. } else {
  197. try {
  198. if (IsUnicodeAtomName) {
  199. UnicodeAtomName = &UnicodeString;
  200. RtlInitUnicodeString( UnicodeAtomName, (PWSTR)AtomName );
  201. Status = STATUS_SUCCESS;
  202. } else {
  203. RtlInitAnsiString( &AnsiString, AtomName );
  204. if (AnsiString.MaximumLength > STATIC_UNICODE_BUFFER_LENGTH) {
  205. UnicodeAtomName = &UnicodeString;
  206. Status = RtlAnsiStringToUnicodeString( UnicodeAtomName, &AnsiString, TRUE );
  207. } else {
  208. UnicodeAtomName = &NtCurrentTeb()->StaticUnicodeString;
  209. Status = RtlAnsiStringToUnicodeString( UnicodeAtomName, &AnsiString, FALSE );
  210. }
  211. }
  212. } except (EXCEPTION_EXECUTE_HANDLER) {
  213. Status = GetExceptionCode();
  214. }
  215. if ( !NT_SUCCESS(Status) ) {
  216. BaseSetLastNTError( Status );
  217. return( INVALID_ATOM );
  218. }
  219. }
  220. Atom = INVALID_ATOM;
  221. try {
  222. if (UseLocalAtomTable) {
  223. Status = RtlAddAtomToAtomTable( InternalInitAtomTable(),
  224. UnicodeAtomName->Buffer,
  225. &Atom
  226. );
  227. } else {
  228. Status = NtAddAtom( UnicodeAtomName->Buffer,
  229. UnicodeAtomName->Length,
  230. &Atom
  231. );
  232. }
  233. if (!NT_SUCCESS( Status )) {
  234. BaseSetLastNTError( Status );
  235. Atom = INVALID_ATOM;
  236. }
  237. } finally {
  238. if (!IsUnicodeAtomName && UnicodeAtomName == &UnicodeString) {
  239. RtlFreeUnicodeString( UnicodeAtomName );
  240. }
  241. }
  242. return( (ATOM)Atom );
  243. }
  244. ATOM
  245. InternalFindAtom(
  246. BOOLEAN UseLocalAtomTable,
  247. BOOLEAN IsUnicodeAtomName,
  248. LPCSTR AtomName
  249. )
  250. {
  251. NTSTATUS Status;
  252. ANSI_STRING AnsiString;
  253. UNICODE_STRING UnicodeString;
  254. PUNICODE_STRING UnicodeAtomName;
  255. ATOM Atom;
  256. if ( (ULONG_PTR)AtomName <= 0xFFFF ) {
  257. Atom = (ATOM)PtrToShort((PVOID)AtomName);
  258. if (Atom >= MAXINTATOM) {
  259. BaseSetLastNTError( STATUS_INVALID_PARAMETER );
  260. return( INVALID_ATOM );
  261. } else {
  262. return( (ATOM)Atom );
  263. }
  264. } else {
  265. try {
  266. if (IsUnicodeAtomName) {
  267. UnicodeAtomName = &UnicodeString;
  268. RtlInitUnicodeString( UnicodeAtomName, (PWSTR)AtomName );
  269. Status = STATUS_SUCCESS;
  270. } else {
  271. RtlInitAnsiString( &AnsiString, AtomName );
  272. if (AnsiString.MaximumLength > STATIC_UNICODE_BUFFER_LENGTH) {
  273. UnicodeAtomName = &UnicodeString;
  274. Status = RtlAnsiStringToUnicodeString( UnicodeAtomName, &AnsiString, TRUE );
  275. } else {
  276. UnicodeAtomName = &NtCurrentTeb()->StaticUnicodeString;
  277. Status = RtlAnsiStringToUnicodeString( UnicodeAtomName, &AnsiString, FALSE );
  278. }
  279. }
  280. } except (EXCEPTION_EXECUTE_HANDLER) {
  281. Status = GetExceptionCode();
  282. }
  283. if ( !NT_SUCCESS(Status) ) {
  284. BaseSetLastNTError( Status );
  285. return( INVALID_ATOM );
  286. }
  287. }
  288. Atom = INVALID_ATOM;
  289. try {
  290. if (UseLocalAtomTable) {
  291. Status = RtlLookupAtomInAtomTable( InternalInitAtomTable(),
  292. UnicodeAtomName->Buffer,
  293. &Atom
  294. );
  295. } else {
  296. if (UnicodeAtomName->Length == 0) {
  297. SetLastError( ERROR_INVALID_NAME );
  298. leave;
  299. }
  300. Status = NtFindAtom( UnicodeAtomName->Buffer,
  301. UnicodeAtomName->Length,
  302. &Atom
  303. );
  304. }
  305. if (!NT_SUCCESS( Status )) {
  306. BaseSetLastNTError( Status );
  307. Atom = INVALID_ATOM;
  308. leave;
  309. }
  310. } finally {
  311. if (!IsUnicodeAtomName && UnicodeAtomName == &UnicodeString) {
  312. RtlFreeUnicodeString( UnicodeAtomName );
  313. }
  314. }
  315. return( (ATOM)Atom );
  316. }
  317. ATOM
  318. InternalDeleteAtom(
  319. BOOLEAN UseLocalAtomTable,
  320. ATOM nAtom
  321. )
  322. {
  323. NTSTATUS Status;
  324. if (nAtom >= MAXINTATOM) {
  325. if (UseLocalAtomTable) {
  326. Status = RtlDeleteAtomFromAtomTable( InternalInitAtomTable(), nAtom );
  327. } else {
  328. Status = NtDeleteAtom( nAtom );
  329. }
  330. if (!NT_SUCCESS( Status )) {
  331. BaseSetLastNTError( Status );
  332. return( INVALID_ATOM );
  333. }
  334. }
  335. return( 0 );
  336. }
  337. UINT
  338. InternalGetAtomName(
  339. BOOLEAN UseLocalAtomTable,
  340. BOOLEAN IsUnicodeAtomName,
  341. ATOM nAtom,
  342. LPSTR AtomName,
  343. DWORD nSize
  344. )
  345. {
  346. NTSTATUS Status;
  347. PVOID FreeBuffer = NULL;
  348. ANSI_STRING AnsiString;
  349. UNICODE_STRING UnicodeString;
  350. PWSTR UnicodeAtomName;
  351. ULONG AtomInfoLength, AtomNameLength;
  352. DWORD ReturnValue;
  353. PATOM_BASIC_INFORMATION AtomInfo;
  354. //
  355. // Trim nSize so that it will not overflow the 16-bit unicode string
  356. // maximum length field. This prevents people that call us with a >=32KB
  357. // query buffer from stubbing their toes when they call the Ansi version
  358. // of the GetAtomName API
  359. //
  360. if (!IsUnicodeAtomName && nSize > 0x7000) {
  361. nSize = 0x7000;
  362. }
  363. if (nSize == 0) {
  364. BaseSetLastNTError( STATUS_BUFFER_OVERFLOW );
  365. return( 0 );
  366. }
  367. if (UseLocalAtomTable) {
  368. if (IsUnicodeAtomName) {
  369. UnicodeAtomName = (PWSTR)AtomName;
  370. } else {
  371. FreeBuffer = RtlAllocateHeap( RtlProcessHeap(),
  372. MAKE_TAG( TMP_TAG ),
  373. nSize * sizeof( WCHAR )
  374. );
  375. if (FreeBuffer == NULL) {
  376. BaseSetLastNTError( STATUS_NO_MEMORY );
  377. return( 0 );
  378. }
  379. UnicodeAtomName = (PWSTR)FreeBuffer;
  380. }
  381. AtomNameLength = nSize * sizeof( WCHAR );
  382. Status = RtlQueryAtomInAtomTable( InternalInitAtomTable(),
  383. nAtom,
  384. NULL,
  385. NULL,
  386. UnicodeAtomName,
  387. &AtomNameLength
  388. );
  389. } else {
  390. AtomInfoLength = sizeof( *AtomInfo ) + (nSize * sizeof( WCHAR ));
  391. FreeBuffer = RtlAllocateHeap( RtlProcessHeap(),
  392. MAKE_TAG( TMP_TAG ),
  393. AtomInfoLength
  394. );
  395. if (FreeBuffer == NULL) {
  396. BaseSetLastNTError( STATUS_NO_MEMORY );
  397. return( 0 );
  398. }
  399. AtomInfo = (PATOM_BASIC_INFORMATION)FreeBuffer;
  400. Status = NtQueryInformationAtom( nAtom,
  401. AtomBasicInformation,
  402. AtomInfo,
  403. AtomInfoLength,
  404. &AtomInfoLength
  405. );
  406. if (NT_SUCCESS( Status )) {
  407. AtomNameLength = (ULONG)AtomInfo->NameLength;
  408. UnicodeAtomName = AtomInfo->Name;
  409. }
  410. }
  411. if (NT_SUCCESS( Status )) {
  412. if (IsUnicodeAtomName) {
  413. ReturnValue = AtomNameLength / sizeof( WCHAR );
  414. if (UnicodeAtomName != (PWSTR)AtomName) {
  415. RtlMoveMemory( AtomName, UnicodeAtomName, AtomNameLength );
  416. }
  417. if (ReturnValue < nSize) {
  418. *((PWSTR)AtomName + ReturnValue) = UNICODE_NULL;
  419. }
  420. } else {
  421. UnicodeString.Buffer = UnicodeAtomName;
  422. UnicodeString.Length = (USHORT)AtomNameLength;
  423. UnicodeString.MaximumLength = (USHORT)(UnicodeString.Length + sizeof( UNICODE_NULL ));
  424. AnsiString.Buffer = AtomName;
  425. AnsiString.Length = 0;
  426. AnsiString.MaximumLength = (USHORT)nSize;
  427. Status = RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeString, FALSE );
  428. if (NT_SUCCESS( Status )) {
  429. ReturnValue = AnsiString.Length;
  430. }
  431. }
  432. }
  433. if (FreeBuffer != NULL) {
  434. RtlFreeHeap( RtlProcessHeap(), 0, FreeBuffer );
  435. }
  436. if (!NT_SUCCESS( Status )) {
  437. BaseSetLastNTError( Status );
  438. return( 0 );
  439. } else {
  440. return( ReturnValue );
  441. }
  442. }