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 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(atom);
45 #define MAX_ATOM_LEN 255
47 /******************************************************************
50 * Returns the local atom table for this process (and create it if doesn't
53 static RTL_ATOM_TABLE get_local_table(DWORD entries)
55 static RTL_ATOM_TABLE local_table;
60 RTL_ATOM_TABLE table = NULL;
62 if ((status = RtlCreateAtomTable( entries, &table )))
63 SetLastError( RtlNtStatusToDosError( status ) );
64 else if (InterlockedCompareExchangePointer((void*)&local_table, table, NULL) != NULL)
65 RtlDestroyAtomTable( table );
72 /***********************************************************************
73 * InitAtomTable (KERNEL32.@)
75 * Initialise the global atom table.
78 * entries [I] The number of entries to reserve in the table.
84 BOOL WINAPI InitAtomTable( DWORD entries )
86 return get_local_table( entries ) ? TRUE : FALSE;
89 /******************************************************************
92 * Check if a string (ANSI or UNICODE) is in fact an integral atom
93 * (but doesn't check the "#1234" form)
95 static inline BOOL check_integral_atom( const void* ptr, ATOM* patom)
97 if (HIWORD( ptr )) return FALSE;
98 if ((*patom = LOWORD( ptr )) >= MAXINTATOM)
100 SetLastError( ERROR_INVALID_PARAMETER );
106 /***********************************************************************
107 * GlobalAddAtomA (KERNEL32.@)
109 * Add a character string to the global atom table and return a unique
110 * value identifying it.
113 * Success: The atom allocated to str.
116 ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] String to add */ )
121 if (!check_integral_atom( str, &atom ))
123 WCHAR buffer[MAX_ATOM_LEN];
124 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
125 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
128 NTSTATUS status = NtAddAtom( buffer, len * sizeof(WCHAR), &atom );
131 SetLastError( RtlNtStatusToDosError( status ) );
139 SetLastError( ERROR_INVALID_PARAMETER );
147 /***********************************************************************
148 * AddAtomA (KERNEL32.@)
150 * Add a character string to the global atom table and return a unique
151 * value identifying it.
154 * Success: The atom allocated to str.
157 ATOM WINAPI AddAtomA( LPCSTR str /* [in] String to add */ )
161 if (!check_integral_atom( str, &atom ))
163 WCHAR buffer[MAX_ATOM_LEN + 1];
165 RTL_ATOM_TABLE table;
167 len = MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, MAX_ATOM_LEN + 1 );
168 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
169 else if ((table = get_local_table( 0 )))
171 NTSTATUS status = RtlAddAtomToAtomTable( table, buffer, &atom );
174 SetLastError( RtlNtStatusToDosError( status ) );
182 /***********************************************************************
183 * GlobalAddAtomW (KERNEL32.@)
185 * Unicode version of GlobalAddAtomA.
187 ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
192 if (!check_integral_atom( str, &atom ) &&
193 (status = NtAddAtom( str, strlenW( str ) * sizeof(WCHAR), &atom )))
195 SetLastError( RtlNtStatusToDosError( status ) );
202 /***********************************************************************
203 * AddAtomW (KERNEL32.@)
205 * Unicode version of AddAtomA.
207 ATOM WINAPI AddAtomW( LPCWSTR str )
210 RTL_ATOM_TABLE table;
212 if (!check_integral_atom( str, &atom ) && (table = get_local_table( 0 )))
214 NTSTATUS status = RtlAddAtomToAtomTable( table, str, &atom );
217 SetLastError( RtlNtStatusToDosError( status ) );
225 /***********************************************************************
226 * GlobalDeleteAtom (KERNEL32.@)
228 * Decrement the reference count of a string atom. If the count is
229 * zero, the string associated with the atom is removed from the table.
235 ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
237 if (atom >= MAXINTATOM)
239 NTSTATUS status = NtDeleteAtom( atom );
242 SetLastError( RtlNtStatusToDosError( status ) );
250 /***********************************************************************
251 * DeleteAtom (KERNEL32.@)
253 * Decrement the reference count of a string atom. If the count becomes
254 * zero, the string associated with the atom is removed from the table.
260 ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ )
263 RTL_ATOM_TABLE table;
265 if (atom >= MAXINTATOM)
267 if (!(table = get_local_table( 0 ))) return atom;
268 status = RtlDeleteAtomFromAtomTable( table, atom );
271 SetLastError( RtlNtStatusToDosError( status ) );
279 /***********************************************************************
280 * GlobalFindAtomA (KERNEL32.@)
282 * Get the atom associated with a string.
285 * Success: The associated atom.
288 ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ )
292 if (!check_integral_atom( str, &atom ))
294 WCHAR buffer[MAX_ATOM_LEN];
295 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
297 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
300 NTSTATUS status = NtFindAtom( buffer, len * sizeof(WCHAR), &atom );
303 SetLastError( RtlNtStatusToDosError( status ) );
311 /***********************************************************************
312 * FindAtomA (KERNEL32.@)
314 * Get the atom associated with a string.
317 * Success: The associated atom.
320 ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ )
324 if (!check_integral_atom( str, &atom ))
326 WCHAR buffer[MAX_ATOM_LEN + 1];
328 RTL_ATOM_TABLE table;
330 len = MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, MAX_ATOM_LEN + 1 );
331 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
332 else if ((table = get_local_table( 0 )))
334 NTSTATUS status = RtlLookupAtomInAtomTable( table, buffer, &atom );
337 SetLastError( RtlNtStatusToDosError( status ) );
346 /***********************************************************************
347 * GlobalFindAtomW (KERNEL32.@)
349 * Unicode version of GlobalFindAtomA.
351 ATOM WINAPI GlobalFindAtomW( LPCWSTR str )
355 if (!check_integral_atom( str, &atom ))
357 NTSTATUS status = NtFindAtom( str, strlenW( str ) * sizeof(WCHAR), &atom );
360 SetLastError( RtlNtStatusToDosError( status ) );
368 /***********************************************************************
369 * FindAtomW (KERNEL32.@)
371 * Unicode version of FindAtomA.
373 ATOM WINAPI FindAtomW( LPCWSTR str )
377 RTL_ATOM_TABLE table;
379 if ((table = get_local_table( 0 )))
381 status = RtlLookupAtomInAtomTable( table, str, &atom );
384 SetLastError( RtlNtStatusToDosError( status ) );
392 /***********************************************************************
393 * GlobalGetAtomNameA (KERNEL32.@)
395 * Get a copy of the string associated with an atom.
398 * Success: The length of the returned string in characters.
401 UINT WINAPI GlobalGetAtomNameA(
402 ATOM atom, /* [in] Atom identifier */
403 LPSTR buffer, /* [out] Pointer to buffer for atom string */
404 INT count ) /* [in] Size of buffer */
406 WCHAR tmpW[MAX_ATOM_LEN + 1];
407 UINT wlen, len = 0, c;
409 if (count <= 0) SetLastError( ERROR_MORE_DATA );
410 else if ((wlen = GlobalGetAtomNameW( atom, tmpW, MAX_ATOM_LEN + 1 )))
412 char tmp[MAX_ATOM_LEN + 1];
414 len = WideCharToMultiByte( CP_ACP, 0, tmpW, wlen, tmp, MAX_ATOM_LEN + 1, NULL, NULL );
415 c = min(len, count - 1);
416 memcpy(buffer, tmp, c);
421 SetLastError( ERROR_MORE_DATA );
428 /***********************************************************************
429 * GetAtomNameA (KERNEL32.@)
431 * Get a copy of the string associated with an atom.
434 * Success: The length of the returned string in characters.
437 UINT WINAPI GetAtomNameA(
438 ATOM atom, /* [in] Atom */
439 LPSTR buffer, /* [out] Pointer to string for atom string */
440 INT count) /* [in] Size of buffer */
442 WCHAR tmpW[MAX_ATOM_LEN + 1];
443 UINT wlen, len = 0, c;
445 if (count <= 0) SetLastError( ERROR_MORE_DATA );
446 else if ((wlen = GetAtomNameW( atom, tmpW, MAX_ATOM_LEN + 1 )))
448 char tmp[MAX_ATOM_LEN + 1];
450 len = WideCharToMultiByte( CP_ACP, 0, tmpW, wlen, tmp, MAX_ATOM_LEN + 1, NULL, NULL );
451 c = min(len, count - 1);
452 memcpy(buffer, tmp, c);
457 SetLastError( ERROR_MORE_DATA );
464 /***********************************************************************
465 * GlobalGetAtomNameW (KERNEL32.@)
467 * Unicode version of GlobalGetAtomNameA.
469 UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
471 char ptr[sizeof(ATOM_BASIC_INFORMATION) + MAX_ATOM_LEN * sizeof(WCHAR)];
472 ATOM_BASIC_INFORMATION* abi = (ATOM_BASIC_INFORMATION*)ptr;
473 ULONG ptr_size = sizeof(ATOM_BASIC_INFORMATION) + MAX_ATOM_LEN * sizeof(WCHAR);
479 SetLastError( ERROR_MORE_DATA );
482 status = NtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
483 if (status) SetLastError( RtlNtStatusToDosError( status ) );
486 length = min( abi->NameLength / sizeof(WCHAR), count);
487 memcpy( buffer, abi->Name, length * sizeof(WCHAR) );
488 /* yes, the string will not be null terminated if the passed buffer
489 * is one WCHAR too small (and it's not an error)
491 if (length < abi->NameLength / sizeof(WCHAR))
493 SetLastError( ERROR_MORE_DATA );
496 else if (length < count) buffer[length] = '\0';
502 /***********************************************************************
503 * GetAtomNameW (KERNEL32.@)
505 * Unicode version of GetAtomNameA.
507 UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
510 RTL_ATOM_TABLE table;
512 WCHAR tmp[MAX_ATOM_LEN + 1];
516 SetLastError( ERROR_MORE_DATA );
519 if (!(table = get_local_table( 0 ))) return 0;
520 length = sizeof(tmp);
521 status = RtlQueryAtomInAtomTable( table, atom, NULL, NULL, tmp, &length );
524 SetLastError( RtlNtStatusToDosError( status ) );
527 length = min(length, (count - 1) * sizeof(WCHAR));
528 if (length) memcpy(buffer, tmp, length);
529 else SetLastError( ERROR_INSUFFICIENT_BUFFER );
530 length /= sizeof(WCHAR);
531 buffer[length] = '\0';