Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenatom.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS system libraries 00004 * FILE: lib/kernel32/misc/atom.c 00005 * PURPOSE: Atom functions 00006 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 #include <k32.h> 00011 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* GLOBALS *******************************************************************/ 00016 00017 PRTL_ATOM_TABLE BaseLocalAtomTable = NULL; 00018 00019 /* FUNCTIONS *****************************************************************/ 00020 00021 PVOID 00022 WINAPI 00023 InternalInitAtomTable(VOID) 00024 { 00025 /* Create or return the local table */ 00026 if (!BaseLocalAtomTable) RtlCreateAtomTable(0, &BaseLocalAtomTable); 00027 return BaseLocalAtomTable; 00028 } 00029 00030 ATOM 00031 WINAPI 00032 InternalAddAtom(BOOLEAN Local, 00033 BOOLEAN Unicode, 00034 LPCSTR AtomName) 00035 { 00036 NTSTATUS Status; 00037 ANSI_STRING AnsiString; 00038 UNICODE_STRING UnicodeString; 00039 PUNICODE_STRING AtomNameString; 00040 ATOM Atom = INVALID_ATOM; 00041 00042 /* Check if it's an integer atom */ 00043 if ((ULONG_PTR)AtomName <= 0xFFFF) 00044 { 00045 /* Convert the name to an atom */ 00046 Atom = (ATOM)PtrToShort((PVOID)AtomName); 00047 if (Atom >= MAXINTATOM) 00048 { 00049 /* Fail, atom number too large */ 00050 BaseSetLastNTError(STATUS_INVALID_PARAMETER); 00051 return INVALID_ATOM; 00052 } 00053 00054 /* Return it */ 00055 return Atom; 00056 } 00057 else 00058 { 00059 /* Check if this is a unicode atom */ 00060 if (Unicode) 00061 { 00062 /* Use a unicode string */ 00063 AtomNameString = &UnicodeString; 00064 RtlInitUnicodeString(AtomNameString, (LPWSTR)AtomName); 00065 Status = STATUS_SUCCESS; 00066 } 00067 else 00068 { 00069 /* Use an ansi string */ 00070 RtlInitAnsiString(&AnsiString, AtomName ); 00071 00072 /* Check if we can abuse the TEB */ 00073 if (AnsiString.MaximumLength > 260) 00074 { 00075 /* We can't, allocate a new string */ 00076 AtomNameString = &UnicodeString; 00077 Status = RtlAnsiStringToUnicodeString(AtomNameString, 00078 &AnsiString, 00079 TRUE); 00080 } 00081 else 00082 { 00083 /* We can! Get the TEB String */ 00084 AtomNameString = &NtCurrentTeb()->StaticUnicodeString; 00085 00086 /* Convert it into the TEB */ 00087 Status = RtlAnsiStringToUnicodeString(AtomNameString, 00088 &AnsiString, 00089 FALSE); 00090 } 00091 } 00092 00093 /* Check for failure */ 00094 if (!NT_SUCCESS(Status)) 00095 { 00096 BaseSetLastNTError(Status); 00097 return Atom; 00098 } 00099 } 00100 00101 /* Check if we're doing local add */ 00102 if (Local) 00103 { 00104 /* Do a local add */ 00105 Status = RtlAddAtomToAtomTable(InternalInitAtomTable(), 00106 AtomNameString->Buffer, 00107 &Atom); 00108 } 00109 else 00110 { 00111 /* Do a global add */ 00112 Status = NtAddAtom(AtomNameString->Buffer, 00113 AtomNameString->Length, 00114 &Atom); 00115 } 00116 00117 /* Check for failure */ 00118 if (!NT_SUCCESS(Status)) BaseSetLastNTError(Status); 00119 00120 /* Check if we were non-static ANSI */ 00121 if (!(Unicode) && (AtomNameString == &UnicodeString)) 00122 { 00123 /* Free the allocated buffer */ 00124 RtlFreeUnicodeString(AtomNameString); 00125 } 00126 00127 /* Return the atom */ 00128 return Atom; 00129 } 00130 00131 ATOM 00132 WINAPI 00133 InternalFindAtom(BOOLEAN Local, 00134 BOOLEAN Unicode, 00135 LPCSTR AtomName) 00136 { 00137 NTSTATUS Status; 00138 ANSI_STRING AnsiString; 00139 UNICODE_STRING UnicodeString; 00140 PUNICODE_STRING AtomNameString; 00141 ATOM Atom = INVALID_ATOM; 00142 00143 /* Check if it's an integer atom */ 00144 if ((ULONG_PTR)AtomName <= 0xFFFF) 00145 { 00146 /* Convert the name to an atom */ 00147 Atom = (ATOM)PtrToShort((PVOID)AtomName); 00148 if (Atom >= MAXINTATOM) 00149 { 00150 /* Fail, atom number too large */ 00151 BaseSetLastNTError(STATUS_INVALID_PARAMETER); 00152 DPRINT1("Invalid atom\n"); 00153 } 00154 00155 /* Return it */ 00156 return Atom; 00157 } 00158 else 00159 { 00160 /* Check if this is a unicode atom */ 00161 if (Unicode) 00162 { 00163 /* Use a unicode string */ 00164 AtomNameString = &UnicodeString; 00165 RtlInitUnicodeString(AtomNameString, (LPWSTR)AtomName); 00166 Status = STATUS_SUCCESS; 00167 } 00168 else 00169 { 00170 /* Use an ansi string */ 00171 RtlInitAnsiString(&AnsiString, AtomName); 00172 00173 /* Check if we can abuse the TEB */ 00174 if (AnsiString.MaximumLength > 260) 00175 { 00176 /* We can't, allocate a new string */ 00177 AtomNameString = &UnicodeString; 00178 Status = RtlAnsiStringToUnicodeString(AtomNameString, 00179 &AnsiString, 00180 TRUE); 00181 } 00182 else 00183 { 00184 /* We can! Get the TEB String */ 00185 AtomNameString = &NtCurrentTeb()->StaticUnicodeString; 00186 00187 /* Convert it into the TEB */ 00188 Status = RtlAnsiStringToUnicodeString(AtomNameString, 00189 &AnsiString, 00190 FALSE); 00191 } 00192 } 00193 00194 /* Check for failure */ 00195 if (!NT_SUCCESS(Status)) 00196 { 00197 DPRINT1("Failed\n"); 00198 BaseSetLastNTError(Status); 00199 return Atom; 00200 } 00201 } 00202 00203 /* Check if we're doing local lookup */ 00204 if (Local) 00205 { 00206 /* Do a local lookup */ 00207 Status = RtlLookupAtomInAtomTable(InternalInitAtomTable(), 00208 AtomNameString->Buffer, 00209 &Atom); 00210 } 00211 else 00212 { 00213 /* Do a global search */ 00214 if (!AtomNameString->Length) 00215 { 00216 /* This is illegal in win32 */ 00217 DPRINT1("No name given\n"); 00218 Status = STATUS_OBJECT_NAME_NOT_FOUND; 00219 } 00220 else 00221 { 00222 /* Call the global function */ 00223 Status = NtFindAtom(AtomNameString->Buffer, 00224 AtomNameString->Length, 00225 &Atom); 00226 } 00227 } 00228 00229 /* Check for failure */ 00230 if (!NT_SUCCESS(Status)) BaseSetLastNTError(Status); 00231 00232 /* Check if we were non-static ANSI */ 00233 if (!(Unicode) && (AtomNameString == &UnicodeString)) 00234 { 00235 /* Free the allocated buffer */ 00236 RtlFreeUnicodeString(AtomNameString); 00237 } 00238 00239 /* Return the atom */ 00240 return Atom; 00241 } 00242 00243 ATOM 00244 WINAPI 00245 InternalDeleteAtom(BOOLEAN Local, 00246 ATOM Atom) 00247 { 00248 NTSTATUS Status; 00249 00250 /* Validate it */ 00251 if (Atom >= MAXINTATOM) 00252 { 00253 /* Check if it's a local delete */ 00254 if (Local) 00255 { 00256 /* Delete it locally */ 00257 Status = RtlDeleteAtomFromAtomTable(InternalInitAtomTable(), Atom); 00258 } 00259 else 00260 { 00261 /* Delete it globall */ 00262 Status = NtDeleteAtom(Atom); 00263 } 00264 00265 /* Check for success */ 00266 if (!NT_SUCCESS(Status)) 00267 { 00268 /* Fail */ 00269 BaseSetLastNTError(Status); 00270 return INVALID_ATOM; 00271 } 00272 } 00273 00274 /* Return failure */ 00275 return 0; 00276 } 00277 00278 UINT 00279 WINAPI 00280 InternalGetAtomName(BOOLEAN Local, 00281 BOOLEAN Unicode, 00282 ATOM Atom, 00283 LPSTR AtomName, 00284 DWORD Size) 00285 { 00286 NTSTATUS Status; 00287 DWORD RetVal = 0; 00288 ANSI_STRING AnsiString; 00289 UNICODE_STRING UnicodeString; 00290 PVOID TempBuffer = NULL; 00291 PWSTR AtomNameString; 00292 ULONG AtomInfoLength; 00293 ULONG AtomNameLength; 00294 PATOM_BASIC_INFORMATION AtomInfo; 00295 00296 /* Normalize the size as not to overflow */ 00297 if (!Unicode && Size > 0x7000) Size = 0x7000; 00298 00299 /* Make sure it's valid too */ 00300 if (!Size) 00301 { 00302 BaseSetLastNTError(STATUS_BUFFER_OVERFLOW); 00303 return 0; 00304 } 00305 if (!Atom) 00306 { 00307 BaseSetLastNTError(STATUS_INVALID_PARAMETER); 00308 return 0; 00309 } 00310 00311 /* Check if this is a global query */ 00312 if (Local) 00313 { 00314 /* Set the query length */ 00315 AtomNameLength = Size * sizeof(WCHAR); 00316 00317 /* If it's unicode, just keep the name */ 00318 if (Unicode) 00319 { 00320 AtomNameString = (PWSTR)AtomName; 00321 } 00322 else 00323 { 00324 /* Allocate memory for the ansi buffer */ 00325 TempBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 00326 0, 00327 AtomNameLength); 00328 AtomNameString = TempBuffer; 00329 } 00330 00331 /* Query the name */ 00332 Status = RtlQueryAtomInAtomTable(InternalInitAtomTable(), 00333 Atom, 00334 NULL, 00335 NULL, 00336 AtomNameString, 00337 &AtomNameLength); 00338 } 00339 else 00340 { 00341 /* We're going to do a global query, so allocate a buffer */ 00342 AtomInfoLength = sizeof(ATOM_BASIC_INFORMATION) + 00343 (Size * sizeof(WCHAR)); 00344 AtomInfo = TempBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 00345 0, 00346 AtomInfoLength); 00347 00348 if (!AtomInfo) 00349 { 00350 BaseSetLastNTError(STATUS_NO_MEMORY); 00351 return 0; 00352 } 00353 00354 /* Query the name */ 00355 Status = NtQueryInformationAtom(Atom, 00356 AtomBasicInformation, 00357 AtomInfo, 00358 AtomInfoLength, 00359 &AtomInfoLength); 00360 if (NT_SUCCESS(Status)) 00361 { 00362 /* Success. Update the length and get the name */ 00363 AtomNameLength = (ULONG)AtomInfo->NameLength; 00364 AtomNameString = AtomInfo->Name; 00365 } 00366 } 00367 00368 /* Check for global success */ 00369 if (NT_SUCCESS(Status)) 00370 { 00371 /* Check if it was unicode */ 00372 if (Unicode) 00373 { 00374 /* We return the length in chars */ 00375 RetVal = AtomNameLength / sizeof(WCHAR); 00376 00377 /* Copy the memory if this was a global query */ 00378 if (AtomNameString != (PWSTR)AtomName) 00379 { 00380 RtlMoveMemory(AtomName, AtomNameString, AtomNameLength); 00381 } 00382 00383 /* And null-terminate it if the buffer was too large */ 00384 if (RetVal < Size) 00385 { 00386 ((PWCHAR)AtomName)[RetVal] = UNICODE_NULL; 00387 } 00388 } 00389 else 00390 { 00391 /* First create a unicode string with our data */ 00392 UnicodeString.Buffer = AtomNameString; 00393 UnicodeString.Length = (USHORT)AtomNameLength; 00394 UnicodeString.MaximumLength = (USHORT)(UnicodeString.Length + 00395 sizeof(WCHAR)); 00396 00397 /* Now prepare an ansi string for conversion */ 00398 AnsiString.Buffer = AtomName; 00399 AnsiString.Length = 0; 00400 AnsiString.MaximumLength = (USHORT)Size; 00401 00402 /* Convert it */ 00403 Status = RtlUnicodeStringToAnsiString(&AnsiString, 00404 &UnicodeString, 00405 FALSE); 00406 00407 /* Return the length */ 00408 if (NT_SUCCESS(Status)) RetVal = AnsiString.Length; 00409 } 00410 } 00411 00412 /* Free the temporary buffer if we have one */ 00413 if (TempBuffer) RtlFreeHeap(RtlGetProcessHeap(), 0, TempBuffer); 00414 00415 /* Check for failure */ 00416 if (!NT_SUCCESS(Status)) 00417 { 00418 /* Fail */ 00419 DPRINT("Failed: %lx\n", Status); 00420 BaseSetLastNTError(Status); 00421 } 00422 00423 /* Return length */ 00424 return RetVal; 00425 } 00426 00427 /* FUNCTIONS *****************************************************************/ 00428 00429 /* 00430 * @implemented 00431 */ 00432 ATOM 00433 WINAPI 00434 GlobalAddAtomA(LPCSTR lpString) 00435 { 00436 return InternalAddAtom(FALSE, FALSE, lpString); 00437 } 00438 00439 /* 00440 * @implemented 00441 */ 00442 ATOM 00443 WINAPI 00444 GlobalAddAtomW(LPCWSTR lpString) 00445 { 00446 return InternalAddAtom(FALSE, TRUE, (LPSTR)lpString); 00447 } 00448 00449 /* 00450 * @implemented 00451 */ 00452 ATOM 00453 WINAPI 00454 GlobalDeleteAtom(ATOM nAtom) 00455 { 00456 return InternalDeleteAtom(FALSE, nAtom); 00457 } 00458 00459 /* 00460 * @implemented 00461 */ 00462 ATOM 00463 WINAPI 00464 GlobalFindAtomA(LPCSTR lpString) 00465 { 00466 return InternalFindAtom(FALSE, FALSE, lpString); 00467 } 00468 00469 /* 00470 * @implemented 00471 */ 00472 ATOM 00473 WINAPI 00474 GlobalFindAtomW(LPCWSTR lpString) 00475 { 00476 return InternalFindAtom(FALSE, TRUE, (LPSTR)lpString); 00477 } 00478 00479 /* 00480 * @implemented 00481 */ 00482 UINT 00483 WINAPI 00484 GlobalGetAtomNameA(ATOM nAtom, 00485 LPSTR lpBuffer, 00486 int nSize) 00487 { 00488 return InternalGetAtomName(FALSE, FALSE, nAtom, lpBuffer, (DWORD)nSize); 00489 } 00490 00491 /* 00492 * @implemented 00493 */ 00494 UINT 00495 WINAPI 00496 GlobalGetAtomNameW(ATOM nAtom, 00497 LPWSTR lpBuffer, 00498 int nSize) 00499 { 00500 return InternalGetAtomName(FALSE, 00501 TRUE, 00502 nAtom, 00503 (LPSTR)lpBuffer, 00504 (DWORD)nSize); 00505 } 00506 00507 /* 00508 * @implemented 00509 */ 00510 BOOL 00511 WINAPI 00512 InitAtomTable(DWORD nSize) 00513 { 00514 /* Normalize size */ 00515 if (nSize < 4 || nSize > 511) nSize = 37; 00516 00517 DPRINT("Here\n"); 00518 return NT_SUCCESS(RtlCreateAtomTable(nSize, &BaseLocalAtomTable)); 00519 } 00520 00521 /* 00522 * @implemented 00523 */ 00524 ATOM 00525 WINAPI 00526 AddAtomA(LPCSTR lpString) 00527 { 00528 return InternalAddAtom(TRUE, FALSE, lpString); 00529 } 00530 00531 /* 00532 * @implemented 00533 */ 00534 ATOM 00535 WINAPI 00536 AddAtomW(LPCWSTR lpString) 00537 { 00538 return InternalAddAtom(TRUE, TRUE, (LPSTR)lpString); 00539 } 00540 00541 /* 00542 * @implemented 00543 */ 00544 ATOM 00545 WINAPI 00546 DeleteAtom(ATOM nAtom) 00547 { 00548 return InternalDeleteAtom(TRUE, nAtom); 00549 } 00550 00551 /* 00552 * @implemented 00553 */ 00554 ATOM 00555 WINAPI 00556 FindAtomA(LPCSTR lpString) 00557 { 00558 return InternalFindAtom(TRUE, FALSE, lpString); 00559 } 00560 00561 /* 00562 * @implemented 00563 */ 00564 ATOM 00565 WINAPI 00566 FindAtomW(LPCWSTR lpString) 00567 { 00568 return InternalFindAtom(TRUE, TRUE, (LPSTR)lpString); 00569 00570 } 00571 00572 /* 00573 * @implemented 00574 */ 00575 UINT 00576 WINAPI 00577 GetAtomNameA(ATOM nAtom, 00578 LPSTR lpBuffer, 00579 int nSize) 00580 { 00581 return InternalGetAtomName(TRUE, FALSE, nAtom, lpBuffer, (DWORD)nSize); 00582 } 00583 00584 /* 00585 * @implemented 00586 */ 00587 UINT 00588 WINAPI 00589 GetAtomNameW(ATOM nAtom, 00590 LPWSTR lpBuffer, 00591 int nSize) 00592 { 00593 return InternalGetAtomName(TRUE, 00594 TRUE, 00595 nAtom, 00596 (LPSTR)lpBuffer, 00597 (DWORD)nSize); 00598 } 00599 /* EOF */ Generated on Sun May 27 2012 04:24:24 for ReactOS by
1.7.6.1
|