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 /***********************************************************************
54 static BOOL ATOM_IsIntAtomA(LPCSTR atomstr,WORD *atomid)
57 if (!HIWORD(atomstr)) atom = LOWORD(atomstr);
60 if (*atomstr++ != '#') return FALSE;
61 while (*atomstr >= '0' && *atomstr <= '9')
63 atom = atom * 10 + *atomstr - '0';
66 if (*atomstr) return FALSE;
68 if (atom >= MAXINTATOM)
70 SetLastError( ERROR_INVALID_PARAMETER );
78 /***********************************************************************
81 static BOOL ATOM_IsIntAtomW(LPCWSTR atomstr,WORD *atomid)
84 if (!HIWORD(atomstr)) atom = LOWORD(atomstr);
87 if (*atomstr++ != '#') return FALSE;
88 while (*atomstr >= '0' && *atomstr <= '9')
90 atom = atom * 10 + *atomstr - '0';
93 if (*atomstr) return FALSE;
95 if (atom >= MAXINTATOM)
97 SetLastError( ERROR_INVALID_PARAMETER );
105 /***********************************************************************
106 * InitAtomTable (KERNEL32.@)
108 * Initialise the global atom table.
111 * entries [I] The number of entries to reserve in the table.
117 BOOL WINAPI InitAtomTable( DWORD entries )
120 SERVER_START_REQ( init_atom_table )
122 req->entries = entries;
123 ret = !wine_server_call_err( req );
130 static ATOM ATOM_AddAtomA( LPCSTR str, BOOL local )
133 if (!ATOM_IsIntAtomA( str, &atom ))
135 WCHAR buffer[MAX_ATOM_LEN];
137 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
140 SetLastError( ERROR_INVALID_PARAMETER );
143 SERVER_START_REQ( add_atom )
145 wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
147 if (!wine_server_call_err(req)) atom = reply->atom;
151 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugstr_a(str), atom );
156 /***********************************************************************
157 * GlobalAddAtomA (KERNEL32.@)
159 * Add a character string to the global atom table and return a unique
160 * value identifying it.
163 * Success: The atom allocated to str.
166 ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] String to add */ )
168 return ATOM_AddAtomA( str, FALSE );
172 /***********************************************************************
173 * AddAtomA (KERNEL32.@)
175 * Add a character string to the global atom table and return a unique
176 * value identifying it.
179 * Success: The atom allocated to str.
182 ATOM WINAPI AddAtomA( LPCSTR str /* [in] String to add */ )
184 return ATOM_AddAtomA( str, TRUE );
188 static ATOM ATOM_AddAtomW( LPCWSTR str, BOOL local )
191 if (!ATOM_IsIntAtomW( str, &atom ))
193 DWORD len = strlenW(str);
194 if (len > MAX_ATOM_LEN)
196 SetLastError( ERROR_INVALID_PARAMETER );
199 SERVER_START_REQ( add_atom )
202 wine_server_add_data( req, str, len * sizeof(WCHAR) );
203 if (!wine_server_call_err(req)) atom = reply->atom;
207 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugstr_w(str), atom );
212 /***********************************************************************
213 * GlobalAddAtomW (KERNEL32.@)
215 * Unicode version of GlobalAddAtomA.
217 ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
219 return ATOM_AddAtomW( str, FALSE );
223 /***********************************************************************
224 * AddAtomW (KERNEL32.@)
226 * Unicode version of AddAtomA.
228 ATOM WINAPI AddAtomW( LPCWSTR str )
230 return ATOM_AddAtomW( str, TRUE );
234 static ATOM ATOM_DeleteAtom( ATOM atom, BOOL local)
236 TRACE( "(%s) %x\n", local ? "local" : "global", atom );
237 if (atom >= MAXINTATOM)
239 SERVER_START_REQ( delete_atom )
243 wine_server_call_err( req );
251 /***********************************************************************
252 * GlobalDeleteAtom (KERNEL32.@)
254 * Decrement the reference count of a string atom. If the count is
255 * zero, the string associated with the atom is removed from the table.
261 ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
263 return ATOM_DeleteAtom( atom, FALSE);
267 /***********************************************************************
268 * DeleteAtom (KERNEL32.@)
270 * Decrement the reference count of a string atom. If the count becomes
271 * zero, the string associated with the atom is removed from the table.
277 ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ )
279 return ATOM_DeleteAtom( atom, TRUE );
283 static ATOM ATOM_FindAtomA( LPCSTR str, BOOL local )
286 if (!ATOM_IsIntAtomA( str, &atom ))
288 WCHAR buffer[MAX_ATOM_LEN];
290 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
293 SetLastError( ERROR_INVALID_PARAMETER );
296 SERVER_START_REQ( find_atom )
299 wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
300 if (!wine_server_call_err(req)) atom = reply->atom;
304 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugstr_a(str), atom );
309 /***********************************************************************
310 * GlobalFindAtomA (KERNEL32.@)
312 * Get the atom associated with a string.
315 * Success: The associated atom.
318 ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ )
320 return ATOM_FindAtomA( str, FALSE );
323 /***********************************************************************
324 * FindAtomA (KERNEL32.@)
326 * Get the atom associated with a string.
329 * Success: The associated atom.
332 ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ )
334 return ATOM_FindAtomA( str, TRUE );
338 static ATOM ATOM_FindAtomW( LPCWSTR str, BOOL local )
341 if (!ATOM_IsIntAtomW( str, &atom ))
343 DWORD len = strlenW(str);
344 if (len > MAX_ATOM_LEN)
346 SetLastError( ERROR_INVALID_PARAMETER );
349 SERVER_START_REQ( find_atom )
351 wine_server_add_data( req, str, len * sizeof(WCHAR) );
353 if (!wine_server_call_err( req )) atom = reply->atom;
357 TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugstr_w(str), atom );
362 /***********************************************************************
363 * GlobalFindAtomW (KERNEL32.@)
365 * Unicode version of GlobalFindAtomA.
367 ATOM WINAPI GlobalFindAtomW( LPCWSTR str )
369 return ATOM_FindAtomW( str, FALSE );
373 /***********************************************************************
374 * FindAtomW (KERNEL32.@)
376 * Unicode version of FindAtomA.
378 ATOM WINAPI FindAtomW( LPCWSTR str )
380 return ATOM_FindAtomW( str, TRUE );
384 static UINT ATOM_GetAtomNameA( ATOM atom, LPSTR buffer, INT count, BOOL local )
390 SetLastError( ERROR_MORE_DATA );
393 if (atom < MAXINTATOM)
398 SetLastError( ERROR_INVALID_PARAMETER );
401 len = sprintf( name, "#%d", atom );
402 lstrcpynA( buffer, name, count );
406 WCHAR full_name[MAX_ATOM_LEN];
409 SERVER_START_REQ( get_atom_name )
413 wine_server_set_reply( req, full_name, sizeof(full_name) );
414 if (!wine_server_call_err( req ))
416 len = WideCharToMultiByte( CP_ACP, 0, full_name,
417 wine_server_reply_size(reply) / sizeof(WCHAR),
418 buffer, count - 1, NULL, NULL );
419 if (!len) len = count; /* overflow */
420 else buffer[len] = 0;
426 if (len && count <= len)
428 SetLastError( ERROR_MORE_DATA );
432 TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_a(buffer) );
437 /***********************************************************************
438 * GlobalGetAtomNameA (KERNEL32.@)
440 * Get a copy of the string associated with an atom.
443 * Success: The length of the returned string in characters.
446 UINT WINAPI GlobalGetAtomNameA(
447 ATOM atom, /* [in] Atom identifier */
448 LPSTR buffer, /* [out] Pointer to buffer for atom string */
449 INT count ) /* [in] Size of buffer */
451 return ATOM_GetAtomNameA( atom, buffer, count, FALSE );
455 /***********************************************************************
456 * GetAtomNameA (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 GetAtomNameA(
465 ATOM atom, /* [in] Atom */
466 LPSTR buffer, /* [out] Pointer to string for atom string */
467 INT count) /* [in] Size of buffer */
469 return ATOM_GetAtomNameA( atom, buffer, count, TRUE );
473 static UINT ATOM_GetAtomNameW( ATOM atom, LPWSTR buffer, INT count, BOOL local )
479 SetLastError( ERROR_MORE_DATA );
482 if (atom < MAXINTATOM)
487 SetLastError( ERROR_INVALID_PARAMETER );
490 sprintf( name, "#%d", atom );
491 len = MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, count );
492 if (!len) buffer[count-1] = 0; /* overflow */
496 WCHAR full_name[MAX_ATOM_LEN];
499 SERVER_START_REQ( get_atom_name )
503 wine_server_set_reply( req, full_name, sizeof(full_name) );
504 if (!wine_server_call_err( req ))
506 len = wine_server_reply_size(reply) / sizeof(WCHAR);
507 if (count > len) count = len + 1;
508 memcpy( buffer, full_name, (count-1) * sizeof(WCHAR) );
515 TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_w(buffer) );
520 /***********************************************************************
521 * GlobalGetAtomNameW (KERNEL32.@)
523 * Unicode version of GlobalGetAtomNameA.
525 UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
527 return ATOM_GetAtomNameW( atom, buffer, count, FALSE);
531 /***********************************************************************
532 * GetAtomNameW (KERNEL32.@)
534 * Unicode version of GetAtomNameA.
536 UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
538 return ATOM_GetAtomNameW( atom, buffer, count, TRUE );