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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
36 #include "wine/exception.h"
38 #include "wine/unicode.h"
39 #include "kernel_private.h"
41 #define MAX_ATOM_LEN 255
43 /******************************************************************
46 * Returns the local atom table for this process (and create it if doesn't
49 static RTL_ATOM_TABLE get_local_table(DWORD entries)
51 static RTL_ATOM_TABLE local_table;
56 RTL_ATOM_TABLE table = NULL;
58 if ((status = RtlCreateAtomTable( entries, &table )))
59 SetLastError( RtlNtStatusToDosError( status ) );
60 else if (InterlockedCompareExchangePointer((void*)&local_table, table, NULL) != NULL)
61 RtlDestroyAtomTable( table );
68 /***********************************************************************
69 * InitAtomTable (KERNEL32.@)
71 * Initialise the global atom table.
74 * entries [I] The number of entries to reserve in the table.
80 BOOL WINAPI InitAtomTable( DWORD entries )
82 return get_local_table( entries ) ? TRUE : FALSE;
85 /******************************************************************
88 * Check if a string (ANSI or UNICODE) is in fact an integral atom
89 * (but doesn't check the "#1234" form)
91 static inline BOOL check_integral_atom( const void* ptr, ATOM* patom)
93 if (HIWORD( ptr )) return FALSE;
94 if ((*patom = LOWORD( ptr )) >= MAXINTATOM)
96 SetLastError( ERROR_INVALID_PARAMETER );
102 /***********************************************************************
103 * GlobalAddAtomA (KERNEL32.@)
105 * Add a character string to the global atom table and return a unique
106 * value identifying it.
109 * Success: The atom allocated to str.
112 ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] String to add */ )
117 if (!check_integral_atom( str, &atom ))
119 WCHAR buffer[MAX_ATOM_LEN];
120 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
121 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
124 NTSTATUS status = NtAddAtom( buffer, len * sizeof(WCHAR), &atom );
127 SetLastError( RtlNtStatusToDosError( status ) );
135 SetLastError( ERROR_INVALID_PARAMETER );
143 /***********************************************************************
144 * AddAtomA (KERNEL32.@)
146 * Add a character string to the global atom table and return a unique
147 * value identifying it.
150 * Success: The atom allocated to str.
153 ATOM WINAPI AddAtomA( LPCSTR str /* [in] String to add */ )
157 if (!check_integral_atom( str, &atom ))
159 WCHAR buffer[MAX_ATOM_LEN + 1];
161 RTL_ATOM_TABLE table;
163 len = MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, MAX_ATOM_LEN + 1 );
164 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
165 else if ((table = get_local_table( 0 )))
167 NTSTATUS status = RtlAddAtomToAtomTable( table, buffer, &atom );
170 SetLastError( RtlNtStatusToDosError( status ) );
178 /***********************************************************************
179 * GlobalAddAtomW (KERNEL32.@)
181 * Unicode version of GlobalAddAtomA.
183 ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
188 if (!check_integral_atom( str, &atom ) &&
189 (status = NtAddAtom( str, strlenW( str ) * sizeof(WCHAR), &atom )))
191 SetLastError( RtlNtStatusToDosError( status ) );
198 /***********************************************************************
199 * AddAtomW (KERNEL32.@)
201 * Unicode version of AddAtomA.
203 ATOM WINAPI AddAtomW( LPCWSTR str )
206 RTL_ATOM_TABLE table;
208 if (!check_integral_atom( str, &atom ) && (table = get_local_table( 0 )))
210 NTSTATUS status = RtlAddAtomToAtomTable( table, str, &atom );
213 SetLastError( RtlNtStatusToDosError( status ) );
221 /***********************************************************************
222 * GlobalDeleteAtom (KERNEL32.@)
224 * Decrement the reference count of a string atom. If the count is
225 * zero, the string associated with the atom is removed from the table.
231 ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
233 if (atom >= MAXINTATOM)
235 NTSTATUS status = NtDeleteAtom( atom );
238 SetLastError( RtlNtStatusToDosError( status ) );
246 /***********************************************************************
247 * DeleteAtom (KERNEL32.@)
249 * Decrement the reference count of a string atom. If the count becomes
250 * zero, the string associated with the atom is removed from the table.
256 ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ )
259 RTL_ATOM_TABLE table;
261 if (atom >= MAXINTATOM)
263 if (!(table = get_local_table( 0 ))) return atom;
264 status = RtlDeleteAtomFromAtomTable( table, atom );
267 SetLastError( RtlNtStatusToDosError( status ) );
275 /***********************************************************************
276 * GlobalFindAtomA (KERNEL32.@)
278 * Get the atom associated with a string.
281 * Success: The associated atom.
284 ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ )
288 if (!check_integral_atom( str, &atom ))
290 WCHAR buffer[MAX_ATOM_LEN];
291 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
293 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
296 NTSTATUS status = NtFindAtom( buffer, len * sizeof(WCHAR), &atom );
299 SetLastError( RtlNtStatusToDosError( status ) );
307 /***********************************************************************
308 * FindAtomA (KERNEL32.@)
310 * Get the atom associated with a string.
313 * Success: The associated atom.
316 ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ )
320 if (!check_integral_atom( str, &atom ))
322 WCHAR buffer[MAX_ATOM_LEN + 1];
324 RTL_ATOM_TABLE table;
326 len = MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, MAX_ATOM_LEN + 1 );
327 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
328 else if ((table = get_local_table( 0 )))
330 NTSTATUS status = RtlLookupAtomInAtomTable( table, buffer, &atom );
333 SetLastError( RtlNtStatusToDosError( status ) );
342 /***********************************************************************
343 * GlobalFindAtomW (KERNEL32.@)
345 * Unicode version of GlobalFindAtomA.
347 ATOM WINAPI GlobalFindAtomW( LPCWSTR str )
351 if (!check_integral_atom( str, &atom ))
353 NTSTATUS status = NtFindAtom( str, strlenW( str ) * sizeof(WCHAR), &atom );
356 SetLastError( RtlNtStatusToDosError( status ) );
364 /***********************************************************************
365 * FindAtomW (KERNEL32.@)
367 * Unicode version of FindAtomA.
369 ATOM WINAPI FindAtomW( LPCWSTR str )
373 RTL_ATOM_TABLE table;
375 if ((table = get_local_table( 0 )))
377 status = RtlLookupAtomInAtomTable( table, str, &atom );
380 SetLastError( RtlNtStatusToDosError( status ) );
388 /***********************************************************************
389 * GlobalGetAtomNameA (KERNEL32.@)
391 * Get a copy of the string associated with an atom.
394 * Success: The length of the returned string in characters.
397 UINT WINAPI GlobalGetAtomNameA(
398 ATOM atom, /* [in] Atom identifier */
399 LPSTR buffer, /* [out] Pointer to buffer for atom string */
400 INT count ) /* [in] Size of buffer */
402 WCHAR tmpW[MAX_ATOM_LEN + 1];
403 UINT wlen, len = 0, c;
405 if (count <= 0) SetLastError( ERROR_MORE_DATA );
406 else if ((wlen = GlobalGetAtomNameW( atom, tmpW, MAX_ATOM_LEN + 1 )))
408 char tmp[MAX_ATOM_LEN + 1];
410 len = WideCharToMultiByte( CP_ACP, 0, tmpW, wlen, tmp, MAX_ATOM_LEN + 1, NULL, NULL );
411 c = min(len, count - 1);
412 memcpy(buffer, tmp, c);
417 SetLastError( ERROR_MORE_DATA );
424 /***********************************************************************
425 * GetAtomNameA (KERNEL32.@)
427 * Get a copy of the string associated with an atom.
430 * Success: The length of the returned string in characters.
433 UINT WINAPI GetAtomNameA(
434 ATOM atom, /* [in] Atom */
435 LPSTR buffer, /* [out] Pointer to string for atom string */
436 INT count) /* [in] Size of buffer */
438 WCHAR tmpW[MAX_ATOM_LEN + 1];
439 UINT wlen, len = 0, c;
441 if (count <= 0) SetLastError( ERROR_MORE_DATA );
442 else if ((wlen = GetAtomNameW( atom, tmpW, MAX_ATOM_LEN + 1 )))
444 char tmp[MAX_ATOM_LEN + 1];
446 len = WideCharToMultiByte( CP_ACP, 0, tmpW, wlen, tmp, MAX_ATOM_LEN + 1, NULL, NULL );
447 c = min(len, count - 1);
448 memcpy(buffer, tmp, c);
453 SetLastError( ERROR_MORE_DATA );
460 /***********************************************************************
461 * GlobalGetAtomNameW (KERNEL32.@)
463 * Unicode version of GlobalGetAtomNameA.
465 UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
467 char ptr[sizeof(ATOM_BASIC_INFORMATION) + MAX_ATOM_LEN * sizeof(WCHAR)];
468 ATOM_BASIC_INFORMATION* abi = (ATOM_BASIC_INFORMATION*)ptr;
469 ULONG ptr_size = sizeof(ATOM_BASIC_INFORMATION) + MAX_ATOM_LEN * sizeof(WCHAR);
475 SetLastError( ERROR_MORE_DATA );
478 status = NtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
479 if (status) SetLastError( RtlNtStatusToDosError( status ) );
482 length = min( abi->NameLength / sizeof(WCHAR), count);
483 memcpy( buffer, abi->Name, length * sizeof(WCHAR) );
484 /* yes, the string will not be null terminated if the passed buffer
485 * is one WCHAR too small (and it's not an error)
487 if (length < abi->NameLength / sizeof(WCHAR))
489 SetLastError( ERROR_MORE_DATA );
492 else if (length < count) buffer[length] = '\0';
498 /***********************************************************************
499 * GetAtomNameW (KERNEL32.@)
501 * Unicode version of GetAtomNameA.
503 UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
506 RTL_ATOM_TABLE table;
508 WCHAR tmp[MAX_ATOM_LEN + 1];
512 SetLastError( ERROR_MORE_DATA );
515 if (!(table = get_local_table( 0 ))) return 0;
516 length = sizeof(tmp);
517 status = RtlQueryAtomInAtomTable( table, atom, NULL, NULL, tmp, &length );
520 SetLastError( RtlNtStatusToDosError( status ) );
523 length = min(length, (count - 1) * sizeof(WCHAR));
524 if (length) memcpy(buffer, tmp, length);
525 else SetLastError( ERROR_INSUFFICIENT_BUFFER );
526 length /= sizeof(WCHAR);
527 buffer[length] = '\0';