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"
35 #include "wine/exception.h"
36 #include "wine/unicode.h"
37 #include "kernel_private.h"
39 #define MAX_ATOM_LEN 255
40 #define IS_INTATOM(x) (((ULONG_PTR)(x) >> 16) == 0)
42 /******************************************************************
45 * Returns the local atom table for this process (and create it if doesn't
48 static RTL_ATOM_TABLE get_local_table(DWORD entries)
50 static RTL_ATOM_TABLE local_table;
55 RTL_ATOM_TABLE table = NULL;
57 if ((status = RtlCreateAtomTable( entries, &table )))
58 SetLastError( RtlNtStatusToDosError( status ) );
59 else if (InterlockedCompareExchangePointer((void*)&local_table, table, NULL) != NULL)
60 RtlDestroyAtomTable( table );
67 /***********************************************************************
68 * InitAtomTable (KERNEL32.@)
70 * Initialise the global atom table.
73 * entries [I] The number of entries to reserve in the table.
79 BOOL WINAPI InitAtomTable( DWORD entries )
81 return get_local_table( entries ) ? TRUE : FALSE;
84 /******************************************************************
87 * Check if a string (ANSI or UNICODE) is in fact an integral atom
88 * (but doesn't check the "#1234" form)
90 static inline BOOL check_integral_atom( const void* ptr, ATOM* patom)
92 if (!IS_INTATOM( ptr )) return FALSE;
93 if ((*patom = LOWORD( ptr )) >= MAXINTATOM)
95 SetLastError( ERROR_INVALID_PARAMETER );
101 /***********************************************************************
102 * GlobalAddAtomA (KERNEL32.@)
104 * Add a character string to the global atom table and return a unique
105 * value identifying it.
108 * Success: The atom allocated to str.
111 ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] String to add */ )
116 if (!check_integral_atom( str, &atom ))
118 WCHAR buffer[MAX_ATOM_LEN];
119 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
120 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
123 NTSTATUS status = NtAddAtom( buffer, len * sizeof(WCHAR), &atom );
126 SetLastError( RtlNtStatusToDosError( status ) );
134 SetLastError( ERROR_INVALID_PARAMETER );
142 /***********************************************************************
143 * AddAtomA (KERNEL32.@)
145 * Add a character string to the global atom table and return a unique
146 * value identifying it.
149 * Success: The atom allocated to str.
152 ATOM WINAPI AddAtomA( LPCSTR str /* [in] String to add */ )
156 if (!check_integral_atom( str, &atom ))
158 WCHAR buffer[MAX_ATOM_LEN + 1];
160 RTL_ATOM_TABLE table;
162 len = MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, MAX_ATOM_LEN + 1 );
163 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
164 else if ((table = get_local_table( 0 )))
166 NTSTATUS status = RtlAddAtomToAtomTable( table, buffer, &atom );
169 SetLastError( RtlNtStatusToDosError( status ) );
177 /***********************************************************************
178 * GlobalAddAtomW (KERNEL32.@)
180 * Unicode version of GlobalAddAtomA.
182 ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
187 if (!check_integral_atom( str, &atom ) &&
188 (status = NtAddAtom( str, strlenW( str ) * sizeof(WCHAR), &atom )))
190 SetLastError( RtlNtStatusToDosError( status ) );
197 /***********************************************************************
198 * AddAtomW (KERNEL32.@)
200 * Unicode version of AddAtomA.
202 ATOM WINAPI AddAtomW( LPCWSTR str )
205 RTL_ATOM_TABLE table;
207 if (!check_integral_atom( str, &atom ) && (table = get_local_table( 0 )))
209 NTSTATUS status = RtlAddAtomToAtomTable( table, str, &atom );
212 SetLastError( RtlNtStatusToDosError( status ) );
220 /***********************************************************************
221 * GlobalDeleteAtom (KERNEL32.@)
223 * Decrement the reference count of a string atom. If the count is
224 * zero, the string associated with the atom is removed from the table.
230 ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
232 if (atom >= MAXINTATOM)
234 NTSTATUS status = NtDeleteAtom( atom );
237 SetLastError( RtlNtStatusToDosError( status ) );
245 /***********************************************************************
246 * DeleteAtom (KERNEL32.@)
248 * Decrement the reference count of a string atom. If the count becomes
249 * zero, the string associated with the atom is removed from the table.
255 ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ )
258 RTL_ATOM_TABLE table;
260 if (atom >= MAXINTATOM)
262 if (!(table = get_local_table( 0 ))) return atom;
263 status = RtlDeleteAtomFromAtomTable( table, atom );
266 SetLastError( RtlNtStatusToDosError( status ) );
274 /***********************************************************************
275 * GlobalFindAtomA (KERNEL32.@)
277 * Get the atom associated with a string.
280 * Success: The associated atom.
283 ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ )
287 if (!check_integral_atom( str, &atom ))
289 WCHAR buffer[MAX_ATOM_LEN];
290 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
292 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
295 NTSTATUS status = NtFindAtom( buffer, len * sizeof(WCHAR), &atom );
298 SetLastError( RtlNtStatusToDosError( status ) );
306 /***********************************************************************
307 * FindAtomA (KERNEL32.@)
309 * Get the atom associated with a string.
312 * Success: The associated atom.
315 ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ )
319 if (!check_integral_atom( str, &atom ))
321 WCHAR buffer[MAX_ATOM_LEN + 1];
323 RTL_ATOM_TABLE table;
325 len = MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, MAX_ATOM_LEN + 1 );
326 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
327 else if ((table = get_local_table( 0 )))
329 NTSTATUS status = RtlLookupAtomInAtomTable( table, buffer, &atom );
332 SetLastError( RtlNtStatusToDosError( status ) );
341 /***********************************************************************
342 * GlobalFindAtomW (KERNEL32.@)
344 * Unicode version of GlobalFindAtomA.
346 ATOM WINAPI GlobalFindAtomW( LPCWSTR str )
350 if (!check_integral_atom( str, &atom ))
352 NTSTATUS status = NtFindAtom( str, strlenW( str ) * sizeof(WCHAR), &atom );
355 SetLastError( RtlNtStatusToDosError( status ) );
363 /***********************************************************************
364 * FindAtomW (KERNEL32.@)
366 * Unicode version of FindAtomA.
368 ATOM WINAPI FindAtomW( LPCWSTR str )
372 RTL_ATOM_TABLE table;
374 if ((table = get_local_table( 0 )))
376 status = RtlLookupAtomInAtomTable( table, str, &atom );
379 SetLastError( RtlNtStatusToDosError( status ) );
387 /***********************************************************************
388 * GlobalGetAtomNameA (KERNEL32.@)
390 * Get a copy of the string associated with an atom.
393 * Success: The length of the returned string in characters.
396 UINT WINAPI GlobalGetAtomNameA(
397 ATOM atom, /* [in] Atom identifier */
398 LPSTR buffer, /* [out] Pointer to buffer for atom string */
399 INT count ) /* [in] Size of buffer */
401 WCHAR tmpW[MAX_ATOM_LEN + 1];
402 UINT wlen, len = 0, c;
404 if (count <= 0) SetLastError( ERROR_MORE_DATA );
405 else if ((wlen = GlobalGetAtomNameW( atom, tmpW, MAX_ATOM_LEN + 1 )))
407 char tmp[MAX_ATOM_LEN + 1];
409 len = WideCharToMultiByte( CP_ACP, 0, tmpW, wlen, tmp, MAX_ATOM_LEN + 1, NULL, NULL );
410 c = min(len, count - 1);
411 memcpy(buffer, tmp, c);
416 SetLastError( ERROR_MORE_DATA );
423 /***********************************************************************
424 * GetAtomNameA (KERNEL32.@)
426 * Get a copy of the string associated with an atom.
429 * Success: The length of the returned string in characters.
432 UINT WINAPI GetAtomNameA(
433 ATOM atom, /* [in] Atom */
434 LPSTR buffer, /* [out] Pointer to string for atom string */
435 INT count) /* [in] Size of buffer */
437 WCHAR tmpW[MAX_ATOM_LEN + 1];
438 UINT wlen, len = 0, c;
440 if (count <= 0) SetLastError( ERROR_MORE_DATA );
441 else if ((wlen = GetAtomNameW( atom, tmpW, MAX_ATOM_LEN + 1 )))
443 char tmp[MAX_ATOM_LEN + 1];
445 len = WideCharToMultiByte( CP_ACP, 0, tmpW, wlen, tmp, MAX_ATOM_LEN + 1, NULL, NULL );
446 c = min(len, count - 1);
447 memcpy(buffer, tmp, c);
452 SetLastError( ERROR_MORE_DATA );
459 /***********************************************************************
460 * GlobalGetAtomNameW (KERNEL32.@)
462 * Unicode version of GlobalGetAtomNameA.
464 UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
466 char ptr[sizeof(ATOM_BASIC_INFORMATION) + MAX_ATOM_LEN * sizeof(WCHAR)];
467 ATOM_BASIC_INFORMATION* abi = (ATOM_BASIC_INFORMATION*)ptr;
468 ULONG ptr_size = sizeof(ATOM_BASIC_INFORMATION) + MAX_ATOM_LEN * sizeof(WCHAR);
474 SetLastError( ERROR_MORE_DATA );
477 status = NtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
478 if (status) SetLastError( RtlNtStatusToDosError( status ) );
481 length = min( abi->NameLength / sizeof(WCHAR), count);
482 memcpy( buffer, abi->Name, length * sizeof(WCHAR) );
483 /* yes, the string will not be null terminated if the passed buffer
484 * is one WCHAR too small (and it's not an error)
486 if (length < abi->NameLength / sizeof(WCHAR))
488 SetLastError( ERROR_MORE_DATA );
491 else if (length < count) buffer[length] = '\0';
497 /***********************************************************************
498 * GetAtomNameW (KERNEL32.@)
500 * Unicode version of GetAtomNameA.
502 UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
505 RTL_ATOM_TABLE table;
507 WCHAR tmp[MAX_ATOM_LEN + 1];
511 SetLastError( ERROR_MORE_DATA );
514 if (!(table = get_local_table( 0 ))) return 0;
515 length = sizeof(tmp);
516 status = RtlQueryAtomInAtomTable( table, atom, NULL, NULL, tmp, &length );
519 SetLastError( RtlNtStatusToDosError( status ) );
522 length = min(length, (count - 1) * sizeof(WCHAR));
523 if (length) memcpy(buffer, tmp, length);
524 else SetLastError( ERROR_INSUFFICIENT_BUFFER );
525 length /= sizeof(WCHAR);
526 buffer[length] = '\0';