7a4a916f37b869a4112d61d6745c4e1a5604e539
[reactos.git] / reactos / lib / kernel32 / misc / atom.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/misc/atom.c
6 * PURPOSE: Atom functions
7 * PROGRAMMER: Eric Kohl ( ariadne@xs4all.nl)
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 * Full rewrite 27/05/2001
11 */
12
13 #include <k32.h>
14
15 #define NDEBUG
16 #include "../include/debug.h"
17
18
19 /* GLOBALS *******************************************************************/
20
21 static PRTL_ATOM_TABLE LocalAtomTable = NULL;
22
23 static PRTL_ATOM_TABLE GetLocalAtomTable(VOID);
24
25
26 /* FUNCTIONS *****************************************************************/
27
28 /*
29 * @implemented
30 */
31 ATOM STDCALL
32 GlobalAddAtomA(LPCSTR lpString)
33 {
34 UNICODE_STRING AtomName;
35 NTSTATUS Status;
36 ATOM Atom;
37
38 if (HIWORD((ULONG)lpString) == 0)
39 {
40 if ((ULONG)lpString >= 0xC000)
41 {
42 SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
43 return (ATOM)0;
44 }
45 return (ATOM)LOWORD((ULONG)lpString);
46 }
47
48 if (lstrlenA(lpString) > 255)
49 {
50 /* This limit does not exist with NtAddAtom so the limit is probably
51 * added for compability. -Gunnar
52 */
53 SetLastError(ERROR_INVALID_PARAMETER);
54 return (ATOM)0;
55 }
56
57 RtlCreateUnicodeStringFromAsciiz(&AtomName,
58 (LPSTR)lpString);
59
60 Status = NtAddAtom(AtomName.Buffer,
61 AtomName.Length,
62 &Atom);
63 RtlFreeUnicodeString(&AtomName);
64 if (!NT_SUCCESS(Status))
65 {
66 SetLastErrorByStatus(Status);
67 return (ATOM)0;
68 }
69
70 return Atom;
71 }
72
73
74 /*
75 * @implemented
76 */
77 ATOM STDCALL
78 GlobalAddAtomW(LPCWSTR lpString)
79 {
80 ATOM Atom;
81 NTSTATUS Status;
82
83 if (HIWORD((ULONG)lpString) == 0)
84 {
85 if ((ULONG)lpString >= 0xC000)
86 {
87 SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
88 return (ATOM)0;
89 }
90 return (ATOM)LOWORD((ULONG)lpString);
91 }
92
93 if (lstrlenW(lpString) > 255)
94 {
95 /* This limit does not exist with NtAddAtom so the limit is probably
96 * added for compability. -Gunnar
97 */
98 SetLastError(ERROR_INVALID_PARAMETER);
99 return (ATOM)0;
100 }
101
102 Status = NtAddAtom((LPWSTR)lpString,
103 wcslen(lpString),
104 &Atom);
105 if (!NT_SUCCESS(Status))
106 {
107 SetLastErrorByStatus(Status);
108 return (ATOM)0;
109 }
110
111 return Atom;
112 }
113
114
115 /*
116 * @implemented
117 */
118 ATOM STDCALL
119 GlobalDeleteAtom(ATOM nAtom)
120 {
121 NTSTATUS Status;
122
123 if (nAtom < 0xC000)
124 {
125 return 0;
126 }
127
128 Status = NtDeleteAtom(nAtom);
129 if (!NT_SUCCESS(Status))
130 {
131 SetLastErrorByStatus(Status);
132 return nAtom;
133 }
134
135 return 0;
136 }
137
138
139 /*
140 * @implemented
141 */
142 ATOM STDCALL
143 GlobalFindAtomA(LPCSTR lpString)
144 {
145 UNICODE_STRING AtomName;
146 NTSTATUS Status;
147 ATOM Atom;
148
149 if (HIWORD((ULONG)lpString) == 0)
150 {
151 if ((ULONG)lpString >= 0xC000)
152 {
153 SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
154 return (ATOM)0;
155 }
156 return (ATOM)LOWORD((ULONG)lpString);
157 }
158
159 if (lstrlenA(lpString) > 255)
160 {
161 /* This limit does not exist with NtAddAtom so the limit is probably
162 * added for compability. -Gunnar
163 */
164 SetLastError(ERROR_INVALID_PARAMETER);
165 return (ATOM)0;
166 }
167
168 RtlCreateUnicodeStringFromAsciiz(&AtomName,
169 (LPSTR)lpString);
170 Status = NtFindAtom(AtomName.Buffer,
171 AtomName.Length,
172 &Atom);
173 RtlFreeUnicodeString(&AtomName);
174 if (!NT_SUCCESS(Status))
175 {
176 SetLastErrorByStatus(Status);
177 return (ATOM)0;
178 }
179
180 return Atom;
181 }
182
183
184 /*
185 * @implemented
186 */
187 ATOM STDCALL
188 GlobalFindAtomW(LPCWSTR lpString)
189 {
190 ATOM Atom;
191 NTSTATUS Status;
192
193 if (HIWORD((ULONG)lpString) == 0)
194 {
195 if ((ULONG)lpString >= 0xC000)
196 {
197 SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
198 return (ATOM)0;
199 }
200 return (ATOM)LOWORD((ULONG)lpString);
201 }
202
203 if (lstrlenW(lpString) > 255)
204 {
205 /* This limit does not exist with NtAddAtom so the limit is probably
206 * added for compability. -Gunnar
207 */
208 SetLastError(ERROR_INVALID_PARAMETER);
209 return (ATOM)0;
210 }
211
212 Status = NtFindAtom((LPWSTR)lpString,
213 wcslen(lpString),
214 &Atom);
215 if (!NT_SUCCESS(Status))
216 {
217 SetLastErrorByStatus(Status);
218 return (ATOM)0;
219 }
220
221 return Atom;
222 }
223
224
225 UINT STDCALL
226 GlobalGetAtomNameA(ATOM nAtom,
227 LPSTR lpBuffer,
228 int nSize)
229 {
230 PATOM_BASIC_INFORMATION Buffer;
231 UNICODE_STRING AtomNameU;
232 ANSI_STRING AtomName;
233 ULONG BufferSize;
234 ULONG ReturnLength;
235 NTSTATUS Status;
236
237 BufferSize = sizeof(ATOM_BASIC_INFORMATION) + nSize * sizeof(WCHAR);
238 Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
239 HEAP_ZERO_MEMORY,
240 BufferSize);
241 if (Buffer == NULL)
242 {
243 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
244 return 0;
245 }
246
247 Status = NtQueryInformationAtom(nAtom,
248 AtomBasicInformation,
249 Buffer,
250 BufferSize,
251 &ReturnLength);
252 if (!NT_SUCCESS(Status))
253 {
254 RtlFreeHeap(RtlGetProcessHeap(),
255 0,
256 Buffer);
257 SetLastErrorByStatus(Status);
258 return 0;
259 }
260
261 RtlInitUnicodeString(&AtomNameU,
262 Buffer->Name);
263 AtomName.Buffer = lpBuffer;
264 AtomName.Length = 0;
265 AtomName.MaximumLength = nSize;
266 RtlUnicodeStringToAnsiString(&AtomName,
267 &AtomNameU,
268 FALSE);
269
270 ReturnLength = AtomName.Length;
271 RtlFreeHeap(RtlGetProcessHeap(),
272 0,
273 Buffer);
274
275 return ReturnLength;
276 }
277
278
279 /*
280 * @implemented
281 */
282 UINT STDCALL
283 GlobalGetAtomNameW(ATOM nAtom,
284 LPWSTR lpBuffer,
285 int nSize)
286 {
287 PATOM_BASIC_INFORMATION Buffer;
288 ULONG BufferSize;
289 ULONG ReturnLength;
290 NTSTATUS Status;
291
292 BufferSize = sizeof(ATOM_BASIC_INFORMATION) + nSize * sizeof(WCHAR);
293 Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
294 HEAP_ZERO_MEMORY,
295 BufferSize);
296 if (Buffer == NULL)
297 {
298 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
299 return 0;
300 }
301
302 Status = NtQueryInformationAtom(nAtom,
303 AtomBasicInformation,
304 Buffer,
305 BufferSize,
306 &ReturnLength);
307 if (!NT_SUCCESS(Status))
308 {
309 RtlFreeHeap(RtlGetProcessHeap(),
310 0,
311 Buffer);
312 SetLastErrorByStatus(Status);
313 return 0;
314 }
315
316 memcpy(lpBuffer, Buffer->Name, Buffer->NameLength);
317 ReturnLength = Buffer->NameLength / sizeof(WCHAR);
318 *(lpBuffer + ReturnLength) = 0;
319 RtlFreeHeap(RtlGetProcessHeap(),
320 0,
321 Buffer);
322
323 return ReturnLength;
324 }
325
326
327 static PRTL_ATOM_TABLE
328 GetLocalAtomTable(VOID)
329 {
330 if (LocalAtomTable != NULL)
331 {
332 return LocalAtomTable;
333 }
334 RtlCreateAtomTable(37,
335 &LocalAtomTable);
336 return LocalAtomTable;
337 }
338
339
340 /*
341 * @implemented
342 */
343 BOOL STDCALL
344 InitAtomTable(DWORD nSize)
345 {
346 NTSTATUS Status;
347
348 /* nSize should be a prime number */
349
350 if ( nSize < 4 || nSize >= 512 )
351 {
352 nSize = 37;
353 }
354
355 if (LocalAtomTable == NULL)
356 {
357 Status = RtlCreateAtomTable(nSize,
358 &LocalAtomTable);
359 if (!NT_SUCCESS(Status))
360 {
361 SetLastErrorByStatus(Status);
362 return FALSE;
363 }
364 }
365
366 return TRUE;
367 }
368
369
370 /*
371 * @implemented
372 */
373 ATOM STDCALL
374 AddAtomA(LPCSTR lpString)
375 {
376 PRTL_ATOM_TABLE AtomTable;
377 UNICODE_STRING AtomName;
378 NTSTATUS Status;
379 ATOM Atom;
380
381 if (HIWORD((ULONG)lpString) == 0)
382 {
383 if ((ULONG)lpString >= 0xC000)
384 {
385 SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
386 return (ATOM)0;
387 }
388 return (ATOM)LOWORD((ULONG)lpString);
389 }
390
391 AtomTable = GetLocalAtomTable();
392
393 RtlCreateUnicodeStringFromAsciiz(&AtomName,
394 (LPSTR)lpString);
395
396 Status = RtlAddAtomToAtomTable(AtomTable,
397 AtomName.Buffer,
398 &Atom);
399 RtlFreeUnicodeString(&AtomName);
400 if (!NT_SUCCESS(Status))
401 {
402 SetLastErrorByStatus(Status);
403 return (ATOM)0;
404 }
405
406 return Atom;
407 }
408
409
410 /*
411 * @implemented
412 */
413 ATOM STDCALL
414 AddAtomW(LPCWSTR lpString)
415 {
416 PRTL_ATOM_TABLE AtomTable;
417 ATOM Atom;
418 NTSTATUS Status;
419
420 if (HIWORD((ULONG)lpString) == 0)
421 {
422 if ((ULONG)lpString >= 0xC000)
423 {
424 SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
425 return (ATOM)0;
426 }
427 return (ATOM)LOWORD((ULONG)lpString);
428 }
429
430 AtomTable = GetLocalAtomTable();
431
432 Status = RtlAddAtomToAtomTable(AtomTable,
433 (LPWSTR)lpString,
434 &Atom);
435 if (!NT_SUCCESS(Status))
436 {
437 SetLastErrorByStatus(Status);
438 return (ATOM)0;
439 }
440
441 return Atom;
442 }
443
444
445 /*
446 * @implemented
447 */
448 ATOM STDCALL
449 DeleteAtom(ATOM nAtom)
450 {
451 PRTL_ATOM_TABLE AtomTable;
452 NTSTATUS Status;
453
454 if (nAtom < 0xC000)
455 {
456 return 0;
457 }
458
459 AtomTable = GetLocalAtomTable();
460
461 Status = RtlDeleteAtomFromAtomTable(AtomTable,
462 nAtom);
463 if (!NT_SUCCESS(Status))
464 {
465 SetLastErrorByStatus(Status);
466 return nAtom;
467 }
468
469 return 0;
470 }
471
472
473 /*
474 * @implemented
475 */
476 ATOM STDCALL
477 FindAtomA(LPCSTR lpString)
478 {
479 PRTL_ATOM_TABLE AtomTable;
480 UNICODE_STRING AtomName;
481 NTSTATUS Status;
482 ATOM Atom;
483
484 if (HIWORD((ULONG)lpString) == 0)
485 {
486 if ((ULONG)lpString >= 0xC000)
487 {
488 SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
489 return (ATOM)0;
490 }
491 return (ATOM)LOWORD((ULONG)lpString);
492 }
493
494 AtomTable = GetLocalAtomTable();
495 RtlCreateUnicodeStringFromAsciiz(&AtomName,
496 (LPSTR)lpString);
497 Status = RtlLookupAtomInAtomTable(AtomTable,
498 AtomName.Buffer,
499 &Atom);
500 RtlFreeUnicodeString(&AtomName);
501 if (!NT_SUCCESS(Status))
502 {
503 SetLastErrorByStatus(Status);
504 return (ATOM)0;
505 }
506
507 return Atom;
508 }
509
510
511 /*
512 * @implemented
513 */
514 ATOM STDCALL
515 FindAtomW(LPCWSTR lpString)
516 {
517 PRTL_ATOM_TABLE AtomTable;
518 ATOM Atom;
519 NTSTATUS Status;
520
521 if (HIWORD((ULONG)lpString) == 0)
522 {
523 if ((ULONG)lpString >= 0xC000)
524 {
525 SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
526 return (ATOM)0;
527 }
528 return (ATOM)LOWORD((ULONG)lpString);
529 }
530
531 AtomTable = GetLocalAtomTable();
532
533 Status = RtlLookupAtomInAtomTable(AtomTable,
534 (LPWSTR)lpString,
535 &Atom);
536 if (!NT_SUCCESS(Status))
537 {
538 SetLastErrorByStatus(Status);
539 return (ATOM)0;
540 }
541
542 return Atom;
543 }
544
545
546 /*
547 * @implemented
548 */
549 UINT STDCALL
550 GetAtomNameA(ATOM nAtom,
551 LPSTR lpBuffer,
552 int nSize)
553 {
554 PRTL_ATOM_TABLE AtomTable;
555 PWCHAR Buffer;
556 UNICODE_STRING AtomNameU;
557 ANSI_STRING AtomName;
558 ULONG NameLength;
559 NTSTATUS Status;
560
561 AtomTable = GetLocalAtomTable();
562
563 NameLength = nSize * sizeof(WCHAR);
564 Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
565 HEAP_ZERO_MEMORY,
566 NameLength);
567 if (Buffer == NULL)
568 {
569 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
570 return 0;
571 }
572
573 Status = RtlQueryAtomInAtomTable(AtomTable,
574 nAtom,
575 NULL,
576 NULL,
577 Buffer,
578 &NameLength);
579 if (!NT_SUCCESS(Status))
580 {
581 RtlFreeHeap(RtlGetProcessHeap(),
582 0,
583 Buffer);
584 SetLastErrorByStatus(Status);
585 return 0;
586 }
587
588 RtlInitUnicodeString(&AtomNameU,
589 Buffer);
590 AtomName.Buffer = lpBuffer;
591 AtomName.Length = 0;
592 AtomName.MaximumLength = nSize;
593 RtlUnicodeStringToAnsiString(&AtomName,
594 &AtomNameU,
595 FALSE);
596
597 NameLength = AtomName.Length;
598 RtlFreeHeap(RtlGetProcessHeap(),
599 0,
600 Buffer);
601
602 return NameLength;
603 }
604
605
606 /*
607 * @implemented
608 */
609 UINT STDCALL
610 GetAtomNameW(ATOM nAtom,
611 LPWSTR lpBuffer,
612 int nSize)
613 {
614 PRTL_ATOM_TABLE AtomTable;
615 ULONG NameLength;
616 NTSTATUS Status;
617
618 AtomTable = GetLocalAtomTable();
619
620 NameLength = nSize * sizeof(WCHAR);
621 Status = RtlQueryAtomInAtomTable(AtomTable,
622 nAtom,
623 NULL,
624 NULL,
625 lpBuffer,
626 &NameLength);
627 if (!NT_SUCCESS(Status))
628 {
629 return 0;
630 }
631
632 return(NameLength / sizeof(WCHAR));
633 }
634
635 /* EOF */