test: exatom.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# exatom.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1992  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     exatom.c
    00008
    00009 Abstract:
    00010
    00011     This file contains functions for manipulating global atom tables
    00012     stored in kernel space.
    00013
    00014 Author:
    00015
    00016     Steve Wood (stevewo) 13-Dec-1995
    00017
    00018 Revision History:
    00019
    00020 --*/
    00021
    00022 #include "exp.h"
    00023 #pragma hdrstop
    00024
    00025 //
    00026 //  Local Procedure prototype
    00027 //
    00028
    00029 PVOID
    00030 ExpGetGlobalAtomTable (
    00031     );
    00032
    00033 #if defined(ALLOC_PRAGMA)
    00034 #pragma alloc_text(PAGE, NtAddAtom)
    00035 #pragma alloc_text(PAGE, NtFindAtom)
    00036 #pragma alloc_text(PAGE, NtDeleteAtom)
    00037 #pragma alloc_text(PAGE, NtQueryInformationAtom)
    00038 #pragma alloc_text(PAGE, ExpGetGlobalAtomTable)
    00039 #endif
    00040
    00041
    00042 NTSYSAPI
    00043 NTSTATUS
    00044 NTAPI
    00045 NtAddAtom (
    00046     IN PWSTR AtomName,
    00047     IN ULONG Length,
    00048     OUT PRTL_ATOM Atom OPTIONAL
    00049     )
    00050
    00051 /*++
    00052
    00053 Routine Description:
    00054
    00055 Arguments:
    00056
    00057 Return Value:
    00058
    00059 --*/
    00060
    00061 {
    00062     NTSTATUS Status;
    00063     RTL_ATOM ReturnAtom;
    00064     PVOID AtomTable = ExpGetGlobalAtomTable();
    00065     KPROCESSOR_MODE PreviousMode;
    00066     PWSTR CapturedAtomNameBuffer;
    00067     ULONG AllocLength;
    00068
    00069     PAGED_CODE();
    00070
    00071     if (AtomTable == NULL) {
    00072
    00073         return STATUS_ACCESS_DENIED;
    00074     }
    00075
    00076     if (Length > (RTL_ATOM_MAXIMUM_NAME_LENGTH * sizeof(WCHAR))) {
    00077
    00078         return STATUS_INVALID_PARAMETER;
    00079     }
    00080
    00081     PreviousMode = KeGetPreviousMode();
    00082     CapturedAtomNameBuffer = NULL;
    00083
    00084     Status = STATUS_SUCCESS;
    00085
    00086     if (PreviousMode != KernelMode) {
    00087
    00088         try {
    00089
    00090             if (ARGUMENT_PRESENT( AtomName )) {
    00091
    00092                 AllocLength = (Length + sizeof( UNICODE_NULL ))&~(sizeof (WCHAR)-1);
    00093                 ProbeForRead( AtomName, Length, sizeof( WCHAR ) );
    00094                 CapturedAtomNameBuffer = ExAllocatePoolWithTag( PagedPool, AllocLength, 'motA' );
    00095
    00096                 if (CapturedAtomNameBuffer == NULL) {
    00097
    00098                     return STATUS_INSUFFICIENT_RESOURCES;
    00099                 }
    00100
    00101                 RtlMoveMemory( CapturedAtomNameBuffer, AtomName, Length );
    00102                 CapturedAtomNameBuffer[Length / sizeof (WCHAR)] = '\0';
    00103             }
    00104
    00105             if (ARGUMENT_PRESENT( Atom )) {
    00106
    00107                 ProbeForWriteUshort( Atom );
    00108             }
    00109
    00110         } except (EXCEPTION_EXECUTE_HANDLER) {
    00111
    00112             Status = GetExceptionCode();
    00113         }
    00114
    00115     } else {
    00116
    00117         if (ARGUMENT_PRESENT( AtomName )) {
    00118
    00119             CapturedAtomNameBuffer = AtomName;
    00120         }
    00121     }
    00122
    00123     if (NT_SUCCESS( Status )) {
    00124
    00125         Status = RtlAddAtomToAtomTable( AtomTable, CapturedAtomNameBuffer, &ReturnAtom );
    00126
    00127         if (NT_SUCCESS( Status ) && ARGUMENT_PRESENT( Atom )) {
    00128
    00129             try {
    00130
    00131                 *Atom = ReturnAtom;
    00132
    00133             } except (EXCEPTION_EXECUTE_HANDLER) {
    00134
    00135                 Status = GetExceptionCode();
    00136             }
    00137         }
    00138     }
    00139
    00140     if ((CapturedAtomNameBuffer != NULL) && (CapturedAtomNameBuffer != AtomName)) {
    00141
    00142         ExFreePool( CapturedAtomNameBuffer );
    00143     }
    00144
    00145     return Status;
    00146 }
    00147
    00148
    00149 NTSYSAPI
    00150 NTSTATUS
    00151 NTAPI
    00152 NtFindAtom (
    00153     IN PWSTR AtomName,
    00154     IN ULONG Length,
    00155     OUT PRTL_ATOM Atom OPTIONAL
    00156     )
    00157
    00158 /*++
    00159
    00160 Routine Description:
    00161
    00162 Arguments:
    00163
    00164 Return Value:
    00165
    00166 --*/
    00167
    00168 {
    00169     NTSTATUS Status;
    00170     RTL_ATOM ReturnAtom;
    00171     PVOID AtomTable = ExpGetGlobalAtomTable();
    00172     KPROCESSOR_MODE PreviousMode;
    00173     PWSTR CapturedAtomNameBuffer;
    00174     ULONG AllocLength;
    00175
    00176     PAGED_CODE();
    00177
    00178     if (AtomTable == NULL) {
    00179
    00180         return STATUS_ACCESS_DENIED;
    00181     }
    00182
    00183     if (Length > (RTL_ATOM_MAXIMUM_NAME_LENGTH * sizeof(WCHAR))) {
    00184
    00185         return STATUS_INVALID_PARAMETER;
    00186     }
    00187
    00188     PreviousMode = KeGetPreviousMode();
    00189     CapturedAtomNameBuffer = NULL;
    00190
    00191     Status = STATUS_SUCCESS;
    00192
    00193     if (PreviousMode != KernelMode) {
    00194
    00195         try {
    00196
    00197             if (ARGUMENT_PRESENT( AtomName )) {
    00198
    00199                 AllocLength = (Length + sizeof( UNICODE_NULL ))&~(sizeof (WCHAR)-1);
    00200                 ProbeForRead( AtomName, Length, sizeof( WCHAR ) );
    00201                 CapturedAtomNameBuffer = ExAllocatePoolWithTag( PagedPool, AllocLength, 'motA' );
    00202
    00203                 if (CapturedAtomNameBuffer == NULL) {
    00204
    00205                     return STATUS_INSUFFICIENT_RESOURCES;
    00206                 }
    00207
    00208                 RtlMoveMemory( CapturedAtomNameBuffer, AtomName, Length );
    00209                 CapturedAtomNameBuffer[Length / sizeof (WCHAR)] = '\0';
    00210
    00211             }
    00212
    00213             if (ARGUMENT_PRESENT( Atom )) {
    00214
    00215                 ProbeForWriteUshort( Atom );
    00216             }
    00217
    00218         } except (EXCEPTION_EXECUTE_HANDLER) {
    00219
    00220             Status = GetExceptionCode();
    00221         }
    00222
    00223     } else {
    00224
    00225         if (ARGUMENT_PRESENT( AtomName )) {
    00226
    00227             CapturedAtomNameBuffer = AtomName;
    00228         }
    00229     }
    00230
    00231     if (NT_SUCCESS( Status )) {
    00232
    00233         Status = RtlLookupAtomInAtomTable( AtomTable, CapturedAtomNameBuffer, &ReturnAtom );
    00234
    00235         if (NT_SUCCESS( Status ) && ARGUMENT_PRESENT( Atom )) {
    00236
    00237             try {
    00238
    00239                 *Atom = ReturnAtom;
    00240
    00241             } except (EXCEPTION_EXECUTE_HANDLER) {
    00242
    00243                 Status = GetExceptionCode();
    00244             }
    00245         }
    00246     }
    00247
    00248     if (CapturedAtomNameBuffer != NULL && CapturedAtomNameBuffer != AtomName) {
    00249
    00250         ExFreePool( CapturedAtomNameBuffer );
    00251     }
    00252
    00253     return Status;
    00254 }
    00255
    00256
    00257 NTSYSAPI
    00258 NTSTATUS
    00259 NTAPI
    00260 NtDeleteAtom (
    00261     IN RTL_ATOM Atom
    00262     )
    00263
    00264 /*++
    00265
    00266 Routine Description:
    00267
    00268 Arguments:
    00269
    00270 Return Value:
    00271
    00272 --*/
    00273
    00274 {
    00275     NTSTATUS Status;
    00276     PVOID AtomTable = ExpGetGlobalAtomTable();
    00277
    00278     PAGED_CODE();
    00279
    00280     if (AtomTable == NULL) {
    00281
    00282         return STATUS_ACCESS_DENIED;
    00283     }
    00284
    00285     Status = RtlDeleteAtomFromAtomTable( AtomTable, Atom );
    00286
    00287     return Status;
    00288 }
    00289
    00290
    00291 NTSYSAPI
    00292 NTSTATUS
    00293 NTAPI
    00294 NtQueryInformationAtom(
    00295     IN RTL_ATOM Atom,
    00296     IN ATOM_INFORMATION_CLASS AtomInformationClass,
    00297     OUT PVOID AtomInformation,
    00298     IN ULONG AtomInformationLength,
    00299     OUT PULONG ReturnLength OPTIONAL
    00300     )
    00301
    00302 /*++
    00303
    00304 Routine Description:
    00305
    00306 Arguments:
    00307
    00308 Return Value:
    00309
    00310 --*/
    00311
    00312 {
    00313     NTSTATUS Status;
    00314     KPROCESSOR_MODE PreviousMode;
    00315     ULONG RequiredLength;
    00316     ULONG UsageCount;
    00317     ULONG NameLength;
    00318     ULONG AtomFlags;
    00319     PATOM_BASIC_INFORMATION BasicInfo;
    00320     PATOM_TABLE_INFORMATION TableInfo;
    00321     PVOID AtomTable = ExpGetGlobalAtomTable();
    00322
    00323     PAGED_CODE();
    00324
    00325     if (AtomTable == NULL) {
    00326
    00327         return STATUS_ACCESS_DENIED;
    00328     }
    00329
    00330     //
    00331     //  Assume successful completion.
    00332     //
    00333
    00334     Status = STATUS_SUCCESS;
    00335
    00336     try {
    00337
    00338         //
    00339         //  Get previous processor mode and probe output argument if necessary.
    00340         //
    00341
    00342         PreviousMode = KeGetPreviousMode();
    00343
    00344         if (PreviousMode != KernelMode) {
    00345
    00346             ProbeForWrite( AtomInformation,
    00347                            AtomInformationLength,
    00348                            sizeof( ULONG ));
    00349
    00350             if (ARGUMENT_PRESENT( ReturnLength )) {
    00351
    00352                 ProbeForWriteUlong( ReturnLength );
    00353             }
    00354         }
    00355
    00356         RequiredLength = 0;
    00357
    00358         switch (AtomInformationClass) {
    00359
    00360         case AtomBasicInformation:
    00361
    00362             RequiredLength = FIELD_OFFSET( ATOM_BASIC_INFORMATION, Name );
    00363
    00364             if (AtomInformationLength < RequiredLength) {
    00365
    00366                 return STATUS_INFO_LENGTH_MISMATCH;
    00367             }
    00368
    00369             BasicInfo = (PATOM_BASIC_INFORMATION)AtomInformation;
    00370             UsageCount = 0;
    00371             NameLength = AtomInformationLength - RequiredLength;
    00372             BasicInfo->Name[ 0 ] = UNICODE_NULL;
    00373
    00374             Status = RtlQueryAtomInAtomTable( AtomTable,
    00375                                               Atom,
    00376                                               &UsageCount,
    00377                                               &AtomFlags,
    00378                                               &BasicInfo->Name[0],
    00379                                               &NameLength );
    00380
    00381             if (NT_SUCCESS(Status)) {
    00382
    00383                 BasicInfo->UsageCount = (USHORT)UsageCount;
    00384                 BasicInfo->Flags = (USHORT)AtomFlags;
    00385                 BasicInfo->NameLength = (USHORT)NameLength;
    00386                 RequiredLength += NameLength + sizeof( UNICODE_NULL );
    00387             }
    00388
    00389             break;
    00390
    00391         case AtomTableInformation:
    00392
    00393             RequiredLength = FIELD_OFFSET( ATOM_TABLE_INFORMATION, Atoms );
    00394
    00395             if (AtomInformationLength < RequiredLength) {
    00396
    00397                 return STATUS_INFO_LENGTH_MISMATCH;
    00398             }
    00399
    00400             TableInfo = (PATOM_TABLE_INFORMATION)AtomInformation;
    00401
    00402             Status = RtlQueryAtomsInAtomTable( AtomTable,
    00403                                                (AtomInformationLength - RequiredLength) / sizeof( RTL_ATOM ),
    00404                                                &TableInfo->NumberOfAtoms,
    00405                                                &TableInfo->Atoms[0] );
    00406
    00407             if (NT_SUCCESS(Status)) {
    00408
    00409                 RequiredLength += TableInfo->NumberOfAtoms * sizeof( RTL_ATOM );
    00410             }
    00411
    00412             break;
    00413
    00414         default:
    00415
    00416             Status = STATUS_INVALID_INFO_CLASS;
    00417
    00418             break;
    00419         }
    00420
    00421         if (ARGUMENT_PRESENT( ReturnLength )) {
    00422
    00423             *ReturnLength = RequiredLength;
    00424         }
    00425
    00426     } except (EXCEPTION_EXECUTE_HANDLER) {
    00427
    00428         Status = GetExceptionCode();
    00429     }
    00430
    00431     return Status;
    00432 }
    00433
    00434
    00435 //
    00436 //  Local support routine
    00437 //
    00438
    00439 PKWIN32_GLOBALATOMTABLE_CALLOUT ExGlobalAtomTableCallout;
    00440
    00441 PVOID
    00442 ExpGetGlobalAtomTable (
    00443     )
    00444
    00445 /*++
    00446
    00447 Routine Description:
    00448
    00449 Arguments:
    00450
    00451 Return Value:
    00452
    00453 --*/
    00454
    00455 {
    00456     if (ExGlobalAtomTableCallout != NULL) {
    00457
    00458         return ((*ExGlobalAtomTableCallout)());
    00459
    00460     } else {
    00461
    00462 #if DBG
    00463         DbgPrint( "EX: ExpGetGlobalAtomTable is about to return NULL!\n" );
    00464         DbgBreakPoint();
    00465 #endif
    00466         return NULL;
    00467     }
    00468 }