update for HEAD-2003091401
[reactos.git] / 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 <kernel32/kernel32.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    RtlCreateUnicodeStringFromAsciiz(&AtomName,
49                                     (LPSTR)lpString);
50
51    Status = NtAddAtom(AtomName.Buffer,
52                       &Atom);
53    RtlFreeUnicodeString(&AtomName);
54    if (!NT_SUCCESS(Status))
55      {
56         SetLastErrorByStatus(Status);
57         return (ATOM)0;
58      }
59
60    return Atom;
61 }
62
63
64 /*
65  * @implemented
66  */
67 ATOM STDCALL
68 GlobalAddAtomW(LPCWSTR lpString)
69 {
70    ATOM Atom;
71    NTSTATUS Status;
72
73    if (HIWORD((ULONG)lpString) == 0)
74      {
75         if ((ULONG)lpString >= 0xC000)
76           {
77              SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
78              return (ATOM)0;
79           }
80         return (ATOM)LOWORD((ULONG)lpString);
81      }
82
83    Status = NtAddAtom((LPWSTR)lpString,
84                       &Atom);
85    if (!NT_SUCCESS(Status))
86      {
87         SetLastErrorByStatus(Status);
88         return (ATOM)0;
89      }
90
91    return Atom;
92 }
93
94
95 /*
96  * @implemented
97  */
98 ATOM STDCALL
99 GlobalDeleteAtom(ATOM nAtom)
100 {
101    NTSTATUS Status;
102    
103    if (nAtom < 0xC000)
104      {
105         return 0;
106      }
107    
108    Status = NtDeleteAtom(nAtom);
109    if (!NT_SUCCESS(Status))
110      {
111         SetLastErrorByStatus(Status);
112         return nAtom;
113      }
114    
115    return 0;
116 }
117
118
119 /*
120  * @implemented
121  */
122 ATOM STDCALL
123 GlobalFindAtomA(LPCSTR lpString)
124 {
125    UNICODE_STRING AtomName;
126    NTSTATUS Status;
127    ATOM Atom;
128
129    if (HIWORD((ULONG)lpString) == 0)
130      {
131         if ((ULONG)lpString >= 0xC000)
132           {
133              SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
134              return (ATOM)0;
135           }
136         return (ATOM)LOWORD((ULONG)lpString);
137      }
138
139    RtlCreateUnicodeStringFromAsciiz(&AtomName,
140                                     (LPSTR)lpString);
141    Status = NtFindAtom(AtomName.Buffer,
142                        &Atom);
143    RtlFreeUnicodeString(&AtomName);
144    if (!NT_SUCCESS(Status))
145      {
146         SetLastErrorByStatus(Status);
147         return (ATOM)0;
148      }
149
150    return Atom;
151 }
152
153
154 /*
155  * @implemented
156  */
157 ATOM STDCALL
158 GlobalFindAtomW(LPCWSTR lpString)
159 {
160    ATOM Atom;
161    NTSTATUS Status;
162
163    if (HIWORD((ULONG)lpString) == 0)
164      {
165         if ((ULONG)lpString >= 0xC000)
166           {
167              SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
168              return (ATOM)0;
169           }
170         return (ATOM)LOWORD((ULONG)lpString);
171      }
172
173    Status = NtFindAtom((LPWSTR)lpString,
174                        &Atom);
175    if (!NT_SUCCESS(Status))
176      {
177         SetLastErrorByStatus(Status);
178         return (ATOM)0;
179      }
180
181    return Atom;
182 }
183
184
185 UINT STDCALL
186 GlobalGetAtomNameA(ATOM nAtom,
187                    LPSTR lpBuffer,
188                    int nSize)
189 {
190    PATOM_BASIC_INFORMATION Buffer;
191    UNICODE_STRING AtomNameU;
192    ANSI_STRING AtomName;
193    ULONG BufferSize;
194    ULONG ReturnLength;
195    NTSTATUS Status;
196
197    BufferSize = sizeof(ATOM_BASIC_INFORMATION) + nSize * sizeof(WCHAR);
198    Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
199                             HEAP_ZERO_MEMORY,
200                             BufferSize);
201
202    Status = NtQueryInformationAtom(nAtom,
203                                    AtomBasicInformation,
204                                    (PVOID)&Buffer,
205                                    BufferSize,
206                                    &ReturnLength);
207    if (!NT_SUCCESS(Status))
208      {
209         RtlFreeHeap(RtlGetProcessHeap(),
210                     0,
211                     Buffer);
212         return 0;
213      }
214
215    RtlInitUnicodeString(&AtomNameU,
216                         Buffer->Name);
217    AtomName.Buffer = lpBuffer;
218    AtomName.Length = 0;
219    AtomName.MaximumLength = nSize;
220    RtlUnicodeStringToAnsiString(&AtomName,
221                                 &AtomNameU,
222                                 FALSE);
223
224    ReturnLength = AtomName.Length;
225    RtlFreeHeap(RtlGetProcessHeap(),
226                0,
227                Buffer);
228
229    return ReturnLength;
230 }
231
232
233 /*
234  * @implemented
235  */
236 UINT STDCALL
237 GlobalGetAtomNameW(ATOM nAtom,
238                    LPWSTR lpBuffer,
239                    int nSize)
240 {
241    PATOM_BASIC_INFORMATION Buffer;
242    ULONG BufferSize;
243    ULONG ReturnLength;
244    NTSTATUS Status;
245
246    BufferSize = sizeof(ATOM_BASIC_INFORMATION) + nSize * sizeof(WCHAR);
247    Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
248                             HEAP_ZERO_MEMORY,
249                             BufferSize);
250
251    Status = NtQueryInformationAtom(nAtom,
252                                    AtomBasicInformation,
253                                    (PVOID)&Buffer,
254                                    BufferSize,
255                                    &ReturnLength);
256    if (!NT_SUCCESS(Status))
257      {
258         RtlFreeHeap(RtlGetProcessHeap(),
259                     0,
260                     Buffer);
261         return 0;
262      }
263
264    wcscpy(lpBuffer, Buffer->Name);
265    ReturnLength = Buffer->NameLength / sizeof(WCHAR);
266    RtlFreeHeap(RtlGetProcessHeap(),
267                0,
268                Buffer);
269
270    return ReturnLength;
271 }
272
273
274 static PRTL_ATOM_TABLE
275 GetLocalAtomTable(VOID)
276 {
277    if (LocalAtomTable != NULL)
278      {
279         return LocalAtomTable;
280      }
281    RtlCreateAtomTable(37,
282                       &LocalAtomTable);
283    return LocalAtomTable;
284 }
285
286
287 /*
288  * @implemented
289  */
290 BOOL STDCALL
291 InitAtomTable(DWORD nSize)
292 {
293    NTSTATUS Status;
294    
295    /* nSize should be a prime number */
296    
297    if ( nSize < 4 || nSize >= 512 )
298      {
299         nSize = 37;
300      }
301    
302    if (LocalAtomTable == NULL)
303     {
304         Status = RtlCreateAtomTable(nSize,
305                                     &LocalAtomTable);
306         if (!NT_SUCCESS(Status))
307           {
308              SetLastErrorByStatus(Status);
309              return FALSE;
310           }
311     }
312
313   return TRUE;
314 }
315
316
317 /*
318  * @implemented
319  */
320 ATOM STDCALL
321 AddAtomA(LPCSTR lpString)
322 {
323    PRTL_ATOM_TABLE AtomTable;
324    UNICODE_STRING AtomName;
325    NTSTATUS Status;
326    ATOM Atom;
327
328    if (HIWORD((ULONG)lpString) == 0)
329      {
330         if ((ULONG)lpString >= 0xC000)
331           {
332              SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
333              return (ATOM)0;
334           }
335         return (ATOM)LOWORD((ULONG)lpString);
336      }
337
338    AtomTable = GetLocalAtomTable();
339
340    RtlCreateUnicodeStringFromAsciiz(&AtomName,
341                                     (LPSTR)lpString);
342
343    Status = RtlAddAtomToAtomTable(AtomTable,
344                                   AtomName.Buffer,
345                                   &Atom);
346    RtlFreeUnicodeString(&AtomName);
347    if (!NT_SUCCESS(Status))
348      {
349         SetLastErrorByStatus(Status);
350         return (ATOM)0;
351      }
352
353    return Atom;
354 }
355
356
357 /*
358  * @implemented
359  */
360 ATOM STDCALL
361 AddAtomW(LPCWSTR lpString)
362 {
363    PRTL_ATOM_TABLE AtomTable;
364    ATOM Atom;
365    NTSTATUS Status;
366
367    if (HIWORD((ULONG)lpString) == 0)
368      {
369         if ((ULONG)lpString >= 0xC000)
370           {
371              SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
372              return (ATOM)0;
373           }
374         return (ATOM)LOWORD((ULONG)lpString);
375      }
376
377    AtomTable = GetLocalAtomTable();
378
379    Status = RtlAddAtomToAtomTable(AtomTable,
380                                   (LPWSTR)lpString,
381                                   &Atom);
382    if (!NT_SUCCESS(Status))
383      {
384         SetLastErrorByStatus(Status);
385         return (ATOM)0;
386      }
387
388    return Atom;
389 }
390
391
392 /*
393  * @implemented
394  */
395 ATOM STDCALL
396 DeleteAtom(ATOM nAtom)
397 {
398    PRTL_ATOM_TABLE AtomTable;
399    NTSTATUS Status;
400    
401    if (nAtom < 0xC000)
402      {
403         return 0;
404      }
405
406    AtomTable = GetLocalAtomTable();
407
408    Status = RtlDeleteAtomFromAtomTable(AtomTable,
409                                        nAtom);
410    if (!NT_SUCCESS(Status))
411      {
412         SetLastErrorByStatus(Status);
413         return nAtom;
414      }
415    
416    return 0;
417 }
418
419
420 /*
421  * @implemented
422  */
423 ATOM STDCALL
424 FindAtomA(LPCSTR lpString)
425 {
426    PRTL_ATOM_TABLE AtomTable;
427    UNICODE_STRING AtomName;
428    NTSTATUS Status;
429    ATOM Atom;
430
431    if (HIWORD((ULONG)lpString) == 0)
432      {
433         if ((ULONG)lpString >= 0xC000)
434           {
435              SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
436              return (ATOM)0;
437           }
438         return (ATOM)LOWORD((ULONG)lpString);
439      }
440
441    AtomTable = GetLocalAtomTable();
442    RtlCreateUnicodeStringFromAsciiz(&AtomName,
443                                     (LPSTR)lpString);
444    Status = RtlLookupAtomInAtomTable(AtomTable,
445                                      AtomName.Buffer,
446                                      &Atom);
447    RtlFreeUnicodeString(&AtomName);
448    if (!NT_SUCCESS(Status))
449      {
450         SetLastErrorByStatus(Status);
451         return (ATOM)0;
452      }
453
454    return Atom;
455 }
456
457
458 /*
459  * @implemented
460  */
461 ATOM STDCALL
462 FindAtomW(LPCWSTR lpString)
463 {
464    PRTL_ATOM_TABLE AtomTable;
465    ATOM Atom;
466    NTSTATUS Status;
467
468    if (HIWORD((ULONG)lpString) == 0)
469      {
470         if ((ULONG)lpString >= 0xC000)
471           {
472              SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
473              return (ATOM)0;
474           }
475         return (ATOM)LOWORD((ULONG)lpString);
476      }
477
478    AtomTable = GetLocalAtomTable();
479
480    Status = RtlLookupAtomInAtomTable(AtomTable,
481                                      (LPWSTR)lpString,
482                                      &Atom);
483    if (!NT_SUCCESS(Status))
484      {
485         SetLastErrorByStatus(Status);
486         return (ATOM)0;
487      }
488
489    return Atom;
490 }
491
492
493 /*
494  * @implemented
495  */
496 UINT STDCALL
497 GetAtomNameA(ATOM nAtom,
498              LPSTR lpBuffer,
499              int nSize)
500 {
501    PRTL_ATOM_TABLE AtomTable;
502    PWCHAR Buffer;
503    UNICODE_STRING AtomNameU;
504    ANSI_STRING AtomName;
505    ULONG NameLength;
506    NTSTATUS Status;
507
508    AtomTable = GetLocalAtomTable();
509
510    NameLength = nSize * sizeof(WCHAR);
511    Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
512                             HEAP_ZERO_MEMORY,
513                             NameLength);
514
515    Status = RtlQueryAtomInAtomTable(AtomTable,
516                                     nAtom,
517                                     NULL,
518                                     NULL,
519                                     Buffer,
520                                     &NameLength);
521    if (!NT_SUCCESS(Status))
522      {
523         RtlFreeHeap(RtlGetProcessHeap(),
524                     0,
525                     Buffer);
526         return 0;
527      }
528
529    RtlInitUnicodeString(&AtomNameU,
530                         Buffer);
531    AtomName.Buffer = lpBuffer;
532    AtomName.Length = 0;
533    AtomName.MaximumLength = nSize;
534    RtlUnicodeStringToAnsiString(&AtomName,
535                                 &AtomNameU,
536                                 FALSE);
537
538    NameLength = AtomName.Length;
539    RtlFreeHeap(RtlGetProcessHeap(),
540                0,
541                Buffer);
542
543    return NameLength;
544 }
545
546
547 /*
548  * @implemented
549  */
550 UINT STDCALL
551 GetAtomNameW(ATOM nAtom,
552              LPWSTR lpBuffer,
553              int nSize)
554 {
555    PRTL_ATOM_TABLE AtomTable;
556    ULONG NameLength;
557    NTSTATUS Status;
558
559    AtomTable = GetLocalAtomTable();
560
561    NameLength = nSize * sizeof(WCHAR);
562    Status = RtlQueryAtomInAtomTable(AtomTable,
563                                     nAtom,
564                                     NULL,
565                                     NULL,
566                                     lpBuffer,
567                                     &NameLength);
568    if (!NT_SUCCESS(Status))
569      {
570         return 0;
571      }
572
573    return(NameLength / sizeof(WCHAR));
574 }
575
576 /* EOF */