blob: 0e79a596980cc92cbfcd20861813c72c5acbf059 [file] [log] [blame]
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001/*
2 * Atom table functions
3 *
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00004 * Copyright 1993, 1994, 1995 Alexandre Julliard
Alexandre Julliard5f721f81994-01-04 20:14:34 +00005 */
6
7/*
Alexandre Julliard808cb041995-08-17 17:11:36 +00008 * Warning: The code assumes that LocalAlloc() returns a block aligned
9 * on a 4-bytes boundary (because of the shifting done in
10 * HANDLETOATOM). If this is not the case, the allocation code will
11 * have to be changed.
Alexandre Julliard5f721f81994-01-04 20:14:34 +000012 */
13
14#include <stdlib.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000015#include <stdio.h>
Alexandre Julliard5f721f81994-01-04 20:14:34 +000016#include <string.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000017#include <ctype.h>
Alexandre Julliard5f721f81994-01-04 20:14:34 +000018
Jeremy Whited3e22d92000-02-10 19:03:02 +000019#include "windef.h"
Alexandre Julliard072dfb52000-09-25 23:30:56 +000020#include "winnls.h"
Patrik Stridvallfdcfdb91999-06-12 14:55:11 +000021#include "wine/winbase16.h"
Alexandre Julliardc7e7df82000-08-14 14:41:19 +000022#include "wine/unicode.h"
Alexandre Julliardb849d792000-02-13 13:56:13 +000023#include "winerror.h"
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000024#include "instance.h"
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000025#include "stackframe.h"
Alexandre Julliard15657091999-05-23 10:25:25 +000026#include "debugtools.h"
Alexandre Julliardb849d792000-02-13 13:56:13 +000027#include "server.h"
Alexandre Julliard5f721f81994-01-04 20:14:34 +000028
Alexandre Julliardb849d792000-02-13 13:56:13 +000029DEFAULT_DEBUG_CHANNEL(atom);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000030
Alexandre Julliard5f721f81994-01-04 20:14:34 +000031#define DEFAULT_ATOMTABLE_SIZE 37
32#define MIN_STR_ATOM 0xc000
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000033#define MAX_ATOM_LEN 255
Alexandre Julliard5f721f81994-01-04 20:14:34 +000034
Alexandre Julliard8bbf8181996-09-13 16:50:47 +000035#define ATOMTOHANDLE(atom) ((HANDLE16)(atom) << 2)
Alexandre Julliard5f721f81994-01-04 20:14:34 +000036#define HANDLETOATOM(handle) ((ATOM)(0xc000 | ((handle) >> 2)))
37
Alexandre Julliard737fa071998-11-15 17:29:15 +000038typedef struct
39{
40 HANDLE16 next;
41 WORD refCount;
42 BYTE length;
43 BYTE str[1];
44} ATOMENTRY;
45
46typedef struct
47{
48 WORD size;
49 HANDLE16 entries[1];
50} ATOMTABLE;
Alexandre Julliardded30381995-07-06 17:18:27 +000051
Alexandre Julliardb849d792000-02-13 13:56:13 +000052static WORD ATOM_UserDS = 0; /* USER data segment */
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000053
Alexandre Julliard5f721f81994-01-04 20:14:34 +000054/***********************************************************************
55 * ATOM_Init
56 *
57 * Global table initialisation.
58 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000059BOOL ATOM_Init( WORD globalTableSel )
Alexandre Julliard5f721f81994-01-04 20:14:34 +000060{
Alexandre Julliardb849d792000-02-13 13:56:13 +000061 ATOM_UserDS = globalTableSel;
62 return TRUE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000063}
64
65
66/***********************************************************************
67 * ATOM_GetTable
68 *
69 * Return a pointer to the atom table of a given segment, creating
70 * it if necessary.
Alexandre Julliard54c27111998-03-29 19:44:57 +000071 *
72 * RETURNS
73 * Pointer to table: Success
74 * NULL: Failure
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000075 */
Alexandre Julliardb849d792000-02-13 13:56:13 +000076static ATOMTABLE *ATOM_GetTable( BOOL create /* [in] Create */ )
Alexandre Julliard737fa071998-11-15 17:29:15 +000077{
Alexandre Julliard982a2232000-12-13 20:20:09 +000078 INSTANCEDATA *ptr = MapSL( MAKESEGPTR( CURRENT_DS, 0 ) );
Alexandre Julliard737fa071998-11-15 17:29:15 +000079 if (ptr->atomtable)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000080 {
Alexandre Julliard737fa071998-11-15 17:29:15 +000081 ATOMTABLE *table = (ATOMTABLE *)((char *)ptr + ptr->atomtable);
82 if (table->size) return table;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000083 }
Alexandre Julliard737fa071998-11-15 17:29:15 +000084 if (!create) return NULL;
Alexandre Julliardb849d792000-02-13 13:56:13 +000085 if (!InitAtomTable16( 0 )) return NULL;
Alexandre Julliard737fa071998-11-15 17:29:15 +000086 /* Reload ptr in case it moved in linear memory */
Alexandre Julliard982a2232000-12-13 20:20:09 +000087 ptr = MapSL( MAKESEGPTR( CURRENT_DS, 0 ) );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000088 return (ATOMTABLE *)((char *)ptr + ptr->atomtable);
Alexandre Julliard5f721f81994-01-04 20:14:34 +000089}
90
91
92/***********************************************************************
Alexandre Julliard5f721f81994-01-04 20:14:34 +000093 * ATOM_Hash
Alexandre Julliard54c27111998-03-29 19:44:57 +000094 * RETURNS
95 * The hash value for the input string
Alexandre Julliard5f721f81994-01-04 20:14:34 +000096 */
Alexandre Julliard54c27111998-03-29 19:44:57 +000097static WORD ATOM_Hash(
98 WORD entries, /* [in] Total number of entries */
99 LPCSTR str, /* [in] Pointer to string to hash */
100 WORD len /* [in] Length of string */
101) {
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000102 WORD i, hash = 0;
103
Alexandre Julliard15657091999-05-23 10:25:25 +0000104 TRACE("%x, %s, %x\n", entries, str, len);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000105
Alexandre Julliardcdd09231994-01-12 11:12:51 +0000106 for (i = 0; i < len; i++) hash ^= toupper(str[i]) + i;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000107 return hash % entries;
108}
109
110
111/***********************************************************************
Alexandre Julliardb849d792000-02-13 13:56:13 +0000112 * ATOM_IsIntAtomA
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000113 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000114static BOOL ATOM_IsIntAtomA(LPCSTR atomstr,WORD *atomid)
115{
116 UINT atom = 0;
117 if (!HIWORD(atomstr)) atom = LOWORD(atomstr);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000118 else
119 {
Alexandre Julliardb849d792000-02-13 13:56:13 +0000120 if (*atomstr++ != '#') return FALSE;
121 while (*atomstr >= '0' && *atomstr <= '9')
122 {
123 atom = atom * 10 + *atomstr - '0';
124 atomstr++;
125 }
126 if (*atomstr) return FALSE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000127 }
Alexandre Julliardb849d792000-02-13 13:56:13 +0000128 if (!atom || (atom >= MIN_STR_ATOM))
129 {
130 SetLastError( ERROR_INVALID_PARAMETER );
131 atom = 0;
132 }
133 *atomid = atom;
134 return TRUE;
135}
136
137
138/***********************************************************************
139 * ATOM_IsIntAtomW
140 */
141static BOOL ATOM_IsIntAtomW(LPCWSTR atomstr,WORD *atomid)
142{
143 UINT atom = 0;
144 if (!HIWORD(atomstr)) atom = LOWORD(atomstr);
145 else
146 {
147 if (*atomstr++ != '#') return FALSE;
148 while (*atomstr >= '0' && *atomstr <= '9')
149 {
150 atom = atom * 10 + *atomstr - '0';
151 atomstr++;
152 }
153 if (*atomstr) return FALSE;
154 }
155 if (!atom || (atom >= MIN_STR_ATOM))
156 {
157 SetLastError( ERROR_INVALID_PARAMETER );
158 atom = 0;
159 }
160 *atomid = atom;
161 return TRUE;
162}
163
164
165/***********************************************************************
166 * ATOM_MakePtr
167 *
168 * Make an ATOMENTRY pointer from a handle (obtained from GetAtomHandle()).
169 */
170static inline ATOMENTRY *ATOM_MakePtr( HANDLE16 handle /* [in] Handle */ )
171{
Alexandre Julliard982a2232000-12-13 20:20:09 +0000172 return MapSL( MAKESEGPTR( CURRENT_DS, handle ) );
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000173}
174
175
176/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000177 * InitAtomTable16 (KERNEL.68)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000178 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000179WORD WINAPI InitAtomTable16( WORD entries )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000180{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000181 int i;
182 HANDLE16 handle;
183 ATOMTABLE *table;
184
185 /* We consider the first table to be initialized as the global table.
186 * This works, as USER (both built-in and native) is the first one to
187 * register ...
188 */
189
190 if (!ATOM_UserDS)
191 {
192 ATOM_UserDS = CURRENT_DS;
193 /* return dummy local handle */
194 return LocalAlloc16( LMEM_FIXED, 1 );
195 }
196
197 /* Allocate the table */
198
Alexandre Julliard737fa071998-11-15 17:29:15 +0000199 if (!entries) entries = DEFAULT_ATOMTABLE_SIZE; /* sanity check */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000200 handle = LocalAlloc16( LMEM_FIXED, sizeof(ATOMTABLE) + (entries-1) * sizeof(HANDLE16) );
201 if (!handle) return 0;
Alexandre Julliard982a2232000-12-13 20:20:09 +0000202 table = MapSL( MAKESEGPTR( CURRENT_DS, handle ) );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000203 table->size = entries;
204 for (i = 0; i < entries; i++) table->entries[i] = 0;
205
206 /* Store a pointer to the table in the instance data */
207
Alexandre Julliard982a2232000-12-13 20:20:09 +0000208 ((INSTANCEDATA *)MapSL( MAKESEGPTR( CURRENT_DS, 0 )))->atomtable = handle;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000209 return handle;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000210}
211
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000212/***********************************************************************
213 * GetAtomHandle (KERNEL.73)
214 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000215HANDLE16 WINAPI GetAtomHandle16( ATOM atom )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000216{
217 if (atom < MIN_STR_ATOM) return 0;
218 return ATOMTOHANDLE( atom );
219}
220
221
222/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000223 * AddAtom16 (KERNEL.70)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000224 *
225 * Windows DWORD aligns the atom entry size.
226 * The remaining unused string space created by the alignment
227 * gets padded with '\0's in a certain way to ensure
228 * that at least one trailing '\0' remains.
229 *
230 * RETURNS
231 * Atom: Success
232 * 0: Failure
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000233 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000234ATOM WINAPI AddAtom16( LPCSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000235{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000236 char buffer[MAX_ATOM_LEN+1];
237 WORD hash;
238 HANDLE16 entry;
239 ATOMENTRY * entryPtr;
240 ATOMTABLE * table;
241 int len, ae_len;
242 WORD iatom;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000243
Alexandre Julliardb849d792000-02-13 13:56:13 +0000244 if (ATOM_IsIntAtomA( str, &iatom )) return iatom;
245
246 TRACE("%s\n",debugstr_a(buffer));
247
248 /* Make a copy of the string to be sure it doesn't move in linear memory. */
249 lstrcpynA( buffer, str, sizeof(buffer) );
250
251 len = strlen( buffer );
252 if (!(table = ATOM_GetTable( TRUE ))) return 0;
Alexandre Julliardbcb7f4e2000-02-19 20:51:29 +0000253 if (CURRENT_DS == ATOM_UserDS) return GlobalAddAtomA( str );
254
Alexandre Julliardb849d792000-02-13 13:56:13 +0000255 hash = ATOM_Hash( table->size, buffer, len );
256 entry = table->entries[hash];
257 while (entry)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000258 {
Alexandre Julliardb849d792000-02-13 13:56:13 +0000259 entryPtr = ATOM_MakePtr( entry );
260 if ((entryPtr->length == len) &&
Alexandre Julliard072dfb52000-09-25 23:30:56 +0000261 (!strncasecmp( entryPtr->str, buffer, len )))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000262 {
263 entryPtr->refCount++;
264 TRACE("-- existing 0x%x\n", entry);
265 return HANDLETOATOM( entry );
266 }
267 entry = entryPtr->next;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000268 }
Alexandre Julliardb849d792000-02-13 13:56:13 +0000269
270 ae_len = (sizeof(ATOMENTRY)+len+3) & ~3;
271 entry = LocalAlloc16( LMEM_FIXED, ae_len );
272 if (!entry) return 0;
273 /* Reload the table ptr in case it moved in linear memory */
274 table = ATOM_GetTable( FALSE );
275 entryPtr = ATOM_MakePtr( entry );
276 entryPtr->next = table->entries[hash];
277 entryPtr->refCount = 1;
278 entryPtr->length = len;
279 /* Some applications _need_ the '\0' padding provided by this strncpy */
280 strncpy( entryPtr->str, buffer, ae_len - sizeof(ATOMENTRY) + 1 );
281 entryPtr->str[ae_len - sizeof(ATOMENTRY)] = '\0';
282 table->entries[hash] = entry;
283 TRACE("-- new 0x%x\n", entry);
284 return HANDLETOATOM( entry );
285}
286
287
288/***********************************************************************
289 * DeleteAtom16 (KERNEL.71)
290 */
291ATOM WINAPI DeleteAtom16( ATOM atom )
292{
293 ATOMENTRY * entryPtr;
294 ATOMTABLE * table;
295 HANDLE16 entry, *prevEntry;
296 WORD hash;
297
298 if (atom < MIN_STR_ATOM) return 0; /* Integer atom */
299 if (CURRENT_DS == ATOM_UserDS) return GlobalDeleteAtom( atom );
300
301 TRACE("0x%x\n",atom);
302
303 if (!(table = ATOM_GetTable( FALSE ))) return 0;
304 entry = ATOMTOHANDLE( atom );
305 entryPtr = ATOM_MakePtr( entry );
306
307 /* Find previous atom */
308 hash = ATOM_Hash( table->size, entryPtr->str, entryPtr->length );
309 prevEntry = &table->entries[hash];
310 while (*prevEntry && *prevEntry != entry)
311 {
312 ATOMENTRY * prevEntryPtr = ATOM_MakePtr( *prevEntry );
313 prevEntry = &prevEntryPtr->next;
314 }
315 if (!*prevEntry) return atom;
316
317 /* Delete atom */
318 if (--entryPtr->refCount == 0)
319 {
320 *prevEntry = entryPtr->next;
321 LocalFree16( entry );
322 }
323 return 0;
324}
325
326
327/***********************************************************************
328 * FindAtom16 (KERNEL.69)
329 */
330ATOM WINAPI FindAtom16( LPCSTR str )
331{
332 ATOMTABLE * table;
333 WORD hash,iatom;
334 HANDLE16 entry;
335 int len;
336
337 if (CURRENT_DS == ATOM_UserDS) return GlobalFindAtomA( str );
338
339 TRACE("%s\n",debugres_a(str));
340
341 if (ATOM_IsIntAtomA( str, &iatom )) return iatom;
342 if ((len = strlen( str )) > 255) len = 255;
343 if (!(table = ATOM_GetTable( FALSE ))) return 0;
344 hash = ATOM_Hash( table->size, str, len );
345 entry = table->entries[hash];
346 while (entry)
347 {
348 ATOMENTRY * entryPtr = ATOM_MakePtr( entry );
349 if ((entryPtr->length == len) &&
Alexandre Julliard072dfb52000-09-25 23:30:56 +0000350 (!strncasecmp( entryPtr->str, str, len )))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000351 {
352 TRACE("-- found %x\n", entry);
353 return HANDLETOATOM( entry );
354 }
355 entry = entryPtr->next;
356 }
357 TRACE("-- not found\n");
358 return 0;
359}
360
361
362/***********************************************************************
363 * GetAtomName16 (KERNEL.72)
364 */
365UINT16 WINAPI GetAtomName16( ATOM atom, LPSTR buffer, INT16 count )
366{
367 ATOMTABLE * table;
368 ATOMENTRY * entryPtr;
369 HANDLE16 entry;
370 char * strPtr;
371 UINT len;
372 char text[8];
373
374 if (CURRENT_DS == ATOM_UserDS) return GlobalGetAtomNameA( atom, buffer, count );
375
376 TRACE("%x\n",atom);
377
378 if (!count) return 0;
379 if (atom < MIN_STR_ATOM)
380 {
381 sprintf( text, "#%d", atom );
382 len = strlen(text);
383 strPtr = text;
384 }
385 else
386 {
387 if (!(table = ATOM_GetTable( FALSE ))) return 0;
388 entry = ATOMTOHANDLE( atom );
389 entryPtr = ATOM_MakePtr( entry );
390 len = entryPtr->length;
391 strPtr = entryPtr->str;
392 }
393 if (len >= count) len = count-1;
394 memcpy( buffer, strPtr, len );
395 buffer[len] = '\0';
396 return len;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000397}
398
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000399/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000400 * InitAtomTable (KERNEL32.@)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000401 */
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000402BOOL WINAPI InitAtomTable( DWORD entries )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000403{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000404 BOOL ret;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000405 SERVER_START_REQ( init_atom_table )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000406 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000407 req->entries = entries;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000408 ret = !SERVER_CALL_ERR();
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000409 }
410 SERVER_END_REQ;
411 return ret;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000412}
413
414
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000415static ATOM ATOM_AddAtomA( LPCSTR str, BOOL local )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000416{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000417 ATOM atom = 0;
418 if (!ATOM_IsIntAtomA( str, &atom ))
419 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000420 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), NULL, 0 );
421 if (len > MAX_ATOM_LEN)
422 {
423 SetLastError( ERROR_INVALID_PARAMETER );
424 return 0;
425 }
Alexandre Julliard67a74992001-02-27 02:09:16 +0000426 SERVER_START_VAR_REQ( add_atom, len * sizeof(WCHAR) )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000427 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000428 MultiByteToWideChar( CP_ACP, 0, str, strlen(str), server_data_ptr(req), len );
429 req->local = local;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000430 if (!SERVER_CALL_ERR()) atom = req->atom + MIN_STR_ATOM;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000431 }
Alexandre Julliard67a74992001-02-27 02:09:16 +0000432 SERVER_END_VAR_REQ;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000433 }
434 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom );
435 return atom;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000436}
437
438
439/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000440 * GlobalAddAtomA (USER.268)
441 * GlobalAddAtomA (KERNEL32.@)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000442 *
Alexandre Julliard54c27111998-03-29 19:44:57 +0000443 * Adds a character string to the global atom table and returns a unique
444 * value identifying the string.
445 *
446 * RETURNS
447 * Atom: Success
448 * 0: Failure
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000449 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000450ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
451{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000452 return ATOM_AddAtomA( str, FALSE );
453}
454
455
456/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000457 * AddAtomA (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000458 * Adds a string to the atom table and returns the atom identifying the
459 * string.
460 *
461 * RETURNS
462 * Atom: Success
463 * 0: Failure
464 */
465ATOM WINAPI AddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
466{
467 return ATOM_AddAtomA( str, TRUE );
468}
469
470
471static ATOM ATOM_AddAtomW( LPCWSTR str, BOOL local )
472{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000473 ATOM atom = 0;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000474 if (!ATOM_IsIntAtomW( str, &atom ))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000475 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000476 DWORD len = strlenW(str);
477 if (len > MAX_ATOM_LEN)
478 {
479 SetLastError( ERROR_INVALID_PARAMETER );
480 return 0;
481 }
Alexandre Julliard67a74992001-02-27 02:09:16 +0000482 SERVER_START_VAR_REQ( add_atom, len * sizeof(WCHAR) )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000483 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000484 memcpy( server_data_ptr(req), str, len * sizeof(WCHAR) );
485 req->local = local;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000486 if (!SERVER_CALL_ERR()) atom = req->atom + MIN_STR_ATOM;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000487 }
Alexandre Julliard67a74992001-02-27 02:09:16 +0000488 SERVER_END_VAR_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000489 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000490 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000491 return atom;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000492}
493
494
495/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000496 * GlobalAddAtomW (KERNEL32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000497 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000498ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000499{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000500 return ATOM_AddAtomW( str, FALSE );
501}
502
503
504/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000505 * AddAtomW (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000506 */
507ATOM WINAPI AddAtomW( LPCWSTR str )
508{
509 return ATOM_AddAtomW( str, TRUE );
510}
511
512
513static ATOM ATOM_DeleteAtom( ATOM atom, BOOL local)
514{
Andreas Mohrc9cf70d2001-01-26 20:40:50 +0000515 TRACE( "(%s) %x\n", local ? "local" : "global", atom );
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000516 if (atom < MIN_STR_ATOM) atom = 0;
517 else
Alexandre Julliardb849d792000-02-13 13:56:13 +0000518 {
Alexandre Julliard67a74992001-02-27 02:09:16 +0000519 SERVER_START_REQ( delete_atom )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000520 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000521 req->atom = atom - MIN_STR_ATOM;
522 req->local = local;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000523 if (!SERVER_CALL_ERR()) atom = 0;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000524 }
525 SERVER_END_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000526 }
Alexandre Julliardb849d792000-02-13 13:56:13 +0000527 return atom;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000528}
529
530
531/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000532 * GlobalDeleteAtom (USER.269)
533 * GlobalDeleteAtom (KERNEL32.@)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000534 * Decrements the reference count of a string atom. If the count is
535 * zero, the string associated with the atom is removed from the table.
536 *
537 * RETURNS
538 * 0: Success
539 * Atom: Failure
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000540 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000541ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000542{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000543 return ATOM_DeleteAtom( atom, FALSE);
544}
545
546
547/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000548 * DeleteAtom (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000549 * Decrements the reference count of a string atom. If count becomes
550 * zero, the string associated with the atom is removed from the table.
551 *
552 * RETURNS
553 * 0: Success
554 * Atom: Failure
555 */
556ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ )
557{
558 return ATOM_DeleteAtom( atom, TRUE );
559}
560
561
562static ATOM ATOM_FindAtomA( LPCSTR str, BOOL local )
563{
564 ATOM atom = 0;
565 if (!ATOM_IsIntAtomA( str, &atom ))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000566 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000567 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), NULL, 0 );
568 if (len > MAX_ATOM_LEN)
569 {
570 SetLastError( ERROR_INVALID_PARAMETER );
571 return 0;
572 }
Alexandre Julliard67a74992001-02-27 02:09:16 +0000573 SERVER_START_VAR_REQ( find_atom, len * sizeof(WCHAR) )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000574 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000575 MultiByteToWideChar( CP_ACP, 0, str, strlen(str), server_data_ptr(req), len );
576 req->local = local;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000577 if (!SERVER_CALL_ERR()) atom = req->atom + MIN_STR_ATOM;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000578 }
Alexandre Julliard67a74992001-02-27 02:09:16 +0000579 SERVER_END_VAR_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000580 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000581 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000582 return atom;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000583}
584
585
586/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000587 * GlobalFindAtomA (USER.270)
588 * GlobalFindAtomA (KERNEL32.@)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000589 *
Alexandre Julliard54c27111998-03-29 19:44:57 +0000590 * Searches the atom table for the string and returns the atom
591 * associated with it.
592 *
593 * RETURNS
594 * Atom: Success
595 * 0: Failure
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000596 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000597ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ )
598{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000599 return ATOM_FindAtomA( str, FALSE );
600}
601
602/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000603 * FindAtomA (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000604 * Searches the local atom table for the string and returns the atom
605 * associated with that string.
606 *
607 * RETURNS
608 * Atom: Success
609 * 0: Failure
610 */
611ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ )
612{
613 return ATOM_FindAtomA( str, TRUE );
614}
615
616
617static ATOM ATOM_FindAtomW( LPCWSTR str, BOOL local )
618{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000619 ATOM atom = 0;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000620 if (!ATOM_IsIntAtomW( str, &atom ))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000621 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000622 DWORD len = strlenW(str);
623 if (len > MAX_ATOM_LEN)
624 {
625 SetLastError( ERROR_INVALID_PARAMETER );
626 return 0;
627 }
Alexandre Julliard67a74992001-02-27 02:09:16 +0000628 SERVER_START_VAR_REQ( find_atom, len * sizeof(WCHAR) )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000629 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000630 memcpy( server_data_ptr(req), str, len * sizeof(WCHAR) );
631 req->local = local;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000632 if (!SERVER_CALL_ERR()) atom = req->atom + MIN_STR_ATOM;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000633 }
Alexandre Julliard67a74992001-02-27 02:09:16 +0000634 SERVER_END_VAR_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000635 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000636 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000637 return atom;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000638}
639
640
641/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000642 * GlobalFindAtomW (KERNEL32.@)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000643 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000644ATOM WINAPI GlobalFindAtomW( LPCWSTR str )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000645{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000646 return ATOM_FindAtomW( str, FALSE );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000647}
648
649
650/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000651 * FindAtomW (KERNEL32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000652 */
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000653ATOM WINAPI FindAtomW( LPCWSTR str )
654{
655 return ATOM_FindAtomW( str, TRUE );
656}
657
658
659static UINT ATOM_GetAtomNameA( ATOM atom, LPSTR buffer, INT count, BOOL local )
Alexandre Julliardb849d792000-02-13 13:56:13 +0000660{
661 INT len;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000662
663 if (count <= 0)
664 {
665 SetLastError( ERROR_MORE_DATA );
666 return 0;
667 }
Alexandre Julliardb849d792000-02-13 13:56:13 +0000668 if (atom < MIN_STR_ATOM)
669 {
670 char name[8];
671 if (!atom)
672 {
673 SetLastError( ERROR_INVALID_PARAMETER );
674 return 0;
675 }
676 len = sprintf( name, "#%d", atom );
677 lstrcpynA( buffer, name, count );
678 }
679 else
680 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000681 len = 0;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000682 SERVER_START_VAR_REQ( get_atom_name, MAX_ATOM_LEN * sizeof(WCHAR) )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000683 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000684 req->atom = atom - MIN_STR_ATOM;
685 req->local = local;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000686 if (!SERVER_CALL_ERR())
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000687 {
Alexandre Julliard942dcb12000-09-04 20:21:48 +0000688 len = WideCharToMultiByte( CP_ACP, 0, server_data_ptr(req),
689 server_data_size(req) / sizeof(WCHAR),
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000690 buffer, count - 1, NULL, NULL );
691 if (!len) len = count; /* overflow */
692 else buffer[len] = 0;
693 }
694 }
Alexandre Julliard67a74992001-02-27 02:09:16 +0000695 SERVER_END_VAR_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000696 }
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000697
698 if (len && count <= len)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000699 {
700 SetLastError( ERROR_MORE_DATA );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000701 buffer[count-1] = 0;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000702 return 0;
703 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000704 TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_a(buffer) );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000705 return len;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000706}
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000707
Alexandre Julliard54c27111998-03-29 19:44:57 +0000708
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000709/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000710 * GlobalGetAtomNameA (USER.271)
711 * GlobalGetAtomNameA (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000712 *
713 * Retrieves a copy of the string associated with an atom.
714 *
715 * RETURNS
716 * Length of string in characters: Success
717 * 0: Failure
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000718 */
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000719UINT WINAPI GlobalGetAtomNameA(
720 ATOM atom, /* [in] Atom identifier */
721 LPSTR buffer, /* [out] Pointer to buffer for atom string */
722 INT count ) /* [in] Size of buffer */
723{
724 return ATOM_GetAtomNameA( atom, buffer, count, FALSE );
725}
726
727
728/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000729 * GetAtomNameA (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000730 * Retrieves a copy of the string associated with the atom.
731 *
732 * RETURNS
733 * Length of string: Success
734 * 0: Failure
735 */
736UINT WINAPI GetAtomNameA(
737 ATOM atom, /* [in] Atom */
738 LPSTR buffer, /* [out] Pointer to string for atom string */
739 INT count) /* [in] Size of buffer */
740{
741 return ATOM_GetAtomNameA( atom, buffer, count, TRUE );
742}
743
744
745static UINT ATOM_GetAtomNameW( ATOM atom, LPWSTR buffer, INT count, BOOL local )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000746{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000747 INT len;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000748
749 if (count <= 0)
750 {
751 SetLastError( ERROR_MORE_DATA );
752 return 0;
753 }
Alexandre Julliardb849d792000-02-13 13:56:13 +0000754 if (atom < MIN_STR_ATOM)
755 {
756 char name[8];
757 if (!atom)
758 {
759 SetLastError( ERROR_INVALID_PARAMETER );
760 return 0;
761 }
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000762 sprintf( name, "#%d", atom );
763 len = MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, count );
764 if (!len) buffer[count-1] = 0; /* overflow */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000765 }
766 else
767 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000768 len = 0;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000769 SERVER_START_VAR_REQ( get_atom_name, MAX_ATOM_LEN * sizeof(WCHAR) )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000770 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000771 req->atom = atom - MIN_STR_ATOM;
772 req->local = local;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000773 if (!SERVER_CALL_ERR())
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000774 {
775 len = server_data_size(req) / sizeof(WCHAR);
776 if (count > len) count = len + 1;
777 memcpy( buffer, server_data_ptr(req), (count-1) * sizeof(WCHAR) );
778 buffer[count-1] = 0;
779 }
780 }
Alexandre Julliard67a74992001-02-27 02:09:16 +0000781 SERVER_END_VAR_REQ;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000782 if (!len) return 0;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000783 }
784 if (count <= len)
785 {
786 SetLastError( ERROR_MORE_DATA );
787 return 0;
788 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000789 TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_w(buffer) );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000790 return len;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000791}
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000792
793
794/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000795 * GlobalGetAtomNameW (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000796 */
797UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
798{
799 return ATOM_GetAtomNameW( atom, buffer, count, FALSE);
800}
801
802
803/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000804 * GetAtomNameW (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000805 */
806UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
807{
808 return ATOM_GetAtomNameW( atom, buffer, count, TRUE );
809}