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 #include "wine/port.h"
36 #include "wine/exception.h"
38 #include "wine/server.h"
39 #include "wine/unicode.h"
40 #include "kernel_private.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(atom);
46 #define MAX_ATOM_LEN 255
48 /* filter for page-fault exceptions */
49 static WINE_EXCEPTION_FILTER(page_fault)
51 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
52 return EXCEPTION_EXECUTE_HANDLER;
53 return EXCEPTION_CONTINUE_SEARCH;
56 /******************************************************************
59 * Returns the local atom table for this process (and create it if doesn't
62 static RTL_ATOM_TABLE get_local_table(DWORD entries)
64 static RTL_ATOM_TABLE local_table;
69 RTL_ATOM_TABLE table = NULL;
71 if ((status = RtlCreateAtomTable( entries, &table )))
72 SetLastError( RtlNtStatusToDosError( status ) );
73 else if (InterlockedCompareExchangePointer((void*)&local_table, table, NULL) != NULL)
74 RtlDestroyAtomTable( table );
81 /***********************************************************************
82 * InitAtomTable (KERNEL32.@)
84 * Initialise the global atom table.
87 * entries [I] The number of entries to reserve in the table.
93 BOOL WINAPI InitAtomTable( DWORD entries )
95 return get_local_table( entries ) ? TRUE : FALSE;
98 /******************************************************************
101 * Check if a string (ANSI or UNICODE) is in fact an integral atom
102 * (but doesn't check the "#1234" form)
104 static inline BOOL check_integral_atom( const void* ptr, ATOM* patom)
106 if (HIWORD( ptr )) return FALSE;
107 if ((*patom = LOWORD( ptr )) >= MAXINTATOM)
109 SetLastError( ERROR_INVALID_PARAMETER );
115 /***********************************************************************
116 * GlobalAddAtomA (KERNEL32.@)
118 * Add a character string to the global atom table and return a unique
119 * value identifying it.
122 * Success: The atom allocated to str.
125 ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] String to add */ )
130 if (!check_integral_atom( str, &atom ))
132 WCHAR buffer[MAX_ATOM_LEN];
133 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
134 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
137 NTSTATUS status = NtAddAtom( buffer, len * sizeof(WCHAR), &atom );
140 SetLastError( RtlNtStatusToDosError( status ) );
148 SetLastError( ERROR_INVALID_PARAMETER );
156 /***********************************************************************
157 * AddAtomA (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 AddAtomA( LPCSTR str /* [in] String to add */ )
170 if (!check_integral_atom( str, &atom ))
172 WCHAR buffer[MAX_ATOM_LEN + 1];
174 RTL_ATOM_TABLE table;
176 len = MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, MAX_ATOM_LEN + 1 );
177 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
178 else if ((table = get_local_table( 0 )))
180 NTSTATUS status = RtlAddAtomToAtomTable( table, buffer, &atom );
183 SetLastError( RtlNtStatusToDosError( status ) );
191 /***********************************************************************
192 * GlobalAddAtomW (KERNEL32.@)
194 * Unicode version of GlobalAddAtomA.
196 ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
201 if (!check_integral_atom( str, &atom ) &&
202 (status = NtAddAtom( str, strlenW( str ) * sizeof(WCHAR), &atom )))
204 SetLastError( RtlNtStatusToDosError( status ) );
211 /***********************************************************************
212 * AddAtomW (KERNEL32.@)
214 * Unicode version of AddAtomA.
216 ATOM WINAPI AddAtomW( LPCWSTR str )
219 RTL_ATOM_TABLE table;
221 if (!check_integral_atom( str, &atom ) && (table = get_local_table( 0 )))
223 NTSTATUS status = RtlAddAtomToAtomTable( table, str, &atom );
226 SetLastError( RtlNtStatusToDosError( status ) );
234 /***********************************************************************
235 * GlobalDeleteAtom (KERNEL32.@)
237 * Decrement the reference count of a string atom. If the count is
238 * zero, the string associated with the atom is removed from the table.
244 ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
246 if (atom >= MAXINTATOM)
248 NTSTATUS status = NtDeleteAtom( atom );
251 SetLastError( RtlNtStatusToDosError( status ) );
259 /***********************************************************************
260 * DeleteAtom (KERNEL32.@)
262 * Decrement the reference count of a string atom. If the count becomes
263 * zero, the string associated with the atom is removed from the table.
269 ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ )
272 RTL_ATOM_TABLE table;
274 if (atom >= MAXINTATOM)
276 if (!(table = get_local_table( 0 ))) return atom;
277 status = RtlDeleteAtomFromAtomTable( table, atom );
280 SetLastError( RtlNtStatusToDosError( status ) );
288 /***********************************************************************
289 * GlobalFindAtomA (KERNEL32.@)
291 * Get the atom associated with a string.
294 * Success: The associated atom.
297 ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ )
301 if (!check_integral_atom( str, &atom ))
303 WCHAR buffer[MAX_ATOM_LEN];
304 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
306 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
309 NTSTATUS status = NtFindAtom( buffer, len * sizeof(WCHAR), &atom );
312 SetLastError( RtlNtStatusToDosError( status ) );
320 /***********************************************************************
321 * FindAtomA (KERNEL32.@)
323 * Get the atom associated with a string.
326 * Success: The associated atom.
329 ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ )
333 if (!check_integral_atom( str, &atom ))
335 WCHAR buffer[MAX_ATOM_LEN + 1];
337 RTL_ATOM_TABLE table;
339 len = MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, MAX_ATOM_LEN + 1 );
340 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
341 else if ((table = get_local_table( 0 )))
343 NTSTATUS status = RtlLookupAtomInAtomTable( table, buffer, &atom );
346 SetLastError( RtlNtStatusToDosError( status ) );
355 /***********************************************************************
356 * GlobalFindAtomW (KERNEL32.@)
358 * Unicode version of GlobalFindAtomA.
360 ATOM WINAPI GlobalFindAtomW( LPCWSTR str )
364 if (!check_integral_atom( str, &atom ))
366 NTSTATUS status = NtFindAtom( str, strlenW( str ) * sizeof(WCHAR), &atom );
369 SetLastError( RtlNtStatusToDosError( status ) );
377 /***********************************************************************
378 * FindAtomW (KERNEL32.@)
380 * Unicode version of FindAtomA.
382 ATOM WINAPI FindAtomW( LPCWSTR str )
386 RTL_ATOM_TABLE table;
388 if ((table = get_local_table( 0 )))
390 status = RtlLookupAtomInAtomTable( table, str, &atom );
393 SetLastError( RtlNtStatusToDosError( status ) );
401 static UINT ATOM_GetAtomNameA( ATOM atom, LPSTR buffer, INT count, struct atom_table* table )
407 SetLastError( ERROR_MORE_DATA );
410 if (atom < MAXINTATOM)
415 SetLastError( ERROR_INVALID_PARAMETER );
418 len = sprintf( name, "#%d", atom );
419 lstrcpynA( buffer, name, count );
423 WCHAR full_name[MAX_ATOM_LEN];
426 SERVER_START_REQ( get_atom_information )
430 wine_server_set_reply( req, full_name, sizeof(full_name) );
431 if (!wine_server_call_err( req ))
433 len = WideCharToMultiByte( CP_ACP, 0, full_name,
434 wine_server_reply_size(reply) / sizeof(WCHAR),
435 buffer, count - 1, NULL, NULL );
436 if (!len) len = count; /* overflow */
437 else buffer[len] = 0;
443 if (len && count <= len)
445 SetLastError( ERROR_MORE_DATA );
449 TRACE( "(%s) %x -> %s\n", table ? "local" : "global", atom, debugstr_a(buffer) );
454 /***********************************************************************
455 * GlobalGetAtomNameA (KERNEL32.@)
457 * Get a copy of the string associated with an atom.
460 * Success: The length of the returned string in characters.
463 UINT WINAPI GlobalGetAtomNameA(
464 ATOM atom, /* [in] Atom identifier */
465 LPSTR buffer, /* [out] Pointer to buffer for atom string */
466 INT count ) /* [in] Size of buffer */
468 return ATOM_GetAtomNameA( atom, buffer, count, NULL );
472 /***********************************************************************
473 * GetAtomNameA (KERNEL32.@)
475 * Get a copy of the string associated with an atom.
478 * Success: The length of the returned string in characters.
481 UINT WINAPI GetAtomNameA(
482 ATOM atom, /* [in] Atom */
483 LPSTR buffer, /* [out] Pointer to string for atom string */
484 INT count) /* [in] Size of buffer */
486 return ATOM_GetAtomNameA( atom, buffer, count, get_local_table(0) );
490 static UINT ATOM_GetAtomNameW( ATOM atom, LPWSTR buffer, INT count, struct atom_table* table )
496 SetLastError( ERROR_MORE_DATA );
499 if (atom < MAXINTATOM)
504 SetLastError( ERROR_INVALID_PARAMETER );
507 sprintf( name, "#%d", atom );
508 len = MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, count );
509 if (!len) buffer[count-1] = 0; /* overflow */
513 WCHAR full_name[MAX_ATOM_LEN];
516 SERVER_START_REQ( get_atom_information )
520 wine_server_set_reply( req, full_name, sizeof(full_name) );
521 if (!wine_server_call_err( req ))
523 len = wine_server_reply_size(reply) / sizeof(WCHAR);
524 if (count > len) count = len + 1;
525 memcpy( buffer, full_name, (count-1) * sizeof(WCHAR) );
532 TRACE( "(%s) %x -> %s\n", table ? "local" : "global", atom, debugstr_w(buffer) );
537 /***********************************************************************
538 * GlobalGetAtomNameW (KERNEL32.@)
540 * Unicode version of GlobalGetAtomNameA.
542 UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
544 return ATOM_GetAtomNameW( atom, buffer, count, NULL);
548 /***********************************************************************
549 * GetAtomNameW (KERNEL32.@)
551 * Unicode version of GetAtomNameA.
553 UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
555 return ATOM_GetAtomNameW( atom, buffer, count, get_local_table(0) );