Something went wrong. Try again.
Reactos
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573#pragma once
#ifdef __cplusplusextern "C"{#endif
/* GLOBAL VARIABLES *********************************************************/
extern RTL_TIME_ZONE_INFORMATION ExpTimeZoneInfo;extern LARGE_INTEGER ExpTimeZoneBias;extern ULONG ExpTimeZoneId;extern ULONG ExpTickCountMultiplier;extern ULONG ExpLastTimeZoneBias;extern POBJECT_TYPE ExEventPairObjectType;extern POBJECT_TYPE _ExEventObjectType, _ExSemaphoreObjectType;extern FAST_MUTEX ExpEnvironmentLock;extern ERESOURCE ExpFirmwareTableResource;extern ERESOURCE ExpTimeRefreshLock;extern LIST_ENTRY ExpFirmwareTableProviderListHead;extern BOOLEAN ExpIsWinPEMode;extern ULONG ExpResourceTimeoutCount;extern LIST_ENTRY ExpSystemResourcesList;extern ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;extern ULONG ExpUnicodeCaseTableDataOffset;extern PVOID ExpNlsSectionPointer;extern ULONG NtGlobalFlag;extern UNICODE_STRING NtSystemRoot;extern ULONG ExpInitializationPhase;extern ULONG ExpAltTimeZoneBias;extern LIST_ENTRY ExSystemLookasideListHead;extern PCALLBACK_OBJECT PowerStateCallback;extern LIST_ENTRY ExPoolLookasideListHead;extern LIST_ENTRY ExpNonPagedLookasideListHead;extern LIST_ENTRY ExpPagedLookasideListHead;extern KSPIN_LOCK ExpNonPagedLookasideListLock;extern KSPIN_LOCK ExpPagedLookasideListLock;extern ULONG ExCriticalWorkerThreads;extern ULONG ExDelayedWorkerThreads;
extern PVOID ExpDefaultErrorPort;extern PEPROCESS ExpDefaultErrorPortProcess;
/* * NT/Cm Version Info variables */extern ULONG NtMajorVersion;extern ULONG NtMinorVersion;extern ULONG NtBuildNumber;extern ULONG CmNtSpBuildNumber;extern ULONG CmNtCSDVersion;extern ULONG CmNtCSDReleaseType;extern UNICODE_STRING CmVersionString;extern UNICODE_STRING CmCSDVersionString;extern CHAR NtBuildLab[];
/* * WinDBG Debugger Worker State Machine data (see dbgctrl.c) */typedef enum _WINKD_WORKER_STATE{ WinKdWorkerReady = 0, WinKdWorkerStart, WinKdWorkerInitialized} WINKD_WORKER_STATE;
extern WORK_QUEUE_ITEM ExpDebuggerWorkItem;extern WINKD_WORKER_STATE ExpDebuggerWork;extern PEPROCESS ExpDebuggerProcessAttach;extern PEPROCESS ExpDebuggerProcessKill;extern ULONG_PTR ExpDebuggerPageIn;
VOIDNTAPIExpDebuggerWorker( _In_ PVOID Context);
#ifdef _WIN64#define HANDLE_LOW_BITS (PAGE_SHIFT - 4)#define HANDLE_HIGH_BITS (PAGE_SHIFT - 3)#else#define HANDLE_LOW_BITS (PAGE_SHIFT - 3)#define HANDLE_HIGH_BITS (PAGE_SHIFT - 2)#endif#define HANDLE_TAG_BITS 2#define HANDLE_INDEX_BITS (HANDLE_LOW_BITS + 2 * HANDLE_HIGH_BITS)#define KERNEL_FLAG_BITS (sizeof(ULONG_PTR) * 8 - HANDLE_INDEX_BITS - HANDLE_TAG_BITS)
typedef union _EXHANDLE{ struct { ULONG_PTR TagBits: HANDLE_TAG_BITS; ULONG_PTR Index: HANDLE_INDEX_BITS; ULONG_PTR KernelFlag: KERNEL_FLAG_BITS; }; struct { ULONG_PTR TagBits2: HANDLE_TAG_BITS; ULONG_PTR LowIndex: HANDLE_LOW_BITS; ULONG_PTR MidIndex: HANDLE_HIGH_BITS; ULONG_PTR HighIndex: HANDLE_HIGH_BITS; ULONG_PTR KernelFlag2: KERNEL_FLAG_BITS; }; HANDLE GenericHandleOverlay; ULONG_PTR Value; ULONG AsULONG;} EXHANDLE, *PEXHANDLE;
typedef struct _ETIMER{ KTIMER KeTimer; KAPC TimerApc; KDPC TimerDpc; LIST_ENTRY ActiveTimerListEntry; KSPIN_LOCK Lock; LONG Period; BOOLEAN ApcAssociated; BOOLEAN WakeTimer; LIST_ENTRY WakeTimerListEntry;} ETIMER, *PETIMER;
typedef struct{ PCALLBACK_OBJECT *CallbackObject; PWSTR Name;} SYSTEM_CALLBACKS;
typedef struct _HARDERROR_USER_PARAMETERS{ ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS]; UNICODE_STRING Strings[MAXIMUM_HARDERROR_PARAMETERS]; WCHAR Buffer[ANYSIZE_ARRAY];} HARDERROR_USER_PARAMETERS, *PHARDERROR_USER_PARAMETERS;
#define MAX_FAST_REFS 7
#define ExAcquireRundownProtection _ExAcquireRundownProtection#define ExReleaseRundownProtection _ExReleaseRundownProtection#define ExInitializeRundownProtection _ExInitializeRundownProtection#define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease#define ExRundownCompleted _ExRundownCompleted#define ExGetPreviousMode KeGetPreviousMode
//// Various bits tagged on the handle or handle table//#define EXHANDLE_TABLE_ENTRY_LOCK_BIT 1#define FREE_HANDLE_MASK -1
//// Number of entries in each table level//#define LOW_LEVEL_ENTRIES (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY))#define MID_LEVEL_ENTRIES (PAGE_SIZE / sizeof(PHANDLE_TABLE_ENTRY))#define HIGH_LEVEL_ENTRIES (16777216 / (LOW_LEVEL_ENTRIES * MID_LEVEL_ENTRIES))
//// Maximum index in each table level before we need another table//#define MAX_LOW_INDEX LOW_LEVEL_ENTRIES#define MAX_MID_INDEX (MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)#define MAX_HIGH_INDEX (MID_LEVEL_ENTRIES * MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
#define ExpChangeRundown(x, y, z) (ULONG_PTR)InterlockedCompareExchangePointer(&(x)->Ptr, (PVOID)(y), (PVOID)(z))#define ExpChangePushlock(x, y, z) InterlockedCompareExchangePointer((PVOID*)(x), (PVOID)(y), (PVOID)(z))#define ExpSetRundown(x, y) InterlockedExchangePointer(&(x)->Ptr, (PVOID)(y))
NTSTATUSNTAPIExGetPoolTagInfo( IN PSYSTEM_POOLTAG_INFORMATION SystemInformation, IN ULONG SystemInformationLength, IN OUT PULONG ReturnLength OPTIONAL);
typedef struct _UUID_CACHED_VALUES_STRUCT{ ULONGLONG Time; LONG AllocatedCount; union { struct { UCHAR ClockSeqHiAndReserved; UCHAR ClockSeqLow; UCHAR NodeId[6 /*SEED_BUFFER_SIZE*/]; }; UCHAR GuidInit[8]; /* Match GUID.Data4 */ };} UUID_CACHED_VALUES_STRUCT, *PUUID_CACHED_VALUES_STRUCT;
C_ASSERT(RTL_FIELD_SIZE(UUID_CACHED_VALUES_STRUCT, GuidInit) == RTL_FIELD_SIZE(UUID, Data4));
/* INITIALIZATION FUNCTIONS *************************************************/
CODE_SEG("INIT")BOOLEANNTAPIExpWin32kInit(VOID);
VOIDNTAPIExInit2(VOID);
VOIDNTAPIPhase1Initialization( IN PVOID Context);
CODE_SEG("INIT")VOIDNTAPIExpInitializePushLocks(VOID);
BOOLEANNTAPIExRefreshTimeZoneInformation( IN PLARGE_INTEGER SystemBootTime);
CODE_SEG("INIT")VOIDNTAPIExpInitializeWorkerThreads(VOID);
VOIDNTAPIExSwapinWorkerThreads(IN BOOLEAN AllowSwap);
CODE_SEG("INIT")VOIDNTAPIExpInitLookasideLists(VOID);
CODE_SEG("INIT")VOIDNTAPIExInitializeSystemLookasideList( IN PGENERAL_LOOKASIDE List, IN POOL_TYPE Type, IN ULONG Size, IN ULONG Tag, IN USHORT MaximumDepth, IN PLIST_ENTRY ListHead);
CODE_SEG("INIT")BOOLEANNTAPIExpInitializeCallbacks(VOID);
CODE_SEG("INIT")BOOLEANNTAPIExpUuidInitialization(VOID);
CODE_SEG("INIT")BOOLEANNTAPIExLuidInitialization(VOID);
CODE_SEG("INIT")VOIDNTAPIExpInitializeExecutive( IN ULONG Cpu, IN PLOADER_PARAMETER_BLOCK LoaderBlock);
VOIDNTAPIExShutdownSystem(VOID);
CODE_SEG("INIT")BOOLEANNTAPIExpInitializeEventImplementation(VOID);
CODE_SEG("INIT")BOOLEANNTAPIExpInitializeKeyedEventImplementation(VOID);
CODE_SEG("INIT")BOOLEANNTAPIExpInitializeEventPairImplementation(VOID);
CODE_SEG("INIT")BOOLEANNTAPIExpInitializeSemaphoreImplementation(VOID);
CODE_SEG("INIT")BOOLEANNTAPIExpInitializeMutantImplementation(VOID);
CODE_SEG("INIT")BOOLEANNTAPIExpInitializeTimerImplementation(VOID);
CODE_SEG("INIT")BOOLEANNTAPIExpInitializeProfileImplementation(VOID);
CODE_SEG("INIT")VOIDNTAPIExpResourceInitialization(VOID);
CODE_SEG("INIT")VOIDNTAPIExInitPoolLookasidePointers(VOID);
/* Callback Functions ********************************************************/
VOIDNTAPIExInitializeCallBack( IN OUT PEX_CALLBACK Callback);
PEX_CALLBACK_ROUTINE_BLOCKNTAPIExAllocateCallBack( IN PEX_CALLBACK_FUNCTION Function, IN PVOID Context);
VOIDNTAPIExFreeCallBack( IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock);
BOOLEANNTAPIExCompareExchangeCallBack ( IN OUT PEX_CALLBACK CallBack, IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock, IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock);
PEX_CALLBACK_ROUTINE_BLOCKNTAPIExReferenceCallBackBlock( IN OUT PEX_CALLBACK CallBack);
VOIDNTAPIExDereferenceCallBackBlock( IN OUT PEX_CALLBACK CallBack, IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock);
PEX_CALLBACK_FUNCTIONNTAPIExGetCallBackBlockRoutine( IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock);
PVOIDNTAPIExGetCallBackBlockContext( IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock);
VOIDNTAPIExWaitForCallBacks( IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock);
/* Rundown Functions ********************************************************/
VOIDFASTCALLExfInitializeRundownProtection( OUT PEX_RUNDOWN_REF RunRef);
VOIDFASTCALLExfReInitializeRundownProtection( OUT PEX_RUNDOWN_REF RunRef);
BOOLEANFASTCALLExfAcquireRundownProtection( IN OUT PEX_RUNDOWN_REF RunRef);
BOOLEANFASTCALLExfAcquireRundownProtectionEx( IN OUT PEX_RUNDOWN_REF RunRef, IN ULONG Count);
VOIDFASTCALLExfReleaseRundownProtection( IN OUT PEX_RUNDOWN_REF RunRef);
VOIDFASTCALLExfReleaseRundownProtectionEx( IN OUT PEX_RUNDOWN_REF RunRef, IN ULONG Count);
VOIDFASTCALLExfRundownCompleted( OUT PEX_RUNDOWN_REF RunRef);
VOIDFASTCALLExfWaitForRundownProtectionRelease( IN OUT PEX_RUNDOWN_REF RunRef);
/* HANDLE TABLE FUNCTIONS ***************************************************/
typedef BOOLEAN(NTAPI *PEX_SWEEP_HANDLE_CALLBACK)( PHANDLE_TABLE_ENTRY HandleTableEntry, HANDLE Handle, PVOID Context);
typedef BOOLEAN(NTAPI *PEX_DUPLICATE_HANDLE_CALLBACK)( IN PEPROCESS Process, IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry, IN PHANDLE_TABLE_ENTRY NewEntry);
typedef BOOLEAN(NTAPI *PEX_CHANGE_HANDLE_CALLBACK)( PHANDLE_TABLE_ENTRY HandleTableEntry, ULONG_PTR Context);
CODE_SEG("INIT")VOIDNTAPIExpInitializeHandleTables( VOID);
PHANDLE_TABLENTAPIExCreateHandleTable( IN PEPROCESS Process OPTIONAL);
VOIDNTAPIExUnlockHandleTableEntry( IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry);
HANDLENTAPIExCreateHandle( IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry);
VOIDNTAPIExDestroyHandleTable( IN PHANDLE_TABLE HandleTable, IN PVOID DestroyHandleProcedure OPTIONAL);
BOOLEANNTAPIExDestroyHandle( IN PHANDLE_TABLE HandleTable, IN HANDLE Handle, IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL);
PHANDLE_TABLE_ENTRYNTAPIExMapHandleToPointer( IN PHANDLE_TABLE HandleTable, IN HANDLE Handle);
PHANDLE_TABLENTAPIExDupHandleTable( IN PEPROCESS Process, IN PHANDLE_TABLE HandleTable, IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure, IN ULONG_PTR Mask);
BOOLEANNTAPIExChangeHandle( IN PHANDLE_TABLE HandleTable, IN HANDLE Handle, IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine, IN ULONG_PTR Context);
VOIDNTAPIExSweepHandleTable( IN PHANDLE_TABLE HandleTable, IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure, IN PVOID Context);
PHANDLE_TABLE_ENTRYNTAPIExpLookupHandleTableEntry( IN PHANDLE_TABLE HandleTable, IN EXHANDLE Handle);
BOOLEANNTAPIExpLockHandleTableEntry( IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry);
/* PSEH EXCEPTION HANDLING **************************************************/
LONGNTAPIExSystemExceptionFilter(VOID);
/* CALLBACKS *****************************************************************/
FORCEINLINEVOIDExDoCallBack(IN OUT PEX_CALLBACK Callback, IN PVOID Context, IN PVOID Argument1, IN PVOID Argument2){ PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock; PEX_CALLBACK_FUNCTION Function;
/* Reference the block */ CallbackBlock = ExReferenceCallBackBlock(Callback); if (CallbackBlock) { /* Get the function */ Function = ExGetCallBackBlockRoutine(CallbackBlock);
/* Do the callback */ Function(Context, Argument1, Argument2);
/* Now dereference it */ ExDereferenceCallBackBlock(Callback, CallbackBlock); }}
/* FAST REFS ******************************************************************/
FORCEINLINEPVOIDExGetObjectFastReference(IN EX_FAST_REF FastRef){ /* Return the unbiased pointer */ return (PVOID)(FastRef.Value & ~MAX_FAST_REFS);}
FORCEINLINEULONGExGetCountFastReference(IN EX_FAST_REF FastRef){ /* Return the reference count */ return (ULONG)FastRef.RefCnt;}
FORCEINLINEVOIDExInitializeFastReference(OUT PEX_FAST_REF FastRef, IN OPTIONAL PVOID Object){ /* Sanity check */ ASSERT((((ULONG_PTR)Object) & MAX_FAST_REFS) == 0);
/* Check if an object is being set */ if (!Object) { /* Clear the field */ FastRef->Object = NULL; } else { /* Otherwise, we assume the object was referenced and is ready */ FastRef->Value = (ULONG_PTR)Object | MAX_FAST_REFS; }}
FORCEINLINEEX_FAST_REFExAcquireFastReference(IN OUT PEX_FAST_REF FastRef){ EX_FAST_REF OldValue, NewValue;
/* Start reference loop */ for (;;) { /* Get the current reference count */ OldValue = *FastRef; if (OldValue.RefCnt) { /* Increase the reference count */ NewValue.Value = OldValue.Value - 1; NewValue.Object = ExpChangePushlock(&FastRef->Object, NewValue.Object, OldValue.Object); if (NewValue.Object != OldValue.Object) continue; }
/* We are done */ break; }
/* Return the old value */ return OldValue;}
FORCEINLINEBOOLEANExInsertFastReference(IN OUT PEX_FAST_REF FastRef, IN PVOID Object){ EX_FAST_REF OldValue, NewValue;
/* Sanity checks */ ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
/* Start update loop */ for (;;) { /* Get the current reference count */ OldValue = *FastRef;
/* Check if the current count is too high or if the pointer changed */ if (((OldValue.RefCnt + MAX_FAST_REFS) > MAX_FAST_REFS) || ((OldValue.Value &~ MAX_FAST_REFS) != (ULONG_PTR)Object)) { /* Fail */ return FALSE; }
/* Update the reference count */ NewValue.Value = OldValue.Value + MAX_FAST_REFS; NewValue.Object = ExpChangePushlock(&FastRef->Object, NewValue.Object, OldValue.Object); if (NewValue.Object != OldValue.Object) continue;
/* We are done */ break; }
/* Return success */ return TRUE;}
FORCEINLINEBOOLEANExReleaseFastReference(IN PEX_FAST_REF FastRef, IN PVOID Object){ EX_FAST_REF OldValue, NewValue;
/* Sanity checks */ ASSERT(Object != NULL); ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
/* Start reference loop */ for (;;) { /* Get the current reference count */ OldValue = *FastRef;
/* Check if we're full if if the pointer changed */ if ((OldValue.Value ^ (ULONG_PTR)Object) >= MAX_FAST_REFS) return FALSE;
/* Decrease the reference count */ NewValue.Value = OldValue.Value + 1; NewValue.Object = ExpChangePushlock(&FastRef->Object, NewValue.Object, OldValue.Object); if (NewValue.Object != OldValue.Object) continue;
/* We are done */ break; }
/* Return success */ return TRUE;}
FORCEINLINEEX_FAST_REFExSwapFastReference(IN PEX_FAST_REF FastRef, IN PVOID Object){ EX_FAST_REF NewValue, OldValue;
/* Sanity check */ ASSERT((((ULONG_PTR)Object) & MAX_FAST_REFS) == 0);
/* Check if an object is being set */ if (!Object) { /* Clear the field */ NewValue.Object = NULL; } else { /* Otherwise, we assume the object was referenced and is ready */ NewValue.Value = (ULONG_PTR)Object | MAX_FAST_REFS; }
/* Update the object */ OldValue.Object = InterlockedExchangePointer(&FastRef->Object, NewValue.Object); return OldValue;}
FORCEINLINEEX_FAST_REFExCompareSwapFastReference(IN PEX_FAST_REF FastRef, IN PVOID Object, IN PVOID OldObject){ EX_FAST_REF OldValue, NewValue;
/* Sanity check and start swap loop */ ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS)); for (;;) { /* Get the current value */ OldValue = *FastRef;
/* Make sure there's enough references to swap */ if (!((OldValue.Value ^ (ULONG_PTR)OldObject) <= MAX_FAST_REFS)) break;
/* Check if we have an object to swap */ if (Object) { /* Set up the value with maximum fast references */ NewValue.Value = (ULONG_PTR)Object | MAX_FAST_REFS; } else { /* Write the object address itself (which is empty) */ NewValue.Value = (ULONG_PTR)Object; }
/* Do the actual compare exchange */ NewValue.Object = ExpChangePushlock(&FastRef->Object, NewValue.Object, OldValue.Object); if (NewValue.Object != OldValue.Object) continue;
/* All done */ break; }
/* Return the old value */ return OldValue;}
/* RUNDOWN *******************************************************************/
FORCEINLINEPEX_RUNDOWN_REFExGetRunRefForGivenProcessor(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware, IN ULONG ProcNumber){ return (PEX_RUNDOWN_REF)((ULONG_PTR)RunRefCacheAware->RunRefs + RunRefCacheAware->RunRefSize * (ProcNumber % RunRefCacheAware->Number));}
/*++ * @name ExfAcquireRundownProtection * INTERNAL MACRO * * The ExfAcquireRundownProtection routine acquires rundown protection for * the specified descriptor. * * @param RunRef * Pointer to a rundown reference descriptor. * * @return TRUE if access to the protected structure was granted, FALSE otherwise. * * @remarks This is the internal macro for system use only.In case the rundown * was active, then the slow-path will be called through the exported * function. * *--*/FORCEINLINEBOOLEAN_ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef){ ULONG_PTR Value, NewValue;
/* Get the current value and mask the active bit */ Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
/* Add a reference */ NewValue = Value + EX_RUNDOWN_COUNT_INC;
/* Change the value */ NewValue = ExpChangeRundown(RunRef, NewValue, Value); if (NewValue != Value) { /* Rundown was active, use long path */ return ExfAcquireRundownProtection(RunRef); }
/* Success */ return TRUE;}
/*++ * @name ExReleaseRundownProtection * INTERNAL MACRO * * The ExReleaseRundownProtection routine releases rundown protection for * the specified descriptor. * * @param RunRef * Pointer to a rundown reference descriptor. * * @return TRUE if access to the protected structure was granted, FALSE otherwise. * * @remarks This is the internal macro for system use only.In case the rundown * was active, then the slow-path will be called through the exported * function. * *--*/FORCEINLINEVOID_ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef){ ULONG_PTR Value, NewValue;
/* Get the current value and mask the active bit */ Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
/* Remove a reference */ NewValue = Value - EX_RUNDOWN_COUNT_INC;
/* Change the value */ NewValue = ExpChangeRundown(RunRef, NewValue, Value);
/* Check if the rundown was active */ if (NewValue != Value) { /* Rundown was active, use long path */ ExfReleaseRundownProtection(RunRef); } else { /* Sanity check */ ASSERT((Value >= EX_RUNDOWN_COUNT_INC) || (KeNumberProcessors > 1)); }}
/*++ * @name ExInitializeRundownProtection * INTERNAL MACRO * * The ExInitializeRundownProtection routine initializes a rundown * protection descriptor. * * @param RunRef * Pointer to a rundown reference descriptor. * * @return None. * * @remarks This is the internal macro for system use only. * *--*/FORCEINLINEVOID_ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef){ /* Set the count to zero */ RunRef->Count = 0;}
/*++ * @name ExWaitForRundownProtectionRelease * INTERNAL MACRO * * The ExWaitForRundownProtectionRelease routine waits until the specified * rundown descriptor has been released. * * @param RunRef * Pointer to a rundown reference descriptor. * * @return None. * * @remarks This is the internal macro for system use only. If a wait is actually * necessary, then the slow path is taken through the exported function. * *--*/FORCEINLINEVOID_ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef){ ULONG_PTR Value;
/* Set the active bit */ Value = ExpChangeRundown(RunRef, EX_RUNDOWN_ACTIVE, 0); if ((Value) && (Value != EX_RUNDOWN_ACTIVE)) { /* If the the rundown wasn't already active, then take the long path */ ExfWaitForRundownProtectionRelease(RunRef); }}
/*++ * @name ExRundownCompleted * INTERNAL MACRO * * The ExRundownCompleted routine completes the rundown of the specified * descriptor by setting the active bit. * * @param RunRef * Pointer to a rundown reference descriptor. * * @return None. * * @remarks This is the internal macro for system use only. * *--*/FORCEINLINEVOID_ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef){ /* Sanity check */ ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0);
/* Mark the counter as active */ ExpSetRundown(RunRef, EX_RUNDOWN_ACTIVE);}
/* PUSHLOCKS *****************************************************************/
/* FIXME: VERIFY THESE! */
VOIDFASTCALLExBlockPushLock( IN PEX_PUSH_LOCK PushLock, IN PVOID WaitBlock);
VOIDFASTCALLExfUnblockPushLock( IN PEX_PUSH_LOCK PushLock, IN PVOID CurrentWaitBlock);
VOIDFASTCALLExWaitForUnblockPushLock( IN PEX_PUSH_LOCK PushLock, IN PVOID WaitBlock);
/*++ * @name _ExInitializePushLock * INTERNAL MACRO * * The _ExInitializePushLock macro initializes a PushLock. * * @params PushLock * Pointer to the pushlock which is to be initialized. * * @return None. * * @remarks None. * *--*/FORCEINLINEVOID_ExInitializePushLock(OUT PEX_PUSH_LOCK PushLock){ /* Set the value to 0 */ PushLock->Ptr = 0;}#define ExInitializePushLock _ExInitializePushLock
/*++ * @name ExAcquirePushLockExclusive * INTERNAL MACRO * * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock. * * @params PushLock * Pointer to the pushlock which is to be acquired. * * @return None. * * @remarks The function attempts the quickest route to acquire the lock, which is * to simply set the lock bit. * However, if the pushlock is already shared, the slower path is taken. * * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL. * This macro should usually be paired up with KeAcquireCriticalRegion. * *--*/FORCEINLINEVOIDExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock){ /* Try acquiring the lock */ if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V)) { /* Someone changed it, use the slow path */ ExfAcquirePushLockExclusive(PushLock); }
/* Sanity check */ ASSERT(PushLock->Locked);}
/*++* @name ExTryToAcquirePushLockExclusive* INTERNAL MACRO** The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.** @params PushLock* Pointer to the pushlock which is to be acquired.** @return None.** @remarks The function attempts the quickest route to acquire the lock, which is* to simply set the lock bit.* However, if the pushlock is already shared, the slower path is taken.** Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.* This macro should usually be paired up with KeAcquireCriticalRegion.**--*/FORCEINLINEBOOLEANExTryToAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock){ /* Try acquiring the lock */ if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V)) { /* Can't acquire */ return FALSE; }
/* Got acquired */ ASSERT (PushLock->Locked); return TRUE;}
/*++ * @name ExAcquirePushLockShared * INTERNAL MACRO * * The ExAcquirePushLockShared macro acquires a shared PushLock. * * @params PushLock * Pointer to the pushlock which is to be acquired. * * @return None. * * @remarks The function attempts the quickest route to acquire the lock, which is * to simply set the lock bit and set the share count to one. * However, if the pushlock is already shared, the slower path is taken. * * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL. * This macro should usually be paired up with KeAcquireCriticalRegion. * *--*/FORCEINLINEVOIDExAcquirePushLockShared(PEX_PUSH_LOCK PushLock){ EX_PUSH_LOCK NewValue;
/* Try acquiring the lock */ NewValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC; if (ExpChangePushlock(PushLock, NewValue.Ptr, 0)) { /* Someone changed it, use the slow path */ ExfAcquirePushLockShared(PushLock); }
/* Sanity checks */ ASSERT(PushLock->Locked);}
/*++ * @name ExConvertPushLockSharedToExclusive * INTERNAL MACRO * * The ExConvertPushLockSharedToExclusive macro converts an exclusive * pushlock to a shared pushlock. * * @params PushLock * Pointer to the pushlock which is to be converted. * * @return FALSE if conversion failed, TRUE otherwise. * * @remarks The function attempts the quickest route to convert the lock, which is * to simply set the lock bit and remove any other bits. * *--*/FORCEINLINEBOOLEANExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock){ EX_PUSH_LOCK OldValue;
/* Set the expected old value */ OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
/* Try converting the lock */ if (ExpChangePushlock(PushLock, EX_PUSH_LOCK_LOCK, OldValue.Value) != OldValue.Ptr) { /* Conversion failed */ return FALSE; }
/* Sanity check */ ASSERT(PushLock->Locked); return TRUE;}
/*++ * @name ExWaitOnPushLock * INTERNAL MACRO * * The ExWaitOnPushLock macro acquires and instantly releases a pushlock. * * @params PushLock * Pointer to a pushlock. * * @return None. * * @remarks The function attempts to get any exclusive waiters out of their slow * path by forcing an instant acquire/release operation. * * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL. * *--*/FORCEINLINEVOIDExWaitOnPushLock(PEX_PUSH_LOCK PushLock){ /* Check if we're locked */ if (PushLock->Locked) { /* Acquire the lock */ ExfAcquirePushLockExclusive(PushLock); ASSERT(PushLock->Locked);
/* Release it */ ExfReleasePushLockExclusive(PushLock); }}
/*++ * @name ExReleasePushLockShared * INTERNAL MACRO * * The ExReleasePushLockShared macro releases a previously acquired PushLock. * * @params PushLock * Pointer to a previously acquired pushlock. * * @return None. * * @remarks The function attempts the quickest route to release the lock, which is * to simply decrease the share count and remove the lock bit. * However, if the pushlock is being waited on then the long path is taken. * * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL. * This macro should usually be paired up with KeLeaveCriticalRegion. * *--*/FORCEINLINEVOIDExReleasePushLockShared(PEX_PUSH_LOCK PushLock){ EX_PUSH_LOCK OldValue;
/* Sanity checks */ ASSERT(PushLock->Locked);
/* Try to clear the pushlock */ OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC; if (ExpChangePushlock(PushLock, 0, OldValue.Ptr) != OldValue.Ptr) { /* There are still other people waiting on it */ ExfReleasePushLockShared(PushLock); }}
/*++ * @name ExReleasePushLockExclusive * INTERNAL MACRO * * The ExReleasePushLockExclusive macro releases a previously * exclusively acquired PushLock. * * @params PushLock * Pointer to a previously acquired pushlock. * * @return None. * * @remarks The function attempts the quickest route to release the lock, which is * to simply clear the locked bit. * However, if the pushlock is being waited on, the slow path is taken * in an attempt to wake up the lock. * * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL. * This macro should usually be paired up with KeLeaveCriticalRegion. * *--*/FORCEINLINEVOIDExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock){ EX_PUSH_LOCK OldValue;
/* Sanity checks */ ASSERT(PushLock->Locked);
/* Unlock the pushlock */ OldValue.Value = InterlockedExchangeAddSizeT((PSIZE_T)PushLock, -(SSIZE_T)EX_PUSH_LOCK_LOCK);
/* Sanity checks */ ASSERT(OldValue.Locked); ASSERT(OldValue.Waiting || OldValue.Shared == 0);
/* Check if anyone is waiting on it and it's not already waking*/ if ((OldValue.Waiting) && !(OldValue.Waking)) { /* Wake it up */ ExfTryToWakePushLock(PushLock); }}
/*++ * @name ExReleasePushLock * INTERNAL MACRO * * The ExReleasePushLock macro releases a previously acquired PushLock. * * @params PushLock * Pointer to a previously acquired pushlock. * * @return None. * * @remarks The function attempts the quickest route to release the lock, which is * to simply clear all the fields and decrease the share count if required. * However, if the pushlock is being waited on then the long path is taken. * * Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL. * This macro should usually be paired up with KeLeaveCriticalRegion. * *--*/FORCEINLINEVOIDExReleasePushLock(PEX_PUSH_LOCK PushLock){ EX_PUSH_LOCK OldValue = *PushLock; EX_PUSH_LOCK NewValue;
/* Sanity checks */ ASSERT(OldValue.Locked);
/* Check if the pushlock is shared */ if (OldValue.Shared > 1) { /* Decrease the share count */ NewValue.Value = OldValue.Value - EX_PUSH_LOCK_SHARE_INC; } else { /* Clear the pushlock entirely */ NewValue.Value = 0; }
/* Check if nobody is waiting on us and try clearing the lock here */ if ((OldValue.Waiting) || (ExpChangePushlock(PushLock, NewValue.Ptr, OldValue.Ptr) != OldValue.Ptr)) { /* We have waiters, use the long path */ ExfReleasePushLock(PushLock); }}
/* FAST MUTEX INLINES *********************************************************/
FORCEINLINEVOID_ExAcquireFastMutexUnsafe(IN PFAST_MUTEX FastMutex){ PKTHREAD Thread = KeGetCurrentThread();
/* Sanity check */ ASSERT((KeGetCurrentIrql() == APC_LEVEL) || (Thread->CombinedApcDisable != 0) || (Thread->Teb == NULL) || (Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START)); ASSERT(FastMutex->Owner != Thread);
/* Decrease the count */ if (InterlockedDecrement(&FastMutex->Count)) { /* Someone is still holding it, use slow path */ KiAcquireFastMutex(FastMutex); }
/* Set the owner */ FastMutex->Owner = Thread;}
FORCEINLINEVOID_ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex){ ASSERT((KeGetCurrentIrql() == APC_LEVEL) || (KeGetCurrentThread()->CombinedApcDisable != 0) || (KeGetCurrentThread()->Teb == NULL) || (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START)); ASSERT(FastMutex->Owner == KeGetCurrentThread());
/* Erase the owner */ FastMutex->Owner = NULL;
/* Increase the count */ if (InterlockedIncrement(&FastMutex->Count) <= 0) { /* Someone was waiting for it, signal the waiter */ KeSetEventBoostPriority(&FastMutex->Event, NULL); }}
FORCEINLINEVOID_ExAcquireFastMutex(IN PFAST_MUTEX FastMutex){ KIRQL OldIrql; ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
/* Raise IRQL to APC */ KeRaiseIrql(APC_LEVEL, &OldIrql);
/* Decrease the count */ if (InterlockedDecrement(&FastMutex->Count)) { /* Someone is still holding it, use slow path */ KiAcquireFastMutex(FastMutex); }
/* Set the owner and IRQL */ FastMutex->Owner = KeGetCurrentThread(); FastMutex->OldIrql = OldIrql;}
FORCEINLINEVOID_ExReleaseFastMutex(IN OUT PFAST_MUTEX FastMutex){ KIRQL OldIrql; ASSERT(KeGetCurrentIrql() == APC_LEVEL);
/* Erase the owner */ FastMutex->Owner = NULL; OldIrql = (KIRQL)FastMutex->OldIrql;
/* Increase the count */ if (InterlockedIncrement(&FastMutex->Count) <= 0) { /* Someone was waiting for it, signal the waiter */ KeSetEventBoostPriority(&FastMutex->Event, NULL); }
/* Lower IRQL back */ KeLowerIrql(OldIrql);}
FORCEINLINEBOOLEAN_ExTryToAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex){ KIRQL OldIrql; ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
/* Raise to APC_LEVEL */ KeRaiseIrql(APC_LEVEL, &OldIrql);
/* Check if we can quickly acquire it */ if (InterlockedCompareExchange(&FastMutex->Count, 0, 1) == 1) { /* We have, set us as owners */ FastMutex->Owner = KeGetCurrentThread(); FastMutex->OldIrql = OldIrql; return TRUE; } else { /* Acquire attempt failed */ KeLowerIrql(OldIrql); YieldProcessor(); return FALSE; }}
FORCEINLINEVOID_ExEnterCriticalRegionAndAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex){ /* Enter the Critical Region */ KeEnterCriticalRegion();
/* Acquire the mutex unsafely */ _ExAcquireFastMutexUnsafe(FastMutex);}
FORCEINLINEVOID_ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(IN OUT PFAST_MUTEX FastMutex){ /* Release the mutex unsafely */ _ExReleaseFastMutexUnsafe(FastMutex);
/* Leave the critical region */ KeLeaveCriticalRegion();}
/* OTHER FUNCTIONS **********************************************************/
BOOLEANNTAPIExTryToAcquireResourceExclusiveLite( IN PERESOURCE Resource);
NTSTATUSExpSetTimeZoneInformation( IN PRTL_TIME_ZONE_INFORMATION TimeZoneInformation);
BOOLEANNTAPIExAcquireTimeRefreshLock( IN BOOLEAN Wait);
VOIDNTAPIExReleaseTimeRefreshLock( VOID);
VOIDNTAPIExUpdateSystemTimeFromCmos( IN BOOLEAN UpdateInterruptTime, IN ULONG MaxSepInSeconds);
VOIDNTAPIExAllocateLocallyUniqueId( OUT LUID *LocallyUniqueId);
VOIDNTAPIExTimerRundown( VOID);
VOIDNTAPIExUnlockUserBuffer(PMDL Mdl);
NTSTATUSNTAPIExLockUserBuffer( PVOID BaseAddress, ULONG Length, KPROCESSOR_MODE AccessMode, LOCK_OPERATION Operation, PVOID *MappedSystemVa, PMDL *OutMdl);
CODE_SEG("INIT")VOIDNTAPIHeadlessInit( IN PLOADER_PARAMETER_BLOCK LoaderBlock);
CODE_SEG("INIT")VOIDNTAPIXIPInit( IN PLOADER_PARAMETER_BLOCK LoaderBlock);
#define InterlockedDecrementUL(Addend) \ (ULONG)InterlockedDecrement((PLONG)(Addend))
#define InterlockedIncrementUL(Addend) \ (ULONG)InterlockedIncrement((PLONG)(Addend))
#define InterlockedExchangeUL(Target, Value) \ (ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
#define InterlockedExchangeAddUL(Addend, Value) \ (ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
#define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \ (ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
#define InterlockedCompareExchangeSizeT(Destination, Exchange, Comperand) \ (SIZE_T)InterlockedCompareExchangePointer((PVOID*)(Destination), (PVOID)(SIZE_T)(Exchange), (PVOID)(SIZE_T)(Comperand))
#ifdef _WIN64#define InterlockedExchangeSizeT(Target, Value) \ (SIZE_T)InterlockedExchange64((PLONG64)(Target), (LONG64)(Value))#else#define InterlockedExchangeSizeT(Target, Value) \ (SIZE_T)InterlockedExchange((PLONG)(Target), (LONG)(Value))#endif
#define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \ (ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))
#ifdef __cplusplus} // extern "C"#endif