ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

atom.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.