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