From 352d524633f59a73e9abcff074ab19c6af17dbad Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 3 Jan 2005 23:02:15 +0000 Subject: [PATCH] Rewrite ROS Critical Section implementation, which was slow and broken (because it always created an event, which is the slow path). Note that coincidentally, Gunnar also fixed this code and committed a patch this morning, taken from WINE. This code is also based on WINE, but adds more features which WINE does not support/need yet (regarding Debug CS). Hence, this code was a re-write of the original ROS code, not of Gunnar's, and we've both discussed the accidental conflict. svn path=/trunk/; revision=12766 --- reactos/include/funcs.h | 2 - reactos/include/ntdll/rtl.h | 43 +- reactos/lib/advapi32/reg/reg.c | 4 +- reactos/lib/kernel32/include/kernel32.h | 2 +- reactos/lib/kernel32/misc/console.c | 4 +- reactos/lib/kernel32/misc/dllmain.c | 6 +- reactos/lib/kernel32/misc/lcformat.c | 6 +- reactos/lib/kernel32/misc/nls.c | 2 +- reactos/lib/kernel32/misc/profile.c | 6 +- reactos/lib/kernel32/synch/critical.c | 6 +- reactos/lib/ntdll/ldr/startup.c | 10 +- reactos/lib/ntdll/rtl/critical.c | 795 ++++++++++++--------- reactos/subsys/csrss/api/process.c | 4 +- reactos/subsys/csrss/include/api.h | 2 +- reactos/subsys/csrss/win32csr/conio.c | 16 +- reactos/subsys/csrss/win32csr/dllmain.c | 2 +- reactos/subsys/csrss/win32csr/guiconsole.c | 2 +- 17 files changed, 542 insertions(+), 370 deletions(-) diff --git a/reactos/include/funcs.h b/reactos/include/funcs.h index 8b7cdbfdce2..573b18eecd6 100644 --- a/reactos/include/funcs.h +++ b/reactos/include/funcs.h @@ -2082,8 +2082,6 @@ VOID STDCALL WEP(); DWORD STDCALL RtlDeleteSecurityObject(DWORD x1); DWORD STDCALL RtlNewSecurityObject(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6); NTSTATUS STDCALL RtlWalkHeap( HANDLE heap, PVOID entry_ptr ); -NTSTATUS STDCALL RtlpUnWaitCriticalSection(RTL_CRITICAL_SECTION *crit); -NTSTATUS STDCALL RtlpWaitForCriticalSection(RTL_CRITICAL_SECTION *crit); NTSTATUS STDCALL LdrLockLoaderLock(ULONG flags, ULONG *result, ULONG *magic); NTSTATUS STDCALL LdrUnlockLoaderLock(ULONG flags, ULONG magic); diff --git a/reactos/include/ntdll/rtl.h b/reactos/include/ntdll/rtl.h index c400129f009..6cd6ada5f7c 100644 --- a/reactos/include/ntdll/rtl.h +++ b/reactos/include/ntdll/rtl.h @@ -99,8 +99,8 @@ typedef struct _CRITICAL_SECTION_DEBUG LIST_ENTRY ProcessLocksList; ULONG EntryCount; ULONG ContentionCount; - ULONG Depth; - PVOID Spare[ 2 ]; + PVOID OwnerBackTrace[2]; + PVOID Spare[2]; } CRITICAL_SECTION_DEBUG, *PCRITICAL_SECTION_DEBUG; @@ -114,9 +114,13 @@ typedef struct _CRITICAL_SECTION ULONG_PTR SpinCount; } CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION; +#define RTL_CRITSECT_TYPE 0 + typedef CRITICAL_SECTION RTL_CRITICAL_SECTION; typedef PCRITICAL_SECTION PRTL_CRITICAL_SECTION; typedef LPCRITICAL_SECTION LPRTL_CRITICAL_SECTION; +typedef CRITICAL_SECTION_DEBUG RTL_CRITICAL_SECTION_DEBUG; +typedef PCRITICAL_SECTION_DEBUG PRTL_CRITICAL_SECTION_DEBUG; #endif /* !__USE_W32API */ @@ -166,6 +170,29 @@ typedef struct _RTL_HANDLE_TABLE #define PDI_HEAP_BLOCKS 0x10 /* The heap blocks */ #define PDI_LOCKS 0x20 /* The locks created by the process */ +NTSTATUS +STDCALL +RtlpWaitForCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection +); + +VOID +STDCALL +RtlpUnWaitCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection +); + +VOID +STDCALL +RtlpCreateCriticalSectionSem( + PRTL_CRITICAL_SECTION CriticalSection +); + +VOID +STDCALL +RtlpInitDeferedCriticalSection( + VOID +); NTSTATUS STDCALL RtlAddAccessAllowedAceEx (IN OUT PACL Acl, @@ -191,19 +218,19 @@ RtlAddAuditAccessAceEx(IN OUT PACL Acl, IN BOOLEAN Failure); NTSTATUS STDCALL -RtlDeleteCriticalSection (PCRITICAL_SECTION CriticalSection); +RtlDeleteCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); WCHAR STDCALL RtlDowncaseUnicodeChar(IN WCHAR Source); NTSTATUS STDCALL -RtlEnterCriticalSection (PCRITICAL_SECTION CriticalSection); +RtlEnterCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); NTSTATUS STDCALL -RtlInitializeCriticalSection (PCRITICAL_SECTION CriticalSection); +RtlInitializeCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); NTSTATUS STDCALL -RtlInitializeCriticalSectionAndSpinCount (PCRITICAL_SECTION CriticalSection, +RtlInitializeCriticalSectionAndSpinCount (PRTL_CRITICAL_SECTION CriticalSection, ULONG SpinCount); NTSTATUS STDCALL @@ -212,10 +239,10 @@ RtlInt64ToUnicodeString (IN ULONGLONG Value, PUNICODE_STRING String); NTSTATUS STDCALL -RtlLeaveCriticalSection (PCRITICAL_SECTION CriticalSection); +RtlLeaveCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); BOOLEAN STDCALL -RtlTryEnterCriticalSection (PCRITICAL_SECTION CriticalSection); +RtlTryEnterCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); DWORD STDCALL RtlCompactHeap ( diff --git a/reactos/lib/advapi32/reg/reg.c b/reactos/lib/advapi32/reg/reg.c index f45d64645dd..9c6a668a95b 100644 --- a/reactos/lib/advapi32/reg/reg.c +++ b/reactos/lib/advapi32/reg/reg.c @@ -1,4 +1,4 @@ -/* $Id: reg.c,v 1.67 2004/12/26 23:09:51 gvg Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -24,7 +24,7 @@ /* GLOBALS ******************************************************************/ -static CRITICAL_SECTION HandleTableCS; +static RTL_CRITICAL_SECTION HandleTableCS; static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES]; static HANDLE ProcessHeap; diff --git a/reactos/lib/kernel32/include/kernel32.h b/reactos/lib/kernel32/include/kernel32.h index 26e3784c743..b4515c0ebc3 100755 --- a/reactos/lib/kernel32/include/kernel32.h +++ b/reactos/lib/kernel32/include/kernel32.h @@ -39,7 +39,7 @@ extern HANDLE hProcessHeap; extern HANDLE hBaseDir; extern HMODULE hCurrentModule; -extern CRITICAL_SECTION DllLock; +extern RTL_CRITICAL_SECTION DllLock; extern UNICODE_STRING DllDirectory; diff --git a/reactos/lib/kernel32/misc/console.c b/reactos/lib/kernel32/misc/console.c index bea635dd3de..0eb896d0ed9 100644 --- a/reactos/lib/kernel32/misc/console.c +++ b/reactos/lib/kernel32/misc/console.c @@ -1,4 +1,4 @@ -/* $Id: console.c,v 1.89 2004/12/24 17:45:57 weiden Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -21,7 +21,7 @@ extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event); extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag); -extern CRITICAL_SECTION ConsoleLock; +extern RTL_CRITICAL_SECTION ConsoleLock; extern BOOL WINAPI IsDebuggerPresent(VOID); diff --git a/reactos/lib/kernel32/misc/dllmain.c b/reactos/lib/kernel32/misc/dllmain.c index 85b08900827..6431ff04873 100644 --- a/reactos/lib/kernel32/misc/dllmain.c +++ b/reactos/lib/kernel32/misc/dllmain.c @@ -1,4 +1,4 @@ -/* $Id: dllmain.c,v 1.38 2004/11/29 00:08:59 gdalsnes Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -33,8 +33,8 @@ DllMain(HANDLE hInst, LPVOID lpReserved); /* Critical section for various kernel32 data structures */ -CRITICAL_SECTION DllLock; -CRITICAL_SECTION ConsoleLock; +RTL_CRITICAL_SECTION DllLock; +RTL_CRITICAL_SECTION ConsoleLock; extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event); diff --git a/reactos/lib/kernel32/misc/lcformat.c b/reactos/lib/kernel32/misc/lcformat.c index 043447a0142..c07b95890d4 100644 --- a/reactos/lib/kernel32/misc/lcformat.c +++ b/reactos/lib/kernel32/misc/lcformat.c @@ -82,15 +82,15 @@ typedef struct _NLS_FORMAT_NODE #define GetShortMonth(fmt,mth) fmt->lppszStrings[30 + mth] /* Write access to the cache is protected by this critical section */ -static CRITICAL_SECTION NLS_FormatsCS; -static CRITICAL_SECTION_DEBUG NLS_FormatsCS_debug = +static RTL_CRITICAL_SECTION NLS_FormatsCS; +static RTL_CRITICAL_SECTION_DEBUG NLS_FormatsCS_debug = { 0, 0, &NLS_FormatsCS, { &NLS_FormatsCS_debug.ProcessLocksList, &NLS_FormatsCS_debug.ProcessLocksList }, 0, 0, { 0, (DWORD)(__FILE__ ": NLS_Formats") } }; -static CRITICAL_SECTION NLS_FormatsCS = { &NLS_FormatsCS_debug, -1, 0, 0, 0, 0 }; +static RTL_CRITICAL_SECTION NLS_FormatsCS = { &NLS_FormatsCS_debug, -1, 0, 0, 0, 0 }; /************************************************************************** * NLS_GetLocaleNumber diff --git a/reactos/lib/kernel32/misc/nls.c b/reactos/lib/kernel32/misc/nls.c index 259d3134231..8ecee401051 100755 --- a/reactos/lib/kernel32/misc/nls.c +++ b/reactos/lib/kernel32/misc/nls.c @@ -58,7 +58,7 @@ static const unsigned char UTF8Mask[6] = {0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; static LIST_ENTRY CodePageListHead; static CODEPAGE_ENTRY AnsiCodePage; static CODEPAGE_ENTRY OemCodePage; -static CRITICAL_SECTION CodePageListLock; +static RTL_CRITICAL_SECTION CodePageListLock; /* FORWARD DECLARATIONS *******************************************************/ diff --git a/reactos/lib/kernel32/misc/profile.c b/reactos/lib/kernel32/misc/profile.c index 406b90fd92b..fdb9ac4276f 100644 --- a/reactos/lib/kernel32/misc/profile.c +++ b/reactos/lib/kernel32/misc/profile.c @@ -72,14 +72,14 @@ static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL}; static const WCHAR emptystringW[] = {0}; -static CRITICAL_SECTION PROFILE_CritSect; -static CRITICAL_SECTION_DEBUG critsect_debug = +static RTL_CRITICAL_SECTION PROFILE_CritSect; +static RTL_CRITICAL_SECTION_DEBUG critsect_debug = { 0, 0, &PROFILE_CritSect, { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, 0, 0, { 0, (DWORD)(__FILE__ ": PROFILE_CritSect") } }; -static CRITICAL_SECTION PROFILE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 }; +static RTL_CRITICAL_SECTION PROFILE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 }; static const char hex[16] = "0123456789ABCDEF"; diff --git a/reactos/lib/kernel32/synch/critical.c b/reactos/lib/kernel32/synch/critical.c index 708d8238b62..87810c8e021 100644 --- a/reactos/lib/kernel32/synch/critical.c +++ b/reactos/lib/kernel32/synch/critical.c @@ -1,4 +1,4 @@ -/* $Id: critical.c,v 1.16 2004/01/29 23:41:36 navaraf Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -26,7 +26,7 @@ InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) { NTSTATUS Status; - Status = RtlInitializeCriticalSection(lpCriticalSection); + Status = RtlInitializeCriticalSection((PRTL_CRITICAL_SECTION)lpCriticalSection); if (!NT_SUCCESS(Status)) { RtlRaiseStatus(Status); @@ -45,7 +45,7 @@ InitializeCriticalSectionAndSpinCount( { NTSTATUS Status; - Status = RtlInitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount); + Status = RtlInitializeCriticalSectionAndSpinCount((PRTL_CRITICAL_SECTION)lpCriticalSection, dwSpinCount); if (Status) { RtlRaiseStatus(Status); diff --git a/reactos/lib/ntdll/ldr/startup.c b/reactos/lib/ntdll/ldr/startup.c index a88701ea3f5..821842bb384 100644 --- a/reactos/lib/ntdll/ldr/startup.c +++ b/reactos/lib/ntdll/ldr/startup.c @@ -1,4 +1,4 @@ -/* $Id: startup.c,v 1.60 2004/12/15 03:00:33 royce Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -259,6 +259,7 @@ __true_LdrInitializeThunk (ULONG Unknown1, /* If MZ header exists */ PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase; DPRINT("PEDosHeader %x\n", PEDosHeader); + if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC || PEDosHeader->e_lfanew == 0L || *(PULONG)((PUCHAR)ImageBase + PEDosHeader->e_lfanew) != IMAGE_PE_MAGIC) @@ -279,6 +280,9 @@ __true_LdrInitializeThunk (ULONG Unknown1, NTHeaders = (PIMAGE_NT_HEADERS)(ImageBase + PEDosHeader->e_lfanew); + /* Initialize Critical Section Data */ + RtlpInitDeferedCriticalSection(); + /* create process heap */ RtlInitializeHeapManager(); Peb->ProcessHeap = RtlCreateHeap(HEAP_GROWABLE, @@ -292,7 +296,7 @@ __true_LdrInitializeThunk (ULONG Unknown1, DPRINT1("Failed to create process heap\n"); ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); } - + /* initalize peb lock support */ RtlInitializeCriticalSection (&PebLock); Peb->FastPebLock = &PebLock; @@ -311,7 +315,7 @@ __true_LdrInitializeThunk (ULONG Unknown1, RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(PVOID) * (USER32_CALLBACK_MAXIMUM + 1)); - + /* initalize loader lock */ RtlInitializeCriticalSection (&LoaderLock); Peb->LoaderLock = &LoaderLock; diff --git a/reactos/lib/ntdll/rtl/critical.c b/reactos/lib/ntdll/rtl/critical.c index 94a533179b9..2e9002533ec 100644 --- a/reactos/lib/ntdll/rtl/critical.c +++ b/reactos/lib/ntdll/rtl/critical.c @@ -6,6 +6,8 @@ * PURPOSE: Critical sections * UPDATE HISTORY: * Created 30/09/98 + * Rewritten ROS version, based on WINE code plus + * some fixes useful only for ROS right now - 03/01/05 */ /* INCLUDES ******************************************************************/ @@ -19,391 +21,532 @@ /* FUNCTIONS *****************************************************************/ -inline static HANDLE RtlGetCurrentThreadId() +static RTL_CRITICAL_SECTION RtlCriticalSectionLock; +static LIST_ENTRY RtlCriticalSectionList; +static BOOLEAN RtlpCritSectInitialized = FALSE; + +/*++ + * RtlDeleteCriticalSection + * @implemented NT4 + * + * Deletes a Critical Section + * + * Params: + * CriticalSection - Critical section to delete. + * + * Returns: + * STATUS_SUCCESS, or error value returned by NtClose. + * + * Remarks: + * The critical section members should not be read after this call. + * + *--*/ +NTSTATUS +STDCALL +RtlDeleteCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) { - return (HANDLE)NtCurrentTeb()->Cid.UniqueThread; + NTSTATUS Status = STATUS_SUCCESS; + + /* Close the Event Object Handle if it exists */ + if (CriticalSection->LockSemaphore) { + Status = NtClose(CriticalSection->LockSemaphore); + } + + /* Protect List */ + RtlEnterCriticalSection(&RtlCriticalSectionLock); + + /* Delete the Debug Data, if it exists */ + if (CriticalSection->DebugInfo) { + + /* Remove it from the list */ + RemoveEntryList(&CriticalSection->DebugInfo->ProcessLocksList); + + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, CriticalSection->DebugInfo); + } + + /* Unprotect */ + RtlLeaveCriticalSection(&RtlCriticalSectionLock); + + /* Wipe it out */ + RtlZeroMemory(CriticalSection, sizeof(RTL_CRITICAL_SECTION)); + + /* Return */ + return Status; } -inline static void small_pause(void) -{ -#ifdef __i386__ - __asm__ __volatile__( "rep;nop" : : : "memory" ); -#else - __asm__ __volatile__( "" : : : "memory" ); -#endif +/*++ + * RtlSetCriticalSectionSpinCount + * @implemented NT4 + * + * Sets the spin count for a critical section. + * + * Params: + * CriticalSection - Critical section to set the spin count for. + * + * SpinCount - Spin count for the critical section. + * + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * SpinCount is ignored on single-processor systems. + * + *--*/ +DWORD +STDCALL +RtlSetCriticalSectionSpinCount( + PRTL_CRITICAL_SECTION CriticalSection, + DWORD SpinCount + ) +{ + DWORD OldCount = CriticalSection->SpinCount; + + /* Set to parameter if MP, or to 0 if this is Uniprocessor */ + CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0; + return OldCount; } -/*********************************************************************** - * get_semaphore - */ -static inline HANDLE get_semaphore( PCRITICAL_SECTION crit ) +/*++ + * RtlEnterCriticalSection + * @implemented NT4 + * + * Waits to gain ownership of the critical section. + * + * Params: + * CriticalSection - Critical section to wait for. + * + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * Uses a fast-path unless contention happens. + * + *--*/ +NTSTATUS +STDCALL +RtlEnterCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) { - HANDLE ret = crit->LockSemaphore; - if (!ret) - { - HANDLE sem; - if (!NT_SUCCESS(NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 ))) return 0; - if (!(ret = (HANDLE)InterlockedCompareExchangePointer( (PVOID *)&crit->LockSemaphore, - (PVOID)sem, 0 ))) - ret = sem; - else - NtClose(sem); /* somebody beat us to it */ - } - return ret; + HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread; + + /* Try to Lock it */ + if (InterlockedIncrement(&CriticalSection->LockCount)) { + + /* + * We've failed to lock it! Does this thread + * actually own it? + */ + if (Thread == CriticalSection->OwningThread) { + + /* You own it, so you'll get it when you're done with it! */ + CriticalSection->RecursionCount++; + return STATUS_SUCCESS; + } + + /* We don't own it, so we must wait for it */ + RtlpWaitForCriticalSection(CriticalSection); + } + + /* Lock successful */ + CriticalSection->OwningThread = Thread; + CriticalSection->RecursionCount = 1; + return STATUS_SUCCESS; } -/*********************************************************************** - * RtlInitializeCriticalSection (NTDLL.@) +/*++ + * RtlInitializeCriticalSection + * @implemented NT4 * - * Initialises a new critical section. + * Initialises a new critical section. * - * PARAMS - * crit [O] Critical section to initialise + * Params: + * CriticalSection - Critical section to initialise * - * RETURNS - * STATUS_SUCCESS. + * Returns: + * STATUS_SUCCESS. * - * SEE - * RtlInitializeCriticalSectionAndSpinCount(), RtlDeleteCriticalSection(), - * RtlEnterCriticalSection(), RtlLeaveCriticalSection(), - * RtlTryEnterCriticalSection(), RtlSetCriticalSectionSpinCount() - */ -NTSTATUS STDCALL RtlInitializeCriticalSection( PCRITICAL_SECTION crit ) -{ - return RtlInitializeCriticalSectionAndSpinCount( crit, 0 ); + * Remarks: + * Simply calls RtlInitializeCriticalSectionAndSpinCount + * + *--*/ +NTSTATUS +STDCALL +RtlInitializeCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) +{ + /* Call the Main Function */ + return RtlInitializeCriticalSectionAndSpinCount(CriticalSection, 0); } -/*********************************************************************** - * RtlInitializeCriticalSectionAndSpinCount (NTDLL.@) +/*++ + * RtlInitializeCriticalSectionAndSpinCount + * @implemented NT4 * - * Initialises a new critical section with a given spin count. + * Initialises a new critical section. * - * PARAMS - * crit [O] Critical section to initialise - * spincount [I] Spin count for crit - * - * RETURNS - * STATUS_SUCCESS. + * Params: + * CriticalSection - Critical section to initialise * - * NOTES - * Available on NT4 SP3 or later. + * SpinCount - Spin count for the critical section. * - * SEE - * RtlInitializeCriticalSection(), RtlDeleteCriticalSection(), - * RtlEnterCriticalSection(), RtlLeaveCriticalSection(), - * RtlTryEnterCriticalSection(), RtlSetCriticalSectionSpinCount() - */ -NTSTATUS STDCALL RtlInitializeCriticalSectionAndSpinCount( PCRITICAL_SECTION crit, ULONG spincount ) + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * SpinCount is ignored on single-processor systems. + * + *--*/ +NTSTATUS +STDCALL +RtlInitializeCriticalSectionAndSpinCount ( + PRTL_CRITICAL_SECTION CriticalSection, + DWORD SpinCount) { - /* Does ROS need this, or is this special to Wine? And if ros need it, should - it be enabled in the release build? -Gunnar */ - if (RtlGetProcessHeap()) crit->DebugInfo = NULL; - else - { - crit->DebugInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(CRITICAL_SECTION_DEBUG)); - if (crit->DebugInfo) - { - crit->DebugInfo->Type = 0; - crit->DebugInfo->CreatorBackTraceIndex = 0; - crit->DebugInfo->CriticalSection = crit; - crit->DebugInfo->ProcessLocksList.Blink = &(crit->DebugInfo->ProcessLocksList); - crit->DebugInfo->ProcessLocksList.Flink = &(crit->DebugInfo->ProcessLocksList); - crit->DebugInfo->EntryCount = 0; - crit->DebugInfo->ContentionCount = 0; - crit->DebugInfo->Spare[0] = 0; - crit->DebugInfo->Spare[1] = 0; - } - } - crit->LockCount = -1; - crit->RecursionCount = 0; - crit->OwningThread = 0; - crit->LockSemaphore = 0; - crit->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? spincount : 0; - return STATUS_SUCCESS; + PRTL_CRITICAL_SECTION_DEBUG CritcalSectionDebugData; + PVOID Heap; + + /* First things first, set up the Object */ + CriticalSection->LockCount = -1; + CriticalSection->RecursionCount = 0; + CriticalSection->OwningThread = 0; + CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0; + + /* + * Now set up the Debug Data + * Think of a better way to allocate it, because the Heap Manager won't + * have any debug data since the Heap isn't initalized! + */ + if ((Heap = RtlGetProcessHeap())) { + + CritcalSectionDebugData = RtlAllocateHeap(Heap, 0, sizeof(RTL_CRITICAL_SECTION_DEBUG)); + CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE; + CritcalSectionDebugData->ContentionCount = 0; + CritcalSectionDebugData->EntryCount = 0; + CritcalSectionDebugData->CriticalSection = CriticalSection; + CriticalSection->DebugInfo = CritcalSectionDebugData; + + /* + * Add it to the List of Critical Sections owned by the process. + * If we've initialized the Lock, then use it. If not, then probably + * this is the lock initialization itself, so insert it directly. + */ + if ((CriticalSection != &RtlCriticalSectionLock) && (RtlpCritSectInitialized)) { + + /* Protect List */ + RtlEnterCriticalSection(&RtlCriticalSectionLock); + + /* Add this one */ + InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); + + /* Unprotect */ + RtlLeaveCriticalSection(&RtlCriticalSectionLock); + + } else { + + /* Add it directly */ + InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); + } + + } else { + + /* This shouldn't happen... */ + CritcalSectionDebugData = NULL; + } + + return STATUS_SUCCESS; } -/*********************************************************************** - * RtlSetCriticalSectionSpinCount (NTDLL.@) +/*++ + * RtlLeaveCriticalSection + * @implemented NT4 * - * Sets the spin count of a critical section. + * Releases a critical section and makes if available for new owners. * - * PARAMS - * crit [I/O] Critical section - * spincount [I] Spin count for crit + * Params: + * CriticalSection - Critical section to release. * - * RETURNS - * The previous spin count. + * Returns: + * STATUS_SUCCESS. * - * NOTES - * If the system is not SMP, spincount is ignored and set to 0. + * Remarks: + * If another thread was waiting, the slow path is entered. * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), - * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() - */ -ULONG STDCALL RtlSetCriticalSectionSpinCount( PCRITICAL_SECTION crit, ULONG spincount ) -{ - ULONG oldspincount = crit->SpinCount; - crit->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? spincount : 0; - return oldspincount; + *--*/ +NTSTATUS +STDCALL +RtlLeaveCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) +{ + /* Decrease the Recursion Count */ + if (--CriticalSection->RecursionCount) { + + /* Someone still owns us, but we are free */ + InterlockedDecrement(&CriticalSection->LockCount); + + } else { + + /* Nobody owns us anymore */ + CriticalSection->OwningThread = 0; + + /* Was someone wanting us? */ + if (InterlockedDecrement(&CriticalSection->LockCount) >= 0) { + + /* Let him have us */ + RtlpUnWaitCriticalSection(CriticalSection); + + } + } + + /* Sucessful! */ + return STATUS_SUCCESS; } -/*********************************************************************** - * RtlDeleteCriticalSection (NTDLL.@) +/*++ + * RtlTryEnterCriticalSection + * @implemented NT4 * - * Frees the resources used by a critical section. + * Attemps to gain ownership of the critical section without waiting. * - * PARAMS - * crit [I/O] Critical section to free + * Params: + * CriticalSection - Critical section to attempt acquiring. * - * RETURNS - * STATUS_SUCCESS. + * Returns: + * TRUE if the critical section has been acquired, FALSE otherwise. * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), - * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() - */ -NTSTATUS STDCALL RtlDeleteCriticalSection( PCRITICAL_SECTION crit ) -{ - crit->LockCount = -1; - crit->RecursionCount = 0; - crit->OwningThread = (HANDLE)0; - if (crit->LockSemaphore) - NtClose( crit->LockSemaphore ); - crit->LockSemaphore = 0; - if (crit->DebugInfo) - { - /* only free the ones we made in here */ - if (!crit->DebugInfo->Spare[1]) - { - RtlFreeHeap( RtlGetProcessHeap(), 0, crit->DebugInfo ); - crit->DebugInfo = NULL; - } - } - return STATUS_SUCCESS; + * Remarks: + * None + * + *--*/ +BOOLEAN +STDCALL +RtlTryEnterCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) +{ + /* Try to take control */ + if (InterlockedCompareExchange(&CriticalSection->LockCount, + 0, + -1) == -1) { + + /* It's ours */ + CriticalSection->OwningThread = NtCurrentTeb()->Cid.UniqueThread; + CriticalSection->RecursionCount = 1; + return TRUE; + + } else if (CriticalSection->OwningThread == NtCurrentTeb()->Cid.UniqueThread) { + + /* It's already ours */ + InterlockedIncrement(&CriticalSection->LockCount); + CriticalSection->RecursionCount++; + return TRUE; + } + + /* It's not ours */ + return FALSE; } - -/*********************************************************************** - * RtlpWaitForCriticalSection (NTDLL.@) +/*++ + * RtlpWaitForCriticalSection * - * Waits for a busy critical section to become free. - * - * PARAMS - * crit [I/O] Critical section to wait for + * Slow path of RtlEnterCriticalSection. Waits on an Event Object. * - * RETURNS - * STATUS_SUCCESS. + * Params: + * CriticalSection - Critical section to acquire. * - * NOTES - * Use RtlEnterCriticalSection() instead of this function as it is often much - * faster. + * Returns: + * STATUS_SUCCESS, or raises an exception if a deadlock is occuring. * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), - * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() - */ -NTSTATUS STDCALL RtlpWaitForCriticalSection( PCRITICAL_SECTION crit ) + * Remarks: + * None + * + *--*/ +NTSTATUS +STDCALL +RtlpWaitForCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) { - for (;;) - { - EXCEPTION_RECORD rec; - HANDLE sem = get_semaphore( crit ); - LARGE_INTEGER time; - NTSTATUS status; - - time.QuadPart = -5000 * 10000; /* 5 seconds */ - status = NtWaitForSingleObject( sem, FALSE, &time ); - if ( status == STATUS_TIMEOUT ) - { - const char *name = NULL; - if (crit->DebugInfo) name = (char *)crit->DebugInfo->Spare[1]; - if (!name) name = "?"; - DPRINT1( "section %p %s wait timed out in thread %04lx, blocked by %04lx, retrying (60 sec)\n", - crit, name, RtlGetCurrentThreadId(), (DWORD)crit->OwningThread ); - time.QuadPart = -60000 * 10000; - status = NtWaitForSingleObject( sem, FALSE, &time ); - if ( status == STATUS_TIMEOUT /*&& TRACE_ON(relay)*/ ) - { - DPRINT1( "section %p %s wait timed out in thread %04lx, blocked by %04lx, retrying (5 min)\n", - crit, name, RtlGetCurrentThreadId(), (DWORD) crit->OwningThread ); - time.QuadPart = -300000 * (ULONGLONG)10000; - status = NtWaitForSingleObject( sem, FALSE, &time ); - } - } - if (status == STATUS_WAIT_0) return STATUS_SUCCESS; - - /* Throw exception only for Wine internal locks */ - if ((!crit->DebugInfo) || (!crit->DebugInfo->Spare[1])) continue; - - rec.ExceptionCode = STATUS_POSSIBLE_DEADLOCK; - rec.ExceptionFlags = 0; - rec.ExceptionRecord = NULL; - rec.ExceptionAddress = RtlRaiseException; /* sic */ - rec.NumberParameters = 1; - rec.ExceptionInformation[0] = (DWORD)crit; - RtlRaiseException( &rec ); - } + NTSTATUS Status; + EXCEPTION_RECORD ExceptionRecord; + BOOLEAN LastChance = FALSE; + LARGE_INTEGER Timeout; + + Timeout = RtlConvertLongToLargeInteger(150000); + /* ^^ HACK HACK HACK. Good way: + Timeout = &NtCurrentPeb()->CriticalSectionTimeout */ + + /* Do we have an Event yet? */ + if (!CriticalSection->LockSemaphore) { + RtlpCreateCriticalSectionSem(CriticalSection); + } + + /* Increase the Debug Entry count */ + CriticalSection->DebugInfo->EntryCount++; + + for (;;) { + + /* Increase the number of times we've had contention */ + CriticalSection->DebugInfo->ContentionCount++; + + /* Wait on the Event */ + Status = NtWaitForSingleObject(CriticalSection->LockSemaphore, + FALSE, + &Timeout); + + /* We have Timed out */ + if (Status == STATUS_TIMEOUT) { + + /* Is this the 2nd time we've timed out? */ + if (LastChance) { + + /* Yes it is, we are raising an exception */ + ExceptionRecord.ExceptionCode = STATUS_POSSIBLE_DEADLOCK; + ExceptionRecord.ExceptionFlags = 0; + ExceptionRecord.ExceptionRecord = NULL; + ExceptionRecord.ExceptionAddress = RtlRaiseException; + ExceptionRecord.NumberParameters = 1; + ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR)CriticalSection; + RtlRaiseException(&ExceptionRecord); + + } + + /* One more try */ + LastChance = TRUE; + + } else { + + /* If we are here, everything went fine */ + return STATUS_SUCCESS; + } + } } - -/*********************************************************************** - * RtlpUnWaitCriticalSection (NTDLL.@) +/*++ + * RtlpUnWaitCriticalSection * - * Notifies other threads waiting on the busy critical section that it has - * become free. - * - * PARAMS - * crit [I/O] Critical section + * Slow path of RtlLeaveCriticalSection. Fires an Event Object. * - * RETURNS - * Success: STATUS_SUCCESS. - * Failure: Any error returned by NtReleaseSemaphore() + * Params: + * CriticalSection - Critical section to release. * - * NOTES - * Use RtlLeaveCriticalSection() instead of this function as it is often much - * faster. + * Returns: + * None. Raises an exception if the system call failed. * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), - * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() - */ -NTSTATUS STDCALL RtlpUnWaitCriticalSection( PCRITICAL_SECTION crit ) + * Remarks: + * None + * + *--*/ +VOID +STDCALL +RtlpUnWaitCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) + { - HANDLE sem = get_semaphore( crit ); - NTSTATUS res = NtReleaseSemaphore( sem, 1, NULL ); - if (!NT_SUCCESS(res)) RtlRaiseStatus( res ); - return res; + NTSTATUS Status; + + /* Do we have an Event yet? */ + if (!CriticalSection->LockSemaphore) { + RtlpCreateCriticalSectionSem(CriticalSection); + } + + /* Signal the Event */ + Status = NtSetEvent(CriticalSection->LockSemaphore, NULL); + + if (!NT_SUCCESS(Status)) { + + /* We've failed */ + RtlRaiseStatus(Status); + } } - -/*********************************************************************** - * RtlEnterCriticalSection (NTDLL.@) +/*++ + * RtlpCreateCriticalSectionSem * - * Enters a critical section, waiting for it to become available if necessary. + * Checks if an Event has been created for the critical section. * - * PARAMS - * crit [I/O] Critical section to enter + * Params: + * None * - * RETURNS - * STATUS_SUCCESS. The critical section is held by the caller. - * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlSetCriticalSectionSpinCount(), - * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() - */ -NTSTATUS STDCALL RtlEnterCriticalSection( PCRITICAL_SECTION crit ) + * Returns: + * None. Raises an exception if the system call failed. + * + * Remarks: + * None + * + *--*/ +VOID +STDCALL +RtlpCreateCriticalSectionSem( + PRTL_CRITICAL_SECTION CriticalSection) { - if (crit->SpinCount) - { - ULONG count; - - if (RtlTryEnterCriticalSection( crit )) return STATUS_SUCCESS; - for (count = crit->SpinCount; count > 0; count--) - { - if (crit->LockCount > 0) break; /* more than one waiter, don't bother spinning */ - if (crit->LockCount == -1) /* try again */ - { - if (InterlockedCompareExchange(&crit->LockCount, 0,-1 ) == -1) goto done; - } - small_pause(); - } - } - - if (InterlockedIncrement( &crit->LockCount )) - { - if (crit->OwningThread == (HANDLE)RtlGetCurrentThreadId()) - { - crit->RecursionCount++; - return STATUS_SUCCESS; - } - - /* Now wait for it */ - RtlpWaitForCriticalSection( crit ); - } -done: - crit->OwningThread = (HANDLE)RtlGetCurrentThreadId(); - crit->RecursionCount = 1; - return STATUS_SUCCESS; + HANDLE hEvent = CriticalSection->LockSemaphore; + HANDLE hNewEvent; + NTSTATUS Status; + + /* Chevk if we have an event */ + if (!hEvent) { + + /* No, so create it */ + if (NT_SUCCESS(Status = NtCreateEvent(hNewEvent, + EVENT_ALL_ACCESS, + NULL, + SynchronizationEvent, + FALSE))) { + + /* We failed, this is bad... */ + InterlockedDecrement(&CriticalSection->LockCount); + RtlRaiseStatus(Status); + return; + } + + if (!(hEvent = InterlockedCompareExchangePointer((PVOID*)&CriticalSection->LockSemaphore, + (PVOID)hNewEvent, + 0))) { + + /* We created a new event succesffuly */ + hEvent = hNewEvent; + } else { + + /* Some just created an event */ + NtClose(hNewEvent); + } + + /* Set either the new or the old */ + CriticalSection->LockSemaphore = hEvent; + } + + return; } - -/*********************************************************************** - * RtlTryEnterCriticalSection (NTDLL.@) +/*++ + * RtlpInitDeferedCriticalSection * - * Tries to enter a critical section without waiting. + * Initializes the Critical Section implementation. * - * PARAMS - * crit [I/O] Critical section to enter + * Params: + * None * - * RETURNS - * Success: TRUE. The critical section is held by the caller. - * Failure: FALSE. The critical section is currently held by another thread. + * Returns: + * None. * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), - * RtlLeaveCriticalSection(), RtlSetCriticalSectionSpinCount() - */ -BOOLEAN STDCALL RtlTryEnterCriticalSection( PCRITICAL_SECTION crit ) + * Remarks: + * After this call, the Process Critical Section list is protected. + * + *--*/ +VOID +STDCALL +RtlpInitDeferedCriticalSection( + VOID) { - BOOL ret = FALSE; - if (InterlockedCompareExchange(&crit->LockCount, 0L, -1 ) == -1) - { - crit->OwningThread = (HANDLE)RtlGetCurrentThreadId(); - crit->RecursionCount = 1; - ret = TRUE; - } - else if (crit->OwningThread == (HANDLE)RtlGetCurrentThreadId()) - { - InterlockedIncrement( &crit->LockCount ); - crit->RecursionCount++; - ret = TRUE; - } - return ret; + + /* Initialize the Process Critical Section List */ + InitializeListHead(&RtlCriticalSectionList); + + /* Initialize the CS Protecting the List */ + RtlInitializeCriticalSection(&RtlCriticalSectionLock); + + /* It's now safe to enter it */ + RtlpCritSectInitialized = TRUE; } - -/*********************************************************************** - * RtlLeaveCriticalSection (NTDLL.@) - * - * Leaves a critical section. - * - * PARAMS - * crit [I/O] Critical section to leave. - * - * RETURNS - * STATUS_SUCCESS. - * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), - * RtlSetCriticalSectionSpinCount(), RtlTryEnterCriticalSection() - */ -NTSTATUS STDCALL RtlLeaveCriticalSection( PCRITICAL_SECTION crit ) -{ - if (crit->OwningThread != RtlGetCurrentThreadId()) - { - DPRINT1("Freeing critical section not owned\n"); - } - - if (--crit->RecursionCount) InterlockedDecrement( &crit->LockCount ); - else - { - crit->OwningThread = 0; - if (InterlockedDecrement( &crit->LockCount ) >= 0) - { - /* someone is waiting */ - RtlpUnWaitCriticalSection( crit ); - } - } - return STATUS_SUCCESS; -} - - /* EOF */ diff --git a/reactos/subsys/csrss/api/process.c b/reactos/subsys/csrss/api/process.c index e3944eee2d0..e985eeaacf9 100644 --- a/reactos/subsys/csrss/api/process.c +++ b/reactos/subsys/csrss/api/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.39 2004/12/25 22:58:59 gvg Exp $ +/* $Id$ * * reactos/subsys/csrss/api/process.c * @@ -25,7 +25,7 @@ static ULONG NrProcess; static PCSRSS_PROCESS_DATA ProcessData[256]; -CRITICAL_SECTION ProcessDataLock; +RTL_CRITICAL_SECTION ProcessDataLock; /* FUNCTIONS *****************************************************************/ diff --git a/reactos/subsys/csrss/include/api.h b/reactos/subsys/csrss/include/api.h index cfc9749e135..07f6b47e042 100644 --- a/reactos/subsys/csrss/include/api.h +++ b/reactos/subsys/csrss/include/api.h @@ -1,4 +1,4 @@ -/* $Id: api.h,v 1.7 2004/11/14 18:47:10 hbirr Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries diff --git a/reactos/subsys/csrss/win32csr/conio.c b/reactos/subsys/csrss/win32csr/conio.c index 098aba4022c..97ca9e5f4b4 100644 --- a/reactos/subsys/csrss/win32csr/conio.c +++ b/reactos/subsys/csrss/win32csr/conio.c @@ -1,4 +1,4 @@ -/* $Id: conio.c,v 1.19 2004/12/25 11:22:37 navaraf Exp $ +/* $Id$ * * reactos/subsys/csrss/win32csr/conio.c * @@ -139,7 +139,7 @@ CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console, { return STATUS_INSUFFICIENT_RESOURCES; } - RtlInitializeCriticalSection(&Buffer->Header.Lock); + InitializeCriticalSection(&Buffer->Header.Lock); ConioInitScreenBuffer(Console, Buffer); /* initialize buffer to be empty with default attributes */ for (Buffer->CurrentY = 0 ; Buffer->CurrentY < Buffer->MaxY; Buffer->CurrentY++) @@ -193,7 +193,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) return STATUS_UNSUCCESSFUL; } Console->PrivateData = NULL; - RtlInitializeCriticalSection(&Console->Header.Lock); + InitializeCriticalSection(&Console->Header.Lock); GuiMode = DtbgIsDesktopVisible(); if (! GuiMode) { @@ -210,7 +210,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) if (! NT_SUCCESS(Status)) { RtlFreeUnicodeString(&Console->Title); - RtlDeleteCriticalSection(&Console->Header.Lock); + DeleteCriticalSection(&Console->Header.Lock); CloseHandle(Console->ActiveEvent); return Status; } @@ -221,7 +221,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) { ConioCleanupConsole(Console); RtlFreeUnicodeString(&Console->Title); - RtlDeleteCriticalSection(&Console->Header.Lock); + DeleteCriticalSection(&Console->Header.Lock); CloseHandle(Console->ActiveEvent); return STATUS_INSUFFICIENT_RESOURCES; } @@ -230,7 +230,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) { ConioCleanupConsole(Console); RtlFreeUnicodeString(&Console->Title); - RtlDeleteCriticalSection(&Console->Header.Lock); + DeleteCriticalSection(&Console->Header.Lock); CloseHandle(Console->ActiveEvent); HeapFree(Win32CsrApiHeap, 0, NewBuffer); return Status; @@ -956,7 +956,7 @@ VOID STDCALL ConioDeleteScreenBuffer(Object_t *Object) { PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER) Object; - RtlDeleteCriticalSection(&Buffer->Header.Lock); + DeleteCriticalSection(&Buffer->Header.Lock); HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer); HeapFree(Win32CsrApiHeap, 0, Buffer); } @@ -998,7 +998,7 @@ ConioDeleteConsole(Object_t *Object) ConioCleanupConsole(Console); CloseHandle(Console->ActiveEvent); - RtlDeleteCriticalSection(&Console->Header.Lock); + DeleteCriticalSection(&Console->Header.Lock); RtlFreeUnicodeString(&Console->Title); HeapFree(Win32CsrApiHeap, 0, Console); } diff --git a/reactos/subsys/csrss/win32csr/dllmain.c b/reactos/subsys/csrss/win32csr/dllmain.c index 4d1bed57dc5..7fd2f7b6c12 100644 --- a/reactos/subsys/csrss/win32csr/dllmain.c +++ b/reactos/subsys/csrss/win32csr/dllmain.c @@ -1,4 +1,4 @@ -/* $Id: dllmain.c,v 1.9 2004/12/24 17:45:58 weiden Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries diff --git a/reactos/subsys/csrss/win32csr/guiconsole.c b/reactos/subsys/csrss/win32csr/guiconsole.c index 78b53e77cf7..46d5c4bd340 100644 --- a/reactos/subsys/csrss/win32csr/guiconsole.c +++ b/reactos/subsys/csrss/win32csr/guiconsole.c @@ -1,4 +1,4 @@ -/* $Id: guiconsole.c,v 1.26 2004/12/25 11:22:37 navaraf Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries