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
41 /******************************************************************
44 * Returns the local atom table for this process (and create it if doesn't
47 static RTL_ATOM_TABLE get_local_table(DWORD entries)
49 static RTL_ATOM_TABLE local_table;
54 RTL_ATOM_TABLE table = NULL;
56 if ((status = RtlCreateAtomTable( entries, &table )))
57 SetLastError( RtlNtStatusToDosError( status ) );
58 else if (InterlockedCompareExchangePointer((void*)&local_table, table, NULL) != NULL)
59 RtlDestroyAtomTable( table );
66 /***********************************************************************
67 * InitAtomTable (KERNEL32.@)
69 * Initialise the global atom table.
72 * entries [I] The number of entries to reserve in the table.
78 BOOL WINAPI InitAtomTable( DWORD entries )
80 return get_local_table( entries ) ? TRUE : FALSE;
83 /******************************************************************
86 * Check if a string (ANSI or UNICODE) is in fact an integral atom
87 * (but doesn't check the "#1234" form)
89 static inline BOOL check_integral_atom( const void* ptr, ATOM* patom)
91 if (HIWORD( ptr )) return FALSE;
92 if ((*patom = LOWORD( ptr )) >= MAXINTATOM)
94 SetLastError( ERROR_INVALID_PARAMETER );
100 /***********************************************************************
101 * GlobalAddAtomA (KERNEL32.@)
103 * Add a character string to the global atom table and return a unique
104 * value identifying it.
107 * Success: The atom allocated to str.
110 ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] String to add */ )
115 if (!check_integral_atom( str, &atom ))
117 WCHAR buffer[MAX_ATOM_LEN];
118 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
119 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
122 NTSTATUS status = NtAddAtom( buffer, len * sizeof(WCHAR), &atom );
125 SetLastError( RtlNtStatusToDosError( status ) );
133 SetLastError( ERROR_INVALID_PARAMETER );
141 /***********************************************************************
142 * AddAtomA (KERNEL32.@)
144 * Add a character string to the global atom table and return a unique
145 * value identifying it.
148 * Success: The atom allocated to str.
151 ATOM WINAPI AddAtomA( LPCSTR str /* [in] String to add */ )
155 if (!check_integral_atom( str, &atom ))
157 WCHAR buffer[MAX_ATOM_LEN + 1];
159 RTL_ATOM_TABLE table;
161 len = MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, MAX_ATOM_LEN + 1 );
162 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
163 else if ((table = get_local_table( 0 )))
165 NTSTATUS status = RtlAddAtomToAtomTable( table, buffer, &atom );
168 SetLastError( RtlNtStatusToDosError( status ) );
176 /***********************************************************************
177 * GlobalAddAtomW (KERNEL32.@)
179 * Unicode version of GlobalAddAtomA.
181 ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
186 if (!check_integral_atom( str, &atom ) &&
187 (status = NtAddAtom( str, strlenW( str ) * sizeof(WCHAR), &atom )))
189 SetLastError( RtlNtStatusToDosError( status ) );
196 /***********************************************************************
197 * AddAtomW (KERNEL32.@)
199 * Unicode version of AddAtomA.
201 ATOM WINAPI AddAtomW( LPCWSTR str )
204 RTL_ATOM_TABLE table;
206 if (!check_integral_atom( str, &atom ) && (table = get_local_table( 0 )))
208 NTSTATUS status = RtlAddAtomToAtomTable( table, str, &atom );
211 SetLastError( RtlNtStatusToDosError( status ) );
219 /***********************************************************************
220 * GlobalDeleteAtom (KERNEL32.@)
222 * Decrement the reference count of a string atom. If the count is
223 * zero, the string associated with the atom is removed from the table.
229 ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
231 if (atom >= MAXINTATOM)
233 NTSTATUS status = NtDeleteAtom( atom );
236 SetLastError( RtlNtStatusToDosError( status ) );
244 /***********************************************************************
245 * DeleteAtom (KERNEL32.@)
247 * Decrement the reference count of a string atom. If the count becomes
248 * zero, the string associated with the atom is removed from the table.
254 ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ )
257 RTL_ATOM_TABLE table;
259 if (atom >= MAXINTATOM)
261 if (!(table = get_local_table( 0 ))) return atom;
262 status = RtlDeleteAtomFromAtomTable( table, atom );
265 SetLastError( RtlNtStatusToDosError( status ) );
273 /***********************************************************************
274 * GlobalFindAtomA (KERNEL32.@)
276 * Get the atom associated with a string.
279 * Success: The associated atom.
282 ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ )
286 if (!check_integral_atom( str, &atom ))
288 WCHAR buffer[MAX_ATOM_LEN];
289 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
291 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
294 NTSTATUS status = NtFindAtom( buffer, len * sizeof(WCHAR), &atom );
297 SetLastError( RtlNtStatusToDosError( status ) );
305 /***********************************************************************
306 * FindAtomA (KERNEL32.@)
308 * Get the atom associated with a string.
311 * Success: The associated atom.
314 ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ )
318 if (!check_integral_atom( str, &atom ))
320 WCHAR buffer[MAX_ATOM_LEN + 1];
322 RTL_ATOM_TABLE table;
324 len = MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, MAX_ATOM_LEN + 1 );
325 if (!len) SetLastError( ERROR_INVALID_PARAMETER );
326 else if ((table = get_local_table( 0 )))
328 NTSTATUS status = RtlLookupAtomInAtomTable( table, buffer, &atom );
331 SetLastError( RtlNtStatusToDosError( status ) );
340 /***********************************************************************
341 * GlobalFindAtomW (KERNEL32.@)
343 * Unicode version of GlobalFindAtomA.
345 ATOM WINAPI GlobalFindAtomW( LPCWSTR str )
349 if (!check_integral_atom( str, &atom ))
351 NTSTATUS status = NtFindAtom( str, strlenW( str ) * sizeof(WCHAR), &atom );
354 SetLastError( RtlNtStatusToDosError( status ) );
362 /***********************************************************************
363 * FindAtomW (KERNEL32.@)
365 * Unicode version of FindAtomA.
367 ATOM WINAPI FindAtomW( LPCWSTR str )
371 RTL_ATOM_TABLE table;
373 if ((table = get_local_table( 0 )))
375 status = RtlLookupAtomInAtomTable( table, str, &atom );
378 SetLastError( RtlNtStatusToDosError( status ) );
386 /***********************************************************************
387 * GlobalGetAtomNameA (KERNEL32.@)
389 * Get a copy of the string associated with an atom.
392 * Success: The length of the returned string in characters.
395 UINT WINAPI GlobalGetAtomNameA(
396 ATOM atom, /* [in] Atom identifier */
397 LPSTR buffer, /* [out] Pointer to buffer for atom string */
398 INT count ) /* [in] Size of buffer */
400 WCHAR tmpW[MAX_ATOM_LEN + 1];
401 UINT wlen, len = 0, c;
403 if (count <= 0) SetLastError( ERROR_MORE_DATA );
404 else if ((wlen = GlobalGetAtomNameW( atom, tmpW, MAX_ATOM_LEN + 1 )))
406 char tmp[MAX_ATOM_LEN + 1];
408 len = WideCharToMultiByte( CP_ACP, 0, tmpW, wlen, tmp, MAX_ATOM_LEN + 1, NULL, NULL );
409 c = min(len, count - 1);
410 memcpy(buffer, tmp, c);
415 SetLastError( ERROR_MORE_DATA );
422 /***********************************************************************
423 * GetAtomNameA (KERNEL32.@)
425 * Get a copy of the string associated with an atom.
428 * Success: The length of the returned string in characters.
431 UINT WINAPI GetAtomNameA(
432 ATOM atom, /* [in] Atom */
433 LPSTR buffer, /* [out] Pointer to string for atom string */
434 INT count) /* [in] Size of buffer */
436 WCHAR tmpW[MAX_ATOM_LEN + 1];
437 UINT wlen, len = 0, c;
439 if (count <= 0) SetLastError( ERROR_MORE_DATA );
440 else if ((wlen = GetAtomNameW( atom, tmpW, MAX_ATOM_LEN + 1 )))
442 char tmp[MAX_ATOM_LEN + 1];
444 len = WideCharToMultiByte( CP_ACP, 0, tmpW, wlen, tmp, MAX_ATOM_LEN + 1, NULL, NULL );
445 c = min(len, count - 1);
446 memcpy(buffer, tmp, c);
451 SetLastError( ERROR_MORE_DATA );
458 /***********************************************************************
459 * GlobalGetAtomNameW (KERNEL32.@)
461 * Unicode version of GlobalGetAtomNameA.
463 UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
465 char ptr[sizeof(ATOM_BASIC_INFORMATION) + MAX_ATOM_LEN * sizeof(WCHAR)];
466 ATOM_BASIC_INFORMATION* abi = (ATOM_BASIC_INFORMATION*)ptr;
467 ULONG ptr_size = sizeof(ATOM_BASIC_INFORMATION) + MAX_ATOM_LEN * sizeof(WCHAR);
473 SetLastError( ERROR_MORE_DATA );
476 status = NtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
477 if (status) SetLastError( RtlNtStatusToDosError( status ) );
480 length = min( abi->NameLength / sizeof(WCHAR), count);
481 memcpy( buffer, abi->Name, length * sizeof(WCHAR) );
482 /* yes, the string will not be null terminated if the passed buffer
483 * is one WCHAR too small (and it's not an error)
485 if (length < abi->NameLength / sizeof(WCHAR))
487 SetLastError( ERROR_MORE_DATA );
490 else if (length < count) buffer[length] = '\0';
496 /***********************************************************************
497 * GetAtomNameW (KERNEL32.@)
499 * Unicode version of GetAtomNameA.
501 UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
504 RTL_ATOM_TABLE table;
506 WCHAR tmp[MAX_ATOM_LEN + 1];
510 SetLastError( ERROR_MORE_DATA );
513 if (!(table = get_local_table( 0 ))) return 0;
514 length = sizeof(tmp);
515 status = RtlQueryAtomInAtomTable( table, atom, NULL, NULL, tmp, &length );
518 SetLastError( RtlNtStatusToDosError( status ) );
521 length = min(length, (count - 1) * sizeof(WCHAR));
522 if (length) memcpy(buffer, tmp, length);
523 else SetLastError( ERROR_INSUFFICIENT_BUFFER );
524 length /= sizeof(WCHAR);
525 buffer[length] = '\0';