Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Atom table functions |
| 3 | * |
Alexandre Julliard | e2abbb1 | 1995-03-19 17:39:39 +0000 | [diff] [blame] | 4 | * Copyright 1993, 1994, 1995 Alexandre Julliard |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 5 | */ |
| 6 | |
| 7 | /* |
Alexandre Julliard | 808cb04 | 1995-08-17 17:11:36 +0000 | [diff] [blame] | 8 | * Warning: The code assumes that LocalAlloc() returns a block aligned |
| 9 | * on a 4-bytes boundary (because of the shifting done in |
| 10 | * HANDLETOATOM). If this is not the case, the allocation code will |
| 11 | * have to be changed. |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 12 | */ |
| 13 | |
| 14 | #include <stdlib.h> |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 15 | #include <stdio.h> |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 16 | #include <string.h> |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 17 | #include <ctype.h> |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 18 | |
Jeremy White | d3e22d9 | 2000-02-10 19:03:02 +0000 | [diff] [blame] | 19 | #include "windef.h" |
Alexandre Julliard | 072dfb5 | 2000-09-25 23:30:56 +0000 | [diff] [blame] | 20 | #include "winnls.h" |
Patrik Stridvall | fdcfdb9 | 1999-06-12 14:55:11 +0000 | [diff] [blame] | 21 | #include "wine/winbase16.h" |
Alexandre Julliard | c7e7df8 | 2000-08-14 14:41:19 +0000 | [diff] [blame] | 22 | #include "wine/unicode.h" |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 23 | #include "winerror.h" |
Alexandre Julliard | e2abbb1 | 1995-03-19 17:39:39 +0000 | [diff] [blame] | 24 | #include "instance.h" |
Alexandre Julliard | e2abbb1 | 1995-03-19 17:39:39 +0000 | [diff] [blame] | 25 | #include "stackframe.h" |
Alexandre Julliard | 1565709 | 1999-05-23 10:25:25 +0000 | [diff] [blame] | 26 | #include "debugtools.h" |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 27 | #include "server.h" |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 28 | |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 29 | DEFAULT_DEBUG_CHANNEL(atom); |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 30 | |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 31 | #define DEFAULT_ATOMTABLE_SIZE 37 |
| 32 | #define MIN_STR_ATOM 0xc000 |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 33 | #define MAX_ATOM_LEN 255 |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 34 | |
Alexandre Julliard | 8bbf818 | 1996-09-13 16:50:47 +0000 | [diff] [blame] | 35 | #define ATOMTOHANDLE(atom) ((HANDLE16)(atom) << 2) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 36 | #define HANDLETOATOM(handle) ((ATOM)(0xc000 | ((handle) >> 2))) |
| 37 | |
Alexandre Julliard | 737fa07 | 1998-11-15 17:29:15 +0000 | [diff] [blame] | 38 | typedef struct |
| 39 | { |
| 40 | HANDLE16 next; |
| 41 | WORD refCount; |
| 42 | BYTE length; |
| 43 | BYTE str[1]; |
| 44 | } ATOMENTRY; |
| 45 | |
| 46 | typedef struct |
| 47 | { |
| 48 | WORD size; |
| 49 | HANDLE16 entries[1]; |
| 50 | } ATOMTABLE; |
Alexandre Julliard | ded3038 | 1995-07-06 17:18:27 +0000 | [diff] [blame] | 51 | |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 52 | static WORD ATOM_UserDS = 0; /* USER data segment */ |
Alexandre Julliard | e2abbb1 | 1995-03-19 17:39:39 +0000 | [diff] [blame] | 53 | |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 54 | /*********************************************************************** |
| 55 | * ATOM_Init |
| 56 | * |
| 57 | * Global table initialisation. |
| 58 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 59 | BOOL ATOM_Init( WORD globalTableSel ) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 60 | { |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 61 | ATOM_UserDS = globalTableSel; |
| 62 | return TRUE; |
Alexandre Julliard | e2abbb1 | 1995-03-19 17:39:39 +0000 | [diff] [blame] | 63 | } |
| 64 | |
| 65 | |
| 66 | /*********************************************************************** |
| 67 | * ATOM_GetTable |
| 68 | * |
| 69 | * Return a pointer to the atom table of a given segment, creating |
| 70 | * it if necessary. |
Alexandre Julliard | 54c2711 | 1998-03-29 19:44:57 +0000 | [diff] [blame] | 71 | * |
| 72 | * RETURNS |
| 73 | * Pointer to table: Success |
| 74 | * NULL: Failure |
Alexandre Julliard | e2abbb1 | 1995-03-19 17:39:39 +0000 | [diff] [blame] | 75 | */ |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 76 | static ATOMTABLE *ATOM_GetTable( BOOL create /* [in] Create */ ) |
Alexandre Julliard | 737fa07 | 1998-11-15 17:29:15 +0000 | [diff] [blame] | 77 | { |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 78 | INSTANCEDATA *ptr = MapSL( MAKESEGPTR( CURRENT_DS, 0 ) ); |
Alexandre Julliard | 737fa07 | 1998-11-15 17:29:15 +0000 | [diff] [blame] | 79 | if (ptr->atomtable) |
Alexandre Julliard | e2abbb1 | 1995-03-19 17:39:39 +0000 | [diff] [blame] | 80 | { |
Alexandre Julliard | 737fa07 | 1998-11-15 17:29:15 +0000 | [diff] [blame] | 81 | ATOMTABLE *table = (ATOMTABLE *)((char *)ptr + ptr->atomtable); |
| 82 | if (table->size) return table; |
Alexandre Julliard | e2abbb1 | 1995-03-19 17:39:39 +0000 | [diff] [blame] | 83 | } |
Alexandre Julliard | 737fa07 | 1998-11-15 17:29:15 +0000 | [diff] [blame] | 84 | if (!create) return NULL; |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 85 | if (!InitAtomTable16( 0 )) return NULL; |
Alexandre Julliard | 737fa07 | 1998-11-15 17:29:15 +0000 | [diff] [blame] | 86 | /* Reload ptr in case it moved in linear memory */ |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 87 | ptr = MapSL( MAKESEGPTR( CURRENT_DS, 0 ) ); |
Alexandre Julliard | e2abbb1 | 1995-03-19 17:39:39 +0000 | [diff] [blame] | 88 | return (ATOMTABLE *)((char *)ptr + ptr->atomtable); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 89 | } |
| 90 | |
| 91 | |
| 92 | /*********************************************************************** |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 93 | * ATOM_Hash |
Alexandre Julliard | 54c2711 | 1998-03-29 19:44:57 +0000 | [diff] [blame] | 94 | * RETURNS |
| 95 | * The hash value for the input string |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 96 | */ |
Alexandre Julliard | 54c2711 | 1998-03-29 19:44:57 +0000 | [diff] [blame] | 97 | static WORD ATOM_Hash( |
| 98 | WORD entries, /* [in] Total number of entries */ |
| 99 | LPCSTR str, /* [in] Pointer to string to hash */ |
| 100 | WORD len /* [in] Length of string */ |
| 101 | ) { |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 102 | WORD i, hash = 0; |
| 103 | |
Alexandre Julliard | 1565709 | 1999-05-23 10:25:25 +0000 | [diff] [blame] | 104 | TRACE("%x, %s, %x\n", entries, str, len); |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 105 | |
Alexandre Julliard | cdd0923 | 1994-01-12 11:12:51 +0000 | [diff] [blame] | 106 | for (i = 0; i < len; i++) hash ^= toupper(str[i]) + i; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 107 | return hash % entries; |
| 108 | } |
| 109 | |
| 110 | |
| 111 | /*********************************************************************** |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 112 | * ATOM_IsIntAtomA |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 113 | */ |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 114 | static BOOL ATOM_IsIntAtomA(LPCSTR atomstr,WORD *atomid) |
| 115 | { |
| 116 | UINT atom = 0; |
| 117 | if (!HIWORD(atomstr)) atom = LOWORD(atomstr); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 118 | else |
| 119 | { |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 120 | if (*atomstr++ != '#') return FALSE; |
| 121 | while (*atomstr >= '0' && *atomstr <= '9') |
| 122 | { |
| 123 | atom = atom * 10 + *atomstr - '0'; |
| 124 | atomstr++; |
| 125 | } |
| 126 | if (*atomstr) return FALSE; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 127 | } |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 128 | if (!atom || (atom >= MIN_STR_ATOM)) |
| 129 | { |
| 130 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 131 | atom = 0; |
| 132 | } |
| 133 | *atomid = atom; |
| 134 | return TRUE; |
| 135 | } |
| 136 | |
| 137 | |
| 138 | /*********************************************************************** |
| 139 | * ATOM_IsIntAtomW |
| 140 | */ |
| 141 | static BOOL ATOM_IsIntAtomW(LPCWSTR atomstr,WORD *atomid) |
| 142 | { |
| 143 | UINT atom = 0; |
| 144 | if (!HIWORD(atomstr)) atom = LOWORD(atomstr); |
| 145 | else |
| 146 | { |
| 147 | if (*atomstr++ != '#') return FALSE; |
| 148 | while (*atomstr >= '0' && *atomstr <= '9') |
| 149 | { |
| 150 | atom = atom * 10 + *atomstr - '0'; |
| 151 | atomstr++; |
| 152 | } |
| 153 | if (*atomstr) return FALSE; |
| 154 | } |
| 155 | if (!atom || (atom >= MIN_STR_ATOM)) |
| 156 | { |
| 157 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 158 | atom = 0; |
| 159 | } |
| 160 | *atomid = atom; |
| 161 | return TRUE; |
| 162 | } |
| 163 | |
| 164 | |
| 165 | /*********************************************************************** |
| 166 | * ATOM_MakePtr |
| 167 | * |
| 168 | * Make an ATOMENTRY pointer from a handle (obtained from GetAtomHandle()). |
| 169 | */ |
| 170 | static inline ATOMENTRY *ATOM_MakePtr( HANDLE16 handle /* [in] Handle */ ) |
| 171 | { |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 172 | return MapSL( MAKESEGPTR( CURRENT_DS, handle ) ); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 173 | } |
| 174 | |
| 175 | |
| 176 | /*********************************************************************** |
Alexandre Julliard | f0cbfa0 | 1997-02-15 14:29:56 +0000 | [diff] [blame] | 177 | * InitAtomTable16 (KERNEL.68) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 178 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 179 | WORD WINAPI InitAtomTable16( WORD entries ) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 180 | { |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 181 | int i; |
| 182 | HANDLE16 handle; |
| 183 | ATOMTABLE *table; |
| 184 | |
| 185 | /* We consider the first table to be initialized as the global table. |
| 186 | * This works, as USER (both built-in and native) is the first one to |
| 187 | * register ... |
| 188 | */ |
| 189 | |
| 190 | if (!ATOM_UserDS) |
| 191 | { |
| 192 | ATOM_UserDS = CURRENT_DS; |
| 193 | /* return dummy local handle */ |
| 194 | return LocalAlloc16( LMEM_FIXED, 1 ); |
| 195 | } |
| 196 | |
| 197 | /* Allocate the table */ |
| 198 | |
Alexandre Julliard | 737fa07 | 1998-11-15 17:29:15 +0000 | [diff] [blame] | 199 | if (!entries) entries = DEFAULT_ATOMTABLE_SIZE; /* sanity check */ |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 200 | handle = LocalAlloc16( LMEM_FIXED, sizeof(ATOMTABLE) + (entries-1) * sizeof(HANDLE16) ); |
| 201 | if (!handle) return 0; |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 202 | table = MapSL( MAKESEGPTR( CURRENT_DS, handle ) ); |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 203 | table->size = entries; |
| 204 | for (i = 0; i < entries; i++) table->entries[i] = 0; |
| 205 | |
| 206 | /* Store a pointer to the table in the instance data */ |
| 207 | |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 208 | ((INSTANCEDATA *)MapSL( MAKESEGPTR( CURRENT_DS, 0 )))->atomtable = handle; |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 209 | return handle; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 210 | } |
| 211 | |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 212 | /*********************************************************************** |
| 213 | * GetAtomHandle (KERNEL.73) |
| 214 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 215 | HANDLE16 WINAPI GetAtomHandle16( ATOM atom ) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 216 | { |
| 217 | if (atom < MIN_STR_ATOM) return 0; |
| 218 | return ATOMTOHANDLE( atom ); |
| 219 | } |
| 220 | |
| 221 | |
| 222 | /*********************************************************************** |
Alexandre Julliard | f0cbfa0 | 1997-02-15 14:29:56 +0000 | [diff] [blame] | 223 | * AddAtom16 (KERNEL.70) |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 224 | * |
| 225 | * Windows DWORD aligns the atom entry size. |
| 226 | * The remaining unused string space created by the alignment |
| 227 | * gets padded with '\0's in a certain way to ensure |
| 228 | * that at least one trailing '\0' remains. |
| 229 | * |
| 230 | * RETURNS |
| 231 | * Atom: Success |
| 232 | * 0: Failure |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 233 | */ |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 234 | ATOM WINAPI AddAtom16( LPCSTR str ) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 235 | { |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 236 | char buffer[MAX_ATOM_LEN+1]; |
| 237 | WORD hash; |
| 238 | HANDLE16 entry; |
| 239 | ATOMENTRY * entryPtr; |
| 240 | ATOMTABLE * table; |
| 241 | int len, ae_len; |
| 242 | WORD iatom; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 243 | |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 244 | if (ATOM_IsIntAtomA( str, &iatom )) return iatom; |
| 245 | |
| 246 | TRACE("%s\n",debugstr_a(buffer)); |
| 247 | |
| 248 | /* Make a copy of the string to be sure it doesn't move in linear memory. */ |
| 249 | lstrcpynA( buffer, str, sizeof(buffer) ); |
| 250 | |
| 251 | len = strlen( buffer ); |
| 252 | if (!(table = ATOM_GetTable( TRUE ))) return 0; |
Alexandre Julliard | bcb7f4e | 2000-02-19 20:51:29 +0000 | [diff] [blame] | 253 | if (CURRENT_DS == ATOM_UserDS) return GlobalAddAtomA( str ); |
| 254 | |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 255 | hash = ATOM_Hash( table->size, buffer, len ); |
| 256 | entry = table->entries[hash]; |
| 257 | while (entry) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 258 | { |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 259 | entryPtr = ATOM_MakePtr( entry ); |
| 260 | if ((entryPtr->length == len) && |
Alexandre Julliard | 072dfb5 | 2000-09-25 23:30:56 +0000 | [diff] [blame] | 261 | (!strncasecmp( entryPtr->str, buffer, len ))) |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 262 | { |
| 263 | entryPtr->refCount++; |
| 264 | TRACE("-- existing 0x%x\n", entry); |
| 265 | return HANDLETOATOM( entry ); |
| 266 | } |
| 267 | entry = entryPtr->next; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 268 | } |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 269 | |
| 270 | ae_len = (sizeof(ATOMENTRY)+len+3) & ~3; |
| 271 | entry = LocalAlloc16( LMEM_FIXED, ae_len ); |
| 272 | if (!entry) return 0; |
| 273 | /* Reload the table ptr in case it moved in linear memory */ |
| 274 | table = ATOM_GetTable( FALSE ); |
| 275 | entryPtr = ATOM_MakePtr( entry ); |
| 276 | entryPtr->next = table->entries[hash]; |
| 277 | entryPtr->refCount = 1; |
| 278 | entryPtr->length = len; |
| 279 | /* Some applications _need_ the '\0' padding provided by this strncpy */ |
| 280 | strncpy( entryPtr->str, buffer, ae_len - sizeof(ATOMENTRY) + 1 ); |
| 281 | entryPtr->str[ae_len - sizeof(ATOMENTRY)] = '\0'; |
| 282 | table->entries[hash] = entry; |
| 283 | TRACE("-- new 0x%x\n", entry); |
| 284 | return HANDLETOATOM( entry ); |
| 285 | } |
| 286 | |
| 287 | |
| 288 | /*********************************************************************** |
| 289 | * DeleteAtom16 (KERNEL.71) |
| 290 | */ |
| 291 | ATOM WINAPI DeleteAtom16( ATOM atom ) |
| 292 | { |
| 293 | ATOMENTRY * entryPtr; |
| 294 | ATOMTABLE * table; |
| 295 | HANDLE16 entry, *prevEntry; |
| 296 | WORD hash; |
| 297 | |
| 298 | if (atom < MIN_STR_ATOM) return 0; /* Integer atom */ |
| 299 | if (CURRENT_DS == ATOM_UserDS) return GlobalDeleteAtom( atom ); |
| 300 | |
| 301 | TRACE("0x%x\n",atom); |
| 302 | |
| 303 | if (!(table = ATOM_GetTable( FALSE ))) return 0; |
| 304 | entry = ATOMTOHANDLE( atom ); |
| 305 | entryPtr = ATOM_MakePtr( entry ); |
| 306 | |
| 307 | /* Find previous atom */ |
| 308 | hash = ATOM_Hash( table->size, entryPtr->str, entryPtr->length ); |
| 309 | prevEntry = &table->entries[hash]; |
| 310 | while (*prevEntry && *prevEntry != entry) |
| 311 | { |
| 312 | ATOMENTRY * prevEntryPtr = ATOM_MakePtr( *prevEntry ); |
| 313 | prevEntry = &prevEntryPtr->next; |
| 314 | } |
| 315 | if (!*prevEntry) return atom; |
| 316 | |
| 317 | /* Delete atom */ |
| 318 | if (--entryPtr->refCount == 0) |
| 319 | { |
| 320 | *prevEntry = entryPtr->next; |
| 321 | LocalFree16( entry ); |
| 322 | } |
| 323 | return 0; |
| 324 | } |
| 325 | |
| 326 | |
| 327 | /*********************************************************************** |
| 328 | * FindAtom16 (KERNEL.69) |
| 329 | */ |
| 330 | ATOM WINAPI FindAtom16( LPCSTR str ) |
| 331 | { |
| 332 | ATOMTABLE * table; |
| 333 | WORD hash,iatom; |
| 334 | HANDLE16 entry; |
| 335 | int len; |
| 336 | |
| 337 | if (CURRENT_DS == ATOM_UserDS) return GlobalFindAtomA( str ); |
| 338 | |
| 339 | TRACE("%s\n",debugres_a(str)); |
| 340 | |
| 341 | if (ATOM_IsIntAtomA( str, &iatom )) return iatom; |
| 342 | if ((len = strlen( str )) > 255) len = 255; |
| 343 | if (!(table = ATOM_GetTable( FALSE ))) return 0; |
| 344 | hash = ATOM_Hash( table->size, str, len ); |
| 345 | entry = table->entries[hash]; |
| 346 | while (entry) |
| 347 | { |
| 348 | ATOMENTRY * entryPtr = ATOM_MakePtr( entry ); |
| 349 | if ((entryPtr->length == len) && |
Alexandre Julliard | 072dfb5 | 2000-09-25 23:30:56 +0000 | [diff] [blame] | 350 | (!strncasecmp( entryPtr->str, str, len ))) |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 351 | { |
| 352 | TRACE("-- found %x\n", entry); |
| 353 | return HANDLETOATOM( entry ); |
| 354 | } |
| 355 | entry = entryPtr->next; |
| 356 | } |
| 357 | TRACE("-- not found\n"); |
| 358 | return 0; |
| 359 | } |
| 360 | |
| 361 | |
| 362 | /*********************************************************************** |
| 363 | * GetAtomName16 (KERNEL.72) |
| 364 | */ |
| 365 | UINT16 WINAPI GetAtomName16( ATOM atom, LPSTR buffer, INT16 count ) |
| 366 | { |
| 367 | ATOMTABLE * table; |
| 368 | ATOMENTRY * entryPtr; |
| 369 | HANDLE16 entry; |
| 370 | char * strPtr; |
| 371 | UINT len; |
| 372 | char text[8]; |
| 373 | |
| 374 | if (CURRENT_DS == ATOM_UserDS) return GlobalGetAtomNameA( atom, buffer, count ); |
| 375 | |
| 376 | TRACE("%x\n",atom); |
| 377 | |
| 378 | if (!count) return 0; |
| 379 | if (atom < MIN_STR_ATOM) |
| 380 | { |
| 381 | sprintf( text, "#%d", atom ); |
| 382 | len = strlen(text); |
| 383 | strPtr = text; |
| 384 | } |
| 385 | else |
| 386 | { |
| 387 | if (!(table = ATOM_GetTable( FALSE ))) return 0; |
| 388 | entry = ATOMTOHANDLE( atom ); |
| 389 | entryPtr = ATOM_MakePtr( entry ); |
| 390 | len = entryPtr->length; |
| 391 | strPtr = entryPtr->str; |
| 392 | } |
| 393 | if (len >= count) len = count-1; |
| 394 | memcpy( buffer, strPtr, len ); |
| 395 | buffer[len] = '\0'; |
| 396 | return len; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 397 | } |
| 398 | |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 399 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 400 | * InitAtomTable (KERNEL32.@) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 401 | */ |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 402 | BOOL WINAPI InitAtomTable( DWORD entries ) |
Alexandre Julliard | f0cbfa0 | 1997-02-15 14:29:56 +0000 | [diff] [blame] | 403 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 404 | BOOL ret; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 405 | SERVER_START_REQ( init_atom_table ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 406 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 407 | req->entries = entries; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 408 | ret = !SERVER_CALL_ERR(); |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 409 | } |
| 410 | SERVER_END_REQ; |
| 411 | return ret; |
Alexandre Julliard | f0cbfa0 | 1997-02-15 14:29:56 +0000 | [diff] [blame] | 412 | } |
| 413 | |
| 414 | |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 415 | static ATOM ATOM_AddAtomA( LPCSTR str, BOOL local ) |
Alexandre Julliard | f0cbfa0 | 1997-02-15 14:29:56 +0000 | [diff] [blame] | 416 | { |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 417 | ATOM atom = 0; |
| 418 | if (!ATOM_IsIntAtomA( str, &atom )) |
| 419 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 420 | DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), NULL, 0 ); |
| 421 | if (len > MAX_ATOM_LEN) |
| 422 | { |
| 423 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 424 | return 0; |
| 425 | } |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 426 | SERVER_START_VAR_REQ( add_atom, len * sizeof(WCHAR) ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 427 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 428 | MultiByteToWideChar( CP_ACP, 0, str, strlen(str), server_data_ptr(req), len ); |
| 429 | req->local = local; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 430 | if (!SERVER_CALL_ERR()) atom = req->atom + MIN_STR_ATOM; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 431 | } |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 432 | SERVER_END_VAR_REQ; |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 433 | } |
| 434 | TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom ); |
| 435 | return atom; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 436 | } |
| 437 | |
| 438 | |
| 439 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 440 | * GlobalAddAtomA (USER.268) |
| 441 | * GlobalAddAtomA (KERNEL32.@) |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 442 | * |
Alexandre Julliard | 54c2711 | 1998-03-29 19:44:57 +0000 | [diff] [blame] | 443 | * Adds a character string to the global atom table and returns a unique |
| 444 | * value identifying the string. |
| 445 | * |
| 446 | * RETURNS |
| 447 | * Atom: Success |
| 448 | * 0: Failure |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 449 | */ |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 450 | ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] Pointer to string to add */ ) |
| 451 | { |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 452 | return ATOM_AddAtomA( str, FALSE ); |
| 453 | } |
| 454 | |
| 455 | |
| 456 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 457 | * AddAtomA (KERNEL32.@) |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 458 | * Adds a string to the atom table and returns the atom identifying the |
| 459 | * string. |
| 460 | * |
| 461 | * RETURNS |
| 462 | * Atom: Success |
| 463 | * 0: Failure |
| 464 | */ |
| 465 | ATOM WINAPI AddAtomA( LPCSTR str /* [in] Pointer to string to add */ ) |
| 466 | { |
| 467 | return ATOM_AddAtomA( str, TRUE ); |
| 468 | } |
| 469 | |
| 470 | |
| 471 | static ATOM ATOM_AddAtomW( LPCWSTR str, BOOL local ) |
| 472 | { |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 473 | ATOM atom = 0; |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 474 | if (!ATOM_IsIntAtomW( str, &atom )) |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 475 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 476 | DWORD len = strlenW(str); |
| 477 | if (len > MAX_ATOM_LEN) |
| 478 | { |
| 479 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 480 | return 0; |
| 481 | } |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 482 | SERVER_START_VAR_REQ( add_atom, len * sizeof(WCHAR) ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 483 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 484 | memcpy( server_data_ptr(req), str, len * sizeof(WCHAR) ); |
| 485 | req->local = local; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 486 | if (!SERVER_CALL_ERR()) atom = req->atom + MIN_STR_ATOM; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 487 | } |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 488 | SERVER_END_VAR_REQ; |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 489 | } |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 490 | TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom ); |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 491 | return atom; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 492 | } |
| 493 | |
| 494 | |
| 495 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 496 | * GlobalAddAtomW (KERNEL32.@) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 497 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 498 | ATOM WINAPI GlobalAddAtomW( LPCWSTR str ) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 499 | { |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 500 | return ATOM_AddAtomW( str, FALSE ); |
| 501 | } |
| 502 | |
| 503 | |
| 504 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 505 | * AddAtomW (KERNEL32.@) |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 506 | */ |
| 507 | ATOM WINAPI AddAtomW( LPCWSTR str ) |
| 508 | { |
| 509 | return ATOM_AddAtomW( str, TRUE ); |
| 510 | } |
| 511 | |
| 512 | |
| 513 | static ATOM ATOM_DeleteAtom( ATOM atom, BOOL local) |
| 514 | { |
Andreas Mohr | c9cf70d | 2001-01-26 20:40:50 +0000 | [diff] [blame] | 515 | TRACE( "(%s) %x\n", local ? "local" : "global", atom ); |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 516 | if (atom < MIN_STR_ATOM) atom = 0; |
| 517 | else |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 518 | { |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 519 | SERVER_START_REQ( delete_atom ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 520 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 521 | req->atom = atom - MIN_STR_ATOM; |
| 522 | req->local = local; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 523 | if (!SERVER_CALL_ERR()) atom = 0; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 524 | } |
| 525 | SERVER_END_REQ; |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 526 | } |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 527 | return atom; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 528 | } |
| 529 | |
| 530 | |
| 531 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 532 | * GlobalDeleteAtom (USER.269) |
| 533 | * GlobalDeleteAtom (KERNEL32.@) |
Alexandre Julliard | 54c2711 | 1998-03-29 19:44:57 +0000 | [diff] [blame] | 534 | * Decrements the reference count of a string atom. If the count is |
| 535 | * zero, the string associated with the atom is removed from the table. |
| 536 | * |
| 537 | * RETURNS |
| 538 | * 0: Success |
| 539 | * Atom: Failure |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 540 | */ |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 541 | ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ ) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 542 | { |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 543 | return ATOM_DeleteAtom( atom, FALSE); |
| 544 | } |
| 545 | |
| 546 | |
| 547 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 548 | * DeleteAtom (KERNEL32.@) |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 549 | * Decrements the reference count of a string atom. If count becomes |
| 550 | * zero, the string associated with the atom is removed from the table. |
| 551 | * |
| 552 | * RETURNS |
| 553 | * 0: Success |
| 554 | * Atom: Failure |
| 555 | */ |
| 556 | ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ ) |
| 557 | { |
| 558 | return ATOM_DeleteAtom( atom, TRUE ); |
| 559 | } |
| 560 | |
| 561 | |
| 562 | static ATOM ATOM_FindAtomA( LPCSTR str, BOOL local ) |
| 563 | { |
| 564 | ATOM atom = 0; |
| 565 | if (!ATOM_IsIntAtomA( str, &atom )) |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 566 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 567 | DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), NULL, 0 ); |
| 568 | if (len > MAX_ATOM_LEN) |
| 569 | { |
| 570 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 571 | return 0; |
| 572 | } |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 573 | SERVER_START_VAR_REQ( find_atom, len * sizeof(WCHAR) ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 574 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 575 | MultiByteToWideChar( CP_ACP, 0, str, strlen(str), server_data_ptr(req), len ); |
| 576 | req->local = local; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 577 | if (!SERVER_CALL_ERR()) atom = req->atom + MIN_STR_ATOM; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 578 | } |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 579 | SERVER_END_VAR_REQ; |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 580 | } |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 581 | TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom ); |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 582 | return atom; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 583 | } |
| 584 | |
| 585 | |
| 586 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 587 | * GlobalFindAtomA (USER.270) |
| 588 | * GlobalFindAtomA (KERNEL32.@) |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 589 | * |
Alexandre Julliard | 54c2711 | 1998-03-29 19:44:57 +0000 | [diff] [blame] | 590 | * Searches the atom table for the string and returns the atom |
| 591 | * associated with it. |
| 592 | * |
| 593 | * RETURNS |
| 594 | * Atom: Success |
| 595 | * 0: Failure |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 596 | */ |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 597 | ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ ) |
| 598 | { |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 599 | return ATOM_FindAtomA( str, FALSE ); |
| 600 | } |
| 601 | |
| 602 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 603 | * FindAtomA (KERNEL32.@) |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 604 | * Searches the local atom table for the string and returns the atom |
| 605 | * associated with that string. |
| 606 | * |
| 607 | * RETURNS |
| 608 | * Atom: Success |
| 609 | * 0: Failure |
| 610 | */ |
| 611 | ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ ) |
| 612 | { |
| 613 | return ATOM_FindAtomA( str, TRUE ); |
| 614 | } |
| 615 | |
| 616 | |
| 617 | static ATOM ATOM_FindAtomW( LPCWSTR str, BOOL local ) |
| 618 | { |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 619 | ATOM atom = 0; |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 620 | if (!ATOM_IsIntAtomW( str, &atom )) |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 621 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 622 | DWORD len = strlenW(str); |
| 623 | if (len > MAX_ATOM_LEN) |
| 624 | { |
| 625 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 626 | return 0; |
| 627 | } |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 628 | SERVER_START_VAR_REQ( find_atom, len * sizeof(WCHAR) ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 629 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 630 | memcpy( server_data_ptr(req), str, len * sizeof(WCHAR) ); |
| 631 | req->local = local; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 632 | if (!SERVER_CALL_ERR()) atom = req->atom + MIN_STR_ATOM; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 633 | } |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 634 | SERVER_END_VAR_REQ; |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 635 | } |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 636 | TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom ); |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 637 | return atom; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 638 | } |
| 639 | |
| 640 | |
| 641 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 642 | * GlobalFindAtomW (KERNEL32.@) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 643 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 644 | ATOM WINAPI GlobalFindAtomW( LPCWSTR str ) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 645 | { |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 646 | return ATOM_FindAtomW( str, FALSE ); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 647 | } |
| 648 | |
| 649 | |
| 650 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 651 | * FindAtomW (KERNEL32.@) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 652 | */ |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 653 | ATOM WINAPI FindAtomW( LPCWSTR str ) |
| 654 | { |
| 655 | return ATOM_FindAtomW( str, TRUE ); |
| 656 | } |
| 657 | |
| 658 | |
| 659 | static UINT ATOM_GetAtomNameA( ATOM atom, LPSTR buffer, INT count, BOOL local ) |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 660 | { |
| 661 | INT len; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 662 | |
| 663 | if (count <= 0) |
| 664 | { |
| 665 | SetLastError( ERROR_MORE_DATA ); |
| 666 | return 0; |
| 667 | } |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 668 | if (atom < MIN_STR_ATOM) |
| 669 | { |
| 670 | char name[8]; |
| 671 | if (!atom) |
| 672 | { |
| 673 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 674 | return 0; |
| 675 | } |
| 676 | len = sprintf( name, "#%d", atom ); |
| 677 | lstrcpynA( buffer, name, count ); |
| 678 | } |
| 679 | else |
| 680 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 681 | len = 0; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 682 | SERVER_START_VAR_REQ( get_atom_name, MAX_ATOM_LEN * sizeof(WCHAR) ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 683 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 684 | req->atom = atom - MIN_STR_ATOM; |
| 685 | req->local = local; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 686 | if (!SERVER_CALL_ERR()) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 687 | { |
Alexandre Julliard | 942dcb1 | 2000-09-04 20:21:48 +0000 | [diff] [blame] | 688 | len = WideCharToMultiByte( CP_ACP, 0, server_data_ptr(req), |
| 689 | server_data_size(req) / sizeof(WCHAR), |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 690 | buffer, count - 1, NULL, NULL ); |
| 691 | if (!len) len = count; /* overflow */ |
| 692 | else buffer[len] = 0; |
| 693 | } |
| 694 | } |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 695 | SERVER_END_VAR_REQ; |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 696 | } |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 697 | |
| 698 | if (len && count <= len) |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 699 | { |
| 700 | SetLastError( ERROR_MORE_DATA ); |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 701 | buffer[count-1] = 0; |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 702 | return 0; |
| 703 | } |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 704 | TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_a(buffer) ); |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 705 | return len; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 706 | } |
Alexandre Julliard | 2ace16a | 1996-04-28 15:09:19 +0000 | [diff] [blame] | 707 | |
Alexandre Julliard | 54c2711 | 1998-03-29 19:44:57 +0000 | [diff] [blame] | 708 | |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 709 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 710 | * GlobalGetAtomNameA (USER.271) |
| 711 | * GlobalGetAtomNameA (KERNEL32.@) |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 712 | * |
| 713 | * Retrieves a copy of the string associated with an atom. |
| 714 | * |
| 715 | * RETURNS |
| 716 | * Length of string in characters: Success |
| 717 | * 0: Failure |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 718 | */ |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 719 | UINT WINAPI GlobalGetAtomNameA( |
| 720 | ATOM atom, /* [in] Atom identifier */ |
| 721 | LPSTR buffer, /* [out] Pointer to buffer for atom string */ |
| 722 | INT count ) /* [in] Size of buffer */ |
| 723 | { |
| 724 | return ATOM_GetAtomNameA( atom, buffer, count, FALSE ); |
| 725 | } |
| 726 | |
| 727 | |
| 728 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 729 | * GetAtomNameA (KERNEL32.@) |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 730 | * Retrieves a copy of the string associated with the atom. |
| 731 | * |
| 732 | * RETURNS |
| 733 | * Length of string: Success |
| 734 | * 0: Failure |
| 735 | */ |
| 736 | UINT WINAPI GetAtomNameA( |
| 737 | ATOM atom, /* [in] Atom */ |
| 738 | LPSTR buffer, /* [out] Pointer to string for atom string */ |
| 739 | INT count) /* [in] Size of buffer */ |
| 740 | { |
| 741 | return ATOM_GetAtomNameA( atom, buffer, count, TRUE ); |
| 742 | } |
| 743 | |
| 744 | |
| 745 | static UINT ATOM_GetAtomNameW( ATOM atom, LPWSTR buffer, INT count, BOOL local ) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 746 | { |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 747 | INT len; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 748 | |
| 749 | if (count <= 0) |
| 750 | { |
| 751 | SetLastError( ERROR_MORE_DATA ); |
| 752 | return 0; |
| 753 | } |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 754 | if (atom < MIN_STR_ATOM) |
| 755 | { |
| 756 | char name[8]; |
| 757 | if (!atom) |
| 758 | { |
| 759 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 760 | return 0; |
| 761 | } |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 762 | sprintf( name, "#%d", atom ); |
| 763 | len = MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, count ); |
| 764 | if (!len) buffer[count-1] = 0; /* overflow */ |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 765 | } |
| 766 | else |
| 767 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 768 | len = 0; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 769 | SERVER_START_VAR_REQ( get_atom_name, MAX_ATOM_LEN * sizeof(WCHAR) ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 770 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 771 | req->atom = atom - MIN_STR_ATOM; |
| 772 | req->local = local; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 773 | if (!SERVER_CALL_ERR()) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 774 | { |
| 775 | len = server_data_size(req) / sizeof(WCHAR); |
| 776 | if (count > len) count = len + 1; |
| 777 | memcpy( buffer, server_data_ptr(req), (count-1) * sizeof(WCHAR) ); |
| 778 | buffer[count-1] = 0; |
| 779 | } |
| 780 | } |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 781 | SERVER_END_VAR_REQ; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 782 | if (!len) return 0; |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 783 | } |
| 784 | if (count <= len) |
| 785 | { |
| 786 | SetLastError( ERROR_MORE_DATA ); |
| 787 | return 0; |
| 788 | } |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 789 | TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_w(buffer) ); |
Alexandre Julliard | b849d79 | 2000-02-13 13:56:13 +0000 | [diff] [blame] | 790 | return len; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 791 | } |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 792 | |
| 793 | |
| 794 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 795 | * GlobalGetAtomNameW (KERNEL32.@) |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 796 | */ |
| 797 | UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count ) |
| 798 | { |
| 799 | return ATOM_GetAtomNameW( atom, buffer, count, FALSE); |
| 800 | } |
| 801 | |
| 802 | |
| 803 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame^] | 804 | * GetAtomNameW (KERNEL32.@) |
Turchanov Sergei | 43a27e3 | 2000-05-30 20:32:06 +0000 | [diff] [blame] | 805 | */ |
| 806 | UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count ) |
| 807 | { |
| 808 | return ATOM_GetAtomNameW( atom, buffer, count, TRUE ); |
| 809 | } |