1 /* $Id: atom.c,v 1.11 2001/03/30 17:26:42 dwelch Exp $
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: Ariadne ( ariadne@xs4all.nl)
8 * modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ]
13 #include <ddk/ntddk.h>
14 #include <kernel32/atom.h>
15 #include <kernel32/proc.h>
16 #include <kernel32/thread.h>
22 * System global and local atom tables.
23 * What does "global" mean? The scope is
24 * the attached process or ANY process?
25 * In the second case, we need to call
29 #define iswlower(c) (c >= L'a' && c <= L'z')
33 static ATOMTABLE GlobalAtomTable
;
34 static ATOMTABLE LocalAtomTable
;
36 /* internal functions */
37 ATOM
GLDeleteAtom(ATOMTABLE
*at
, ATOM nAtom
);
38 ATOM
AWGLAddAtom( ATOMTABLE
*at
, const WCHAR
*lpString
);
39 ATOM
AWGLFindAtom(ATOMTABLE
*at
, const WCHAR
*lpString
);
40 UINT
AWGLGetAtomName(ATOMTABLE
*at
,ATOM atom
, WCHAR
*lpString
, int nSize
);
42 static ATOMENTRY
*GetAtomPointer(ATOMTABLE
*,int);
43 static ATOMID
AtomHashString(const WCHAR
*,int *);
45 #define ATOMBASE 0xcc00
47 int unicode2ansi( char *ansi
,const WCHAR
*uni
, int s
);
48 int ansi2unicode( WCHAR
*uni
,const char *ansi
, int s
);
52 GlobalDeleteAtom(ATOM nAtom
)
54 return GLDeleteAtom(&GlobalAtomTable
, nAtom
);
59 InitAtomTable(DWORD nSize
)
61 /* nSize should be a prime number */
63 if ( nSize
< 4 || nSize
>= 512 )
68 if (LocalAtomTable
.lpDrvData
== NULL
)
70 LocalAtomTable
.lpDrvData
=
71 RtlAllocateHeap(GetProcessHeap(),
72 (HEAP_GENERATE_EXCEPTIONS
| HEAP_ZERO_MEMORY
),
73 (nSize
* sizeof (ATOMENTRY
)));
81 DeleteAtom(ATOM nAtom
)
83 return GLDeleteAtom(&LocalAtomTable
, nAtom
);
87 GlobalAddAtomA(LPCSTR lpString
)
89 UINT BufLen
= strlen(lpString
);
94 (WCHAR
*) RtlAllocateHeap(GetProcessHeap(),
95 (HEAP_GENERATE_EXCEPTIONS
| HEAP_ZERO_MEMORY
),
96 (BufLen
* sizeof (WCHAR
)));
97 ansi2unicode(lpBuffer
, lpString
, BufLen
);
98 atom
= AWGLAddAtom(&GlobalAtomTable
, lpBuffer
);
99 RtlFreeHeap(GetProcessHeap(), 0, lpBuffer
);
104 GlobalAddAtomW(LPCWSTR lpString
)
106 return AWGLAddAtom(&GlobalAtomTable
, lpString
);
111 GlobalFindAtomA(LPCSTR lpString
)
114 UINT BufLen
= strlen(lpString
);
115 WCHAR
*lpBuffer
= (WCHAR
*)RtlAllocateHeap(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,BufLen
*sizeof(WCHAR
));
116 ansi2unicode(lpBuffer
, lpString
,BufLen
);
117 a
= AWGLFindAtom(&GlobalAtomTable
, lpBuffer
);
118 RtlFreeHeap(GetProcessHeap(),0,lpBuffer
);
124 GlobalFindAtomW(const WCHAR
*lpString
)
126 return AWGLFindAtom(&GlobalAtomTable
, lpString
);
132 GlobalGetAtomNameA(ATOM nAtom
,
136 WCHAR
*lpUnicode
= (WCHAR
*)RtlAllocateHeap(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,nSize
*sizeof(WCHAR
));
137 UINT x
= AWGLGetAtomName(&GlobalAtomTable
,nAtom
, lpUnicode
,nSize
);
138 unicode2ansi(lpBuffer
,lpUnicode
,nSize
);
139 RtlFreeHeap(GetProcessHeap(),0,lpUnicode
);
144 GlobalGetAtomNameW(ATOM nAtom
,
148 return AWGLGetAtomName(&GlobalAtomTable
, nAtom
, lpBuffer
, nSize
);
153 AddAtomA(const char *lpString
)
155 UINT BufLen
= strlen(lpString
);
156 WCHAR
*lpBuffer
= (WCHAR
*)RtlAllocateHeap(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,BufLen
*2);
158 ansi2unicode(lpBuffer
, lpString
,BufLen
);
159 a
= AWGLAddAtom(&LocalAtomTable
, lpBuffer
);
160 RtlFreeHeap(GetProcessHeap(),0,lpBuffer
);
166 AddAtomW(const WCHAR
* lpString
)
168 return AWGLAddAtom(&LocalAtomTable
, lpString
);
172 FindAtomA(const char *lpString
)
174 UINT BufLen
= strlen(lpString
);
175 WCHAR
*lpBuffer
= (WCHAR
*)RtlAllocateHeap(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,BufLen
*2);
177 ansi2unicode(lpBuffer
, lpString
,BufLen
);
178 a
= AWGLFindAtom(&LocalAtomTable
, lpBuffer
);
179 RtlFreeHeap(GetProcessHeap(),0,lpBuffer
);
184 FindAtomW(const WCHAR
* lpString
)
186 return AWGLFindAtom(&LocalAtomTable
, lpString
);
190 GetAtomNameA(ATOM nAtom
,
194 LPWSTR lpUnicode
= (WCHAR
*)RtlAllocateHeap(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,nSize
*2);
195 UINT x
= AWGLGetAtomName(&GlobalAtomTable
, nAtom
,lpUnicode
,nSize
);
196 unicode2ansi(lpBuffer
,lpUnicode
,nSize
);
197 RtlFreeHeap(GetProcessHeap(),0,lpUnicode
);
202 GetAtomNameW(ATOM nAtom
,
206 return AWGLGetAtomName(&LocalAtomTable
,nAtom
,lpBuffer
, nSize
);
210 GLDeleteAtom(ATOMTABLE
*at
, ATOM nAtom
)
214 /* a free slot has q == 0 && refcnt == 0 */
215 if((lp
= GetAtomPointer(at
,nAtom
- ATOMBASE
))) {
219 if(lp
->refcnt
== 0) {
220 RtlFreeHeap(GetProcessHeap(),0,at
->AtomTable
);
221 at
->AtomTable
= NULL
;
222 RtlFreeHeap(GetProcessHeap(),0,at
->AtomData
);
232 AWGLAddAtom(ATOMTABLE
*at
, const WCHAR
*lpString
)
236 LPATOMENTRY lp
,lpfree
;
241 /* if we already have it, bump refcnt */
242 if((atom
= AWGLFindAtom(at
, lpString
)))
244 lp
= GetAtomPointer(at
,atom
- ATOMBASE
);
245 if(lp
->idsize
) lp
->refcnt
++;
249 /* add to a free slot */
250 q
= AtomHashString(lpString
,&atomlen
);
255 for(index
= 0;(lp
= GetAtomPointer(at
,index
));index
++)
257 if(lp
->q
== 0 && lp
->refcnt
== 0)
259 if(lp
->idsize
> atomlen
)
262 (lpfree
->idsize
> lp
->idsize
))
270 /* intatoms do not take space in data, but do get new entries */
271 /* an INTATOM will have length of 0 */
272 if(lpfree
&& atomlen
)
276 lstrcpynW(&at
->AtomData
[lpfree
->idx
],lpString
,atomlen
);
277 return freeindex
+ ATOMBASE
;
280 /* no space was available, or we have an INTATOM */
281 /* so expand or create the table */
282 if(at
->AtomTable
== 0)
284 at
->AtomTable
= (ATOMENTRY
*) RtlAllocateHeap(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,sizeof(ATOMENTRY
));
292 at
->AtomTable
= (ATOMENTRY
*) RtlReAllocateHeap(GetProcessHeap(),0,
293 (LPVOID
) at
->AtomTable
,
294 at
->TableSize
* sizeof(ATOMENTRY
));
295 lp
= &at
->AtomTable
[at
->TableSize
- 1];
298 /* set in the entry */
301 lp
->idsize
= atomlen
;
304 /* add an entry if not intatom... */
306 newlen
= at
->DataSize
+ atomlen
;
308 if(at
->AtomData
== 0) {
309 at
->AtomData
= (WCHAR
*) RtlAllocateHeap(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,newlen
*2);
313 at
->AtomData
= (WCHAR
*) RtlReAllocateHeap(GetProcessHeap(),0,at
->AtomData
,newlen
*2);
314 lp
->idx
= at
->DataSize
;
317 lstrcpyW(&at
->AtomData
[lp
->idx
],lpString
);
318 at
->DataSize
= newlen
;
321 return index
+ ATOMBASE
;
334 AWGLFindAtom(ATOMTABLE
*at
, const WCHAR
*lpString
)
343 /* convert string to 'q', and get length */
344 q
= AtomHashString(lpString
,&atomlen
);
346 /* find the q value, note: this could be INTATOM */
347 /* if q matches, then do case insensitive compare*/
348 for(index
= 0;(lp
= GetAtomPointer(at
,index
));index
++) {
350 if(HIWORD(lpString
) == 0)
351 return ATOMBASE
+ index
;
352 if(lstrcmpiW(&at
->AtomData
[lp
->idx
],lpString
) == 0)
353 return ATOMBASE
+ index
;
361 AWGLGetAtomName(ATOMTABLE
*at
, ATOM atom
, WCHAR
*lpString
,int len
)
370 /* return the atom name, or create the INTATOM */
371 if((lp
= GetAtomPointer(at
,atom
- ATOMBASE
))) {
373 atomlen
= lstrlenW(atomstr
= &at
->AtomData
[lp
->idx
]);
375 lstrcpyW(lpString
,atomstr
);
377 lstrcpynW(lpString
,atomstr
,len
-1);
378 lpString
[len
-1] = '\0';
380 return (UINT
)lstrlenW(lpString
);
382 //wsprintf((wchar *)lpString,"#%d",lp->q);
383 return (UINT
)lstrlenW(lpString
);
390 /********************************************************/
391 /* convert alphanumeric string to a 'q' value. */
392 /* 'q' values do not need to be unique, they just limit */
393 /* the search we need to make to find a string */
394 /********************************************************/
397 AtomHashString(const WCHAR
* lp
,int *lplen
)
403 /* if we have an intatom... */
404 if(HIWORD(lp
) == 0) {
405 if(lplen
) *lplen
= 0;
409 /* convert the string to an internal representation */
410 for(p
=(WCHAR
*)lp
,q
=0,len
=0;(p
++,ch
=*p
++);len
++)
411 q
= (q
<<1) + iswlower(ch
)?towupper(ch
):ch
;
413 /* 0 is reserved for empty slots */
417 /* avoid strlen later */
418 /* check out with unicode */
425 /********************************************************/
426 /* convert an atom index into a pointer into an */
427 /* atom table. This validates the pointer is in */
428 /* range, and that the data is accessible */
429 /********************************************************/
432 GetAtomPointer(ATOMTABLE
*at
,int index
)
436 /* if no table, then no pointers */
437 if(at
->AtomTable
== 0)
441 if((index
< 0) || (index
>= at
->TableSize
))
444 /* we have a pointer */
445 lp
= &at
->AtomTable
[index
];
448 /* is the index past stored data, validity check */
449 /* LATER: is the size of the entry within the available space */
450 if(lp
->idx
> at
->DataSize
)
456 int ansi2unicode( WCHAR
*uni
,const char *ansi
, int s
)
461 uni
[i
] = (WCHAR
)ansi
[i
];
466 unicode2ansi( char *ansi
,const WCHAR
*uni
, int s
)
471 ansi
[i
] = (char)uni
[i
];