Author: ion
Date: Tue Jul 11 23:45:16 2006
New Revision: 23013
URL:
http://svn.reactos.org/svn/reactos?rev=23013&view=rev
Log:
- Implement Fast Referencing and fix EX_FAST_REF definition.
- Implement ObReferenceEx and ObDereferenceEx.
- Split off ObpDeferObjectCompletion. A new win2003/vista API requires direct acess to
being able to defer deletes.
- Fix some bugs in Process Token management and make it all properly use Fast
Referencing.
- When duplicating a token in a new process, don't de-reference it before it's
even created, and also insert it.
- Change ExpChangeRundown macro to fix warnings in msvc.
Modified:
trunk/reactos/include/ndk/extypes.h
trunk/reactos/ntoskrnl/include/internal/ex.h
trunk/reactos/ntoskrnl/include/internal/se.h
trunk/reactos/ntoskrnl/ob/obref.c
trunk/reactos/ntoskrnl/ps/psmgr.c
trunk/reactos/ntoskrnl/ps/security.c
trunk/reactos/ntoskrnl/ps/thread.c
trunk/reactos/ntoskrnl/se/semgr.c
trunk/reactos/ntoskrnl/se/token.c
Modified: trunk/reactos/include/ndk/extypes.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/extypes.h?rev=…
==============================================================================
--- trunk/reactos/include/ndk/extypes.h (original)
+++ trunk/reactos/include/ndk/extypes.h Tue Jul 11 23:45:16 2006
@@ -361,8 +361,8 @@
union
{
PVOID Object;
- ULONG RefCnt:3;
- ULONG Value;
+ ULONG_PTR RefCnt:3;
+ ULONG_PTR Value;
};
} EX_FAST_REF, *PEX_FAST_REF;
Modified: trunk/reactos/ntoskrnl/include/internal/ex.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ex.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ex.h Tue Jul 11 23:45:16 2006
@@ -267,7 +267,7 @@
#define ExpChangeRundown(x, y, z) InterlockedCompareExchange64((PLONGLONG)x, y, z)
#define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
#else
-#define ExpChangeRundown(x, y, z) InterlockedCompareExchange((PLONG)x, y, z)
+#define ExpChangeRundown(x, y, z) InterlockedCompareExchange((PLONG)x, PtrToLong(y),
PtrToLong(z))
#define ExpSetRundown(x, y) InterlockedExchange((PLONG)x, y)
#endif
Modified: trunk/reactos/ntoskrnl/include/internal/se.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/se.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/se.h Tue Jul 11 23:45:16 2006
@@ -121,6 +121,15 @@
SeDeassignPrimaryToken(struct _EPROCESS *Process);
NTSTATUS
+NTAPI
+SeSubProcessToken(
+ IN PTOKEN Parent,
+ OUT PTOKEN *Token,
+ IN BOOLEAN InUse,
+ IN ULONG SessionId
+);
+
+NTSTATUS
STDCALL
SepCreateImpersonationTokenDacl(
PTOKEN Token,
Modified: trunk/reactos/ntoskrnl/ob/obref.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obref.c?rev=23…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obref.c (original)
+++ trunk/reactos/ntoskrnl/ob/obref.c Tue Jul 11 23:45:16 2006
@@ -18,36 +18,182 @@
/* PRIVATE FUNCTIONS *********************************************************/
VOID
+NTAPI
+ObpDeferObjectDeletion(IN PVOID Object)
+{
+ POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object);
+
+ /* Add us to the list */
+ do
+ {
+ Header->NextToFree = ObpReaperList;
+ } while (InterlockedCompareExchangePointer(&ObpReaperList,
+ Header,
+ Header->NextToFree) !=
+ Header->NextToFree);
+
+ /* Queue the work item */
+ ExQueueWorkItem(&ObpReaperWorkItem, DelayedWorkQueue);
+}
+
+LONG
+FASTCALL
+ObReferenceObjectEx(IN PVOID Object,
+ IN ULONG Count)
+{
+ /* Increment the reference count and return the count now */
+ return InterlockedExchangeAdd(&OBJECT_TO_OBJECT_HEADER(Object)->
+ PointerCount,
+ Count);
+}
+
+LONG
+FASTCALL
+ObDereferenceObjectEx(IN PVOID Object,
+ IN ULONG Count)
+{
+ POBJECT_HEADER Header;
+ ULONG NewCount;
+
+ /* Extract the object header */
+ Header = OBJECT_TO_OBJECT_HEADER(Object);
+
+ /* Check whether the object can now be deleted. */
+ NewCount = InterlockedExchangeAdd(&Header->PointerCount, -Count);
+ if (!Count)
+ {
+ /* Add us to the deferred deletion list */
+ ObpDeferObjectDeletion(Object);
+ }
+
+ /* Return the current count */
+ return NewCount;
+}
+
+VOID
FASTCALL
ObInitializeFastReference(IN PEX_FAST_REF FastRef,
- PVOID Object)
-{
- /* FIXME: Fast Referencing is Unimplemented */
- FastRef->Object = Object;
+ IN PVOID Object OPTIONAL)
+{
+ /* Check if we were given an object and reference it 7 times */
+ if (Object) ObReferenceObjectEx(Object, MAX_FAST_REFS);
+
+ /* Sanity check */
+ ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
+
+ /* Check if the caller gave us an object */
+ if (Object)
+ {
+ /* He did, so write the biased pointer */
+ FastRef->Object = (PVOID)((ULONG_PTR)Object | MAX_FAST_REFS);
+ }
+ else
+ {
+ /* Otherwise, clear the current object */
+ FastRef->Object = NULL;
+ }
}
PVOID
FASTCALL
+ObFastReferenceObjectLocked(IN PEX_FAST_REF FastRef)
+{
+ PVOID Object;
+
+ /* Get the object and reference it slowly */
+ Object = (PVOID)((ULONG_PTR)FastRef->Object & MAX_FAST_REFS);
+ if (Object) ObReferenceObject(Object);
+ return Object;
+}
+
+PVOID
+FASTCALL
ObFastReferenceObject(IN PEX_FAST_REF FastRef)
{
- /* FIXME: Fast Referencing is Unimplemented */
-
- /* Do a normal Reference */
- ObReferenceObject(FastRef->Object);
+ ULONG_PTR Value, NewValue;
+ ULONG_PTR Count;
+ PVOID Object;
+
+ /* Start reference loop */
+ for (;;)
+ {
+ /* Get the current count */
+ Value = FastRef->Value;
+ if (!Value & MAX_FAST_REFS) break;
+
+ /* Increase the reference count */
+ NewValue = Value - 1;
+ if (ExpChangeRundown(FastRef, NewValue, Value) == Value) break;
+ }
+
+ /* Get the object and count */
+ Object = (PVOID)(Value &~ MAX_FAST_REFS);
+ Count = Value & MAX_FAST_REFS;
+ DPRINT("Ref: %p\n", Object);
+
+ /* Check if the reference count is over 1 */
+ if (Count > 1) return Object;
+
+ /* Check if the reference count has reached 0 */
+ if (!Count) return NULL;
+
+ /* Otherwise, reference the object 7 times */
+ ObReferenceObjectEx(Object, MAX_FAST_REFS);
+ ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
+
+ for (;;)
+ {
+ /* Check if the current count is too high */
+ Value = FastRef->Value;
+ if (((FastRef->RefCnt + MAX_FAST_REFS) > MAX_FAST_REFS) ||
+ ((PVOID)((ULONG_PTR)FastRef->Object &~ MAX_FAST_REFS) != Object))
+ {
+ /* Completely dereference the object */
+ ObDereferenceObjectEx(Object, MAX_FAST_REFS);
+ break;
+ }
+ else
+ {
+ /* Increase the reference count */
+ NewValue = Value + MAX_FAST_REFS;
+ if (ExpChangeRundown(FastRef, NewValue, Value) == Value) break;
+ }
+ }
/* Return the Object */
- return FastRef->Object;
+ return Object;
}
VOID
FASTCALL
ObFastDereferenceObject(IN PEX_FAST_REF FastRef,
- PVOID Object)
-{
- /* FIXME: Fast Referencing is Unimplemented */
-
- /* Do a normal Dereference */
- ObDereferenceObject(FastRef->Object);
+ IN PVOID Object)
+{
+ ULONG_PTR Value, NewValue;
+
+ /* Sanity checks */
+ DPRINT("DeRef: %p\n", Object);
+ ASSERT(Object);
+ ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
+
+ /* Start dereference loop */
+ for (;;)
+ {
+ /* Get the current count */
+ Value = FastRef->Value;
+ if ((Value ^ (ULONG_PTR)Object) < MAX_FAST_REFS)
+ {
+ /* Decrease the reference count */
+ NewValue = Value + 1;
+ if (ExpChangeRundown(FastRef, NewValue, Value) == Value) return;
+ }
+ else
+ {
+ /* Do a normal Dereference */
+ ObDereferenceObject(Object);
+ return;
+ }
+ }
}
PVOID
@@ -55,15 +201,38 @@
ObFastReplaceObject(IN PEX_FAST_REF FastRef,
PVOID Object)
{
- PVOID OldObject = FastRef->Object;
-
- /* FIXME: Fast Referencing is Unimplemented */
- FastRef->Object = Object;
-
- /* Do a normal Dereference */
- ObDereferenceObject(OldObject);
-
- /* Return old Object*/
+ ULONG_PTR NewValue;
+ EX_FAST_REF OldRef;
+ PVOID OldObject;
+
+ /* Check if we were given an object and reference it 7 times */
+ if (Object) ObReferenceObjectEx(Object, MAX_FAST_REFS);
+
+ /* Sanity check */
+ ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
+
+ /* Check if the caller gave us an object */
+ if (Object)
+ {
+ /* He did, so bias the pointer */
+ NewValue = (ULONG_PTR)Object | MAX_FAST_REFS;
+ }
+ else
+ {
+ /* No object, we're clearing */
+ NewValue = 0;
+ }
+
+ /* Switch objects */
+ OldRef.Value = InterlockedExchange(&FastRef->Value, NewValue);
+ OldObject = (PVOID)((ULONG_PTR)OldRef.Object &~ MAX_FAST_REFS);
+ if ((OldObject) && (OldRef.RefCnt))
+ {
+ /* Dereference the old object */
+ ObDereferenceObjectEx(OldObject, OldRef.RefCnt);
+ }
+
+ /* Return the old object */
return OldObject;
}
@@ -112,17 +281,8 @@
}
else
{
- /* Add us to the list */
- do
- {
- Header->NextToFree = ObpReaperList;
- } while (InterlockedCompareExchangePointer(&ObpReaperList,
- Header,
- Header->NextToFree) !=
- Header->NextToFree);
-
- /* Queue the work item */
- ExQueueWorkItem(&ObpReaperWorkItem, DelayedWorkQueue);
+ /* Add us to the deferred deletion list */
+ ObpDeferObjectDeletion(Object);
}
}
}
Modified: trunk/reactos/ntoskrnl/ps/psmgr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/psmgr.c?rev=23…
==============================================================================
--- trunk/reactos/ntoskrnl/ps/psmgr.c (original)
+++ trunk/reactos/ntoskrnl/ps/psmgr.c Tue Jul 11 23:45:16 2006
@@ -196,6 +196,7 @@
InitializeListHead(&PsIdleProcess->Pcb.ThreadListHead);
InitializeListHead(&PsIdleProcess->ThreadListHead);
InitializeListHead(&PsIdleProcess->ActiveProcessLinks);
+ ObInitializeFastReference(&PsIdleProcess->Token, NULL);
KeInitializeDispatcherHeader(&PsIdleProcess->Pcb.Header,
ProcessObject,
sizeof(EPROCESS) / sizeof(LONG),
@@ -278,8 +279,7 @@
/* No parent, this is the Initial System Process. Assign Boot Token */
BootToken = SepCreateSystemProcessToken();
BootToken->TokenInUse = TRUE;
- PsInitialSystemProcess->Token.Object = BootToken; /* FIXME */
- ObReferenceObject(BootToken);
+ ObInitializeFastReference(&PsInitialSystemProcess->Token, BootToken);
}
#endif
}
Modified: trunk/reactos/ntoskrnl/ps/security.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/security.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ps/security.c (original)
+++ trunk/reactos/ntoskrnl/ps/security.c Tue Jul 11 23:45:16 2006
@@ -176,7 +176,7 @@
PspLockProcessSecurityShared(Process);
/* Do a Locked Fast Reference */
- //Token = ObFastReferenceObjectLocked(&Process->Token);
+ Token = ObFastReferenceObjectLocked(&Process->Token);
/* Unlock the Process */
PspUnlockProcessSecurityShared(Process);
@@ -222,47 +222,25 @@
PEPROCESS Parent OPTIONAL)
{
NTSTATUS Status = STATUS_SUCCESS;
+ PTOKEN NewToken, ParentToken;
/* If we have a parent, then duplicate the Token */
- if (Parent) {
-
- PTOKEN pNewToken;
- PTOKEN pParentToken;
- OBJECT_ATTRIBUTES ObjectAttributes;
-
+ if (Parent)
+ {
/* Get the Parent Token */
- pParentToken = PsReferencePrimaryToken(Parent);
-
- /* Initialize the Object Attributes */
- InitializeObjectAttributes(&ObjectAttributes,
- NULL,
- 0,
- NULL,
- NULL);
-
- /* Duplicate the Token */
- Status = SepDuplicateToken(pParentToken,
- &ObjectAttributes,
- FALSE,
- TokenPrimary,
- pParentToken->ImpersonationLevel,
- KernelMode,
- &pNewToken);
-
- if(!NT_SUCCESS(Status)) {
-
- DPRINT1("Failed to Duplicate Token\n");
- return Status;
- }
-
- /* Dereference the Token */
- ObFastDereferenceObject(&Parent->Token, pParentToken);
+ ParentToken = PsReferencePrimaryToken(Parent);
+
+ /* Duplicate it */
+ Status = SeSubProcessToken(ParentToken, &NewToken, TRUE, 0);
+
+ /* Dereference the Parent */
+ ObFastDereferenceObject(&Parent->Token, ParentToken);
/* Set the new Token */
- ObInitializeFastReference(&Process->Token, pNewToken);
-
- } else {
-
+ ObInitializeFastReference(&Process->Token, NewToken);
+ }
+ else
+ {
#ifdef SCHED_REWRITE
PTOKEN BootToken;
@@ -449,7 +427,7 @@
PspLockProcessSecurityShared(Process);
/* Do a Locked Fast Reference */
- //Token = ObFastReferenceObjectLocked(&Process->Token);
+ Token = ObFastReferenceObjectLocked(&Process->Token);
/* Unlock the Process */
PspUnlockProcessSecurityShared(Process);
Modified: trunk/reactos/ntoskrnl/ps/thread.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/thread.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/ps/thread.c (original)
+++ trunk/reactos/ntoskrnl/ps/thread.c Tue Jul 11 23:45:16 2006
@@ -10,10 +10,9 @@
/*
* Alex FIXMEs:
* - CRITICAL: NtCurrentTeb returns KPCR.
- * - CRITICAL: Verify rundown APIs (ex/rundown.c) and use them where necessary.
- * - MAJOR: Implement Pushlocks and use them as process lock.
+ * - MAJOR: Use Process Rundown
+ * - MAJOR: Use Process Pushlock Locks
* - MAJOR: Implement Safe Referencing (See PsGetNextProcess/Thread).
- * - MAJOR: Implement Fast Referencing (mostly for tokens).
* - MAJOR: Use Guarded Mutex instead of Fast Mutex for Active Process Locks.
* - Generate process cookie for user-more thread.
* - Add security calls where necessary.
Modified: trunk/reactos/ntoskrnl/se/semgr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/semgr.c?rev=23…
==============================================================================
--- trunk/reactos/ntoskrnl/se/semgr.c (original)
+++ trunk/reactos/ntoskrnl/se/semgr.c Tue Jul 11 23:45:16 2006
@@ -485,7 +485,7 @@
if (SubjectContext->PrimaryToken != NULL)
{
- ObDereferenceObject(SubjectContext->PrimaryToken);
+ ObFastDereferenceObject(&PsGetCurrentProcess()->Token,
SubjectContext->PrimaryToken);
}
if (SubjectContext->ClientToken != NULL)
Modified: trunk/reactos/ntoskrnl/se/token.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/token.c?rev=23…
==============================================================================
--- trunk/reactos/ntoskrnl/se/token.c (original)
+++ trunk/reactos/ntoskrnl/se/token.c Tue Jul 11 23:45:16 2006
@@ -321,8 +321,51 @@
return(STATUS_SUCCESS);
}
- ObDereferenceObject(AccessToken);
return(Status);
+}
+
+NTSTATUS
+NTAPI
+SeSubProcessToken(IN PTOKEN ParentToken,
+ OUT PTOKEN *Token,
+ IN BOOLEAN InUse,
+ IN ULONG SessionId)
+{
+ PTOKEN NewToken;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+
+ /* Initialize the attributes and duplicate it */
+ InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
+ Status = SepDuplicateToken(ParentToken,
+ &ObjectAttributes,
+ FALSE,
+ TokenPrimary,
+ ParentToken->ImpersonationLevel,
+ KernelMode,
+ &NewToken);
+ if (NT_SUCCESS(Status))
+ {
+ /* Insert it */
+ Status = ObInsertObject(NewToken,
+ NULL,
+ 0,
+ 1,
+ NULL,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ /* Set the session ID */
+ NewToken->SessionId = SessionId;
+ NewToken->TokenInUse = InUse;
+
+ /* Return the token */
+ *Token = NewToken;
+ }
+ }
+
+ /* Return status */
+ return Status;
}
/*
@@ -2472,6 +2515,7 @@
PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
+ KEBUGCHECK(0);
ObfDereferenceObject(PrimaryToken);
ObfDereferenceObject(Thread);
if (!NT_SUCCESS(Status))