blob: 5ff65442bc0e4339731f760b46178b6f0a9d4568 [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"
20#include "wingdi.h"
21#include "winuser.h"
Patrik Stridvallfdcfdb91999-06-12 14:55:11 +000022#include "wine/winbase16.h"
23#include "wine/winuser16.h"
Alexandre Julliardb849d792000-02-13 13:56:13 +000024#include "winerror.h"
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000025#include "instance.h"
26#include "ldt.h"
27#include "stackframe.h"
28#include "user.h"
Alexandre Julliard15657091999-05-23 10:25:25 +000029#include "debugtools.h"
Alexandre Julliardb849d792000-02-13 13:56:13 +000030#include "server.h"
Alexandre Julliard5f721f81994-01-04 20:14:34 +000031
Alexandre Julliardb849d792000-02-13 13:56:13 +000032DEFAULT_DEBUG_CHANNEL(atom);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000033
Alexandre Julliard5f721f81994-01-04 20:14:34 +000034#define DEFAULT_ATOMTABLE_SIZE 37
35#define MIN_STR_ATOM 0xc000
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000036#define MAX_ATOM_LEN 255
Alexandre Julliard5f721f81994-01-04 20:14:34 +000037
Alexandre Julliard8bbf8181996-09-13 16:50:47 +000038#define ATOMTOHANDLE(atom) ((HANDLE16)(atom) << 2)
Alexandre Julliard5f721f81994-01-04 20:14:34 +000039#define HANDLETOATOM(handle) ((ATOM)(0xc000 | ((handle) >> 2)))
40
Alexandre Julliard737fa071998-11-15 17:29:15 +000041typedef struct
42{
43 HANDLE16 next;
44 WORD refCount;
45 BYTE length;
46 BYTE str[1];
47} ATOMENTRY;
48
49typedef struct
50{
51 WORD size;
52 HANDLE16 entries[1];
53} ATOMTABLE;
Alexandre Julliardded30381995-07-06 17:18:27 +000054
Alexandre Julliardb849d792000-02-13 13:56:13 +000055static WORD ATOM_UserDS = 0; /* USER data segment */
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000056
Alexandre Julliard5f721f81994-01-04 20:14:34 +000057/***********************************************************************
58 * ATOM_Init
59 *
60 * Global table initialisation.
61 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000062BOOL ATOM_Init( WORD globalTableSel )
Alexandre Julliard5f721f81994-01-04 20:14:34 +000063{
Alexandre Julliardb849d792000-02-13 13:56:13 +000064 ATOM_UserDS = globalTableSel;
65 return TRUE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000066}
67
68
69/***********************************************************************
70 * ATOM_GetTable
71 *
72 * Return a pointer to the atom table of a given segment, creating
73 * it if necessary.
Alexandre Julliard54c27111998-03-29 19:44:57 +000074 *
75 * RETURNS
76 * Pointer to table: Success
77 * NULL: Failure
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000078 */
Alexandre Julliardb849d792000-02-13 13:56:13 +000079static ATOMTABLE *ATOM_GetTable( BOOL create /* [in] Create */ )
Alexandre Julliard737fa071998-11-15 17:29:15 +000080{
Alexandre Julliardb849d792000-02-13 13:56:13 +000081 INSTANCEDATA *ptr = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( CURRENT_DS, 0 );
Alexandre Julliard737fa071998-11-15 17:29:15 +000082 if (ptr->atomtable)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000083 {
Alexandre Julliard737fa071998-11-15 17:29:15 +000084 ATOMTABLE *table = (ATOMTABLE *)((char *)ptr + ptr->atomtable);
85 if (table->size) return table;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000086 }
Alexandre Julliard737fa071998-11-15 17:29:15 +000087 if (!create) return NULL;
Alexandre Julliardb849d792000-02-13 13:56:13 +000088 if (!InitAtomTable16( 0 )) return NULL;
Alexandre Julliard737fa071998-11-15 17:29:15 +000089 /* Reload ptr in case it moved in linear memory */
Alexandre Julliardb849d792000-02-13 13:56:13 +000090 ptr = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( CURRENT_DS, 0 );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000091 return (ATOMTABLE *)((char *)ptr + ptr->atomtable);
Alexandre Julliard5f721f81994-01-04 20:14:34 +000092}
93
94
95/***********************************************************************
Alexandre Julliard5f721f81994-01-04 20:14:34 +000096 * ATOM_Hash
Alexandre Julliard54c27111998-03-29 19:44:57 +000097 * RETURNS
98 * The hash value for the input string
Alexandre Julliard5f721f81994-01-04 20:14:34 +000099 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000100static WORD ATOM_Hash(
101 WORD entries, /* [in] Total number of entries */
102 LPCSTR str, /* [in] Pointer to string to hash */
103 WORD len /* [in] Length of string */
104) {
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000105 WORD i, hash = 0;
106
Alexandre Julliard15657091999-05-23 10:25:25 +0000107 TRACE("%x, %s, %x\n", entries, str, len);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000108
Alexandre Julliardcdd09231994-01-12 11:12:51 +0000109 for (i = 0; i < len; i++) hash ^= toupper(str[i]) + i;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000110 return hash % entries;
111}
112
113
114/***********************************************************************
Alexandre Julliardb849d792000-02-13 13:56:13 +0000115 * ATOM_IsIntAtomA
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000116 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000117static BOOL ATOM_IsIntAtomA(LPCSTR atomstr,WORD *atomid)
118{
119 UINT atom = 0;
120 if (!HIWORD(atomstr)) atom = LOWORD(atomstr);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000121 else
122 {
Alexandre Julliardb849d792000-02-13 13:56:13 +0000123 if (*atomstr++ != '#') return FALSE;
124 while (*atomstr >= '0' && *atomstr <= '9')
125 {
126 atom = atom * 10 + *atomstr - '0';
127 atomstr++;
128 }
129 if (*atomstr) return FALSE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000130 }
Alexandre Julliardb849d792000-02-13 13:56:13 +0000131 if (!atom || (atom >= MIN_STR_ATOM))
132 {
133 SetLastError( ERROR_INVALID_PARAMETER );
134 atom = 0;
135 }
136 *atomid = atom;
137 return TRUE;
138}
139
140
141/***********************************************************************
142 * ATOM_IsIntAtomW
143 */
144static BOOL ATOM_IsIntAtomW(LPCWSTR atomstr,WORD *atomid)
145{
146 UINT atom = 0;
147 if (!HIWORD(atomstr)) atom = LOWORD(atomstr);
148 else
149 {
150 if (*atomstr++ != '#') return FALSE;
151 while (*atomstr >= '0' && *atomstr <= '9')
152 {
153 atom = atom * 10 + *atomstr - '0';
154 atomstr++;
155 }
156 if (*atomstr) return FALSE;
157 }
158 if (!atom || (atom >= MIN_STR_ATOM))
159 {
160 SetLastError( ERROR_INVALID_PARAMETER );
161 atom = 0;
162 }
163 *atomid = atom;
164 return TRUE;
165}
166
167
168/***********************************************************************
169 * ATOM_MakePtr
170 *
171 * Make an ATOMENTRY pointer from a handle (obtained from GetAtomHandle()).
172 */
173static inline ATOMENTRY *ATOM_MakePtr( HANDLE16 handle /* [in] Handle */ )
174{
175 return (ATOMENTRY *)PTR_SEG_OFF_TO_LIN( CURRENT_DS, handle );
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000176}
177
178
179/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000180 * InitAtomTable16 (KERNEL.68)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000181 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000182WORD WINAPI InitAtomTable16( WORD entries )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000183{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000184 int i;
185 HANDLE16 handle;
186 ATOMTABLE *table;
187
188 /* We consider the first table to be initialized as the global table.
189 * This works, as USER (both built-in and native) is the first one to
190 * register ...
191 */
192
193 if (!ATOM_UserDS)
194 {
195 ATOM_UserDS = CURRENT_DS;
196 /* return dummy local handle */
197 return LocalAlloc16( LMEM_FIXED, 1 );
198 }
199
200 /* Allocate the table */
201
Alexandre Julliard737fa071998-11-15 17:29:15 +0000202 if (!entries) entries = DEFAULT_ATOMTABLE_SIZE; /* sanity check */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000203 handle = LocalAlloc16( LMEM_FIXED, sizeof(ATOMTABLE) + (entries-1) * sizeof(HANDLE16) );
204 if (!handle) return 0;
205 table = (ATOMTABLE *)PTR_SEG_OFF_TO_LIN( CURRENT_DS, handle );
206 table->size = entries;
207 for (i = 0; i < entries; i++) table->entries[i] = 0;
208
209 /* Store a pointer to the table in the instance data */
210
211 ((INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( CURRENT_DS, 0 ))->atomtable = handle;
212 return handle;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000213}
214
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000215/***********************************************************************
216 * GetAtomHandle (KERNEL.73)
217 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000218HANDLE16 WINAPI GetAtomHandle16( ATOM atom )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000219{
220 if (atom < MIN_STR_ATOM) return 0;
221 return ATOMTOHANDLE( atom );
222}
223
224
225/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000226 * AddAtom16 (KERNEL.70)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000227 *
228 * Windows DWORD aligns the atom entry size.
229 * The remaining unused string space created by the alignment
230 * gets padded with '\0's in a certain way to ensure
231 * that at least one trailing '\0' remains.
232 *
233 * RETURNS
234 * Atom: Success
235 * 0: Failure
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000236 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000237ATOM WINAPI AddAtom16( LPCSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000238{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000239 char buffer[MAX_ATOM_LEN+1];
240 WORD hash;
241 HANDLE16 entry;
242 ATOMENTRY * entryPtr;
243 ATOMTABLE * table;
244 int len, ae_len;
245 WORD iatom;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000246
Alexandre Julliardb849d792000-02-13 13:56:13 +0000247 if (ATOM_IsIntAtomA( str, &iatom )) return iatom;
248
249 TRACE("%s\n",debugstr_a(buffer));
250
251 /* Make a copy of the string to be sure it doesn't move in linear memory. */
252 lstrcpynA( buffer, str, sizeof(buffer) );
253
254 len = strlen( buffer );
255 if (!(table = ATOM_GetTable( TRUE ))) return 0;
Alexandre Julliardbcb7f4e2000-02-19 20:51:29 +0000256 if (CURRENT_DS == ATOM_UserDS) return GlobalAddAtomA( str );
257
Alexandre Julliardb849d792000-02-13 13:56:13 +0000258 hash = ATOM_Hash( table->size, buffer, len );
259 entry = table->entries[hash];
260 while (entry)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000261 {
Alexandre Julliardb849d792000-02-13 13:56:13 +0000262 entryPtr = ATOM_MakePtr( entry );
263 if ((entryPtr->length == len) &&
264 (!lstrncmpiA( entryPtr->str, buffer, len )))
265 {
266 entryPtr->refCount++;
267 TRACE("-- existing 0x%x\n", entry);
268 return HANDLETOATOM( entry );
269 }
270 entry = entryPtr->next;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000271 }
Alexandre Julliardb849d792000-02-13 13:56:13 +0000272
273 ae_len = (sizeof(ATOMENTRY)+len+3) & ~3;
274 entry = LocalAlloc16( LMEM_FIXED, ae_len );
275 if (!entry) return 0;
276 /* Reload the table ptr in case it moved in linear memory */
277 table = ATOM_GetTable( FALSE );
278 entryPtr = ATOM_MakePtr( entry );
279 entryPtr->next = table->entries[hash];
280 entryPtr->refCount = 1;
281 entryPtr->length = len;
282 /* Some applications _need_ the '\0' padding provided by this strncpy */
283 strncpy( entryPtr->str, buffer, ae_len - sizeof(ATOMENTRY) + 1 );
284 entryPtr->str[ae_len - sizeof(ATOMENTRY)] = '\0';
285 table->entries[hash] = entry;
286 TRACE("-- new 0x%x\n", entry);
287 return HANDLETOATOM( entry );
288}
289
290
291/***********************************************************************
292 * DeleteAtom16 (KERNEL.71)
293 */
294ATOM WINAPI DeleteAtom16( ATOM atom )
295{
296 ATOMENTRY * entryPtr;
297 ATOMTABLE * table;
298 HANDLE16 entry, *prevEntry;
299 WORD hash;
300
301 if (atom < MIN_STR_ATOM) return 0; /* Integer atom */
302 if (CURRENT_DS == ATOM_UserDS) return GlobalDeleteAtom( atom );
303
304 TRACE("0x%x\n",atom);
305
306 if (!(table = ATOM_GetTable( FALSE ))) return 0;
307 entry = ATOMTOHANDLE( atom );
308 entryPtr = ATOM_MakePtr( entry );
309
310 /* Find previous atom */
311 hash = ATOM_Hash( table->size, entryPtr->str, entryPtr->length );
312 prevEntry = &table->entries[hash];
313 while (*prevEntry && *prevEntry != entry)
314 {
315 ATOMENTRY * prevEntryPtr = ATOM_MakePtr( *prevEntry );
316 prevEntry = &prevEntryPtr->next;
317 }
318 if (!*prevEntry) return atom;
319
320 /* Delete atom */
321 if (--entryPtr->refCount == 0)
322 {
323 *prevEntry = entryPtr->next;
324 LocalFree16( entry );
325 }
326 return 0;
327}
328
329
330/***********************************************************************
331 * FindAtom16 (KERNEL.69)
332 */
333ATOM WINAPI FindAtom16( LPCSTR str )
334{
335 ATOMTABLE * table;
336 WORD hash,iatom;
337 HANDLE16 entry;
338 int len;
339
340 if (CURRENT_DS == ATOM_UserDS) return GlobalFindAtomA( str );
341
342 TRACE("%s\n",debugres_a(str));
343
344 if (ATOM_IsIntAtomA( str, &iatom )) return iatom;
345 if ((len = strlen( str )) > 255) len = 255;
346 if (!(table = ATOM_GetTable( FALSE ))) return 0;
347 hash = ATOM_Hash( table->size, str, len );
348 entry = table->entries[hash];
349 while (entry)
350 {
351 ATOMENTRY * entryPtr = ATOM_MakePtr( entry );
352 if ((entryPtr->length == len) &&
353 (!lstrncmpiA( entryPtr->str, str, len )))
354 {
355 TRACE("-- found %x\n", entry);
356 return HANDLETOATOM( entry );
357 }
358 entry = entryPtr->next;
359 }
360 TRACE("-- not found\n");
361 return 0;
362}
363
364
365/***********************************************************************
366 * GetAtomName16 (KERNEL.72)
367 */
368UINT16 WINAPI GetAtomName16( ATOM atom, LPSTR buffer, INT16 count )
369{
370 ATOMTABLE * table;
371 ATOMENTRY * entryPtr;
372 HANDLE16 entry;
373 char * strPtr;
374 UINT len;
375 char text[8];
376
377 if (CURRENT_DS == ATOM_UserDS) return GlobalGetAtomNameA( atom, buffer, count );
378
379 TRACE("%x\n",atom);
380
381 if (!count) return 0;
382 if (atom < MIN_STR_ATOM)
383 {
384 sprintf( text, "#%d", atom );
385 len = strlen(text);
386 strPtr = text;
387 }
388 else
389 {
390 if (!(table = ATOM_GetTable( FALSE ))) return 0;
391 entry = ATOMTOHANDLE( atom );
392 entryPtr = ATOM_MakePtr( entry );
393 len = entryPtr->length;
394 strPtr = entryPtr->str;
395 }
396 if (len >= count) len = count-1;
397 memcpy( buffer, strPtr, len );
398 buffer[len] = '\0';
399 return len;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000400}
401
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000402/***********************************************************************
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000403 * InitAtomTable (KERNEL32.471)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000404 */
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000405BOOL WINAPI InitAtomTable( DWORD entries )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000406{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000407 struct init_atom_table_request *req = get_req_buffer();
408 req->entries = entries;
409 return !server_call( REQ_INIT_ATOM_TABLE );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000410}
411
412
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000413static ATOM ATOM_AddAtomA( LPCSTR str, BOOL local )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000414{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000415 ATOM atom = 0;
416 if (!ATOM_IsIntAtomA( str, &atom ))
417 {
418 struct add_atom_request *req = get_req_buffer();
419 server_strcpyAtoW( req->name, str );
420 req->local = local;
421 if (!server_call( REQ_ADD_ATOM )) atom = req->atom + MIN_STR_ATOM;
422 }
423 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom );
424 return atom;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000425}
426
427
428/***********************************************************************
Alexandre Julliardb849d792000-02-13 13:56:13 +0000429 * GlobalAddAtomA (USER.268) (KERNEL32.313)
430 *
Alexandre Julliard54c27111998-03-29 19:44:57 +0000431 * Adds a character string to the global atom table and returns a unique
432 * value identifying the string.
433 *
434 * RETURNS
435 * Atom: Success
436 * 0: Failure
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000437 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000438ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
439{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000440 return ATOM_AddAtomA( str, FALSE );
441}
442
443
444/***********************************************************************
445 * AddAtomA (KERNEL32.0)
446 * Adds a string to the atom table and returns the atom identifying the
447 * string.
448 *
449 * RETURNS
450 * Atom: Success
451 * 0: Failure
452 */
453ATOM WINAPI AddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
454{
455 return ATOM_AddAtomA( str, TRUE );
456}
457
458
459static ATOM ATOM_AddAtomW( LPCWSTR str, BOOL local )
460{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000461 ATOM atom = 0;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000462 if (!ATOM_IsIntAtomW( str, &atom ))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000463 {
464 struct add_atom_request *req = get_req_buffer();
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000465 server_strcpyW( req->name, str );
466 req->local = local;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000467 if (!server_call( REQ_ADD_ATOM )) atom = req->atom + MIN_STR_ATOM;
468 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000469 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000470 return atom;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000471}
472
473
474/***********************************************************************
Alexandre Julliardb849d792000-02-13 13:56:13 +0000475 * GlobalAddAtomW (KERNEL32.314)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000476 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000477ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000478{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000479 return ATOM_AddAtomW( str, FALSE );
480}
481
482
483/***********************************************************************
484 * AddAtomW (KERNEL32.1)
485 */
486ATOM WINAPI AddAtomW( LPCWSTR str )
487{
488 return ATOM_AddAtomW( str, TRUE );
489}
490
491
492static ATOM ATOM_DeleteAtom( ATOM atom, BOOL local)
493{
494 TRACE( "(%s) %x\n", local ? "local" : "glbal", atom );
495 if (atom < MIN_STR_ATOM) atom = 0;
496 else
Alexandre Julliardb849d792000-02-13 13:56:13 +0000497 {
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000498 struct delete_atom_request *req = get_req_buffer();
499 req->atom = atom - MIN_STR_ATOM;
500 req->local = local;
501 if (!server_call( REQ_DELETE_ATOM )) atom = 0;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000502 }
Alexandre Julliardb849d792000-02-13 13:56:13 +0000503 return atom;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000504}
505
506
507/***********************************************************************
508 * GlobalDeleteAtom (USER.269) (KERNEL32.317)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000509 * Decrements the reference count of a string atom. If the count is
510 * zero, the string associated with the atom is removed from the table.
511 *
512 * RETURNS
513 * 0: Success
514 * Atom: Failure
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000515 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000516ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000517{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000518 return ATOM_DeleteAtom( atom, FALSE);
519}
520
521
522/***********************************************************************
523 * DeleteAtom (KERNEL32.69)
524 * Decrements the reference count of a string atom. If count becomes
525 * zero, the string associated with the atom is removed from the table.
526 *
527 * RETURNS
528 * 0: Success
529 * Atom: Failure
530 */
531ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ )
532{
533 return ATOM_DeleteAtom( atom, TRUE );
534}
535
536
537static ATOM ATOM_FindAtomA( LPCSTR str, BOOL local )
538{
539 ATOM atom = 0;
540 if (!ATOM_IsIntAtomA( str, &atom ))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000541 {
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000542 struct find_atom_request *req = get_req_buffer();
543 server_strcpyAtoW( req->name, str );
544 req->local = local;
545 if (!server_call( REQ_FIND_ATOM )) atom = req->atom + MIN_STR_ATOM;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000546 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000547 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000548 return atom;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000549}
550
551
552/***********************************************************************
Alexandre Julliardb849d792000-02-13 13:56:13 +0000553 * GlobalFindAtomA (USER.270) (KERNEL32.318)
554 *
Alexandre Julliard54c27111998-03-29 19:44:57 +0000555 * Searches the atom table for the string and returns the atom
556 * associated with it.
557 *
558 * RETURNS
559 * Atom: Success
560 * 0: Failure
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000561 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000562ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ )
563{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000564 return ATOM_FindAtomA( str, FALSE );
565}
566
567/***********************************************************************
568 * FindAtomA (KERNEL32.117)
569 * Searches the local atom table for the string and returns the atom
570 * associated with that string.
571 *
572 * RETURNS
573 * Atom: Success
574 * 0: Failure
575 */
576ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ )
577{
578 return ATOM_FindAtomA( str, TRUE );
579}
580
581
582static ATOM ATOM_FindAtomW( LPCWSTR str, BOOL local )
583{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000584 ATOM atom = 0;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000585 if (!ATOM_IsIntAtomW( str, &atom ))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000586 {
587 struct find_atom_request *req = get_req_buffer();
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000588 server_strcpyW( req->name, str );
589 req->local = local;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000590 if (!server_call( REQ_FIND_ATOM )) atom = req->atom + MIN_STR_ATOM;
591 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000592 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000593 return atom;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000594}
595
596
597/***********************************************************************
Alexandre Julliardb849d792000-02-13 13:56:13 +0000598 * GlobalFindAtomW (KERNEL32.319)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000599 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000600ATOM WINAPI GlobalFindAtomW( LPCWSTR str )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000601{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000602 return ATOM_FindAtomW( str, FALSE );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000603}
604
605
606/***********************************************************************
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000607 * FindAtomW (KERNEL32.118)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000608 */
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000609ATOM WINAPI FindAtomW( LPCWSTR str )
610{
611 return ATOM_FindAtomW( str, TRUE );
612}
613
614
615static UINT ATOM_GetAtomNameA( ATOM atom, LPSTR buffer, INT count, BOOL local )
Alexandre Julliardb849d792000-02-13 13:56:13 +0000616{
617 INT len;
618 if (atom < MIN_STR_ATOM)
619 {
620 char name[8];
621 if (!atom)
622 {
623 SetLastError( ERROR_INVALID_PARAMETER );
624 return 0;
625 }
626 len = sprintf( name, "#%d", atom );
627 lstrcpynA( buffer, name, count );
628 }
629 else
630 {
631 struct get_atom_name_request *req = get_req_buffer();
632 req->atom = atom - MIN_STR_ATOM;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000633 req->local = local;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000634 if (server_call( REQ_GET_ATOM_NAME )) return 0;
635 lstrcpynWtoA( buffer, req->name, count );
636 len = lstrlenW( req->name );
637 }
638 if (count <= len)
639 {
640 SetLastError( ERROR_MORE_DATA );
641 return 0;
642 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000643 TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_a(buffer) );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000644 return len;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000645}
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000646
Alexandre Julliard54c27111998-03-29 19:44:57 +0000647
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000648/***********************************************************************
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000649 * GlobalGetAtomNameA (USER.271) (KERNEL32.323)
650 *
651 * Retrieves a copy of the string associated with an atom.
652 *
653 * RETURNS
654 * Length of string in characters: Success
655 * 0: Failure
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000656 */
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000657UINT WINAPI GlobalGetAtomNameA(
658 ATOM atom, /* [in] Atom identifier */
659 LPSTR buffer, /* [out] Pointer to buffer for atom string */
660 INT count ) /* [in] Size of buffer */
661{
662 return ATOM_GetAtomNameA( atom, buffer, count, FALSE );
663}
664
665
666/***********************************************************************
667 * GetAtomNameA (KERNEL32.149)
668 * Retrieves a copy of the string associated with the atom.
669 *
670 * RETURNS
671 * Length of string: Success
672 * 0: Failure
673 */
674UINT WINAPI GetAtomNameA(
675 ATOM atom, /* [in] Atom */
676 LPSTR buffer, /* [out] Pointer to string for atom string */
677 INT count) /* [in] Size of buffer */
678{
679 return ATOM_GetAtomNameA( atom, buffer, count, TRUE );
680}
681
682
683static UINT ATOM_GetAtomNameW( ATOM atom, LPWSTR buffer, INT count, BOOL local )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000684{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000685 INT len;
686 if (atom < MIN_STR_ATOM)
687 {
688 char name[8];
689 if (!atom)
690 {
691 SetLastError( ERROR_INVALID_PARAMETER );
692 return 0;
693 }
694 len = sprintf( name, "#%d", atom );
695 lstrcpynAtoW( buffer, name, count );
696 }
697 else
698 {
699 struct get_atom_name_request *req = get_req_buffer();
700 req->atom = atom - MIN_STR_ATOM;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000701 req->local = local;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000702 if (server_call( REQ_GET_ATOM_NAME )) return 0;
703 lstrcpynW( buffer, req->name, count );
704 len = lstrlenW( req->name );
705 }
706 if (count <= len)
707 {
708 SetLastError( ERROR_MORE_DATA );
709 return 0;
710 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000711 TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_w(buffer) );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000712 return len;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000713}
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000714
715
716/***********************************************************************
717 * GlobalGetAtomNameW (KERNEL32.324)
718 */
719UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
720{
721 return ATOM_GetAtomNameW( atom, buffer, count, FALSE);
722}
723
724
725/***********************************************************************
726 * GetAtomNameW (KERNEL32.150)
727 */
728UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
729{
730 return ATOM_GetAtomNameW( atom, buffer, count, TRUE );
731}