1*c2c66affSColin Finck /* 2*c2c66affSColin Finck * PROJECT: ReactOS Kernel 3*c2c66affSColin Finck * COPYRIGHT: GPL - See COPYING in the top level directory 4*c2c66affSColin Finck * FILE: ntoskrnl/ex/atom.c 5*c2c66affSColin Finck * PURPOSE: Executive Atom Functions 6*c2c66affSColin Finck * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 7*c2c66affSColin Finck * Gunnar Dalsnes 8*c2c66affSColin Finck */ 9*c2c66affSColin Finck 10*c2c66affSColin Finck /* INCLUDES *****************************************************************/ 11*c2c66affSColin Finck 12*c2c66affSColin Finck #include <ntoskrnl.h> 13*c2c66affSColin Finck #define NDEBUG 14*c2c66affSColin Finck #include <debug.h> 15*c2c66affSColin Finck 16*c2c66affSColin Finck #define TAG_ATOM 'motA' 17*c2c66affSColin Finck 18*c2c66affSColin Finck /* GLOBALS ****************************************************************/ 19*c2c66affSColin Finck 20*c2c66affSColin Finck /* 21*c2c66affSColin Finck * FIXME: this is WRONG! The global atom table should live in the WinSta struct 22*c2c66affSColin Finck * and accessed through a win32k callout (received in PsEstablishWin32Callouts) 23*c2c66affSColin Finck * NOTE: There is a session/win32k global atom table also, but its private to 24*c2c66affSColin Finck * win32k. Its used for RegisterWindowMessage() and for window classes. 25*c2c66affSColin Finck * -Gunnar 26*c2c66affSColin Finck */ 27*c2c66affSColin Finck PRTL_ATOM_TABLE GlobalAtomTable; 28*c2c66affSColin Finck 29*c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/ 30*c2c66affSColin Finck 31*c2c66affSColin Finck /*++ 32*c2c66affSColin Finck * @name ExpGetGlobalAtomTable 33*c2c66affSColin Finck * 34*c2c66affSColin Finck * Gets pointer to a global atom table, creates it if not already created 35*c2c66affSColin Finck * 36*c2c66affSColin Finck * @return Pointer to the RTL_ATOM_TABLE, or NULL if it's impossible 37*c2c66affSColin Finck * to create atom table 38*c2c66affSColin Finck * 39*c2c66affSColin Finck * @remarks Internal function 40*c2c66affSColin Finck * 41*c2c66affSColin Finck *--*/ 42*c2c66affSColin Finck PRTL_ATOM_TABLE 43*c2c66affSColin Finck NTAPI 44*c2c66affSColin Finck ExpGetGlobalAtomTable(VOID) 45*c2c66affSColin Finck { 46*c2c66affSColin Finck NTSTATUS Status; 47*c2c66affSColin Finck 48*c2c66affSColin Finck /* Return it if we have one */ 49*c2c66affSColin Finck if (GlobalAtomTable) return GlobalAtomTable; 50*c2c66affSColin Finck 51*c2c66affSColin Finck /* Create it */ 52*c2c66affSColin Finck Status = RtlCreateAtomTable(37, &GlobalAtomTable); 53*c2c66affSColin Finck 54*c2c66affSColin Finck /* If we couldn't create it, return NULL */ 55*c2c66affSColin Finck if (!NT_SUCCESS(Status)) return NULL; 56*c2c66affSColin Finck 57*c2c66affSColin Finck /* Return the newly created one */ 58*c2c66affSColin Finck return GlobalAtomTable; 59*c2c66affSColin Finck } 60*c2c66affSColin Finck 61*c2c66affSColin Finck /* FUNCTIONS ****************************************************************/ 62*c2c66affSColin Finck 63*c2c66affSColin Finck /*++ 64*c2c66affSColin Finck * @name NtAddAtom 65*c2c66affSColin Finck * @implemented 66*c2c66affSColin Finck * 67*c2c66affSColin Finck * Function NtAddAtom creates new Atom in Global Atom Table. If Atom 68*c2c66affSColin Finck * with the same name already exist, internal Atom counter is incremented. 69*c2c66affSColin Finck * See: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Atoms/NtAddAtom.html 70*c2c66affSColin Finck * 71*c2c66affSColin Finck * @param AtomName 72*c2c66affSColin Finck * Atom name in Unicode 73*c2c66affSColin Finck * 74*c2c66affSColin Finck * @param AtomNameLength 75*c2c66affSColin Finck * Length of the atom name 76*c2c66affSColin Finck * 77*c2c66affSColin Finck * @param Atom 78*c2c66affSColin Finck * Pointer to RTL_ATOM 79*c2c66affSColin Finck * 80*c2c66affSColin Finck * @return STATUS_SUCCESS in case of success, proper error code 81*c2c66affSColin Finck * otherwise. 82*c2c66affSColin Finck * 83*c2c66affSColin Finck * @remarks None 84*c2c66affSColin Finck * 85*c2c66affSColin Finck *--*/ 86*c2c66affSColin Finck NTSTATUS 87*c2c66affSColin Finck NTAPI 88*c2c66affSColin Finck NtAddAtom(IN PWSTR AtomName, 89*c2c66affSColin Finck IN ULONG AtomNameLength, 90*c2c66affSColin Finck OUT PRTL_ATOM Atom) 91*c2c66affSColin Finck { 92*c2c66affSColin Finck PRTL_ATOM_TABLE AtomTable = ExpGetGlobalAtomTable(); 93*c2c66affSColin Finck NTSTATUS Status; 94*c2c66affSColin Finck KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 95*c2c66affSColin Finck LPWSTR CapturedName; 96*c2c66affSColin Finck ULONG CapturedSize; 97*c2c66affSColin Finck RTL_ATOM SafeAtom; 98*c2c66affSColin Finck PAGED_CODE(); 99*c2c66affSColin Finck 100*c2c66affSColin Finck /* Check for the table */ 101*c2c66affSColin Finck if (AtomTable == NULL) return STATUS_ACCESS_DENIED; 102*c2c66affSColin Finck 103*c2c66affSColin Finck /* Check for valid name */ 104*c2c66affSColin Finck if (AtomNameLength > (RTL_MAXIMUM_ATOM_LENGTH * sizeof(WCHAR))) 105*c2c66affSColin Finck { 106*c2c66affSColin Finck /* Fail */ 107*c2c66affSColin Finck DPRINT1("Atom name too long\n"); 108*c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 109*c2c66affSColin Finck } 110*c2c66affSColin Finck 111*c2c66affSColin Finck /* Check if we're called from user-mode or kernel-mode */ 112*c2c66affSColin Finck if (PreviousMode == KernelMode) 113*c2c66affSColin Finck { 114*c2c66affSColin Finck /* Re-use the given name if kernel mode */ 115*c2c66affSColin Finck CapturedName = AtomName; 116*c2c66affSColin Finck } 117*c2c66affSColin Finck else 118*c2c66affSColin Finck { 119*c2c66affSColin Finck /* Check if we have a name */ 120*c2c66affSColin Finck if (AtomName) 121*c2c66affSColin Finck { 122*c2c66affSColin Finck /* Allocate an aligned buffer + the null char */ 123*c2c66affSColin Finck CapturedSize = ((AtomNameLength + sizeof(WCHAR)) & 124*c2c66affSColin Finck ~(sizeof(WCHAR) -1)); 125*c2c66affSColin Finck CapturedName = ExAllocatePoolWithTag(PagedPool, 126*c2c66affSColin Finck CapturedSize, 127*c2c66affSColin Finck TAG_ATOM); 128*c2c66affSColin Finck 129*c2c66affSColin Finck if (!CapturedName) 130*c2c66affSColin Finck { 131*c2c66affSColin Finck /* Fail the call */ 132*c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 133*c2c66affSColin Finck } 134*c2c66affSColin Finck 135*c2c66affSColin Finck /* Enter SEH */ 136*c2c66affSColin Finck _SEH2_TRY 137*c2c66affSColin Finck { 138*c2c66affSColin Finck /* Probe the atom */ 139*c2c66affSColin Finck ProbeForRead(AtomName, AtomNameLength, sizeof(WCHAR)); 140*c2c66affSColin Finck 141*c2c66affSColin Finck /* Copy the name and null-terminate it */ 142*c2c66affSColin Finck RtlCopyMemory(CapturedName, AtomName, AtomNameLength); 143*c2c66affSColin Finck CapturedName[AtomNameLength / sizeof(WCHAR)] = UNICODE_NULL; 144*c2c66affSColin Finck 145*c2c66affSColin Finck /* Probe the atom too */ 146*c2c66affSColin Finck if (Atom) ProbeForWriteUshort(Atom); 147*c2c66affSColin Finck } 148*c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 149*c2c66affSColin Finck { 150*c2c66affSColin Finck /* Return the exception code */ 151*c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 152*c2c66affSColin Finck } 153*c2c66affSColin Finck _SEH2_END; 154*c2c66affSColin Finck } 155*c2c66affSColin Finck else 156*c2c66affSColin Finck { 157*c2c66affSColin Finck /* No name */ 158*c2c66affSColin Finck CapturedName = NULL; 159*c2c66affSColin Finck } 160*c2c66affSColin Finck } 161*c2c66affSColin Finck 162*c2c66affSColin Finck /* Call the runtime function */ 163*c2c66affSColin Finck Status = RtlAddAtomToAtomTable(AtomTable, CapturedName, &SafeAtom); 164*c2c66affSColin Finck if (NT_SUCCESS(Status) && (Atom)) 165*c2c66affSColin Finck { 166*c2c66affSColin Finck /* Success and caller wants the atom back.. .enter SEH */ 167*c2c66affSColin Finck _SEH2_TRY 168*c2c66affSColin Finck { 169*c2c66affSColin Finck /* Return the atom */ 170*c2c66affSColin Finck *Atom = SafeAtom; 171*c2c66affSColin Finck } 172*c2c66affSColin Finck _SEH2_EXCEPT(ExSystemExceptionFilter()) 173*c2c66affSColin Finck { 174*c2c66affSColin Finck /* Get the exception code */ 175*c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 176*c2c66affSColin Finck } 177*c2c66affSColin Finck _SEH2_END; 178*c2c66affSColin Finck } 179*c2c66affSColin Finck 180*c2c66affSColin Finck /* If we captured anything, free it */ 181*c2c66affSColin Finck if ((CapturedName != NULL) && (CapturedName != AtomName)) 182*c2c66affSColin Finck ExFreePoolWithTag(CapturedName, TAG_ATOM); 183*c2c66affSColin Finck 184*c2c66affSColin Finck /* Return to caller */ 185*c2c66affSColin Finck return Status; 186*c2c66affSColin Finck } 187*c2c66affSColin Finck 188*c2c66affSColin Finck /*++ 189*c2c66affSColin Finck * @name NtDeleteAtom 190*c2c66affSColin Finck * @implemented 191*c2c66affSColin Finck * 192*c2c66affSColin Finck * Removes Atom from Global Atom Table. If Atom's reference counter 193*c2c66affSColin Finck * is greater then 1, function decrements this counter, but Atom 194*c2c66affSColin Finck * stayed in Global Atom Table. 195*c2c66affSColin Finck * See: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Atoms/NtDeleteAtom.html 196*c2c66affSColin Finck * 197*c2c66affSColin Finck * @param Atom 198*c2c66affSColin Finck * Atom identifier 199*c2c66affSColin Finck * 200*c2c66affSColin Finck * @return STATUS_SUCCESS in case of success, proper error code 201*c2c66affSColin Finck * otherwise. 202*c2c66affSColin Finck * 203*c2c66affSColin Finck * @remarks None 204*c2c66affSColin Finck * 205*c2c66affSColin Finck *--*/ 206*c2c66affSColin Finck NTSTATUS 207*c2c66affSColin Finck NTAPI 208*c2c66affSColin Finck NtDeleteAtom(IN RTL_ATOM Atom) 209*c2c66affSColin Finck { 210*c2c66affSColin Finck PRTL_ATOM_TABLE AtomTable = ExpGetGlobalAtomTable(); 211*c2c66affSColin Finck PAGED_CODE(); 212*c2c66affSColin Finck 213*c2c66affSColin Finck /* Check for valid table */ 214*c2c66affSColin Finck if (AtomTable == NULL) return STATUS_ACCESS_DENIED; 215*c2c66affSColin Finck 216*c2c66affSColin Finck /* Call worker function */ 217*c2c66affSColin Finck return RtlDeleteAtomFromAtomTable(AtomTable, Atom); 218*c2c66affSColin Finck } 219*c2c66affSColin Finck 220*c2c66affSColin Finck /*++ 221*c2c66affSColin Finck * @name NtFindAtom 222*c2c66affSColin Finck * @implemented 223*c2c66affSColin Finck * 224*c2c66affSColin Finck * Retrieves existing Atom's identifier without incrementing Atom's 225*c2c66affSColin Finck * internal counter 226*c2c66affSColin Finck * See: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Atoms/NtFindAtom.html 227*c2c66affSColin Finck * 228*c2c66affSColin Finck * @param AtomName 229*c2c66affSColin Finck * Atom name in Unicode 230*c2c66affSColin Finck * 231*c2c66affSColin Finck * @param AtomNameLength 232*c2c66affSColin Finck * Length of the atom name 233*c2c66affSColin Finck * 234*c2c66affSColin Finck * @param Atom 235*c2c66affSColin Finck * Pointer to RTL_ATOM 236*c2c66affSColin Finck * 237*c2c66affSColin Finck * @return STATUS_SUCCESS in case of success, proper error code 238*c2c66affSColin Finck * otherwise. 239*c2c66affSColin Finck * 240*c2c66affSColin Finck * @remarks None 241*c2c66affSColin Finck * 242*c2c66affSColin Finck *--*/ 243*c2c66affSColin Finck NTSTATUS 244*c2c66affSColin Finck NTAPI 245*c2c66affSColin Finck NtFindAtom(IN PWSTR AtomName, 246*c2c66affSColin Finck IN ULONG AtomNameLength, 247*c2c66affSColin Finck OUT PRTL_ATOM Atom) 248*c2c66affSColin Finck { 249*c2c66affSColin Finck PRTL_ATOM_TABLE AtomTable = ExpGetGlobalAtomTable(); 250*c2c66affSColin Finck NTSTATUS Status; 251*c2c66affSColin Finck KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 252*c2c66affSColin Finck LPWSTR CapturedName = NULL; 253*c2c66affSColin Finck ULONG CapturedSize; 254*c2c66affSColin Finck RTL_ATOM SafeAtom; 255*c2c66affSColin Finck PAGED_CODE(); 256*c2c66affSColin Finck 257*c2c66affSColin Finck /* Check for the table */ 258*c2c66affSColin Finck if (AtomTable == NULL) return STATUS_ACCESS_DENIED; 259*c2c66affSColin Finck 260*c2c66affSColin Finck /* Check for valid name */ 261*c2c66affSColin Finck if (AtomNameLength > (RTL_MAXIMUM_ATOM_LENGTH * sizeof(WCHAR))) 262*c2c66affSColin Finck { 263*c2c66affSColin Finck /* Fail */ 264*c2c66affSColin Finck DPRINT1("Atom name too long\n"); 265*c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 266*c2c66affSColin Finck } 267*c2c66affSColin Finck 268*c2c66affSColin Finck /* Re-use the given name if kernel mode or no atom name */ 269*c2c66affSColin Finck CapturedName = AtomName; 270*c2c66affSColin Finck 271*c2c66affSColin Finck /* Check if we're called from user-mode*/ 272*c2c66affSColin Finck if (PreviousMode != KernelMode) 273*c2c66affSColin Finck { 274*c2c66affSColin Finck /* Enter SEH */ 275*c2c66affSColin Finck _SEH2_TRY 276*c2c66affSColin Finck { 277*c2c66affSColin Finck /* Check if we have a name */ 278*c2c66affSColin Finck if (AtomName) 279*c2c66affSColin Finck { 280*c2c66affSColin Finck /* Probe the atom */ 281*c2c66affSColin Finck ProbeForRead(AtomName, AtomNameLength, sizeof(WCHAR)); 282*c2c66affSColin Finck 283*c2c66affSColin Finck /* Allocate an aligned buffer + the null char */ 284*c2c66affSColin Finck CapturedSize = ((AtomNameLength + sizeof(WCHAR)) &~ 285*c2c66affSColin Finck (sizeof(WCHAR) -1)); 286*c2c66affSColin Finck CapturedName = ExAllocatePoolWithTag(PagedPool, 287*c2c66affSColin Finck CapturedSize, 288*c2c66affSColin Finck TAG_ATOM); 289*c2c66affSColin Finck if (!CapturedName) 290*c2c66affSColin Finck { 291*c2c66affSColin Finck /* Fail the call */ 292*c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES; 293*c2c66affSColin Finck } 294*c2c66affSColin Finck else 295*c2c66affSColin Finck { 296*c2c66affSColin Finck /* Copy the name and null-terminate it */ 297*c2c66affSColin Finck RtlCopyMemory(CapturedName, AtomName, AtomNameLength); 298*c2c66affSColin Finck CapturedName[AtomNameLength / sizeof(WCHAR)] = UNICODE_NULL; 299*c2c66affSColin Finck } 300*c2c66affSColin Finck 301*c2c66affSColin Finck /* Probe the atom too */ 302*c2c66affSColin Finck if (Atom) ProbeForWriteUshort(Atom); 303*c2c66affSColin Finck } 304*c2c66affSColin Finck } 305*c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 306*c2c66affSColin Finck { 307*c2c66affSColin Finck /* Return the exception code */ 308*c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 309*c2c66affSColin Finck } 310*c2c66affSColin Finck _SEH2_END; 311*c2c66affSColin Finck } 312*c2c66affSColin Finck 313*c2c66affSColin Finck /* Call the runtime function */ 314*c2c66affSColin Finck Status = RtlLookupAtomInAtomTable(AtomTable, CapturedName, &SafeAtom); 315*c2c66affSColin Finck if (NT_SUCCESS(Status) && (Atom)) 316*c2c66affSColin Finck { 317*c2c66affSColin Finck /* Success and caller wants the atom back.. .enter SEH */ 318*c2c66affSColin Finck _SEH2_TRY 319*c2c66affSColin Finck { 320*c2c66affSColin Finck /* Return the atom */ 321*c2c66affSColin Finck *Atom = SafeAtom; 322*c2c66affSColin Finck } 323*c2c66affSColin Finck _SEH2_EXCEPT(ExSystemExceptionFilter()) 324*c2c66affSColin Finck { 325*c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 326*c2c66affSColin Finck } 327*c2c66affSColin Finck _SEH2_END; 328*c2c66affSColin Finck } 329*c2c66affSColin Finck 330*c2c66affSColin Finck /* If we captured anything, free it */ 331*c2c66affSColin Finck if ((CapturedName) && (CapturedName != AtomName)) 332*c2c66affSColin Finck ExFreePoolWithTag(CapturedName, TAG_ATOM); 333*c2c66affSColin Finck 334*c2c66affSColin Finck /* Return to caller */ 335*c2c66affSColin Finck return Status; 336*c2c66affSColin Finck } 337*c2c66affSColin Finck 338*c2c66affSColin Finck /*++ 339*c2c66affSColin Finck * @name NtQueryInformationAtom 340*c2c66affSColin Finck * @implemented 341*c2c66affSColin Finck * 342*c2c66affSColin Finck * Gets single Atom properties or reads Global Atom Table 343*c2c66affSColin Finck * See: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Atoms/NtQueryInformationAtom.html 344*c2c66affSColin Finck * 345*c2c66affSColin Finck * @param Atom 346*c2c66affSColin Finck * Atom to query. If AtomInformationClass parameter is 347*c2c66affSColin Finck * AtomTableInformation, Atom parameter is not used. 348*c2c66affSColin Finck * 349*c2c66affSColin Finck * @param AtomInformationClass 350*c2c66affSColin Finck * See ATOM_INFORMATION_CLASS enumeration type for details 351*c2c66affSColin Finck * 352*c2c66affSColin Finck * @param AtomInformation 353*c2c66affSColin Finck * Result of call - pointer to user's allocated buffer for data 354*c2c66affSColin Finck * 355*c2c66affSColin Finck * @param AtomInformationLength 356*c2c66affSColin Finck * Size of AtomInformation buffer, in bytes 357*c2c66affSColin Finck * 358*c2c66affSColin Finck * @param ReturnLength 359*c2c66affSColin Finck * Pointer to ULONG value containing required AtomInformation 360*c2c66affSColin Finck * buffer size 361*c2c66affSColin Finck * 362*c2c66affSColin Finck * @return STATUS_SUCCESS in case of success, proper error code 363*c2c66affSColin Finck * otherwise. 364*c2c66affSColin Finck * 365*c2c66affSColin Finck * @remarks None 366*c2c66affSColin Finck * 367*c2c66affSColin Finck *--*/ 368*c2c66affSColin Finck NTSTATUS 369*c2c66affSColin Finck NTAPI 370*c2c66affSColin Finck NtQueryInformationAtom(RTL_ATOM Atom, 371*c2c66affSColin Finck ATOM_INFORMATION_CLASS AtomInformationClass, 372*c2c66affSColin Finck PVOID AtomInformation, 373*c2c66affSColin Finck ULONG AtomInformationLength, 374*c2c66affSColin Finck PULONG ReturnLength) 375*c2c66affSColin Finck { 376*c2c66affSColin Finck PRTL_ATOM_TABLE AtomTable = ExpGetGlobalAtomTable(); 377*c2c66affSColin Finck PATOM_BASIC_INFORMATION BasicInformation = AtomInformation; 378*c2c66affSColin Finck PATOM_TABLE_INFORMATION TableInformation = AtomInformation; 379*c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS; 380*c2c66affSColin Finck ULONG Flags, UsageCount, NameLength, RequiredLength = 0; 381*c2c66affSColin Finck KPROCESSOR_MODE PreviousMode; 382*c2c66affSColin Finck 383*c2c66affSColin Finck PAGED_CODE(); 384*c2c66affSColin Finck 385*c2c66affSColin Finck /* Check for valid table */ 386*c2c66affSColin Finck if (AtomTable == NULL) return STATUS_ACCESS_DENIED; 387*c2c66affSColin Finck 388*c2c66affSColin Finck PreviousMode = ExGetPreviousMode(); 389*c2c66affSColin Finck 390*c2c66affSColin Finck _SEH2_TRY 391*c2c66affSColin Finck { 392*c2c66affSColin Finck /* Probe the parameters */ 393*c2c66affSColin Finck if (PreviousMode != KernelMode) 394*c2c66affSColin Finck { 395*c2c66affSColin Finck ProbeForWrite(AtomInformation, 396*c2c66affSColin Finck AtomInformationLength, 397*c2c66affSColin Finck sizeof(ULONG)); 398*c2c66affSColin Finck 399*c2c66affSColin Finck if (ReturnLength != NULL) 400*c2c66affSColin Finck { 401*c2c66affSColin Finck ProbeForWriteUlong(ReturnLength); 402*c2c66affSColin Finck } 403*c2c66affSColin Finck } 404*c2c66affSColin Finck 405*c2c66affSColin Finck /* Choose class */ 406*c2c66affSColin Finck switch (AtomInformationClass) 407*c2c66affSColin Finck { 408*c2c66affSColin Finck /* Caller requested info about an atom */ 409*c2c66affSColin Finck case AtomBasicInformation: 410*c2c66affSColin Finck 411*c2c66affSColin Finck /* Size check */ 412*c2c66affSColin Finck RequiredLength = FIELD_OFFSET(ATOM_BASIC_INFORMATION, Name); 413*c2c66affSColin Finck if (RequiredLength > AtomInformationLength) 414*c2c66affSColin Finck { 415*c2c66affSColin Finck /* Fail */ 416*c2c66affSColin Finck DPRINT1("Buffer too small\n"); 417*c2c66affSColin Finck Status = STATUS_INFO_LENGTH_MISMATCH; 418*c2c66affSColin Finck _SEH2_LEAVE; 419*c2c66affSColin Finck } 420*c2c66affSColin Finck 421*c2c66affSColin Finck /* Prepare query */ 422*c2c66affSColin Finck UsageCount = 0; 423*c2c66affSColin Finck NameLength = AtomInformationLength - RequiredLength; 424*c2c66affSColin Finck BasicInformation->Name[0] = UNICODE_NULL; 425*c2c66affSColin Finck 426*c2c66affSColin Finck /* Query the data */ 427*c2c66affSColin Finck Status = RtlQueryAtomInAtomTable(AtomTable, 428*c2c66affSColin Finck Atom, 429*c2c66affSColin Finck &UsageCount, 430*c2c66affSColin Finck &Flags, 431*c2c66affSColin Finck BasicInformation->Name, 432*c2c66affSColin Finck &NameLength); 433*c2c66affSColin Finck if (NT_SUCCESS(Status)) 434*c2c66affSColin Finck { 435*c2c66affSColin Finck /* Return data */ 436*c2c66affSColin Finck BasicInformation->UsageCount = (USHORT)UsageCount; 437*c2c66affSColin Finck BasicInformation->Flags = (USHORT)Flags; 438*c2c66affSColin Finck BasicInformation->NameLength = (USHORT)NameLength; 439*c2c66affSColin Finck RequiredLength += NameLength + sizeof(WCHAR); 440*c2c66affSColin Finck } 441*c2c66affSColin Finck break; 442*c2c66affSColin Finck 443*c2c66affSColin Finck /* Caller requested info about an Atom Table */ 444*c2c66affSColin Finck case AtomTableInformation: 445*c2c66affSColin Finck 446*c2c66affSColin Finck /* Size check */ 447*c2c66affSColin Finck RequiredLength = FIELD_OFFSET(ATOM_TABLE_INFORMATION, Atoms); 448*c2c66affSColin Finck if (RequiredLength > AtomInformationLength) 449*c2c66affSColin Finck { 450*c2c66affSColin Finck /* Fail */ 451*c2c66affSColin Finck DPRINT1("Buffer too small\n"); 452*c2c66affSColin Finck Status = STATUS_INFO_LENGTH_MISMATCH; 453*c2c66affSColin Finck _SEH2_LEAVE; 454*c2c66affSColin Finck } 455*c2c66affSColin Finck 456*c2c66affSColin Finck /* Query the data */ 457*c2c66affSColin Finck Status = RtlQueryAtomListInAtomTable(AtomTable, 458*c2c66affSColin Finck (AtomInformationLength - RequiredLength) / 459*c2c66affSColin Finck sizeof(RTL_ATOM), 460*c2c66affSColin Finck &TableInformation->NumberOfAtoms, 461*c2c66affSColin Finck TableInformation->Atoms); 462*c2c66affSColin Finck if (NT_SUCCESS(Status)) 463*c2c66affSColin Finck { 464*c2c66affSColin Finck /* Update the return length */ 465*c2c66affSColin Finck RequiredLength += TableInformation->NumberOfAtoms * sizeof(RTL_ATOM); 466*c2c66affSColin Finck } 467*c2c66affSColin Finck break; 468*c2c66affSColin Finck 469*c2c66affSColin Finck /* Caller was on crack */ 470*c2c66affSColin Finck default: 471*c2c66affSColin Finck 472*c2c66affSColin Finck /* Unrecognized class */ 473*c2c66affSColin Finck Status = STATUS_INVALID_INFO_CLASS; 474*c2c66affSColin Finck break; 475*c2c66affSColin Finck } 476*c2c66affSColin Finck 477*c2c66affSColin Finck /* Return the required size */ 478*c2c66affSColin Finck if (ReturnLength != NULL) 479*c2c66affSColin Finck { 480*c2c66affSColin Finck *ReturnLength = RequiredLength; 481*c2c66affSColin Finck } 482*c2c66affSColin Finck } 483*c2c66affSColin Finck _SEH2_EXCEPT(ExSystemExceptionFilter()) 484*c2c66affSColin Finck { 485*c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 486*c2c66affSColin Finck } 487*c2c66affSColin Finck _SEH2_END; 488*c2c66affSColin Finck 489*c2c66affSColin Finck /* Return to caller */ 490*c2c66affSColin Finck return Status; 491*c2c66affSColin Finck } 492*c2c66affSColin Finck 493*c2c66affSColin Finck /* EOF */ 494