blob: 6aa12402249388982fe7fdf28aa0f6591e0b0378 [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 Julliard0799c1a2002-03-09 23:29:33 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Alexandre Julliard5f721f81994-01-04 20:14:34 +000019 */
20
21/*
Alexandre Julliard808cb041995-08-17 17:11:36 +000022 * Warning: The code assumes that LocalAlloc() returns a block aligned
23 * on a 4-bytes boundary (because of the shifting done in
24 * HANDLETOATOM). If this is not the case, the allocation code will
25 * have to be changed.
Alexandre Julliard5f721f81994-01-04 20:14:34 +000026 */
27
Patrik Stridvallbc38d6b2001-07-20 18:00:00 +000028#include "config.h"
Patrik Stridvall51e6c0c2002-08-31 19:04:14 +000029#include "wine/port.h"
Patrik Stridvallbc38d6b2001-07-20 18:00:00 +000030
Alexandre Julliard5f721f81994-01-04 20:14:34 +000031#include <stdlib.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000032#include <stdio.h>
Alexandre Julliard5f721f81994-01-04 20:14:34 +000033#include <string.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000034#include <ctype.h>
Alexandre Julliard5f721f81994-01-04 20:14:34 +000035
Jeremy Whited3e22d92000-02-10 19:03:02 +000036#include "windef.h"
Francois Gouget541ff5f2001-10-15 17:49:23 +000037#include "winbase.h"
Alexandre Julliardb849d792000-02-13 13:56:13 +000038#include "winerror.h"
Patrik Stridvallbc38d6b2001-07-20 18:00:00 +000039
40#include "wine/server.h"
41#include "wine/unicode.h"
42#include "wine/winbase16.h"
43#include "global.h"
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000044#include "instance.h"
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000045#include "stackframe.h"
Patrik Stridvallbc38d6b2001-07-20 18:00:00 +000046
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000047#include "wine/debug.h"
Alexandre Julliard5f721f81994-01-04 20:14:34 +000048
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000049WINE_DEFAULT_DEBUG_CHANNEL(atom);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000050
Alexandre Julliard5f721f81994-01-04 20:14:34 +000051#define DEFAULT_ATOMTABLE_SIZE 37
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000052#define MAX_ATOM_LEN 255
Alexandre Julliard5f721f81994-01-04 20:14:34 +000053
Alexandre Julliard8bbf8181996-09-13 16:50:47 +000054#define ATOMTOHANDLE(atom) ((HANDLE16)(atom) << 2)
Alexandre Julliard5f721f81994-01-04 20:14:34 +000055#define HANDLETOATOM(handle) ((ATOM)(0xc000 | ((handle) >> 2)))
56
Alexandre Julliard737fa071998-11-15 17:29:15 +000057typedef struct
58{
59 HANDLE16 next;
60 WORD refCount;
61 BYTE length;
62 BYTE str[1];
63} ATOMENTRY;
64
65typedef struct
66{
67 WORD size;
68 HANDLE16 entries[1];
69} ATOMTABLE;
Vincent Béron9a624912002-05-31 23:06:46 +000070
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000071
72/***********************************************************************
73 * ATOM_GetTable
74 *
75 * Return a pointer to the atom table of a given segment, creating
76 * it if necessary.
Alexandre Julliard54c27111998-03-29 19:44:57 +000077 *
78 * RETURNS
79 * Pointer to table: Success
80 * NULL: Failure
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000081 */
Alexandre Julliardb849d792000-02-13 13:56:13 +000082static ATOMTABLE *ATOM_GetTable( BOOL create /* [in] Create */ )
Alexandre Julliard737fa071998-11-15 17:29:15 +000083{
Alexandre Julliard982a2232000-12-13 20:20:09 +000084 INSTANCEDATA *ptr = MapSL( MAKESEGPTR( CURRENT_DS, 0 ) );
Alexandre Julliard737fa071998-11-15 17:29:15 +000085 if (ptr->atomtable)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000086 {
Alexandre Julliard737fa071998-11-15 17:29:15 +000087 ATOMTABLE *table = (ATOMTABLE *)((char *)ptr + ptr->atomtable);
88 if (table->size) return table;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000089 }
Alexandre Julliard737fa071998-11-15 17:29:15 +000090 if (!create) return NULL;
Alexandre Julliardb849d792000-02-13 13:56:13 +000091 if (!InitAtomTable16( 0 )) return NULL;
Alexandre Julliard737fa071998-11-15 17:29:15 +000092 /* Reload ptr in case it moved in linear memory */
Alexandre Julliard982a2232000-12-13 20:20:09 +000093 ptr = MapSL( MAKESEGPTR( CURRENT_DS, 0 ) );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000094 return (ATOMTABLE *)((char *)ptr + ptr->atomtable);
Alexandre Julliard5f721f81994-01-04 20:14:34 +000095}
96
97
98/***********************************************************************
Alexandre Julliard5f721f81994-01-04 20:14:34 +000099 * ATOM_Hash
Alexandre Julliard54c27111998-03-29 19:44:57 +0000100 * RETURNS
101 * The hash value for the input string
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000102 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000103static WORD ATOM_Hash(
104 WORD entries, /* [in] Total number of entries */
105 LPCSTR str, /* [in] Pointer to string to hash */
106 WORD len /* [in] Length of string */
107) {
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000108 WORD i, hash = 0;
109
Alexandre Julliard15657091999-05-23 10:25:25 +0000110 TRACE("%x, %s, %x\n", entries, str, len);
Vincent Béron9a624912002-05-31 23:06:46 +0000111
Alexandre Julliardcdd09231994-01-12 11:12:51 +0000112 for (i = 0; i < len; i++) hash ^= toupper(str[i]) + i;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000113 return hash % entries;
114}
115
116
117/***********************************************************************
Alexandre Julliardb849d792000-02-13 13:56:13 +0000118 * ATOM_IsIntAtomA
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000119 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000120static BOOL ATOM_IsIntAtomA(LPCSTR atomstr,WORD *atomid)
121{
122 UINT atom = 0;
123 if (!HIWORD(atomstr)) atom = LOWORD(atomstr);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000124 else
125 {
Alexandre Julliardb849d792000-02-13 13:56:13 +0000126 if (*atomstr++ != '#') return FALSE;
127 while (*atomstr >= '0' && *atomstr <= '9')
128 {
129 atom = atom * 10 + *atomstr - '0';
130 atomstr++;
131 }
132 if (*atomstr) return FALSE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000133 }
Dmitry Timoshkovc8ab54d2002-10-04 17:45:00 +0000134 if (atom >= MAXINTATOM)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000135 {
136 SetLastError( ERROR_INVALID_PARAMETER );
137 atom = 0;
138 }
139 *atomid = atom;
140 return TRUE;
141}
142
143
144/***********************************************************************
145 * ATOM_IsIntAtomW
146 */
147static BOOL ATOM_IsIntAtomW(LPCWSTR atomstr,WORD *atomid)
148{
149 UINT atom = 0;
150 if (!HIWORD(atomstr)) atom = LOWORD(atomstr);
151 else
152 {
153 if (*atomstr++ != '#') return FALSE;
154 while (*atomstr >= '0' && *atomstr <= '9')
155 {
156 atom = atom * 10 + *atomstr - '0';
157 atomstr++;
158 }
159 if (*atomstr) return FALSE;
160 }
Dmitry Timoshkovc8ab54d2002-10-04 17:45:00 +0000161 if (atom >= MAXINTATOM)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000162 {
163 SetLastError( ERROR_INVALID_PARAMETER );
164 atom = 0;
165 }
166 *atomid = atom;
167 return TRUE;
168}
169
170
171/***********************************************************************
172 * ATOM_MakePtr
173 *
174 * Make an ATOMENTRY pointer from a handle (obtained from GetAtomHandle()).
175 */
176static inline ATOMENTRY *ATOM_MakePtr( HANDLE16 handle /* [in] Handle */ )
177{
Alexandre Julliard982a2232000-12-13 20:20:09 +0000178 return MapSL( MAKESEGPTR( CURRENT_DS, handle ) );
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000179}
180
181
182/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000183 * InitAtomTable (KERNEL.68)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000184 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000185WORD WINAPI InitAtomTable16( WORD entries )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000186{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000187 int i;
188 HANDLE16 handle;
189 ATOMTABLE *table;
190
Alexandre Julliardb849d792000-02-13 13:56:13 +0000191 /* Allocate the table */
192
Alexandre Julliard737fa071998-11-15 17:29:15 +0000193 if (!entries) entries = DEFAULT_ATOMTABLE_SIZE; /* sanity check */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000194 handle = LocalAlloc16( LMEM_FIXED, sizeof(ATOMTABLE) + (entries-1) * sizeof(HANDLE16) );
195 if (!handle) return 0;
Alexandre Julliard982a2232000-12-13 20:20:09 +0000196 table = MapSL( MAKESEGPTR( CURRENT_DS, handle ) );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000197 table->size = entries;
198 for (i = 0; i < entries; i++) table->entries[i] = 0;
199
200 /* Store a pointer to the table in the instance data */
201
Alexandre Julliard982a2232000-12-13 20:20:09 +0000202 ((INSTANCEDATA *)MapSL( MAKESEGPTR( CURRENT_DS, 0 )))->atomtable = handle;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000203 return handle;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000204}
205
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000206/***********************************************************************
207 * GetAtomHandle (KERNEL.73)
208 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000209HANDLE16 WINAPI GetAtomHandle16( ATOM atom )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000210{
Francois Gouget541ff5f2001-10-15 17:49:23 +0000211 if (atom < MAXINTATOM) return 0;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000212 return ATOMTOHANDLE( atom );
213}
214
215
216/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000217 * AddAtom (KERNEL.70)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000218 *
219 * Windows DWORD aligns the atom entry size.
220 * The remaining unused string space created by the alignment
221 * gets padded with '\0's in a certain way to ensure
222 * that at least one trailing '\0' remains.
223 *
224 * RETURNS
225 * Atom: Success
226 * 0: Failure
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000227 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000228ATOM WINAPI AddAtom16( LPCSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000229{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000230 char buffer[MAX_ATOM_LEN+1];
231 WORD hash;
232 HANDLE16 entry;
233 ATOMENTRY * entryPtr;
234 ATOMTABLE * table;
235 int len, ae_len;
236 WORD iatom;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000237
Alexandre Julliardb849d792000-02-13 13:56:13 +0000238 if (ATOM_IsIntAtomA( str, &iatom )) return iatom;
239
240 TRACE("%s\n",debugstr_a(buffer));
Vincent Béron9a624912002-05-31 23:06:46 +0000241
Alexandre Julliardb849d792000-02-13 13:56:13 +0000242 /* Make a copy of the string to be sure it doesn't move in linear memory. */
243 lstrcpynA( buffer, str, sizeof(buffer) );
244
245 len = strlen( buffer );
246 if (!(table = ATOM_GetTable( TRUE ))) return 0;
Alexandre Julliardbcb7f4e2000-02-19 20:51:29 +0000247
Alexandre Julliardb849d792000-02-13 13:56:13 +0000248 hash = ATOM_Hash( table->size, buffer, len );
249 entry = table->entries[hash];
250 while (entry)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000251 {
Alexandre Julliardb849d792000-02-13 13:56:13 +0000252 entryPtr = ATOM_MakePtr( entry );
Vincent Béron9a624912002-05-31 23:06:46 +0000253 if ((entryPtr->length == len) &&
Alexandre Julliard072dfb52000-09-25 23:30:56 +0000254 (!strncasecmp( entryPtr->str, buffer, len )))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000255 {
256 entryPtr->refCount++;
257 TRACE("-- existing 0x%x\n", entry);
258 return HANDLETOATOM( entry );
259 }
260 entry = entryPtr->next;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000261 }
Alexandre Julliardb849d792000-02-13 13:56:13 +0000262
263 ae_len = (sizeof(ATOMENTRY)+len+3) & ~3;
264 entry = LocalAlloc16( LMEM_FIXED, ae_len );
265 if (!entry) return 0;
266 /* Reload the table ptr in case it moved in linear memory */
267 table = ATOM_GetTable( FALSE );
268 entryPtr = ATOM_MakePtr( entry );
269 entryPtr->next = table->entries[hash];
270 entryPtr->refCount = 1;
271 entryPtr->length = len;
272 /* Some applications _need_ the '\0' padding provided by this strncpy */
273 strncpy( entryPtr->str, buffer, ae_len - sizeof(ATOMENTRY) + 1 );
274 entryPtr->str[ae_len - sizeof(ATOMENTRY)] = '\0';
275 table->entries[hash] = entry;
276 TRACE("-- new 0x%x\n", entry);
277 return HANDLETOATOM( entry );
278}
279
280
281/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000282 * DeleteAtom (KERNEL.71)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000283 */
284ATOM WINAPI DeleteAtom16( ATOM atom )
285{
286 ATOMENTRY * entryPtr;
287 ATOMTABLE * table;
288 HANDLE16 entry, *prevEntry;
289 WORD hash;
290
Francois Gouget541ff5f2001-10-15 17:49:23 +0000291 if (atom < MAXINTATOM) return 0; /* Integer atom */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000292
293 TRACE("0x%x\n",atom);
294
295 if (!(table = ATOM_GetTable( FALSE ))) return 0;
296 entry = ATOMTOHANDLE( atom );
297 entryPtr = ATOM_MakePtr( entry );
298
299 /* Find previous atom */
300 hash = ATOM_Hash( table->size, entryPtr->str, entryPtr->length );
301 prevEntry = &table->entries[hash];
302 while (*prevEntry && *prevEntry != entry)
303 {
304 ATOMENTRY * prevEntryPtr = ATOM_MakePtr( *prevEntry );
305 prevEntry = &prevEntryPtr->next;
Vincent Béron9a624912002-05-31 23:06:46 +0000306 }
Alexandre Julliardb849d792000-02-13 13:56:13 +0000307 if (!*prevEntry) return atom;
308
309 /* Delete atom */
310 if (--entryPtr->refCount == 0)
311 {
312 *prevEntry = entryPtr->next;
313 LocalFree16( entry );
Vincent Béron9a624912002-05-31 23:06:46 +0000314 }
Alexandre Julliardb849d792000-02-13 13:56:13 +0000315 return 0;
316}
317
318
319/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000320 * FindAtom (KERNEL.69)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000321 */
322ATOM WINAPI FindAtom16( LPCSTR str )
323{
324 ATOMTABLE * table;
325 WORD hash,iatom;
326 HANDLE16 entry;
327 int len;
328
Alexandre Julliard0aa28b52002-05-17 02:55:48 +0000329 TRACE("%s\n",debugstr_a(str));
Alexandre Julliardb849d792000-02-13 13:56:13 +0000330
331 if (ATOM_IsIntAtomA( str, &iatom )) return iatom;
332 if ((len = strlen( str )) > 255) len = 255;
333 if (!(table = ATOM_GetTable( FALSE ))) return 0;
334 hash = ATOM_Hash( table->size, str, len );
335 entry = table->entries[hash];
336 while (entry)
337 {
338 ATOMENTRY * entryPtr = ATOM_MakePtr( entry );
Vincent Béron9a624912002-05-31 23:06:46 +0000339 if ((entryPtr->length == len) &&
Alexandre Julliard072dfb52000-09-25 23:30:56 +0000340 (!strncasecmp( entryPtr->str, str, len )))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000341 {
342 TRACE("-- found %x\n", entry);
343 return HANDLETOATOM( entry );
344 }
345 entry = entryPtr->next;
346 }
347 TRACE("-- not found\n");
348 return 0;
349}
350
351
352/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000353 * GetAtomName (KERNEL.72)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000354 */
355UINT16 WINAPI GetAtomName16( ATOM atom, LPSTR buffer, INT16 count )
356{
357 ATOMTABLE * table;
358 ATOMENTRY * entryPtr;
359 HANDLE16 entry;
360 char * strPtr;
361 UINT len;
362 char text[8];
363
Alexandre Julliardb849d792000-02-13 13:56:13 +0000364 TRACE("%x\n",atom);
Vincent Béron9a624912002-05-31 23:06:46 +0000365
Alexandre Julliardb849d792000-02-13 13:56:13 +0000366 if (!count) return 0;
Francois Gouget541ff5f2001-10-15 17:49:23 +0000367 if (atom < MAXINTATOM)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000368 {
369 sprintf( text, "#%d", atom );
370 len = strlen(text);
371 strPtr = text;
372 }
373 else
374 {
375 if (!(table = ATOM_GetTable( FALSE ))) return 0;
376 entry = ATOMTOHANDLE( atom );
377 entryPtr = ATOM_MakePtr( entry );
378 len = entryPtr->length;
379 strPtr = entryPtr->str;
380 }
381 if (len >= count) len = count-1;
382 memcpy( buffer, strPtr, len );
383 buffer[len] = '\0';
384 return len;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000385}
386
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000387/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000388 * InitAtomTable (KERNEL32.@)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000389 */
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000390BOOL WINAPI InitAtomTable( DWORD entries )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000391{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000392 BOOL ret;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000393 SERVER_START_REQ( init_atom_table )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000394 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000395 req->entries = entries;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000396 ret = !wine_server_call_err( req );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000397 }
398 SERVER_END_REQ;
399 return ret;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000400}
401
402
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000403static ATOM ATOM_AddAtomA( LPCSTR str, BOOL local )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000404{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000405 ATOM atom = 0;
406 if (!ATOM_IsIntAtomA( str, &atom ))
407 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000408 WCHAR buffer[MAX_ATOM_LEN];
409
410 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
411 if (!len)
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000412 {
413 SetLastError( ERROR_INVALID_PARAMETER );
414 return 0;
415 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000416 SERVER_START_REQ( add_atom )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000417 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000418 wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000419 req->local = local;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000420 if (!wine_server_call_err(req)) atom = reply->atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000421 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000422 SERVER_END_REQ;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000423 }
Alexandre Julliard0aa28b52002-05-17 02:55:48 +0000424 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugstr_a(str), atom );
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000425 return atom;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000426}
427
428
429/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000430 * GlobalAddAtomA (KERNEL32.@)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000431 *
Alexandre Julliard54c27111998-03-29 19:44:57 +0000432 * Adds a character string to the global atom table and returns a unique
433 * value identifying the string.
434 *
435 * RETURNS
436 * Atom: Success
437 * 0: Failure
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000438 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000439ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
440{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000441 return ATOM_AddAtomA( str, FALSE );
442}
443
444
445/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000446 * AddAtomA (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000447 * Adds a string to the atom table and returns the atom identifying the
448 * string.
449 *
450 * RETURNS
451 * Atom: Success
452 * 0: Failure
453 */
454ATOM WINAPI AddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
455{
456 return ATOM_AddAtomA( str, TRUE );
457}
458
459
460static ATOM ATOM_AddAtomW( LPCWSTR str, BOOL local )
461{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000462 ATOM atom = 0;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000463 if (!ATOM_IsIntAtomW( str, &atom ))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000464 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000465 DWORD len = strlenW(str);
466 if (len > MAX_ATOM_LEN)
467 {
468 SetLastError( ERROR_INVALID_PARAMETER );
469 return 0;
470 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000471 SERVER_START_REQ( add_atom )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000472 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000473 req->local = local;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000474 wine_server_add_data( req, str, len * sizeof(WCHAR) );
475 if (!wine_server_call_err(req)) atom = reply->atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000476 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000477 SERVER_END_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000478 }
Alexandre Julliard0aa28b52002-05-17 02:55:48 +0000479 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugstr_w(str), atom );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000480 return atom;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000481}
482
483
484/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000485 * GlobalAddAtomW (KERNEL32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000486 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000487ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000488{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000489 return ATOM_AddAtomW( str, FALSE );
490}
491
492
493/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000494 * AddAtomW (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000495 */
496ATOM WINAPI AddAtomW( LPCWSTR str )
497{
498 return ATOM_AddAtomW( str, TRUE );
499}
500
501
502static ATOM ATOM_DeleteAtom( ATOM atom, BOOL local)
503{
Andreas Mohrc9cf70d2001-01-26 20:40:50 +0000504 TRACE( "(%s) %x\n", local ? "local" : "global", atom );
Dmitry Timoshkovc8ab54d2002-10-04 17:45:00 +0000505 if (atom >= MAXINTATOM)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000506 {
Alexandre Julliard67a74992001-02-27 02:09:16 +0000507 SERVER_START_REQ( delete_atom )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000508 {
Alexandre Julliardd8a8c112001-10-12 18:45:29 +0000509 req->atom = atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000510 req->local = local;
Dmitry Timoshkovc8ab54d2002-10-04 17:45:00 +0000511 wine_server_call_err( req );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000512 }
513 SERVER_END_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000514 }
Dmitry Timoshkovc8ab54d2002-10-04 17:45:00 +0000515 return 0;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000516}
517
518
519/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000520 * GlobalDeleteAtom (KERNEL32.@)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000521 * Decrements the reference count of a string atom. If the count is
522 * zero, the string associated with the atom is removed from the table.
523 *
524 * RETURNS
525 * 0: Success
526 * Atom: Failure
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000527 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000528ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000529{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000530 return ATOM_DeleteAtom( atom, FALSE);
531}
532
533
534/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000535 * DeleteAtom (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000536 * Decrements the reference count of a string atom. If count becomes
537 * zero, the string associated with the atom is removed from the table.
538 *
539 * RETURNS
540 * 0: Success
541 * Atom: Failure
542 */
543ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ )
544{
Vincent Béron9a624912002-05-31 23:06:46 +0000545 return ATOM_DeleteAtom( atom, TRUE );
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000546}
547
548
549static ATOM ATOM_FindAtomA( LPCSTR str, BOOL local )
550{
551 ATOM atom = 0;
552 if (!ATOM_IsIntAtomA( str, &atom ))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000553 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000554 WCHAR buffer[MAX_ATOM_LEN];
555
556 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
557 if (!len)
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000558 {
559 SetLastError( ERROR_INVALID_PARAMETER );
560 return 0;
561 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000562 SERVER_START_REQ( find_atom )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000563 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000564 req->local = local;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000565 wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
566 if (!wine_server_call_err(req)) atom = reply->atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000567 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000568 SERVER_END_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000569 }
Alexandre Julliard0aa28b52002-05-17 02:55:48 +0000570 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugstr_a(str), atom );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000571 return atom;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000572}
573
574
575/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000576 * GlobalFindAtomA (KERNEL32.@)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000577 *
Alexandre Julliard54c27111998-03-29 19:44:57 +0000578 * Searches the atom table for the string and returns the atom
579 * associated with it.
580 *
581 * RETURNS
582 * Atom: Success
583 * 0: Failure
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000584 */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000585ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ )
586{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000587 return ATOM_FindAtomA( str, FALSE );
588}
589
590/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000591 * FindAtomA (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000592 * Searches the local atom table for the string and returns the atom
593 * associated with that string.
594 *
595 * RETURNS
596 * Atom: Success
597 * 0: Failure
598 */
599ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ )
600{
601 return ATOM_FindAtomA( str, TRUE );
602}
603
604
605static ATOM ATOM_FindAtomW( LPCWSTR str, BOOL local )
606{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000607 ATOM atom = 0;
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000608 if (!ATOM_IsIntAtomW( str, &atom ))
Alexandre Julliardb849d792000-02-13 13:56:13 +0000609 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000610 DWORD len = strlenW(str);
611 if (len > MAX_ATOM_LEN)
612 {
613 SetLastError( ERROR_INVALID_PARAMETER );
614 return 0;
615 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000616 SERVER_START_REQ( find_atom )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000617 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000618 wine_server_add_data( req, str, len * sizeof(WCHAR) );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000619 req->local = local;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000620 if (!wine_server_call_err( req )) atom = reply->atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000621 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000622 SERVER_END_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000623 }
Alexandre Julliard0aa28b52002-05-17 02:55:48 +0000624 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugstr_w(str), atom );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000625 return atom;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000626}
627
628
629/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000630 * GlobalFindAtomW (KERNEL32.@)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000631 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000632ATOM WINAPI GlobalFindAtomW( LPCWSTR str )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000633{
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000634 return ATOM_FindAtomW( str, FALSE );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000635}
636
637
638/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000639 * FindAtomW (KERNEL32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000640 */
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000641ATOM WINAPI FindAtomW( LPCWSTR str )
642{
643 return ATOM_FindAtomW( str, TRUE );
644}
645
646
647static UINT ATOM_GetAtomNameA( ATOM atom, LPSTR buffer, INT count, BOOL local )
Alexandre Julliardb849d792000-02-13 13:56:13 +0000648{
649 INT len;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000650
651 if (count <= 0)
652 {
653 SetLastError( ERROR_MORE_DATA );
654 return 0;
655 }
Francois Gouget541ff5f2001-10-15 17:49:23 +0000656 if (atom < MAXINTATOM)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000657 {
658 char name[8];
659 if (!atom)
660 {
661 SetLastError( ERROR_INVALID_PARAMETER );
662 return 0;
663 }
664 len = sprintf( name, "#%d", atom );
665 lstrcpynA( buffer, name, count );
666 }
667 else
668 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000669 WCHAR full_name[MAX_ATOM_LEN];
670
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000671 len = 0;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000672 SERVER_START_REQ( get_atom_name )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000673 {
Alexandre Julliardd8a8c112001-10-12 18:45:29 +0000674 req->atom = atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000675 req->local = local;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000676 wine_server_set_reply( req, full_name, sizeof(full_name) );
677 if (!wine_server_call_err( req ))
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000678 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000679 len = WideCharToMultiByte( CP_ACP, 0, full_name,
680 wine_server_reply_size(reply) / sizeof(WCHAR),
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000681 buffer, count - 1, NULL, NULL );
682 if (!len) len = count; /* overflow */
683 else buffer[len] = 0;
684 }
685 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000686 SERVER_END_REQ;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000687 }
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000688
689 if (len && count <= len)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000690 {
691 SetLastError( ERROR_MORE_DATA );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000692 buffer[count-1] = 0;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000693 return 0;
694 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000695 TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_a(buffer) );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000696 return len;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000697}
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000698
Alexandre Julliard54c27111998-03-29 19:44:57 +0000699
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000700/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000701 * GlobalGetAtomNameA (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000702 *
703 * Retrieves a copy of the string associated with an atom.
704 *
705 * RETURNS
706 * Length of string in characters: Success
707 * 0: Failure
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000708 */
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000709UINT WINAPI GlobalGetAtomNameA(
710 ATOM atom, /* [in] Atom identifier */
711 LPSTR buffer, /* [out] Pointer to buffer for atom string */
712 INT count ) /* [in] Size of buffer */
713{
714 return ATOM_GetAtomNameA( atom, buffer, count, FALSE );
715}
716
717
718/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000719 * GetAtomNameA (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000720 * Retrieves a copy of the string associated with the atom.
721 *
722 * RETURNS
723 * Length of string: Success
724 * 0: Failure
725 */
726UINT WINAPI GetAtomNameA(
727 ATOM atom, /* [in] Atom */
728 LPSTR buffer, /* [out] Pointer to string for atom string */
729 INT count) /* [in] Size of buffer */
730{
731 return ATOM_GetAtomNameA( atom, buffer, count, TRUE );
732}
733
734
735static UINT ATOM_GetAtomNameW( ATOM atom, LPWSTR buffer, INT count, BOOL local )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000736{
Alexandre Julliardb849d792000-02-13 13:56:13 +0000737 INT len;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000738
739 if (count <= 0)
740 {
741 SetLastError( ERROR_MORE_DATA );
742 return 0;
743 }
Francois Gouget541ff5f2001-10-15 17:49:23 +0000744 if (atom < MAXINTATOM)
Alexandre Julliardb849d792000-02-13 13:56:13 +0000745 {
746 char name[8];
747 if (!atom)
748 {
749 SetLastError( ERROR_INVALID_PARAMETER );
750 return 0;
751 }
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000752 sprintf( name, "#%d", atom );
753 len = MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, count );
754 if (!len) buffer[count-1] = 0; /* overflow */
Alexandre Julliardb849d792000-02-13 13:56:13 +0000755 }
756 else
757 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000758 WCHAR full_name[MAX_ATOM_LEN];
759
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000760 len = 0;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000761 SERVER_START_REQ( get_atom_name )
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000762 {
Alexandre Julliardd8a8c112001-10-12 18:45:29 +0000763 req->atom = atom;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000764 req->local = local;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000765 wine_server_set_reply( req, full_name, sizeof(full_name) );
766 if (!wine_server_call_err( req ))
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000767 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000768 len = wine_server_reply_size(reply) / sizeof(WCHAR);
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000769 if (count > len) count = len + 1;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000770 memcpy( buffer, full_name, (count-1) * sizeof(WCHAR) );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000771 buffer[count-1] = 0;
772 }
773 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000774 SERVER_END_REQ;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000775 if (!len) return 0;
Alexandre Julliardb849d792000-02-13 13:56:13 +0000776 }
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000777 TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_w(buffer) );
Alexandre Julliardb849d792000-02-13 13:56:13 +0000778 return len;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000779}
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000780
781
782/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000783 * GlobalGetAtomNameW (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000784 */
785UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
786{
787 return ATOM_GetAtomNameW( atom, buffer, count, FALSE);
788}
789
790
791/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000792 * GetAtomNameW (KERNEL32.@)
Turchanov Sergei43a27e32000-05-30 20:32:06 +0000793 */
794UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
795{
796 return ATOM_GetAtomNameW( atom, buffer, count, TRUE );
797}