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  * PROJECT:         ReactOS Kernel
00003  * COPYRIGHT:       GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/ex/atom.c
00005  * PURPOSE:         Executive Atom Functions
00006  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
00007  *                  Gunnar Dalsnes
00008  */
00009 
00010 /* INCLUDES *****************************************************************/
00011 
00012 #include <ntoskrnl.h>
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 #define TAG_ATOM 'motA'
00017 
00018 /* GLOBALS ****************************************************************/
00019 
00020 /*
00021  * FIXME: this is WRONG! The global atom table should live in the WinSta struct
00022  * and accessed through a win32k callout (received in PsEstablishWin32Callouts)
00023  * NOTE: There is a session/win32k global atom table also, but its private to
00024  * win32k. Its used for RegisterWindowMessage() and for window classes.
00025  * -Gunnar
00026  */
00027 PRTL_ATOM_TABLE GlobalAtomTable;
00028 
00029 /* PRIVATE FUNCTIONS *********************************************************/
00030 
00031 /*++
00032  * @name ExpGetGlobalAtomTable
00033  *
00034  * Gets pointer to a global atom table, creates it if not already created
00035  *
00036  * @return Pointer to the RTL_ATOM_TABLE, or NULL if it's impossible
00037  *         to create atom table
00038  *
00039  * @remarks Internal function
00040  *
00041  *--*/
00042 PRTL_ATOM_TABLE
00043 NTAPI
00044 ExpGetGlobalAtomTable(VOID)
00045 {
00046     NTSTATUS Status;
00047 
00048     /* Return it if we have one */
00049     if (GlobalAtomTable) return GlobalAtomTable;
00050 
00051     /* Create it */
00052     Status = RtlCreateAtomTable(37, &GlobalAtomTable);
00053 
00054     /* If we couldn't create it, return NULL */
00055     if (!NT_SUCCESS(Status)) return NULL;
00056 
00057     /* Return the newly created one */
00058     return GlobalAtomTable;
00059 }
00060 
00061 /* FUNCTIONS ****************************************************************/
00062 
00063 /*++
00064  * @name NtAddAtom
00065  * @implemented
00066  *
00067  * Function NtAddAtom creates new Atom in Global Atom Table. If Atom
00068  * with the same name already exist, internal Atom counter is incremented.
00069  * See: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Atoms/NtAddAtom.html
00070  *
00071  * @param AtomName
00072  *        Atom name in Unicode
00073  *
00074  * @param AtomNameLength
00075  *        Length of the atom name
00076  *
00077  * @param Atom
00078  *        Pointer to RTL_ATOM
00079  *
00080  * @return STATUS_SUCCESS in case of success, proper error code
00081  *         othwerwise.
00082  *
00083  * @remarks None
00084  *
00085  *--*/
00086 NTSTATUS
00087 NTAPI
00088 NtAddAtom(IN PWSTR AtomName,
00089           IN ULONG AtomNameLength,
00090           OUT PRTL_ATOM Atom)
00091 {
00092     PRTL_ATOM_TABLE AtomTable = ExpGetGlobalAtomTable();
00093     NTSTATUS Status;
00094     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
00095     LPWSTR CapturedName;
00096     ULONG CapturedSize;
00097     RTL_ATOM SafeAtom;
00098     PAGED_CODE();
00099 
00100     /* Check for the table */
00101     if (AtomTable == NULL) return STATUS_ACCESS_DENIED;
00102 
00103     /* Check for valid name */
00104     if (AtomNameLength > (RTL_MAXIMUM_ATOM_LENGTH * sizeof(WCHAR)))
00105     {
00106         /* Fail */
00107         DPRINT1("Atom name too long\n");
00108         return STATUS_INVALID_PARAMETER;
00109     }
00110     
00111     /* Re-use the given name if kernel mode or no atom name */
00112     CapturedName = AtomName;
00113 
00114     /* Check if we're called from user-mode*/
00115     if (PreviousMode != KernelMode)
00116     {
00117         /* Enter SEH */
00118         _SEH2_TRY
00119         {
00120             /* Check if we have a name */
00121             if (AtomName)
00122             {
00123                 /* Probe the atom */
00124                 ProbeForRead(AtomName, AtomNameLength, sizeof(WCHAR));
00125 
00126                 /* Allocate an aligned buffer + the null char */
00127                 CapturedSize = ((AtomNameLength + sizeof(WCHAR)) &~
00128                                 (sizeof(WCHAR) -1));
00129                 CapturedName = ExAllocatePoolWithTag(PagedPool,
00130                                                      CapturedSize,
00131                                                      TAG_ATOM);
00132                 if (!CapturedName)
00133                 {
00134                     /* Fail the call */
00135                     Status = STATUS_INSUFFICIENT_RESOURCES;
00136                 }
00137                 else
00138                 {
00139                     /* Copy the name and null-terminate it */
00140                     RtlCopyMemory(CapturedName, AtomName, AtomNameLength);
00141                     CapturedName[AtomNameLength / sizeof(WCHAR)] = UNICODE_NULL;
00142                 }
00143 
00144                 /* Probe the atom too */
00145                 if (Atom) ProbeForWriteUshort(Atom);
00146             }
00147         }
00148         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00149         {
00150             /* Return the exception code */
00151             _SEH2_YIELD(return _SEH2_GetExceptionCode());
00152         }
00153         _SEH2_END;
00154     }
00155 
00156     /* Call the runtime function */
00157     Status = RtlAddAtomToAtomTable(AtomTable, CapturedName, &SafeAtom);
00158     if (NT_SUCCESS(Status) && (Atom))
00159     {
00160         /* Success and caller wants the atom back.. .enter SEH */
00161         _SEH2_TRY
00162         {
00163             /* Return the atom */
00164             *Atom = SafeAtom;
00165         }
00166         _SEH2_EXCEPT(ExSystemExceptionFilter())
00167         {
00168             /* Get the exception code */
00169             Status = _SEH2_GetExceptionCode();
00170         }
00171         _SEH2_END;
00172     }
00173 
00174     /* If we captured anything, free it */
00175     if ((CapturedName) && (CapturedName != AtomName))
00176         ExFreePoolWithTag(CapturedName, TAG_ATOM);
00177 
00178     /* Return to caller */
00179     return Status;
00180 }
00181 
00182 /*++
00183  * @name NtDeleteAtom
00184  * @implemented
00185  *
00186  * Removes Atom from Global Atom Table. If Atom's reference counter
00187  * is greater then 1, function decrements this counter, but Atom
00188  * stayed in Global Atom Table.
00189  * See: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Atoms/NtDeleteAtom.html
00190  *
00191  * @param Atom
00192  *        Atom identifier
00193  *
00194  * @return STATUS_SUCCESS in case of success, proper error code
00195  *         othwerwise.
00196  *
00197  * @remarks None
00198  *
00199  *--*/
00200 NTSTATUS
00201 NTAPI
00202 NtDeleteAtom(IN RTL_ATOM Atom)
00203 {
00204     PRTL_ATOM_TABLE AtomTable = ExpGetGlobalAtomTable();
00205     PAGED_CODE();
00206 
00207     /* Check for valid table */
00208     if (AtomTable == NULL) return STATUS_ACCESS_DENIED;
00209 
00210     /* Call worker function */
00211     return RtlDeleteAtomFromAtomTable(AtomTable, Atom);
00212 }
00213 
00214 /*++
00215  * @name NtFindAtom
00216  * @implemented
00217  *
00218  * Retrieves existing Atom's identifier without incrementing Atom's
00219  * internal counter
00220  * See: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Atoms/NtFindAtom.html
00221  *
00222  * @param AtomName
00223  *        Atom name in Unicode
00224  *
00225  * @param AtomNameLength
00226  *        Length of the atom name
00227  *
00228  * @param Atom
00229  *        Pointer to RTL_ATOM
00230  *
00231  * @return STATUS_SUCCESS in case of success, proper error code
00232  *         othwerwise.
00233  *
00234  * @remarks None
00235  *
00236  *--*/
00237 NTSTATUS
00238 NTAPI
00239 NtFindAtom(IN PWSTR AtomName,
00240            IN ULONG AtomNameLength,
00241            OUT PRTL_ATOM Atom)
00242 {
00243     PRTL_ATOM_TABLE AtomTable = ExpGetGlobalAtomTable();
00244     NTSTATUS Status;
00245     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
00246     LPWSTR CapturedName = NULL;
00247     ULONG CapturedSize;
00248     RTL_ATOM SafeAtom;
00249     PAGED_CODE();
00250 
00251     /* Check for the table */
00252     if (AtomTable == NULL) return STATUS_ACCESS_DENIED;
00253 
00254     /* Check for valid name */
00255     if (AtomNameLength > (RTL_MAXIMUM_ATOM_LENGTH * sizeof(WCHAR)))
00256     {
00257         /* Fail */
00258         DPRINT1("Atom name too long\n");
00259         return STATUS_INVALID_PARAMETER;
00260     }
00261     
00262     /* Re-use the given name if kernel mode or no atom name */
00263     CapturedName = AtomName;
00264 
00265     /* Check if we're called from user-mode*/
00266     if (PreviousMode != KernelMode)
00267     {
00268         /* Enter SEH */
00269         _SEH2_TRY
00270         {
00271             /* Check if we have a name */
00272             if (AtomName)
00273             {
00274                 /* Probe the atom */
00275                 ProbeForRead(AtomName, AtomNameLength, sizeof(WCHAR));
00276 
00277                 /* Allocate an aligned buffer + the null char */
00278                 CapturedSize = ((AtomNameLength + sizeof(WCHAR)) &~
00279                                 (sizeof(WCHAR) -1));
00280                 CapturedName = ExAllocatePoolWithTag(PagedPool,
00281                                                      CapturedSize,
00282                                                      TAG_ATOM);
00283                 if (!CapturedName)
00284                 {
00285                     /* Fail the call */
00286                     Status = STATUS_INSUFFICIENT_RESOURCES;
00287                 }
00288                 else
00289                 {
00290                     /* Copy the name and null-terminate it */
00291                     RtlCopyMemory(CapturedName, AtomName, AtomNameLength);
00292                     CapturedName[AtomNameLength / sizeof(WCHAR)] = UNICODE_NULL;
00293                 }
00294 
00295                 /* Probe the atom too */
00296                 if (Atom) ProbeForWriteUshort(Atom);
00297             }
00298         }
00299         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00300         {
00301             /* Return the exception code */
00302             _SEH2_YIELD(return _SEH2_GetExceptionCode());
00303         }
00304         _SEH2_END;
00305     }
00306 
00307     /* Call the runtime function */
00308     Status = RtlLookupAtomInAtomTable(AtomTable, CapturedName, &SafeAtom);
00309     if (NT_SUCCESS(Status) && (Atom))
00310     {
00311         /* Success and caller wants the atom back.. .enter SEH */
00312         _SEH2_TRY
00313         {
00314             /* Return the atom */
00315             *Atom = SafeAtom;
00316         }
00317         _SEH2_EXCEPT(ExSystemExceptionFilter())
00318         {
00319             Status = _SEH2_GetExceptionCode();
00320         }
00321         _SEH2_END;
00322     }
00323 
00324     /* If we captured anything, free it */
00325     if ((CapturedName) && (CapturedName != AtomName))
00326         ExFreePoolWithTag(CapturedName, TAG_ATOM);
00327 
00328     /* Return to caller */
00329     return Status;
00330 }
00331 
00332 /*++
00333  * @name NtQueryInformationAtom
00334  * @implemented
00335  *
00336  * Gets single Atom properties or reads Global Atom Table
00337  * See: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Atoms/NtQueryInformationAtom.html
00338  *
00339  * @param Atom
00340  *        Atom to query. If AtomInformationClass parameter is
00341  *        AtomTableInformation, Atom parameter is not used.
00342  *
00343  * @param AtomInformationClass
00344  *        See ATOM_INFORMATION_CLASS enumeration type for details
00345  *
00346  * @param AtomInformation
00347  *        Result of call - pointer to user's allocated buffer for data
00348  *
00349  * @param AtomInformationLength
00350  *        Size of AtomInformation buffer, in bytes
00351  *
00352  * @param ReturnLength
00353  *        Pointer to ULONG value containing required AtomInformation
00354  *        buffer size
00355  *
00356  * @return STATUS_SUCCESS in case of success, proper error code
00357  *         othwerwise.
00358  *
00359  * @remarks None
00360  *
00361  *--*/
00362 NTSTATUS
00363 NTAPI
00364 NtQueryInformationAtom(RTL_ATOM Atom,
00365                        ATOM_INFORMATION_CLASS AtomInformationClass,
00366                        PVOID AtomInformation,
00367                        ULONG AtomInformationLength,
00368                        PULONG ReturnLength)
00369 {
00370     PRTL_ATOM_TABLE AtomTable = ExpGetGlobalAtomTable();
00371     PATOM_BASIC_INFORMATION BasicInformation = AtomInformation;
00372     PATOM_TABLE_INFORMATION TableInformation = AtomInformation;
00373     NTSTATUS Status = STATUS_SUCCESS;
00374     ULONG Flags, UsageCount, NameLength, RequiredLength = 0;
00375     KPROCESSOR_MODE PreviousMode;
00376 
00377     PAGED_CODE();
00378 
00379     /* Check for valid table */
00380     if (AtomTable == NULL) return STATUS_ACCESS_DENIED;
00381 
00382     PreviousMode = ExGetPreviousMode();
00383 
00384     _SEH2_TRY
00385     {
00386         /* Probe the parameters */
00387         if (PreviousMode != KernelMode)
00388         {
00389             ProbeForWrite(AtomInformation,
00390                           AtomInformationLength,
00391                           sizeof(ULONG));
00392 
00393             if (ReturnLength != NULL)
00394             {
00395                 ProbeForWriteUlong(ReturnLength);
00396             }
00397         }
00398 
00399         /* Choose class */
00400         switch (AtomInformationClass)
00401         {
00402             /* Caller requested info about an atom */
00403             case AtomBasicInformation:
00404 
00405                 /* Size check */
00406                 RequiredLength = FIELD_OFFSET(ATOM_BASIC_INFORMATION, Name);
00407                 if (RequiredLength > AtomInformationLength)
00408                 {
00409                     /* Fail */
00410                     DPRINT1("Buffer too small\n");
00411                     Status = STATUS_INFO_LENGTH_MISMATCH;
00412                     _SEH2_LEAVE;
00413                 }
00414 
00415                 /* Prepare query */
00416                 UsageCount = 0;
00417                 NameLength = AtomInformationLength - RequiredLength;
00418                 BasicInformation->Name[0] = UNICODE_NULL;
00419 
00420                 /* Query the data */
00421                 Status = RtlQueryAtomInAtomTable(AtomTable,
00422                                                  Atom,
00423                                                  &UsageCount,
00424                                                  &Flags,
00425                                                  BasicInformation->Name,
00426                                                  &NameLength);
00427                 if (NT_SUCCESS(Status))
00428                 {
00429                     /* Return data */
00430                     BasicInformation->UsageCount = (USHORT)UsageCount;
00431                     BasicInformation->Flags = (USHORT)Flags;
00432                     BasicInformation->NameLength = (USHORT)NameLength;
00433                     RequiredLength += NameLength + sizeof(WCHAR);
00434                 }
00435                 break;
00436 
00437             /* Caller requested info about an Atom Table */
00438             case AtomTableInformation:
00439 
00440                 /* Size check */
00441                 RequiredLength = FIELD_OFFSET(ATOM_TABLE_INFORMATION, Atoms);
00442                 if (RequiredLength > AtomInformationLength)
00443                 {
00444                     /* Fail */
00445                     DPRINT1("Buffer too small\n");
00446                     Status = STATUS_INFO_LENGTH_MISMATCH;
00447                     _SEH2_LEAVE;
00448                 }
00449 
00450                 /* Query the data */
00451                 Status = RtlQueryAtomListInAtomTable(AtomTable,
00452                                                      (AtomInformationLength - RequiredLength) /
00453                                                      sizeof(RTL_ATOM),
00454                                                      &TableInformation->NumberOfAtoms,
00455                                                      TableInformation->Atoms);
00456                 if (NT_SUCCESS(Status))
00457                 {
00458                     /* Update the return length */
00459                     RequiredLength += TableInformation->NumberOfAtoms * sizeof(RTL_ATOM);
00460                 }
00461                 break;
00462 
00463             /* Caller was on crack */
00464             default:
00465 
00466                 /* Unrecognized class */
00467                 Status = STATUS_INVALID_INFO_CLASS;
00468                 break;
00469         }
00470 
00471         /* Return the required size */
00472         if (ReturnLength != NULL)
00473         {
00474             *ReturnLength = RequiredLength;
00475         }
00476     }
00477     _SEH2_EXCEPT(ExSystemExceptionFilter())
00478     {
00479         Status = _SEH2_GetExceptionCode();
00480     }
00481     _SEH2_END;
00482 
00483     /* Return to caller */
00484     return Status;
00485 }
00486 
00487 /* 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.