4 * Copyright 1993, 1994, 1995 Alexandre Julliard
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.
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.
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
22 * 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
29 #include "wine/port.h"
41 #include "wine/server.h"
42 #include "wine/unicode.h"
43 #include "kernel_private.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(atom);
49 #define MAX_ATOM_LEN 255
51 static struct atom_table* get_local_table(DWORD entries)
53 static struct atom_table* local_table;
58 struct atom_table* table;
60 SERVER_START_REQ( init_atom_table )
62 req->entries = entries;
63 status = wine_server_call( req );
69 SetLastError( RtlNtStatusToDosError( status ) );
70 else if (InterlockedCompareExchangePointer((void*)&local_table, table, NULL) != NULL)
71 NtClose((HANDLE)table);
76 /***********************************************************************
79 static BOOL ATOM_IsIntAtomA(LPCSTR atomstr,WORD *atomid)
82 if (!HIWORD(atomstr)) atom = LOWORD(atomstr);
85 if (*atomstr++ != '#') return FALSE;
86 while (*atomstr >= '0' && *atomstr <= '9')
88 atom = atom * 10 + *atomstr - '0';
91 if (*atomstr) return FALSE;
93 if (atom >= MAXINTATOM)
95 SetLastError( ERROR_INVALID_PARAMETER );
103 /***********************************************************************
106 static BOOL ATOM_IsIntAtomW(LPCWSTR atomstr,WORD *atomid)
109 if (!HIWORD(atomstr)) atom = LOWORD(atomstr);
112 if (*atomstr++ != '#') return FALSE;
113 while (*atomstr >= '0' && *atomstr <= '9')
115 atom = atom * 10 + *atomstr - '0';
118 if (*atomstr) return FALSE;
120 if (atom >= MAXINTATOM)
122 SetLastError( ERROR_INVALID_PARAMETER );
130 /***********************************************************************
131 * InitAtomTable (KERNEL32.@)
133 * Initialise the global atom table.
136 * entries [I] The number of entries to reserve in the table.
142 BOOL WINAPI InitAtomTable( DWORD entries )
144 return get_local_table( entries ) ? TRUE : FALSE;
148 static ATOM ATOM_AddAtomA( LPCSTR str, struct atom_table* table )
151 if (!ATOM_IsIntAtomA( str, &atom ))
153 WCHAR buffer[MAX_ATOM_LEN];
155 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
158 SetLastError( ERROR_INVALID_PARAMETER );
161 SERVER_START_REQ( add_atom )
163 wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
165 if (!wine_server_call_err(req)) atom = reply->atom;
169 TRACE( "(%s) %s -> %x\n", table ? "local" : "global", debugstr_a(str), atom );
174 /***********************************************************************
175 * GlobalAddAtomA (KERNEL32.@)
177 * Add a character string to the global atom table and return a unique
178 * value identifying it.
181 * Success: The atom allocated to str.
184 ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] String to add */ )
186 return ATOM_AddAtomA( str, NULL );
190 /***********************************************************************
191 * AddAtomA (KERNEL32.@)
193 * Add a character string to the global atom table and return a unique
194 * value identifying it.
197 * Success: The atom allocated to str.
200 ATOM WINAPI AddAtomA( LPCSTR str /* [in] String to add */ )
202 return ATOM_AddAtomA( str, get_local_table(0) );
206 static ATOM ATOM_AddAtomW( LPCWSTR str, struct atom_table* table )
209 if (!ATOM_IsIntAtomW( str, &atom ))
211 DWORD len = strlenW(str);
212 if (len > MAX_ATOM_LEN)
214 SetLastError( ERROR_INVALID_PARAMETER );
217 SERVER_START_REQ( add_atom )
220 wine_server_add_data( req, str, len * sizeof(WCHAR) );
221 if (!wine_server_call_err(req)) atom = reply->atom;
225 TRACE( "(%s) %s -> %x\n", table ? "local" : "global", debugstr_w(str), atom );
230 /***********************************************************************
231 * GlobalAddAtomW (KERNEL32.@)
233 * Unicode version of GlobalAddAtomA.
235 ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
237 return ATOM_AddAtomW( str, NULL );
241 /***********************************************************************
242 * AddAtomW (KERNEL32.@)
244 * Unicode version of AddAtomA.
246 ATOM WINAPI AddAtomW( LPCWSTR str )
248 return ATOM_AddAtomW( str, get_local_table(0) );
252 static ATOM ATOM_DeleteAtom( ATOM atom, struct atom_table* table )
254 TRACE( "(%s) %x\n", table ? "local" : "global", atom );
255 if (atom >= MAXINTATOM)
257 SERVER_START_REQ( delete_atom )
261 wine_server_call_err( req );
269 /***********************************************************************
270 * GlobalDeleteAtom (KERNEL32.@)
272 * Decrement the reference count of a string atom. If the count is
273 * zero, the string associated with the atom is removed from the table.
279 ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
281 return ATOM_DeleteAtom( atom, NULL);
285 /***********************************************************************
286 * DeleteAtom (KERNEL32.@)
288 * Decrement the reference count of a string atom. If the count becomes
289 * zero, the string associated with the atom is removed from the table.
295 ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ )
297 return ATOM_DeleteAtom( atom, get_local_table(0) );
301 static ATOM ATOM_FindAtomA( LPCSTR str, struct atom_table* table )
304 if (!ATOM_IsIntAtomA( str, &atom ))
306 WCHAR buffer[MAX_ATOM_LEN];
308 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
311 SetLastError( ERROR_INVALID_PARAMETER );
314 SERVER_START_REQ( find_atom )
317 wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
318 if (!wine_server_call_err(req)) atom = reply->atom;
322 TRACE( "(%s) %s -> %x\n", table ? "local" : "global", debugstr_a(str), atom );
327 /***********************************************************************
328 * GlobalFindAtomA (KERNEL32.@)
330 * Get the atom associated with a string.
333 * Success: The associated atom.
336 ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ )
338 return ATOM_FindAtomA( str, NULL );
341 /***********************************************************************
342 * FindAtomA (KERNEL32.@)
344 * Get the atom associated with a string.
347 * Success: The associated atom.
350 ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ )
352 return ATOM_FindAtomA( str, get_local_table(0) );
356 static ATOM ATOM_FindAtomW( LPCWSTR str, struct atom_table* table )
359 if (!ATOM_IsIntAtomW( str, &atom ))
361 DWORD len = strlenW(str);
362 if (len > MAX_ATOM_LEN)
364 SetLastError( ERROR_INVALID_PARAMETER );
367 SERVER_START_REQ( find_atom )
369 wine_server_add_data( req, str, len * sizeof(WCHAR) );
371 if (!wine_server_call_err( req )) atom = reply->atom;
375 TRACE( "(%s) %s -> %x\n", table ? "local" : "global", debugstr_w(str), atom );
380 /***********************************************************************
381 * GlobalFindAtomW (KERNEL32.@)
383 * Unicode version of GlobalFindAtomA.
385 ATOM WINAPI GlobalFindAtomW( LPCWSTR str )
387 return ATOM_FindAtomW( str, NULL );
391 /***********************************************************************
392 * FindAtomW (KERNEL32.@)
394 * Unicode version of FindAtomA.
396 ATOM WINAPI FindAtomW( LPCWSTR str )
398 return ATOM_FindAtomW( str, get_local_table(0) );
402 static UINT ATOM_GetAtomNameA( ATOM atom, LPSTR buffer, INT count, struct atom_table* table )
408 SetLastError( ERROR_MORE_DATA );
411 if (atom < MAXINTATOM)
416 SetLastError( ERROR_INVALID_PARAMETER );
419 len = sprintf( name, "#%d", atom );
420 lstrcpynA( buffer, name, count );
424 WCHAR full_name[MAX_ATOM_LEN];
427 SERVER_START_REQ( get_atom_information )
431 wine_server_set_reply( req, full_name, sizeof(full_name) );
432 if (!wine_server_call_err( req ))
434 len = WideCharToMultiByte( CP_ACP, 0, full_name,
435 wine_server_reply_size(reply) / sizeof(WCHAR),
436 buffer, count - 1, NULL, NULL );
437 if (!len) len = count; /* overflow */
438 else buffer[len] = 0;
444 if (len && count <= len)
446 SetLastError( ERROR_MORE_DATA );
450 TRACE( "(%s) %x -> %s\n", table ? "local" : "global", atom, debugstr_a(buffer) );
455 /***********************************************************************
456 * GlobalGetAtomNameA (KERNEL32.@)
458 * Get a copy of the string associated with an atom.
461 * Success: The length of the returned string in characters.
464 UINT WINAPI GlobalGetAtomNameA(
465 ATOM atom, /* [in] Atom identifier */
466 LPSTR buffer, /* [out] Pointer to buffer for atom string */
467 INT count ) /* [in] Size of buffer */
469 return ATOM_GetAtomNameA( atom, buffer, count, NULL );
473 /***********************************************************************
474 * GetAtomNameA (KERNEL32.@)
476 * Get a copy of the string associated with an atom.
479 * Success: The length of the returned string in characters.
482 UINT WINAPI GetAtomNameA(
483 ATOM atom, /* [in] Atom */
484 LPSTR buffer, /* [out] Pointer to string for atom string */
485 INT count) /* [in] Size of buffer */
487 return ATOM_GetAtomNameA( atom, buffer, count, get_local_table(0) );
491 static UINT ATOM_GetAtomNameW( ATOM atom, LPWSTR buffer, INT count, struct atom_table* table )
497 SetLastError( ERROR_MORE_DATA );
500 if (atom < MAXINTATOM)
505 SetLastError( ERROR_INVALID_PARAMETER );
508 sprintf( name, "#%d", atom );
509 len = MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, count );
510 if (!len) buffer[count-1] = 0; /* overflow */
514 WCHAR full_name[MAX_ATOM_LEN];
517 SERVER_START_REQ( get_atom_information )
521 wine_server_set_reply( req, full_name, sizeof(full_name) );
522 if (!wine_server_call_err( req ))
524 len = wine_server_reply_size(reply) / sizeof(WCHAR);
525 if (count > len) count = len + 1;
526 memcpy( buffer, full_name, (count-1) * sizeof(WCHAR) );
533 TRACE( "(%s) %x -> %s\n", table ? "local" : "global", atom, debugstr_w(buffer) );
538 /***********************************************************************
539 * GlobalGetAtomNameW (KERNEL32.@)
541 * Unicode version of GlobalGetAtomNameA.
543 UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
545 return ATOM_GetAtomNameW( atom, buffer, count, NULL);
549 /***********************************************************************
550 * GetAtomNameW (KERNEL32.@)
552 * Unicode version of GetAtomNameA.
554 UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
556 return ATOM_GetAtomNameW( atom, buffer, count, get_local_table(0) );