blob: 033eb4c41678b2972e2ebd2d7d9967bfa26418c1 [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
Patrik Stridvallbc38d6b2001-07-20 18:00:00 +000014#include "config.h"
15
Alexandre Julliard5f721f81994-01-04 20:14:34 +000016#include <stdlib.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000017#include <stdio.h>
Alexandre Julliard5f721f81994-01-04 20:14:34 +000018#include <string.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000019#include <ctype.h>
Alexandre Julliard5f721f81994-01-04 20:14:34 +000020
Jeremy Whited3e22d92000-02-10 19:03:02 +000021#include "windef.h"
Francois Gouget541ff5f2001-10-15 17:49:23 +000022#include "winbase.h"
Alexandre Julliardb849d792000-02-13 13:56:13 +000023#include "winerror.h"
Patrik Stridvallbc38d6b2001-07-20 18:00:00 +000024
25#include "wine/server.h"
26#include "wine/unicode.h"
27#include "wine/winbase16.h"
28#include "global.h"
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000029#include "instance.h"
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000030#include "stackframe.h"
Patrik Stridvallbc38d6b2001-07-20 18:00:00 +000031
Alexandre Julliard15657091999-05-23 10:25:25 +000032#include "debugtools.h"
Alexandre Julliard5f721f81994-01-04 20:14:34 +000033
Alexandre Julliardb849d792000-02-13 13:56:13 +000034DEFAULT_DEBUG_CHANNEL(atom);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000035
Alexandre Julliard5f721f81994-01-04 20:14:34 +000036#define DEFAULT_ATOMTABLE_SIZE 37
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000037#define MAX_ATOM_LEN 255
Alexandre Julliard5f721f81994-01-04 20:14:34 +000038
Alexandre Julliard8bbf8181996-09-13 16:50:47 +000039#define ATOMTOHANDLE(atom) ((HANDLE16)(atom) << 2)
Alexandre Julliard5f721f81994-01-04 20:14:34 +000040#define HANDLETOATOM(handle) ((ATOM)(0xc000 | ((handle) >> 2)))
41
Alexandre Julliard737fa071998-11-15 17:29:15 +000042typedef struct
43{
44 HANDLE16 next;
45 WORD refCount;
46 BYTE length;
47 BYTE str[1];
48} ATOMENTRY;
49
50typedef struct
51{
52 WORD size;
53 HANDLE16 entries[1];
54} ATOMTABLE;
Alexandre Julliardded30381995-07-06 17:18:27 +000055
Alexandre Julliardb849d792000-02-13 13:56:13 +000056static WORD ATOM_UserDS = 0; /* USER data segment */
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000057
Alexandre Julliard5f721f81994-01-04 20:14:34 +000058/***********************************************************************
59 * ATOM_Init
60 *
61 * Global table initialisation.
62 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000063BOOL ATOM_Init( WORD globalTableSel )
Alexandre Julliard5f721f81994-01-04 20:14:34 +000064{
Alexandre Julliardb849d792000-02-13 13:56:13 +000065 ATOM_UserDS = globalTableSel;
66 return TRUE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000067}
68
69
70/***********************************************************************
71 * ATOM_GetTable
72 *
73 * Return a pointer to the atom table of a given segment, creating
74 * it if necessary.
Alexandre Julliard54c27111998-03-29 19:44:57 +000075 *
76 * RETURNS
77 * Pointer to table: Success
78 * NULL: Failure
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000079 */
Alexandre Julliardb849d792000-02-13 13:56:13 +000080static ATOMTABLE *ATOM_GetTable( BOOL create /* [in] Create */ )
Alexandre Julliard737fa071998-11-15 17:29:15 +000081{
Alexandre Julliard982a2232000-12-13 20:20:09 +000082 INSTANCEDATA *ptr = MapSL( MAKESEGPTR( CURRENT_DS, 0 ) );
Alexandre Julliard737fa071998-11-15 17:29:15 +000083 if (ptr->atomtable)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000084 {
Alexandre Julliard737fa071998-11-15 17:29:15 +000085 ATOMTABLE *table = (ATOMTABLE *)((char *)ptr + ptr->atomtable);
86 if (table->size) return table;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000087 }
Alexandre Julliard737fa071998-11-15 17:29:15 +000088 if (!create) return NULL;
Alexandre Julliardb849d792000-02-13 13:56:13 +000089 if (!InitAtomTable16( 0 )) return NULL;
Alexandre Julliard737fa071998-11-15 17:29:15 +000090 /* Reload ptr in case it moved in linear memory */
Alexandre Julliard982a2232000-12-13 20:20:09 +000091 ptr = MapSL( MAKESEGPTR( CURRENT_DS, 0 ) );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000092 return (ATOMTABLE *)((char *)ptr + ptr->atomtable);
Alexandre Julliard5f721f81994-01-04 20:14:34 +000093}
94
95
96/***********************************************************************
Alexandre Julliard5f721f81994-01-04 20:14:34 +000097 * ATOM_Hash
Alexandre Julliard54c27111998-03-29 19:44:57 +000098 * RETURNS
99 * The hash value for the input string
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000100 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000101static WORD ATOM_Hash(
102 WORD entries, /* [in] Total number of entries */
103 LPCSTR str, /* [in] Pointer to string to hash */
104 WORD len /* [in] Length of string */
105) {
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000106 WORD i, hash = 0;
107
Alexandre Julliard15657091999-05-23 10:25:25 +0000108 TRACE("%x, %s, %x\n", entries, str, len);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000109
Alexandre Julliardcdd09231994-01-12 11:12:51 +0000110 for (i = 0; i < len; i++) hash ^= toupper(str[i]) + i;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000111 return hash % entries;
112}
113
114
115/***********************************************************************
Alexandre Julliardb849d792000-02-13 13:56:13 +0000116 * ATOM_IsIntAtomA
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000117 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000118static BOOL ATOM_IsIntAtomA(LPCSTR atomstr,WORD *atomid)
119{
120 UINT atom = 0;
121 if (!HIWORD(atomstr)) atom = LOWORD(atomstr);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000122 else
123 {
Alexandre Julliardb849d792000-02-13 13:56:13 +0000124 if (*atomstr++ != '#') return FALSE;
125 while (*atomstr >= '0' && *atomstr <= '9')
126 {
127 atom = atom * 10 + *atomstr - '0';
128 atomstr++;
129 }
130 if (*atomstr) return FALSE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000131 }
Francois Gouget541ff5f2001-10-15 17:49:23 +0000132 if (!atom || (atom >= MAXINTATOM))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000133 {
134 SetLastError( ERROR_INVALID_PARAMETER );
135 atom = 0;
136 }
137 *atomid = atom;
138 return TRUE;
139}
140
141
142/***********************************************************************
143 * ATOM_IsIntAtomW
144 */
145static BOOL ATOM_IsIntAtomW(LPCWSTR atomstr,WORD *atomid)
146{
147 UINT atom = 0;
148 if (!HIWORD(atomstr)) atom = LOWORD(atomstr);
149 else
150 {
151 if (*atomstr++ != '#') return FALSE;
152 while (*atomstr >= '0' && *atomstr <= '9')
153 {
154 atom = atom * 10 + *atomstr - '0';
155 atomstr++;
156 }
157 if (*atomstr) return FALSE;
158 }
Francois Gouget541ff5f2001-10-15 17:49:23 +0000159 if (!atom || (atom >= MAXINTATOM))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000160 {
161 SetLastError( ERROR_INVALID_PARAMETER );
162 atom = 0;
163 }
164 *atomid = atom;
165 return TRUE;
166}
167
168
169/***********************************************************************
170 * ATOM_MakePtr
171 *
172 * Make an ATOMENTRY pointer from a handle (obtained from GetAtomHandle()).
173 */
174static inline ATOMENTRY *ATOM_MakePtr( HANDLE16 handle /* [in] Handle */ )
175{
Alexandre Julliard982a2232000-12-13 20:20:09 +0000176 return MapSL( MAKESEGPTR( CURRENT_DS, handle ) );
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000177}
178
179
180/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000181 * InitAtomTable (KERNEL.68)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000182 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000183WORD WINAPI InitAtomTable16( WORD entries )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000184{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000185 int i;
186 HANDLE16 handle;
187 ATOMTABLE *table;
188
189 /* We consider the first table to be initialized as the global table.
190 * This works, as USER (both built-in and native) is the first one to
191 * register ...
192 */
193
194 if (!ATOM_UserDS)
195 {
196 ATOM_UserDS = CURRENT_DS;
197 /* return dummy local handle */
198 return LocalAlloc16( LMEM_FIXED, 1 );
199 }
200
201 /* Allocate the table */
202
Alexandre Julliard737fa071998-11-15 17:29:15 +0000203 if (!entries) entries = DEFAULT_ATOMTABLE_SIZE; /* sanity check */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000204 handle = LocalAlloc16( LMEM_FIXED, sizeof(ATOMTABLE) + (entries-1) * sizeof(HANDLE16) );
205 if (!handle) return 0;
Alexandre Julliard982a2232000-12-13 20:20:09 +0000206 table = MapSL( MAKESEGPTR( CURRENT_DS, handle ) );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000207 table->size = entries;
208 for (i = 0; i < entries; i++) table->entries[i] = 0;
209
210 /* Store a pointer to the table in the instance data */
211
Alexandre Julliard982a2232000-12-13 20:20:09 +0000212 ((INSTANCEDATA *)MapSL( MAKESEGPTR( CURRENT_DS, 0 )))->atomtable = handle;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000213 return handle;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000214}
215
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000216/***********************************************************************
217 * GetAtomHandle (KERNEL.73)
218 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000219HANDLE16 WINAPI GetAtomHandle16( ATOM atom )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000220{
Francois Gouget541ff5f2001-10-15 17:49:23 +0000221 if (atom < MAXINTATOM) return 0;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000222 return ATOMTOHANDLE( atom );
223}
224
225
226/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000227 * AddAtom (KERNEL.70)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000228 *
229 * Windows DWORD aligns the atom entry size.
230 * The remaining unused string space created by the alignment
231 * gets padded with '\0's in a certain way to ensure
232 * that at least one trailing '\0' remains.
233 *
234 * RETURNS
235 * Atom: Success
236 * 0: Failure
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000237 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000238ATOM WINAPI AddAtom16( LPCSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000239{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000240 char buffer[MAX_ATOM_LEN+1];
241 WORD hash;
242 HANDLE16 entry;
243 ATOMENTRY * entryPtr;
244 ATOMTABLE * table;
245 int len, ae_len;
246 WORD iatom;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000247
Alexandre Julliardb849d792000-02-13 13:56:13 +0000248 if (ATOM_IsIntAtomA( str, &iatom )) return iatom;
249
250 TRACE("%s\n",debugstr_a(buffer));
251
252 /* Make a copy of the string to be sure it doesn't move in linear memory. */
253 lstrcpynA( buffer, str, sizeof(buffer) );
254
255 len = strlen( buffer );
256 if (!(table = ATOM_GetTable( TRUE ))) return 0;
Alexandre Julliardbcb7f4e2000-02-19 20:51:29 +0000257 if (CURRENT_DS == ATOM_UserDS) return GlobalAddAtomA( str );
258
Alexandre Julliardb849d792000-02-13 13:56:13 +0000259 hash = ATOM_Hash( table->size, buffer, len );
260 entry = table->entries[hash];
261 while (entry)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000262 {
Alexandre Julliardb849d792000-02-13 13:56:13 +0000263 entryPtr = ATOM_MakePtr( entry );
264 if ((entryPtr->length == len) &&
Alexandre Julliard072dfb52000-09-25 23:30:56 +0000265 (!strncasecmp( entryPtr->str, buffer, len )))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000266 {
267 entryPtr->refCount++;
268 TRACE("-- existing 0x%x\n", entry);
269 return HANDLETOATOM( entry );
270 }
271 entry = entryPtr->next;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000272 }
Alexandre Julliardb849d792000-02-13 13:56:13 +0000273
274 ae_len = (sizeof(ATOMENTRY)+len+3) & ~3;
275 entry = LocalAlloc16( LMEM_FIXED, ae_len );
276 if (!entry) return 0;
277 /* Reload the table ptr in case it moved in linear memory */
278 table = ATOM_GetTable( FALSE );
279 entryPtr = ATOM_MakePtr( entry );
280 entryPtr->next = table->entries[hash];
281 entryPtr->refCount = 1;
282 entryPtr->length = len;
283 /* Some applications _need_ the '\0' padding provided by this strncpy */
284 strncpy( entryPtr->str, buffer, ae_len - sizeof(ATOMENTRY) + 1 );
285 entryPtr->str[ae_len - sizeof(ATOMENTRY)] = '\0';
286 table->entries[hash] = entry;
287 TRACE("-- new 0x%x\n", entry);
288 return HANDLETOATOM( entry );
289}
290
291
292/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000293 * DeleteAtom (KERNEL.71)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000294 */
295ATOM WINAPI DeleteAtom16( ATOM atom )
296{
297 ATOMENTRY * entryPtr;
298 ATOMTABLE * table;
299 HANDLE16 entry, *prevEntry;
300 WORD hash;
301
Francois Gouget541ff5f2001-10-15 17:49:23 +0000302 if (atom < MAXINTATOM) return 0; /* Integer atom */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000303 if (CURRENT_DS == ATOM_UserDS) return GlobalDeleteAtom( atom );
304
305 TRACE("0x%x\n",atom);
306
307 if (!(table = ATOM_GetTable( FALSE ))) return 0;
308 entry = ATOMTOHANDLE( atom );
309 entryPtr = ATOM_MakePtr( entry );
310
311 /* Find previous atom */
312 hash = ATOM_Hash( table->size, entryPtr->str, entryPtr->length );
313 prevEntry = &table->entries[hash];
314 while (*prevEntry && *prevEntry != entry)
315 {
316 ATOMENTRY * prevEntryPtr = ATOM_MakePtr( *prevEntry );
317 prevEntry = &prevEntryPtr->next;
318 }
319 if (!*prevEntry) return atom;
320
321 /* Delete atom */
322 if (--entryPtr->refCount == 0)
323 {
324 *prevEntry = entryPtr->next;
325 LocalFree16( entry );
326 }
327 return 0;
328}
329
330
331/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000332 * FindAtom (KERNEL.69)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000333 */
334ATOM WINAPI FindAtom16( LPCSTR str )
335{
336 ATOMTABLE * table;
337 WORD hash,iatom;
338 HANDLE16 entry;
339 int len;
340
341 if (CURRENT_DS == ATOM_UserDS) return GlobalFindAtomA( str );
342
343 TRACE("%s\n",debugres_a(str));
344
345 if (ATOM_IsIntAtomA( str, &iatom )) return iatom;
346 if ((len = strlen( str )) > 255) len = 255;
347 if (!(table = ATOM_GetTable( FALSE ))) return 0;
348 hash = ATOM_Hash( table->size, str, len );
349 entry = table->entries[hash];
350 while (entry)
351 {
352 ATOMENTRY * entryPtr = ATOM_MakePtr( entry );
353 if ((entryPtr->length == len) &&
Alexandre Julliard072dfb52000-09-25 23:30:56 +0000354 (!strncasecmp( entryPtr->str, str, len )))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000355 {
356 TRACE("-- found %x\n", entry);
357 return HANDLETOATOM( entry );
358 }
359 entry = entryPtr->next;
360 }
361 TRACE("-- not found\n");
362 return 0;
363}
364
365
366/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000367 * GetAtomName (KERNEL.72)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000368 */
369UINT16 WINAPI GetAtomName16( ATOM atom, LPSTR buffer, INT16 count )
370{
371 ATOMTABLE * table;
372 ATOMENTRY * entryPtr;
373 HANDLE16 entry;
374 char * strPtr;
375 UINT len;
376 char text[8];
377
378 if (CURRENT_DS == ATOM_UserDS) return GlobalGetAtomNameA( atom, buffer, count );
379
380 TRACE("%x\n",atom);
381
382 if (!count) return 0;
Francois Gouget541ff5f2001-10-15 17:49:23 +0000383 if (atom < MAXINTATOM)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000384 {
385 sprintf( text, "#%d", atom );
386 len = strlen(text);
387 strPtr = text;
388 }
389 else
390 {
391 if (!(table = ATOM_GetTable( FALSE ))) return 0;
392 entry = ATOMTOHANDLE( atom );
393 entryPtr = ATOM_MakePtr( entry );
394 len = entryPtr->length;
395 strPtr = entryPtr->str;
396 }
397 if (len >= count) len = count-1;
398 memcpy( buffer, strPtr, len );
399 buffer[len] = '\0';
400 return len;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000401}
402
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000403/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000404 * InitAtomTable (KERNEL32.@)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000405 */
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000406BOOL WINAPI InitAtomTable( DWORD entries )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000407{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000408 BOOL ret;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000409 SERVER_START_REQ( init_atom_table )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000410 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000411 req->entries = entries;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000412 ret = !wine_server_call_err( req );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000413 }
414 SERVER_END_REQ;
415 return ret;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000416}
417
418
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000419static ATOM ATOM_AddAtomA( LPCSTR str, BOOL local )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000420{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000421 ATOM atom = 0;
422 if (!ATOM_IsIntAtomA( str, &atom ))
423 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000424 WCHAR buffer[MAX_ATOM_LEN];
425
426 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
427 if (!len)
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000428 {
429 SetLastError( ERROR_INVALID_PARAMETER );
430 return 0;
431 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000432 SERVER_START_REQ( add_atom )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000433 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000434 wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000435 req->local = local;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000436 if (!wine_server_call_err(req)) atom = reply->atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000437 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000438 SERVER_END_REQ;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000439 }
440 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom );
441 return atom;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000442}
443
444
445/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000446 * GlobalAddAtomA (KERNEL32.@)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000447 *
Alexandre Julliard54c27111998-03-29 19:44:57 +0000448 * Adds a character string to the global atom table and returns a unique
449 * value identifying the string.
450 *
451 * RETURNS
452 * Atom: Success
453 * 0: Failure
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000454 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000455ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
456{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000457 return ATOM_AddAtomA( str, FALSE );
458}
459
460
461/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000462 * AddAtomA (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000463 * Adds a string to the atom table and returns the atom identifying the
464 * string.
465 *
466 * RETURNS
467 * Atom: Success
468 * 0: Failure
469 */
470ATOM WINAPI AddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
471{
472 return ATOM_AddAtomA( str, TRUE );
473}
474
475
476static ATOM ATOM_AddAtomW( LPCWSTR str, BOOL local )
477{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000478 ATOM atom = 0;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000479 if (!ATOM_IsIntAtomW( str, &atom ))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000480 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000481 DWORD len = strlenW(str);
482 if (len > MAX_ATOM_LEN)
483 {
484 SetLastError( ERROR_INVALID_PARAMETER );
485 return 0;
486 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000487 SERVER_START_REQ( add_atom )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000488 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000489 req->local = local;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000490 wine_server_add_data( req, str, len * sizeof(WCHAR) );
491 if (!wine_server_call_err(req)) atom = reply->atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000492 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000493 SERVER_END_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000494 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000495 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000496 return atom;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000497}
498
499
500/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000501 * GlobalAddAtomW (KERNEL32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000502 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000503ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000504{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000505 return ATOM_AddAtomW( str, FALSE );
506}
507
508
509/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000510 * AddAtomW (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000511 */
512ATOM WINAPI AddAtomW( LPCWSTR str )
513{
514 return ATOM_AddAtomW( str, TRUE );
515}
516
517
518static ATOM ATOM_DeleteAtom( ATOM atom, BOOL local)
519{
Andreas Mohrc9cf70d2001-01-26 20:40:50 +0000520 TRACE( "(%s) %x\n", local ? "local" : "global", atom );
Francois Gouget541ff5f2001-10-15 17:49:23 +0000521 if (atom < MAXINTATOM) atom = 0;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000522 else
Alexandre Julliardb849d792000-02-13 13:56:13 +0000523 {
Alexandre Julliard67a74992001-02-27 02:09:16 +0000524 SERVER_START_REQ( delete_atom )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000525 {
Alexandre Julliardd8a8c112001-10-12 18:45:29 +0000526 req->atom = atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000527 req->local = local;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000528 if (!wine_server_call_err( req )) atom = 0;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000529 }
530 SERVER_END_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000531 }
Alexandre Julliardb849d792000-02-13 13:56:13 +0000532 return atom;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000533}
534
535
536/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000537 * GlobalDeleteAtom (KERNEL32.@)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000538 * Decrements the reference count of a string atom. If the count is
539 * zero, the string associated with the atom is removed from the table.
540 *
541 * RETURNS
542 * 0: Success
543 * Atom: Failure
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000544 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000545ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000546{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000547 return ATOM_DeleteAtom( atom, FALSE);
548}
549
550
551/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000552 * DeleteAtom (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000553 * Decrements the reference count of a string atom. If count becomes
554 * zero, the string associated with the atom is removed from the table.
555 *
556 * RETURNS
557 * 0: Success
558 * Atom: Failure
559 */
560ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ )
561{
562 return ATOM_DeleteAtom( atom, TRUE );
563}
564
565
566static ATOM ATOM_FindAtomA( LPCSTR str, BOOL local )
567{
568 ATOM atom = 0;
569 if (!ATOM_IsIntAtomA( str, &atom ))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000570 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000571 WCHAR buffer[MAX_ATOM_LEN];
572
573 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
574 if (!len)
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000575 {
576 SetLastError( ERROR_INVALID_PARAMETER );
577 return 0;
578 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000579 SERVER_START_REQ( find_atom )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000580 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000581 req->local = local;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000582 wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
583 if (!wine_server_call_err(req)) atom = reply->atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000584 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000585 SERVER_END_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000586 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000587 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000588 return atom;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000589}
590
591
592/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000593 * GlobalFindAtomA (KERNEL32.@)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000594 *
Alexandre Julliard54c27111998-03-29 19:44:57 +0000595 * Searches the atom table for the string and returns the atom
596 * associated with it.
597 *
598 * RETURNS
599 * Atom: Success
600 * 0: Failure
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000601 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000602ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ )
603{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000604 return ATOM_FindAtomA( str, FALSE );
605}
606
607/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000608 * FindAtomA (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000609 * Searches the local atom table for the string and returns the atom
610 * associated with that string.
611 *
612 * RETURNS
613 * Atom: Success
614 * 0: Failure
615 */
616ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ )
617{
618 return ATOM_FindAtomA( str, TRUE );
619}
620
621
622static ATOM ATOM_FindAtomW( LPCWSTR str, BOOL local )
623{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000624 ATOM atom = 0;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000625 if (!ATOM_IsIntAtomW( str, &atom ))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000626 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000627 DWORD len = strlenW(str);
628 if (len > MAX_ATOM_LEN)
629 {
630 SetLastError( ERROR_INVALID_PARAMETER );
631 return 0;
632 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000633 SERVER_START_REQ( find_atom )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000634 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000635 wine_server_add_data( req, str, len * sizeof(WCHAR) );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000636 req->local = local;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000637 if (!wine_server_call_err( req )) atom = reply->atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000638 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000639 SERVER_END_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000640 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000641 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000642 return atom;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000643}
644
645
646/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000647 * GlobalFindAtomW (KERNEL32.@)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000648 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000649ATOM WINAPI GlobalFindAtomW( LPCWSTR str )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000650{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000651 return ATOM_FindAtomW( str, FALSE );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000652}
653
654
655/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000656 * FindAtomW (KERNEL32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000657 */
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000658ATOM WINAPI FindAtomW( LPCWSTR str )
659{
660 return ATOM_FindAtomW( str, TRUE );
661}
662
663
664static UINT ATOM_GetAtomNameA( ATOM atom, LPSTR buffer, INT count, BOOL local )
Alexandre Julliardb849d792000-02-13 13:56:13 +0000665{
666 INT len;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000667
668 if (count <= 0)
669 {
670 SetLastError( ERROR_MORE_DATA );
671 return 0;
672 }
Francois Gouget541ff5f2001-10-15 17:49:23 +0000673 if (atom < MAXINTATOM)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000674 {
675 char name[8];
676 if (!atom)
677 {
678 SetLastError( ERROR_INVALID_PARAMETER );
679 return 0;
680 }
681 len = sprintf( name, "#%d", atom );
682 lstrcpynA( buffer, name, count );
683 }
684 else
685 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000686 WCHAR full_name[MAX_ATOM_LEN];
687
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000688 len = 0;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000689 SERVER_START_REQ( get_atom_name )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000690 {
Alexandre Julliardd8a8c112001-10-12 18:45:29 +0000691 req->atom = atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000692 req->local = local;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000693 wine_server_set_reply( req, full_name, sizeof(full_name) );
694 if (!wine_server_call_err( req ))
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000695 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000696 len = WideCharToMultiByte( CP_ACP, 0, full_name,
697 wine_server_reply_size(reply) / sizeof(WCHAR),
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000698 buffer, count - 1, NULL, NULL );
699 if (!len) len = count; /* overflow */
700 else buffer[len] = 0;
701 }
702 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000703 SERVER_END_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000704 }
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000705
706 if (len && count <= len)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000707 {
708 SetLastError( ERROR_MORE_DATA );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000709 buffer[count-1] = 0;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000710 return 0;
711 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000712 TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_a(buffer) );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000713 return len;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000714}
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000715
Alexandre Julliard54c27111998-03-29 19:44:57 +0000716
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000717/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000718 * GlobalGetAtomNameA (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000719 *
720 * Retrieves a copy of the string associated with an atom.
721 *
722 * RETURNS
723 * Length of string in characters: Success
724 * 0: Failure
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000725 */
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000726UINT WINAPI GlobalGetAtomNameA(
727 ATOM atom, /* [in] Atom identifier */
728 LPSTR buffer, /* [out] Pointer to buffer for atom string */
729 INT count ) /* [in] Size of buffer */
730{
731 return ATOM_GetAtomNameA( atom, buffer, count, FALSE );
732}
733
734
735/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000736 * GetAtomNameA (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000737 * Retrieves a copy of the string associated with the atom.
738 *
739 * RETURNS
740 * Length of string: Success
741 * 0: Failure
742 */
743UINT WINAPI GetAtomNameA(
744 ATOM atom, /* [in] Atom */
745 LPSTR buffer, /* [out] Pointer to string for atom string */
746 INT count) /* [in] Size of buffer */
747{
748 return ATOM_GetAtomNameA( atom, buffer, count, TRUE );
749}
750
751
752static UINT ATOM_GetAtomNameW( ATOM atom, LPWSTR buffer, INT count, BOOL local )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000753{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000754 INT len;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000755
756 if (count <= 0)
757 {
758 SetLastError( ERROR_MORE_DATA );
759 return 0;
760 }
Francois Gouget541ff5f2001-10-15 17:49:23 +0000761 if (atom < MAXINTATOM)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000762 {
763 char name[8];
764 if (!atom)
765 {
766 SetLastError( ERROR_INVALID_PARAMETER );
767 return 0;
768 }
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000769 sprintf( name, "#%d", atom );
770 len = MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, count );
771 if (!len) buffer[count-1] = 0; /* overflow */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000772 }
773 else
774 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000775 WCHAR full_name[MAX_ATOM_LEN];
776
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000777 len = 0;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000778 SERVER_START_REQ( get_atom_name )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000779 {
Alexandre Julliardd8a8c112001-10-12 18:45:29 +0000780 req->atom = atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000781 req->local = local;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000782 wine_server_set_reply( req, full_name, sizeof(full_name) );
783 if (!wine_server_call_err( req ))
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000784 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000785 len = wine_server_reply_size(reply) / sizeof(WCHAR);
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000786 if (count > len) count = len + 1;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000787 memcpy( buffer, full_name, (count-1) * sizeof(WCHAR) );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000788 buffer[count-1] = 0;
789 }
790 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000791 SERVER_END_REQ;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000792 if (!len) return 0;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000793 }
794 if (count <= len)
795 {
796 SetLastError( ERROR_MORE_DATA );
797 return 0;
798 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000799 TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_w(buffer) );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000800 return len;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000801}
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000802
803
804/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000805 * GlobalGetAtomNameW (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000806 */
807UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
808{
809 return ATOM_GetAtomNameW( atom, buffer, count, FALSE);
810}
811
812
813/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000814 * GetAtomNameW (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000815 */
816UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
817{
818 return ATOM_GetAtomNameW( atom, buffer, count, TRUE );
819}