From f9c3ffa9d19a7a316930617600898adb746215ce Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Tue, 9 Jan 2007 21:48:26 +0000 Subject: [PATCH 01/36] - Heavy cleanup of locking and lookup macros in ob_x.h. - Add calls to ObpInitializeDirectoryLookup where required. - Fixup calls to ObpAcquireDirectoryLockExclusive, but still keep them stubbed out for now. svn path=/trunk/; revision=25403 --- reactos/ntoskrnl/include/internal/ob_x.h | 227 ++++++++++++----------- reactos/ntoskrnl/ob/obhandle.c | 12 +- reactos/ntoskrnl/ob/obinit.c | 5 +- reactos/ntoskrnl/ob/oblife.c | 9 +- reactos/ntoskrnl/ob/obname.c | 17 +- reactos/ntoskrnl/ob/obref.c | 2 +- 6 files changed, 144 insertions(+), 128 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/ob_x.h b/reactos/ntoskrnl/include/internal/ob_x.h index cf7ce2548a8..058be1bfe26 100644 --- a/reactos/ntoskrnl/include/internal/ob_x.h +++ b/reactos/ntoskrnl/include/internal/ob_x.h @@ -8,92 +8,12 @@ #include "ex.h" -#if DBG -VOID -FORCEINLINE -ObpCalloutStart(IN PKIRQL CalloutIrql) -{ - /* Save the callout IRQL */ - *CalloutIrql = KeGetCurrentIrql(); -} - -VOID -FORCEINLINE -ObpCalloutEnd(IN KIRQL CalloutIrql, - IN PCHAR Procedure, - IN POBJECT_TYPE ObjectType, - IN PVOID Object) -{ - /* Detect IRQL change */ - if (CalloutIrql != KeGetCurrentIrql()) - { - /* Print error */ - DbgPrint("OB: ObjectType: %wZ Procedure: %s Object: %08x\n", - &ObjectType->Name, Procedure, Object); - DbgPrint(" Returned at %x IRQL, but was called at %x IRQL\n", - KeGetCurrentIrql(), CalloutIrql); - DbgBreakPoint(); - } -} -#else -VOID -FORCEINLINE -ObpCalloutStart(IN PKIRQL CalloutIrql) -{ - /* No-op */ - UNREFERENCED_PARAMETER(CalloutIrql); -} - -VOID -FORCEINLINE -ObpCalloutEnd(IN KIRQL CalloutIrql, - IN PCHAR Procedure, - IN POBJECT_TYPE ObjectType, - IN PVOID Object) -{ - UNREFERENCED_PARAMETER(CalloutIrql); -} -#endif - -VOID -FORCEINLINE -_ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory, - IN POBP_LOOKUP_CONTEXT Context) -{ - /* It's not, set lock flag */ - Context->LockStateSignature = 0xBBBB1234; - - /* Lock it */ - KeEnterCriticalRegion(); - ExAcquirePushLockShared(&Directory->Lock); - - /* Update lock flag */ - Context->LockStateSignature = 0xDDDD1234; -} - -VOID -FORCEINLINE -_ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory, - IN POBP_LOOKUP_CONTEXT Context) -{ - /* Update lock flag */ - Context->LockStateSignature = 0xAAAA1234; - - /* Lock it */ - KeEnterCriticalRegion(); - ExAcquirePushLockExclusive(&Directory->Lock); -} - -VOID -FORCEINLINE -_ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory, - IN POBP_LOOKUP_CONTEXT Context) -{ - /* Release the lock */ - ExReleasePushLock(&Directory->Lock); - Context->LockStateSignature = 0xEEEE1234; - KeLeaveCriticalRegion(); -} +#define OBP_LOCK_STATE_PRE_ACQUISITION_EXCLUSIVE 0xAAAA1234 +#define OBP_LOCK_STATE_PRE_ACQUISITION_SHARED 0xBBBB1234 +#define OBP_LOCK_STATE_POST_ACQUISITION_EXCLUSIVE 0xCCCC1234 +#define OBP_LOCK_STATE_POST_ACQUISITION_SHARED 0xDDDD1234 +#define OBP_LOCK_STATE_RELEASED 0xEEEE1234 +#define OBP_LOCK_STATE_INITIALIZED 0xFFFF1234 ULONG FORCEINLINE @@ -159,23 +79,69 @@ _ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo) VOID FORCEINLINE -_ObpCleanupDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context, - IN BOOLEAN DereferenceObject) +_ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory, + IN POBP_LOOKUP_CONTEXT Context) +{ + /* It's not, set lock flag */ + Context->LockStateSignature = OBP_LOCK_STATE_PRE_ACQUISITION_SHARED; + + /* Lock it */ + KeEnterCriticalRegion(); + ExAcquirePushLockShared(&Directory->Lock); + + /* Update lock flag */ + Context->LockStateSignature = OBP_LOCK_STATE_POST_ACQUISITION_SHARED; +} + +VOID +FORCEINLINE +_ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory, + IN POBP_LOOKUP_CONTEXT Context) +{ + /* Update lock flag */ + Context->LockStateSignature = OBP_LOCK_STATE_PRE_ACQUISITION_EXCLUSIVE; + + /* Acquire an exclusive directory lock */ + KeEnterCriticalRegion(); + ExAcquirePushLockExclusive(&Directory->Lock); + + /* Set the directory */ + Context->Directory = Directory; + + /* Update lock settings */ + Context->LockStateSignature = OBP_LOCK_STATE_POST_ACQUISITION_EXCLUSIVE; + Context->DirectoryLocked = TRUE; +} + +VOID +FORCEINLINE +_ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory, + IN POBP_LOOKUP_CONTEXT Context) +{ + /* Release the lock */ + ExReleasePushLock(&Directory->Lock); + Context->LockStateSignature = OBP_LOCK_STATE_RELEASED; + KeLeaveCriticalRegion(); +} + +VOID +FORCEINLINE +_ObpInitializeDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context) +{ + /* Initialize a null context */ + Context->Object = NULL; + Context->Directory = NULL; + Context->DirectoryLocked = FALSE; + Context->LockStateSignature = OBP_LOCK_STATE_INITIALIZED; +} + +VOID +FORCEINLINE +_ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context) { POBJECT_HEADER ObjectHeader; POBJECT_HEADER_NAME_INFO HeaderNameInfo; - /* Check if we came back with the directory locked */ - if (Context->DirectoryLocked) - { - /* Release the lock */ - _ObpReleaseDirectoryLock(Context->Directory, Context); - } - - /* Clear the context */ - Context->Directory = NULL; - Context->DirectoryLocked = FALSE; - /* Check if we had found an object */ if (Context->Object) { @@ -186,20 +152,27 @@ _ObpCleanupDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context, /* Check if we do have name information */ if (HeaderNameInfo) _ObpDecrementQueryReference(HeaderNameInfo); - /* Check if we need to dereference it */ - if (DereferenceObject) ObDereferenceObject(Context->Object); + /* Dereference the object */ + ObDereferenceObject(Context->Object); + Context->Object = NULL; } } VOID FORCEINLINE -_ObpInitializeDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context) +_ObpCleanupDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context) { - /* Initialize a null context */ - Context->Object = NULL; + /* Check if we came back with the directory locked */ + if (Context->DirectoryLocked) + { + /* Release the lock */ + _ObpReleaseDirectoryLock(Context->Directory, Context); + } + + /* Clear the context */ Context->Directory = NULL; Context->DirectoryLocked = FALSE; - Context->LockStateSignature = 0xFFFF1234; + _ObpReleaseLookupContextObject(Context); } #if _OB_DEBUG_ @@ -365,5 +338,49 @@ ObpFreeAndReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateIn ObpFreeCapturedAttributes(ObjectCreateInfo, LookasideCreateInfoList); } +#if DBG +VOID +FORCEINLINE +ObpCalloutStart(IN PKIRQL CalloutIrql) +{ + /* Save the callout IRQL */ + *CalloutIrql = KeGetCurrentIrql(); +} +VOID +FORCEINLINE +ObpCalloutEnd(IN KIRQL CalloutIrql, + IN PCHAR Procedure, + IN POBJECT_TYPE ObjectType, + IN PVOID Object) +{ + /* Detect IRQL change */ + if (CalloutIrql != KeGetCurrentIrql()) + { + /* Print error */ + DbgPrint("OB: ObjectType: %wZ Procedure: %s Object: %08x\n", + &ObjectType->Name, Procedure, Object); + DbgPrint(" Returned at %x IRQL, but was called at %x IRQL\n", + KeGetCurrentIrql(), CalloutIrql); + DbgBreakPoint(); + } +} +#else +VOID +FORCEINLINE +ObpCalloutStart(IN PKIRQL CalloutIrql) +{ + /* No-op */ + UNREFERENCED_PARAMETER(CalloutIrql); +} +VOID +FORCEINLINE +ObpCalloutEnd(IN KIRQL CalloutIrql, + IN PCHAR Procedure, + IN POBJECT_TYPE ObjectType, + IN PVOID Object) +{ + UNREFERENCED_PARAMETER(CalloutIrql); +} +#endif diff --git a/reactos/ntoskrnl/ob/obhandle.c b/reactos/ntoskrnl/ob/obhandle.c index fcdcd09ffe8..3fc6cb1a8cc 100644 --- a/reactos/ntoskrnl/ob/obhandle.c +++ b/reactos/ntoskrnl/ob/obhandle.c @@ -1249,7 +1249,7 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, if ((Type) && (ObjectType != Type)) { /* They don't, cleanup */ - //if (Context) ObpCleanupDirectoryLookup(Object, Context); + //if (Context) ObpCleanupDirectoryLookup(Context); return STATUS_OBJECT_TYPE_MISMATCH; } @@ -1287,7 +1287,7 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, * We failed (meaning security failure, according to NT Internals) * detach and return */ - //if (Context) ObpCleanupDirectoryLookup(Object, Context); + //if (Context) ObpCleanupDirectoryLookup(Context); if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); return Status; } @@ -1327,7 +1327,8 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, } /* Now we can release the object */ - //if (Context) ObpCleanupDirectoryLookup(Object, Context); + //if (Context) ObpCleanupDirectoryLookup(Context); + if (Context) Context->Object = NULL; /* Save the object header */ NewEntry.Object = ObjectHeader; @@ -2116,7 +2117,7 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, if (!NT_SUCCESS(Status)) { /* Cleanup after lookup */ - //ObpCleanupDirectoryLookup(&TempBuffer->LookupContext, TRUE); + //ObpCleanupDirectoryLookup(&TempBuffer->LookupContext); TempBuffer->LookupContext.Object = NULL; goto Cleanup; } @@ -2151,7 +2152,8 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, Status = STATUS_INVALID_PARAMETER; /* Cleanup after lookup */ - //ObpCleanupDirectoryLookup(&TempBuffer->LookupContext, TRUE); + //ObpCleanupDirectoryLookup(&TempBuffer->LookupContext); + TempBuffer->LookupContext.Object = NULL; } else { diff --git a/reactos/ntoskrnl/ob/obinit.c b/reactos/ntoskrnl/ob/obinit.c index f7e6ab93d88..e4d68b2eafa 100644 --- a/reactos/ntoskrnl/ob/obinit.c +++ b/reactos/ntoskrnl/ob/obinit.c @@ -283,9 +283,6 @@ ObPostPhase0: /* Lock it */ //ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context); - - /* Setup directory */ - // FIXME: ObpSetLookupDirectory(Dir);? Context.Directory = ObpTypeDirectoryObject; Context.DirectoryLocked = TRUE; Context.LockStateSignature = 0xCCCC1234; @@ -326,7 +323,7 @@ ObPostPhase0: } /* Cleanup after lookup */ - //ObpCleanupDirectoryLookup(&Context, TRUE); + //ObpCleanupDirectoryLookup(&Context); Context.Object = NULL; /* Initialize DOS Devices Directory and related Symbolic Links */ diff --git a/reactos/ntoskrnl/ob/oblife.c b/reactos/ntoskrnl/ob/oblife.c index 6384275e179..c692d87af94 100644 --- a/reactos/ntoskrnl/ob/oblife.c +++ b/reactos/ntoskrnl/ob/oblife.c @@ -958,14 +958,19 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName, if (*p++ == OBJ_NAME_PATH_SEPARATOR) return STATUS_OBJECT_NAME_INVALID; } - Context.Object = NULL; + /* Setup a lookup context */ + ObpInitializeDirectoryLookup(&Context); /* Check if we've already created the directory of types */ if (ObpTypeDirectoryObject) { - /* Then scan it to figure out if we've already created this type */ + /* Acquire the directory lock */ + //ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context); Context.Directory = ObpTypeDirectoryObject; Context.DirectoryLocked = TRUE; + Context.LockStateSignature = 0xCCCC1234; + + /* Do the lookup */ if (ObpLookupEntryDirectory(ObpTypeDirectoryObject, TypeName, OBJ_CASE_INSENSITIVE, diff --git a/reactos/ntoskrnl/ob/obname.c b/reactos/ntoskrnl/ob/obname.c index 6f57486173d..ce0e71a7955 100644 --- a/reactos/ntoskrnl/ob/obname.c +++ b/reactos/ntoskrnl/ob/obname.c @@ -194,12 +194,10 @@ ObpDeleteNameCheck(IN PVOID Object) !(ObjectHeader->Flags & OB_FLAG_PERMANENT)) { /* Setup a lookup context */ - Context.Object = NULL; + ObpInitializeDirectoryLookup(&Context); /* Lock the directory */ //ObpAcquireDirectoryLockExclusive(ObjectNameInfo->Directory, &Context); - - /* Set the lookup parameters */ Context.Directory = ObjectNameInfo->Directory; Context.DirectoryLocked = TRUE; Context.LockStateSignature = 0xCCCC1234; @@ -255,7 +253,7 @@ ObpDeleteNameCheck(IN PVOID Object) } /* Cleanup after lookup */ - //ObpCleanupDirectoryLookup(&Context, TRUE); + //ObpCleanupDirectoryLookup(&Context); Context.Object = NULL; /* Remove another query reference since we added one on top */ @@ -313,7 +311,7 @@ ObpLookupObjectName(IN HANDLE RootHandle, InsertObject); /* Initialize starting state */ - LookupContext->Object = NULL; + ObpInitializeDirectoryLookup(LookupContext); *FoundObject = NULL; Status = STATUS_SUCCESS; Object = NULL; @@ -575,10 +573,7 @@ ReparseNewDir: if (InsertObject) { /* Lock the directory */ - //ObpAcquireDirectoryLockExclusive(LookupContext, Directory); - - /* Setup the context */ - // FIXME: ObpSetLookupDirectory(Dir);? + //ObpAcquireDirectoryLockExclusive(Directory, LookupContext); LookupContext->Directory = Directory; LookupContext->DirectoryLocked = TRUE; LookupContext->LockStateSignature = 0xCCCC1234; @@ -701,7 +696,7 @@ Reparse: InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1); /* Cleanup from the first lookup */ - //ObpCleanupDirectoryLookup(LookupContext, TRUE); + //ObpCleanupDirectoryLookup(LookupContext); LookupContext->Object = NULL; /* Check if we have a referenced directory */ @@ -868,7 +863,7 @@ Reparse: if (!NT_SUCCESS(Status)) { /* Cleanup after lookup */ - //ObpCleanupDirectoryLookup(LookupContext, TRUE); + //ObpCleanupDirectoryLookup(LookupContext); LookupContext->Object = NULL; } diff --git a/reactos/ntoskrnl/ob/obref.c b/reactos/ntoskrnl/ob/obref.c index bc4b768263d..16763d45a97 100644 --- a/reactos/ntoskrnl/ob/obref.c +++ b/reactos/ntoskrnl/ob/obref.c @@ -430,7 +430,7 @@ ObReferenceObjectByName(IN PUNICODE_STRING ObjectPath, &Object); /* Cleanup after lookup */ - //ObpCleanupDirectoryLookup(&Context, TRUE); + //ObpCleanupDirectoryLookup(&Context); Context.Object = NULL; /* Check if the lookup succeeded */ From cf06d4975f650d62afb58aba00a5924e77a91e63 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Tue, 9 Jan 2007 22:02:17 +0000 Subject: [PATCH 02/36] Updated French translation by Pierre Schweitzer 2007 (heis_spiter AT hotmail DOT com) See issue #1969 for more details. svn path=/trunk/; revision=25404 --- reactos/dll/cpl/desk/Fr.rc | 57 +++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/reactos/dll/cpl/desk/Fr.rc b/reactos/dll/cpl/desk/Fr.rc index 53196da600c..528e456ae44 100644 --- a/reactos/dll/cpl/desk/Fr.rc +++ b/reactos/dll/cpl/desk/Fr.rc @@ -1,4 +1,5 @@ /* French translation by Benoit Plante 2005 (cmoibenlepro AT hotmail DOT com) */ +/* Updated French translation by Pierre Schweitzer 2007 (heis_spiter AT hotmail DOT com) */ LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL @@ -88,19 +89,19 @@ IDR_POPUP_MENU MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Configure", ID_MENU_CONFIG - MENUITEM "&Preview", ID_MENU_PREVIEW + MENUITEM "&Configurer", ID_MENU_CONFIG + MENUITEM "A&perçu", ID_MENU_PREVIEW MENUITEM SEPARATOR - MENUITEM "&Add", ID_MENU_ADD - MENUITEM "&Delete\tDel", ID_MENU_DELETE + MENUITEM "&Ajouer", ID_MENU_ADD + MENUITEM "Supprimer\tSuppr", ID_MENU_DELETE END END IDR_PREVIEW_MENU MENU BEGIN MENUITEM "Normal", ID_MENU_NORMAL - MENUITEM "Disabled", ID_MENU_DISABLED - MENUITEM "Selected", ID_MENU_SELECTED + MENUITEM "Désactivé", ID_MENU_DISABLED + MENUITEM "Sélectionné", ID_MENU_SELECTED END STRINGTABLE @@ -132,32 +133,32 @@ END STRINGTABLE DISCARDABLE BEGIN - IDS_INACTWIN "Inactive Window" - IDS_ACTWIN "Active Window" - IDS_WINTEXT "Window Text" - IDS_MESSBOX "Message Box" - IDS_MESSTEXT "Message Text" + IDS_INACTWIN "Fenêtre inactive" + IDS_ACTWIN "Fenêtre active" + IDS_WINTEXT "Texte de la fenêtre" + IDS_MESSBOX "Boîte de message" + IDS_MESSTEXT "Texte de message" IDS_BUTTEXT "OK" END STRINGTABLE DISCARDABLE BEGIN - IDS_ITEM_3D_OBJECTS "3D Objects" - IDS_ITEM_SCROLLBAR "Scrollbar" - IDS_ITEM_DESKTOP "Desktop" - IDS_ITEM_MESSAGE_BOX "Message Box" - IDS_ITEM_WINDOW "Window" - IDS_ITEM_APP_BACKGROUND "Application Background" - IDS_ITEM_SELECTED_ITEMS "Selected Items" + IDS_ITEM_3D_OBJECTS "Objets 3D" + IDS_ITEM_SCROLLBAR "Barre de défilement" + IDS_ITEM_DESKTOP "Bureau" + IDS_ITEM_MESSAGE_BOX "Boîte de message" + IDS_ITEM_WINDOW "Fenêtre" + IDS_ITEM_APP_BACKGROUND "Espace de travail de l'application" + IDS_ITEM_SELECTED_ITEMS "Éléments sélectionnés" IDS_ITEM_MENU "Menu" - IDS_ITEM_PALETTE_TITLE "Palette Title" - IDS_ITEM_TOOLTIP "Tooltip" - IDS_ITEM_INACTIVE_WINDOW "Inactive Window Border" - IDS_ITEM_ACTIVE_WINDOW "Active Window Border" - IDS_ITEM_ICON "Icon" - IDS_ITEM_ICON_SPACE_HORZ "Icon Spacing (Horizontal)" - IDS_ITEM_ICON_SPACE_VERT "Icon Spacing (Vertical)" - IDS_ITEM_INACTIVE_TITLE "Inactive Title Bar" - IDS_ITEM_ACTIVE_TITLE "Active Title Bar" - IDS_ITEM_CAPTION_BUTTONS "Caption Buttons" + IDS_ITEM_PALETTE_TITLE "Tite de palette" + IDS_ITEM_TOOLTIP "Info-bulle" + IDS_ITEM_INACTIVE_WINDOW "Bordure de fenêtre inactive" + IDS_ITEM_ACTIVE_WINDOW "Bordure de fenêtre active" + IDS_ITEM_ICON "Icône" + IDS_ITEM_ICON_SPACE_HORZ "Espacement des icônes (horizontal)" + IDS_ITEM_ICON_SPACE_VERT "Espacement des icônes (vertical)" + IDS_ITEM_INACTIVE_TITLE "Barre de titre inactive" + IDS_ITEM_ACTIVE_TITLE "Barre de titre active" + IDS_ITEM_CAPTION_BUTTONS "Boutons de barre de titre" END From 208da846ac90dbd4d0c0f26aabdbc3bdfb2a6336 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Tue, 9 Jan 2007 22:55:40 +0000 Subject: [PATCH 03/36] Implement new keyboard driver and layout structures to help Saveliy Tretiakovs LoadKeyboardLayout implementation. svn path=/trunk/; revision=25405 --- .../subsystems/win32/win32k/include/input.h | 18 ++++++++++++++++++ .../subsystems/win32/win32k/ntuser/keyboard.c | 3 +++ 2 files changed, 21 insertions(+) diff --git a/reactos/subsystems/win32/win32k/include/input.h b/reactos/subsystems/win32/win32k/include/input.h index 4619b680c27..bee57e3653e 100644 --- a/reactos/subsystems/win32/win32k/include/input.h +++ b/reactos/subsystems/win32/win32k/include/input.h @@ -3,6 +3,24 @@ #include +typedef struct _KBDRVFILE +{ + PSINGLE_LIST_ENTRY pkbdfChain; + WCHAR wcKBDF[9]; // used w GetKeyboardLayoutName same as wszKLID. + struct _KBDTABLES* KBTables; // KBDTABLES in ntoskrnl/include/internal/kbd.h +} KBDRVFILE, *PKBDRVFILE; + +typedef struct _KBL +{ + PLIST_ENTRY pklChain; + DWORD dwKBLFlags; + HKL hkl; + PKBDRVFILE pkbdf; +} KBL, *PKBL; + +#define KBL_UNLOADED 0x2000000 +#define KBL_RESET 0x4000000 + NTSTATUS FASTCALL InitInputImpl(VOID); NTSTATUS FASTCALL diff --git a/reactos/subsystems/win32/win32k/ntuser/keyboard.c b/reactos/subsystems/win32/win32k/ntuser/keyboard.c index d97660630a6..e8ea2681b48 100644 --- a/reactos/subsystems/win32/win32k/ntuser/keyboard.c +++ b/reactos/subsystems/win32/win32k/ntuser/keyboard.c @@ -53,6 +53,9 @@ BYTE gQueueKeyStateTable[256]; +PKBDRVFILE KBLList = NULL; // Keyboard layout list. + + /* FUNCTIONS *****************************************************************/ /* Initialization -- Right now, just zero the key state and init the lock */ From 8fb22da8e53e3481f70d0a9f56f5c43cea31ba2b Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Tue, 9 Jan 2007 23:00:21 +0000 Subject: [PATCH 04/36] - Add currency page controls. - Display currency format information. svn path=/trunk/; revision=25406 --- reactos/dll/cpl/intl/Fr.rc | 178 ++++++++++--------- reactos/dll/cpl/intl/Ja.rc | 20 ++- reactos/dll/cpl/intl/currency.c | 299 +++++++++++++++++++++++++++++++- reactos/dll/cpl/intl/cz.rc | 20 ++- reactos/dll/cpl/intl/de.rc | 20 ++- reactos/dll/cpl/intl/en.rc | 20 ++- reactos/dll/cpl/intl/es.rc | 20 ++- reactos/dll/cpl/intl/hu.rc | 20 ++- reactos/dll/cpl/intl/nl.rc | 20 ++- reactos/dll/cpl/intl/resource.h | 12 +- reactos/dll/cpl/intl/ru.rc | 20 ++- reactos/dll/cpl/intl/sv.rc | 38 +++- reactos/dll/cpl/intl/uk.rc | 20 ++- 13 files changed, 606 insertions(+), 101 deletions(-) diff --git a/reactos/dll/cpl/intl/Fr.rc b/reactos/dll/cpl/intl/Fr.rc index 4377a00e4ab..3a52d591b17 100644 --- a/reactos/dll/cpl/intl/Fr.rc +++ b/reactos/dll/cpl/intl/Fr.rc @@ -1,82 +1,100 @@ /* French translation by Benoit Plante 2005 (cmoibenlepro AT hotmail DOT com) */ -LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL - -IDD_GENERALPAGE DIALOGEX 0, 0, 246, 188 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Général" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Page de propriétés 1",-1,73,74,90,8 -END - - -IDD_NUMBERSPAGE DIALOGEX 0, 0, 246, 188 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Nombres" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Page de propriétés 2",-1,73,74,90,8 -END - - -IDD_CURRENCYPAGE DIALOGEX 0, 0, 246, 188 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Devise" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Page de propriétés 3",-1,73,74,90,8 -END - - -IDD_TIMEPAGE DIALOGEX 0, 0, 246, 188 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Heure" -FONT 8, "MS Shell Dlg" -BEGIN - GROUPBOX "Apparence de l'heure", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE - LTEXT "Échantillon d'heure:", -1, 13, 21, 54, 10, WS_CHILD |WS_VISIBLE | WS_GROUP - EDITTEXT IDC_TIMESAMPLE, 68, 19, 84, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "Format d'heure:", -1, 13, 52, 54, 10, WS_CHILD |WS_VISIBLE | WS_GROUP - COMBOBOX IDC_TIMEFORMAT, 68, 50, 84, 100, CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "&Séparateur des heures:", -1, 13, 70, 54, 10, WS_VISIBLE | WS_GROUP - COMBOBOX IDC_TIMESEPARATOR, 68, 68, 84, 100, CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "Symbole de l'avant-midi(A&M):", -1, 13, 88, 54, 10, WS_VISIBLE | WS_GROUP - COMBOBOX IDC_TIMEAMSYMBOL, 68, 86, 84, 100, CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "Symbole de l'après-midi(&PM):", -1, 13, 106, 54, 10, WS_VISIBLE | WS_GROUP - COMBOBOX IDC_TIMEPMSYMBOL, 68, 104, 84, 100, CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_TABSTOP - GROUPBOX "", -1, 7, 124, 228, 60, WS_VISIBLE - LTEXT "Notation de l'heure\n\n\ -h = heure m = minute s = seconde t = AM ou PM\n\n\ -h = 12 heures H =24 heures \n\ -hh, mm, ss = Zéro de départ h, m, s = Pas de zéro de départ", - -1, 13, 133, 214, 47, WS_CHILD |WS_VISIBLE | WS_GROUP -END - - -IDD_DATEPAGE DIALOGEX 0, 0, 246, 188 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Date" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Page de propriétés 5",-1,73,74,90,8 -END - - -IDD_LOCALEPAGE DIALOGEX 0, 0, 246, 188 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Langues" -FONT 8, "MS Shell Dlg" -BEGIN - GROUPBOX "Langue principale", -1, 8, 11, 228, 74 - ICON IDC_FLAGS, IDC_ICON1, 12, 26, 21, 20, SS_ICON - LTEXT "Sélectionnez la langue principale que vous voulez utiliser:", -1, 38, 25, 193, 22 - COMBOBOX IDC_LANGUAGELIST, 39, 49, 191, 83, CBS_DROPDOWNLIST | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL -END - - -STRINGTABLE -BEGIN - IDS_CPLNAME "Options régionales" - IDS_CPLDESCRIPTION "Selectionner les langues, les formats de nombres, les devises, l'heure et la date." -END +LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL + +IDD_GENERALPAGE DIALOGEX 0, 0, 246, 188 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Général" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Page de propriétés 1",-1,73,74,90,8 +END + + +IDD_NUMBERSPAGE DIALOGEX 0, 0, 246, 188 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Nombres" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Page de propriétés 2",-1,73,74,90,8 +END + + +IDD_CURRENCYPAGE DIALOGEX 0, 0, 246, 188 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Devise" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Appearance sample", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE + LTEXT "Positive:", -1, 13, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYPOSSAMPLE, 42, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Negative:", -1, 120, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYNEGSAMPLE, 154, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "&Currency symbol:", -1, 20, 51, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYSYMBOL, 124, 49, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Positive Amount:", -1, 20, 68, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYPOSVALUE, 124, 66, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Negative Amount:", -1, 20, 85, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYNEGVALUE, 124, 83, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Decimal separator:", -1, 20, 111, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECSEP, 124, 109, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Number of fractional digits:", -1, 20, 128, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECNUM, 124, 126, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Grouping symbol:", -1, 20, 156, 100, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPSEP, 124, 154, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Digit grouping:", -1, 20, 173, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPNUM, 124, 171, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL +END + + +IDD_TIMEPAGE DIALOGEX 0, 0, 246, 188 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Heure" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Apparence de l'heure", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE + LTEXT "Échantillon d'heure:", -1, 13, 21, 54, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_TIMESAMPLE, 68, 19, 84, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Format d'heure:", -1, 13, 52, 54, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_TIMEFORMAT, 68, 50, 84, 100, CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "&Séparateur des heures:", -1, 13, 70, 54, 10, WS_VISIBLE | WS_GROUP + COMBOBOX IDC_TIMESEPARATOR, 68, 68, 84, 100, CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Symbole de l'avant-midi(A&M):", -1, 13, 88, 54, 10, WS_VISIBLE | WS_GROUP + COMBOBOX IDC_TIMEAMSYMBOL, 68, 86, 84, 100, CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Symbole de l'après-midi(&PM):", -1, 13, 106, 54, 10, WS_VISIBLE | WS_GROUP + COMBOBOX IDC_TIMEPMSYMBOL, 68, 104, 84, 100, CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "", -1, 7, 124, 228, 60, WS_VISIBLE + LTEXT "Notation de l'heure\n\n\ +h = heure m = minute s = seconde t = AM ou PM\n\n\ +h = 12 heures H =24 heures \n\ +hh, mm, ss = Zéro de départ h, m, s = Pas de zéro de départ", + -1, 13, 133, 214, 47, WS_CHILD |WS_VISIBLE | WS_GROUP +END + + +IDD_DATEPAGE DIALOGEX 0, 0, 246, 188 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Date" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Page de propriétés 5",-1,73,74,90,8 +END + + +IDD_LOCALEPAGE DIALOGEX 0, 0, 246, 188 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Langues" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Langue principale", -1, 8, 11, 228, 74 + ICON IDC_FLAGS, IDC_ICON1, 12, 26, 21, 20, SS_ICON + LTEXT "Sélectionnez la langue principale que vous voulez utiliser:", -1, 38, 25, 193, 22 + COMBOBOX IDC_LANGUAGELIST, 39, 49, 191, 83, CBS_DROPDOWNLIST | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL +END + + +STRINGTABLE +BEGIN + IDS_CPLNAME "Options régionales" + IDS_CPLDESCRIPTION "Selectionner les langues, les formats de nombres, les devises, l'heure et la date." +END diff --git a/reactos/dll/cpl/intl/Ja.rc b/reactos/dll/cpl/intl/Ja.rc index 5614e386aae..366a6ba85b9 100644 --- a/reactos/dll/cpl/intl/Ja.rc +++ b/reactos/dll/cpl/intl/Ja.rc @@ -23,7 +23,25 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "’ʉÝ" FONT 9, "MS UI Gothic" BEGIN - LTEXT "Property Page 3",-1,73,74,90,8 + GROUPBOX "Appearance sample", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE + LTEXT "Positive:", -1, 13, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYPOSSAMPLE, 42, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Negative:", -1, 120, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYNEGSAMPLE, 154, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "&Currency symbol:", -1, 20, 51, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYSYMBOL, 124, 49, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Positive Amount:", -1, 20, 68, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYPOSVALUE, 124, 66, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Negative Amount:", -1, 20, 85, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYNEGVALUE, 124, 83, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Decimal separator:", -1, 20, 111, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECSEP, 124, 109, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Number of fractional digits:", -1, 20, 128, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECNUM, 124, 126, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Grouping symbol:", -1, 20, 156, 100, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPSEP, 124, 154, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Digit grouping:", -1, 20, 173, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPNUM, 124, 171, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL END diff --git a/reactos/dll/cpl/intl/currency.c b/reactos/dll/cpl/intl/currency.c index 9700546e152..5fea83f7123 100644 --- a/reactos/dll/cpl/intl/currency.c +++ b/reactos/dll/cpl/intl/currency.c @@ -27,24 +27,305 @@ #include #include #include +#include #include "intl.h" #include "resource.h" +typedef struct _GLOBAL_DATA +{ + TCHAR szCurrencySymbol[6]; + TCHAR szDecimalSep[4]; + TCHAR szThousandSep[4]; + TCHAR szGrouping[10]; + + int PositiveOrder; + int NegativeOrder; + int NumDigits; + +} GLOBAL_DATA, *PGLOBAL_DATA; + + +static VOID +GetInitialCurrencyValues(PGLOBAL_DATA pGlobalData) +{ + TCHAR szBuffer[256]; + int ret; + + /* Get currency symbol */ + ret = GetLocaleInfo(LOCALE_USER_DEFAULT, + LOCALE_SCURRENCY, + pGlobalData->szCurrencySymbol, 6); + + /* Get positive format */ + ret = GetLocaleInfo(LOCALE_USER_DEFAULT, + LOCALE_ICURRENCY, + szBuffer, 256); + if (ret != 0) + { + pGlobalData->PositiveOrder = _ttoi(szBuffer); + } + + /* Get negative format */ + ret = GetLocaleInfo(LOCALE_USER_DEFAULT, + LOCALE_INEGCURR, + szBuffer, 256); + if (ret != 0) + { + pGlobalData->NegativeOrder = _ttoi(szBuffer); + } + + /* Get number of fractional digits */ + ret = GetLocaleInfo(LOCALE_USER_DEFAULT, + LOCALE_ICURRDIGITS, + szBuffer, 256); + if (ret != 0) + { + pGlobalData->NumDigits = _ttoi(szBuffer); + } + + /* Get decimal separator */ + ret = GetLocaleInfoW(LOCALE_USER_DEFAULT, + LOCALE_SMONDECIMALSEP, + pGlobalData->szDecimalSep, 4); + + /* Get group separator */ + ret = GetLocaleInfo(LOCALE_USER_DEFAULT, + LOCALE_SMONTHOUSANDSEP, + pGlobalData->szThousandSep, 4); + + /* Get grouping */ + ret = GetLocaleInfo(LOCALE_USER_DEFAULT, + LOCALE_SMONGROUPING, + pGlobalData->szGrouping, 10); + +} + + +static VOID +UpdateExamples(HWND hwndDlg, PGLOBAL_DATA pGlobalData) +{ + TCHAR szBuffer[256]; + CURRENCYFMT cyFmt; + + cyFmt.NumDigits = pGlobalData->NumDigits; + cyFmt.LeadingZero = 0; + cyFmt.Grouping = 3; + cyFmt.lpDecimalSep = pGlobalData->szDecimalSep; + cyFmt.lpThousandSep = pGlobalData->szThousandSep; + cyFmt.PositiveOrder = pGlobalData->PositiveOrder; + cyFmt.NegativeOrder = pGlobalData->NegativeOrder; + cyFmt.lpCurrencySymbol = pGlobalData->szCurrencySymbol; + + /* positive example */ + GetCurrencyFormat(LOCALE_USER_DEFAULT, 0, + _T("123456789.00"), + &cyFmt, szBuffer, 256); + + SetDlgItemText(hwndDlg, + IDC_CURRENCYPOSSAMPLE, + szBuffer); + + /* negative example */ + GetCurrencyFormat(LOCALE_USER_DEFAULT, 0, + _T("-123456789.00"), + &cyFmt, szBuffer, 256); + + SetDlgItemText(hwndDlg, + IDC_CURRENCYNEGSAMPLE, + szBuffer); +} + + +static VOID +OnInitDialog(HWND hwndDlg, PGLOBAL_DATA pGlobalData) +{ + TCHAR szBuffer[256]; + CURRENCYFMT cyFmt; + int i; + + GetInitialCurrencyValues(pGlobalData); + + /* Set currency symbol */ + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYSYMBOL), + CB_ADDSTRING, + 0, + (LPARAM)pGlobalData->szCurrencySymbol); + + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYSYMBOL), + CB_SETCURSEL, + 0, /* index */ + 0); + + + /* positive currency values */ + cyFmt.NumDigits = pGlobalData->NumDigits; + cyFmt.LeadingZero = 0; + cyFmt.Grouping = 3; + cyFmt.lpDecimalSep = pGlobalData->szDecimalSep; + cyFmt.lpThousandSep = pGlobalData->szThousandSep; + cyFmt.NegativeOrder = 0; + cyFmt.lpCurrencySymbol = pGlobalData->szCurrencySymbol; + + for (i = 0; i < 4; i++) + { + cyFmt.PositiveOrder = i; + GetCurrencyFormat(LOCALE_USER_DEFAULT, 0, + _T("1.1"), + &cyFmt, szBuffer, 256); + + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYPOSVALUE), + CB_INSERTSTRING, + -1, + (LPARAM)szBuffer); + } + + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYPOSVALUE), + CB_SETCURSEL, + pGlobalData->PositiveOrder, + 0); + + /* negative currency values */ + cyFmt.PositiveOrder = 0; + for (i = 0; i < 16; i++) + { + cyFmt.NegativeOrder = i; + GetCurrencyFormat(LOCALE_USER_DEFAULT, 0, + _T("-1.1"), + &cyFmt, szBuffer, 256); + + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYNEGVALUE), + CB_INSERTSTRING, + -1, + (LPARAM)szBuffer); + } + + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYNEGVALUE), + CB_SETCURSEL, + pGlobalData->NegativeOrder, /* index */ + 0); + + /* decimal separator */ + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECSEP), + CB_ADDSTRING, + 0, + (LPARAM)pGlobalData->szDecimalSep); + + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECSEP), + CB_SETCURSEL, + 0, /* index */ + 0); + + + /* */ + for (i = 0; i < 10; i++) + { + szBuffer[0] = _T('0') + i; + szBuffer[1] = 0; + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECNUM), + CB_ADDSTRING, + 0, + (LPARAM)szBuffer); + } + + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECNUM), + CB_SETCURSEL, + pGlobalData->NumDigits, /* index */ + 0); + + + /* digit group separator */ + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPSEP), + CB_ADDSTRING, + 0, + (LPARAM)pGlobalData->szThousandSep); + + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPSEP), + CB_SETCURSEL, + 0, /* index */ + 0); + + /* digit grouping */ + cyFmt.NumDigits = 0; + cyFmt.LeadingZero = 0; + cyFmt.lpDecimalSep = _T(""); + cyFmt.lpThousandSep = pGlobalData->szThousandSep; + cyFmt.NegativeOrder = 0; + cyFmt.lpCurrencySymbol = _T(""); + cyFmt.Grouping = 0; + GetCurrencyFormat(LOCALE_USER_DEFAULT, 0, + _T("123456789"), + &cyFmt, szBuffer, 256); + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM), + CB_INSERTSTRING, + -1, + (LPARAM)szBuffer); + + cyFmt.Grouping = 3; + GetCurrencyFormat(LOCALE_USER_DEFAULT, 0, + _T("123456789"), + &cyFmt, szBuffer, 256); + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM), + CB_INSERTSTRING, + -1, + (LPARAM)szBuffer); + + cyFmt.Grouping = 32; + GetCurrencyFormat(LOCALE_USER_DEFAULT, 0, + _T("123456789"), + &cyFmt, szBuffer, 256); + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM), + CB_INSERTSTRING, + -1, + (LPARAM)szBuffer); + + i = 0; + if (pGlobalData->szGrouping[0] == _T('3')) + { + if ((pGlobalData->szGrouping[1] == _T(';')) && + (pGlobalData->szGrouping[2] == _T('2'))) + i = 2; + else + i = 1; + } + + SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM), + CB_SETCURSEL, + i, /* index */ + 0); + + /* Show the examples */ + UpdateExamples(hwndDlg, pGlobalData); +} + + /* Property page dialog callback */ INT_PTR CALLBACK CurrencyPageProc(HWND hwndDlg, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { - switch(uMsg) - { - case WM_INITDIALOG: - break; - } - return FALSE; + PGLOBAL_DATA pGlobalData; + + pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER); + + switch (uMsg) + { + case WM_INITDIALOG: + pGlobalData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLOBAL_DATA)); + SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData); + OnInitDialog(hwndDlg, pGlobalData); + break; + + + case WM_DESTROY: + HeapFree(GetProcessHeap(), 0, pGlobalData); + break; + } + + return FALSE; } /* EOF */ diff --git a/reactos/dll/cpl/intl/cz.rc b/reactos/dll/cpl/intl/cz.rc index 1eca1973d44..69ab2dcfee2 100644 --- a/reactos/dll/cpl/intl/cz.rc +++ b/reactos/dll/cpl/intl/cz.rc @@ -25,7 +25,25 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Mìna" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Property Page 3",-1,73,74,90,8 + GROUPBOX "Appearance sample", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE + LTEXT "Positive:", -1, 13, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYPOSSAMPLE, 42, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Negative:", -1, 120, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYNEGSAMPLE, 154, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "&Currency symbol:", -1, 20, 51, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYSYMBOL, 124, 49, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Positive Amount:", -1, 20, 68, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYPOSVALUE, 124, 66, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Negative Amount:", -1, 20, 85, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYNEGVALUE, 124, 83, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Decimal separator:", -1, 20, 111, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECSEP, 124, 109, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Number of fractional digits:", -1, 20, 128, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECNUM, 124, 126, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Grouping symbol:", -1, 20, 156, 100, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPSEP, 124, 154, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Digit grouping:", -1, 20, 173, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPNUM, 124, 171, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL END diff --git a/reactos/dll/cpl/intl/de.rc b/reactos/dll/cpl/intl/de.rc index 4553386f3a9..5e2535acad0 100644 --- a/reactos/dll/cpl/intl/de.rc +++ b/reactos/dll/cpl/intl/de.rc @@ -25,7 +25,25 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Währung" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Property Page 3",-1,73,74,90,8 + GROUPBOX "Darstellung", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE + LTEXT "Positiv:", -1, 13, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYPOSSAMPLE, 42, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Negativ:", -1, 120, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYNEGSAMPLE, 154, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "&Währungssymbol:", -1, 20, 51, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYSYMBOL, 124, 49, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "Format für &positive Beträge:", -1, 20, 68, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYPOSVALUE, 124, 66, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "Format für &negative Beträge:", -1, 20, 85, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYNEGVALUE, 124, 83, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Dezimaltrennzeichen:", -1, 20, 111, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECSEP, 124, 109, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Anzahl der Dezimalstellen:", -1, 20, 128, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECNUM, 124, 126, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Symbol für Zifferngruppierung:", -1, 20, 156, 100, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPSEP, 124, 154, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Zifferngruppierung:", -1, 20, 173, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPNUM, 124, 171, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL END diff --git a/reactos/dll/cpl/intl/en.rc b/reactos/dll/cpl/intl/en.rc index 88d88542650..be3f714f3df 100644 --- a/reactos/dll/cpl/intl/en.rc +++ b/reactos/dll/cpl/intl/en.rc @@ -25,7 +25,25 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Currency" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Property Page 3",-1,73,74,90,8 + GROUPBOX "Appearance sample", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE + LTEXT "Positive:", -1, 13, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYPOSSAMPLE, 42, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Negative:", -1, 120, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYNEGSAMPLE, 154, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "&Currency symbol:", -1, 20, 51, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYSYMBOL, 124, 49, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Positive Amount:", -1, 20, 68, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYPOSVALUE, 124, 66, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Negative Amount:", -1, 20, 85, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYNEGVALUE, 124, 83, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Decimal separator:", -1, 20, 111, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECSEP, 124, 109, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Number of fractional digits:", -1, 20, 128, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECNUM, 124, 126, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Grouping symbol:", -1, 20, 156, 100, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPSEP, 124, 154, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Digit grouping:", -1, 20, 173, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPNUM, 124, 171, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL END diff --git a/reactos/dll/cpl/intl/es.rc b/reactos/dll/cpl/intl/es.rc index fada44838ad..04b2b48385f 100644 --- a/reactos/dll/cpl/intl/es.rc +++ b/reactos/dll/cpl/intl/es.rc @@ -29,7 +29,25 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Moneda" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Property Page 3",-1,73,74,90,8 + GROUPBOX "Appearance sample", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE + LTEXT "Positive:", -1, 13, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYPOSSAMPLE, 42, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Negative:", -1, 120, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYNEGSAMPLE, 154, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "&Currency symbol:", -1, 20, 51, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYSYMBOL, 124, 49, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Positive Amount:", -1, 20, 68, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYPOSVALUE, 124, 66, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Negative Amount:", -1, 20, 85, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYNEGVALUE, 124, 83, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Decimal separator:", -1, 20, 111, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECSEP, 124, 109, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Number of fractional digits:", -1, 20, 128, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECNUM, 124, 126, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Grouping symbol:", -1, 20, 156, 100, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPSEP, 124, 154, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Digit grouping:", -1, 20, 173, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPNUM, 124, 171, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL END diff --git a/reactos/dll/cpl/intl/hu.rc b/reactos/dll/cpl/intl/hu.rc index 980fc8fdfd1..f84f90a2ed0 100644 --- a/reactos/dll/cpl/intl/hu.rc +++ b/reactos/dll/cpl/intl/hu.rc @@ -24,7 +24,25 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Pénznem" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "3.tulajdonságlap",-1,73,74,90,8 + GROUPBOX "Appearance sample", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE + LTEXT "Positive:", -1, 13, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYPOSSAMPLE, 42, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Negative:", -1, 120, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYNEGSAMPLE, 154, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "&Currency symbol:", -1, 20, 51, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYSYMBOL, 124, 49, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Positive Amount:", -1, 20, 68, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYPOSVALUE, 124, 66, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Negative Amount:", -1, 20, 85, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYNEGVALUE, 124, 83, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Decimal separator:", -1, 20, 111, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECSEP, 124, 109, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Number of fractional digits:", -1, 20, 128, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECNUM, 124, 126, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Grouping symbol:", -1, 20, 156, 100, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPSEP, 124, 154, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Digit grouping:", -1, 20, 173, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPNUM, 124, 171, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL END diff --git a/reactos/dll/cpl/intl/nl.rc b/reactos/dll/cpl/intl/nl.rc index 3f6d4c9945f..4e49f667388 100644 --- a/reactos/dll/cpl/intl/nl.rc +++ b/reactos/dll/cpl/intl/nl.rc @@ -25,7 +25,25 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Valuta" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Property Page 3",-1,73,74,90,8 + GROUPBOX "Appearance sample", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE + LTEXT "Positive:", -1, 13, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYPOSSAMPLE, 42, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Negative:", -1, 120, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYNEGSAMPLE, 154, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "&Currency symbol:", -1, 20, 51, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYSYMBOL, 124, 49, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Positive Amount:", -1, 20, 68, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYPOSVALUE, 124, 66, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Negative Amount:", -1, 20, 85, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYNEGVALUE, 124, 83, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Decimal separator:", -1, 20, 111, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECSEP, 124, 109, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Number of fractional digits:", -1, 20, 128, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECNUM, 124, 126, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Grouping symbol:", -1, 20, 156, 100, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPSEP, 124, 154, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Digit grouping:", -1, 20, 173, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPNUM, 124, 171, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL END diff --git a/reactos/dll/cpl/intl/resource.h b/reactos/dll/cpl/intl/resource.h index d125194b565..ffd0718c4df 100644 --- a/reactos/dll/cpl/intl/resource.h +++ b/reactos/dll/cpl/intl/resource.h @@ -8,7 +8,17 @@ #define IDD_GENERALPAGE 100 #define IDD_NUMBERSPAGE 101 -#define IDD_CURRENCYPAGE 102 + +#define IDD_CURRENCYPAGE 140 +#define IDC_CURRENCYPOSSAMPLE 141 +#define IDC_CURRENCYNEGSAMPLE 142 +#define IDC_CURRENCYSYMBOL 143 +#define IDC_CURRENCYPOSVALUE 144 +#define IDC_CURRENCYNEGVALUE 145 +#define IDC_CURRENCYDECSEP 146 +#define IDC_CURRENCYDECNUM 148 +#define IDC_CURRENCYGRPSEP 149 +#define IDC_CURRENCYGRPNUM 150 #define IDD_TIMEPAGE 103 #define IDC_TIMESAMPLE 107 diff --git a/reactos/dll/cpl/intl/ru.rc b/reactos/dll/cpl/intl/ru.rc index c7d293a68bc..4994f35fafd 100644 --- a/reactos/dll/cpl/intl/ru.rc +++ b/reactos/dll/cpl/intl/ru.rc @@ -25,7 +25,25 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Äåíåæíàÿ åäèíèöà" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Âêëàäêà 3",-1,73,74,90,8 + GROUPBOX "Appearance sample", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE + LTEXT "Positive:", -1, 13, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYPOSSAMPLE, 42, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Negative:", -1, 120, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYNEGSAMPLE, 154, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "&Currency symbol:", -1, 20, 51, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYSYMBOL, 124, 49, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Positive Amount:", -1, 20, 68, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYPOSVALUE, 124, 66, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Negative Amount:", -1, 20, 85, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYNEGVALUE, 124, 83, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Decimal separator:", -1, 20, 111, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECSEP, 124, 109, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Number of fractional digits:", -1, 20, 128, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECNUM, 124, 126, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Grouping symbol:", -1, 20, 156, 100, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPSEP, 124, 154, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Digit grouping:", -1, 20, 173, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPNUM, 124, 171, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL END diff --git a/reactos/dll/cpl/intl/sv.rc b/reactos/dll/cpl/intl/sv.rc index e566700b7fe..705e0e75a4f 100644 --- a/reactos/dll/cpl/intl/sv.rc +++ b/reactos/dll/cpl/intl/sv.rc @@ -26,7 +26,25 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Valuta" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Property Page 3",-1,73,74,90,8 + GROUPBOX "Appearance sample", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE + LTEXT "Positive:", -1, 13, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYPOSSAMPLE, 42, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Negative:", -1, 120, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYNEGSAMPLE, 154, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "&Currency symbol:", -1, 20, 51, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYSYMBOL, 124, 49, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Positive Amount:", -1, 20, 68, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYPOSVALUE, 124, 66, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Negative Amount:", -1, 20, 85, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYNEGVALUE, 124, 83, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Decimal separator:", -1, 20, 111, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECSEP, 124, 109, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Number of fractional digits:", -1, 20, 128, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECNUM, 124, 126, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Grouping symbol:", -1, 20, 156, 100, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPSEP, 124, 154, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Digit grouping:", -1, 20, 173, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPNUM, 124, 171, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL END @@ -35,7 +53,23 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Tid" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Property Page 4",-1,73,74,90,8 + GROUPBOX "Appearance sample", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE + LTEXT "Time sample:", -1, 13, 21, 54, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_TIMESAMPLE, 68, 19, 84, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "&Time format:", -1, 13, 52, 54, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_TIMEFORMAT, 68, 50, 84, 100, CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Time &separator:", -1, 13, 70, 54, 10, WS_VISIBLE | WS_GROUP + COMBOBOX IDC_TIMESEPARATOR, 68, 68, 84, 100, CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "A&M symbol:", -1, 13, 88, 54, 10, WS_VISIBLE | WS_GROUP + COMBOBOX IDC_TIMEAMSYMBOL, 68, 86, 84, 100, CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "&PM symbol:", -1, 13, 106, 54, 10, WS_VISIBLE | WS_GROUP + COMBOBOX IDC_TIMEPMSYMBOL, 68, 104, 84, 100, CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "", -1, 7, 124, 228, 60, WS_VISIBLE + LTEXT "Time format notation\n\n\ +h = hour m = minute s = second t = am or pm\n\n\ +h = 12 hour H = 24 hour\n\ +hh, mm, ss = leading zero h, m, s = no leading zero", + -1, 13, 133, 214, 47, WS_CHILD |WS_VISIBLE | WS_GROUP END diff --git a/reactos/dll/cpl/intl/uk.rc b/reactos/dll/cpl/intl/uk.rc index e1f93d5352b..2e5bf5609c5 100644 --- a/reactos/dll/cpl/intl/uk.rc +++ b/reactos/dll/cpl/intl/uk.rc @@ -32,7 +32,25 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Ãðîøîâà îäèíèöÿ" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Âêëàäêà âëàñòèâîñòåé 3",-1,73,74,90,8 + GROUPBOX "Appearance sample", -1, 7, 7, 228, 33, WS_CHILD | WS_VISIBLE + LTEXT "Positive:", -1, 13, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYPOSSAMPLE, 42, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Negative:", -1, 120, 21, 31, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + EDITTEXT IDC_CURRENCYNEGSAMPLE, 154, 19, 72, 14, ES_READONLY | WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "&Currency symbol:", -1, 20, 51, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYSYMBOL, 124, 49, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Positive Amount:", -1, 20, 68, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYPOSVALUE, 124, 66, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Negative Amount:", -1, 20, 85, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYNEGVALUE, 124, 83, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Decimal separator:", -1, 20, 111, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECSEP, 124, 109, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Number of fractional digits:", -1, 20, 128, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYDECNUM, 124, 126, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Grouping symbol:", -1, 20, 156, 100, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPSEP, 124, 154, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "&Digit grouping:", -1, 20, 173, 96, 10, WS_CHILD |WS_VISIBLE | WS_GROUP + COMBOBOX IDC_CURRENCYGRPNUM, 124, 171, 100, 83, CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL END From 6e3ccb6ffd2d4855aee25571093fa797b2c16129 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Wed, 10 Jan 2007 01:00:46 +0000 Subject: [PATCH 05/36] - Fix a bug in ExfWakePushLock. - Implement object directory locking to avoid race conditions in Ob and enable most of the query referencing code. svn path=/trunk/; revision=25407 --- reactos/ntoskrnl/ex/pushlock.c | 2 +- reactos/ntoskrnl/include/internal/ob_x.h | 60 ++++-------------------- reactos/ntoskrnl/ob/obdir.c | 6 +-- reactos/ntoskrnl/ob/obhandle.c | 19 ++++---- reactos/ntoskrnl/ob/obinit.c | 8 +--- reactos/ntoskrnl/ob/oblife.c | 17 +++---- reactos/ntoskrnl/ob/obname.c | 20 +++----- reactos/ntoskrnl/ob/obref.c | 3 +- 8 files changed, 41 insertions(+), 94 deletions(-) diff --git a/reactos/ntoskrnl/ex/pushlock.c b/reactos/ntoskrnl/ex/pushlock.c index bccf40a2482..80103eaa68b 100644 --- a/reactos/ntoskrnl/ex/pushlock.c +++ b/reactos/ntoskrnl/ex/pushlock.c @@ -97,7 +97,7 @@ ExfWakePushLock(PEX_PUSH_LOCK PushLock, OldValue = NewValue; /* Check if it's still locked */ - if (OldValue.Locked) continue; + if (!OldValue.Locked) break; } } diff --git a/reactos/ntoskrnl/include/internal/ob_x.h b/reactos/ntoskrnl/include/internal/ob_x.h index 058be1bfe26..34a5011857a 100644 --- a/reactos/ntoskrnl/include/internal/ob_x.h +++ b/reactos/ntoskrnl/include/internal/ob_x.h @@ -51,7 +51,7 @@ ObpIncrementQueryReference(IN POBJECT_HEADER ObjectHeader, VOID FORCEINLINE -_ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo) +ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo) { POBJECT_DIRECTORY Directory; @@ -79,7 +79,7 @@ _ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo) VOID FORCEINLINE -_ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory, +ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory, IN POBP_LOOKUP_CONTEXT Context) { /* It's not, set lock flag */ @@ -95,7 +95,7 @@ _ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory, VOID FORCEINLINE -_ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory, +ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory, IN POBP_LOOKUP_CONTEXT Context) { /* Update lock flag */ @@ -115,7 +115,7 @@ _ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory, VOID FORCEINLINE -_ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory, +ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory, IN POBP_LOOKUP_CONTEXT Context) { /* Release the lock */ @@ -126,7 +126,7 @@ _ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory, VOID FORCEINLINE -_ObpInitializeDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context) +ObpInitializeDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context) { /* Initialize a null context */ Context->Object = NULL; @@ -137,7 +137,7 @@ _ObpInitializeDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context) VOID FORCEINLINE -_ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context) +ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context) { POBJECT_HEADER ObjectHeader; POBJECT_HEADER_NAME_INFO HeaderNameInfo; @@ -150,7 +150,7 @@ _ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context) HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); /* Check if we do have name information */ - if (HeaderNameInfo) _ObpDecrementQueryReference(HeaderNameInfo); + if (HeaderNameInfo) ObpDecrementQueryReference(HeaderNameInfo); /* Dereference the object */ ObDereferenceObject(Context->Object); @@ -160,61 +160,21 @@ _ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context) VOID FORCEINLINE -_ObpCleanupDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context) +ObpCleanupDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context) { /* Check if we came back with the directory locked */ if (Context->DirectoryLocked) { /* Release the lock */ - _ObpReleaseDirectoryLock(Context->Directory, Context); + ObpReleaseDirectoryLock(Context->Directory, Context); } /* Clear the context */ Context->Directory = NULL; Context->DirectoryLocked = FALSE; - _ObpReleaseLookupContextObject(Context); + ObpReleaseLookupContextObject(Context); } -#if _OB_DEBUG_ -#define ObpAcquireDirectoryLockShared(a, b) \ -{ \ - DbgPrint("OB QUERY: Acquiring lock at %s %d\n", __FUNCTION__, __LINE__);\ - _ObpAcquireDirectoryLockShared(a, b); \ -} -#define ObpAcquireDirectoryLockExclusive(a, b) \ -{ \ - DbgPrint("OB QUERY: Acquiring lock at %s %d\n", __FUNCTION__, __LINE__);\ - _ObpAcquireDirectoryLockExclusive(a, b); \ -} -#define ObpReleaseDirectoryLock(a, b) \ -{ \ - DbgPrint("OB QUERY: Releasing lock at %s %d\n", __FUNCTION__, __LINE__);\ - _ObpReleaseDirectoryLock(a, b); \ -} -#define ObpInitializeDirectoryLookup(a) \ -{ \ - DbgPrint("OB QUERY: Initialization at %s %d\n", __FUNCTION__, __LINE__);\ - _ObpInitializeDirectoryLookup(a); \ -} -#define ObpCleanupDirectoryLookup(a, b) \ -{ \ - DbgPrint("OB QUERY: Cleanup at %s %d\n", __FUNCTION__, __LINE__); \ - _ObpCleanupDirectoryLookup(a, b); \ -} -#define ObpDecrementQueryReference(a) \ -{ \ - DbgPrint("OB QUERY: Decrement at %s %d\n", __FUNCTION__, __LINE__); \ - _ObpDecrementQueryReference(a); \ -} -#else -#define ObpDecrementQueryReference _ObpDecrementQueryReference -#define ObpAcquireDirectoryLockExclusive _ObpAcquireDirectoryLockExclusive -#define ObpAcquireDirectoryLockShared _ObpAcquireDirectoryLockShared -#define ObpReleaseDirectoryLock _ObpReleaseDirectoryLock -#define ObpInitializeDirectoryLookup _ObpInitializeDirectoryLookup -#define ObpCleanupDirectoryLookup _ObpCleanupDirectoryLookup -#endif - VOID FORCEINLINE ObpEnterObjectTypeMutex(IN POBJECT_TYPE ObjectType) diff --git a/reactos/ntoskrnl/ob/obdir.c b/reactos/ntoskrnl/ob/obdir.c index 663b112ff93..5ec63bcaf08 100644 --- a/reactos/ntoskrnl/ob/obdir.c +++ b/reactos/ntoskrnl/ob/obdir.c @@ -247,11 +247,11 @@ ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory, if (HeaderNameInfo) { /* Add a query reference */ - //ObpIncrementQueryReference(ObjectHeader, HeaderNameInfo); + ObpIncrementQueryReference(ObjectHeader, HeaderNameInfo); } /* Reference the object being looked up */ - //ObReferenceObject(FoundObject); + ObReferenceObject(FoundObject); /* Check if the directory was locked */ if (!Context->DirectoryLocked) @@ -282,7 +282,7 @@ Quickie: if (Context->Object) { /* We already did a lookup, so remove this object's query reference */ - //ObpRemoveQueryReference(Context->Object); + //ObpDecrementQueryReference(Context->Object); } /* Return the object we found */ diff --git a/reactos/ntoskrnl/ob/obhandle.c b/reactos/ntoskrnl/ob/obhandle.c index 3fc6cb1a8cc..c9395df23e8 100644 --- a/reactos/ntoskrnl/ob/obhandle.c +++ b/reactos/ntoskrnl/ob/obhandle.c @@ -1249,7 +1249,7 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, if ((Type) && (ObjectType != Type)) { /* They don't, cleanup */ - //if (Context) ObpCleanupDirectoryLookup(Context); + if (Context) ObpCleanupDirectoryLookup(Context); return STATUS_OBJECT_TYPE_MISMATCH; } @@ -1287,7 +1287,7 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, * We failed (meaning security failure, according to NT Internals) * detach and return */ - //if (Context) ObpCleanupDirectoryLookup(Context); + if (Context) ObpCleanupDirectoryLookup(Context); if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); return Status; } @@ -1327,8 +1327,7 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, } /* Now we can release the object */ - //if (Context) ObpCleanupDirectoryLookup(Context); - if (Context) Context->Object = NULL; + if (Context) ObpCleanupDirectoryLookup(Context); /* Save the object header */ NewEntry.Object = ObjectHeader; @@ -2117,8 +2116,7 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, if (!NT_SUCCESS(Status)) { /* Cleanup after lookup */ - //ObpCleanupDirectoryLookup(&TempBuffer->LookupContext); - TempBuffer->LookupContext.Object = NULL; + ObpCleanupDirectoryLookup(&TempBuffer->LookupContext); goto Cleanup; } @@ -2152,8 +2150,7 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, Status = STATUS_INVALID_PARAMETER; /* Cleanup after lookup */ - //ObpCleanupDirectoryLookup(&TempBuffer->LookupContext); - TempBuffer->LookupContext.Object = NULL; + ObpCleanupDirectoryLookup(&TempBuffer->LookupContext); } else { @@ -2589,6 +2586,9 @@ ObInsertObject(IN PVOID Object, /* Check if anything until now failed */ if (!NT_SUCCESS(Status)) { + /* Cleanup after lookup */ + ObpCleanupDirectoryLookup(&Context); + /* Remove query reference that we added */ if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo); @@ -2657,6 +2657,9 @@ ObInsertObject(IN PVOID Object, /* Check if anything until now failed */ if (!NT_SUCCESS(Status)) { + /* Cleanup lookup context */ + ObpCleanupDirectoryLookup(&Context); + /* Remove query reference that we added */ if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo); diff --git a/reactos/ntoskrnl/ob/obinit.c b/reactos/ntoskrnl/ob/obinit.c index e4d68b2eafa..5f023dda3bf 100644 --- a/reactos/ntoskrnl/ob/obinit.c +++ b/reactos/ntoskrnl/ob/obinit.c @@ -282,10 +282,7 @@ ObPostPhase0: ObpInitializeDirectoryLookup(&Context); /* Lock it */ - //ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context); - Context.Directory = ObpTypeDirectoryObject; - Context.DirectoryLocked = TRUE; - Context.LockStateSignature = 0xCCCC1234; + ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context); /* Loop the object types */ ListHead = &ObTypeObjectType->TypeList; @@ -323,8 +320,7 @@ ObPostPhase0: } /* Cleanup after lookup */ - //ObpCleanupDirectoryLookup(&Context); - Context.Object = NULL; + ObpCleanupDirectoryLookup(&Context); /* Initialize DOS Devices Directory and related Symbolic Links */ Status = ObpCreateDosDevicesDirectory(); diff --git a/reactos/ntoskrnl/ob/oblife.c b/reactos/ntoskrnl/ob/oblife.c index c692d87af94..488af3131a1 100644 --- a/reactos/ntoskrnl/ob/oblife.c +++ b/reactos/ntoskrnl/ob/oblife.c @@ -965,10 +965,7 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName, if (ObpTypeDirectoryObject) { /* Acquire the directory lock */ - //ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context); - Context.Directory = ObpTypeDirectoryObject; - Context.DirectoryLocked = TRUE; - Context.LockStateSignature = 0xCCCC1234; + ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context); /* Do the lookup */ if (ObpLookupEntryDirectory(ObpTypeDirectoryObject, @@ -978,7 +975,7 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName, &Context)) { /* We have already created it, so fail */ - Context.Object = NULL; + ObpCleanupDirectoryLookup(&Context); return STATUS_OBJECT_NAME_COLLISION; } } @@ -990,7 +987,7 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName, if (!ObjectName.Buffer) { /* Out of memory, fail */ - Context.Object = NULL; + ObpCleanupDirectoryLookup(&Context); return STATUS_INSUFFICIENT_RESOURCES; } @@ -1007,9 +1004,8 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName, (POBJECT_HEADER*)&Header); if (!NT_SUCCESS(Status)) { - Context.Object = NULL; - /* Free the name and fail */ + ObpCleanupDirectoryLookup(&Context); ExFreePool(ObjectName.Buffer); return Status; } @@ -1138,7 +1134,8 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName, ObReferenceObject(ObpTypeDirectoryObject); } - Context.Object = NULL; + /* Cleanup the lookup context */ + ObpCleanupDirectoryLookup(&Context); /* Return the object type and success */ *ObjectType = LocalObjectType; @@ -1146,7 +1143,7 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName, } /* If we got here, then we failed */ - Context.Object = NULL; + ObpCleanupDirectoryLookup(&Context); return STATUS_INSUFFICIENT_RESOURCES; } diff --git a/reactos/ntoskrnl/ob/obname.c b/reactos/ntoskrnl/ob/obname.c index ce0e71a7955..2becdbc3bd8 100644 --- a/reactos/ntoskrnl/ob/obname.c +++ b/reactos/ntoskrnl/ob/obname.c @@ -191,16 +191,14 @@ ObpDeleteNameCheck(IN PVOID Object) if (!(ObjectHeader->HandleCount) && (ObjectNameInfo) && (ObjectNameInfo->Name.Length) && + (ObjectNameInfo->Directory) && !(ObjectHeader->Flags & OB_FLAG_PERMANENT)) { /* Setup a lookup context */ ObpInitializeDirectoryLookup(&Context); /* Lock the directory */ - //ObpAcquireDirectoryLockExclusive(ObjectNameInfo->Directory, &Context); - Context.Directory = ObjectNameInfo->Directory; - Context.DirectoryLocked = TRUE; - Context.LockStateSignature = 0xCCCC1234; + ObpAcquireDirectoryLockExclusive(ObjectNameInfo->Directory, &Context); /* Do the lookup */ Object = ObpLookupEntryDirectory(ObjectNameInfo->Directory, @@ -253,8 +251,7 @@ ObpDeleteNameCheck(IN PVOID Object) } /* Cleanup after lookup */ - //ObpCleanupDirectoryLookup(&Context); - Context.Object = NULL; + ObpCleanupDirectoryLookup(&Context); /* Remove another query reference since we added one on top */ ObpDecrementQueryReference(ObjectNameInfo); @@ -573,10 +570,7 @@ ReparseNewDir: if (InsertObject) { /* Lock the directory */ - //ObpAcquireDirectoryLockExclusive(Directory, LookupContext); - LookupContext->Directory = Directory; - LookupContext->DirectoryLocked = TRUE; - LookupContext->LockStateSignature = 0xCCCC1234; + ObpAcquireDirectoryLockExclusive(Directory, LookupContext); } } @@ -696,8 +690,7 @@ Reparse: InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1); /* Cleanup from the first lookup */ - //ObpCleanupDirectoryLookup(LookupContext); - LookupContext->Object = NULL; + ObpCleanupDirectoryLookup(LookupContext); /* Check if we have a referenced directory */ if (ReferencedDirectory) @@ -863,8 +856,7 @@ Reparse: if (!NT_SUCCESS(Status)) { /* Cleanup after lookup */ - //ObpCleanupDirectoryLookup(LookupContext); - LookupContext->Object = NULL; + ObpCleanupDirectoryLookup(LookupContext); } /* Check if we have a device map and dereference it if so */ diff --git a/reactos/ntoskrnl/ob/obref.c b/reactos/ntoskrnl/ob/obref.c index 16763d45a97..60e83cf7abd 100644 --- a/reactos/ntoskrnl/ob/obref.c +++ b/reactos/ntoskrnl/ob/obref.c @@ -430,8 +430,7 @@ ObReferenceObjectByName(IN PUNICODE_STRING ObjectPath, &Object); /* Cleanup after lookup */ - //ObpCleanupDirectoryLookup(&Context); - Context.Object = NULL; + ObpCleanupDirectoryLookup(&Context); /* Check if the lookup succeeded */ if (NT_SUCCESS(Status)) From 70d1578a28bbf2268bcbe2742b4ab0be17944156 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Wed, 10 Jan 2007 03:35:59 +0000 Subject: [PATCH 06/36] - Implement ObReferenceProcessHandleTable and ObDereferenceProcessHandleTable and use them where appropriate to avoid race issues if the process is being killed meanwhile. - Implement ObpReferenceProcessObjectByHandle and simplfy ObDuplicateObject. - Disable hard errors while closing handles, and protect against races. Also print our error message since it seems handles aren't being closed now (message displays leak count). - Honour DUPLICATE_CLOSE_SOURCE during failure paths in ObDuplicateObject, and catch race conditions. - Add some more sanity checks and speed up some internal referencing. svn path=/trunk/; revision=25408 --- reactos/ntoskrnl/KrnlFun.c | 5 - reactos/ntoskrnl/include/internal/ob.h | 12 + reactos/ntoskrnl/ob/obhandle.c | 297 ++++++++++++++++++++++--- reactos/ntoskrnl/ob/obref.c | 22 +- 4 files changed, 289 insertions(+), 47 deletions(-) diff --git a/reactos/ntoskrnl/KrnlFun.c b/reactos/ntoskrnl/KrnlFun.c index 19fc3355f82..41337191e2d 100644 --- a/reactos/ntoskrnl/KrnlFun.c +++ b/reactos/ntoskrnl/KrnlFun.c @@ -8,11 +8,6 @@ // Do NOT ask when it will be fixed. // Failure to respect this will *ACHIEVE NOTHING*. // -// -// Ob: -// - Add Directory Lock. -// - Add Object Table Referencing. -// // Ex: // - Fixup existing code that talks to Ke. // - Implement Generic Callback mechanism. diff --git a/reactos/ntoskrnl/include/internal/ob.h b/reactos/ntoskrnl/include/internal/ob.h index 0c845d2aa60..f9fbf9c3cfb 100644 --- a/reactos/ntoskrnl/include/internal/ob.h +++ b/reactos/ntoskrnl/include/internal/ob.h @@ -171,6 +171,18 @@ ObpCreateHandleTable( IN PEPROCESS Process ); +PHANDLE_TABLE +NTAPI +ObReferenceProcessHandleTable( + IN PEPROCESS Process +); + +VOID +NTAPI +ObDereferenceProcessHandleTable( + IN PEPROCESS Process +); + VOID NTAPI ObKillProcess( diff --git a/reactos/ntoskrnl/ob/obhandle.c b/reactos/ntoskrnl/ob/obhandle.c index c9395df23e8..34cd8bae2bf 100644 --- a/reactos/ntoskrnl/ob/obhandle.c +++ b/reactos/ntoskrnl/ob/obhandle.c @@ -23,6 +23,165 @@ PHANDLE_TABLE ObpKernelHandleTable = NULL; /* PRIVATE FUNCTIONS *********************************************************/ +PHANDLE_TABLE +NTAPI +ObReferenceProcessHandleTable(IN PEPROCESS Process) +{ + PHANDLE_TABLE HandleTable = NULL; + + /* Lock the process */ + if (ExAcquireRundownProtection(&Process->RundownProtect)) + { + /* Get the handle table */ + HandleTable = Process->ObjectTable; + if (!HandleTable) + { + /* No table, release the lock */ + ExReleaseRundownProtection(&Process->RundownProtect); + } + } + + /* Return the handle table */ + return HandleTable; +} + +VOID +NTAPI +ObDereferenceProcessHandleTable(IN PEPROCESS Process) +{ + /* Release the process lock */ + ExReleaseRundownProtection(&Process->RundownProtect); +} + +NTSTATUS +NTAPI +ObpReferenceProcessObjectByHandle(IN HANDLE Handle, + IN PEPROCESS Process, + IN PHANDLE_TABLE HandleTable, + IN KPROCESSOR_MODE AccessMode, + OUT PVOID *Object, + OUT POBJECT_HANDLE_INFORMATION HandleInformation) +{ + PHANDLE_TABLE_ENTRY HandleEntry; + POBJECT_HEADER ObjectHeader; + ACCESS_MASK GrantedAccess; + ULONG Attributes; + PEPROCESS CurrentProcess; + PETHREAD CurrentThread; + NTSTATUS Status; + PAGED_CODE(); + + /* Assume failure */ + *Object = NULL; + + /* Check if the caller wants the current process */ + if (Handle == NtCurrentProcess()) + { + /* Get the current process */ + CurrentProcess = PsGetCurrentProcess(); + + /* Check if the caller wanted handle information */ + if (HandleInformation) + { + /* Return it */ + HandleInformation->HandleAttributes = 0; + HandleInformation->GrantedAccess = Process->GrantedAccess; + } + + /* Reference ourselves */ + ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentProcess); + InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1); + + /* Return the pointer */ + *Object = CurrentProcess; + return STATUS_SUCCESS; + } + + /* Check if the caller wants the current thread */ + if (Handle == NtCurrentThread()) + { + /* Get the current thread */ + CurrentThread = PsGetCurrentThread(); + + /* Check if the caller wanted handle information */ + if (HandleInformation) + { + /* Return it */ + HandleInformation->HandleAttributes = 0; + HandleInformation->GrantedAccess = CurrentThread->GrantedAccess; + } + + /* Reference ourselves */ + ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentThread); + InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1); + + /* Return the pointer */ + *Object = CurrentThread; + return STATUS_SUCCESS; + } + + /* Check if this is a kernel handle */ + if (ObIsKernelHandle(Handle, AccessMode)) + { + /* Use the kernel handle table and get the actual handle value */ + Handle = ObKernelHandleToHandle(Handle); + HandleTable = ObpKernelHandleTable; + } + else + { + /* Otherwise use this process's handle table */ + HandleTable = PsGetCurrentProcess()->ObjectTable; + } + + /* Enter a critical region while we touch the handle table */ + ASSERT(HandleTable != NULL); + KeEnterCriticalRegion(); + + /* Get the handle entry */ + HandleEntry = ExMapHandleToPointer(HandleTable, Handle); + if (HandleEntry) + { + /* Get the object header and validate the type*/ + ObjectHeader = EX_HTE_TO_HDR(HandleEntry); + + /* Get the granted access and validate it */ + GrantedAccess = HandleEntry->GrantedAccess; + + /* Mask out the internal attributes */ + Attributes = HandleEntry->ObAttributes & + (EX_HANDLE_ENTRY_PROTECTFROMCLOSE | + EX_HANDLE_ENTRY_INHERITABLE | + EX_HANDLE_ENTRY_AUDITONCLOSE); + + /* Fill out the information */ + HandleInformation->HandleAttributes = Attributes; + HandleInformation->GrantedAccess = GrantedAccess; + + /* Return the pointer */ + *Object = &ObjectHeader->Body; + + /* Add a reference */ + InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1); + + /* Unlock the handle */ + ExUnlockHandleTableEntry(HandleTable, HandleEntry); + KeLeaveCriticalRegion(); + + /* Return success */ + ASSERT(*Object != NULL); + return STATUS_SUCCESS; + } + else + { + /* Invalid handle */ + Status = STATUS_INVALID_HANDLE; + } + + /* Return failure status */ + KeLeaveCriticalRegion(); + return Status; +} + BOOLEAN NTAPI ObpEnumFindHandleProcedure(IN PHANDLE_TABLE_ENTRY HandleEntry, @@ -1741,11 +1900,15 @@ ObpCreateHandleTable(IN PEPROCESS Parent, /* Check if we have a parent */ if (Parent) { + /* Get the parent's table */ + HandleTable = ObReferenceProcessHandleTable(Parent); + if (!HandleTable) return STATUS_PROCESS_IS_TERMINATING; + /* Duplicate the parent's */ HandleTable = ExDupHandleTable(Process, ObpDuplicateHandleCallback, NULL, - Parent->ObjectTable); + HandleTable); } else { @@ -1753,11 +1916,14 @@ ObpCreateHandleTable(IN PEPROCESS Parent, HandleTable = ExCreateHandleTable(Process); } - /* Now write it and make sure we got one */ + /* Now write it */ Process->ObjectTable = HandleTable; - if (!HandleTable) return STATUS_INSUFFICIENT_RESOURCES; - /* If we got here then the table was created OK */ + /* Dereference the parent's handle table if we have one */ + if (Parent) ObDereferenceProcessHandleTable(Parent); + + /* Fail or succeed depending on whether we got a handle table or not */ + if (!HandleTable) return STATUS_INSUFFICIENT_RESOURCES; return STATUS_SUCCESS; } @@ -1778,10 +1944,21 @@ VOID NTAPI ObKillProcess(IN PEPROCESS Process) { - PHANDLE_TABLE HandleTable = Process->ObjectTable; + PHANDLE_TABLE HandleTable; OBP_CLOSE_HANDLE_CONTEXT Context; + BOOLEAN HardErrors; PAGED_CODE(); + /* Wait for process rundown */ + ExWaitForRundownProtectionRelease(&Process->RundownProtect); + + /* Get the object table */ + HandleTable = Process->ObjectTable; + if (!HandleTable) return; + + /* Disable hard errors while we close handles */ + HardErrors = IoSetThreadHardErrorMode(FALSE); + /* Enter a critical region */ KeEnterCriticalRegion(); @@ -1793,13 +1970,20 @@ ObKillProcess(IN PEPROCESS Process) ExSweepHandleTable(HandleTable, ObpCloseHandleCallback, &Context); + if (HandleTable->HandleCount != 0) + { + DPRINT1("FIXME: %d handles remain!\n", HandleTable->HandleCount); + } - /* Destroy the table and leave the critical region */ - ExDestroyHandleTable(HandleTable); + /* Leave the critical region */ KeLeaveCriticalRegion(); - /* Clear the object table */ + /* Re-enable hard errors */ + IoSetThreadHardErrorMode(HardErrors); + + /* Destroy the object table */ Process->ObjectTable = NULL; + ExDestroyHandleTable(HandleTable); } NTSTATUS @@ -1820,12 +2004,12 @@ ObDuplicateObject(IN PEPROCESS SourceProcess, POBJECT_TYPE ObjectType; HANDLE NewHandle; KAPC_STATE ApcState; - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status; ACCESS_MASK TargetAccess, SourceAccess; ACCESS_STATE AccessState; PACCESS_STATE PassedAccessState = NULL; AUX_DATA AuxData; - PHANDLE_TABLE HandleTable = NULL; + PHANDLE_TABLE HandleTable; OBJECT_HANDLE_INFORMATION HandleInformation; PAGED_CODE(); OBTRACE(OB_HANDLE_DEBUG, @@ -1835,32 +2019,77 @@ ObDuplicateObject(IN PEPROCESS SourceProcess, SourceProcess, TargetProcess); - /* Check if we're not in the source process */ - if (SourceProcess != PsGetCurrentProcess()) + /* Check if we're not duplicating the same access */ + if (!(Options & DUPLICATE_SAME_ACCESS)) { - /* Attach to it */ - KeStackAttachProcess(&SourceProcess->Pcb, &ApcState); - AttachedToProcess = TRUE; + /* Validate the desired access */ + Status = STATUS_SUCCESS; //ObpValidateDesiredAccess(DesiredAccess); + if (!NT_SUCCESS(Status)) return Status; } - /* Now reference the source handle */ - Status = ObReferenceObjectByHandle(SourceHandle, - 0, - NULL, - PreviousMode, - (PVOID*)&SourceObject, - &HandleInformation); + /* Reference the object table */ + HandleTable = ObReferenceProcessHandleTable(SourceProcess); + if (!HandleTable) return STATUS_PROCESS_IS_TERMINATING; - /* Check if we were attached */ - if (AttachedToProcess) + /* Reference the process object */ + Status = ObpReferenceProcessObjectByHandle(SourceHandle, + 0, + HandleTable, + PreviousMode, + &SourceObject, + &HandleInformation); + if (!NT_SUCCESS(Status)) { - /* We can safely detach now */ - KeUnstackDetachProcess(&ApcState); - AttachedToProcess = FALSE; + /* Fail */ + ObDereferenceProcessHandleTable(SourceProcess); + return Status; } - /* Fail if we couldn't reference it */ - if (!NT_SUCCESS(Status)) return Status; + /* Check if there's no target process */ + if (!TargetProcess) + { + /* Check if the caller wanted actual duplication */ + if (!(Options & DUPLICATE_CLOSE_SOURCE)) + { + /* Invalid request */ + Status = STATUS_INVALID_PARAMETER; + } + else + { + /* Otherwise, do the attach */ + KeStackAttachProcess(&SourceProcess->Pcb, &ApcState); + + /* Close the handle and detach */ + NtClose(SourceHandle); + KeUnstackDetachProcess(&ApcState); + } + + /* Return */ + ObDereferenceProcessHandleTable(SourceProcess); + ObDereferenceObject(SourceObject); + return Status; + } + + /* Get the target handle table */ + HandleTable = ObReferenceProcessHandleTable(TargetProcess); + if (!HandleTable) + { + /* Check if the caller wanted us to close the handle */ + if (Options & DUPLICATE_CLOSE_SOURCE) + { + /* Do the attach */ + KeStackAttachProcess(&SourceProcess->Pcb, &ApcState); + + /* Close the handle and detach */ + NtClose(SourceHandle); + KeUnstackDetachProcess(&ApcState); + } + + /* Return */ + ObDereferenceProcessHandleTable(SourceProcess); + ObDereferenceObject(SourceObject); + return STATUS_PROCESS_IS_TERMINATING; + } /* Get the source access */ SourceAccess = HandleInformation.GrantedAccess; @@ -1898,7 +2127,8 @@ ObDuplicateObject(IN PEPROCESS SourceProcess, if (DesiredAccess & GENERIC_ACCESS) { /* Map it */ - RtlMapGenericMask(&DesiredAccess, &ObjectType->TypeInfo.GenericMapping); + RtlMapGenericMask(&DesiredAccess, + &ObjectType->TypeInfo.GenericMapping); } /* Set the target access */ @@ -1940,9 +2170,6 @@ ObDuplicateObject(IN PEPROCESS SourceProcess, HandleAttributes, PsGetCurrentProcess(), ObDuplicateHandle); - - /* Set the handle table, now that we know this handle was added */ - HandleTable = PsGetCurrentProcess()->ObjectTable; } /* Check if we were attached */ @@ -1990,6 +2217,10 @@ ObDuplicateObject(IN PEPROCESS SourceProcess, /* Return the handle */ if (TargetHandle) *TargetHandle = NewHandle; + /* Dereference handle tables */ + ObDereferenceProcessHandleTable(SourceProcess); + ObDereferenceProcessHandleTable(TargetProcess); + /* Return status */ OBTRACE(OB_HANDLE_DEBUG, "%s - Duplicated handle: %lx for %p into %p. Source: %p HC PC %lx %lx\n", diff --git a/reactos/ntoskrnl/ob/obref.c b/reactos/ntoskrnl/ob/obref.c index 60e83cf7abd..519f6798aa2 100644 --- a/reactos/ntoskrnl/ob/obref.c +++ b/reactos/ntoskrnl/ob/obref.c @@ -478,8 +478,8 @@ ObReferenceObjectByHandle(IN HANDLE Handle, NTSTATUS Status; PAGED_CODE(); - /* Fail immediately if the handle is NULL */ - if (!Handle) return STATUS_INVALID_HANDLE; + /* Assume failure */ + *Object = NULL; /* Check if the caller wants the current process */ if ((Handle == NtCurrentProcess()) && @@ -488,9 +488,6 @@ ObReferenceObjectByHandle(IN HANDLE Handle, /* Get the current process */ CurrentProcess = PsGetCurrentProcess(); - /* Reference ourselves */ - ObReferenceObject(CurrentProcess); - /* Check if the caller wanted handle information */ if (HandleInformation) { @@ -499,6 +496,10 @@ ObReferenceObjectByHandle(IN HANDLE Handle, HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS; } + /* Reference ourselves */ + ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentProcess); + InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1); + /* Return the pointer */ *Object = CurrentProcess; return STATUS_SUCCESS; @@ -516,9 +517,6 @@ ObReferenceObjectByHandle(IN HANDLE Handle, /* Get the current thread */ CurrentThread = PsGetCurrentThread(); - /* Reference ourselves */ - ObReferenceObject(CurrentThread); - /* Check if the caller wanted handle information */ if (HandleInformation) { @@ -527,6 +525,10 @@ ObReferenceObjectByHandle(IN HANDLE Handle, HandleInformation->GrantedAccess = THREAD_ALL_ACCESS; } + /* Reference ourselves */ + ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentThread); + InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1); + /* Return the pointer */ *Object = CurrentThread; return STATUS_SUCCESS; @@ -551,6 +553,7 @@ ObReferenceObjectByHandle(IN HANDLE Handle, } /* Enter a critical region while we touch the handle table */ + ASSERT(HandleTable != NULL); KeEnterCriticalRegion(); /* Get the handle entry */ @@ -588,9 +591,10 @@ ObReferenceObjectByHandle(IN HANDLE Handle, /* Unlock the handle */ ExUnlockHandleTableEntry(HandleTable, HandleEntry); + KeLeaveCriticalRegion(); /* Return success */ - KeLeaveCriticalRegion(); + ASSERT(*Object != NULL); return STATUS_SUCCESS; } else From 78749a977a9413fe7e5709a58edf299d2ff99ae5 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Wed, 10 Jan 2007 03:42:10 +0000 Subject: [PATCH 07/36] Should be 7 zeros not 6. svn path=/trunk/; revision=25409 --- reactos/subsystems/win32/win32k/include/input.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reactos/subsystems/win32/win32k/include/input.h b/reactos/subsystems/win32/win32k/include/input.h index bee57e3653e..6f201eae1b7 100644 --- a/reactos/subsystems/win32/win32k/include/input.h +++ b/reactos/subsystems/win32/win32k/include/input.h @@ -18,8 +18,8 @@ typedef struct _KBL PKBDRVFILE pkbdf; } KBL, *PKBL; -#define KBL_UNLOADED 0x2000000 -#define KBL_RESET 0x4000000 +#define KBL_UNLOADED 0x20000000 +#define KBL_RESET 0x40000000 NTSTATUS FASTCALL InitInputImpl(VOID); From d8160f0676ed8e723b0d911569b3543921ab2faa Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Wed, 10 Jan 2007 04:23:33 +0000 Subject: [PATCH 08/36] Make NtUserSetFocus accept NULL window. svn path=/trunk/; revision=25410 --- .../subsystems/win32/win32k/ntuser/focus.c | 51 ++++++++++++------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/reactos/subsystems/win32/win32k/ntuser/focus.c b/reactos/subsystems/win32/win32k/ntuser/focus.c index f98a4289522..3f764aa2570 100644 --- a/reactos/subsystems/win32/win32k/ntuser/focus.c +++ b/reactos/subsystems/win32/win32k/ntuser/focus.c @@ -304,27 +304,37 @@ co_IntSetActiveWindow(PWINDOW_OBJECT Window OPTIONAL) static HWND FASTCALL -co_IntSetFocusWindow(PWINDOW_OBJECT Window) +co_IntSetFocusWindow(PWINDOW_OBJECT Window OPTIONAL) { HWND hWndPrev = 0; PUSER_MESSAGE_QUEUE ThreadQueue; - ASSERT_REFS_CO(Window); + if (Window) + ASSERT_REFS_CO(Window); ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetCurrentThreadWin32Thread()->MessageQueue; ASSERT(ThreadQueue != 0); hWndPrev = ThreadQueue->FocusWindow; - if (hWndPrev == Window->hSelf) + + if (Window != 0) { - return hWndPrev; + if (hWndPrev == Window->hSelf) + { + return hWndPrev; + } + + ThreadQueue->FocusWindow = Window->hSelf; + + co_IntSendKillFocusMessages(hWndPrev, Window->hSelf); + co_IntSendSetFocusMessages(hWndPrev, Window->hSelf); + } + else + { + ThreadQueue->FocusWindow = 0; + + co_IntSendKillFocusMessages(hWndPrev, 0); } - - ThreadQueue->FocusWindow = Window->hSelf; - - co_IntSendKillFocusMessages(hWndPrev, Window->hSelf); - co_IntSendSetFocusMessages(hWndPrev, Window->hSelf); - return hWndPrev; } @@ -562,16 +572,23 @@ NtUserSetFocus(HWND hWnd) DPRINT("Enter NtUserSetFocus(%x)\n", hWnd); UserEnterExclusive(); - if (!(Window = UserGetWindowObject(hWnd))) + if (hWnd) { - RETURN(NULL); - } + if (!(Window = UserGetWindowObject(hWnd))) + { + RETURN(NULL); + } - UserRefObjectCo(Window, &Ref); - ret = co_UserSetFocus(Window); - UserDerefObjectCo(Window); + UserRefObjectCo(Window, &Ref); + ret = co_UserSetFocus(Window); + UserDerefObjectCo(Window); - RETURN(ret); + RETURN(ret); + } + else + { + RETURN( co_UserSetFocus(0)); + } CLEANUP: DPRINT("Leave NtUserSetFocus, ret=%i\n",_ret_); From 6af685313a7b1e54d40f710fc3adfa4eedb86329 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Wed, 10 Jan 2007 04:27:40 +0000 Subject: [PATCH 09/36] - Commit NTLPC and remove old implementation. - Yeah, this adds another regression on top of the new Ob stuff, but in the end it's for the better, as it removes more race conditions and buggy code. - This whole week I've fixed about 45 bugs and removed a dozen race conditions, sorry for the 2-3 regressions, they will be fixed ASAP. - DELETE MAKEFILE.AUTO BEFORE BUILDING THIS BUILD. svn path=/trunk/; revision=25411 --- reactos/config.template.rbuild | 2 +- reactos/ntoskrnl/include/internal/lpc.h | 242 ++- .../{lpc/ntlpc => include/internal}/lpc_x.h | 244 +-- reactos/ntoskrnl/lpc/close.c | 453 ++++-- reactos/ntoskrnl/lpc/complete.c | 426 ++++- reactos/ntoskrnl/lpc/connect.c | 1371 ++++++----------- reactos/ntoskrnl/lpc/create.c | 315 ++-- reactos/ntoskrnl/lpc/listen.c | 90 +- reactos/ntoskrnl/lpc/ntlpc/close.c | 395 ----- reactos/ntoskrnl/lpc/ntlpc/complete.c | 376 ----- reactos/ntoskrnl/lpc/ntlpc/connect.c | 568 ------- reactos/ntoskrnl/lpc/ntlpc/create.c | 195 --- reactos/ntoskrnl/lpc/ntlpc/listen.c | 53 - reactos/ntoskrnl/lpc/ntlpc/lpc.h | 130 -- reactos/ntoskrnl/lpc/ntlpc/port.c | 109 -- reactos/ntoskrnl/lpc/ntlpc/reply.c | 491 ------ reactos/ntoskrnl/lpc/ntlpc/send.c | 426 ----- reactos/ntoskrnl/lpc/port.c | 148 +- reactos/ntoskrnl/lpc/query.c | 69 - reactos/ntoskrnl/lpc/queue.c | 83 - reactos/ntoskrnl/lpc/receive.c | 41 - reactos/ntoskrnl/lpc/reply.c | 849 +++++----- reactos/ntoskrnl/lpc/send.c | 765 ++++----- reactos/ntoskrnl/ntoskrnl.rbuild | 42 +- reactos/ntoskrnl/ob/obhandle.c | 3 +- 25 files changed, 2554 insertions(+), 5332 deletions(-) rename reactos/ntoskrnl/{lpc/ntlpc => include/internal}/lpc_x.h (97%) delete mode 100644 reactos/ntoskrnl/lpc/ntlpc/close.c delete mode 100644 reactos/ntoskrnl/lpc/ntlpc/complete.c delete mode 100644 reactos/ntoskrnl/lpc/ntlpc/connect.c delete mode 100644 reactos/ntoskrnl/lpc/ntlpc/create.c delete mode 100644 reactos/ntoskrnl/lpc/ntlpc/listen.c delete mode 100644 reactos/ntoskrnl/lpc/ntlpc/lpc.h delete mode 100644 reactos/ntoskrnl/lpc/ntlpc/port.c delete mode 100644 reactos/ntoskrnl/lpc/ntlpc/reply.c delete mode 100644 reactos/ntoskrnl/lpc/ntlpc/send.c delete mode 100644 reactos/ntoskrnl/lpc/query.c delete mode 100644 reactos/ntoskrnl/lpc/queue.c delete mode 100644 reactos/ntoskrnl/lpc/receive.c diff --git a/reactos/config.template.rbuild b/reactos/config.template.rbuild index 92c8107b284..252e5234a78 100644 --- a/reactos/config.template.rbuild +++ b/reactos/config.template.rbuild @@ -75,6 +75,6 @@ working on the \ntlpc directory. Leave this disabled unless you really know what you're doing. --> - + diff --git a/reactos/ntoskrnl/include/internal/lpc.h b/reactos/ntoskrnl/include/internal/lpc.h index 8803f81ad6d..5570e81c6dc 100644 --- a/reactos/ntoskrnl/include/internal/lpc.h +++ b/reactos/ntoskrnl/include/internal/lpc.h @@ -1,91 +1,56 @@ -#ifndef __INCLUDE_INTERNAL_PORT_H -#define __INCLUDE_INTERNAL_PORT_H +/* +* PROJECT: ReactOS Kernel +* LICENSE: GPL - See COPYING in the top level directory +* FILE: ntoskrnl/include/lpc.h +* PURPOSE: Internal header for the Local Procedure Call +* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) +*/ -/* EPORT.Type */ +// +// Define this if you want debugging support +// +#define _LPC_DEBUG_ 0x01 -#define EPORT_TYPE_SERVER_RQST_PORT (0) -#define EPORT_TYPE_SERVER_COMM_PORT (1) -#define EPORT_TYPE_CLIENT_COMM_PORT (2) +// +// These define the Debug Masks Supported +// +#define LPC_CREATE_DEBUG 0x01 +#define LPC_CLOSE_DEBUG 0x02 +#define LPC_CONNECT_DEBUG 0x04 +#define LPC_LISTEN_DEBUG 0x08 +#define LPC_REPLY_DEBUG 0x10 +#define LPC_COMPLETE_DEBUG 0x20 +#define LPC_SEND_DEBUG 0x40 -/* EPORT.State */ - -#define EPORT_INACTIVE (0) -#define EPORT_WAIT_FOR_CONNECT (1) -#define EPORT_WAIT_FOR_ACCEPT (2) -#define EPORT_WAIT_FOR_COMPLETE_SRV (3) -#define EPORT_WAIT_FOR_COMPLETE_CLT (4) -#define EPORT_CONNECTED_CLIENT (5) -#define EPORT_CONNECTED_SERVER (6) -#define EPORT_DISCONNECTED (7) - -extern POBJECT_TYPE LpcPortObjectType; -extern ULONG LpcpNextMessageId; -#ifndef NTLPC -extern FAST_MUTEX LpcpLock; +// +// Debug/Tracing support +// +#if _LPC_DEBUG_ +#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented +#define LPCTRACE(x, ...) \ + { \ + DbgPrintEx("%s [%.16s] - ", \ + __FUNCTION__, \ + PsGetCurrentProcess()->ImageFileName); \ + DbgPrintEx(__VA_ARGS__); \ + } +#else +#define LPCTRACE(x, ...) \ + if (x & LpcpTraceLevel) \ + { \ + DbgPrint("%s [%.16s:%lx] - ", \ + __FUNCTION__, \ + PsGetCurrentProcess()->ImageFileName, \ + PsGetCurrentThreadId()); \ + DbgPrint(__VA_ARGS__); \ + } +#endif #endif -typedef struct _EPORT_LISTENER -{ - HANDLE ListenerPid; - LIST_ENTRY ListenerListEntry; -} EPORT_LISTENER, *PEPORT_LISTENER; - -typedef struct _EPORT -{ - KSPIN_LOCK Lock; - KSEMAPHORE Semaphore; - USHORT Type; - USHORT State; - struct _EPORT *RequestPort; - struct _EPORT *OtherPort; - ULONG QueueLength; - LIST_ENTRY QueueListHead; - ULONG ConnectQueueLength; - LIST_ENTRY ConnectQueueListHead; - ULONG MaxDataLength; - ULONG MaxConnectInfoLength; - ULONG MaxPoolUsage; /* size of NP zone */ -} EPORT, *PEPORT; - -typedef struct _EPORT_CONNECT_REQUEST_MESSAGE -{ - PORT_MESSAGE MessageHeader; - PEPROCESS ConnectingProcess; - struct _SECTION_OBJECT* SendSectionObject; - LARGE_INTEGER SendSectionOffset; - ULONG SendViewSize; - ULONG ConnectDataLength; - UCHAR ConnectData[0]; -} EPORT_CONNECT_REQUEST_MESSAGE, *PEPORT_CONNECT_REQUEST_MESSAGE; - -typedef struct _EPORT_CONNECT_REPLY_MESSAGE -{ - PORT_MESSAGE MessageHeader; - PVOID SendServerViewBase; - ULONG ReceiveClientViewSize; - PVOID ReceiveClientViewBase; - ULONG MaximumMessageSize; - ULONG ConnectDataLength; - UCHAR ConnectData[0]; -} EPORT_CONNECT_REPLY_MESSAGE, *PEPORT_CONNECT_REPLY_MESSAGE; - -typedef struct _QUEUEDMESSAGE -{ - PEPORT Sender; - LIST_ENTRY QueueListEntry; - PORT_MESSAGE Message; -} QUEUEDMESSAGE, *PQUEUEDMESSAGE; - -NTSTATUS -NTAPI -LpcSendTerminationPort( - PEPORT Port, - LARGE_INTEGER CreationTime -); - -/* Code in ntoskrnl/lpc/close.c */ - -VOID +// +// Internal Port Management +// +VOID NTAPI LpcpClosePort( IN PEPROCESS Process OPTIONAL, @@ -97,66 +62,69 @@ LpcpClosePort( VOID NTAPI -LpcpDeletePort(IN PVOID ObjectBody); - -VOID -NTAPI -LpcExitThread(IN PETHREAD Thread); - -/* Code in ntoskrnl/lpc/queue.c */ - -VOID -NTAPI -EiEnqueueConnectMessagePort( - IN OUT PEPORT Port, - IN PQUEUEDMESSAGE Message -); - -VOID -NTAPI -EiEnqueueMessagePort( - IN OUT PEPORT Port, - IN PQUEUEDMESSAGE Message -); - -VOID -NTAPI -EiEnqueueMessageAtHeadPort( - IN OUT PEPORT Port, - IN PQUEUEDMESSAGE Message -); - -PQUEUEDMESSAGE -NTAPI -EiDequeueConnectMessagePort(IN OUT PEPORT Port); - -PQUEUEDMESSAGE -NTAPI -EiDequeueMessagePort(IN OUT PEPORT Port); - -/* Code in ntoskrnl/lpc/port.c */ - -NTSTATUS -NTAPI -LpcpInitializePort( - IN OUT PEPORT Port, - IN USHORT Type, - IN PEPORT Parent OPTIONAL +LpcpDeletePort( + IN PVOID ObjectBody ); NTSTATUS NTAPI -LpcpInitSystem (VOID); +LpcpInitializePortQueue( + IN PLPCP_PORT_OBJECT Port +); -/* Code in ntoskrnl/lpc/reply.c */ - -NTSTATUS +VOID NTAPI -EiReplyOrRequestPort( - IN PEPORT Port, - IN PPORT_MESSAGE LpcReply, +LpcpFreeToPortZone( + IN PLPCP_MESSAGE Message, + IN ULONG Flags +); + +VOID +NTAPI +LpcpMoveMessage( + IN PPORT_MESSAGE Destination, + IN PPORT_MESSAGE Origin, + IN PVOID Data, IN ULONG MessageType, - IN PEPORT Sender + IN PCLIENT_ID ClientId ); -#endif /* __INCLUDE_INTERNAL_PORT_H */ +VOID +NTAPI +LpcpSaveDataInfoMessage( + IN PLPCP_PORT_OBJECT Port, + IN PLPCP_MESSAGE Message +); + +// +// Module-external utlity functions +// +VOID +NTAPI +LpcExitThread( + IN PETHREAD Thread +); + +// +// Initialization functions +// +NTSTATUS +NTAPI +LpcpInitSystem( + VOID +); + +// +// Global data inside the Process Manager +// +extern POBJECT_TYPE LpcPortObjectType; +extern ULONG LpcpNextMessageId, LpcpNextCallbackId; +extern KGUARDED_MUTEX LpcpLock; +extern PAGED_LOOKASIDE_LIST LpcpMessagesLookaside; +extern ULONG LpcpMaxMessageSize; +extern ULONG LpcpTraceLevel; + +// +// Inlined Functions +// +#include "lpc_x.h" diff --git a/reactos/ntoskrnl/lpc/ntlpc/lpc_x.h b/reactos/ntoskrnl/include/internal/lpc_x.h similarity index 97% rename from reactos/ntoskrnl/lpc/ntlpc/lpc_x.h rename to reactos/ntoskrnl/include/internal/lpc_x.h index 3c0bc8fd86b..0ba3b0aac74 100644 --- a/reactos/ntoskrnl/lpc/ntlpc/lpc_x.h +++ b/reactos/ntoskrnl/include/internal/lpc_x.h @@ -1,122 +1,122 @@ -/* -* PROJECT: ReactOS Kernel -* LICENSE: GPL - See COPYING in the top level directory -* FILE: ntoskrnl/include/lpc_x.h -* PURPOSE: Intenral Inlined Functions for Local Procedure Call -* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) -*/ - -// -// Gets the message type, removing the kernel-mode flag -// -#define LpcpGetMessageType(x) \ - ((x)->u2.s2.Type &~ LPC_KERNELMODE_MESSAGE) - -// -// Waits on an LPC semaphore for a receive operation -// -#define LpcpReceiveWait(s, w) \ -{ \ - LPCTRACE(LPC_REPLY_DEBUG, "Wait: %p\n", s); \ - Status = KeWaitForSingleObject(s, \ - WrLpcReceive, \ - w, \ - FALSE, \ - NULL); \ - LPCTRACE(LPC_REPLY_DEBUG, "Wait done: %lx\n", Status); \ -} - -// -// Waits on an LPC semaphore for a reply operation -// -#define LpcpReplyWait(s, w) \ -{ \ - LPCTRACE(LPC_SEND_DEBUG, "Wait: %p\n", s); \ - Status = KeWaitForSingleObject(s, \ - WrLpcReply, \ - w, \ - FALSE, \ - NULL); \ - LPCTRACE(LPC_SEND_DEBUG, "Wait done: %lx\n", Status); \ - if (Status == STATUS_USER_APC) \ - { \ - /* We were preempted by an APC */ \ - if (KeReadStateSemaphore(s)) \ - { \ - /* It's still signaled, so wait on it */ \ - KeWaitForSingleObject(s, \ - Executive, \ - KernelMode, \ - FALSE, \ - NULL); \ - Status = STATUS_SUCCESS; \ - } \ - } \ -} - -// -// Waits on an LPC semaphore for a connect operation -// -#define LpcpConnectWait(s, w) \ -{ \ - LPCTRACE(LPC_CONNECT_DEBUG, "Wait: %p\n", s); \ - Status = KeWaitForSingleObject(s, \ - Executive, \ - w, \ - FALSE, \ - NULL); \ - LPCTRACE(LPC_CONNECT_DEBUG, "Wait done: %lx\n", Status);\ - if (Status == STATUS_USER_APC) \ - { \ - /* We were preempted by an APC */ \ - if (KeReadStateSemaphore(s)) \ - { \ - /* It's still signaled, so wait on it */ \ - KeWaitForSingleObject(s, \ - Executive, \ - KernelMode, \ - FALSE, \ - NULL); \ - Status = STATUS_SUCCESS; \ - } \ - } \ -} - -// -// Releases an LPC Semaphore to complete a wait -// -#define LpcpCompleteWait(s) \ -{ \ - /* Release the semaphore */ \ - LPCTRACE(LPC_SEND_DEBUG, "Release: %p\n", s); \ - KeReleaseSemaphore(s, 1, 1, FALSE); \ -} - -// -// Allocates a new message -// -PLPCP_MESSAGE -FORCEINLINE -LpcpAllocateFromPortZone(VOID) -{ - PLPCP_MESSAGE Message; - - /* Allocate a message from the port zone while holding the lock */ - KeAcquireGuardedMutex(&LpcpLock); - Message = ExAllocateFromPagedLookasideList(&LpcpMessagesLookaside); - if (!Message) - { - /* Fail, and let caller cleanup */ - KeReleaseGuardedMutex(&LpcpLock); - return NULL; - } - - /* Initialize it */ - InitializeListHead(&Message->Entry); - Message->RepliedToThread = NULL; - Message->Request.u2.ZeroInit = 0; - - /* Release the lock */ - KeReleaseGuardedMutex(&LpcpLock); - return Message; -} +/* +* PROJECT: ReactOS Kernel +* LICENSE: GPL - See COPYING in the top level directory +* FILE: ntoskrnl/include/lpc_x.h +* PURPOSE: Intenral Inlined Functions for Local Procedure Call +* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) +*/ + +// +// Gets the message type, removing the kernel-mode flag +// +#define LpcpGetMessageType(x) \ + ((x)->u2.s2.Type &~ LPC_KERNELMODE_MESSAGE) + +// +// Waits on an LPC semaphore for a receive operation +// +#define LpcpReceiveWait(s, w) \ +{ \ + LPCTRACE(LPC_REPLY_DEBUG, "Wait: %p\n", s); \ + Status = KeWaitForSingleObject(s, \ + WrLpcReceive, \ + w, \ + FALSE, \ + NULL); \ + LPCTRACE(LPC_REPLY_DEBUG, "Wait done: %lx\n", Status); \ +} + +// +// Waits on an LPC semaphore for a reply operation +// +#define LpcpReplyWait(s, w) \ +{ \ + LPCTRACE(LPC_SEND_DEBUG, "Wait: %p\n", s); \ + Status = KeWaitForSingleObject(s, \ + WrLpcReply, \ + w, \ + FALSE, \ + NULL); \ + LPCTRACE(LPC_SEND_DEBUG, "Wait done: %lx\n", Status); \ + if (Status == STATUS_USER_APC) \ + { \ + /* We were preempted by an APC */ \ + if (KeReadStateSemaphore(s)) \ + { \ + /* It's still signaled, so wait on it */ \ + KeWaitForSingleObject(s, \ + Executive, \ + KernelMode, \ + FALSE, \ + NULL); \ + Status = STATUS_SUCCESS; \ + } \ + } \ +} + +// +// Waits on an LPC semaphore for a connect operation +// +#define LpcpConnectWait(s, w) \ +{ \ + LPCTRACE(LPC_CONNECT_DEBUG, "Wait: %p\n", s); \ + Status = KeWaitForSingleObject(s, \ + Executive, \ + w, \ + FALSE, \ + NULL); \ + LPCTRACE(LPC_CONNECT_DEBUG, "Wait done: %lx\n", Status);\ + if (Status == STATUS_USER_APC) \ + { \ + /* We were preempted by an APC */ \ + if (KeReadStateSemaphore(s)) \ + { \ + /* It's still signaled, so wait on it */ \ + KeWaitForSingleObject(s, \ + Executive, \ + KernelMode, \ + FALSE, \ + NULL); \ + Status = STATUS_SUCCESS; \ + } \ + } \ +} + +// +// Releases an LPC Semaphore to complete a wait +// +#define LpcpCompleteWait(s) \ +{ \ + /* Release the semaphore */ \ + LPCTRACE(LPC_SEND_DEBUG, "Release: %p\n", s); \ + KeReleaseSemaphore(s, 1, 1, FALSE); \ +} + +// +// Allocates a new message +// +PLPCP_MESSAGE +FORCEINLINE +LpcpAllocateFromPortZone(VOID) +{ + PLPCP_MESSAGE Message; + + /* Allocate a message from the port zone while holding the lock */ + KeAcquireGuardedMutex(&LpcpLock); + Message = ExAllocateFromPagedLookasideList(&LpcpMessagesLookaside); + if (!Message) + { + /* Fail, and let caller cleanup */ + KeReleaseGuardedMutex(&LpcpLock); + return NULL; + } + + /* Initialize it */ + InitializeListHead(&Message->Entry); + Message->RepliedToThread = NULL; + Message->Request.u2.ZeroInit = 0; + + /* Release the lock */ + KeReleaseGuardedMutex(&LpcpLock); + return Message; +} diff --git a/reactos/ntoskrnl/lpc/close.c b/reactos/ntoskrnl/lpc/close.c index cf569dc02b6..af9803dbfc7 100644 --- a/reactos/ntoskrnl/lpc/close.c +++ b/reactos/ntoskrnl/lpc/close.c @@ -1,25 +1,29 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/lpc/close.c - * PURPOSE: Communication mechanism - * - * PROGRAMMERS: David Welch (welch@cwcom.net) + * PURPOSE: Local Procedure Call: Rundown, Cleanup, Deletion + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ -/* INCLUDES *****************************************************************/ +/* INCLUDES ******************************************************************/ #include +#include "lpc.h" #define NDEBUG #include -/* FUNCTIONS *****************************************************************/ +/* PRIVATE FUNCTIONS *********************************************************/ VOID NTAPI LpcExitThread(IN PETHREAD Thread) { + PLPCP_MESSAGE Message; + + /* Acquire the lock */ + KeAcquireGuardedMutex(&LpcpLock); + /* Make sure that the Reply Chain is empty */ if (!IsListEmpty(&Thread->LpcReplyChain)) { @@ -31,104 +35,361 @@ LpcExitThread(IN PETHREAD Thread) Thread->LpcExitThreadCalled = TRUE; Thread->LpcReplyMessageId = 0; - /* FIXME: Reply to the LpcReplyMessage */ -} - -/********************************************************************** - * NAME - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - */ -VOID STDCALL -LpcpClosePort (IN PEPROCESS Process OPTIONAL, - IN PVOID ObjectBody, - IN ACCESS_MASK GrantedAccess, - IN ULONG HandleCount, - IN ULONG SystemHandleCount) -{ - PEPORT Port = (PEPORT)ObjectBody; - PORT_MESSAGE Message; - - /* FIXME Race conditions here! */ - - /* - * If the client has just closed its handle then tell the server what - * happened and disconnect this port. - */ - if (!(HandleCount)&& (Port->State == EPORT_CONNECTED_CLIENT)) + /* Check if there's a reply message */ + Message = Thread->LpcReplyMessage; + if (Message) { - DPRINT("Informing server\n"); - Message.u1.s1.TotalLength = sizeof(PORT_MESSAGE); - Message.u1.s1.DataLength = 0; - EiReplyOrRequestPort (Port->OtherPort, - &Message, - LPC_PORT_CLOSED, - Port); - Port->OtherPort->OtherPort = NULL; - Port->OtherPort->State = EPORT_DISCONNECTED; - KeReleaseSemaphore( &Port->OtherPort->Semaphore, - IO_NO_INCREMENT, - 1, - FALSE ); - ObDereferenceObject (Port); + /* FIXME: TODO */ + KEBUGCHECK(0); } - /* - * If the server has closed all of its handles then disconnect the port, - * don't actually notify the client until it attempts an operation. - */ - if (!(HandleCount)&& (Port->State == EPORT_CONNECTED_SERVER)) - { - DPRINT("Cleaning up server\n"); - Port->OtherPort->OtherPort = NULL; - Port->OtherPort->State = EPORT_DISCONNECTED; - ObDereferenceObject(Port->OtherPort); - } + /* Release the lock */ + KeReleaseGuardedMutex(&LpcpLock); } - -/********************************************************************** - * NAME - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - */ -VOID STDCALL -LpcpDeletePort (PVOID ObjectBody) +VOID +NTAPI +LpcpFreeToPortZone(IN PLPCP_MESSAGE Message, + IN ULONG Flags) { - PLIST_ENTRY Entry; - PQUEUEDMESSAGE Message; + PLPCP_CONNECTION_MESSAGE ConnectMessage; + PLPCP_PORT_OBJECT ClientPort = NULL; + PETHREAD Thread = NULL; + BOOLEAN LockHeld = Flags & 1; + PAGED_CODE(); + LPCTRACE(LPC_CLOSE_DEBUG, "Message: %p. Flags: %lx\n", Message, Flags); - PEPORT Port = (PEPORT)ObjectBody; + /* Acquire the lock if not already */ + if (!LockHeld) KeAcquireGuardedMutex(&LpcpLock); - DPRINT("Deleting port %x\n", Port); + /* Check if the queue list is empty */ + if (!IsListEmpty(&Message->Entry)) + { + /* Remove and re-initialize */ + RemoveEntryList(&Message->Entry); + InitializeListHead(&Message->Entry); + } - /* Free all waiting messages */ - while (!IsListEmpty(&Port->QueueListHead)) - { - Entry = RemoveHeadList(&Port->QueueListHead); - Message = CONTAINING_RECORD (Entry, QUEUEDMESSAGE, QueueListEntry); - ExFreePool(Message); - } + /* Check if we've already replied */ + if (Message->RepliedToThread) + { + /* Set thread to dereference and clean up */ + Thread = Message->RepliedToThread; + Message->RepliedToThread = NULL; + } - while (!IsListEmpty(&Port->ConnectQueueListHead)) - { - Entry = RemoveHeadList(&Port->ConnectQueueListHead); - Message = CONTAINING_RECORD (Entry, QUEUEDMESSAGE, QueueListEntry); - ExFreePool(Message); - } + /* Check if this is a connection request */ + if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST) + { + /* Get the connection message */ + ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); + + /* Clear the client port */ + ClientPort = ConnectMessage->ClientPort; + if (ClientPort) ConnectMessage->ClientPort = NULL; + } + + /* Release the lock */ + KeReleaseGuardedMutex(&LpcpLock); + + /* Check if we had anything to dereference */ + if (Thread) ObDereferenceObject(Thread); + if (ClientPort) ObDereferenceObject(ClientPort); + + /* Free the entry */ + ExFreeToPagedLookasideList(&LpcpMessagesLookaside, Message); + + /* Reacquire the lock if needed */ + if ((LockHeld) && !(Flags & 2)) KeAcquireGuardedMutex(&LpcpLock); } +VOID +NTAPI +LpcpDestroyPortQueue(IN PLPCP_PORT_OBJECT Port, + IN BOOLEAN Destroy) +{ + PLIST_ENTRY ListHead, NextEntry; + PETHREAD Thread; + PLPCP_MESSAGE Message; + PLPCP_CONNECTION_MESSAGE ConnectMessage; + LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags); + + /* Hold the lock */ + KeAcquireGuardedMutex(&LpcpLock); + + /* Disconnect the port to which this port is connected */ + if (Port->ConnectedPort) Port->ConnectedPort->ConnectedPort = NULL; + + /* Check if this is a connection port */ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT) + { + /* Delete the name */ + Port->Flags |= LPCP_NAME_DELETED; + } + + /* Walk all the threads waiting and signal them */ + ListHead = &Port->LpcReplyChainHead; + NextEntry = ListHead->Flink; + while (NextEntry != ListHead) + { + /* Get the Thread */ + Thread = CONTAINING_RECORD(NextEntry, ETHREAD, LpcReplyChain); + + /* Make sure we're not in exit */ + if (Thread->LpcExitThreadCalled) break; + + /* Move to the next entry */ + NextEntry = NextEntry->Flink; + + /* Remove and reinitialize the List */ + RemoveEntryList(&Thread->LpcReplyChain); + InitializeListHead(&Thread->LpcReplyChain); + + /* Check if someone is waiting */ + if (!KeReadStateSemaphore(&Thread->LpcReplySemaphore)) + { + /* Get the message and check if it's a connection request */ + Message = Thread->LpcReplyMessage; + if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST) + { + /* Get the connection message */ + ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); + + /* Check if it had a section */ + if (ConnectMessage->SectionToMap) + { + /* Dereference it */ + ObDereferenceObject(ConnectMessage->SectionToMap); + } + } + + /* Clear the reply message */ + Thread->LpcReplyMessage = NULL; + + /* And remove the message from the port zone */ + LpcpFreeToPortZone(Message, TRUE); + } + + /* Release the semaphore and reset message id count */ + Thread->LpcReplyMessageId = 0; + LpcpCompleteWait(&Thread->LpcReplySemaphore); + } + + /* Reinitialize the list head */ + InitializeListHead(&Port->LpcReplyChainHead); + + /* Loop queued messages */ + ListHead = &Port->MsgQueue.ReceiveHead; + NextEntry = ListHead->Flink; + while (ListHead != NextEntry) + { + /* Get the message */ + Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry); + NextEntry = NextEntry->Flink; + + /* Free and reinitialize it's list head */ + InitializeListHead(&Message->Entry); + + /* Remove it from the port zone */ + LpcpFreeToPortZone(Message, TRUE); + } + + /* Reinitialize the message queue list head */ + InitializeListHead(&Port->MsgQueue.ReceiveHead); + + /* Release the lock */ + KeReleaseGuardedMutex(&LpcpLock); + + /* Check if we have to free the port entirely */ + if (Destroy) + { + /* Check if the semaphore exists */ + if (Port->MsgQueue.Semaphore) + { + /* Use the semaphore to find the port queue and free it */ + ExFreePool(CONTAINING_RECORD(Port->MsgQueue.Semaphore, + LPCP_NONPAGED_PORT_QUEUE, + Semaphore)); + } + } +} + +VOID +NTAPI +LpcpClosePort(IN PEPROCESS Process OPTIONAL, + IN PVOID Object, + IN ACCESS_MASK GrantedAccess, + IN ULONG ProcessHandleCount, + IN ULONG SystemHandleCount) +{ + PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)Object; + LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags); + + /* Only Server-side Connection Ports need clean up*/ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT) + { + /* Check the handle count */ + switch (SystemHandleCount) + { + /* No handles left */ + case 0: + + /* Destroy the port queue */ + LpcpDestroyPortQueue(Port, TRUE); + break; + + /* Last handle remaining */ + case 1: + + /* Reset the queue only */ + LpcpDestroyPortQueue(Port, FALSE); + + /* More handles remain, do nothing */ + default: + break; + } + } +} + +VOID +NTAPI +LpcpFreePortClientSecurity(IN PLPCP_PORT_OBJECT Port) +{ + /* Check if this is a client port */ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT) + { + /* Check if security is static */ + if (!(Port->Flags & LPCP_SECURITY_DYNAMIC)) + { + /* Check if we have a token */ + if (Port->StaticSecurity.ClientToken) + { + /* Free security */ + SeDeleteClientSecurity(&Port->StaticSecurity); + } + } + } +} + +VOID +NTAPI +LpcpDeletePort(IN PVOID ObjectBody) +{ + LARGE_INTEGER Timeout; + PETHREAD Thread; + PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)ObjectBody; + PLPCP_PORT_OBJECT ConnectionPort; + PLPCP_MESSAGE Message; + PLIST_ENTRY ListHead, NextEntry; + HANDLE Pid; + CLIENT_DIED_MSG ClientDiedMsg; + Timeout.QuadPart = -1000000; + PAGED_CODE(); + LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags); + + /* Check if this is a communication port */ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_COMMUNICATION_PORT) + { + /* Acquire the lock */ + KeAcquireGuardedMutex(&LpcpLock); + + /* Get the thread */ + Thread = Port->ClientThread; + if (Thread) + { + /* Clear it */ + Port->ClientThread = NULL; + + /* Release the lock and dereference */ + KeReleaseGuardedMutex(&LpcpLock); + ObDereferenceObject(Thread); + } + else + { + /* Release the lock */ + KeReleaseGuardedMutex(&LpcpLock); + } + } + + /* Check if this is a client-side port */ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT) + { + /* Setup the client died message */ + ClientDiedMsg.h.u1.s1.TotalLength = sizeof(ClientDiedMsg); + ClientDiedMsg.h.u1.s1.DataLength = sizeof(ClientDiedMsg.CreateTime); + ClientDiedMsg.h.u2.ZeroInit = LPC_PORT_CLOSED; + ClientDiedMsg.CreateTime = PsGetCurrentProcess()->CreateTime; + + /* Send it */ + for (;;) + { + /* Send the message */ + if (LpcRequestPort(Port, + &ClientDiedMsg.h) != STATUS_NO_MEMORY) break; + + /* Wait until trying again */ + KeDelayExecutionThread(KernelMode, FALSE, &Timeout); + } + } + + /* Destroy the port queue */ + LpcpDestroyPortQueue(Port, TRUE); + + /* Check if we had a client view */ + if (Port->ClientSectionBase) MmUnmapViewOfSection(PsGetCurrentProcess(), + Port->ClientSectionBase); + + /* Check for a server view */ + if (Port->ServerSectionBase) MmUnmapViewOfSection(PsGetCurrentProcess(), + Port->ServerSectionBase); + + /* Get the connection port */ + ConnectionPort = Port->ConnectionPort; + if (ConnectionPort) + { + /* Get the PID */ + Pid = PsGetCurrentProcessId(); + + /* Acquire the lock */ + KeAcquireGuardedMutex(&LpcpLock); + + /* Loop the data lists */ + ListHead = &ConnectionPort->LpcDataInfoChainHead; + NextEntry = ListHead->Flink; + while (NextEntry != ListHead) + { + /* Get the message */ + Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry); + NextEntry = NextEntry->Flink; + + /* Check if the PID matches */ + if (Message->Request.ClientId.UniqueProcess == Pid) + { + /* Remove it */ + RemoveEntryList(&Message->Entry); + LpcpFreeToPortZone(Message, TRUE); + } + } + + /* Release the lock */ + KeReleaseGuardedMutex(&LpcpLock); + + /* Dereference the object unless it's the same port */ + if (ConnectionPort != Port) ObDereferenceObject(ConnectionPort); + } + + /* Check if this is a connection port with a server process*/ + if (((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT) && + (ConnectionPort->ServerProcess)) + { + /* Dereference the server process */ + ObDereferenceObject(ConnectionPort->ServerProcess); + ConnectionPort->ServerProcess = NULL; + } + + /* Free client security */ + LpcpFreePortClientSecurity(Port); + LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p deleted\n", Port); +} /* EOF */ diff --git a/reactos/ntoskrnl/lpc/complete.c b/reactos/ntoskrnl/lpc/complete.c index e14350d5623..b5e4e190ee1 100644 --- a/reactos/ntoskrnl/lpc/complete.c +++ b/reactos/ntoskrnl/lpc/complete.c @@ -1,82 +1,376 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/lpc/complete.c - * PURPOSE: Communication mechanism - * - * PROGRAMMERS: David Welch (welch@cwcom.net) - */ +/* +* PROJECT: ReactOS Kernel +* LICENSE: GPL - See COPYING in the top level directory +* FILE: ntoskrnl/lpc/complete.c +* PURPOSE: Local Procedure Call: Connection Completion +* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) +*/ /* INCLUDES ******************************************************************/ #include +#include "lpc.h" #define NDEBUG #include -/* FUNCTIONS *****************************************************************/ +/* PRIVATE FUNCTIONS *********************************************************/ -/*********************************************************************** - * NAME EXPORTED - * NtCompleteConnectPort/1 - * - * DESCRIPTION - * Wake up the client thread that issued the NtConnectPort call - * this server-side port was created for communicating with. - * To be used in LPC servers processes on reply ports only. - * - * ARGUMENTS - * hServerSideCommPort: a reply port handle returned by - * NtAcceptConnectPort. - * - * RETURN VALUE - * STATUS_SUCCESS or an error code from Ob. - */ -NTSTATUS STDCALL -NtCompleteConnectPort (HANDLE hServerSideCommPort) +VOID +NTAPI +LpcpPrepareToWakeClient(IN PETHREAD Thread) { - NTSTATUS Status; - PEPORT ReplyPort; + PAGED_CODE(); - DPRINT("NtCompleteConnectPort(hServerSideCommPort %x)\n", hServerSideCommPort); - - /* - * Ask Ob to translate the port handle to EPORT - */ - Status = ObReferenceObjectByHandle (hServerSideCommPort, - PORT_ALL_ACCESS, - LpcPortObjectType, - UserMode, - (PVOID*)&ReplyPort, - NULL); - if (!NT_SUCCESS(Status)) + /* Make sure the thread isn't dying and it has a valid chain */ + if (!(Thread->LpcExitThreadCalled) && + !(IsListEmpty(&Thread->LpcReplyChain))) { - return (Status); + /* Remove it from the list and reinitialize it */ + RemoveEntryList(&Thread->LpcReplyChain); + InitializeListHead(&Thread->LpcReplyChain); } - /* - * Verify EPORT type is a server-side reply port; - * otherwise tell the caller the port handle is not - * valid. - */ - if (ReplyPort->Type != EPORT_TYPE_SERVER_COMM_PORT) - { - ObDereferenceObject (ReplyPort); - return STATUS_INVALID_PORT_HANDLE; - } - - ReplyPort->State = EPORT_CONNECTED_SERVER; - /* - * Wake up the client thread that issued NtConnectPort. - */ - KeReleaseSemaphore(&ReplyPort->OtherPort->Semaphore, IO_NO_INCREMENT, 1, - FALSE); - /* - * Tell Ob we are no more interested in ReplyPort - */ - ObDereferenceObject (ReplyPort); - - return (STATUS_SUCCESS); } +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @implemented + */ +NTSTATUS +NTAPI +NtAcceptConnectPort(OUT PHANDLE PortHandle, + IN PVOID PortContext OPTIONAL, + IN PPORT_MESSAGE ReplyMessage, + IN BOOLEAN AcceptConnection, + IN PPORT_VIEW ServerView, + IN PREMOTE_PORT_VIEW ClientView) +{ + PLPCP_PORT_OBJECT ConnectionPort, ServerPort, ClientPort; + PVOID ClientSectionToMap = NULL; + HANDLE Handle; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); + NTSTATUS Status; + ULONG ConnectionInfoLength; + PLPCP_MESSAGE Message; + PLPCP_CONNECTION_MESSAGE ConnectMessage; + PEPROCESS ClientProcess; + PETHREAD ClientThread; + LARGE_INTEGER SectionOffset; + PAGED_CODE(); + LPCTRACE(LPC_COMPLETE_DEBUG, + "Context: %p. Message: %p. Accept: %lx. Views: %p/%p\n", + PortContext, + ReplyMessage, + AcceptConnection, + ClientView, + ServerView); + + /* Validate the size of the server view */ + if ((ServerView) && (ServerView->Length != sizeof(PORT_VIEW))) + { + /* Invalid size */ + return STATUS_INVALID_PARAMETER; + } + + /* Validate the size of the client view */ + if ((ClientView) && (ClientView->Length != sizeof(REMOTE_PORT_VIEW))) + { + /* Invalid size */ + return STATUS_INVALID_PARAMETER; + } + + /* Get the client process and thread */ + Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId, + &ClientProcess, + &ClientThread); + if (!NT_SUCCESS(Status)) return Status; + + /* Acquire the LPC Lock */ + KeAcquireGuardedMutex(&LpcpLock); + + /* Make sure that the client wants a reply, and this is the right one */ + if (!(ClientThread->LpcReplyMessage) || + !(ReplyMessage->MessageId) || + (ClientThread->LpcReplyMessageId != ReplyMessage->MessageId)) + { + /* Not the reply asked for, or no reply wanted, fail */ + KeReleaseGuardedMutex(&LpcpLock); + ObDereferenceObject(ClientProcess); + ObDereferenceObject(ClientThread); + return STATUS_REPLY_MESSAGE_MISMATCH; + } + + /* Now get the message and connection message */ + Message = ClientThread->LpcReplyMessage; + ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); + + /* Get the client and connection port as well */ + ClientPort = ConnectMessage->ClientPort; + ConnectionPort = ClientPort->ConnectionPort; + + /* Make sure that the reply is being sent to the proper server process */ + if (ConnectionPort->ServerProcess != PsGetCurrentProcess()) + { + /* It's not, so fail */ + KeReleaseGuardedMutex(&LpcpLock); + ObDereferenceObject(ClientProcess); + ObDereferenceObject(ClientThread); + return STATUS_REPLY_MESSAGE_MISMATCH; + } + + /* At this point, don't let other accept attempts happen */ + ClientThread->LpcReplyMessage = NULL; + ClientThread->LpcReplyMessageId = 0; + + /* Clear the client port for now as well, then release the lock */ + ConnectMessage->ClientPort = NULL; + KeReleaseGuardedMutex(&LpcpLock); + + /* Get the connection information length */ + ConnectionInfoLength = ReplyMessage->u1.s1.DataLength; + if (ConnectionInfoLength > ConnectionPort->MaxConnectionInfoLength) + { + /* Normalize it since it's too large */ + ConnectionInfoLength = ConnectionPort->MaxConnectionInfoLength; + } + + /* Set the sizes of our reply message */ + Message->Request.u1.s1.DataLength = sizeof(LPCP_CONNECTION_MESSAGE) + + ConnectionInfoLength; + Message->Request.u1.s1.TotalLength = sizeof(LPCP_MESSAGE) + + Message->Request.u1.s1.DataLength; + + /* Setup the reply message */ + Message->Request.u2.s2.Type = LPC_REPLY; + Message->Request.u2.s2.DataInfoOffset = 0; + Message->Request.ClientId = ReplyMessage->ClientId; + Message->Request.MessageId = ReplyMessage->MessageId; + Message->Request.ClientViewSize = 0; + RtlMoveMemory(ConnectMessage + 1, ReplyMessage + 1, ConnectionInfoLength); + + /* At this point, if the caller refused the connection, go to cleanup */ + if (!AcceptConnection) goto Cleanup; + + /* Otherwise, create the actual port */ + Status = ObCreateObject(PreviousMode, + LpcPortObjectType, + NULL, + PreviousMode, + NULL, + sizeof(LPCP_PORT_OBJECT), + 0, + 0, + (PVOID*)&ServerPort); + if (!NT_SUCCESS(Status)) goto Cleanup; + + /* Set it up */ + RtlZeroMemory(ServerPort, sizeof(LPCP_PORT_OBJECT)); + ServerPort->PortContext = PortContext; + ServerPort->Flags = LPCP_COMMUNICATION_PORT; + ServerPort->MaxMessageLength = ConnectionPort->MaxMessageLength; + InitializeListHead(&ServerPort->LpcReplyChainHead); + InitializeListHead(&ServerPort->LpcDataInfoChainHead); + + /* Reference the connection port until we're fully setup */ + ObReferenceObject(ConnectionPort); + + /* Link the ports together */ + ServerPort->ConnectionPort = ConnectionPort; + ServerPort->ConnectedPort = ClientPort; + ClientPort->ConnectedPort = ServerPort; + + /* Also set the creator CID */ + ServerPort->Creator = PsGetCurrentThread()->Cid; + ClientPort->Creator = Message->Request.ClientId; + + /* Get the section associated and then clear it, while inside the lock */ + KeAcquireGuardedMutex(&LpcpLock); + ClientSectionToMap = ConnectMessage->SectionToMap; + ConnectMessage->SectionToMap = NULL; + KeReleaseGuardedMutex(&LpcpLock); + + /* Now check if there's a client section */ + if (ClientSectionToMap) + { + /* Setup the offset */ + SectionOffset.QuadPart = ConnectMessage->ClientView.SectionOffset; + + /* Map the section */ + Status = MmMapViewOfSection(ClientSectionToMap, + PsGetCurrentProcess(), + &ServerPort->ClientSectionBase, + 0, + 0, + &SectionOffset, + &ConnectMessage->ClientView.ViewSize, + ViewUnmap, + 0, + PAGE_READWRITE); + + /* Update the offset and check for mapping status */ + ConnectMessage->ClientView.SectionOffset = SectionOffset.LowPart; + if (NT_SUCCESS(Status)) + { + /* Set the view base */ + ConnectMessage->ClientView.ViewRemoteBase = ServerPort-> + ClientSectionBase; + } + else + { + /* Otherwise, quit */ + ObDereferenceObject(ServerPort); + goto Cleanup; + } + } + + /* Check if there's a server section */ + if (ServerView) + { + /* FIXME: TODO */ + ASSERT(FALSE); + } + + /* Reference the server port until it's fully inserted */ + ObReferenceObject(ServerPort); + + /* Insert the server port in the namespace */ + Status = ObInsertObject(ServerPort, + NULL, + PORT_ALL_ACCESS, + 0, + NULL, + &Handle); + if (!NT_SUCCESS(Status)) + { + /* We failed, remove the extra reference and cleanup */ + ObDereferenceObject(ServerPort); + goto Cleanup; + } + + /* Check if the caller gave a client view */ + if (ClientView) + { + /* Fill it out */ + ClientView->ViewBase = ConnectMessage->ClientView.ViewRemoteBase; + ClientView->ViewSize = ConnectMessage->ClientView.ViewSize; + } + + /* Return the handle to user mode */ + *PortHandle = Handle; + LPCTRACE(LPC_COMPLETE_DEBUG, + "Handle: %lx. Messages: %p/%p. Ports: %p/%p/%p\n", + Handle, + Message, + ConnectMessage, + ServerPort, + ClientPort, + ConnectionPort); + + /* If there was no port context, use the handle by default */ + if (!PortContext) ServerPort->PortContext = Handle; + ServerPort->ClientThread = ClientThread; + + /* Set this message as the LPC Reply message while holding the lock */ + KeAcquireGuardedMutex(&LpcpLock); + ClientThread->LpcReplyMessage = Message; + KeReleaseGuardedMutex(&LpcpLock); + + /* Clear the thread pointer so it doesn't get cleaned later */ + ClientThread = NULL; + + /* Remove the extra reference we had added */ + ObDereferenceObject(ServerPort); + +Cleanup: + /* If there was a section, dereference it */ + if (ClientSectionToMap) ObDereferenceObject(ClientSectionToMap); + + /* Check if we got here while still having a client thread */ + if (ClientThread) + { + /* FIXME: Complex cleanup code */ + ASSERT(FALSE); + } + + /* Dereference the client port if we have one, and the process */ + LPCTRACE(LPC_COMPLETE_DEBUG, + "Status: %lx. Thread: %p. Process: [%.16s]\n", + Status, + ClientThread, + ClientProcess->ImageFileName); + if (ClientPort) ObDereferenceObject(ClientPort); + ObDereferenceObject(ClientProcess); + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +NtCompleteConnectPort(IN HANDLE PortHandle) +{ + NTSTATUS Status; + PLPCP_PORT_OBJECT Port; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); + PETHREAD Thread; + PAGED_CODE(); + LPCTRACE(LPC_COMPLETE_DEBUG, "Handle: %lx\n", PortHandle); + + /* Get the Port Object */ + Status = ObReferenceObjectByHandle(PortHandle, + PORT_ALL_ACCESS, + LpcPortObjectType, + PreviousMode, + (PVOID*)&Port, + NULL); + if (!NT_SUCCESS(Status)) return Status; + + /* Make sure this is a connection port */ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_COMMUNICATION_PORT) + { + /* It isn't, fail */ + ObDereferenceObject(Port); + return STATUS_INVALID_PORT_HANDLE; + } + + /* Acquire the lock */ + KeAcquireGuardedMutex(&LpcpLock); + + /* Make sure we have a client thread */ + if (!Port->ClientThread) + { + /* We don't, fail */ + KeReleaseGuardedMutex(&LpcpLock); + ObDereferenceObject(Port); + return STATUS_INVALID_PARAMETER; + } + + /* Get the thread */ + Thread = Port->ClientThread; + + /* Make sure it has a reply message */ + if (!Thread->LpcReplyMessage) + { + /* It doesn't, fail */ + KeReleaseGuardedMutex(&LpcpLock); + ObDereferenceObject(Port); + return STATUS_PORT_DISCONNECTED; + } + + /* Clear the client thread and wake it up */ + Port->ClientThread = NULL; + LpcpPrepareToWakeClient(Thread); + + /* Release the lock and wait for an answer */ + KeReleaseGuardedMutex(&LpcpLock); + LpcpCompleteWait(&Thread->LpcReplySemaphore); + + /* Dereference the Thread and Port and return */ + ObDereferenceObject(Port); + ObDereferenceObject(Thread); + LPCTRACE(LPC_COMPLETE_DEBUG, "Port: %p. Thread: %p\n", Port, Thread); + return Status; +} /* EOF */ diff --git a/reactos/ntoskrnl/lpc/connect.c b/reactos/ntoskrnl/lpc/connect.c index 6aa36904cfe..2b9259ef588 100644 --- a/reactos/ntoskrnl/lpc/connect.c +++ b/reactos/ntoskrnl/lpc/connect.c @@ -1,933 +1,568 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/lpc/connect.c - * PURPOSE: Communication mechanism - * - * PROGRAMMERS: David Welch (welch@cwcom.net) + * PURPOSE: Local Procedure Call: Connection Management + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ -/* INCLUDES *****************************************************************/ +/* INCLUDES ******************************************************************/ #include +#include "lpc.h" #define NDEBUG #include -/* FUNCTIONS *****************************************************************/ +/* PRIVATE FUNCTIONS *********************************************************/ -/********************************************************************** - * NAME EXPORTED - * EiConnectPort/12 - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - */ -NTSTATUS STDCALL -EiConnectPort(IN PEPORT* ConnectedPort, - IN PEPORT NamedPort, - IN PVOID Section, - IN LARGE_INTEGER SectionOffset, - IN ULONG ViewSize, - OUT PVOID* ClientSendViewBase, - OUT PVOID* ServerSendViewBase, - OUT PULONG ReceiveViewSize, - OUT PVOID* ReceiveViewBase, - OUT PULONG MaximumMessageSize, - IN OUT PVOID ConnectData, - IN OUT PULONG ConnectDataLength) +PVOID +NTAPI +LpcpFreeConMsg(IN OUT PLPCP_MESSAGE *Message, + IN OUT PLPCP_CONNECTION_MESSAGE *ConnectMessage, + IN PETHREAD CurrentThread) { - PEPORT_CONNECT_REQUEST_MESSAGE RequestMessage; - ULONG RequestConnectDataLength; - PEPORT OurPort; - PQUEUEDMESSAGE Reply; - PEPORT_CONNECT_REPLY_MESSAGE CReply; - NTSTATUS Status; - KIRQL oldIrql; + PVOID SectionToMap; - if (ConnectDataLength == NULL) + /* Acquire the LPC lock */ + KeAcquireGuardedMutex(&LpcpLock); + + /* Check if the reply chain is not empty */ + if (!IsListEmpty(&CurrentThread->LpcReplyChain)) { - RequestConnectDataLength = 0; - } - else - { - RequestConnectDataLength = *ConnectDataLength; + /* Remove this entry and re-initialize it */ + RemoveEntryList(&CurrentThread->LpcReplyChain); + InitializeListHead(&CurrentThread->LpcReplyChain); } - /* - * Create a port to represent our side of the connection - */ - Status = ObCreateObject (KernelMode, - LpcPortObjectType, - NULL, - KernelMode, - NULL, - sizeof(EPORT), - 0, - 0, - (PVOID*)&OurPort); - if (!NT_SUCCESS(Status)) + /* Check if there's a reply message */ + if (CurrentThread->LpcReplyMessage) { - return (Status); - } - LpcpInitializePort(OurPort, EPORT_TYPE_CLIENT_COMM_PORT, NamedPort); + /* Get the message */ + *Message = CurrentThread->LpcReplyMessage; - /* - * Allocate a request message. - */ - RequestMessage = ExAllocatePool(NonPagedPool, - sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + - RequestConnectDataLength); - if (RequestMessage == NULL) + /* Clear message data */ + CurrentThread->LpcReceivedMessageId = 0; + CurrentThread->LpcReplyMessage = NULL; + + /* Get the connection message and clear the section */ + *ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(*Message + 1); + SectionToMap = (*ConnectMessage)->SectionToMap; + (*ConnectMessage)->SectionToMap = NULL; + } + else { - ObDereferenceObject(OurPort); - return(STATUS_NO_MEMORY); + /* No message to return */ + *Message = NULL; + SectionToMap = NULL; } - /* - * Initialize the request message. - */ - RequestMessage->MessageHeader.u1.s1.DataLength = - sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + RequestConnectDataLength - - sizeof(PORT_MESSAGE); - RequestMessage->MessageHeader.u1.s1.TotalLength = - sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + RequestConnectDataLength; - DPRINT("RequestMessageSize %d\n", - RequestMessage->MessageHeader.u1.s1.TotalLength); - RequestMessage->MessageHeader.ClientViewSize = 0; - RequestMessage->ConnectingProcess = PsGetCurrentProcess(); - ObReferenceObjectByPointer(RequestMessage->ConnectingProcess, - PROCESS_VM_OPERATION, - NULL, - KernelMode); - RequestMessage->SendSectionObject = (struct _SECTION_OBJECT*)Section; - RequestMessage->SendSectionOffset = SectionOffset; - RequestMessage->SendViewSize = ViewSize; - RequestMessage->ConnectDataLength = RequestConnectDataLength; - if (RequestConnectDataLength > 0) - { - memcpy(RequestMessage->ConnectData, ConnectData, - RequestConnectDataLength); - } - - /* - * Queue the message to the named port - */ - EiReplyOrRequestPort(NamedPort, - &RequestMessage->MessageHeader, - LPC_CONNECTION_REQUEST, - OurPort); - KeReleaseSemaphore(&NamedPort->Semaphore, IO_NO_INCREMENT, 1, FALSE); - ExFreePool(RequestMessage); - - /* - * Wait for them to accept our connection - */ - KeWaitForSingleObject(&OurPort->Semaphore, - UserRequest, - UserMode, - FALSE, - NULL); - - /* - * Dequeue the response - */ - KeAcquireSpinLock (&OurPort->Lock, &oldIrql); - Reply = EiDequeueMessagePort (OurPort); - KeReleaseSpinLock (&OurPort->Lock, oldIrql); - CReply = (PEPORT_CONNECT_REPLY_MESSAGE)&Reply->Message; - - /* - * Do some initial cleanup. - */ - ObDereferenceObject(PsGetCurrentProcess()); - - /* - * Check for connection refusal. - */ - if (CReply->MessageHeader.u2.s2.Type == LPC_CONNECTION_REFUSED) - { - ObDereferenceObject(OurPort); - ExFreePool(Reply); - /* - * FIXME: Check what NT does here. Giving the user data back on - * connect failure sounds reasonable; it probably wouldn't break - * anything anyway. - */ - if (ConnectDataLength != NULL) - { - *ConnectDataLength = CReply->ConnectDataLength; - memcpy(ConnectData, CReply->ConnectData, CReply->ConnectDataLength); - } - return(STATUS_PORT_CONNECTION_REFUSED); - } - - /* - * Otherwise we are connected. Copy data back to the client. - */ - *ServerSendViewBase = CReply->SendServerViewBase; - *ReceiveViewSize = CReply->ReceiveClientViewSize; - *ReceiveViewBase = CReply->ReceiveClientViewBase; - *MaximumMessageSize = CReply->MaximumMessageSize; - if (ConnectDataLength != NULL) - { - *ConnectDataLength = CReply->ConnectDataLength; - memcpy(ConnectData, CReply->ConnectData, CReply->ConnectDataLength); - } - - /* - * Create our view of the send section object. - */ - if (Section != NULL) - { - *ClientSendViewBase = 0; - Status = MmMapViewOfSection(Section, - PsGetCurrentProcess(), - ClientSendViewBase, - 0, - ViewSize, - &SectionOffset, - &ViewSize, - ViewUnmap, - 0 /* MEM_TOP_DOWN? */, - PAGE_READWRITE); - if (!NT_SUCCESS(Status)) - { - /* FIXME: Cleanup here. */ - return(Status); - } - } - - /* - * Do the final initialization of our port. - */ - OurPort->State = EPORT_CONNECTED_CLIENT; - - /* - * Cleanup. - */ - ExFreePool(Reply); - *ConnectedPort = OurPort; - return(STATUS_SUCCESS); + /* Release the lock and return the section */ + KeReleaseGuardedMutex(&LpcpLock); + return SectionToMap; } -/********************************************************************** - * NAME EXPORTED - * NtConnectPort/8 - * - * DESCRIPTION - * Connect to a named port and wait for the other side to - * accept or reject the connection request. - * - * ARGUMENTS - * ConnectedPort - * PortName - * Qos - * WriteMap - * ReadMap - * MaxMessageSize - * ConnectInfo - * UserConnectInfoLength - * - * RETURN VALUE - * - * @unimplemented +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @implemented */ -NTSTATUS STDCALL -NtConnectPort (PHANDLE UnsafeConnectedPortHandle, - PUNICODE_STRING PortName, - PSECURITY_QUALITY_OF_SERVICE Qos, - PPORT_VIEW UnsafeWriteMap, - PREMOTE_PORT_VIEW UnsafeReadMap, - PULONG UnsafeMaximumMessageSize, - PVOID UnsafeConnectData, - PULONG UnsafeConnectDataLength) +NTSTATUS +NTAPI +NtSecureConnectPort(OUT PHANDLE PortHandle, + IN PUNICODE_STRING PortName, + IN PSECURITY_QUALITY_OF_SERVICE Qos, + IN OUT PPORT_VIEW ClientView OPTIONAL, + IN PSID ServerSid OPTIONAL, + IN OUT PREMOTE_PORT_VIEW ServerView OPTIONAL, + OUT PULONG MaxMessageLength OPTIONAL, + IN OUT PVOID ConnectionInformation OPTIONAL, + IN OUT PULONG ConnectionInformationLength OPTIONAL) { - HANDLE ConnectedPortHandle; - PORT_VIEW WriteMap; - REMOTE_PORT_VIEW ReadMap; - ULONG MaximumMessageSize; - PVOID ConnectData = NULL; - ULONG ConnectDataLength = 0; - PVOID SectionObject; - LARGE_INTEGER SectionOffset; - PEPORT ConnectedPort; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - PEPORT NamedPort; - - PreviousMode = ExGetPreviousMode(); - - if (PreviousMode != KernelMode) + ULONG ConnectionInfoLength = 0; + PLPCP_PORT_OBJECT Port, ClientPort; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); + NTSTATUS Status = STATUS_SUCCESS; + HANDLE Handle; + PVOID SectionToMap; + PLPCP_MESSAGE Message; + PLPCP_CONNECTION_MESSAGE ConnectMessage; + PETHREAD Thread = PsGetCurrentThread(); + ULONG PortMessageLength; + LARGE_INTEGER SectionOffset; + PTOKEN Token; + PTOKEN_USER TokenUserInfo; + PAGED_CODE(); + LPCTRACE(LPC_CONNECT_DEBUG, + "Name: %wZ. Qos: %p. Views: %p/%p. Sid: %p\n", + PortName, + Qos, + ClientView, + ServerView, + ServerSid); + + /* Validate client view */ + if ((ClientView) && (ClientView->Length != sizeof(PORT_VIEW))) { - _SEH_TRY - { - ProbeForWriteHandle(UnsafeConnectedPortHandle); - if (UnsafeMaximumMessageSize != NULL) - { - ProbeForWriteUlong(UnsafeMaximumMessageSize); - } - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - return Status; - } + /* Fail */ + return STATUS_INVALID_PARAMETER; } - /* - * Copy in write map and partially validate. - */ - if (UnsafeWriteMap != NULL) + /* Validate server view */ + if ((ServerView) && (ServerView->Length != sizeof(REMOTE_PORT_VIEW))) { - if (PreviousMode != KernelMode) - { - _SEH_TRY - { - ProbeForWrite(UnsafeWriteMap, - sizeof(PORT_VIEW), - 1); - RtlCopyMemory(&WriteMap, - UnsafeWriteMap, - sizeof(PORT_VIEW)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - return Status; - } - } - else - { - RtlCopyMemory(&WriteMap, - UnsafeWriteMap, - sizeof(PORT_VIEW)); - } - - if (WriteMap.Length != sizeof(PORT_VIEW)) - { - return(STATUS_INVALID_PARAMETER_4); - } - SectionOffset.QuadPart = WriteMap.SectionOffset; - } - else - { - WriteMap.SectionHandle = INVALID_HANDLE_VALUE; + /* Fail */ + return STATUS_INVALID_PARAMETER; } - /* - * Handle connection data. - */ - if (UnsafeConnectData) + /* Check if caller sent connection information length */ + if (ConnectionInformationLength) { - if (PreviousMode != KernelMode) - { - _SEH_TRY - { - ConnectDataLength = ProbeForReadUlong(UnsafeConnectDataLength); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; + /* Retrieve the input length */ + ConnectionInfoLength = *ConnectionInformationLength; + } - if (!NT_SUCCESS(Status)) - { - return Status; - } - } - else - { - ConnectDataLength = *UnsafeConnectDataLength; - } + /* Get the port */ + Status = ObReferenceObjectByName(PortName, + 0, + NULL, + PORT_ALL_ACCESS, + LpcPortObjectType, + PreviousMode, + NULL, + (PVOID *)&Port); + if (!NT_SUCCESS(Status)) return Status; - if (ConnectDataLength != 0) - { - ConnectData = ExAllocatePool(NonPagedPool, ConnectDataLength); - if (ConnectData == NULL) - { - return(STATUS_NO_MEMORY); - } + /* This has to be a connection port */ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT) + { + /* It isn't, so fail */ + ObDereferenceObject(Port); + return STATUS_INVALID_PORT_HANDLE; + } - if (PreviousMode != KernelMode) + /* Check if we have a SID */ + if (ServerSid) + { + /* Make sure that we have a server */ + if (Port->ServerProcess) + { + /* Get its token and query user information */ + Token = PsReferencePrimaryToken(Port->ServerProcess); + //Status = SeQueryInformationToken(Token, TokenUser, (PVOID*)&TokenUserInfo); + // FIXME: Need SeQueryInformationToken + Status = STATUS_SUCCESS; + TokenUserInfo = ExAllocatePool(PagedPool, sizeof(TOKEN_USER)); + TokenUserInfo->User.Sid = ServerSid; + PsDereferencePrimaryToken(Token); + + /* Check for success */ + if (NT_SUCCESS(Status)) { - _SEH_TRY + /* Compare the SIDs */ + if (!RtlEqualSid(ServerSid, TokenUserInfo->User.Sid)) { - ProbeForWriteUlong(UnsafeConnectData); - RtlCopyMemory(ConnectData, - UnsafeConnectData, - ConnectDataLength); + /* Fail */ + Status = STATUS_SERVER_SID_MISMATCH; } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - if (!NT_SUCCESS(Status)) - { - ExFreePool(ConnectData); - return Status; - } - } - else - { - RtlCopyMemory(ConnectData, - UnsafeConnectData, - ConnectDataLength); + /* Free token information */ + ExFreePool(TokenUserInfo); } } + else + { + /* Invalid SID */ + Status = STATUS_SERVER_SID_MISMATCH; + } + + /* Check if SID failed */ + if (!NT_SUCCESS(Status)) + { + /* Quit */ + ObDereferenceObject(Port); + return Status; + } } - /* - * Reference the named port. - */ - Status = ObReferenceObjectByName (PortName, + /* Create the client port */ + Status = ObCreateObject(PreviousMode, + LpcPortObjectType, + NULL, + PreviousMode, + NULL, + sizeof(LPCP_PORT_OBJECT), + 0, + 0, + (PVOID *)&ClientPort); + if (!NT_SUCCESS(Status)) + { + /* Failed, dereference the server port and return */ + ObDereferenceObject(Port); + return Status; + } + + /* Setup the client port */ + RtlZeroMemory(ClientPort, sizeof(LPCP_PORT_OBJECT)); + ClientPort->Flags = LPCP_CLIENT_PORT; + ClientPort->ConnectionPort = Port; + ClientPort->MaxMessageLength = Port->MaxMessageLength; + ClientPort->SecurityQos = *Qos; + InitializeListHead(&ClientPort->LpcReplyChainHead); + InitializeListHead(&ClientPort->LpcDataInfoChainHead); + + /* Check if we have dynamic security */ + if (Qos->ContextTrackingMode == SECURITY_DYNAMIC_TRACKING) + { + /* Remember that */ + ClientPort->Flags |= LPCP_SECURITY_DYNAMIC; + } + else + { + /* Create our own client security */ + Status = SeCreateClientSecurity(Thread, + Qos, + FALSE, + &ClientPort->StaticSecurity); + if (!NT_SUCCESS(Status)) + { + /* Security failed, dereference and return */ + ObDereferenceObject(ClientPort); + return Status; + } + } + + /* Initialize the port queue */ + Status = LpcpInitializePortQueue(ClientPort); + if (!NT_SUCCESS(Status)) + { + /* Failed */ + ObDereferenceObject(ClientPort); + return Status; + } + + /* Check if we have a client view */ + if (ClientView) + { + /* Get the section handle */ + Status = ObReferenceObjectByHandle(ClientView->SectionHandle, + SECTION_MAP_READ | + SECTION_MAP_WRITE, + MmSectionObjectType, + PreviousMode, + (PVOID*)&SectionToMap, + NULL); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ObDereferenceObject(Port); + return Status; + } + + /* Set the section offset */ + SectionOffset.QuadPart = ClientView->SectionOffset; + + /* Map it */ + Status = MmMapViewOfSection(SectionToMap, + PsGetCurrentProcess(), + &Port->ClientSectionBase, 0, + 0, + &SectionOffset, + &ClientView->ViewSize, + ViewUnmap, + 0, + PAGE_READWRITE); + + /* Update the offset */ + ClientView->SectionOffset = SectionOffset.LowPart; + + /* Check for failure */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ObDereferenceObject(SectionToMap); + ObDereferenceObject(Port); + return Status; + } + + /* Update the base */ + ClientView->ViewBase = Port->ClientSectionBase; + } + else + { + /* No section */ + SectionToMap = NULL; + } + + /* Normalize connection information */ + if (ConnectionInfoLength > Port->MaxConnectionInfoLength) + { + /* Use the port's maximum allowed value */ + ConnectionInfoLength = Port->MaxConnectionInfoLength; + } + + /* Allocate a message from the port zone */ + Message = LpcpAllocateFromPortZone(); + if (!Message) + { + /* Fail if we couldn't allocate a message */ + if (SectionToMap) ObDereferenceObject(SectionToMap); + ObDereferenceObject(ClientPort); + return STATUS_NO_MEMORY; + } + + /* Set pointer to the connection message and fill in the CID */ + ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); + Message->Request.ClientId = Thread->Cid; + + /* Check if we have a client view */ + if (ClientView) + { + /* Set the view size */ + Message->Request.ClientViewSize = ClientView->ViewSize; + + /* Copy the client view and clear the server view */ + RtlMoveMemory(&ConnectMessage->ClientView, + ClientView, + sizeof(PORT_VIEW)); + RtlZeroMemory(&ConnectMessage->ServerView, sizeof(REMOTE_PORT_VIEW)); + } + else + { + /* Set the size to 0 and clear the connect message */ + Message->Request.ClientViewSize = 0; + RtlZeroMemory(ConnectMessage, sizeof(LPCP_CONNECTION_MESSAGE)); + } + + /* Set the section and client port. Port is NULL for now */ + ConnectMessage->ClientPort = NULL; + ConnectMessage->SectionToMap = SectionToMap; + + /* Set the data for the connection request message */ + Message->Request.u1.s1.DataLength = sizeof(LPCP_CONNECTION_MESSAGE) + + ConnectionInfoLength; + Message->Request.u1.s1.TotalLength = sizeof(LPCP_MESSAGE) + + Message->Request.u1.s1.DataLength; + Message->Request.u2.s2.Type = LPC_CONNECTION_REQUEST; + + /* Check if we have connection information */ + if (ConnectionInformation) + { + /* Copy it in */ + RtlMoveMemory(ConnectMessage + 1, + ConnectionInformation, + ConnectionInfoLength); + } + + /* Acquire the port lock */ + KeAcquireGuardedMutex(&LpcpLock); + + /* Check if someone already deleted the port name */ + if (Port->Flags & LPCP_NAME_DELETED) + { + /* Fail the request */ + KeReleaseGuardedMutex(&LpcpLock); + Status = STATUS_OBJECT_NAME_NOT_FOUND; + goto Cleanup; + } + + /* Associate no thread yet */ + Message->RepliedToThread = NULL; + + /* Generate the Message ID and set it */ + Message->Request.MessageId = LpcpNextMessageId++; + if (!LpcpNextMessageId) LpcpNextMessageId = 1; + Thread->LpcReplyMessageId = Message->Request.MessageId; + + /* Insert the message into the queue and thread chain */ + InsertTailList(&Port->MsgQueue.ReceiveHead, &Message->Entry); + InsertTailList(&Port->LpcReplyChainHead, &Thread->LpcReplyChain); + Thread->LpcReplyMessage = Message; + + /* Now we can finally reference the client port and link it*/ + ObReferenceObject(ClientPort); + ConnectMessage->ClientPort = ClientPort; + + /* Release the lock */ + KeReleaseGuardedMutex(&LpcpLock); + LPCTRACE(LPC_CONNECT_DEBUG, + "Messages: %p/%p. Ports: %p/%p. Status: %lx\n", + Message, + ConnectMessage, + Port, + ClientPort, + Status); + + /* If this is a waitable port, set the event */ + if (Port->Flags & LPCP_WAITABLE_PORT) KeSetEvent(&Port->WaitEvent, + 1, + FALSE); + + /* Release the queue semaphore */ + LpcpCompleteWait(Port->MsgQueue.Semaphore); + + /* Now wait for a reply */ + LpcpConnectWait(&Thread->LpcReplySemaphore, PreviousMode); + + /* Check if our wait ended in success */ + if (Status != STATUS_SUCCESS) goto Cleanup; + + /* Free the connection message */ + SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread); + + /* Check if we got a message back */ + if (Message) + { + /* Check for new return length */ + if ((Message->Request.u1.s1.DataLength - + sizeof(LPCP_CONNECTION_MESSAGE)) < ConnectionInfoLength) + { + /* Set new normalized connection length */ + ConnectionInfoLength = Message->Request.u1.s1.DataLength - + sizeof(LPCP_CONNECTION_MESSAGE); + } + + /* Check if we had connection information */ + if (ConnectionInformation) + { + /* Check if we had a length pointer */ + if (ConnectionInformationLength) + { + /* Return the length */ + *ConnectionInformationLength = ConnectionInfoLength; + } + + /* Return the connection information */ + RtlMoveMemory(ConnectionInformation, + ConnectMessage + 1, + ConnectionInfoLength ); + } + + /* Make sure we had a connected port */ + if (ClientPort->ConnectedPort) + { + /* Get the message length before the port might get killed */ + PortMessageLength = Port->MaxMessageLength; + + /* Insert the client port */ + Status = ObInsertObject(ClientPort, NULL, - PORT_ALL_ACCESS, /* DesiredAccess */ - LpcPortObjectType, - PreviousMode, - NULL, - (PVOID*)&NamedPort); - if (!NT_SUCCESS(Status)) - { - if (KeGetPreviousMode() != KernelMode) - { - ExFreePool(ConnectData); - } - return(Status); - } - - /* - * Reference the send section object. - */ - if (WriteMap.SectionHandle != INVALID_HANDLE_VALUE) - { - Status = ObReferenceObjectByHandle(WriteMap.SectionHandle, - SECTION_MAP_READ | SECTION_MAP_WRITE, - MmSectionObjectType, - PreviousMode, - (PVOID*)&SectionObject, - NULL); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(NamedPort); - if (KeGetPreviousMode() != KernelMode) - { - ExFreePool(ConnectData); - } - return(Status); - } - } - else - { - SectionObject = NULL; - } - - /* - * Do the connection establishment. - */ - Status = EiConnectPort(&ConnectedPort, - NamedPort, - SectionObject, - SectionOffset, - WriteMap.ViewSize, - &WriteMap.ViewBase, - &WriteMap.ViewRemoteBase, - &ReadMap.ViewSize, - &ReadMap.ViewBase, - &MaximumMessageSize, - ConnectData, - &ConnectDataLength); - if (!NT_SUCCESS(Status)) - { - /* FIXME: Again, check what NT does here. */ - if (UnsafeConnectDataLength != NULL) - { - if (PreviousMode != KernelMode) - { - _SEH_TRY - { - RtlCopyMemory(UnsafeConnectData, - ConnectData, - ConnectDataLength); - *UnsafeConnectDataLength = ConnectDataLength; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - else - { - RtlCopyMemory(UnsafeConnectData, - ConnectData, - ConnectDataLength); - *UnsafeConnectDataLength = ConnectDataLength; - } - - ExFreePool(ConnectData); - } - return(Status); - } - - /* - * Do some initial cleanup. - */ - if (SectionObject != NULL) - { - ObDereferenceObject(SectionObject); - SectionObject = NULL; - } - ObDereferenceObject(NamedPort); - NamedPort = NULL; - - /* - * Copy the data back to the caller. - */ - - if (UnsafeConnectDataLength != NULL) - { - if (PreviousMode != KernelMode) - { - _SEH_TRY + PORT_ALL_ACCESS, + 0, + (PVOID *)NULL, + &Handle); + if (NT_SUCCESS(Status)) { - *UnsafeConnectDataLength = ConnectDataLength; - - if (ConnectData != NULL) + /* Return the handle */ + *PortHandle = Handle; + LPCTRACE(LPC_CONNECT_DEBUG, + "Handle: %lx. Length: %lx\n", + Handle, + PortMessageLength); + + /* Check if maximum length was requested */ + if (MaxMessageLength) *MaxMessageLength = PortMessageLength; + + /* Check if we had a client view */ + if (ClientView) { - RtlCopyMemory(UnsafeConnectData, - ConnectData, - ConnectDataLength); + /* Copy it back */ + RtlMoveMemory(ClientView, + &ConnectMessage->ClientView, + sizeof(PORT_VIEW)); + } + + /* Check if we had a server view */ + if (ServerView) + { + /* Copy it back */ + RtlMoveMemory(ServerView, + &ConnectMessage->ServerView, + sizeof(REMOTE_PORT_VIEW)); } } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - if (ConnectData != NULL) - { - ExFreePool(ConnectData); - } - return(Status); - } - } - else + } + else { - *UnsafeConnectDataLength = ConnectDataLength; - - if (ConnectData != NULL) + /* No connection port, we failed */ + if (SectionToMap) ObDereferenceObject(SectionToMap); + + /* Check if it's because the name got deleted */ + if (Port->Flags & LPCP_NAME_DELETED) { - RtlCopyMemory(UnsafeConnectData, - ConnectData, - ConnectDataLength); + /* Set the correct status */ + Status = STATUS_OBJECT_NAME_NOT_FOUND; } + else + { + /* Otherwise, the caller refused us */ + Status = STATUS_PORT_CONNECTION_REFUSED; + } + + /* Kill the port */ + ObDereferenceObject(ClientPort); } - if (ConnectData != NULL) - { - ExFreePool(ConnectData); - } + /* Free the message */ + LpcpFreeToPortZone(Message, FALSE); + return Status; } - Status = ObInsertObject(ConnectedPort, - NULL, - PORT_ALL_ACCESS, - 1, - (PVOID*)&ConnectedPort, - &ConnectedPortHandle); - if (!NT_SUCCESS(Status)) + + /* No reply message, fail */ + if (SectionToMap) ObDereferenceObject(SectionToMap); + ObDereferenceObject(ClientPort); + return STATUS_PORT_CONNECTION_REFUSED; + +Cleanup: + /* We failed, free the message */ + SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread); + + /* Check if the semaphore got signaled */ + if (KeReadStateSemaphore(&Thread->LpcReplySemaphore)) { - return(Status); + /* Wait on it */ + KeWaitForSingleObject(&Thread->LpcReplySemaphore, + KernelMode, + Executive, + FALSE, + NULL); } - if (PreviousMode != KernelMode) - { - _SEH_TRY - { - *UnsafeConnectedPortHandle = ConnectedPortHandle; - - if (UnsafeWriteMap != NULL) - { - RtlCopyMemory(UnsafeWriteMap, - &WriteMap, - sizeof(PORT_VIEW)); - } + /* Check if we had a message and free it */ + if (Message) LpcpFreeToPortZone(Message, FALSE); - if (UnsafeReadMap != NULL) - { - RtlCopyMemory(UnsafeReadMap, - &ReadMap, - sizeof(REMOTE_PORT_VIEW)); - } + /* Dereference other objects */ + if (SectionToMap) ObDereferenceObject(SectionToMap); + ObDereferenceObject(ClientPort); - if (UnsafeMaximumMessageSize != NULL) - { - *UnsafeMaximumMessageSize = MaximumMessageSize; - } - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - return Status; - } - } - else - { - *UnsafeConnectedPortHandle = ConnectedPortHandle; - - if (UnsafeWriteMap != NULL) - { - RtlCopyMemory(UnsafeWriteMap, - &WriteMap, - sizeof(PORT_VIEW)); - } - - if (UnsafeReadMap != NULL) - { - RtlCopyMemory(UnsafeReadMap, - &ReadMap, - sizeof(REMOTE_PORT_VIEW)); - } - - if (UnsafeMaximumMessageSize != NULL) - { - *UnsafeMaximumMessageSize = MaximumMessageSize; - } - } - - /* - * All done. - */ - - return(STATUS_SUCCESS); + /* Return status */ + return Status; } - -/********************************************************************** - * NAME EXPORTED - * NtAcceptConnectPort/6 - * - * DESCRIPTION - * - * ARGUMENTS - * ServerPortHandle - * NamedPortHandle - * LpcMessage - * AcceptIt - * WriteMap - * ReadMap - * - * RETURN VALUE +/* + * @implemented */ -/*EXPORTED*/ NTSTATUS STDCALL -NtAcceptConnectPort (PHANDLE ServerPortHandle, - HANDLE NamedPortHandle, - PPORT_MESSAGE LpcMessage, - BOOLEAN AcceptIt, - PPORT_VIEW WriteMap, - PREMOTE_PORT_VIEW ReadMap) +NTSTATUS +NTAPI +NtConnectPort(OUT PHANDLE PortHandle, + IN PUNICODE_STRING PortName, + IN PSECURITY_QUALITY_OF_SERVICE Qos, + IN PPORT_VIEW ClientView, + IN PREMOTE_PORT_VIEW ServerView, + OUT PULONG MaxMessageLength, + IN PVOID ConnectionInformation, + OUT PULONG ConnectionInformationLength) { - NTSTATUS Status; - PEPORT NamedPort; - PEPORT OurPort = NULL; - PQUEUEDMESSAGE ConnectionRequest; - KIRQL oldIrql; - PEPORT_CONNECT_REQUEST_MESSAGE CRequest; - PEPORT_CONNECT_REPLY_MESSAGE CReply; - ULONG Size; - KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - - Size = sizeof(EPORT_CONNECT_REPLY_MESSAGE); - if (LpcMessage) - { - Size += LpcMessage->u1.s1.DataLength; - } - - CReply = ExAllocatePool(NonPagedPool, Size); - if (CReply == NULL) - { - return(STATUS_NO_MEMORY); - } - - Status = ObReferenceObjectByHandle(NamedPortHandle, - PORT_ALL_ACCESS, - LpcPortObjectType, - PreviousMode, - (PVOID*)&NamedPort, - NULL); - if (!NT_SUCCESS(Status)) - { - ExFreePool(CReply); - return (Status); - } - - /* - * Create a port object for our side of the connection - */ - if (AcceptIt) - { - Status = ObCreateObject(PreviousMode, - LpcPortObjectType, - NULL, - PreviousMode, - NULL, - sizeof(EPORT), - 0, - 0, - (PVOID*)&OurPort); - if (!NT_SUCCESS(Status)) - { - ExFreePool(CReply); - ObDereferenceObject(NamedPort); - return(Status); - } - - Status = ObInsertObject ((PVOID)OurPort, - NULL, - PORT_ALL_ACCESS, - 0, - NULL, - ServerPortHandle); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(OurPort); - ExFreePool(CReply); - ObDereferenceObject(NamedPort); - return(Status); - } - - LpcpInitializePort(OurPort, EPORT_TYPE_SERVER_COMM_PORT, NamedPort); - } - - /* - * Dequeue the connection request - */ - KeAcquireSpinLock(&NamedPort->Lock, &oldIrql); - ConnectionRequest = EiDequeueConnectMessagePort (NamedPort); - KeReleaseSpinLock(&NamedPort->Lock, oldIrql); - CRequest = (PEPORT_CONNECT_REQUEST_MESSAGE)(&ConnectionRequest->Message); - - /* - * Prepare the reply. - */ - if (LpcMessage != NULL) - { - memcpy(&CReply->MessageHeader, LpcMessage, sizeof(PORT_MESSAGE)); - memcpy(&CReply->ConnectData, (PVOID)(LpcMessage + 1), - LpcMessage->u1.s1.DataLength); - CReply->MessageHeader.u1.s1.TotalLength = - sizeof(EPORT_CONNECT_REPLY_MESSAGE) + LpcMessage->u1.s1.DataLength; - CReply->MessageHeader.u1.s1.DataLength = CReply->MessageHeader.u1.s1.TotalLength - - sizeof(PORT_MESSAGE); - CReply->ConnectDataLength = LpcMessage->u1.s1.DataLength; - } - else - { - CReply->MessageHeader.u1.s1.TotalLength = sizeof(EPORT_CONNECT_REPLY_MESSAGE); - CReply->MessageHeader.u1.s1.DataLength = sizeof(EPORT_CONNECT_REPLY_MESSAGE) - - sizeof(PORT_MESSAGE); - CReply->ConnectDataLength = 0; - } - if (!AcceptIt) - { - EiReplyOrRequestPort(ConnectionRequest->Sender, - &CReply->MessageHeader, - LPC_CONNECTION_REFUSED, - NamedPort); - KeReleaseSemaphore(&ConnectionRequest->Sender->Semaphore, - IO_NO_INCREMENT, - 1, - FALSE); - ObDereferenceObject(ConnectionRequest->Sender); - ExFreePool(ConnectionRequest); - ExFreePool(CReply); - ObDereferenceObject(NamedPort); - return (STATUS_SUCCESS); - } - - /* - * Prepare the connection. - */ - if (WriteMap != NULL) - { - PVOID SectionObject; - LARGE_INTEGER SectionOffset; - - Status = ObReferenceObjectByHandle(WriteMap->SectionHandle, - SECTION_MAP_READ | SECTION_MAP_WRITE, - MmSectionObjectType, - PreviousMode, - (PVOID*)&SectionObject, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - SectionOffset.QuadPart = WriteMap->SectionOffset; - WriteMap->ViewRemoteBase = 0; - CReply->ReceiveClientViewSize = WriteMap->ViewSize; - Status = MmMapViewOfSection(SectionObject, - CRequest->ConnectingProcess, - &WriteMap->ViewRemoteBase, - 0, - CReply->ReceiveClientViewSize, - &SectionOffset, - &CReply->ReceiveClientViewSize, - ViewUnmap, - 0 /* MEM_TOP_DOWN? */, - PAGE_READWRITE); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - WriteMap->ViewBase = 0; - Status = MmMapViewOfSection(SectionObject, - PsGetCurrentProcess(), - &WriteMap->ViewBase, - 0, - WriteMap->ViewSize, - &SectionOffset, - &WriteMap->ViewSize, - ViewUnmap, - 0 /* MEM_TOP_DOWN? */, - PAGE_READWRITE); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - ObDereferenceObject(SectionObject); - } - if (ReadMap != NULL && CRequest->SendSectionObject != NULL) - { - LARGE_INTEGER SectionOffset; - - SectionOffset = CRequest->SendSectionOffset; - ReadMap->ViewSize = CRequest->SendViewSize; - ReadMap->ViewBase = 0; - Status = MmMapViewOfSection(CRequest->SendSectionObject, - PsGetCurrentProcess(), - &ReadMap->ViewBase, - 0, - CRequest->SendViewSize, - &SectionOffset, - &CRequest->SendViewSize, - ViewUnmap, - 0 /* MEM_TOP_DOWN? */, - PAGE_READWRITE); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - } - - /* - * Finish the reply. - */ - if (ReadMap != NULL) - { - CReply->SendServerViewBase = ReadMap->ViewBase; - } - else - { - CReply->SendServerViewBase = 0; - } - if (WriteMap != NULL) - { - CReply->ReceiveClientViewBase = WriteMap->ViewRemoteBase; - } - CReply->MaximumMessageSize = LPC_MAX_MESSAGE_LENGTH; - - - /* - * Connect the two ports - */ - OurPort->OtherPort = ConnectionRequest->Sender; - OurPort->OtherPort->OtherPort = OurPort; - EiReplyOrRequestPort(ConnectionRequest->Sender, - (PPORT_MESSAGE)CReply, - LPC_REPLY, - OurPort); - ExFreePool(ConnectionRequest); - ExFreePool(CReply); - - //ObDereferenceObject(OurPort); - ObDereferenceObject(NamedPort); - - return (STATUS_SUCCESS); -} - -/********************************************************************** - * NAME EXPORTED - * NtSecureConnectPort/9 - * - * DESCRIPTION - * Connect to a named port and wait for the other side to - * accept the connection. Possibly verify that the server - * matches the ServerSid (trusted server). - * Present in w2k+. - * - * ARGUMENTS - * ConnectedPort - * PortName: fully qualified name in the Ob name space; - * Qos - * WriteMap - * ServerSid - * ReadMap - * MaxMessageSize - * ConnectInfo - * UserConnectInfoLength - * - * RETURN VALUE - */ -NTSTATUS STDCALL -NtSecureConnectPort (OUT PHANDLE ConnectedPort, - IN PUNICODE_STRING PortName, - IN PSECURITY_QUALITY_OF_SERVICE Qos, - IN OUT PPORT_VIEW WriteMap OPTIONAL, - IN PSID ServerSid OPTIONAL, - IN OUT PREMOTE_PORT_VIEW ReadMap OPTIONAL, - OUT PULONG MaxMessageSize OPTIONAL, - IN OUT PVOID ConnectInfo OPTIONAL, - IN OUT PULONG UserConnectInfoLength OPTIONAL) -{ - /* TODO: implement a new object type: WaitablePort */ - /* TODO: verify the process' SID that hosts the rendez-vous port equals ServerSid */ - return NtConnectPort (ConnectedPort, - PortName, - Qos, - WriteMap, - ReadMap, - MaxMessageSize, - ConnectInfo, - UserConnectInfoLength); + /* Call the newer API */ + return NtSecureConnectPort(PortHandle, + PortName, + Qos, + ClientView, + NULL, + ServerView, + MaxMessageLength, + ConnectionInformation, + ConnectionInformationLength); } /* EOF */ diff --git a/reactos/ntoskrnl/lpc/create.c b/reactos/ntoskrnl/lpc/create.c index 1fcefa0d6b0..2bf08c13e11 100644 --- a/reactos/ntoskrnl/lpc/create.c +++ b/reactos/ntoskrnl/lpc/create.c @@ -1,180 +1,195 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/lpc/create.c - * PURPOSE: Communication mechanism - * - * PROGRAMMERS: David Welch (welch@cwcom.net) + * PURPOSE: Local Procedure Call: Port/Queue/Message Creation + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ -/* INCLUDES *****************************************************************/ +/* INCLUDES ******************************************************************/ #include +#include "lpc.h" #define NDEBUG #include -/********************************************************************** - * NAME - * LpcpVerifyCreateParameters/5 - * - * DESCRIPTION - * Verify user parameters in NtCreatePort and in - * NtCreateWaitablePort. - * - * ARGUMENTS - * - * RETURN VALUE - */ -static NTSTATUS STDCALL -LpcpVerifyCreateParameters (IN PHANDLE PortHandle, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN ULONG MaxConnectInfoLength, - IN ULONG MaxDataLength, - IN ULONG MaxPoolUsage) +/* PRIVATE FUNCTIONS *********************************************************/ + +NTSTATUS +NTAPI +LpcpInitializePortQueue(IN PLPCP_PORT_OBJECT Port) { - if (NULL == PortHandle) - { - return (STATUS_INVALID_PARAMETER_1); - } - if (NULL == ObjectAttributes) - { - return (STATUS_INVALID_PARAMETER_2); - } - if ((ObjectAttributes->Attributes & OBJ_OPENLINK) - || (ObjectAttributes->Attributes & OBJ_OPENIF) - || (ObjectAttributes->Attributes & OBJ_EXCLUSIVE) - || (ObjectAttributes->Attributes & OBJ_PERMANENT) - || (ObjectAttributes->Attributes & OBJ_INHERIT)) - { - return (STATUS_INVALID_PORT_ATTRIBUTES); - } - if (MaxConnectInfoLength > LPC_MAX_DATA_LENGTH) - { - return (STATUS_INVALID_PARAMETER_3); - } - if (MaxDataLength > LPC_MAX_MESSAGE_LENGTH) - { - return (STATUS_INVALID_PARAMETER_4); - } - /* TODO: some checking is done also on MaxPoolUsage - * to avoid choking the executive */ - return (STATUS_SUCCESS); + PLPCP_NONPAGED_PORT_QUEUE MessageQueue; + + /* Allocate the queue */ + MessageQueue = ExAllocatePoolWithTag(NonPagedPool, + sizeof(LPCP_NONPAGED_PORT_QUEUE), + TAG('P', 'o', 'r', 't')); + if (!MessageQueue) return STATUS_INSUFFICIENT_RESOURCES; + + /* Set it up */ + KeInitializeSemaphore(&MessageQueue->Semaphore, 0, MAXLONG); + MessageQueue->BackPointer = Port; + + /* And link it with the Paged Pool part */ + Port->MsgQueue.Semaphore = &MessageQueue->Semaphore; + InitializeListHead(&Port->MsgQueue.ReceiveHead); + return STATUS_SUCCESS; } -/********************************************************************** - * NAME EXPORTED - * NtCreatePort/5 - * - * DESCRIPTION - * - * ARGUMENTS - * PortHandle, - * ObjectAttributes, - * MaxConnectInfoLength, - * MaxDataLength, - * MaxPoolUsage: size of NP zone the NP part of msgs is kept in - * - * RETURN VALUE - */ -/*EXPORTED*/ NTSTATUS STDCALL -NtCreatePort (PHANDLE PortHandle, - POBJECT_ATTRIBUTES ObjectAttributes, - ULONG MaxConnectInfoLength, - ULONG MaxDataLength, - ULONG MaxPoolUsage) +NTSTATUS +NTAPI +LpcpCreatePort(OUT PHANDLE PortHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG MaxConnectionInfoLength, + IN ULONG MaxMessageLength, + IN ULONG MaxPoolUsage, + IN BOOLEAN Waitable) { - PEPORT Port; - NTSTATUS Status; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); + NTSTATUS Status; + PLPCP_PORT_OBJECT Port; + LPCTRACE(LPC_CREATE_DEBUG, "Name: %wZ\n", ObjectAttributes->ObjectName); - DPRINT("NtCreatePort() Name %x\n", ObjectAttributes->ObjectName->Buffer); + /* Create the Object */ + Status = ObCreateObject(PreviousMode, + LpcPortObjectType, + ObjectAttributes, + PreviousMode, + NULL, + sizeof(LPCP_PORT_OBJECT), + 0, + 0, + (PVOID*)&Port); + if (!NT_SUCCESS(Status)) return Status; - /* Verify parameters */ - Status = LpcpVerifyCreateParameters (PortHandle, - ObjectAttributes, - MaxConnectInfoLength, - MaxDataLength, - MaxPoolUsage); - if (STATUS_SUCCESS != Status) + /* Set up the Object */ + RtlZeroMemory(Port, sizeof(LPCP_PORT_OBJECT)); + Port->ConnectionPort = Port; + Port->Creator = PsGetCurrentThread()->Cid; + InitializeListHead(&Port->LpcDataInfoChainHead); + InitializeListHead(&Port->LpcReplyChainHead); + + /* Check if we don't have a name */ + if (!ObjectAttributes->ObjectName->Buffer) { - return (Status); + /* Set up for an unconnected port */ + Port->Flags = LPCP_UNCONNECTED_PORT; + Port->ConnectedPort = Port; + Port->ServerProcess = NULL; + } + else + { + /* Set up for a named connection port */ + Port->Flags = LPCP_CONNECTION_PORT; + Port->ServerProcess = PsGetCurrentProcess(); + + /* Don't let the process die on us */ + ObReferenceObject(Port->ServerProcess); } - /* Ask Ob to create the object */ - Status = ObCreateObject (ExGetPreviousMode(), - LpcPortObjectType, - ObjectAttributes, - ExGetPreviousMode(), - NULL, - sizeof(EPORT), - 0, - 0, - (PVOID*)&Port); - if (!NT_SUCCESS(Status)) + /* Check if this is a waitable port */ + if (Waitable) Port->Flags |= LPCP_WAITABLE_PORT; + + /* Setup the port queue */ + Status = LpcpInitializePortQueue(Port); + if (!NT_SUCCESS(Status)) { - return (Status); + /* Fail */ + ObDereferenceObject(Port); + return Status; } - Status = ObInsertObject ((PVOID)Port, - NULL, - PORT_ALL_ACCESS, - 0, - NULL, - PortHandle); - if (!NT_SUCCESS(Status)) + /* Check if this is a waitable port */ + if (Port->Flags & LPCP_WAITABLE_PORT) { - ObDereferenceObject (Port); - return (Status); + /* Setup the wait event */ + KeInitializeEvent(&Port->WaitEvent, NotificationEvent, FALSE); } - Status = LpcpInitializePort (Port, EPORT_TYPE_SERVER_RQST_PORT, NULL); - Port->MaxConnectInfoLength = LPC_MAX_DATA_LENGTH; - Port->MaxDataLength = LPC_MAX_MESSAGE_LENGTH; - Port->MaxPoolUsage = MaxPoolUsage; + /* Set the maximum message size allowed */ + Port->MaxMessageLength = LpcpMaxMessageSize - + FIELD_OFFSET(LPCP_MESSAGE, Request); - return (Status); + /* Now subtract the actual message structures and get the data size */ + Port->MaxConnectionInfoLength = Port->MaxMessageLength - + sizeof(PORT_MESSAGE) - + sizeof(LPCP_CONNECTION_MESSAGE); + + /* Validate the sizes */ + if (Port->MaxConnectionInfoLength < MaxConnectionInfoLength) + { + /* Not enough space for your request */ + ObDereferenceObject(Port); + return STATUS_INVALID_PARAMETER_3; + } + else if (Port->MaxMessageLength < MaxMessageLength) + { + /* Not enough space for your request */ + ObDereferenceObject(Port); + return STATUS_INVALID_PARAMETER_4; + } + + /* Now set the custom setting */ + Port->MaxMessageLength = MaxMessageLength; + + /* Insert it now */ + Status = ObInsertObject((PVOID)Port, + NULL, + PORT_ALL_ACCESS, + 0, + NULL, + PortHandle); + + /* Return success or the error */ + LPCTRACE(LPC_CREATE_DEBUG, "Port: %p. Handle: %lx\n", Port, *PortHandle); + return Status; } -/********************************************************************** - * NAME EXPORTED - * NtCreateWaitablePort/5 - * - * DESCRIPTION - * Waitable ports can be connected to with NtSecureConnectPort. - * No port interface can be used with waitable ports but - * NtReplyWaitReceivePort and NtReplyWaitReceivePortEx. - * Present only in w2k+. - * - * ARGUMENTS - * PortHandle, - * ObjectAttributes, - * MaxConnectInfoLength, - * MaxDataLength, - * MaxPoolUsage - * - * RETURN VALUE - */ -/*EXPORTED*/ NTSTATUS STDCALL -NtCreateWaitablePort (OUT PHANDLE PortHandle, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN ULONG MaxConnectInfoLength, - IN ULONG MaxDataLength, - IN ULONG MaxPoolUsage) -{ - NTSTATUS Status; +/* PUBLIC FUNCTIONS **********************************************************/ - /* Verify parameters */ - Status = LpcpVerifyCreateParameters (PortHandle, - ObjectAttributes, - MaxConnectInfoLength, - MaxDataLength, - MaxPoolUsage); - if (STATUS_SUCCESS != Status) - { - return (Status); - } - /* TODO */ - return (STATUS_NOT_IMPLEMENTED); +/* + * @implemented + */ +NTSTATUS +NTAPI +NtCreatePort(OUT PHANDLE PortHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG MaxConnectInfoLength, + IN ULONG MaxDataLength, + IN ULONG MaxPoolUsage) +{ + PAGED_CODE(); + + /* Call the internal API */ + return LpcpCreatePort(PortHandle, + ObjectAttributes, + MaxConnectInfoLength, + MaxDataLength, + MaxPoolUsage, + FALSE); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +NtCreateWaitablePort(OUT PHANDLE PortHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG MaxConnectInfoLength, + IN ULONG MaxDataLength, + IN ULONG MaxPoolUsage) +{ + PAGED_CODE(); + + /* Call the internal API */ + return LpcpCreatePort(PortHandle, + ObjectAttributes, + MaxConnectInfoLength, + MaxDataLength, + MaxPoolUsage, + TRUE); } /* EOF */ diff --git a/reactos/ntoskrnl/lpc/listen.c b/reactos/ntoskrnl/lpc/listen.c index 901c816f1ec..ee2ade0c03d 100644 --- a/reactos/ntoskrnl/lpc/listen.c +++ b/reactos/ntoskrnl/lpc/listen.c @@ -1,72 +1,52 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/lpc/listen.c - * PURPOSE: Communication mechanism - * - * PROGRAMMERS: David Welch (welch@cwcom.net) + * PURPOSE: Local Procedure Call: Listening + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ /* INCLUDES ******************************************************************/ #include +#include "lpc.h" #define NDEBUG #include -/* FUNCTIONS *****************************************************************/ +/* PUBLIC FUNCTIONS **********************************************************/ -/********************************************************************** - * NAME EXPORTED - * NtListenPort@8 - * - * DESCRIPTION - * Listen on a named port and wait for a connection attempt. - * - * ARGUMENTS - * PortHandle [IN] LPC port to listen on. - * - * ConnectMsg [IN] User provided storage for a - * possible connection request LPC message. - * - * RETURN VALUE - * STATUS_SUCCESS if a connection request is received - * successfully; otherwise an error code. - * - * The buffer ConnectMessage is filled with the connection - * request message queued by NtConnectPort() in PortHandle. - * - * NOTE +/* + * @implemented */ -/*EXPORTED*/ NTSTATUS STDCALL -NtListenPort (IN HANDLE PortHandle, - IN PPORT_MESSAGE ConnectMsg) +NTSTATUS +NTAPI +NtListenPort(IN HANDLE PortHandle, + OUT PPORT_MESSAGE ConnectMessage) { - NTSTATUS Status; + NTSTATUS Status; + PAGED_CODE(); + LPCTRACE(LPC_LISTEN_DEBUG, "Handle: %lx\n", PortHandle); - /* - * Wait forever for a connection request. - */ - for (;;) - { - Status = NtReplyWaitReceivePort(PortHandle, - NULL, - NULL, - ConnectMsg); - /* - * Accept only LPC_CONNECTION_REQUEST requests. - * Drop any other message. - */ - if (!NT_SUCCESS(Status) || - LPC_CONNECTION_REQUEST == ConnectMsg->u2.s2.Type) - { - DPRINT("Got message (type %x)\n", LPC_CONNECTION_REQUEST); - break; - } - DPRINT("Got message (type %x)\n", ConnectMsg->u2.s2.Type); - } + /* Wait forever for a connection request. */ + for (;;) + { + /* Do the wait */ + Status = NtReplyWaitReceivePort(PortHandle, + NULL, + NULL, + ConnectMessage); - return (Status); + /* Accept only LPC_CONNECTION_REQUEST requests. */ + if ((Status != STATUS_SUCCESS) || + (LpcpGetMessageType(ConnectMessage) == LPC_CONNECTION_REQUEST)) + { + /* Break out */ + break; + } + } + + /* Return status */ + return Status; } diff --git a/reactos/ntoskrnl/lpc/ntlpc/close.c b/reactos/ntoskrnl/lpc/ntlpc/close.c deleted file mode 100644 index af9803dbfc7..00000000000 --- a/reactos/ntoskrnl/lpc/ntlpc/close.c +++ /dev/null @@ -1,395 +0,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory - * FILE: ntoskrnl/lpc/close.c - * PURPOSE: Local Procedure Call: Rundown, Cleanup, Deletion - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include -#include "lpc.h" -#define NDEBUG -#include - -/* PRIVATE FUNCTIONS *********************************************************/ - -VOID -NTAPI -LpcExitThread(IN PETHREAD Thread) -{ - PLPCP_MESSAGE Message; - - /* Acquire the lock */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Make sure that the Reply Chain is empty */ - if (!IsListEmpty(&Thread->LpcReplyChain)) - { - /* It's not, remove the entry */ - RemoveEntryList(&Thread->LpcReplyChain); - } - - /* Set the thread in exit mode */ - Thread->LpcExitThreadCalled = TRUE; - Thread->LpcReplyMessageId = 0; - - /* Check if there's a reply message */ - Message = Thread->LpcReplyMessage; - if (Message) - { - /* FIXME: TODO */ - KEBUGCHECK(0); - } - - /* Release the lock */ - KeReleaseGuardedMutex(&LpcpLock); -} - -VOID -NTAPI -LpcpFreeToPortZone(IN PLPCP_MESSAGE Message, - IN ULONG Flags) -{ - PLPCP_CONNECTION_MESSAGE ConnectMessage; - PLPCP_PORT_OBJECT ClientPort = NULL; - PETHREAD Thread = NULL; - BOOLEAN LockHeld = Flags & 1; - PAGED_CODE(); - LPCTRACE(LPC_CLOSE_DEBUG, "Message: %p. Flags: %lx\n", Message, Flags); - - /* Acquire the lock if not already */ - if (!LockHeld) KeAcquireGuardedMutex(&LpcpLock); - - /* Check if the queue list is empty */ - if (!IsListEmpty(&Message->Entry)) - { - /* Remove and re-initialize */ - RemoveEntryList(&Message->Entry); - InitializeListHead(&Message->Entry); - } - - /* Check if we've already replied */ - if (Message->RepliedToThread) - { - /* Set thread to dereference and clean up */ - Thread = Message->RepliedToThread; - Message->RepliedToThread = NULL; - } - - /* Check if this is a connection request */ - if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST) - { - /* Get the connection message */ - ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); - - /* Clear the client port */ - ClientPort = ConnectMessage->ClientPort; - if (ClientPort) ConnectMessage->ClientPort = NULL; - } - - /* Release the lock */ - KeReleaseGuardedMutex(&LpcpLock); - - /* Check if we had anything to dereference */ - if (Thread) ObDereferenceObject(Thread); - if (ClientPort) ObDereferenceObject(ClientPort); - - /* Free the entry */ - ExFreeToPagedLookasideList(&LpcpMessagesLookaside, Message); - - /* Reacquire the lock if needed */ - if ((LockHeld) && !(Flags & 2)) KeAcquireGuardedMutex(&LpcpLock); -} - -VOID -NTAPI -LpcpDestroyPortQueue(IN PLPCP_PORT_OBJECT Port, - IN BOOLEAN Destroy) -{ - PLIST_ENTRY ListHead, NextEntry; - PETHREAD Thread; - PLPCP_MESSAGE Message; - PLPCP_CONNECTION_MESSAGE ConnectMessage; - LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags); - - /* Hold the lock */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Disconnect the port to which this port is connected */ - if (Port->ConnectedPort) Port->ConnectedPort->ConnectedPort = NULL; - - /* Check if this is a connection port */ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT) - { - /* Delete the name */ - Port->Flags |= LPCP_NAME_DELETED; - } - - /* Walk all the threads waiting and signal them */ - ListHead = &Port->LpcReplyChainHead; - NextEntry = ListHead->Flink; - while (NextEntry != ListHead) - { - /* Get the Thread */ - Thread = CONTAINING_RECORD(NextEntry, ETHREAD, LpcReplyChain); - - /* Make sure we're not in exit */ - if (Thread->LpcExitThreadCalled) break; - - /* Move to the next entry */ - NextEntry = NextEntry->Flink; - - /* Remove and reinitialize the List */ - RemoveEntryList(&Thread->LpcReplyChain); - InitializeListHead(&Thread->LpcReplyChain); - - /* Check if someone is waiting */ - if (!KeReadStateSemaphore(&Thread->LpcReplySemaphore)) - { - /* Get the message and check if it's a connection request */ - Message = Thread->LpcReplyMessage; - if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST) - { - /* Get the connection message */ - ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); - - /* Check if it had a section */ - if (ConnectMessage->SectionToMap) - { - /* Dereference it */ - ObDereferenceObject(ConnectMessage->SectionToMap); - } - } - - /* Clear the reply message */ - Thread->LpcReplyMessage = NULL; - - /* And remove the message from the port zone */ - LpcpFreeToPortZone(Message, TRUE); - } - - /* Release the semaphore and reset message id count */ - Thread->LpcReplyMessageId = 0; - LpcpCompleteWait(&Thread->LpcReplySemaphore); - } - - /* Reinitialize the list head */ - InitializeListHead(&Port->LpcReplyChainHead); - - /* Loop queued messages */ - ListHead = &Port->MsgQueue.ReceiveHead; - NextEntry = ListHead->Flink; - while (ListHead != NextEntry) - { - /* Get the message */ - Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry); - NextEntry = NextEntry->Flink; - - /* Free and reinitialize it's list head */ - InitializeListHead(&Message->Entry); - - /* Remove it from the port zone */ - LpcpFreeToPortZone(Message, TRUE); - } - - /* Reinitialize the message queue list head */ - InitializeListHead(&Port->MsgQueue.ReceiveHead); - - /* Release the lock */ - KeReleaseGuardedMutex(&LpcpLock); - - /* Check if we have to free the port entirely */ - if (Destroy) - { - /* Check if the semaphore exists */ - if (Port->MsgQueue.Semaphore) - { - /* Use the semaphore to find the port queue and free it */ - ExFreePool(CONTAINING_RECORD(Port->MsgQueue.Semaphore, - LPCP_NONPAGED_PORT_QUEUE, - Semaphore)); - } - } -} - -VOID -NTAPI -LpcpClosePort(IN PEPROCESS Process OPTIONAL, - IN PVOID Object, - IN ACCESS_MASK GrantedAccess, - IN ULONG ProcessHandleCount, - IN ULONG SystemHandleCount) -{ - PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)Object; - LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags); - - /* Only Server-side Connection Ports need clean up*/ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT) - { - /* Check the handle count */ - switch (SystemHandleCount) - { - /* No handles left */ - case 0: - - /* Destroy the port queue */ - LpcpDestroyPortQueue(Port, TRUE); - break; - - /* Last handle remaining */ - case 1: - - /* Reset the queue only */ - LpcpDestroyPortQueue(Port, FALSE); - - /* More handles remain, do nothing */ - default: - break; - } - } -} - -VOID -NTAPI -LpcpFreePortClientSecurity(IN PLPCP_PORT_OBJECT Port) -{ - /* Check if this is a client port */ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT) - { - /* Check if security is static */ - if (!(Port->Flags & LPCP_SECURITY_DYNAMIC)) - { - /* Check if we have a token */ - if (Port->StaticSecurity.ClientToken) - { - /* Free security */ - SeDeleteClientSecurity(&Port->StaticSecurity); - } - } - } -} - -VOID -NTAPI -LpcpDeletePort(IN PVOID ObjectBody) -{ - LARGE_INTEGER Timeout; - PETHREAD Thread; - PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)ObjectBody; - PLPCP_PORT_OBJECT ConnectionPort; - PLPCP_MESSAGE Message; - PLIST_ENTRY ListHead, NextEntry; - HANDLE Pid; - CLIENT_DIED_MSG ClientDiedMsg; - Timeout.QuadPart = -1000000; - PAGED_CODE(); - LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags); - - /* Check if this is a communication port */ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_COMMUNICATION_PORT) - { - /* Acquire the lock */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Get the thread */ - Thread = Port->ClientThread; - if (Thread) - { - /* Clear it */ - Port->ClientThread = NULL; - - /* Release the lock and dereference */ - KeReleaseGuardedMutex(&LpcpLock); - ObDereferenceObject(Thread); - } - else - { - /* Release the lock */ - KeReleaseGuardedMutex(&LpcpLock); - } - } - - /* Check if this is a client-side port */ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT) - { - /* Setup the client died message */ - ClientDiedMsg.h.u1.s1.TotalLength = sizeof(ClientDiedMsg); - ClientDiedMsg.h.u1.s1.DataLength = sizeof(ClientDiedMsg.CreateTime); - ClientDiedMsg.h.u2.ZeroInit = LPC_PORT_CLOSED; - ClientDiedMsg.CreateTime = PsGetCurrentProcess()->CreateTime; - - /* Send it */ - for (;;) - { - /* Send the message */ - if (LpcRequestPort(Port, - &ClientDiedMsg.h) != STATUS_NO_MEMORY) break; - - /* Wait until trying again */ - KeDelayExecutionThread(KernelMode, FALSE, &Timeout); - } - } - - /* Destroy the port queue */ - LpcpDestroyPortQueue(Port, TRUE); - - /* Check if we had a client view */ - if (Port->ClientSectionBase) MmUnmapViewOfSection(PsGetCurrentProcess(), - Port->ClientSectionBase); - - /* Check for a server view */ - if (Port->ServerSectionBase) MmUnmapViewOfSection(PsGetCurrentProcess(), - Port->ServerSectionBase); - - /* Get the connection port */ - ConnectionPort = Port->ConnectionPort; - if (ConnectionPort) - { - /* Get the PID */ - Pid = PsGetCurrentProcessId(); - - /* Acquire the lock */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Loop the data lists */ - ListHead = &ConnectionPort->LpcDataInfoChainHead; - NextEntry = ListHead->Flink; - while (NextEntry != ListHead) - { - /* Get the message */ - Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry); - NextEntry = NextEntry->Flink; - - /* Check if the PID matches */ - if (Message->Request.ClientId.UniqueProcess == Pid) - { - /* Remove it */ - RemoveEntryList(&Message->Entry); - LpcpFreeToPortZone(Message, TRUE); - } - } - - /* Release the lock */ - KeReleaseGuardedMutex(&LpcpLock); - - /* Dereference the object unless it's the same port */ - if (ConnectionPort != Port) ObDereferenceObject(ConnectionPort); - } - - /* Check if this is a connection port with a server process*/ - if (((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT) && - (ConnectionPort->ServerProcess)) - { - /* Dereference the server process */ - ObDereferenceObject(ConnectionPort->ServerProcess); - ConnectionPort->ServerProcess = NULL; - } - - /* Free client security */ - LpcpFreePortClientSecurity(Port); - LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p deleted\n", Port); -} - -/* EOF */ diff --git a/reactos/ntoskrnl/lpc/ntlpc/complete.c b/reactos/ntoskrnl/lpc/ntlpc/complete.c deleted file mode 100644 index b5e4e190ee1..00000000000 --- a/reactos/ntoskrnl/lpc/ntlpc/complete.c +++ /dev/null @@ -1,376 +0,0 @@ -/* -* PROJECT: ReactOS Kernel -* LICENSE: GPL - See COPYING in the top level directory -* FILE: ntoskrnl/lpc/complete.c -* PURPOSE: Local Procedure Call: Connection Completion -* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) -*/ - -/* INCLUDES ******************************************************************/ - -#include -#include "lpc.h" -#define NDEBUG -#include - -/* PRIVATE FUNCTIONS *********************************************************/ - -VOID -NTAPI -LpcpPrepareToWakeClient(IN PETHREAD Thread) -{ - PAGED_CODE(); - - /* Make sure the thread isn't dying and it has a valid chain */ - if (!(Thread->LpcExitThreadCalled) && - !(IsListEmpty(&Thread->LpcReplyChain))) - { - /* Remove it from the list and reinitialize it */ - RemoveEntryList(&Thread->LpcReplyChain); - InitializeListHead(&Thread->LpcReplyChain); - } -} - -/* PUBLIC FUNCTIONS **********************************************************/ - -/* - * @implemented - */ -NTSTATUS -NTAPI -NtAcceptConnectPort(OUT PHANDLE PortHandle, - IN PVOID PortContext OPTIONAL, - IN PPORT_MESSAGE ReplyMessage, - IN BOOLEAN AcceptConnection, - IN PPORT_VIEW ServerView, - IN PREMOTE_PORT_VIEW ClientView) -{ - PLPCP_PORT_OBJECT ConnectionPort, ServerPort, ClientPort; - PVOID ClientSectionToMap = NULL; - HANDLE Handle; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - NTSTATUS Status; - ULONG ConnectionInfoLength; - PLPCP_MESSAGE Message; - PLPCP_CONNECTION_MESSAGE ConnectMessage; - PEPROCESS ClientProcess; - PETHREAD ClientThread; - LARGE_INTEGER SectionOffset; - PAGED_CODE(); - LPCTRACE(LPC_COMPLETE_DEBUG, - "Context: %p. Message: %p. Accept: %lx. Views: %p/%p\n", - PortContext, - ReplyMessage, - AcceptConnection, - ClientView, - ServerView); - - /* Validate the size of the server view */ - if ((ServerView) && (ServerView->Length != sizeof(PORT_VIEW))) - { - /* Invalid size */ - return STATUS_INVALID_PARAMETER; - } - - /* Validate the size of the client view */ - if ((ClientView) && (ClientView->Length != sizeof(REMOTE_PORT_VIEW))) - { - /* Invalid size */ - return STATUS_INVALID_PARAMETER; - } - - /* Get the client process and thread */ - Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId, - &ClientProcess, - &ClientThread); - if (!NT_SUCCESS(Status)) return Status; - - /* Acquire the LPC Lock */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Make sure that the client wants a reply, and this is the right one */ - if (!(ClientThread->LpcReplyMessage) || - !(ReplyMessage->MessageId) || - (ClientThread->LpcReplyMessageId != ReplyMessage->MessageId)) - { - /* Not the reply asked for, or no reply wanted, fail */ - KeReleaseGuardedMutex(&LpcpLock); - ObDereferenceObject(ClientProcess); - ObDereferenceObject(ClientThread); - return STATUS_REPLY_MESSAGE_MISMATCH; - } - - /* Now get the message and connection message */ - Message = ClientThread->LpcReplyMessage; - ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); - - /* Get the client and connection port as well */ - ClientPort = ConnectMessage->ClientPort; - ConnectionPort = ClientPort->ConnectionPort; - - /* Make sure that the reply is being sent to the proper server process */ - if (ConnectionPort->ServerProcess != PsGetCurrentProcess()) - { - /* It's not, so fail */ - KeReleaseGuardedMutex(&LpcpLock); - ObDereferenceObject(ClientProcess); - ObDereferenceObject(ClientThread); - return STATUS_REPLY_MESSAGE_MISMATCH; - } - - /* At this point, don't let other accept attempts happen */ - ClientThread->LpcReplyMessage = NULL; - ClientThread->LpcReplyMessageId = 0; - - /* Clear the client port for now as well, then release the lock */ - ConnectMessage->ClientPort = NULL; - KeReleaseGuardedMutex(&LpcpLock); - - /* Get the connection information length */ - ConnectionInfoLength = ReplyMessage->u1.s1.DataLength; - if (ConnectionInfoLength > ConnectionPort->MaxConnectionInfoLength) - { - /* Normalize it since it's too large */ - ConnectionInfoLength = ConnectionPort->MaxConnectionInfoLength; - } - - /* Set the sizes of our reply message */ - Message->Request.u1.s1.DataLength = sizeof(LPCP_CONNECTION_MESSAGE) + - ConnectionInfoLength; - Message->Request.u1.s1.TotalLength = sizeof(LPCP_MESSAGE) + - Message->Request.u1.s1.DataLength; - - /* Setup the reply message */ - Message->Request.u2.s2.Type = LPC_REPLY; - Message->Request.u2.s2.DataInfoOffset = 0; - Message->Request.ClientId = ReplyMessage->ClientId; - Message->Request.MessageId = ReplyMessage->MessageId; - Message->Request.ClientViewSize = 0; - RtlMoveMemory(ConnectMessage + 1, ReplyMessage + 1, ConnectionInfoLength); - - /* At this point, if the caller refused the connection, go to cleanup */ - if (!AcceptConnection) goto Cleanup; - - /* Otherwise, create the actual port */ - Status = ObCreateObject(PreviousMode, - LpcPortObjectType, - NULL, - PreviousMode, - NULL, - sizeof(LPCP_PORT_OBJECT), - 0, - 0, - (PVOID*)&ServerPort); - if (!NT_SUCCESS(Status)) goto Cleanup; - - /* Set it up */ - RtlZeroMemory(ServerPort, sizeof(LPCP_PORT_OBJECT)); - ServerPort->PortContext = PortContext; - ServerPort->Flags = LPCP_COMMUNICATION_PORT; - ServerPort->MaxMessageLength = ConnectionPort->MaxMessageLength; - InitializeListHead(&ServerPort->LpcReplyChainHead); - InitializeListHead(&ServerPort->LpcDataInfoChainHead); - - /* Reference the connection port until we're fully setup */ - ObReferenceObject(ConnectionPort); - - /* Link the ports together */ - ServerPort->ConnectionPort = ConnectionPort; - ServerPort->ConnectedPort = ClientPort; - ClientPort->ConnectedPort = ServerPort; - - /* Also set the creator CID */ - ServerPort->Creator = PsGetCurrentThread()->Cid; - ClientPort->Creator = Message->Request.ClientId; - - /* Get the section associated and then clear it, while inside the lock */ - KeAcquireGuardedMutex(&LpcpLock); - ClientSectionToMap = ConnectMessage->SectionToMap; - ConnectMessage->SectionToMap = NULL; - KeReleaseGuardedMutex(&LpcpLock); - - /* Now check if there's a client section */ - if (ClientSectionToMap) - { - /* Setup the offset */ - SectionOffset.QuadPart = ConnectMessage->ClientView.SectionOffset; - - /* Map the section */ - Status = MmMapViewOfSection(ClientSectionToMap, - PsGetCurrentProcess(), - &ServerPort->ClientSectionBase, - 0, - 0, - &SectionOffset, - &ConnectMessage->ClientView.ViewSize, - ViewUnmap, - 0, - PAGE_READWRITE); - - /* Update the offset and check for mapping status */ - ConnectMessage->ClientView.SectionOffset = SectionOffset.LowPart; - if (NT_SUCCESS(Status)) - { - /* Set the view base */ - ConnectMessage->ClientView.ViewRemoteBase = ServerPort-> - ClientSectionBase; - } - else - { - /* Otherwise, quit */ - ObDereferenceObject(ServerPort); - goto Cleanup; - } - } - - /* Check if there's a server section */ - if (ServerView) - { - /* FIXME: TODO */ - ASSERT(FALSE); - } - - /* Reference the server port until it's fully inserted */ - ObReferenceObject(ServerPort); - - /* Insert the server port in the namespace */ - Status = ObInsertObject(ServerPort, - NULL, - PORT_ALL_ACCESS, - 0, - NULL, - &Handle); - if (!NT_SUCCESS(Status)) - { - /* We failed, remove the extra reference and cleanup */ - ObDereferenceObject(ServerPort); - goto Cleanup; - } - - /* Check if the caller gave a client view */ - if (ClientView) - { - /* Fill it out */ - ClientView->ViewBase = ConnectMessage->ClientView.ViewRemoteBase; - ClientView->ViewSize = ConnectMessage->ClientView.ViewSize; - } - - /* Return the handle to user mode */ - *PortHandle = Handle; - LPCTRACE(LPC_COMPLETE_DEBUG, - "Handle: %lx. Messages: %p/%p. Ports: %p/%p/%p\n", - Handle, - Message, - ConnectMessage, - ServerPort, - ClientPort, - ConnectionPort); - - /* If there was no port context, use the handle by default */ - if (!PortContext) ServerPort->PortContext = Handle; - ServerPort->ClientThread = ClientThread; - - /* Set this message as the LPC Reply message while holding the lock */ - KeAcquireGuardedMutex(&LpcpLock); - ClientThread->LpcReplyMessage = Message; - KeReleaseGuardedMutex(&LpcpLock); - - /* Clear the thread pointer so it doesn't get cleaned later */ - ClientThread = NULL; - - /* Remove the extra reference we had added */ - ObDereferenceObject(ServerPort); - -Cleanup: - /* If there was a section, dereference it */ - if (ClientSectionToMap) ObDereferenceObject(ClientSectionToMap); - - /* Check if we got here while still having a client thread */ - if (ClientThread) - { - /* FIXME: Complex cleanup code */ - ASSERT(FALSE); - } - - /* Dereference the client port if we have one, and the process */ - LPCTRACE(LPC_COMPLETE_DEBUG, - "Status: %lx. Thread: %p. Process: [%.16s]\n", - Status, - ClientThread, - ClientProcess->ImageFileName); - if (ClientPort) ObDereferenceObject(ClientPort); - ObDereferenceObject(ClientProcess); - return Status; -} - -/* - * @implemented - */ -NTSTATUS -NTAPI -NtCompleteConnectPort(IN HANDLE PortHandle) -{ - NTSTATUS Status; - PLPCP_PORT_OBJECT Port; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - PETHREAD Thread; - PAGED_CODE(); - LPCTRACE(LPC_COMPLETE_DEBUG, "Handle: %lx\n", PortHandle); - - /* Get the Port Object */ - Status = ObReferenceObjectByHandle(PortHandle, - PORT_ALL_ACCESS, - LpcPortObjectType, - PreviousMode, - (PVOID*)&Port, - NULL); - if (!NT_SUCCESS(Status)) return Status; - - /* Make sure this is a connection port */ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_COMMUNICATION_PORT) - { - /* It isn't, fail */ - ObDereferenceObject(Port); - return STATUS_INVALID_PORT_HANDLE; - } - - /* Acquire the lock */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Make sure we have a client thread */ - if (!Port->ClientThread) - { - /* We don't, fail */ - KeReleaseGuardedMutex(&LpcpLock); - ObDereferenceObject(Port); - return STATUS_INVALID_PARAMETER; - } - - /* Get the thread */ - Thread = Port->ClientThread; - - /* Make sure it has a reply message */ - if (!Thread->LpcReplyMessage) - { - /* It doesn't, fail */ - KeReleaseGuardedMutex(&LpcpLock); - ObDereferenceObject(Port); - return STATUS_PORT_DISCONNECTED; - } - - /* Clear the client thread and wake it up */ - Port->ClientThread = NULL; - LpcpPrepareToWakeClient(Thread); - - /* Release the lock and wait for an answer */ - KeReleaseGuardedMutex(&LpcpLock); - LpcpCompleteWait(&Thread->LpcReplySemaphore); - - /* Dereference the Thread and Port and return */ - ObDereferenceObject(Port); - ObDereferenceObject(Thread); - LPCTRACE(LPC_COMPLETE_DEBUG, "Port: %p. Thread: %p\n", Port, Thread); - return Status; -} - -/* EOF */ diff --git a/reactos/ntoskrnl/lpc/ntlpc/connect.c b/reactos/ntoskrnl/lpc/ntlpc/connect.c deleted file mode 100644 index 2b9259ef588..00000000000 --- a/reactos/ntoskrnl/lpc/ntlpc/connect.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory - * FILE: ntoskrnl/lpc/connect.c - * PURPOSE: Local Procedure Call: Connection Management - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include -#include "lpc.h" -#define NDEBUG -#include - -/* PRIVATE FUNCTIONS *********************************************************/ - -PVOID -NTAPI -LpcpFreeConMsg(IN OUT PLPCP_MESSAGE *Message, - IN OUT PLPCP_CONNECTION_MESSAGE *ConnectMessage, - IN PETHREAD CurrentThread) -{ - PVOID SectionToMap; - - /* Acquire the LPC lock */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Check if the reply chain is not empty */ - if (!IsListEmpty(&CurrentThread->LpcReplyChain)) - { - /* Remove this entry and re-initialize it */ - RemoveEntryList(&CurrentThread->LpcReplyChain); - InitializeListHead(&CurrentThread->LpcReplyChain); - } - - /* Check if there's a reply message */ - if (CurrentThread->LpcReplyMessage) - { - /* Get the message */ - *Message = CurrentThread->LpcReplyMessage; - - /* Clear message data */ - CurrentThread->LpcReceivedMessageId = 0; - CurrentThread->LpcReplyMessage = NULL; - - /* Get the connection message and clear the section */ - *ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(*Message + 1); - SectionToMap = (*ConnectMessage)->SectionToMap; - (*ConnectMessage)->SectionToMap = NULL; - } - else - { - /* No message to return */ - *Message = NULL; - SectionToMap = NULL; - } - - /* Release the lock and return the section */ - KeReleaseGuardedMutex(&LpcpLock); - return SectionToMap; -} - -/* PUBLIC FUNCTIONS **********************************************************/ - -/* - * @implemented - */ -NTSTATUS -NTAPI -NtSecureConnectPort(OUT PHANDLE PortHandle, - IN PUNICODE_STRING PortName, - IN PSECURITY_QUALITY_OF_SERVICE Qos, - IN OUT PPORT_VIEW ClientView OPTIONAL, - IN PSID ServerSid OPTIONAL, - IN OUT PREMOTE_PORT_VIEW ServerView OPTIONAL, - OUT PULONG MaxMessageLength OPTIONAL, - IN OUT PVOID ConnectionInformation OPTIONAL, - IN OUT PULONG ConnectionInformationLength OPTIONAL) -{ - ULONG ConnectionInfoLength = 0; - PLPCP_PORT_OBJECT Port, ClientPort; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - NTSTATUS Status = STATUS_SUCCESS; - HANDLE Handle; - PVOID SectionToMap; - PLPCP_MESSAGE Message; - PLPCP_CONNECTION_MESSAGE ConnectMessage; - PETHREAD Thread = PsGetCurrentThread(); - ULONG PortMessageLength; - LARGE_INTEGER SectionOffset; - PTOKEN Token; - PTOKEN_USER TokenUserInfo; - PAGED_CODE(); - LPCTRACE(LPC_CONNECT_DEBUG, - "Name: %wZ. Qos: %p. Views: %p/%p. Sid: %p\n", - PortName, - Qos, - ClientView, - ServerView, - ServerSid); - - /* Validate client view */ - if ((ClientView) && (ClientView->Length != sizeof(PORT_VIEW))) - { - /* Fail */ - return STATUS_INVALID_PARAMETER; - } - - /* Validate server view */ - if ((ServerView) && (ServerView->Length != sizeof(REMOTE_PORT_VIEW))) - { - /* Fail */ - return STATUS_INVALID_PARAMETER; - } - - /* Check if caller sent connection information length */ - if (ConnectionInformationLength) - { - /* Retrieve the input length */ - ConnectionInfoLength = *ConnectionInformationLength; - } - - /* Get the port */ - Status = ObReferenceObjectByName(PortName, - 0, - NULL, - PORT_ALL_ACCESS, - LpcPortObjectType, - PreviousMode, - NULL, - (PVOID *)&Port); - if (!NT_SUCCESS(Status)) return Status; - - /* This has to be a connection port */ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT) - { - /* It isn't, so fail */ - ObDereferenceObject(Port); - return STATUS_INVALID_PORT_HANDLE; - } - - /* Check if we have a SID */ - if (ServerSid) - { - /* Make sure that we have a server */ - if (Port->ServerProcess) - { - /* Get its token and query user information */ - Token = PsReferencePrimaryToken(Port->ServerProcess); - //Status = SeQueryInformationToken(Token, TokenUser, (PVOID*)&TokenUserInfo); - // FIXME: Need SeQueryInformationToken - Status = STATUS_SUCCESS; - TokenUserInfo = ExAllocatePool(PagedPool, sizeof(TOKEN_USER)); - TokenUserInfo->User.Sid = ServerSid; - PsDereferencePrimaryToken(Token); - - /* Check for success */ - if (NT_SUCCESS(Status)) - { - /* Compare the SIDs */ - if (!RtlEqualSid(ServerSid, TokenUserInfo->User.Sid)) - { - /* Fail */ - Status = STATUS_SERVER_SID_MISMATCH; - } - - /* Free token information */ - ExFreePool(TokenUserInfo); - } - } - else - { - /* Invalid SID */ - Status = STATUS_SERVER_SID_MISMATCH; - } - - /* Check if SID failed */ - if (!NT_SUCCESS(Status)) - { - /* Quit */ - ObDereferenceObject(Port); - return Status; - } - } - - /* Create the client port */ - Status = ObCreateObject(PreviousMode, - LpcPortObjectType, - NULL, - PreviousMode, - NULL, - sizeof(LPCP_PORT_OBJECT), - 0, - 0, - (PVOID *)&ClientPort); - if (!NT_SUCCESS(Status)) - { - /* Failed, dereference the server port and return */ - ObDereferenceObject(Port); - return Status; - } - - /* Setup the client port */ - RtlZeroMemory(ClientPort, sizeof(LPCP_PORT_OBJECT)); - ClientPort->Flags = LPCP_CLIENT_PORT; - ClientPort->ConnectionPort = Port; - ClientPort->MaxMessageLength = Port->MaxMessageLength; - ClientPort->SecurityQos = *Qos; - InitializeListHead(&ClientPort->LpcReplyChainHead); - InitializeListHead(&ClientPort->LpcDataInfoChainHead); - - /* Check if we have dynamic security */ - if (Qos->ContextTrackingMode == SECURITY_DYNAMIC_TRACKING) - { - /* Remember that */ - ClientPort->Flags |= LPCP_SECURITY_DYNAMIC; - } - else - { - /* Create our own client security */ - Status = SeCreateClientSecurity(Thread, - Qos, - FALSE, - &ClientPort->StaticSecurity); - if (!NT_SUCCESS(Status)) - { - /* Security failed, dereference and return */ - ObDereferenceObject(ClientPort); - return Status; - } - } - - /* Initialize the port queue */ - Status = LpcpInitializePortQueue(ClientPort); - if (!NT_SUCCESS(Status)) - { - /* Failed */ - ObDereferenceObject(ClientPort); - return Status; - } - - /* Check if we have a client view */ - if (ClientView) - { - /* Get the section handle */ - Status = ObReferenceObjectByHandle(ClientView->SectionHandle, - SECTION_MAP_READ | - SECTION_MAP_WRITE, - MmSectionObjectType, - PreviousMode, - (PVOID*)&SectionToMap, - NULL); - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ObDereferenceObject(Port); - return Status; - } - - /* Set the section offset */ - SectionOffset.QuadPart = ClientView->SectionOffset; - - /* Map it */ - Status = MmMapViewOfSection(SectionToMap, - PsGetCurrentProcess(), - &Port->ClientSectionBase, - 0, - 0, - &SectionOffset, - &ClientView->ViewSize, - ViewUnmap, - 0, - PAGE_READWRITE); - - /* Update the offset */ - ClientView->SectionOffset = SectionOffset.LowPart; - - /* Check for failure */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ObDereferenceObject(SectionToMap); - ObDereferenceObject(Port); - return Status; - } - - /* Update the base */ - ClientView->ViewBase = Port->ClientSectionBase; - } - else - { - /* No section */ - SectionToMap = NULL; - } - - /* Normalize connection information */ - if (ConnectionInfoLength > Port->MaxConnectionInfoLength) - { - /* Use the port's maximum allowed value */ - ConnectionInfoLength = Port->MaxConnectionInfoLength; - } - - /* Allocate a message from the port zone */ - Message = LpcpAllocateFromPortZone(); - if (!Message) - { - /* Fail if we couldn't allocate a message */ - if (SectionToMap) ObDereferenceObject(SectionToMap); - ObDereferenceObject(ClientPort); - return STATUS_NO_MEMORY; - } - - /* Set pointer to the connection message and fill in the CID */ - ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); - Message->Request.ClientId = Thread->Cid; - - /* Check if we have a client view */ - if (ClientView) - { - /* Set the view size */ - Message->Request.ClientViewSize = ClientView->ViewSize; - - /* Copy the client view and clear the server view */ - RtlMoveMemory(&ConnectMessage->ClientView, - ClientView, - sizeof(PORT_VIEW)); - RtlZeroMemory(&ConnectMessage->ServerView, sizeof(REMOTE_PORT_VIEW)); - } - else - { - /* Set the size to 0 and clear the connect message */ - Message->Request.ClientViewSize = 0; - RtlZeroMemory(ConnectMessage, sizeof(LPCP_CONNECTION_MESSAGE)); - } - - /* Set the section and client port. Port is NULL for now */ - ConnectMessage->ClientPort = NULL; - ConnectMessage->SectionToMap = SectionToMap; - - /* Set the data for the connection request message */ - Message->Request.u1.s1.DataLength = sizeof(LPCP_CONNECTION_MESSAGE) + - ConnectionInfoLength; - Message->Request.u1.s1.TotalLength = sizeof(LPCP_MESSAGE) + - Message->Request.u1.s1.DataLength; - Message->Request.u2.s2.Type = LPC_CONNECTION_REQUEST; - - /* Check if we have connection information */ - if (ConnectionInformation) - { - /* Copy it in */ - RtlMoveMemory(ConnectMessage + 1, - ConnectionInformation, - ConnectionInfoLength); - } - - /* Acquire the port lock */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Check if someone already deleted the port name */ - if (Port->Flags & LPCP_NAME_DELETED) - { - /* Fail the request */ - KeReleaseGuardedMutex(&LpcpLock); - Status = STATUS_OBJECT_NAME_NOT_FOUND; - goto Cleanup; - } - - /* Associate no thread yet */ - Message->RepliedToThread = NULL; - - /* Generate the Message ID and set it */ - Message->Request.MessageId = LpcpNextMessageId++; - if (!LpcpNextMessageId) LpcpNextMessageId = 1; - Thread->LpcReplyMessageId = Message->Request.MessageId; - - /* Insert the message into the queue and thread chain */ - InsertTailList(&Port->MsgQueue.ReceiveHead, &Message->Entry); - InsertTailList(&Port->LpcReplyChainHead, &Thread->LpcReplyChain); - Thread->LpcReplyMessage = Message; - - /* Now we can finally reference the client port and link it*/ - ObReferenceObject(ClientPort); - ConnectMessage->ClientPort = ClientPort; - - /* Release the lock */ - KeReleaseGuardedMutex(&LpcpLock); - LPCTRACE(LPC_CONNECT_DEBUG, - "Messages: %p/%p. Ports: %p/%p. Status: %lx\n", - Message, - ConnectMessage, - Port, - ClientPort, - Status); - - /* If this is a waitable port, set the event */ - if (Port->Flags & LPCP_WAITABLE_PORT) KeSetEvent(&Port->WaitEvent, - 1, - FALSE); - - /* Release the queue semaphore */ - LpcpCompleteWait(Port->MsgQueue.Semaphore); - - /* Now wait for a reply */ - LpcpConnectWait(&Thread->LpcReplySemaphore, PreviousMode); - - /* Check if our wait ended in success */ - if (Status != STATUS_SUCCESS) goto Cleanup; - - /* Free the connection message */ - SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread); - - /* Check if we got a message back */ - if (Message) - { - /* Check for new return length */ - if ((Message->Request.u1.s1.DataLength - - sizeof(LPCP_CONNECTION_MESSAGE)) < ConnectionInfoLength) - { - /* Set new normalized connection length */ - ConnectionInfoLength = Message->Request.u1.s1.DataLength - - sizeof(LPCP_CONNECTION_MESSAGE); - } - - /* Check if we had connection information */ - if (ConnectionInformation) - { - /* Check if we had a length pointer */ - if (ConnectionInformationLength) - { - /* Return the length */ - *ConnectionInformationLength = ConnectionInfoLength; - } - - /* Return the connection information */ - RtlMoveMemory(ConnectionInformation, - ConnectMessage + 1, - ConnectionInfoLength ); - } - - /* Make sure we had a connected port */ - if (ClientPort->ConnectedPort) - { - /* Get the message length before the port might get killed */ - PortMessageLength = Port->MaxMessageLength; - - /* Insert the client port */ - Status = ObInsertObject(ClientPort, - NULL, - PORT_ALL_ACCESS, - 0, - (PVOID *)NULL, - &Handle); - if (NT_SUCCESS(Status)) - { - /* Return the handle */ - *PortHandle = Handle; - LPCTRACE(LPC_CONNECT_DEBUG, - "Handle: %lx. Length: %lx\n", - Handle, - PortMessageLength); - - /* Check if maximum length was requested */ - if (MaxMessageLength) *MaxMessageLength = PortMessageLength; - - /* Check if we had a client view */ - if (ClientView) - { - /* Copy it back */ - RtlMoveMemory(ClientView, - &ConnectMessage->ClientView, - sizeof(PORT_VIEW)); - } - - /* Check if we had a server view */ - if (ServerView) - { - /* Copy it back */ - RtlMoveMemory(ServerView, - &ConnectMessage->ServerView, - sizeof(REMOTE_PORT_VIEW)); - } - } - } - else - { - /* No connection port, we failed */ - if (SectionToMap) ObDereferenceObject(SectionToMap); - - /* Check if it's because the name got deleted */ - if (Port->Flags & LPCP_NAME_DELETED) - { - /* Set the correct status */ - Status = STATUS_OBJECT_NAME_NOT_FOUND; - } - else - { - /* Otherwise, the caller refused us */ - Status = STATUS_PORT_CONNECTION_REFUSED; - } - - /* Kill the port */ - ObDereferenceObject(ClientPort); - } - - /* Free the message */ - LpcpFreeToPortZone(Message, FALSE); - return Status; - } - - /* No reply message, fail */ - if (SectionToMap) ObDereferenceObject(SectionToMap); - ObDereferenceObject(ClientPort); - return STATUS_PORT_CONNECTION_REFUSED; - -Cleanup: - /* We failed, free the message */ - SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread); - - /* Check if the semaphore got signaled */ - if (KeReadStateSemaphore(&Thread->LpcReplySemaphore)) - { - /* Wait on it */ - KeWaitForSingleObject(&Thread->LpcReplySemaphore, - KernelMode, - Executive, - FALSE, - NULL); - } - - /* Check if we had a message and free it */ - if (Message) LpcpFreeToPortZone(Message, FALSE); - - /* Dereference other objects */ - if (SectionToMap) ObDereferenceObject(SectionToMap); - ObDereferenceObject(ClientPort); - - /* Return status */ - return Status; -} - -/* - * @implemented - */ -NTSTATUS -NTAPI -NtConnectPort(OUT PHANDLE PortHandle, - IN PUNICODE_STRING PortName, - IN PSECURITY_QUALITY_OF_SERVICE Qos, - IN PPORT_VIEW ClientView, - IN PREMOTE_PORT_VIEW ServerView, - OUT PULONG MaxMessageLength, - IN PVOID ConnectionInformation, - OUT PULONG ConnectionInformationLength) -{ - /* Call the newer API */ - return NtSecureConnectPort(PortHandle, - PortName, - Qos, - ClientView, - NULL, - ServerView, - MaxMessageLength, - ConnectionInformation, - ConnectionInformationLength); -} - -/* EOF */ diff --git a/reactos/ntoskrnl/lpc/ntlpc/create.c b/reactos/ntoskrnl/lpc/ntlpc/create.c deleted file mode 100644 index 2bf08c13e11..00000000000 --- a/reactos/ntoskrnl/lpc/ntlpc/create.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory - * FILE: ntoskrnl/lpc/create.c - * PURPOSE: Local Procedure Call: Port/Queue/Message Creation - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include -#include "lpc.h" -#define NDEBUG -#include - -/* PRIVATE FUNCTIONS *********************************************************/ - -NTSTATUS -NTAPI -LpcpInitializePortQueue(IN PLPCP_PORT_OBJECT Port) -{ - PLPCP_NONPAGED_PORT_QUEUE MessageQueue; - - /* Allocate the queue */ - MessageQueue = ExAllocatePoolWithTag(NonPagedPool, - sizeof(LPCP_NONPAGED_PORT_QUEUE), - TAG('P', 'o', 'r', 't')); - if (!MessageQueue) return STATUS_INSUFFICIENT_RESOURCES; - - /* Set it up */ - KeInitializeSemaphore(&MessageQueue->Semaphore, 0, MAXLONG); - MessageQueue->BackPointer = Port; - - /* And link it with the Paged Pool part */ - Port->MsgQueue.Semaphore = &MessageQueue->Semaphore; - InitializeListHead(&Port->MsgQueue.ReceiveHead); - return STATUS_SUCCESS; -} - -NTSTATUS -NTAPI -LpcpCreatePort(OUT PHANDLE PortHandle, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN ULONG MaxConnectionInfoLength, - IN ULONG MaxMessageLength, - IN ULONG MaxPoolUsage, - IN BOOLEAN Waitable) -{ - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - NTSTATUS Status; - PLPCP_PORT_OBJECT Port; - LPCTRACE(LPC_CREATE_DEBUG, "Name: %wZ\n", ObjectAttributes->ObjectName); - - /* Create the Object */ - Status = ObCreateObject(PreviousMode, - LpcPortObjectType, - ObjectAttributes, - PreviousMode, - NULL, - sizeof(LPCP_PORT_OBJECT), - 0, - 0, - (PVOID*)&Port); - if (!NT_SUCCESS(Status)) return Status; - - /* Set up the Object */ - RtlZeroMemory(Port, sizeof(LPCP_PORT_OBJECT)); - Port->ConnectionPort = Port; - Port->Creator = PsGetCurrentThread()->Cid; - InitializeListHead(&Port->LpcDataInfoChainHead); - InitializeListHead(&Port->LpcReplyChainHead); - - /* Check if we don't have a name */ - if (!ObjectAttributes->ObjectName->Buffer) - { - /* Set up for an unconnected port */ - Port->Flags = LPCP_UNCONNECTED_PORT; - Port->ConnectedPort = Port; - Port->ServerProcess = NULL; - } - else - { - /* Set up for a named connection port */ - Port->Flags = LPCP_CONNECTION_PORT; - Port->ServerProcess = PsGetCurrentProcess(); - - /* Don't let the process die on us */ - ObReferenceObject(Port->ServerProcess); - } - - /* Check if this is a waitable port */ - if (Waitable) Port->Flags |= LPCP_WAITABLE_PORT; - - /* Setup the port queue */ - Status = LpcpInitializePortQueue(Port); - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ObDereferenceObject(Port); - return Status; - } - - /* Check if this is a waitable port */ - if (Port->Flags & LPCP_WAITABLE_PORT) - { - /* Setup the wait event */ - KeInitializeEvent(&Port->WaitEvent, NotificationEvent, FALSE); - } - - /* Set the maximum message size allowed */ - Port->MaxMessageLength = LpcpMaxMessageSize - - FIELD_OFFSET(LPCP_MESSAGE, Request); - - /* Now subtract the actual message structures and get the data size */ - Port->MaxConnectionInfoLength = Port->MaxMessageLength - - sizeof(PORT_MESSAGE) - - sizeof(LPCP_CONNECTION_MESSAGE); - - /* Validate the sizes */ - if (Port->MaxConnectionInfoLength < MaxConnectionInfoLength) - { - /* Not enough space for your request */ - ObDereferenceObject(Port); - return STATUS_INVALID_PARAMETER_3; - } - else if (Port->MaxMessageLength < MaxMessageLength) - { - /* Not enough space for your request */ - ObDereferenceObject(Port); - return STATUS_INVALID_PARAMETER_4; - } - - /* Now set the custom setting */ - Port->MaxMessageLength = MaxMessageLength; - - /* Insert it now */ - Status = ObInsertObject((PVOID)Port, - NULL, - PORT_ALL_ACCESS, - 0, - NULL, - PortHandle); - - /* Return success or the error */ - LPCTRACE(LPC_CREATE_DEBUG, "Port: %p. Handle: %lx\n", Port, *PortHandle); - return Status; -} - -/* PUBLIC FUNCTIONS **********************************************************/ - -/* - * @implemented - */ -NTSTATUS -NTAPI -NtCreatePort(OUT PHANDLE PortHandle, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN ULONG MaxConnectInfoLength, - IN ULONG MaxDataLength, - IN ULONG MaxPoolUsage) -{ - PAGED_CODE(); - - /* Call the internal API */ - return LpcpCreatePort(PortHandle, - ObjectAttributes, - MaxConnectInfoLength, - MaxDataLength, - MaxPoolUsage, - FALSE); -} - -/* - * @implemented - */ -NTSTATUS -NTAPI -NtCreateWaitablePort(OUT PHANDLE PortHandle, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN ULONG MaxConnectInfoLength, - IN ULONG MaxDataLength, - IN ULONG MaxPoolUsage) -{ - PAGED_CODE(); - - /* Call the internal API */ - return LpcpCreatePort(PortHandle, - ObjectAttributes, - MaxConnectInfoLength, - MaxDataLength, - MaxPoolUsage, - TRUE); -} - -/* EOF */ diff --git a/reactos/ntoskrnl/lpc/ntlpc/listen.c b/reactos/ntoskrnl/lpc/ntlpc/listen.c deleted file mode 100644 index ee2ade0c03d..00000000000 --- a/reactos/ntoskrnl/lpc/ntlpc/listen.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory - * FILE: ntoskrnl/lpc/listen.c - * PURPOSE: Local Procedure Call: Listening - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include -#include "lpc.h" -#define NDEBUG -#include - -/* PUBLIC FUNCTIONS **********************************************************/ - -/* - * @implemented - */ -NTSTATUS -NTAPI -NtListenPort(IN HANDLE PortHandle, - OUT PPORT_MESSAGE ConnectMessage) -{ - NTSTATUS Status; - PAGED_CODE(); - LPCTRACE(LPC_LISTEN_DEBUG, "Handle: %lx\n", PortHandle); - - /* Wait forever for a connection request. */ - for (;;) - { - /* Do the wait */ - Status = NtReplyWaitReceivePort(PortHandle, - NULL, - NULL, - ConnectMessage); - - /* Accept only LPC_CONNECTION_REQUEST requests. */ - if ((Status != STATUS_SUCCESS) || - (LpcpGetMessageType(ConnectMessage) == LPC_CONNECTION_REQUEST)) - { - /* Break out */ - break; - } - } - - /* Return status */ - return Status; -} - - -/* EOF */ diff --git a/reactos/ntoskrnl/lpc/ntlpc/lpc.h b/reactos/ntoskrnl/lpc/ntlpc/lpc.h deleted file mode 100644 index 5570e81c6dc..00000000000 --- a/reactos/ntoskrnl/lpc/ntlpc/lpc.h +++ /dev/null @@ -1,130 +0,0 @@ -/* -* PROJECT: ReactOS Kernel -* LICENSE: GPL - See COPYING in the top level directory -* FILE: ntoskrnl/include/lpc.h -* PURPOSE: Internal header for the Local Procedure Call -* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) -*/ - -// -// Define this if you want debugging support -// -#define _LPC_DEBUG_ 0x01 - -// -// These define the Debug Masks Supported -// -#define LPC_CREATE_DEBUG 0x01 -#define LPC_CLOSE_DEBUG 0x02 -#define LPC_CONNECT_DEBUG 0x04 -#define LPC_LISTEN_DEBUG 0x08 -#define LPC_REPLY_DEBUG 0x10 -#define LPC_COMPLETE_DEBUG 0x20 -#define LPC_SEND_DEBUG 0x40 - -// -// Debug/Tracing support -// -#if _LPC_DEBUG_ -#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented -#define LPCTRACE(x, ...) \ - { \ - DbgPrintEx("%s [%.16s] - ", \ - __FUNCTION__, \ - PsGetCurrentProcess()->ImageFileName); \ - DbgPrintEx(__VA_ARGS__); \ - } -#else -#define LPCTRACE(x, ...) \ - if (x & LpcpTraceLevel) \ - { \ - DbgPrint("%s [%.16s:%lx] - ", \ - __FUNCTION__, \ - PsGetCurrentProcess()->ImageFileName, \ - PsGetCurrentThreadId()); \ - DbgPrint(__VA_ARGS__); \ - } -#endif -#endif - -// -// Internal Port Management -// -VOID -NTAPI -LpcpClosePort( - IN PEPROCESS Process OPTIONAL, - IN PVOID Object, - IN ACCESS_MASK GrantedAccess, - IN ULONG ProcessHandleCount, - IN ULONG SystemHandleCount -); - -VOID -NTAPI -LpcpDeletePort( - IN PVOID ObjectBody -); - -NTSTATUS -NTAPI -LpcpInitializePortQueue( - IN PLPCP_PORT_OBJECT Port -); - -VOID -NTAPI -LpcpFreeToPortZone( - IN PLPCP_MESSAGE Message, - IN ULONG Flags -); - -VOID -NTAPI -LpcpMoveMessage( - IN PPORT_MESSAGE Destination, - IN PPORT_MESSAGE Origin, - IN PVOID Data, - IN ULONG MessageType, - IN PCLIENT_ID ClientId -); - -VOID -NTAPI -LpcpSaveDataInfoMessage( - IN PLPCP_PORT_OBJECT Port, - IN PLPCP_MESSAGE Message -); - -// -// Module-external utlity functions -// -VOID -NTAPI -LpcExitThread( - IN PETHREAD Thread -); - -// -// Initialization functions -// -NTSTATUS -NTAPI -LpcpInitSystem( - VOID -); - -// -// Global data inside the Process Manager -// -extern POBJECT_TYPE LpcPortObjectType; -extern ULONG LpcpNextMessageId, LpcpNextCallbackId; -extern KGUARDED_MUTEX LpcpLock; -extern PAGED_LOOKASIDE_LIST LpcpMessagesLookaside; -extern ULONG LpcpMaxMessageSize; -extern ULONG LpcpTraceLevel; - -// -// Inlined Functions -// -#include "lpc_x.h" diff --git a/reactos/ntoskrnl/lpc/ntlpc/port.c b/reactos/ntoskrnl/lpc/ntlpc/port.c deleted file mode 100644 index dcc5a979d44..00000000000 --- a/reactos/ntoskrnl/lpc/ntlpc/port.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory - * FILE: ntoskrnl/lpc/port.c - * PURPOSE: Local Procedure Call: Port Management - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include -#include "lpc.h" -#define NDEBUG -#include - -/* GLOBALS *******************************************************************/ - -POBJECT_TYPE LpcPortObjectType; -ULONG LpcpMaxMessageSize; -PAGED_LOOKASIDE_LIST LpcpMessagesLookaside; -KGUARDED_MUTEX LpcpLock; -ULONG LpcpTraceLevel = LPC_CLOSE_DEBUG; -ULONG LpcpNextMessageId = 1, LpcpNextCallbackId = 1; - -static GENERIC_MAPPING LpcpPortMapping = -{ - STANDARD_RIGHTS_READ, - STANDARD_RIGHTS_WRITE, - 0, - PORT_ALL_ACCESS -}; - -/* PRIVATE FUNCTIONS *********************************************************/ - -NTSTATUS -INIT_FUNCTION -NTAPI -LpcpInitSystem(VOID) -{ - OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; - UNICODE_STRING Name; - - /* Setup the LPC Lock */ - KeInitializeGuardedMutex(&LpcpLock); - - /* Create the Port Object Type */ - RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); - RtlInitUnicodeString(&Name, L"Port"); - ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); - ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(LPCP_PORT_OBJECT); - ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(LPCP_NONPAGED_PORT_QUEUE); - ObjectTypeInitializer.GenericMapping = LpcpPortMapping; - ObjectTypeInitializer.PoolType = PagedPool; - ObjectTypeInitializer.UseDefaultObject = TRUE; - ObjectTypeInitializer.CloseProcedure = LpcpClosePort; - ObjectTypeInitializer.DeleteProcedure = LpcpDeletePort; - ObjectTypeInitializer.ValidAccessMask = PORT_ALL_ACCESS; - ObjectTypeInitializer.MaintainTypeList = TRUE; - ObCreateObjectType(&Name, - &ObjectTypeInitializer, - NULL, - &LpcPortObjectType); - - /* Allocate the LPC lookaside list */ - LpcpMaxMessageSize = LPCP_MAX_MESSAGE_SIZE; - ExInitializePagedLookasideList(&LpcpMessagesLookaside, - NULL, - NULL, - 0, - LpcpMaxMessageSize, - TAG('L', 'p', 'c', 'M'), - 32); - - /* We're done */ - return STATUS_SUCCESS; -} - -/* PUBLIC FUNCTIONS **********************************************************/ - -NTSTATUS -NTAPI -NtImpersonateClientOfPort(IN HANDLE PortHandle, - IN PPORT_MESSAGE ClientMessage) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtQueryPortInformationProcess(VOID) -{ - /* This is all this function does */ - return STATUS_UNSUCCESSFUL; -} - -NTSTATUS -NTAPI -NtQueryInformationPort(IN HANDLE PortHandle, - IN PORT_INFORMATION_CLASS PortInformationClass, - OUT PVOID PortInformation, - IN ULONG PortInformationLength, - OUT PULONG ReturnLength) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -/* EOF */ diff --git a/reactos/ntoskrnl/lpc/ntlpc/reply.c b/reactos/ntoskrnl/lpc/ntlpc/reply.c deleted file mode 100644 index 311002eb2eb..00000000000 --- a/reactos/ntoskrnl/lpc/ntlpc/reply.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory - * FILE: ntoskrnl/lpc/reply.c - * PURPOSE: Local Procedure Call: Receive (Replies) - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include -#include "lpc.h" -#define NDEBUG -#include - -/* PRIVATE FUNCTIONS *********************************************************/ - -VOID -NTAPI -LpcpFreeDataInfoMessage(IN PLPCP_PORT_OBJECT Port, - IN ULONG MessageId, - IN ULONG CallbackId) -{ - PLPCP_MESSAGE Message; - PLIST_ENTRY ListHead, NextEntry; - - /* Check if the port we want is the connection port */ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) > LPCP_UNCONNECTED_PORT) - { - /* Use it */ - Port = Port->ConnectionPort; - } - - /* Loop the list */ - ListHead = &Port->LpcDataInfoChainHead; - NextEntry = ListHead->Flink; - while (ListHead != NextEntry) - { - /* Get the message */ - Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry); - - /* Make sure it matches */ - if ((Message->Request.MessageId == MessageId) && - (Message->Request.CallbackId == CallbackId)) - { - /* Unlink and free it */ - RemoveEntryList(&Message->Entry); - InitializeListHead(&Message->Entry); - LpcpFreeToPortZone(Message, TRUE); - break; - } - - /* Go to the next entry */ - NextEntry = NextEntry->Flink; - } -} - -VOID -NTAPI -LpcpSaveDataInfoMessage(IN PLPCP_PORT_OBJECT Port, - IN PLPCP_MESSAGE Message) -{ - PAGED_CODE(); - - /* Acquire the lock */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Check if the port we want is the connection port */ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) > LPCP_UNCONNECTED_PORT) - { - /* Use it */ - Port = Port->ConnectionPort; - } - - /* Link the message */ - InsertTailList(&Port->LpcDataInfoChainHead, &Message->Entry); - - /* Release the lock */ - KeReleaseGuardedMutex(&LpcpLock); -} - -VOID -NTAPI -LpcpMoveMessage(IN PPORT_MESSAGE Destination, - IN PPORT_MESSAGE Origin, - IN PVOID Data, - IN ULONG MessageType, - IN PCLIENT_ID ClientId) -{ - /* Set the Message size */ - LPCTRACE((LPC_REPLY_DEBUG | LPC_SEND_DEBUG), - "Destination/Origin: %p/%p. Data: %p. Length: %lx\n", - Destination, - Origin, - Data, - Origin->u1.Length); - Destination->u1.Length = Origin->u1.Length; - - /* Set the Message Type */ - Destination->u2.s2.Type = !MessageType ? - Origin->u2.s2.Type : MessageType & 0xFFFF; - - /* Check if we have a Client ID */ - if (ClientId) - { - /* Set the Client ID */ - Destination->ClientId.UniqueProcess = ClientId->UniqueProcess; - Destination->ClientId.UniqueThread = ClientId->UniqueThread; - } - else - { - /* Otherwise, copy it */ - Destination->ClientId.UniqueProcess = Origin->ClientId.UniqueProcess; - Destination->ClientId.UniqueThread = Origin->ClientId.UniqueThread; - } - - /* Copy the MessageId and ClientViewSize */ - Destination->MessageId = Origin->MessageId; - Destination->ClientViewSize = Origin->ClientViewSize; - - /* Copy the Message Data */ - RtlMoveMemory(Destination + 1, - Data, - ((Destination->u1.Length & 0xFFFF) + 3) &~3); -} - -/* PUBLIC FUNCTIONS **********************************************************/ - -/* - * @unimplemented - */ -NTSTATUS -NTAPI -NtReplyPort(IN HANDLE PortHandle, - IN PPORT_MESSAGE LpcReply) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -/* - * @implemented - */ -NTSTATUS -NTAPI -NtReplyWaitReceivePortEx(IN HANDLE PortHandle, - OUT PVOID *PortContext OPTIONAL, - IN PPORT_MESSAGE ReplyMessage OPTIONAL, - OUT PPORT_MESSAGE ReceiveMessage, - IN PLARGE_INTEGER Timeout OPTIONAL) -{ - PLPCP_PORT_OBJECT Port, ReceivePort; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(), WaitMode = PreviousMode; - NTSTATUS Status; - PLPCP_MESSAGE Message; - PETHREAD Thread = PsGetCurrentThread(), WakeupThread; - PLPCP_CONNECTION_MESSAGE ConnectMessage; - ULONG ConnectionInfoLength; - PAGED_CODE(); - LPCTRACE(LPC_REPLY_DEBUG, - "Handle: %lx. Messages: %p/%p. Context: %p\n", - PortHandle, - ReplyMessage, - ReceiveMessage, - PortContext); - - /* If this is a system thread, then let it page out its stack */ - if (Thread->SystemThread) WaitMode = UserMode; - - /* Check if caller has a reply message */ - if (ReplyMessage) - { - /* Validate its length */ - if ((ReplyMessage->u1.s1.DataLength + sizeof(PORT_MESSAGE)) > - ReplyMessage->u1.s1.TotalLength) - { - /* Fail */ - return STATUS_INVALID_PARAMETER; - } - - /* Make sure it has a valid ID */ - if (!ReplyMessage->MessageId) return STATUS_INVALID_PARAMETER; - } - - /* Get the Port object */ - Status = ObReferenceObjectByHandle(PortHandle, - 0, - LpcPortObjectType, - PreviousMode, - (PVOID*)&Port, - NULL); - if (!NT_SUCCESS(Status)) return Status; - - /* Check if the caller has a reply message */ - if (ReplyMessage) - { - /* Validate its length in respect to the port object */ - if ((ReplyMessage->u1.s1.TotalLength > Port->MaxMessageLength) || - (ReplyMessage->u1.s1.TotalLength <= ReplyMessage->u1.s1.DataLength)) - { - /* Too large, fail */ - ObDereferenceObject(Port); - return STATUS_PORT_MESSAGE_TOO_LONG; - } - } - - /* Check if this is anything but a client port */ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CLIENT_PORT) - { - /* Use the connection port */ - ReceivePort = Port->ConnectionPort; - } - else - { - /* Otherwise, use the port itself */ - ReceivePort = Port; - } - - /* Check if the caller gave a reply message */ - if (ReplyMessage) - { - /* Get the ETHREAD corresponding to it */ - Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId, - NULL, - &WakeupThread); - if (!NT_SUCCESS(Status)) - { - /* No thread found, fail */ - ObDereferenceObject(Port); - return Status; - } - - /* Allocate a message from the port zone */ - Message = LpcpAllocateFromPortZone(); - if (!Message) - { - /* Fail if we couldn't allocate a message */ - ObDereferenceObject(WakeupThread); - ObDereferenceObject(Port); - return STATUS_NO_MEMORY; - } - - /* Keep the lock acquired */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Make sure this is the reply the thread is waiting for */ - if (WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId) - { - /* It isn't, fail */ - LpcpFreeToPortZone(Message, TRUE); - KeReleaseGuardedMutex(&LpcpLock); - ObDereferenceObject(WakeupThread); - ObDereferenceObject(Port); - return STATUS_REPLY_MESSAGE_MISMATCH; - } - - /* Copy the message */ - LpcpMoveMessage(&Message->Request, - ReplyMessage, - ReplyMessage + 1, - LPC_REPLY, - NULL); - - /* Free any data information */ - LpcpFreeDataInfoMessage(Port, - ReplyMessage->MessageId, - ReplyMessage->CallbackId); - - /* Reference the thread while we use it */ - ObReferenceObject(WakeupThread); - Message->RepliedToThread = WakeupThread; - - /* Set this as the reply message */ - WakeupThread->LpcReplyMessageId = 0; - WakeupThread->LpcReplyMessage = (PVOID)Message; - - /* Check if we have messages on the reply chain */ - if (!(WakeupThread->LpcExitThreadCalled) && - !(IsListEmpty(&WakeupThread->LpcReplyChain))) - { - /* Remove us from it and reinitialize it */ - RemoveEntryList(&WakeupThread->LpcReplyChain); - InitializeListHead(&WakeupThread->LpcReplyChain); - } - - /* Check if this is the message the thread had received */ - if ((Thread->LpcReceivedMsgIdValid) && - (Thread->LpcReceivedMessageId == ReplyMessage->MessageId)) - { - /* Clear this data */ - Thread->LpcReceivedMessageId = 0; - Thread->LpcReceivedMsgIdValid = FALSE; - } - - /* Release the lock and release the LPC semaphore to wake up waiters */ - KeReleaseGuardedMutex(&LpcpLock); - LpcpCompleteWait(&WakeupThread->LpcReplySemaphore); - - /* Now we can let go of the thread */ - ObDereferenceObject(WakeupThread); - } - - /* Now wait for someone to reply to us */ - LpcpReceiveWait(ReceivePort->MsgQueue.Semaphore, WaitMode); - if (Status != STATUS_SUCCESS) goto Cleanup; - - /* Wait done, get the LPC lock */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Check if we've received nothing */ - if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead)) - { - /* Check if this was a waitable port and wake it */ - if (ReceivePort->Flags & LPCP_WAITABLE_PORT) - { - /* Reset its event */ - KeResetEvent(&ReceivePort->WaitEvent); - } - - /* Release the lock and fail */ - KeReleaseGuardedMutex(&LpcpLock); - ObDereferenceObject(Port); - return STATUS_UNSUCCESSFUL; - } - - /* Get the message on the queue */ - Message = CONTAINING_RECORD(RemoveHeadList(&ReceivePort-> - MsgQueue.ReceiveHead), - LPCP_MESSAGE, - Entry); - - /* Check if the queue is empty now */ - if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead)) - { - /* Check if this was a waitable port */ - if (ReceivePort->Flags & LPCP_WAITABLE_PORT) - { - /* Reset its event */ - KeResetEvent(&ReceivePort->WaitEvent); - } - } - - /* Re-initialize the message's list entry */ - InitializeListHead(&Message->Entry); - - /* Set this as the received message */ - Thread->LpcReceivedMessageId = Message->Request.MessageId; - Thread->LpcReceivedMsgIdValid = TRUE; - - /* Done touching global data, release the lock */ - KeReleaseGuardedMutex(&LpcpLock); - - /* Check if this was a connection request */ - if (LpcpGetMessageType(&Message->Request) == LPC_CONNECTION_REQUEST) - { - /* Get the connection message */ - ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); - LPCTRACE(LPC_REPLY_DEBUG, - "Request Messages: %p/%p\n", - Message, - ConnectMessage); - - /* Get its length */ - ConnectionInfoLength = Message->Request.u1.s1.DataLength - - sizeof(LPCP_CONNECTION_MESSAGE); - - /* Return it as the receive message */ - *ReceiveMessage = Message->Request; - - /* Clear our stack variable so the message doesn't get freed */ - Message = NULL; - - /* Setup the receive message */ - ReceiveMessage->u1.s1.TotalLength = sizeof(LPCP_MESSAGE) + - ConnectionInfoLength; - ReceiveMessage->u1.s1.DataLength = ConnectionInfoLength; - RtlMoveMemory(ReceiveMessage + 1, - ConnectMessage + 1, - ConnectionInfoLength); - - /* Clear the port context if the caller requested one */ - if (PortContext) *PortContext = NULL; - } - else if (Message->Request.u2.s2.Type != LPC_REPLY) - { - /* Otherwise, this is a new message or event */ - LPCTRACE(LPC_REPLY_DEBUG, - "Non-Reply Messages: %p/%p\n", - &Message->Request, - (&Message->Request) + 1); - - /* Copy it */ - LpcpMoveMessage(ReceiveMessage, - &Message->Request, - (&Message->Request) + 1, - 0, - NULL); - - /* Return its context */ - if (PortContext) *PortContext = Message->PortContext; - - /* And check if it has data information */ - if (Message->Request.u2.s2.DataInfoOffset) - { - /* It does, save it, and don't free the message below */ - LpcpSaveDataInfoMessage(Port, Message); - Message = NULL; - } - } - else - { - /* This is a reply message, should never happen! */ - ASSERT(FALSE); - } - - /* If we have a message pointer here, free it */ - if (Message) LpcpFreeToPortZone(Message, FALSE); - -Cleanup: - /* All done, dereference the port and return the status */ - LPCTRACE(LPC_REPLY_DEBUG, - "Port: %p. Status: %p\n", - Port, - Status); - ObDereferenceObject(Port); - return Status; -} - -/* - * @implemented - */ -NTSTATUS -NTAPI -NtReplyWaitReceivePort(IN HANDLE PortHandle, - OUT PVOID *PortContext OPTIONAL, - IN PPORT_MESSAGE ReplyMessage OPTIONAL, - OUT PPORT_MESSAGE ReceiveMessage) -{ - /* Call the newer API */ - return NtReplyWaitReceivePortEx(PortHandle, - PortContext, - ReplyMessage, - ReceiveMessage, - NULL); -} - -/* - * @unimplemented - */ -NTSTATUS -NTAPI -NtReplyWaitReplyPort(IN HANDLE PortHandle, - IN PPORT_MESSAGE ReplyMessage) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -/* - * @unimplemented - */ -NTSTATUS -NTAPI -NtReadRequestData(IN HANDLE PortHandle, - IN PPORT_MESSAGE Message, - IN ULONG Index, - IN PVOID Buffer, - IN ULONG BufferLength, - OUT PULONG Returnlength) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -/* - * @unimplemented - */ -NTSTATUS -NTAPI -NtWriteRequestData(IN HANDLE PortHandle, - IN PPORT_MESSAGE Message, - IN ULONG Index, - IN PVOID Buffer, - IN ULONG BufferLength, - OUT PULONG ReturnLength) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -/* EOF */ diff --git a/reactos/ntoskrnl/lpc/ntlpc/send.c b/reactos/ntoskrnl/lpc/ntlpc/send.c deleted file mode 100644 index f49e0a6550f..00000000000 --- a/reactos/ntoskrnl/lpc/ntlpc/send.c +++ /dev/null @@ -1,426 +0,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory - * FILE: ntoskrnl/lpc/send.c - * PURPOSE: Local Procedure Call: Sending (Requests) - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include -#include "lpc.h" -#define NDEBUG -#include - -/* PUBLIC FUNCTIONS **********************************************************/ - -/* - * @implemented - */ -NTSTATUS -NTAPI -LpcRequestPort(IN PVOID PortObject, - IN PPORT_MESSAGE LpcMessage) -{ - PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)PortObject, QueuePort; - ULONG MessageType; - PLPCP_MESSAGE Message; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - PAGED_CODE(); - LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", Port, LpcMessage); - - /* Check if this is a non-datagram message */ - if (LpcMessage->u2.s2.Type) - { - /* Get the message type */ - MessageType = LpcpGetMessageType(LpcMessage); - - /* Validate it */ - if ((MessageType < LPC_DATAGRAM) || (MessageType > LPC_CLIENT_DIED)) - { - /* Fail */ - return STATUS_INVALID_PARAMETER; - } - - /* Mark this as a kernel-mode message only if we really came from there */ - if ((PreviousMode == KernelMode) && - (LpcMessage->u2.s2.Type & LPC_KERNELMODE_MESSAGE)) - { - /* We did, this is a kernel mode message */ - MessageType |= LPC_KERNELMODE_MESSAGE; - } - } - else - { - /* This is a datagram */ - MessageType = LPC_DATAGRAM; - } - - /* Can't have data information on this type of call */ - if (LpcMessage->u2.s2.DataInfoOffset) return STATUS_INVALID_PARAMETER; - - /* Validate message sizes */ - if ((LpcMessage->u1.s1.TotalLength > Port->MaxMessageLength) || - (LpcMessage->u1.s1.TotalLength <= LpcMessage->u1.s1.DataLength)) - { - /* Fail */ - return STATUS_PORT_MESSAGE_TOO_LONG; - } - - /* Allocate a new message */ - Message = LpcpAllocateFromPortZone(); - if (!Message) return STATUS_NO_MEMORY; - - /* Clear the context */ - Message->PortContext = NULL; - - /* Copy the message */ - LpcpMoveMessage(&Message->Request, - LpcMessage, - LpcMessage + 1, - MessageType, - &PsGetCurrentThread()->Cid); - - /* Acquire the LPC lock */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Check if this is anything but a connection port */ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT) - { - /* The queue port is the connected port */ - QueuePort = Port->ConnectedPort; - if (QueuePort) - { - /* Check if this is a client port */ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT) - { - /* Then copy the context */ - Message->PortContext = QueuePort->PortContext; - QueuePort = Port->ConnectionPort; - } - else if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_COMMUNICATION_PORT) - { - /* Any other kind of port, use the connection port */ - QueuePort = Port->ConnectionPort; - } - } - } - else - { - /* For connection ports, use the port itself */ - QueuePort = PortObject; - } - - /* Make sure we have a port */ - if (QueuePort) - { - /* Generate the Message ID and set it */ - Message->Request.MessageId = LpcpNextMessageId++; - if (!LpcpNextMessageId) LpcpNextMessageId = 1; - Message->Request.CallbackId = 0; - - /* No Message ID for the thread */ - PsGetCurrentThread()->LpcReplyMessageId = 0; - - /* Insert the message in our chain */ - InsertTailList(&QueuePort->MsgQueue.ReceiveHead, &Message->Entry); - - /* Release the lock and release the semaphore */ - KeReleaseGuardedMutex(&LpcpLock); - LpcpCompleteWait(QueuePort->MsgQueue.Semaphore); - - /* If this is a waitable port, wake it up */ - if (QueuePort->Flags & LPCP_WAITABLE_PORT) - { - /* Wake it */ - KeSetEvent(&QueuePort->WaitEvent, IO_NO_INCREMENT, FALSE); - } - - /* We're done */ - LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", QueuePort, Message); - return STATUS_SUCCESS; - } - - /* If we got here, then free the message and fail */ - LpcpFreeToPortZone(Message, TRUE); - KeReleaseGuardedMutex(&LpcpLock); - return STATUS_PORT_DISCONNECTED; -} - -/* -* @unimplemented -*/ -NTSTATUS -NTAPI -LpcRequestWaitReplyPort(IN PVOID Port, - IN PPORT_MESSAGE LpcMessageRequest, - OUT PPORT_MESSAGE LpcMessageReply) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -/* - * @unimplemented - */ -NTSTATUS -NTAPI -NtRequestPort(IN HANDLE PortHandle, - IN PPORT_MESSAGE LpcMessage) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -/* - * @implemented - */ -NTSTATUS -NTAPI -NtRequestWaitReplyPort(IN HANDLE PortHandle, - IN PPORT_MESSAGE LpcRequest, - IN OUT PPORT_MESSAGE LpcReply) -{ - PLPCP_PORT_OBJECT Port, QueuePort, ReplyPort; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - NTSTATUS Status; - PLPCP_MESSAGE Message; - PETHREAD Thread = PsGetCurrentThread(); - BOOLEAN Callback; - PKSEMAPHORE Semaphore; - ULONG MessageType; - PAGED_CODE(); - LPCTRACE(LPC_SEND_DEBUG, - "Handle: %lx. Messages: %p/%p. Type: %lx\n", - PortHandle, - LpcRequest, - LpcReply, - LpcpGetMessageType(LpcRequest)); - - /* Check if the thread is dying */ - if (Thread->LpcExitThreadCalled) return STATUS_THREAD_IS_TERMINATING; - - /* Check if this is an LPC Request */ - if (LpcpGetMessageType(LpcRequest) == LPC_REQUEST) - { - /* Then it's a callback */ - Callback = TRUE; - } - else if (LpcpGetMessageType(LpcRequest)) - { - /* This is a not kernel-mode message */ - return STATUS_INVALID_PARAMETER; - } - else - { - /* This is a kernel-mode message without a callback */ - LpcRequest->u2.s2.Type |= LPC_REQUEST; - Callback = FALSE; - } - - /* Get the message type */ - MessageType = LpcRequest->u2.s2.Type; - - /* Validate the length */ - if ((LpcRequest->u1.s1.DataLength + sizeof(PORT_MESSAGE)) > - LpcRequest->u1.s1.TotalLength) - { - /* Fail */ - return STATUS_INVALID_PARAMETER; - } - - /* Reference the object */ - Status = ObReferenceObjectByHandle(PortHandle, - 0, - LpcPortObjectType, - PreviousMode, - (PVOID*)&Port, - NULL); - if (!NT_SUCCESS(Status)) return Status; - - /* Validate the message length */ - if ((LpcRequest->u1.s1.TotalLength > Port->MaxMessageLength) || - (LpcRequest->u1.s1.TotalLength <= LpcRequest->u1.s1.DataLength)) - { - /* Fail */ - ObDereferenceObject(Port); - return STATUS_PORT_MESSAGE_TOO_LONG; - } - - /* Allocate a message from the port zone */ - Message = LpcpAllocateFromPortZone(); - if (!Message) - { - /* Fail if we couldn't allocate a message */ - ObDereferenceObject(Port); - return STATUS_NO_MEMORY; - } - - /* Check if this is a callback */ - if (Callback) - { - /* FIXME: TODO */ - Semaphore = NULL; // we'd use the Thread Semaphore here - ASSERT(FALSE); - } - else - { - /* No callback, just copy the message */ - LpcpMoveMessage(&Message->Request, - LpcRequest, - LpcRequest + 1, - MessageType, - &Thread->Cid); - - /* Acquire the LPC lock */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Right now clear the port context */ - Message->PortContext = NULL; - - /* Check if this is a not connection port */ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT) - { - /* We want the connected port */ - QueuePort = Port->ConnectedPort; - if (!QueuePort) - { - /* We have no connected port, fail */ - LpcpFreeToPortZone(Message, TRUE); - KeReleaseGuardedMutex(&LpcpLock); - ObDereferenceObject(Port); - return STATUS_PORT_DISCONNECTED; - } - - /* This will be the rundown port */ - ReplyPort = QueuePort; - - /* Check if this is a communication port */ - if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT) - { - /* Copy the port context and use the connection port */ - Message->PortContext = ReplyPort->PortContext; - QueuePort = Port->ConnectionPort; - } - else if ((Port->Flags & LPCP_PORT_TYPE_MASK) != - LPCP_COMMUNICATION_PORT) - { - /* Use the connection port for anything but communication ports */ - QueuePort = Port->ConnectionPort; - } - } - else - { - /* Otherwise, for a connection port, use the same port object */ - QueuePort = ReplyPort = Port; - } - - /* No reply thread */ - Message->RepliedToThread = NULL; - - /* Generate the Message ID and set it */ - Message->Request.MessageId = LpcpNextMessageId++; - if (!LpcpNextMessageId) LpcpNextMessageId = 1; - Message->Request.CallbackId = 0; - - /* Set the message ID for our thread now */ - Thread->LpcReplyMessageId = Message->Request.MessageId; - Thread->LpcReplyMessage = NULL; - - /* Insert the message in our chain */ - InsertTailList(&QueuePort->MsgQueue.ReceiveHead, &Message->Entry); - InsertTailList(&ReplyPort->LpcReplyChainHead, &Thread->LpcReplyChain); - - /* Release the lock and get the semaphore we'll use later */ - KeReleaseGuardedMutex(&LpcpLock); - Semaphore = QueuePort->MsgQueue.Semaphore; - - /* If this is a waitable port, wake it up */ - if (QueuePort->Flags & LPCP_WAITABLE_PORT) - { - /* Wake it */ - KeSetEvent(&QueuePort->WaitEvent, IO_NO_INCREMENT, FALSE); - } - } - - /* Now release the semaphore */ - LpcpCompleteWait(Semaphore); - - /* And let's wait for the reply */ - LpcpReplyWait(&Thread->LpcReplySemaphore, PreviousMode); - - /* Acquire the LPC lock */ - KeAcquireGuardedMutex(&LpcpLock); - - /* Get the LPC Message and clear our thread's reply data */ - Message = Thread->LpcReplyMessage; - Thread->LpcReplyMessage = NULL; - Thread->LpcReplyMessageId = 0; - - /* Check if we have anything on the reply chain*/ - if (!IsListEmpty(&Thread->LpcReplyChain)) - { - /* Remove this thread and reinitialize the list */ - RemoveEntryList(&Thread->LpcReplyChain); - InitializeListHead(&Thread->LpcReplyChain); - } - - /* Release the lock */ - KeReleaseGuardedMutex(&LpcpLock); - - /* Check if we got a reply */ - if (Status == STATUS_SUCCESS) - { - /* Check if we have a valid message */ - if (Message) - { - LPCTRACE(LPC_SEND_DEBUG, - "Reply Messages: %p/%p\n", - &Message->Request, - (&Message->Request) + 1); - - /* Move the message */ - LpcpMoveMessage(LpcReply, - &Message->Request, - (&Message->Request) + 1, - 0, - NULL); - - /* Check if this is an LPC request with data information */ - if ((LpcpGetMessageType(&Message->Request) == LPC_REQUEST) && - (Message->Request.u2.s2.DataInfoOffset)) - { - /* Save the data information */ - LpcpSaveDataInfoMessage(Port, Message); - } - else - { - /* Otherwise, just free it */ - LpcpFreeToPortZone(Message, FALSE); - } - } - else - { - /* We don't have a reply */ - Status = STATUS_LPC_REPLY_LOST; - } - } - else - { - /* The wait failed, free the message while holding the lock */ - KeAcquireGuardedMutex(&LpcpLock); - LpcpFreeToPortZone(Message, TRUE); - KeReleaseGuardedMutex(&LpcpLock); - } - - /* All done */ - LPCTRACE(LPC_SEND_DEBUG, - "Port: %p. Status: %p\n", - Port, - Status); - ObDereferenceObject(Port); - return Status; -} - -/* EOF */ diff --git a/reactos/ntoskrnl/lpc/port.c b/reactos/ntoskrnl/lpc/port.c index 18fec96de83..dcc5a979d44 100644 --- a/reactos/ntoskrnl/lpc/port.c +++ b/reactos/ntoskrnl/lpc/port.c @@ -1,29 +1,26 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/lpc/port.c - * PURPOSE: Communication mechanism - * - * PROGRAMMERS: David Welch (welch@cwcom.net) + * PURPOSE: Local Procedure Call: Port Management + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ -/* INCLUDES *****************************************************************/ +/* INCLUDES ******************************************************************/ #include +#include "lpc.h" #define NDEBUG #include -#if defined (ALLOC_PRAGMA) -#pragma alloc_text(INIT, LpcpInitSystem) -#endif - - /* GLOBALS *******************************************************************/ -POBJECT_TYPE LpcPortObjectType = 0; -ULONG LpcpNextMessageId = 0; /* 0 is not a valid ID */ -FAST_MUTEX LpcpLock; /* global internal sync in LPC facility */ +POBJECT_TYPE LpcPortObjectType; +ULONG LpcpMaxMessageSize; +PAGED_LOOKASIDE_LIST LpcpMessagesLookaside; +KGUARDED_MUTEX LpcpLock; +ULONG LpcpTraceLevel = LPC_CLOSE_DEBUG; +ULONG LpcpNextMessageId = 1, LpcpNextCallbackId = 1; static GENERIC_MAPPING LpcpPortMapping = { @@ -33,105 +30,60 @@ static GENERIC_MAPPING LpcpPortMapping = PORT_ALL_ACCESS }; -/* FUNCTIONS *****************************************************************/ - +/* PRIVATE FUNCTIONS *********************************************************/ NTSTATUS INIT_FUNCTION NTAPI -LpcpInitSystem (VOID) +LpcpInitSystem(VOID) { OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; UNICODE_STRING Name; - DPRINT("Creating Port Object Type\n"); - + /* Setup the LPC Lock */ + KeInitializeGuardedMutex(&LpcpLock); + /* Create the Port Object Type */ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); RtlInitUnicodeString(&Name, L"Port"); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); - ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(EPORT); + ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(LPCP_PORT_OBJECT); + ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(LPCP_NONPAGED_PORT_QUEUE); ObjectTypeInitializer.GenericMapping = LpcpPortMapping; - ObjectTypeInitializer.PoolType = NonPagedPool; + ObjectTypeInitializer.PoolType = PagedPool; ObjectTypeInitializer.UseDefaultObject = TRUE; ObjectTypeInitializer.CloseProcedure = LpcpClosePort; ObjectTypeInitializer.DeleteProcedure = LpcpDeletePort; ObjectTypeInitializer.ValidAccessMask = PORT_ALL_ACCESS; - ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &LpcPortObjectType); + ObjectTypeInitializer.MaintainTypeList = TRUE; + ObCreateObjectType(&Name, + &ObjectTypeInitializer, + NULL, + &LpcPortObjectType); - LpcpNextMessageId = 0; - ExInitializeFastMutex (& LpcpLock); + /* Allocate the LPC lookaside list */ + LpcpMaxMessageSize = LPCP_MAX_MESSAGE_SIZE; + ExInitializePagedLookasideList(&LpcpMessagesLookaside, + NULL, + NULL, + 0, + LpcpMaxMessageSize, + TAG('L', 'p', 'c', 'M'), + 32); - return(STATUS_SUCCESS); + /* We're done */ + return STATUS_SUCCESS; } +/* PUBLIC FUNCTIONS **********************************************************/ -/********************************************************************** - * NAME INTERNAL - * NiInitializePort/3 - * - * DESCRIPTION - * Initialize the EPORT object attributes. The Port - * object enters the inactive state. - * - * ARGUMENTS - * Port Pointer to an EPORT object to initialize. - * Type connect (RQST), or communication port (COMM) - * Parent OPTIONAL connect port a communication port - * is created from - * - * RETURN VALUE - * STATUS_SUCCESS if initialization succedeed. An error code - * otherwise. - */ -NTSTATUS STDCALL -LpcpInitializePort (IN OUT PEPORT Port, - IN USHORT Type, - IN PEPORT Parent OPTIONAL) +NTSTATUS +NTAPI +NtImpersonateClientOfPort(IN HANDLE PortHandle, + IN PPORT_MESSAGE ClientMessage) { - if ((Type != EPORT_TYPE_SERVER_RQST_PORT) && - (Type != EPORT_TYPE_SERVER_COMM_PORT) && - (Type != EPORT_TYPE_CLIENT_COMM_PORT)) - { - return STATUS_INVALID_PARAMETER_2; - } - memset (Port, 0, sizeof(EPORT)); - KeInitializeSpinLock (& Port->Lock); - KeInitializeSemaphore( &Port->Semaphore, 0, MAXLONG ); - Port->RequestPort = Parent; - Port->OtherPort = NULL; - Port->QueueLength = 0; - Port->ConnectQueueLength = 0; - Port->Type = Type; - Port->State = EPORT_INACTIVE; - InitializeListHead (& Port->QueueListHead); - InitializeListHead (& Port->ConnectQueueListHead); - - return (STATUS_SUCCESS); -} - - -/* MISCELLANEA SYSTEM SERVICES */ - - -/********************************************************************** - * NAME SYSTEM - * NtImpersonateClientOfPort/2 - * - * DESCRIPTION - * - * ARGUMENTS - * PortHandle, - * ClientMessage - * - * RETURN VALUE - */ -NTSTATUS STDCALL -NtImpersonateClientOfPort (HANDLE PortHandle, - PPORT_MESSAGE ClientMessage) -{ - UNIMPLEMENTED; - return(STATUS_NOT_IMPLEMENTED); + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; } NTSTATUS @@ -142,4 +94,16 @@ NtQueryPortInformationProcess(VOID) return STATUS_UNSUCCESSFUL; } +NTSTATUS +NTAPI +NtQueryInformationPort(IN HANDLE PortHandle, + IN PORT_INFORMATION_CLASS PortInformationClass, + OUT PVOID PortInformation, + IN ULONG PortInformationLength, + OUT PULONG ReturnLength) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + /* EOF */ diff --git a/reactos/ntoskrnl/lpc/query.c b/reactos/ntoskrnl/lpc/query.c deleted file mode 100644 index 3463047c82a..00000000000 --- a/reactos/ntoskrnl/lpc/query.c +++ /dev/null @@ -1,69 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/lpc/query.c - * PURPOSE: Communication mechanism - * - * PROGRAMMERS: David Welch (welch@cwcom.net) - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -/********************************************************************** - * NAME EXPORTED - * NtQueryInformationPort@20 - * - * DESCRIPTION - * - * ARGUMENTS - * PortHandle [IN] - * PortInformationClass [IN] - * PortInformation [OUT] - * PortInformationLength [IN] - * ReturnLength [OUT] - * - * RETURN VALUE - * STATUS_SUCCESS if the call succedeed. An error code - * otherwise. - * - * NOTES - * P. Dabak reports that this system service seems to return - * no information. - */ -/*EXPORTED*/ NTSTATUS STDCALL -NtQueryInformationPort (IN HANDLE PortHandle, - IN PORT_INFORMATION_CLASS PortInformationClass, - OUT PVOID PortInformation, - IN ULONG PortInformationLength, - OUT PULONG ReturnLength) -{ - NTSTATUS Status; - PEPORT Port; - - Status = ObReferenceObjectByHandle (PortHandle, - PORT_ALL_ACCESS, /* AccessRequired */ - LpcPortObjectType, - UserMode, - (PVOID *) & Port, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("NtQueryInformationPort() = %x\n", Status); - return (Status); - } - /* - * FIXME: NT does nothing here! - */ - ObDereferenceObject (Port); - return STATUS_SUCCESS; -} - - -/* EOF */ diff --git a/reactos/ntoskrnl/lpc/queue.c b/reactos/ntoskrnl/lpc/queue.c deleted file mode 100644 index 971e1085d51..00000000000 --- a/reactos/ntoskrnl/lpc/queue.c +++ /dev/null @@ -1,83 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/lpc/queue.c - * PURPOSE: Communication mechanism - * - * PROGRAMMERS: David Welch (welch@cwcom.net) - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -VOID STDCALL -EiEnqueueMessagePort (IN OUT PEPORT Port, - IN PQUEUEDMESSAGE Message) -{ - InsertTailList (&Port->QueueListHead, - &Message->QueueListEntry); - Port->QueueLength++; -} - -VOID STDCALL -EiEnqueueMessageAtHeadPort (IN OUT PEPORT Port, - IN PQUEUEDMESSAGE Message) -{ - InsertTailList (&Port->QueueListHead, - &Message->QueueListEntry); - Port->QueueLength++; -} - -PQUEUEDMESSAGE STDCALL -EiDequeueMessagePort (IN OUT PEPORT Port) -{ - PQUEUEDMESSAGE Message; - PLIST_ENTRY entry; - - if (IsListEmpty(&Port->QueueListHead)) - { - return(NULL); - } - entry = RemoveHeadList (&Port->QueueListHead); - Message = CONTAINING_RECORD (entry, QUEUEDMESSAGE, QueueListEntry); - Port->QueueLength--; - - return (Message); -} - - -VOID STDCALL -EiEnqueueConnectMessagePort (IN OUT PEPORT Port, - IN PQUEUEDMESSAGE Message) -{ - InsertTailList (&Port->ConnectQueueListHead, - &Message->QueueListEntry); - Port->ConnectQueueLength++; -} - - -PQUEUEDMESSAGE STDCALL -EiDequeueConnectMessagePort (IN OUT PEPORT Port) -{ - PQUEUEDMESSAGE Message; - PLIST_ENTRY entry; - - if (IsListEmpty(&Port->ConnectQueueListHead)) - { - return(NULL); - } - entry = RemoveHeadList (&Port->ConnectQueueListHead); - Message = CONTAINING_RECORD (entry, QUEUEDMESSAGE, QueueListEntry); - Port->ConnectQueueLength--; - - return (Message); -} - - -/* EOF */ diff --git a/reactos/ntoskrnl/lpc/receive.c b/reactos/ntoskrnl/lpc/receive.c deleted file mode 100644 index 83631aa388d..00000000000 --- a/reactos/ntoskrnl/lpc/receive.c +++ /dev/null @@ -1,41 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/lpc/receive.c - * PURPOSE: Communication mechanism - * - * PROGRAMMERS: David Welch (welch@cwcom.net) - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -/********************************************************************** - * NAME SYSTEM - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - */ -NTSTATUS STDCALL -NtReadRequestData (HANDLE PortHandle, - PPORT_MESSAGE Message, - ULONG Index, - PVOID Buffer, - ULONG BufferLength, - PULONG Returnlength) -{ - UNIMPLEMENTED; - return(STATUS_NOT_IMPLEMENTED); -} - - -/* EOF */ diff --git a/reactos/ntoskrnl/lpc/reply.c b/reactos/ntoskrnl/lpc/reply.c index 5fb58c22fb6..311002eb2eb 100644 --- a/reactos/ntoskrnl/lpc/reply.c +++ b/reactos/ntoskrnl/lpc/reply.c @@ -1,421 +1,141 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/lpc/reply.c - * PURPOSE: Communication mechanism - * - * PROGRAMMERS: David Welch (welch@cwcom.net) + * PURPOSE: Local Procedure Call: Receive (Replies) + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ /* INCLUDES ******************************************************************/ #include +#include "lpc.h" #define NDEBUG #include -/* GLOBALS *******************************************************************/ +/* PRIVATE FUNCTIONS *********************************************************/ -/* FUNCTIONS *****************************************************************/ - -/********************************************************************** - * NAME - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - */ -NTSTATUS STDCALL -EiReplyOrRequestPort (IN PEPORT Port, - IN PPORT_MESSAGE LpcReply, - IN ULONG MessageType, - IN PEPORT Sender) +VOID +NTAPI +LpcpFreeDataInfoMessage(IN PLPCP_PORT_OBJECT Port, + IN ULONG MessageId, + IN ULONG CallbackId) { - KIRQL oldIrql; - PQUEUEDMESSAGE MessageReply; - ULONG Size; + PLPCP_MESSAGE Message; + PLIST_ENTRY ListHead, NextEntry; - if (Port == NULL) - { - KEBUGCHECK(0); - } + /* Check if the port we want is the connection port */ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) > LPCP_UNCONNECTED_PORT) + { + /* Use it */ + Port = Port->ConnectionPort; + } - Size = sizeof(QUEUEDMESSAGE); - if (LpcReply && LpcReply->u1.s1.TotalLength > (CSHORT)sizeof(PORT_MESSAGE)) - { - Size += LpcReply->u1.s1.TotalLength - sizeof(PORT_MESSAGE); - } - MessageReply = ExAllocatePoolWithTag(NonPagedPool, Size, - TAG_LPC_MESSAGE); - MessageReply->Sender = Sender; + /* Loop the list */ + ListHead = &Port->LpcDataInfoChainHead; + NextEntry = ListHead->Flink; + while (ListHead != NextEntry) + { + /* Get the message */ + Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry); - if (LpcReply != NULL) - { - memcpy(&MessageReply->Message, LpcReply, LpcReply->u1.s1.TotalLength); - } - else - { - MessageReply->Message.u1.s1.TotalLength = sizeof(PORT_MESSAGE); - MessageReply->Message.u1.s1.DataLength = 0; - } + /* Make sure it matches */ + if ((Message->Request.MessageId == MessageId) && + (Message->Request.CallbackId == CallbackId)) + { + /* Unlink and free it */ + RemoveEntryList(&Message->Entry); + InitializeListHead(&Message->Entry); + LpcpFreeToPortZone(Message, TRUE); + break; + } - MessageReply->Message.ClientId.UniqueProcess = PsGetCurrentProcessId(); - MessageReply->Message.ClientId.UniqueThread = PsGetCurrentThreadId(); - MessageReply->Message.u2.s2.Type = (CSHORT)MessageType; - MessageReply->Message.MessageId = InterlockedIncrementUL(&LpcpNextMessageId); - - KeAcquireSpinLock(&Port->Lock, &oldIrql); - EiEnqueueMessagePort(Port, MessageReply); - KeReleaseSpinLock(&Port->Lock, oldIrql); - - return(STATUS_SUCCESS); + /* Go to the next entry */ + NextEntry = NextEntry->Flink; + } } - -/********************************************************************** - * NAME EXPORTED - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - */ -NTSTATUS STDCALL -NtReplyPort (IN HANDLE PortHandle, - IN PPORT_MESSAGE LpcReply) +VOID +NTAPI +LpcpSaveDataInfoMessage(IN PLPCP_PORT_OBJECT Port, + IN PLPCP_MESSAGE Message) { - NTSTATUS Status; - PEPORT Port; + PAGED_CODE(); - DPRINT("NtReplyPort(PortHandle %x, LpcReply %x)\n", PortHandle, LpcReply); + /* Acquire the lock */ + KeAcquireGuardedMutex(&LpcpLock); - Status = ObReferenceObjectByHandle(PortHandle, - PORT_ALL_ACCESS, /* AccessRequired */ - LpcPortObjectType, - UserMode, - (PVOID*)&Port, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("NtReplyPort() = %x\n", Status); - return(Status); - } + /* Check if the port we want is the connection port */ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) > LPCP_UNCONNECTED_PORT) + { + /* Use it */ + Port = Port->ConnectionPort; + } - if (EPORT_DISCONNECTED == Port->State) - { - ObDereferenceObject(Port); - return STATUS_PORT_DISCONNECTED; - } + /* Link the message */ + InsertTailList(&Port->LpcDataInfoChainHead, &Message->Entry); - Status = EiReplyOrRequestPort(Port->OtherPort, - LpcReply, - LPC_REPLY, - Port); - KeReleaseSemaphore(&Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, FALSE); - - ObDereferenceObject(Port); - - return(Status); + /* Release the lock */ + KeReleaseGuardedMutex(&LpcpLock); } - -/********************************************************************** - * NAME EXPORTED - * NtReplyWaitReceivePortEx - * - * DESCRIPTION - * Can be used with waitable ports. - * Present only in w2k+. - * - * ARGUMENTS - * PortHandle - * PortId - * LpcReply - * LpcMessage - * Timeout - * - * RETURN VALUE - * - * REVISIONS - */ -NTSTATUS STDCALL -NtReplyWaitReceivePortEx(IN HANDLE PortHandle, - OUT PVOID *PortContext OPTIONAL, - IN PPORT_MESSAGE ReplyMessage OPTIONAL, - OUT PPORT_MESSAGE ReceiveMessage, - IN PLARGE_INTEGER Timeout OPTIONAL) +VOID +NTAPI +LpcpMoveMessage(IN PPORT_MESSAGE Destination, + IN PPORT_MESSAGE Origin, + IN PVOID Data, + IN ULONG MessageType, + IN PCLIENT_ID ClientId) { - PEPORT Port; - KIRQL oldIrql; - PQUEUEDMESSAGE Request; - BOOLEAN Disconnected; - LARGE_INTEGER to; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - PreviousMode = ExGetPreviousMode(); + /* Set the Message size */ + LPCTRACE((LPC_REPLY_DEBUG | LPC_SEND_DEBUG), + "Destination/Origin: %p/%p. Data: %p. Length: %lx\n", + Destination, + Origin, + Data, + Origin->u1.Length); + Destination->u1.Length = Origin->u1.Length; - DPRINT("NtReplyWaitReceivePortEx(PortHandle %x, LpcReply %x, " - "LpcMessage %x)\n", PortHandle, ReplyMessage, ReceiveMessage); + /* Set the Message Type */ + Destination->u2.s2.Type = !MessageType ? + Origin->u2.s2.Type : MessageType & 0xFFFF; - if (PreviousMode != KernelMode) - { - _SEH_TRY - { - ProbeForWrite(ReceiveMessage, - sizeof(PORT_MESSAGE), - 1); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - return Status; - } - } + /* Check if we have a Client ID */ + if (ClientId) + { + /* Set the Client ID */ + Destination->ClientId.UniqueProcess = ClientId->UniqueProcess; + Destination->ClientId.UniqueThread = ClientId->UniqueThread; + } + else + { + /* Otherwise, copy it */ + Destination->ClientId.UniqueProcess = Origin->ClientId.UniqueProcess; + Destination->ClientId.UniqueThread = Origin->ClientId.UniqueThread; + } - Status = ObReferenceObjectByHandle(PortHandle, - PORT_ALL_ACCESS, - LpcPortObjectType, - UserMode, - (PVOID*)&Port, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status); - return(Status); - } - if( Port->State == EPORT_DISCONNECTED ) - { - /* If the port is disconnected, force the timeout to be 0 - * so we don't wait for new messages, because there won't be - * any, only try to remove any existing messages - */ - Disconnected = TRUE; - to.QuadPart = 0; - Timeout = &to; - } - else Disconnected = FALSE; + /* Copy the MessageId and ClientViewSize */ + Destination->MessageId = Origin->MessageId; + Destination->ClientViewSize = Origin->ClientViewSize; - /* - * Send the reply, only if port is connected - */ - if (ReplyMessage != NULL && !Disconnected) - { - Status = EiReplyOrRequestPort(Port->OtherPort, - ReplyMessage, - LPC_REPLY, - Port); - KeReleaseSemaphore(&Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, - FALSE); - - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(Port); - DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status); - return(Status); - } - } - - /* - * Want for a message to be received - */ - Status = KeWaitForSingleObject(&Port->Semaphore, - UserRequest, - UserMode, - FALSE, - Timeout); - if( Status == STATUS_TIMEOUT ) - { - /* - * if the port is disconnected, and there are no remaining messages, - * return STATUS_PORT_DISCONNECTED - */ - ObDereferenceObject(Port); - return(Disconnected ? STATUS_PORT_DISCONNECTED : STATUS_TIMEOUT); - } - - if (!NT_SUCCESS(Status)) - { - if (STATUS_THREAD_IS_TERMINATING != Status) - { - DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status); - } - ObDereferenceObject(Port); - return(Status); - } - - /* - * Dequeue the message - */ - KeAcquireSpinLock(&Port->Lock, &oldIrql); - Request = EiDequeueMessagePort(Port); - KeReleaseSpinLock(&Port->Lock, oldIrql); - - if (Request == NULL) - { - ObDereferenceObject(Port); - return STATUS_UNSUCCESSFUL; - } - - if (Request->Message.u2.s2.Type == LPC_CONNECTION_REQUEST) - { - PORT_MESSAGE Header; - PEPORT_CONNECT_REQUEST_MESSAGE CRequest; - - CRequest = (PEPORT_CONNECT_REQUEST_MESSAGE)&Request->Message; - memcpy(&Header, &Request->Message, sizeof(PORT_MESSAGE)); - Header.u1.s1.DataLength = (CSHORT)CRequest->ConnectDataLength; - Header.u1.s1.TotalLength = Header.u1.s1.DataLength + sizeof(PORT_MESSAGE); - - if (PreviousMode != KernelMode) - { - _SEH_TRY - { - ProbeForWrite((PVOID)(ReceiveMessage + 1), - CRequest->ConnectDataLength, - 1); - - RtlCopyMemory(ReceiveMessage, - &Header, - sizeof(PORT_MESSAGE)); - RtlCopyMemory((PVOID)(ReceiveMessage + 1), - CRequest->ConnectData, - CRequest->ConnectDataLength); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - else - { - RtlCopyMemory(ReceiveMessage, - &Header, - sizeof(PORT_MESSAGE)); - RtlCopyMemory((PVOID)(ReceiveMessage + 1), - CRequest->ConnectData, - CRequest->ConnectDataLength); - } - } - else - { - if (PreviousMode != KernelMode) - { - _SEH_TRY - { - ProbeForWrite(ReceiveMessage, - Request->Message.u1.s1.TotalLength, - 1); - - RtlCopyMemory(ReceiveMessage, - &Request->Message, - Request->Message.u1.s1.TotalLength); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - else - { - RtlCopyMemory(ReceiveMessage, - &Request->Message, - Request->Message.u1.s1.TotalLength); - } - } - if (!NT_SUCCESS(Status)) - { - /* - * Copying the message to the caller's buffer failed so - * undo what we did and return. - * FIXME: Also increment semaphore. - */ - KeAcquireSpinLock(&Port->Lock, &oldIrql); - EiEnqueueMessageAtHeadPort(Port, Request); - KeReleaseSpinLock(&Port->Lock, oldIrql); - ObDereferenceObject(Port); - return(Status); - } - if (Request->Message.u2.s2.Type == LPC_CONNECTION_REQUEST) - { - KeAcquireSpinLock(&Port->Lock, &oldIrql); - EiEnqueueConnectMessagePort(Port, Request); - KeReleaseSpinLock(&Port->Lock, oldIrql); - } - else - { - ExFreePool(Request); - } - - /* - * Dereference the port - */ - ObDereferenceObject(Port); - return(STATUS_SUCCESS); + /* Copy the Message Data */ + RtlMoveMemory(Destination + 1, + Data, + ((Destination->u1.Length & 0xFFFF) + 3) &~3); } +/* PUBLIC FUNCTIONS **********************************************************/ -/********************************************************************** - * NAME EXPORTED - * NtReplyWaitReceivePort - * - * DESCRIPTION - * Can be used with waitable ports. - * - * ARGUMENTS - * PortHandle - * PortId - * LpcReply - * LpcMessage - * - * RETURN VALUE - * - * REVISIONS +/* + * @unimplemented */ -NTSTATUS STDCALL -NtReplyWaitReceivePort(IN HANDLE PortHandle, - OUT PVOID *PortContext OPTIONAL, - IN PPORT_MESSAGE ReplyMessage OPTIONAL, - OUT PPORT_MESSAGE ReceiveMessage) +NTSTATUS +NTAPI +NtReplyPort(IN HANDLE PortHandle, + IN PPORT_MESSAGE LpcReply) { - return NtReplyWaitReceivePortEx(PortHandle, - PortContext, - ReplyMessage, - ReceiveMessage, - NULL); -} - -/********************************************************************** - * NAME - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - */ -NTSTATUS STDCALL -NtReplyWaitReplyPort (HANDLE PortHandle, - PPORT_MESSAGE ReplyMessage) -{ - UNIMPLEMENTED; - return(STATUS_NOT_IMPLEMENTED); + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; } /* @@ -423,36 +143,349 @@ NtReplyWaitReplyPort (HANDLE PortHandle, */ NTSTATUS NTAPI -LpcRequestWaitReplyPort(IN PVOID Port, - IN PPORT_MESSAGE LpcMessageRequest, - OUT PPORT_MESSAGE LpcMessageReply) +NtReplyWaitReceivePortEx(IN HANDLE PortHandle, + OUT PVOID *PortContext OPTIONAL, + IN PPORT_MESSAGE ReplyMessage OPTIONAL, + OUT PPORT_MESSAGE ReceiveMessage, + IN PLARGE_INTEGER Timeout OPTIONAL) { - HANDLE PortHandle; + PLPCP_PORT_OBJECT Port, ReceivePort; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(), WaitMode = PreviousMode; NTSTATUS Status; - UNICODE_STRING PortName; - ULONG ConnectInfoLength; + PLPCP_MESSAGE Message; + PETHREAD Thread = PsGetCurrentThread(), WakeupThread; + PLPCP_CONNECTION_MESSAGE ConnectMessage; + ULONG ConnectionInfoLength; + PAGED_CODE(); + LPCTRACE(LPC_REPLY_DEBUG, + "Handle: %lx. Messages: %p/%p. Context: %p\n", + PortHandle, + ReplyMessage, + ReceiveMessage, + PortContext); - // - // OMG HAXX! - // - RtlInitUnicodeString(&PortName, L"\\Windows\\ApiPort"); - ConnectInfoLength = 0; - Status = ZwConnectPort(&PortHandle, - &PortName, - NULL, - NULL, - NULL, - NULL, - NULL, - &ConnectInfoLength); + /* If this is a system thread, then let it page out its stack */ + if (Thread->SystemThread) WaitMode = UserMode; - Status = ZwRequestWaitReplyPort(PortHandle, - LpcMessageRequest, - LpcMessageReply); + /* Check if caller has a reply message */ + if (ReplyMessage) + { + /* Validate its length */ + if ((ReplyMessage->u1.s1.DataLength + sizeof(PORT_MESSAGE)) > + ReplyMessage->u1.s1.TotalLength) + { + /* Fail */ + return STATUS_INVALID_PARAMETER; + } - /* Close the handle */ - ObCloseHandle(PortHandle, KernelMode); + /* Make sure it has a valid ID */ + if (!ReplyMessage->MessageId) return STATUS_INVALID_PARAMETER; + } + + /* Get the Port object */ + Status = ObReferenceObjectByHandle(PortHandle, + 0, + LpcPortObjectType, + PreviousMode, + (PVOID*)&Port, + NULL); + if (!NT_SUCCESS(Status)) return Status; + + /* Check if the caller has a reply message */ + if (ReplyMessage) + { + /* Validate its length in respect to the port object */ + if ((ReplyMessage->u1.s1.TotalLength > Port->MaxMessageLength) || + (ReplyMessage->u1.s1.TotalLength <= ReplyMessage->u1.s1.DataLength)) + { + /* Too large, fail */ + ObDereferenceObject(Port); + return STATUS_PORT_MESSAGE_TOO_LONG; + } + } + + /* Check if this is anything but a client port */ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CLIENT_PORT) + { + /* Use the connection port */ + ReceivePort = Port->ConnectionPort; + } + else + { + /* Otherwise, use the port itself */ + ReceivePort = Port; + } + + /* Check if the caller gave a reply message */ + if (ReplyMessage) + { + /* Get the ETHREAD corresponding to it */ + Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId, + NULL, + &WakeupThread); + if (!NT_SUCCESS(Status)) + { + /* No thread found, fail */ + ObDereferenceObject(Port); + return Status; + } + + /* Allocate a message from the port zone */ + Message = LpcpAllocateFromPortZone(); + if (!Message) + { + /* Fail if we couldn't allocate a message */ + ObDereferenceObject(WakeupThread); + ObDereferenceObject(Port); + return STATUS_NO_MEMORY; + } + + /* Keep the lock acquired */ + KeAcquireGuardedMutex(&LpcpLock); + + /* Make sure this is the reply the thread is waiting for */ + if (WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId) + { + /* It isn't, fail */ + LpcpFreeToPortZone(Message, TRUE); + KeReleaseGuardedMutex(&LpcpLock); + ObDereferenceObject(WakeupThread); + ObDereferenceObject(Port); + return STATUS_REPLY_MESSAGE_MISMATCH; + } + + /* Copy the message */ + LpcpMoveMessage(&Message->Request, + ReplyMessage, + ReplyMessage + 1, + LPC_REPLY, + NULL); + + /* Free any data information */ + LpcpFreeDataInfoMessage(Port, + ReplyMessage->MessageId, + ReplyMessage->CallbackId); + + /* Reference the thread while we use it */ + ObReferenceObject(WakeupThread); + Message->RepliedToThread = WakeupThread; + + /* Set this as the reply message */ + WakeupThread->LpcReplyMessageId = 0; + WakeupThread->LpcReplyMessage = (PVOID)Message; + + /* Check if we have messages on the reply chain */ + if (!(WakeupThread->LpcExitThreadCalled) && + !(IsListEmpty(&WakeupThread->LpcReplyChain))) + { + /* Remove us from it and reinitialize it */ + RemoveEntryList(&WakeupThread->LpcReplyChain); + InitializeListHead(&WakeupThread->LpcReplyChain); + } + + /* Check if this is the message the thread had received */ + if ((Thread->LpcReceivedMsgIdValid) && + (Thread->LpcReceivedMessageId == ReplyMessage->MessageId)) + { + /* Clear this data */ + Thread->LpcReceivedMessageId = 0; + Thread->LpcReceivedMsgIdValid = FALSE; + } + + /* Release the lock and release the LPC semaphore to wake up waiters */ + KeReleaseGuardedMutex(&LpcpLock); + LpcpCompleteWait(&WakeupThread->LpcReplySemaphore); + + /* Now we can let go of the thread */ + ObDereferenceObject(WakeupThread); + } + + /* Now wait for someone to reply to us */ + LpcpReceiveWait(ReceivePort->MsgQueue.Semaphore, WaitMode); + if (Status != STATUS_SUCCESS) goto Cleanup; + + /* Wait done, get the LPC lock */ + KeAcquireGuardedMutex(&LpcpLock); + + /* Check if we've received nothing */ + if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead)) + { + /* Check if this was a waitable port and wake it */ + if (ReceivePort->Flags & LPCP_WAITABLE_PORT) + { + /* Reset its event */ + KeResetEvent(&ReceivePort->WaitEvent); + } + + /* Release the lock and fail */ + KeReleaseGuardedMutex(&LpcpLock); + ObDereferenceObject(Port); + return STATUS_UNSUCCESSFUL; + } + + /* Get the message on the queue */ + Message = CONTAINING_RECORD(RemoveHeadList(&ReceivePort-> + MsgQueue.ReceiveHead), + LPCP_MESSAGE, + Entry); + + /* Check if the queue is empty now */ + if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead)) + { + /* Check if this was a waitable port */ + if (ReceivePort->Flags & LPCP_WAITABLE_PORT) + { + /* Reset its event */ + KeResetEvent(&ReceivePort->WaitEvent); + } + } + + /* Re-initialize the message's list entry */ + InitializeListHead(&Message->Entry); + + /* Set this as the received message */ + Thread->LpcReceivedMessageId = Message->Request.MessageId; + Thread->LpcReceivedMsgIdValid = TRUE; + + /* Done touching global data, release the lock */ + KeReleaseGuardedMutex(&LpcpLock); + + /* Check if this was a connection request */ + if (LpcpGetMessageType(&Message->Request) == LPC_CONNECTION_REQUEST) + { + /* Get the connection message */ + ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); + LPCTRACE(LPC_REPLY_DEBUG, + "Request Messages: %p/%p\n", + Message, + ConnectMessage); + + /* Get its length */ + ConnectionInfoLength = Message->Request.u1.s1.DataLength - + sizeof(LPCP_CONNECTION_MESSAGE); + + /* Return it as the receive message */ + *ReceiveMessage = Message->Request; + + /* Clear our stack variable so the message doesn't get freed */ + Message = NULL; + + /* Setup the receive message */ + ReceiveMessage->u1.s1.TotalLength = sizeof(LPCP_MESSAGE) + + ConnectionInfoLength; + ReceiveMessage->u1.s1.DataLength = ConnectionInfoLength; + RtlMoveMemory(ReceiveMessage + 1, + ConnectMessage + 1, + ConnectionInfoLength); + + /* Clear the port context if the caller requested one */ + if (PortContext) *PortContext = NULL; + } + else if (Message->Request.u2.s2.Type != LPC_REPLY) + { + /* Otherwise, this is a new message or event */ + LPCTRACE(LPC_REPLY_DEBUG, + "Non-Reply Messages: %p/%p\n", + &Message->Request, + (&Message->Request) + 1); + + /* Copy it */ + LpcpMoveMessage(ReceiveMessage, + &Message->Request, + (&Message->Request) + 1, + 0, + NULL); + + /* Return its context */ + if (PortContext) *PortContext = Message->PortContext; + + /* And check if it has data information */ + if (Message->Request.u2.s2.DataInfoOffset) + { + /* It does, save it, and don't free the message below */ + LpcpSaveDataInfoMessage(Port, Message); + Message = NULL; + } + } + else + { + /* This is a reply message, should never happen! */ + ASSERT(FALSE); + } + + /* If we have a message pointer here, free it */ + if (Message) LpcpFreeToPortZone(Message, FALSE); + +Cleanup: + /* All done, dereference the port and return the status */ + LPCTRACE(LPC_REPLY_DEBUG, + "Port: %p. Status: %p\n", + Port, + Status); + ObDereferenceObject(Port); return Status; } +/* + * @implemented + */ +NTSTATUS +NTAPI +NtReplyWaitReceivePort(IN HANDLE PortHandle, + OUT PVOID *PortContext OPTIONAL, + IN PPORT_MESSAGE ReplyMessage OPTIONAL, + OUT PPORT_MESSAGE ReceiveMessage) +{ + /* Call the newer API */ + return NtReplyWaitReceivePortEx(PortHandle, + PortContext, + ReplyMessage, + ReceiveMessage, + NULL); +} + +/* + * @unimplemented + */ +NTSTATUS +NTAPI +NtReplyWaitReplyPort(IN HANDLE PortHandle, + IN PPORT_MESSAGE ReplyMessage) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +/* + * @unimplemented + */ +NTSTATUS +NTAPI +NtReadRequestData(IN HANDLE PortHandle, + IN PPORT_MESSAGE Message, + IN ULONG Index, + IN PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG Returnlength) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +/* + * @unimplemented + */ +NTSTATUS +NTAPI +NtWriteRequestData(IN HANDLE PortHandle, + IN PPORT_MESSAGE Message, + IN ULONG Index, + IN PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnLength) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + /* EOF */ diff --git a/reactos/ntoskrnl/lpc/send.c b/reactos/ntoskrnl/lpc/send.c index 1dc522f7e66..f49e0a6550f 100644 --- a/reactos/ntoskrnl/lpc/send.c +++ b/reactos/ntoskrnl/lpc/send.c @@ -1,395 +1,426 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/lpc/send.c - * PURPOSE: Communication mechanism - * - * PROGRAMMERS: David Welch (welch@cwcom.net) + * PURPOSE: Local Procedure Call: Sending (Requests) + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ -/* INCLUDES *****************************************************************/ +/* INCLUDES ******************************************************************/ #include - +#include "lpc.h" #define NDEBUG #include -/********************************************************************** - * NAME - * LpcRequestPort/2 - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - * 2002-03-01 EA - * I investigated this function a bit more in depth. - * It looks like the legal values for the MessageType field in the - * message to send are in the range LPC_NEW_MESSAGE .. LPC_CLIENT_DIED, - * but LPC_DATAGRAM is explicitly forbidden. - * +/* PUBLIC FUNCTIONS **********************************************************/ + +/* * @implemented */ -NTSTATUS STDCALL LpcRequestPort (IN PVOID PortObject, - IN PPORT_MESSAGE LpcMessage) +NTSTATUS +NTAPI +LpcRequestPort(IN PVOID PortObject, + IN PPORT_MESSAGE LpcMessage) { - NTSTATUS Status; - PEPORT Port = (PEPORT)PortObject; + PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)PortObject, QueuePort; + ULONG MessageType; + PLPCP_MESSAGE Message; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); + PAGED_CODE(); + LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", Port, LpcMessage); - DPRINT("LpcRequestPort(PortHandle %08x, LpcMessage %08x)\n", Port, LpcMessage); + /* Check if this is a non-datagram message */ + if (LpcMessage->u2.s2.Type) + { + /* Get the message type */ + MessageType = LpcpGetMessageType(LpcMessage); -#ifdef __USE_NT_LPC__ - /* Check the message's type */ - if (LPC_NEW_MESSAGE == LpcMessage->u2.s2.Type) - { - LpcMessage->u2.s2.Type = LPC_DATAGRAM; - } - else if (LPC_DATAGRAM == LpcMessage->u2.s2.Type) - { - return STATUS_INVALID_PARAMETER; - } - else if (LpcMessage->u2.s2.Type > LPC_CLIENT_DIED) - { - return STATUS_INVALID_PARAMETER; - } - /* Check the range offset */ - if (0 != LpcMessage->VirtualRangesOffset) - { - return STATUS_INVALID_PARAMETER; - } -#endif + /* Validate it */ + if ((MessageType < LPC_DATAGRAM) || (MessageType > LPC_CLIENT_DIED)) + { + /* Fail */ + return STATUS_INVALID_PARAMETER; + } - Status = EiReplyOrRequestPort(Port, - LpcMessage, - LPC_DATAGRAM, - Port); - KeReleaseSemaphore( &Port->Semaphore, IO_NO_INCREMENT, 1, FALSE ); + /* Mark this as a kernel-mode message only if we really came from there */ + if ((PreviousMode == KernelMode) && + (LpcMessage->u2.s2.Type & LPC_KERNELMODE_MESSAGE)) + { + /* We did, this is a kernel mode message */ + MessageType |= LPC_KERNELMODE_MESSAGE; + } + } + else + { + /* This is a datagram */ + MessageType = LPC_DATAGRAM; + } - return(Status); + /* Can't have data information on this type of call */ + if (LpcMessage->u2.s2.DataInfoOffset) return STATUS_INVALID_PARAMETER; + + /* Validate message sizes */ + if ((LpcMessage->u1.s1.TotalLength > Port->MaxMessageLength) || + (LpcMessage->u1.s1.TotalLength <= LpcMessage->u1.s1.DataLength)) + { + /* Fail */ + return STATUS_PORT_MESSAGE_TOO_LONG; + } + + /* Allocate a new message */ + Message = LpcpAllocateFromPortZone(); + if (!Message) return STATUS_NO_MEMORY; + + /* Clear the context */ + Message->PortContext = NULL; + + /* Copy the message */ + LpcpMoveMessage(&Message->Request, + LpcMessage, + LpcMessage + 1, + MessageType, + &PsGetCurrentThread()->Cid); + + /* Acquire the LPC lock */ + KeAcquireGuardedMutex(&LpcpLock); + + /* Check if this is anything but a connection port */ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT) + { + /* The queue port is the connected port */ + QueuePort = Port->ConnectedPort; + if (QueuePort) + { + /* Check if this is a client port */ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT) + { + /* Then copy the context */ + Message->PortContext = QueuePort->PortContext; + QueuePort = Port->ConnectionPort; + } + else if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_COMMUNICATION_PORT) + { + /* Any other kind of port, use the connection port */ + QueuePort = Port->ConnectionPort; + } + } + } + else + { + /* For connection ports, use the port itself */ + QueuePort = PortObject; + } + + /* Make sure we have a port */ + if (QueuePort) + { + /* Generate the Message ID and set it */ + Message->Request.MessageId = LpcpNextMessageId++; + if (!LpcpNextMessageId) LpcpNextMessageId = 1; + Message->Request.CallbackId = 0; + + /* No Message ID for the thread */ + PsGetCurrentThread()->LpcReplyMessageId = 0; + + /* Insert the message in our chain */ + InsertTailList(&QueuePort->MsgQueue.ReceiveHead, &Message->Entry); + + /* Release the lock and release the semaphore */ + KeReleaseGuardedMutex(&LpcpLock); + LpcpCompleteWait(QueuePort->MsgQueue.Semaphore); + + /* If this is a waitable port, wake it up */ + if (QueuePort->Flags & LPCP_WAITABLE_PORT) + { + /* Wake it */ + KeSetEvent(&QueuePort->WaitEvent, IO_NO_INCREMENT, FALSE); + } + + /* We're done */ + LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", QueuePort, Message); + return STATUS_SUCCESS; + } + + /* If we got here, then free the message and fail */ + LpcpFreeToPortZone(Message, TRUE); + KeReleaseGuardedMutex(&LpcpLock); + return STATUS_PORT_DISCONNECTED; } +/* +* @unimplemented +*/ +NTSTATUS +NTAPI +LpcRequestWaitReplyPort(IN PVOID Port, + IN PPORT_MESSAGE LpcMessageRequest, + OUT PPORT_MESSAGE LpcMessageReply) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} -/********************************************************************** - * NAME - * NtRequestPort/2 - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - * +/* + * @unimplemented + */ +NTSTATUS +NTAPI +NtRequestPort(IN HANDLE PortHandle, + IN PPORT_MESSAGE LpcMessage) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +/* * @implemented */ -NTSTATUS STDCALL NtRequestPort (IN HANDLE PortHandle, - IN PPORT_MESSAGE LpcMessage) +NTSTATUS +NTAPI +NtRequestWaitReplyPort(IN HANDLE PortHandle, + IN PPORT_MESSAGE LpcRequest, + IN OUT PPORT_MESSAGE LpcReply) { - NTSTATUS Status; - PEPORT Port; + PLPCP_PORT_OBJECT Port, QueuePort, ReplyPort; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); + NTSTATUS Status; + PLPCP_MESSAGE Message; + PETHREAD Thread = PsGetCurrentThread(); + BOOLEAN Callback; + PKSEMAPHORE Semaphore; + ULONG MessageType; + PAGED_CODE(); + LPCTRACE(LPC_SEND_DEBUG, + "Handle: %lx. Messages: %p/%p. Type: %lx\n", + PortHandle, + LpcRequest, + LpcReply, + LpcpGetMessageType(LpcRequest)); - DPRINT("NtRequestPort(PortHandle %x LpcMessage %x)\n", PortHandle, - LpcMessage); + /* Check if the thread is dying */ + if (Thread->LpcExitThreadCalled) return STATUS_THREAD_IS_TERMINATING; - Status = ObReferenceObjectByHandle(PortHandle, - PORT_ALL_ACCESS, - LpcPortObjectType, - UserMode, - (PVOID*)&Port, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("NtRequestPort() = %x\n", Status); - return(Status); - } + /* Check if this is an LPC Request */ + if (LpcpGetMessageType(LpcRequest) == LPC_REQUEST) + { + /* Then it's a callback */ + Callback = TRUE; + } + else if (LpcpGetMessageType(LpcRequest)) + { + /* This is a not kernel-mode message */ + return STATUS_INVALID_PARAMETER; + } + else + { + /* This is a kernel-mode message without a callback */ + LpcRequest->u2.s2.Type |= LPC_REQUEST; + Callback = FALSE; + } - Status = LpcRequestPort(Port->OtherPort, - LpcMessage); + /* Get the message type */ + MessageType = LpcRequest->u2.s2.Type; - ObDereferenceObject(Port); - return(Status); + /* Validate the length */ + if ((LpcRequest->u1.s1.DataLength + sizeof(PORT_MESSAGE)) > + LpcRequest->u1.s1.TotalLength) + { + /* Fail */ + return STATUS_INVALID_PARAMETER; + } + + /* Reference the object */ + Status = ObReferenceObjectByHandle(PortHandle, + 0, + LpcPortObjectType, + PreviousMode, + (PVOID*)&Port, + NULL); + if (!NT_SUCCESS(Status)) return Status; + + /* Validate the message length */ + if ((LpcRequest->u1.s1.TotalLength > Port->MaxMessageLength) || + (LpcRequest->u1.s1.TotalLength <= LpcRequest->u1.s1.DataLength)) + { + /* Fail */ + ObDereferenceObject(Port); + return STATUS_PORT_MESSAGE_TOO_LONG; + } + + /* Allocate a message from the port zone */ + Message = LpcpAllocateFromPortZone(); + if (!Message) + { + /* Fail if we couldn't allocate a message */ + ObDereferenceObject(Port); + return STATUS_NO_MEMORY; + } + + /* Check if this is a callback */ + if (Callback) + { + /* FIXME: TODO */ + Semaphore = NULL; // we'd use the Thread Semaphore here + ASSERT(FALSE); + } + else + { + /* No callback, just copy the message */ + LpcpMoveMessage(&Message->Request, + LpcRequest, + LpcRequest + 1, + MessageType, + &Thread->Cid); + + /* Acquire the LPC lock */ + KeAcquireGuardedMutex(&LpcpLock); + + /* Right now clear the port context */ + Message->PortContext = NULL; + + /* Check if this is a not connection port */ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT) + { + /* We want the connected port */ + QueuePort = Port->ConnectedPort; + if (!QueuePort) + { + /* We have no connected port, fail */ + LpcpFreeToPortZone(Message, TRUE); + KeReleaseGuardedMutex(&LpcpLock); + ObDereferenceObject(Port); + return STATUS_PORT_DISCONNECTED; + } + + /* This will be the rundown port */ + ReplyPort = QueuePort; + + /* Check if this is a communication port */ + if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT) + { + /* Copy the port context and use the connection port */ + Message->PortContext = ReplyPort->PortContext; + QueuePort = Port->ConnectionPort; + } + else if ((Port->Flags & LPCP_PORT_TYPE_MASK) != + LPCP_COMMUNICATION_PORT) + { + /* Use the connection port for anything but communication ports */ + QueuePort = Port->ConnectionPort; + } + } + else + { + /* Otherwise, for a connection port, use the same port object */ + QueuePort = ReplyPort = Port; + } + + /* No reply thread */ + Message->RepliedToThread = NULL; + + /* Generate the Message ID and set it */ + Message->Request.MessageId = LpcpNextMessageId++; + if (!LpcpNextMessageId) LpcpNextMessageId = 1; + Message->Request.CallbackId = 0; + + /* Set the message ID for our thread now */ + Thread->LpcReplyMessageId = Message->Request.MessageId; + Thread->LpcReplyMessage = NULL; + + /* Insert the message in our chain */ + InsertTailList(&QueuePort->MsgQueue.ReceiveHead, &Message->Entry); + InsertTailList(&ReplyPort->LpcReplyChainHead, &Thread->LpcReplyChain); + + /* Release the lock and get the semaphore we'll use later */ + KeReleaseGuardedMutex(&LpcpLock); + Semaphore = QueuePort->MsgQueue.Semaphore; + + /* If this is a waitable port, wake it up */ + if (QueuePort->Flags & LPCP_WAITABLE_PORT) + { + /* Wake it */ + KeSetEvent(&QueuePort->WaitEvent, IO_NO_INCREMENT, FALSE); + } + } + + /* Now release the semaphore */ + LpcpCompleteWait(Semaphore); + + /* And let's wait for the reply */ + LpcpReplyWait(&Thread->LpcReplySemaphore, PreviousMode); + + /* Acquire the LPC lock */ + KeAcquireGuardedMutex(&LpcpLock); + + /* Get the LPC Message and clear our thread's reply data */ + Message = Thread->LpcReplyMessage; + Thread->LpcReplyMessage = NULL; + Thread->LpcReplyMessageId = 0; + + /* Check if we have anything on the reply chain*/ + if (!IsListEmpty(&Thread->LpcReplyChain)) + { + /* Remove this thread and reinitialize the list */ + RemoveEntryList(&Thread->LpcReplyChain); + InitializeListHead(&Thread->LpcReplyChain); + } + + /* Release the lock */ + KeReleaseGuardedMutex(&LpcpLock); + + /* Check if we got a reply */ + if (Status == STATUS_SUCCESS) + { + /* Check if we have a valid message */ + if (Message) + { + LPCTRACE(LPC_SEND_DEBUG, + "Reply Messages: %p/%p\n", + &Message->Request, + (&Message->Request) + 1); + + /* Move the message */ + LpcpMoveMessage(LpcReply, + &Message->Request, + (&Message->Request) + 1, + 0, + NULL); + + /* Check if this is an LPC request with data information */ + if ((LpcpGetMessageType(&Message->Request) == LPC_REQUEST) && + (Message->Request.u2.s2.DataInfoOffset)) + { + /* Save the data information */ + LpcpSaveDataInfoMessage(Port, Message); + } + else + { + /* Otherwise, just free it */ + LpcpFreeToPortZone(Message, FALSE); + } + } + else + { + /* We don't have a reply */ + Status = STATUS_LPC_REPLY_LOST; + } + } + else + { + /* The wait failed, free the message while holding the lock */ + KeAcquireGuardedMutex(&LpcpLock); + LpcpFreeToPortZone(Message, TRUE); + KeReleaseGuardedMutex(&LpcpLock); + } + + /* All done */ + LPCTRACE(LPC_SEND_DEBUG, + "Port: %p. Status: %p\n", + Port, + Status); + ObDereferenceObject(Port); + return Status; } - -/********************************************************************** - * NAME - * NtRequestWaitReplyPort/3 - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - * - * @implemented - */ -NTSTATUS STDCALL -NtRequestWaitReplyPort (IN HANDLE PortHandle, - PPORT_MESSAGE UnsafeLpcRequest, - PPORT_MESSAGE UnsafeLpcReply) -{ - PETHREAD CurrentThread; - struct _KPROCESS *AttachedProcess; - PEPORT Port; - PQUEUEDMESSAGE Message; - KIRQL oldIrql; - PPORT_MESSAGE LpcRequest; - USHORT LpcRequestMessageSize = 0, LpcRequestDataSize = 0; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - PreviousMode = ExGetPreviousMode(); - - if (PreviousMode != KernelMode) - { - _SEH_TRY - { - ProbeForRead(UnsafeLpcRequest, - sizeof(PORT_MESSAGE), - 1); - ProbeForWrite(UnsafeLpcReply, - sizeof(PORT_MESSAGE), - 1); - LpcRequestMessageSize = UnsafeLpcRequest->u1.s1.TotalLength; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - return Status; - } - } - else - { - LpcRequestMessageSize = UnsafeLpcRequest->u1.s1.TotalLength; - } - - DPRINT("NtRequestWaitReplyPort(PortHandle %x, LpcRequest %x, " - "LpcReply %x)\n", PortHandle, UnsafeLpcRequest, UnsafeLpcReply); - - Status = ObReferenceObjectByHandle(PortHandle, - PORT_ALL_ACCESS, - LpcPortObjectType, - UserMode, - (PVOID*)&Port, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - if (EPORT_DISCONNECTED == Port->State) - { - ObDereferenceObject(Port); - return STATUS_PORT_DISCONNECTED; - } - - /* win32k sometimes needs to KeAttach() the CSRSS process in order to make - the PortHandle valid. Now that we've got the EPORT structure from the - handle we can undo this, so everything is normal again. Need to - re-KeAttach() before returning though */ - CurrentThread = PsGetCurrentThread(); - if (&CurrentThread->ThreadsProcess->Pcb == CurrentThread->Tcb.ApcState.Process) - { - AttachedProcess = NULL; - } - else - { - AttachedProcess = CurrentThread->Tcb.ApcState.Process; - KeDetachProcess(); - } - - if (LpcRequestMessageSize > LPC_MAX_MESSAGE_LENGTH) - { - if (NULL != AttachedProcess) - { - KeAttachProcess(AttachedProcess); - } - ObDereferenceObject(Port); - return(STATUS_PORT_MESSAGE_TOO_LONG); - } - LpcRequest = ExAllocatePool(NonPagedPool, LpcRequestMessageSize); - if (LpcRequest == NULL) - { - if (NULL != AttachedProcess) - { - KeAttachProcess(AttachedProcess); - } - ObDereferenceObject(Port); - return(STATUS_NO_MEMORY); - } - if (PreviousMode != KernelMode) - { - _SEH_TRY - { - RtlCopyMemory(LpcRequest, - UnsafeLpcRequest, - LpcRequestMessageSize); - LpcRequestMessageSize = LpcRequest->u1.s1.TotalLength; - LpcRequestDataSize = LpcRequest->u1.s1.DataLength; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - ExFreePool(LpcRequest); - if (NULL != AttachedProcess) - { - KeAttachProcess(AttachedProcess); - } - ObDereferenceObject(Port); - return(Status); - } - } - else - { - RtlCopyMemory(LpcRequest, - UnsafeLpcRequest, - LpcRequestMessageSize); - LpcRequestMessageSize = LpcRequest->u1.s1.TotalLength; - LpcRequestDataSize = LpcRequest->u1.s1.DataLength; - } - - if (LpcRequestMessageSize > LPC_MAX_MESSAGE_LENGTH) - { - ExFreePool(LpcRequest); - if (NULL != AttachedProcess) - { - KeAttachProcess(AttachedProcess); - } - ObDereferenceObject(Port); - return(STATUS_PORT_MESSAGE_TOO_LONG); - } - if (LpcRequestDataSize > LPC_MAX_DATA_LENGTH) - { - ExFreePool(LpcRequest); - if (NULL != AttachedProcess) - { - KeAttachProcess(AttachedProcess); - } - ObDereferenceObject(Port); - return(STATUS_PORT_MESSAGE_TOO_LONG); - } - - Status = EiReplyOrRequestPort(Port->OtherPort, - LpcRequest, - LpcRequest->u2.s2.Type == LPC_ERROR_EVENT ? LPC_ERROR_EVENT : LPC_REQUEST, - Port); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Enqueue failed\n"); - ExFreePool(LpcRequest); - if (NULL != AttachedProcess) - { - KeAttachProcess(AttachedProcess); - } - ObDereferenceObject(Port); - return(Status); - } - ExFreePool(LpcRequest); - KeReleaseSemaphore (&Port->OtherPort->Semaphore, IO_NO_INCREMENT, - 1, FALSE); - - /* - * Wait for a reply - */ - Status = KeWaitForSingleObject(&Port->Semaphore, - UserRequest, - UserMode, - FALSE, - NULL); - if (Status == STATUS_SUCCESS) - { - - /* - * Dequeue the reply - */ - KeAcquireSpinLock(&Port->Lock, &oldIrql); - Message = EiDequeueMessagePort(Port); - KeReleaseSpinLock(&Port->Lock, oldIrql); - if (Message) - { - DPRINT("Message->Message.u1.s1.TotalLength %d\n", - Message->Message.u1.s1.TotalLength); - if (PreviousMode != KernelMode) - { - _SEH_TRY - { - RtlCopyMemory(UnsafeLpcReply, - &Message->Message, - Message->Message.u1.s1.TotalLength); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - else - { - RtlCopyMemory(UnsafeLpcReply, - &Message->Message, - Message->Message.u1.s1.TotalLength); - } - ExFreePool(Message); - } - else - Status = STATUS_UNSUCCESSFUL; - } - else - { - if (NT_SUCCESS(Status)) - { - Status = STATUS_UNSUCCESSFUL; - } - } - if (NULL != AttachedProcess) - { - KeAttachProcess(AttachedProcess); - } - ObDereferenceObject(Port); - - return(Status); -} - - -/********************************************************************** - * NAME - * NtWriteRequestData/6 - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - */ -NTSTATUS STDCALL NtWriteRequestData (HANDLE PortHandle, - PPORT_MESSAGE Message, - ULONG Index, - PVOID Buffer, - ULONG BufferLength, - PULONG ReturnLength) -{ - UNIMPLEMENTED; - return(STATUS_NOT_IMPLEMENTED); -} - - /* EOF */ diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild index 10c6ed34404..dd73ec5d4fc 100644 --- a/reactos/ntoskrnl/ntoskrnl.rbuild +++ b/reactos/ntoskrnl/ntoskrnl.rbuild @@ -9,9 +9,6 @@ - - - . include include/reactos/drivers @@ -230,35 +227,16 @@ loader.c rtl.c - - - close.c - complete.c - connect.c - create.c - listen.c - port.c - query.c - queue.c - receive.c - reply.c - send.c - - - - - - close.c - complete.c - connect.c - create.c - listen.c - port.c - reply.c - send.c - - - + + close.c + complete.c + connect.c + create.c + listen.c + port.c + reply.c + send.c + diff --git a/reactos/ntoskrnl/ob/obhandle.c b/reactos/ntoskrnl/ob/obhandle.c index 34cd8bae2bf..3622370a9c7 100644 --- a/reactos/ntoskrnl/ob/obhandle.c +++ b/reactos/ntoskrnl/ob/obhandle.c @@ -1716,8 +1716,7 @@ ObpSetHandleAttributes(IN PHANDLE_TABLE HandleTable, IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry, IN PVOID Context) { - POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo = - (POBP_SET_HANDLE_ATTRIBUTES_CONTEXT)Context; + POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo = Context; POBJECT_HEADER ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry); PAGED_CODE(); From b824f044923cede20cd1550cb351f4b13bbd6729 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Wed, 10 Jan 2007 04:51:27 +0000 Subject: [PATCH 10/36] remove focus from window, when it gets diabled - fixes bug 843 See issue #843 for more details. svn path=/trunk/; revision=25412 --- reactos/dll/win32/user32/windows/input.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/reactos/dll/win32/user32/windows/input.c b/reactos/dll/win32/user32/windows/input.c index 6f7bac23902..43305ae3595 100644 --- a/reactos/dll/win32/user32/windows/input.c +++ b/reactos/dll/win32/user32/windows/input.c @@ -36,6 +36,7 @@ /* Directory to load key layouts from */ #define SYSTEMROOT_DIR L"\\SystemRoot\\System32\\" +#define STATE_GWL_OFFSET 0 /* GLOBALS *******************************************************************/ @@ -338,11 +339,24 @@ EnableWindow(HWND hWnd, BOOL bEnable) { LONG Style = NtUserGetWindowLong(hWnd, GWL_STYLE, FALSE); - Style = bEnable ? Style & ~WS_DISABLED : Style | WS_DISABLED; - NtUserSetWindowLong(hWnd, GWL_STYLE, Style, FALSE); - - SendMessageA(hWnd, WM_ENABLE, (LPARAM) IsWindowEnabled(hWnd), 0); + /* check if updating is needed */ + UINT bIsDisabled = (Style & WS_DISABLED); + if ( (bIsDisabled && bEnable) || (!bIsDisabled && !bEnable) ) + { + if (bEnable) + { + Style &= ~WS_DISABLED; + } + else + { + /* Remove keyboard focus from that window */ + SetFocus(NULL); + Style |= WS_DISABLED; + } + NtUserSetWindowLong(hWnd, GWL_STYLE, Style, FALSE); + SendMessageA(hWnd, WM_ENABLE, (LPARAM) IsWindowEnabled(hWnd), 0); + } // Return nonzero if it was disabled, or zero if it wasn't: return IsWindowEnabled(hWnd); } From b432f6d20fdb15354a5757b88188d4ba5133e344 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Wed, 10 Jan 2007 06:09:57 +0000 Subject: [PATCH 11/36] - Fix build. svn path=/trunk/; revision=25413 --- reactos/ntoskrnl/lpc/close.c | 3 +-- reactos/ntoskrnl/lpc/complete.c | 3 +-- reactos/ntoskrnl/lpc/connect.c | 3 +-- reactos/ntoskrnl/lpc/create.c | 3 +-- reactos/ntoskrnl/lpc/listen.c | 3 +-- reactos/ntoskrnl/lpc/port.c | 5 ++--- reactos/ntoskrnl/lpc/reply.c | 3 +-- reactos/ntoskrnl/lpc/send.c | 3 +-- 8 files changed, 9 insertions(+), 17 deletions(-) diff --git a/reactos/ntoskrnl/lpc/close.c b/reactos/ntoskrnl/lpc/close.c index af9803dbfc7..88ed35a657c 100644 --- a/reactos/ntoskrnl/lpc/close.c +++ b/reactos/ntoskrnl/lpc/close.c @@ -9,9 +9,8 @@ /* INCLUDES ******************************************************************/ #include -#include "lpc.h" #define NDEBUG -#include +#include /* PRIVATE FUNCTIONS *********************************************************/ diff --git a/reactos/ntoskrnl/lpc/complete.c b/reactos/ntoskrnl/lpc/complete.c index b5e4e190ee1..eeda2e4c412 100644 --- a/reactos/ntoskrnl/lpc/complete.c +++ b/reactos/ntoskrnl/lpc/complete.c @@ -9,9 +9,8 @@ /* INCLUDES ******************************************************************/ #include -#include "lpc.h" #define NDEBUG -#include +#include /* PRIVATE FUNCTIONS *********************************************************/ diff --git a/reactos/ntoskrnl/lpc/connect.c b/reactos/ntoskrnl/lpc/connect.c index 2b9259ef588..73a57ff3219 100644 --- a/reactos/ntoskrnl/lpc/connect.c +++ b/reactos/ntoskrnl/lpc/connect.c @@ -9,9 +9,8 @@ /* INCLUDES ******************************************************************/ #include -#include "lpc.h" #define NDEBUG -#include +#include /* PRIVATE FUNCTIONS *********************************************************/ diff --git a/reactos/ntoskrnl/lpc/create.c b/reactos/ntoskrnl/lpc/create.c index 2bf08c13e11..a0478d5ed5e 100644 --- a/reactos/ntoskrnl/lpc/create.c +++ b/reactos/ntoskrnl/lpc/create.c @@ -9,9 +9,8 @@ /* INCLUDES ******************************************************************/ #include -#include "lpc.h" #define NDEBUG -#include +#include /* PRIVATE FUNCTIONS *********************************************************/ diff --git a/reactos/ntoskrnl/lpc/listen.c b/reactos/ntoskrnl/lpc/listen.c index ee2ade0c03d..8bc84c324be 100644 --- a/reactos/ntoskrnl/lpc/listen.c +++ b/reactos/ntoskrnl/lpc/listen.c @@ -9,9 +9,8 @@ /* INCLUDES ******************************************************************/ #include -#include "lpc.h" #define NDEBUG -#include +#include /* PUBLIC FUNCTIONS **********************************************************/ diff --git a/reactos/ntoskrnl/lpc/port.c b/reactos/ntoskrnl/lpc/port.c index dcc5a979d44..b085e9183d3 100644 --- a/reactos/ntoskrnl/lpc/port.c +++ b/reactos/ntoskrnl/lpc/port.c @@ -9,9 +9,8 @@ /* INCLUDES ******************************************************************/ #include -#include "lpc.h" #define NDEBUG -#include +#include /* GLOBALS *******************************************************************/ @@ -19,7 +18,7 @@ POBJECT_TYPE LpcPortObjectType; ULONG LpcpMaxMessageSize; PAGED_LOOKASIDE_LIST LpcpMessagesLookaside; KGUARDED_MUTEX LpcpLock; -ULONG LpcpTraceLevel = LPC_CLOSE_DEBUG; +ULONG LpcpTraceLevel = 0; ULONG LpcpNextMessageId = 1, LpcpNextCallbackId = 1; static GENERIC_MAPPING LpcpPortMapping = diff --git a/reactos/ntoskrnl/lpc/reply.c b/reactos/ntoskrnl/lpc/reply.c index 311002eb2eb..1e613b02e5b 100644 --- a/reactos/ntoskrnl/lpc/reply.c +++ b/reactos/ntoskrnl/lpc/reply.c @@ -9,9 +9,8 @@ /* INCLUDES ******************************************************************/ #include -#include "lpc.h" #define NDEBUG -#include +#include /* PRIVATE FUNCTIONS *********************************************************/ diff --git a/reactos/ntoskrnl/lpc/send.c b/reactos/ntoskrnl/lpc/send.c index f49e0a6550f..8605a70edb7 100644 --- a/reactos/ntoskrnl/lpc/send.c +++ b/reactos/ntoskrnl/lpc/send.c @@ -9,9 +9,8 @@ /* INCLUDES ******************************************************************/ #include -#include "lpc.h" #define NDEBUG -#include +#include /* PUBLIC FUNCTIONS **********************************************************/ From de1bca6b2c0f12ecc85075243eedef1f548fbff0 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Wed, 10 Jan 2007 18:31:33 +0000 Subject: [PATCH 12/36] sorry, forgot to remove that line svn path=/trunk/; revision=25414 --- reactos/dll/win32/user32/windows/input.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/reactos/dll/win32/user32/windows/input.c b/reactos/dll/win32/user32/windows/input.c index 43305ae3595..0d4fe32b36e 100644 --- a/reactos/dll/win32/user32/windows/input.c +++ b/reactos/dll/win32/user32/windows/input.c @@ -36,8 +36,6 @@ /* Directory to load key layouts from */ #define SYSTEMROOT_DIR L"\\SystemRoot\\System32\\" -#define STATE_GWL_OFFSET 0 - /* GLOBALS *******************************************************************/ typedef struct __TRACKINGLIST { From 35f20cc413651924b6c0badefc9a727b9d9a8358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Wed, 10 Jan 2007 19:39:01 +0000 Subject: [PATCH 13/36] Move x86 specific part to i386/ directory. Fix a few warnings svn path=/trunk/; revision=25415 --- reactos/lib/rtl/austin/udict.h | 4 +- reactos/lib/rtl/i386/thread.c | 80 ++++++++++++++++++++++++++++++++++ reactos/lib/rtl/nls.c | 4 +- reactos/lib/rtl/rtl.rbuild | 1 + reactos/lib/rtl/thread.c | 57 ------------------------ 5 files changed, 85 insertions(+), 61 deletions(-) create mode 100644 reactos/lib/rtl/i386/thread.c diff --git a/reactos/lib/rtl/austin/udict.h b/reactos/lib/rtl/austin/udict.h index f5b9620590f..033413e1d14 100644 --- a/reactos/lib/rtl/austin/udict.h +++ b/reactos/lib/rtl/austin/udict.h @@ -57,8 +57,8 @@ typedef enum { typedef enum { udict_balanced = 0, - udict_leftheavy = -1, - udict_rightheavy = 1 + udict_leftheavy = 1, + udict_rightheavy = 2 } udict_avl_balance_t; typedef union { diff --git a/reactos/lib/rtl/i386/thread.c b/reactos/lib/rtl/i386/thread.c new file mode 100644 index 00000000000..5f223fca151 --- /dev/null +++ b/reactos/lib/rtl/i386/thread.c @@ -0,0 +1,80 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * PURPOSE: Rtl user thread functions + * FILE: lib/rtl/thread.c + * PROGRAMERS: + * Alex Ionescu (alex@relsoft.net) + * Eric Kohl + * KJK::Hyperion + */ + +/* INCLUDES *****************************************************************/ + +#include +#include "i386/ketypes.h" + +#define NDEBUG +#include + +/* PRIVATE FUNCTIONS *******************************************************/ + +/* + * @implemented + */ +VOID +NTAPI +RtlInitializeContext(IN HANDLE ProcessHandle, + OUT PCONTEXT ThreadContext, + IN PVOID ThreadStartParam OPTIONAL, + IN PTHREAD_START_ROUTINE ThreadStartAddress, + IN PINITIAL_TEB InitialTeb) +{ + DPRINT("RtlInitializeContext: (hProcess: %p, ThreadContext: %p, Teb: %p\n", + ProcessHandle, ThreadContext, InitialTeb); + + /* + * Set the Initial Registers + * This is based on NT's default values -- crazy apps might expect this... + */ + ThreadContext->Ebp = 0; + ThreadContext->Eax = 0; + ThreadContext->Ebx = 1; + ThreadContext->Ecx = 2; + ThreadContext->Edx = 3; + ThreadContext->Esi = 4; + ThreadContext->Edi = 5; + + /* Set the Selectors */ + ThreadContext->SegGs = 0; + ThreadContext->SegFs = KGDT_R3_TEB; + ThreadContext->SegEs = KGDT_R3_DATA; + ThreadContext->SegDs = KGDT_R3_DATA; + ThreadContext->SegSs = KGDT_R3_DATA; + ThreadContext->SegCs = KGDT_R3_CODE; + + /* Enable Interrupts */ + ThreadContext->EFlags = EFLAGS_INTERRUPT_MASK; + + /* Settings passed */ + ThreadContext->Eip = (ULONG)ThreadStartAddress; + ThreadContext->Esp = (ULONG)InitialTeb; + + /* Only the basic Context is initialized */ + ThreadContext->ContextFlags = CONTEXT_CONTROL | + CONTEXT_INTEGER | + CONTEXT_SEGMENTS; + + /* Set up ESP to the right value */ + ThreadContext->Esp -= sizeof(PVOID); + ZwWriteVirtualMemory(ProcessHandle, + (PVOID)ThreadContext->Esp, + (PVOID)&ThreadStartParam, + sizeof(PVOID), + NULL); + + /* Push it down one more notch for RETEIP */ + ThreadContext->Esp -= sizeof(PVOID); +} + +/* EOF */ diff --git a/reactos/lib/rtl/nls.c b/reactos/lib/rtl/nls.c index 4bfa0c96160..4fd59e765d0 100644 --- a/reactos/lib/rtl/nls.c +++ b/reactos/lib/rtl/nls.c @@ -359,7 +359,7 @@ RtlResetRtlTranslations(IN PNLSTABLEINFO NlsTable) DPRINT("RtlResetRtlTranslations() called\n"); /* Set ANSI data */ - NlsAnsiToUnicodeTable = NlsTable->AnsiTableInfo.MultiByteTable; + NlsAnsiToUnicodeTable = (PWCHAR)NlsTable->AnsiTableInfo.MultiByteTable; /* Real type is PUSHORT */ NlsUnicodeToAnsiTable = NlsTable->AnsiTableInfo.WideCharTable; NlsDbcsUnicodeToAnsiTable = (PWCHAR)NlsTable->AnsiTableInfo.WideCharTable; NlsMbCodePageTag = (NlsTable->AnsiTableInfo.DBCSCodePage != 0); @@ -368,7 +368,7 @@ RtlResetRtlTranslations(IN PNLSTABLEINFO NlsTable) DPRINT("Ansi codepage %hu\n", NlsAnsiCodePage); /* Set OEM data */ - NlsOemToUnicodeTable = NlsTable->OemTableInfo.MultiByteTable; + NlsOemToUnicodeTable = (PWCHAR)NlsTable->OemTableInfo.MultiByteTable; /* Real type is PUSHORT */ NlsUnicodeToOemTable = NlsTable->OemTableInfo.WideCharTable; NlsDbcsUnicodeToOemTable = (PWCHAR)NlsTable->OemTableInfo.WideCharTable; NlsMbOemCodePageTag = (NlsTable->OemTableInfo.DBCSCodePage != 0); diff --git a/reactos/lib/rtl/rtl.rbuild b/reactos/lib/rtl/rtl.rbuild index 4ddf39a7afa..674cdfd93bd 100644 --- a/reactos/lib/rtl/rtl.rbuild +++ b/reactos/lib/rtl/rtl.rbuild @@ -39,6 +39,7 @@ sin_asm.s sqrt_asm.s tan_asm.s + thread.c diff --git a/reactos/lib/rtl/thread.c b/reactos/lib/rtl/thread.c index 55dae05113c..0b87c7b469b 100644 --- a/reactos/lib/rtl/thread.c +++ b/reactos/lib/rtl/thread.c @@ -12,7 +12,6 @@ /* INCLUDES *****************************************************************/ #include -#include "i386/ketypes.h" #define NDEBUG #include @@ -218,62 +217,6 @@ RtlCreateUserThread(IN HANDLE ProcessHandle, return Status; } -/* - * FIXME: Should go in /i386 - @implemented -*/ -VOID -NTAPI -RtlInitializeContext(IN HANDLE ProcessHandle, - OUT PCONTEXT ThreadContext, - IN PVOID ThreadStartParam OPTIONAL, - IN PTHREAD_START_ROUTINE ThreadStartAddress, - IN PINITIAL_TEB InitialTeb) -{ - /* - * Set the Initial Registers - * This is based on NT's default values -- crazy apps might expect this... - */ - ThreadContext->Ebp = 0; - ThreadContext->Eax = 0; - ThreadContext->Ebx = 1; - ThreadContext->Ecx = 2; - ThreadContext->Edx = 3; - ThreadContext->Esi = 4; - ThreadContext->Edi = 5; - - /* Set the Selectors */ - ThreadContext->SegGs = 0; - ThreadContext->SegFs = KGDT_R3_TEB; - ThreadContext->SegEs = KGDT_R3_DATA; - ThreadContext->SegDs = KGDT_R3_DATA; - ThreadContext->SegSs = KGDT_R3_DATA; - ThreadContext->SegCs = KGDT_R3_CODE; - - /* Enable Interrupts */ - ThreadContext->EFlags = EFLAGS_INTERRUPT_MASK; - - /* Settings passed */ - ThreadContext->Eip = (ULONG)ThreadStartAddress; - ThreadContext->Esp = (ULONG)InitialTeb; - - /* Only the basic Context is initialized */ - ThreadContext->ContextFlags = CONTEXT_CONTROL | - CONTEXT_INTEGER | - CONTEXT_SEGMENTS; - - /* Set up ESP to the right value */ - ThreadContext->Esp -= sizeof(PVOID); - ZwWriteVirtualMemory(ProcessHandle, - (PVOID)ThreadContext->Esp, - (PVOID)&ThreadStartParam, - sizeof(PVOID), - NULL); - - /* Push it down one more notch for RETEIP */ - ThreadContext->Esp -= sizeof(PVOID); -} - /* * @implemented */ From 263d5e238b3bb2757e62fa2baeb4076920d0e94b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Wed, 10 Jan 2007 19:39:52 +0000 Subject: [PATCH 14/36] Allow use of ROS_PREFIX on MS Windows platforms (needed for cross-compiling) svn path=/trunk/; revision=25416 --- reactos/Makefile | 81 +++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/reactos/Makefile b/reactos/Makefile index b13b55055ed..9392802ee9f 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -274,45 +274,48 @@ endif cp = $(Q)cp NUL = /dev/null else # mingw32-windows - ifeq ($(OSTYPE),msys) - HOST=mingw32-linux - export EXEPREFIX = ./ - export EXEPOSTFIX = .exe - export SEP = / - mkdir = -$(Q)mkdir -p - gcc = $(Q)gcc - gpp = $(Q)g++ - ld = $(Q)ld - nm = $(Q)nm - objdump = $(Q)objdump - ar = $(Q)ar - objcopy = $(Q)objcopy - dlltool = $(Q)dlltool - strip = $(Q)strip - windres = $(Q)windres - rm = $(Q)rm -f - cp = $(Q)cp - NUL = /dev/null - else - export EXEPREFIX = - export EXEPOSTFIX = .exe - ROS_EMPTY = - export SEP = \$(ROS_EMPTY) - mkdir = -$(Q)mkdir - gcc = $(Q)gcc - gpp = $(Q)g++ - ld = $(Q)ld - nm = $(Q)nm - objdump = $(Q)objdump - ar = $(Q)ar - objcopy = $(Q)objcopy - dlltool = $(Q)dlltool - strip = $(Q)strip - windres = $(Q)windres - rm = $(Q)del /f /q - cp = $(Q)copy /y - NUL = NUL - endif + ifeq ($(OSTYPE),msys) + HOST=mingw32-linux + export EXEPREFIX = ./ + export EXEPOSTFIX = .exe + export SEP = / + mkdir = -$(Q)mkdir -p + rm = $(Q)rm -f + cp = $(Q)cp + NUL = /dev/null + else + export EXEPREFIX = + export EXEPOSTFIX = .exe + ROS_EMPTY = + export SEP = \$(ROS_EMPTY) + mkdir = -$(Q)mkdir + rm = $(Q)del /f /q + cp = $(Q)copy /y + NUL = NUL + endif + ifeq ($(ROS_PREFIX),) + gcc = $(Q)gcc + gpp = $(Q)g++ + ld = $(Q)ld + nm = $(Q)nm + objdump = $(Q)objdump + ar = $(Q)ar + objcopy = $(Q)objcopy + dlltool = $(Q)dlltool + strip = $(Q)strip + windres = $(Q)windres + else + gcc = $(ROS_PREFIX)-gcc + gpp = $(Q)$(ROS_PREFIX)-g++ + ld = $(Q)$(ROS_PREFIX)-ld + nm = $(Q)$(ROS_PREFIX)-nm + objdump = $(Q)$(ROS_PREFIX)-objdump + ar = $(Q)$(ROS_PREFIX)-ar + objcopy = $(Q)$(ROS_PREFIX)-objcopy + dlltool = $(Q)$(ROS_PREFIX)-dlltool + strip = $(Q)$(ROS_PREFIX)-strip + windres = $(Q)$(ROS_PREFIX)-windres + endif endif ifneq ($(ROS_INTERMEDIATE),) From e6f6ed291d18789e77dd28d6f6564e97bb4d7dca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Wed, 10 Jan 2007 19:48:35 +0000 Subject: [PATCH 15/36] Disable some boot options on non-x86 platforms. You can enable them again for specific platforms if needed. svn path=/trunk/; revision=25417 --- reactos/boot/freeldr/freeldr/bootmgr.c | 4 ++++ reactos/boot/freeldr/freeldr/custom.c | 14 +++++++++++++- reactos/boot/freeldr/freeldr/drivemap.c | 2 ++ reactos/boot/freeldr/freeldr/include/drivemap.h | 3 ++- reactos/boot/freeldr/freeldr/include/linux.h | 3 ++- reactos/boot/freeldr/freeldr/include/miscboot.h | 2 ++ reactos/boot/freeldr/freeldr/include/options.h | 2 ++ reactos/boot/freeldr/freeldr/linuxboot.c | 2 ++ reactos/boot/freeldr/freeldr/miscboot.c | 2 ++ 9 files changed, 31 insertions(+), 3 deletions(-) diff --git a/reactos/boot/freeldr/freeldr/bootmgr.c b/reactos/boot/freeldr/freeldr/bootmgr.c index 43b1ef6c18b..ac0dd3fee5c 100644 --- a/reactos/boot/freeldr/freeldr/bootmgr.c +++ b/reactos/boot/freeldr/freeldr/bootmgr.c @@ -119,11 +119,14 @@ NoGui: } // Install the drive mapper according to this sections drive mappings +#ifdef __i386__ DriveMapMapDrivesInSection(OperatingSystemSectionNames[SelectedOperatingSystem]); +#endif if (_stricmp(SettingValue, "ReactOS") == 0) { LoadAndBootReactOS(OperatingSystemSectionNames[SelectedOperatingSystem]); } +#ifdef __i386__ else if (_stricmp(SettingValue, "WindowsNT40") == 0) { LoadAndBootWindows(OperatingSystemSectionNames[SelectedOperatingSystem], _WIN32_WINNT_NT4); @@ -156,6 +159,7 @@ NoGui: { LoadAndBootDrive(OperatingSystemSectionNames[SelectedOperatingSystem]); } +#endif } diff --git a/reactos/boot/freeldr/freeldr/custom.c b/reactos/boot/freeldr/freeldr/custom.c index 38b61dd0620..e4d9de58f91 100644 --- a/reactos/boot/freeldr/freeldr/custom.c +++ b/reactos/boot/freeldr/freeldr/custom.c @@ -33,7 +33,15 @@ const CHAR CustomBootPrompt[] = "Press ENTER to boot your custom boot setup."; VOID OptionMenuCustomBoot(VOID) { - PCSTR CustomBootMenuList[] = { "Disk", "Partition", "Boot Sector File", "ReactOS", "Linux" }; + PCSTR CustomBootMenuList[] = { +#ifdef __i386__ + "Disk", + "Partition", + "Boot Sector File", + "ReactOS", + "Linux" +#endif /* __i386__ */ + }; ULONG CustomBootMenuCount = sizeof(CustomBootMenuList) / sizeof(CustomBootMenuList[0]); ULONG SelectedMenuItem; @@ -45,6 +53,7 @@ VOID OptionMenuCustomBoot(VOID) switch (SelectedMenuItem) { +#ifdef __i386__ case 0: // Disk OptionMenuCustomBootDisk(); break; @@ -60,9 +69,11 @@ VOID OptionMenuCustomBoot(VOID) case 4: // Linux OptionMenuCustomBootLinux(); break; +#endif /* __i386__ */ } } +#ifdef __i386__ VOID OptionMenuCustomBootDisk(VOID) { CHAR SectionName[100]; @@ -397,3 +408,4 @@ VOID OptionMenuCustomBootLinux(VOID) LoadAndBootLinux(SectionName, "Custom Linux Setup"); } +#endif /* __i386__ */ diff --git a/reactos/boot/freeldr/freeldr/drivemap.c b/reactos/boot/freeldr/freeldr/drivemap.c index 31ecab7a37b..7e82f13eea5 100644 --- a/reactos/boot/freeldr/freeldr/drivemap.c +++ b/reactos/boot/freeldr/freeldr/drivemap.c @@ -22,6 +22,7 @@ #define NDEBUG #include +#ifdef __i386__ BOOLEAN DriveMapInstalled = FALSE; // Tells us if we have already installed our drive map int 13h handler code ULONG OldInt13HandlerAddress = 0; // Address of BIOS int 13h handler ULONG DriveMapHandlerAddress = 0; // Linear address of our drive map handler @@ -222,3 +223,4 @@ VOID DriveMapRemoveInt13Handler(VOID) DriveMapInstalled = FALSE; } } +#endif /* __i386__ */ diff --git a/reactos/boot/freeldr/freeldr/include/drivemap.h b/reactos/boot/freeldr/freeldr/include/drivemap.h index 1d25f1f29f7..29a3d2cc5c2 100644 --- a/reactos/boot/freeldr/freeldr/include/drivemap.h +++ b/reactos/boot/freeldr/freeldr/include/drivemap.h @@ -20,7 +20,7 @@ #ifndef __DRIVEMAP_H #define __DRIVEMAP_H - +#ifdef __i386__ typedef struct { UCHAR DriveMapCount; // Count of drives currently mapped @@ -39,5 +39,6 @@ extern PVOID DriveMapInt13HandlerStart; extern PVOID DriveMapInt13HandlerEnd; extern ULONG DriveMapOldInt13HandlerAddress; extern DRIVE_MAP_LIST DriveMapInt13HandlerMapList; +#endif /* __i386__ */ #endif // #defined __DRIVEMAP_H diff --git a/reactos/boot/freeldr/freeldr/include/linux.h b/reactos/boot/freeldr/freeldr/include/linux.h index 90c6a8aea9c..14d3bf0d8be 100644 --- a/reactos/boot/freeldr/freeldr/include/linux.h +++ b/reactos/boot/freeldr/freeldr/include/linux.h @@ -22,7 +22,7 @@ #ifndef __LINUX_H #define __LINUX_H - +#ifdef __i386__ #define LINUX_LOADER_TYPE_LILO 0x01 #define LINUX_LOADER_TYPE_LOADLIN 0x11 #define LINUX_LOADER_TYPE_BOOTSECT 0x21 @@ -135,5 +135,6 @@ BOOLEAN LinuxReadSetupSector(PFILE LinuxKernelFile); BOOLEAN LinuxReadKernel(PFILE LinuxKernelFile); BOOLEAN LinuxCheckKernelVersion(VOID); BOOLEAN LinuxReadInitrd(PFILE LinuxInitrdFile); +#endif /* __i386__ */ #endif // defined __LINUX_H diff --git a/reactos/boot/freeldr/freeldr/include/miscboot.h b/reactos/boot/freeldr/freeldr/include/miscboot.h index e274c9ae2af..c0aea8381c2 100644 --- a/reactos/boot/freeldr/freeldr/include/miscboot.h +++ b/reactos/boot/freeldr/freeldr/include/miscboot.h @@ -20,8 +20,10 @@ #ifndef __BOOT_H #define __BOOT_H +#ifdef __i386__ VOID LoadAndBootBootSector(PCSTR OperatingSystemName); VOID LoadAndBootPartition(PCSTR OperatingSystemName); VOID LoadAndBootDrive(PCSTR OperatingSystemName); +#endif /* __i386__ */ #endif // defined __BOOT_H diff --git a/reactos/boot/freeldr/freeldr/include/options.h b/reactos/boot/freeldr/freeldr/include/options.h index 82ac6150e69..72cfa53aaea 100644 --- a/reactos/boot/freeldr/freeldr/include/options.h +++ b/reactos/boot/freeldr/freeldr/include/options.h @@ -25,10 +25,12 @@ VOID DoOptionsMenu(VOID); VOID OptionMenuReboot(VOID); VOID OptionMenuCustomBoot(VOID); +#ifdef __i386__ VOID OptionMenuCustomBootDisk(VOID); VOID OptionMenuCustomBootPartition(VOID); VOID OptionMenuCustomBootBootSectorFile(VOID); VOID OptionMenuCustomBootReactOS(VOID); VOID OptionMenuCustomBootLinux(VOID); +#endif /* __i386__ */ #endif // #defined __OPTIONS_H diff --git a/reactos/boot/freeldr/freeldr/linuxboot.c b/reactos/boot/freeldr/freeldr/linuxboot.c index 27589bd6a26..5c086ef00fa 100644 --- a/reactos/boot/freeldr/freeldr/linuxboot.c +++ b/reactos/boot/freeldr/freeldr/linuxboot.c @@ -23,6 +23,7 @@ #define NDEBUG #include +#ifdef __i386__ #define LINUX_READ_CHUNK_SIZE 0x20000 // Read 128k at a time @@ -491,3 +492,4 @@ BOOLEAN LinuxReadInitrd(PFILE LinuxInitrdFile) return TRUE; } +#endif /* __i386__ */ diff --git a/reactos/boot/freeldr/freeldr/miscboot.c b/reactos/boot/freeldr/freeldr/miscboot.c index bbbf34f9ac2..a96bbd5cd28 100644 --- a/reactos/boot/freeldr/freeldr/miscboot.c +++ b/reactos/boot/freeldr/freeldr/miscboot.c @@ -19,6 +19,7 @@ #include +#ifdef __i386__ VOID LoadAndBootBootSector(PCSTR OperatingSystemName) { PFILE FilePointer; @@ -213,3 +214,4 @@ VOID LoadAndBootDrive(PCSTR OperatingSystemName) //DisableA20(); ChainLoadBiosBootSectorCode(); } +#endif /* __i386__ */ From d9466bc852262df680de042e6ca3835f2e5504ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Wed, 10 Jan 2007 19:57:52 +0000 Subject: [PATCH 16/36] Move up wpp include, as it is needed by widl svn path=/trunk/; revision=25418 --- reactos/tools/tools.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/tools/tools.mak b/reactos/tools/tools.mak index 1ef5a123eaf..cbc5f417af7 100644 --- a/reactos/tools/tools.mak +++ b/reactos/tools/tools.mak @@ -56,8 +56,8 @@ include tools/rgenstat/rgenstat.mak include tools/rsym.mak include tools/sysreg/sysreg.mak include tools/unicode/unicode.mak +include tools/wpp/wpp.mak include tools/widl/widl.mak include tools/winebuild/winebuild.mak include tools/wmc/wmc.mak -include tools/wpp/wpp.mak include tools/wrc/wrc.mak \ No newline at end of file From f1f9bb147e92e7851a020d5e73403c4576eb25ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Wed, 10 Jan 2007 20:02:41 +0000 Subject: [PATCH 17/36] Don't rely on stdio.h to define EOF, as native stdio.h can conflict with ROS headers svn path=/trunk/; revision=25419 --- reactos/lib/string/sscanf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/reactos/lib/string/sscanf.c b/reactos/lib/string/sscanf.c index 39b28f22299..fdb2bc78363 100644 --- a/reactos/lib/string/sscanf.c +++ b/reactos/lib/string/sscanf.c @@ -5,7 +5,8 @@ #include #include #include -#include + +#define EOF (-1) /* helper function for *scanf. Returns the value of character c in the * given base, or -1 if the given character is not a digit of the base. From 11f6279e1191e0a233d7d1f535a2eef353baf888 Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Wed, 10 Jan 2007 22:52:07 +0000 Subject: [PATCH 18/36] Fix warnings svn path=/trunk/; revision=25421 --- reactos/ntoskrnl/fsrtl/largemcb.c | 12 ++++++++++-- reactos/ntoskrnl/include/internal/ob_x.h | 4 ++-- reactos/ntoskrnl/ob/oblife.c | 2 +- reactos/ntoskrnl/ob/obname.c | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/reactos/ntoskrnl/fsrtl/largemcb.c b/reactos/ntoskrnl/fsrtl/largemcb.c index f0e4c8c1cac..a63dc90a623 100644 --- a/reactos/ntoskrnl/fsrtl/largemcb.c +++ b/reactos/ntoskrnl/fsrtl/largemcb.c @@ -58,6 +58,9 @@ FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb, OUT PLONGLONG SectorCount) { KEBUGCHECK(0); + *Vbn = 0; + *Lbn = 0; + *SectorCount= 0; return FALSE; } @@ -132,6 +135,8 @@ FsRtlLookupLargeMcbEntry(IN PLARGE_MCB Mcb, OUT PULONG Index OPTIONAL) { KEBUGCHECK(0); + *Lbn = 0; + *SectorCountFromLbn = 0; return FALSE; } @@ -146,6 +151,9 @@ FsRtlLookupLastLargeMcbEntryAndIndex(IN PLARGE_MCB OpaqueMcb, OUT PULONG Index) { KEBUGCHECK(0); + *LargeVbn = 0; + *LargeLbn = 0; + *Index = 0; return FALSE; } @@ -172,8 +180,8 @@ FsRtlLookupLastMcbEntry(IN PMCB Mcb, OUT PLBN Lbn) { BOOLEAN Return = FALSE; - LONGLONG llVbn; - LONGLONG llLbn; + LONGLONG llVbn = 0; + LONGLONG llLbn = 0; /* Call the Large version */ Return = FsRtlLookupLastLargeMcbEntry( diff --git a/reactos/ntoskrnl/include/internal/ob_x.h b/reactos/ntoskrnl/include/internal/ob_x.h index 34a5011857a..c768d3e373b 100644 --- a/reactos/ntoskrnl/include/internal/ob_x.h +++ b/reactos/ntoskrnl/include/internal/ob_x.h @@ -27,7 +27,7 @@ ObpIncrementQueryReference(IN POBJECT_HEADER ObjectHeader, while ((NewValue != 0) && (References = NewValue)) { /* Increment the number of references */ - if (InterlockedCompareExchange(&ObjectNameInfo->QueryReferences, + if (InterlockedCompareExchange((PLONG)&ObjectNameInfo->QueryReferences, NewValue + 1, NewValue) == References) { @@ -56,7 +56,7 @@ ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo) POBJECT_DIRECTORY Directory; /* Remove a query reference and check if it was the last one */ - if (!InterlockedExchangeAdd(&HeaderNameInfo->QueryReferences, -1)) + if (!InterlockedExchangeAdd((PLONG)&HeaderNameInfo->QueryReferences, -1)) { /* Check if we have a name */ if (HeaderNameInfo->Name.Buffer) diff --git a/reactos/ntoskrnl/ob/oblife.c b/reactos/ntoskrnl/ob/oblife.c index 488af3131a1..b791acb7833 100644 --- a/reactos/ntoskrnl/ob/oblife.c +++ b/reactos/ntoskrnl/ob/oblife.c @@ -801,7 +801,7 @@ ObpAllocateObject(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo, if (ObjectType) { /* Increase the number of objects of this type */ - InterlockedIncrement(&ObjectType->TotalNumberOfObjects); + InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfObjects); /* Update the high water */ ObjectType->HighWaterNumberOfObjects = max(ObjectType-> diff --git a/reactos/ntoskrnl/ob/obname.c b/reactos/ntoskrnl/ob/obname.c index 2becdbc3bd8..afa422a346f 100644 --- a/reactos/ntoskrnl/ob/obname.c +++ b/reactos/ntoskrnl/ob/obname.c @@ -238,7 +238,7 @@ ObpDeleteNameCheck(IN PVOID Object) (ObjectNameInfo->QueryReferences & 0x40000000)) { /* Add deletion flag */ - InterlockedExchangeAdd(&ObjectNameInfo->QueryReferences, + InterlockedExchangeAdd((PLONG)&ObjectNameInfo->QueryReferences, 0xC0000000); } From b2c4c0e76ea473b941924c777d6b14587425366e Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Wed, 10 Jan 2007 23:48:02 +0000 Subject: [PATCH 19/36] Don't remove keyboard focus from any other window than the one that was disabled. svn path=/trunk/; revision=25422 --- reactos/dll/win32/user32/windows/input.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/reactos/dll/win32/user32/windows/input.c b/reactos/dll/win32/user32/windows/input.c index 0d4fe32b36e..ed5a7138ee7 100644 --- a/reactos/dll/win32/user32/windows/input.c +++ b/reactos/dll/win32/user32/windows/input.c @@ -347,9 +347,12 @@ EnableWindow(HWND hWnd, } else { - /* Remove keyboard focus from that window */ - SetFocus(NULL); Style |= WS_DISABLED; + /* Remove keyboard focus from that window if it had focus */ + if (hWnd == GetFocus()) + { + SetFocus(NULL); + } } NtUserSetWindowLong(hWnd, GWL_STYLE, Style, FALSE); From dc8aa9ffd77a5fde7b14ab97579382061eeb0a1a Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Wed, 10 Jan 2007 23:55:53 +0000 Subject: [PATCH 20/36] - Make IntSystemParametersInfo send a WM_SETTINGCHANGE message when needed. - Some code cleanup svn path=/trunk/; revision=25423 --- reactos/subsystems/win32/win32k/ntuser/misc.c | 138 ++++++++++-------- 1 file changed, 79 insertions(+), 59 deletions(-) diff --git a/reactos/subsystems/win32/win32k/ntuser/misc.c b/reactos/subsystems/win32/win32k/ntuser/misc.c index 44c245d0916..cf5708537bf 100644 --- a/reactos/subsystems/win32/win32k/ntuser/misc.c +++ b/reactos/subsystems/win32/win32k/ntuser/misc.c @@ -909,6 +909,7 @@ IntSystemParametersInfo( { PWINSTATION_OBJECT WinStaObject; NTSTATUS Status; + BOOL bChanged = FALSE; static BOOL bInitialized = FALSE; static LOGFONTW IconFont; @@ -956,16 +957,18 @@ IntSystemParametersInfo( case SPI_SETDOUBLECLKHEIGHT: case SPI_SETDOUBLECLICKTIME: case SPI_SETDESKWALLPAPER: + case SPI_SETSCREENSAVERRUNNING: + case SPI_SETSCREENSAVETIMEOUT: + case SPI_SETFLATMENU: + /* We will change something, so set the flag here */ + bChanged = TRUE; case SPI_GETDESKWALLPAPER: case SPI_GETWHEELSCROLLLINES: case SPI_GETWHEELSCROLLCHARS: - case SPI_SETSCREENSAVERRUNNING: case SPI_GETSCREENSAVERRUNNING: case SPI_GETSCREENSAVETIMEOUT: - case SPI_SETSCREENSAVETIMEOUT: case SPI_GETSCREENSAVEACTIVE: case SPI_GETFLATMENU: - case SPI_SETFLATMENU: { PSYSTEM_CURSORINFO CurInfo; @@ -982,43 +985,42 @@ IntSystemParametersInfo( switch(uiAction) { case SPI_GETFLATMENU: - if (pvParam != NULL) *((UINT*)pvParam) = WinStaObject->FlatMenu; - return TRUE; + ASSERT(pvParam); + *((UINT*)pvParam) = WinStaObject->FlatMenu; break; - case SPI_SETFLATMENU: - WinStaObject->FlatMenu = uiParam; + case SPI_SETFLATMENU: + WinStaObject->FlatMenu = uiParam; break; case SPI_GETSCREENSAVETIMEOUT: - if (pvParam != NULL) *((UINT*)pvParam) = WinStaObject->ScreenSaverTimeOut; - return TRUE; - break; - case SPI_SETSCREENSAVETIMEOUT: - WinStaObject->ScreenSaverTimeOut = uiParam; + ASSERT(pvParam); + *((UINT*)pvParam) = WinStaObject->ScreenSaverTimeOut; + break; + case SPI_SETSCREENSAVETIMEOUT: + WinStaObject->ScreenSaverTimeOut = uiParam; break; case SPI_GETSCREENSAVERRUNNING: if (pvParam != NULL) *((BOOL*)pvParam) = WinStaObject->ScreenSaverRunning; - return TRUE; break; - case SPI_SETSCREENSAVERRUNNING: + case SPI_SETSCREENSAVERRUNNING: if (pvParam != NULL) *((BOOL*)pvParam) = WinStaObject->ScreenSaverRunning; - WinStaObject->ScreenSaverRunning = uiParam; + WinStaObject->ScreenSaverRunning = uiParam; break; case SPI_GETSCREENSAVEACTIVE: /* FIXME: how to disable the screensaver? */ - if (pvParam != NULL) *((BOOL*)pvParam) = TRUE; - return TRUE; + ASSERT(pvParam); + *((BOOL*)pvParam) = TRUE; break; case SPI_GETWHEELSCROLLLINES: + ASSERT(pvParam); CurInfo = IntGetSysCursorInfo(WinStaObject); - if (pvParam != NULL) *((UINT*)pvParam) = CurInfo->WheelScroLines; + *((UINT*)pvParam) = CurInfo->WheelScroLines; /* FIXME add this value to scroll list as scroll value ?? */ - return TRUE; break; case SPI_GETWHEELSCROLLCHARS: + ASSERT(pvParam); CurInfo = IntGetSysCursorInfo(WinStaObject); - if (pvParam != NULL) *((UINT*)pvParam) = CurInfo->WheelScroChars; + *((UINT*)pvParam) = CurInfo->WheelScroChars; // FIXME add this value to scroll list as scroll value ?? - return TRUE; break; case SPI_SETDOUBLECLKWIDTH: CurInfo = IntGetSysCursorInfo(WinStaObject); @@ -1125,7 +1127,7 @@ IntSystemParametersInfo( if(!KeyValuePartialInfo) { NtClose(KeyHandle); - return 0; + return FALSE; } Status = ZwQueryValueKey(KeyHandle, &Tile, KeyValuePartialInformation, @@ -1134,7 +1136,7 @@ IntSystemParametersInfo( { ZwClose(KeyHandle); ExFreePool(KeyValuePartialInfo); - return 0; + return FALSE; } Tile.Length = KeyValuePartialInfo->DataLength; @@ -1160,7 +1162,7 @@ IntSystemParametersInfo( if(!KeyValuePartialInfo) { ZwClose(KeyHandle); - return 0; + return FALSE; } Status = ZwQueryValueKey(KeyHandle, &Style, KeyValuePartialInformation, @@ -1169,7 +1171,7 @@ IntSystemParametersInfo( { ZwClose(KeyHandle); ExFreePool(KeyValuePartialInfo); - return 0; + return FALSE; } Style.Length = KeyValuePartialInfo->DataLength; @@ -1210,7 +1212,7 @@ IntSystemParametersInfo( /* FIXME save the value to the registry */ ObDereferenceObject(WinStaObject); - return TRUE; + break; } case SPI_SETWORKAREA: { @@ -1226,8 +1228,9 @@ IntSystemParametersInfo( ASSERT(pvParam); rc = (RECT*)pvParam; Desktop->WorkArea = *rc; + bChanged = TRUE; - return TRUE; + break; } case SPI_GETWORKAREA: { @@ -1242,13 +1245,14 @@ IntSystemParametersInfo( ASSERT(pvParam); IntGetDesktopWorkArea(Desktop, (PRECT)pvParam); - return TRUE; + break; } case SPI_SETGRADIENTCAPTIONS: { GradientCaptions = (pvParam != NULL); /* FIXME - should be checked if the color depth is higher than 8bpp? */ - return TRUE; + bChanged = TRUE; + break; } case SPI_GETGRADIENTCAPTIONS: { @@ -1256,78 +1260,83 @@ IntSystemParametersInfo( BOOL Ret = GradientCaptions; hDC = IntGetScreenDC(); - if(hDC) + if(!hDC) { - Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && Ret; - - ASSERT(pvParam); - *((PBOOL)pvParam) = Ret; - return TRUE; + return FALSE; } - return FALSE; + Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && Ret; + + ASSERT(pvParam); + *((PBOOL)pvParam) = Ret; + break; } case SPI_SETFONTSMOOTHING: { IntEnableFontRendering(uiParam != 0); - return TRUE; + bChanged = TRUE; + break; } case SPI_GETFONTSMOOTHING: { ASSERT(pvParam); *((BOOL*)pvParam) = IntIsFontRenderingEnabled(); - return TRUE; + break; } case SPI_GETICONTITLELOGFONT: { ASSERT(pvParam); *((LOGFONTW*)pvParam) = IconFont; - return TRUE; + break; } case SPI_GETNONCLIENTMETRICS: { ASSERT(pvParam); *((NONCLIENTMETRICSW*)pvParam) = pMetrics; - return TRUE; + break; } case SPI_SETNONCLIENTMETRICS: { ASSERT(pvParam); pMetrics = *((NONCLIENTMETRICSW*)pvParam); - return TRUE; + bChanged = TRUE; + break; } case SPI_GETMINIMIZEDMETRICS: { ASSERT(pvParam); *((MINIMIZEDMETRICS*)pvParam) = MinimizedMetrics; - return TRUE; + break; } case SPI_SETMINIMIZEDMETRICS: { ASSERT(pvParam); MinimizedMetrics = *((MINIMIZEDMETRICS*)pvParam); - return TRUE; + bChanged = TRUE; + break; } case SPI_GETFOCUSBORDERHEIGHT: { ASSERT(pvParam); *((UINT*)pvParam) = FocusBorderHeight; - return TRUE; + break; } case SPI_GETFOCUSBORDERWIDTH: { ASSERT(pvParam); *((UINT*)pvParam) = FocusBorderWidth; - return TRUE; + break; } case SPI_SETFOCUSBORDERHEIGHT: { FocusBorderHeight = (UINT)pvParam; - return TRUE; + bChanged = TRUE; + break; } case SPI_SETFOCUSBORDERWIDTH: { FocusBorderWidth = (UINT)pvParam; - return TRUE; + bChanged = TRUE; + break; } default: @@ -1337,7 +1346,18 @@ IntSystemParametersInfo( return FALSE; } } - return FALSE; + /* Did we change something ? */ + if (bChanged) + { + /* Shall we send a WM_SETTINGCHANGE message ? */ + if (fWinIni & (SPIF_UPDATEINIFILE | SPIF_SENDCHANGE)) + { + /* Broadcast WM_SETTINGCHANGE to all toplevel windows */ + /* FIXME: lParam should be pointer to a string containing the reg key */ + UserPostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)uiAction, 0); + } + } + return TRUE; } /* @@ -1396,14 +1416,14 @@ UserSystemParametersInfo( case SPI_GETGRADIENTCAPTIONS: case SPI_GETFOCUSBORDERHEIGHT: case SPI_GETFOCUSBORDERWIDTH: - case SPI_GETWHEELSCROLLLINES: + case SPI_GETWHEELSCROLLLINES: case SPI_GETWHEELSCROLLCHARS: - case SPI_GETSCREENSAVERRUNNING: - case SPI_SETSCREENSAVERRUNNING: - case SPI_GETSCREENSAVETIMEOUT: - case SPI_SETSCREENSAVETIMEOUT: - case SPI_GETSCREENSAVEACTIVE: - case SPI_GETFLATMENU: + case SPI_GETSCREENSAVERRUNNING: + case SPI_SETSCREENSAVERRUNNING: + case SPI_GETSCREENSAVETIMEOUT: + case SPI_SETSCREENSAVETIMEOUT: + case SPI_GETSCREENSAVEACTIVE: + case SPI_GETFLATMENU: case SPI_SETFLATMENU: { BOOL Ret; @@ -1529,10 +1549,10 @@ UserSystemParametersInfo( return( TRUE); } default : - { - DPRINT1("FIXME: UNIMPLEMENTED SPI Code: %lx \n",uiAction ); - break; - } + { + DPRINT1("FIXME: UNIMPLEMENTED SPI Code: %lx \n",uiAction ); + break; + } } return( FALSE); } From 98a086245c84c9fb7e28def80cd5bad75c2df49d Mon Sep 17 00:00:00 2001 From: Peter Ward Date: Thu, 11 Jan 2007 14:47:50 +0000 Subject: [PATCH 21/36] - Applied patch for "Invalid Sync after loading BLUE.SYS (bootCD-dbg)". - See issue http://www.reactos.org/bugzilla/show_bug.cgi?id=1953 - Patch by Dmitry G. Gorbachev (hto at mail cnt dot ru). svn path=/trunk/; revision=25425 --- reactos/drivers/base/blue/blue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/drivers/base/blue/blue.c b/reactos/drivers/base/blue/blue.c index 6ef84ffb709..2b1743cb4fd 100644 --- a/reactos/drivers/base/blue/blue.c +++ b/reactos/drivers/base/blue/blue.c @@ -109,7 +109,7 @@ static const VGA_REGISTERS VidpMode3Regs = /* Sequencer Registers */ {0x03, 0x00, 0x03, 0x00, 0x02}, /* Misc Output Register */ - 0xE3 + 0x67 }; static const UCHAR DefaultPalette[] = From c093c9b6b5614c6c193a07b04b0b55edd56d25ce Mon Sep 17 00:00:00 2001 From: Peter Ward Date: Thu, 11 Jan 2007 15:22:04 +0000 Subject: [PATCH 22/36] - Fix a couple of typos, patch by GreyGhost. svn path=/trunk/; revision=25426 --- reactos/base/applications/cacls/lang/en-US.rc | 2 +- reactos/base/applications/imagesoft/lang/en-US.rc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/reactos/base/applications/cacls/lang/en-US.rc b/reactos/base/applications/cacls/lang/en-US.rc index dfc4b4b2325..4ccd5c5b88b 100644 --- a/reactos/base/applications/cacls/lang/en-US.rc +++ b/reactos/base/applications/cacls/lang/en-US.rc @@ -24,7 +24,7 @@ CACLS filename [/T] [/E] [/C] [/G user:perm [...]] [/R user [...]]\n\ C Change (write)\n\ F Full control\n\ /D user Deny specified user access.\n\ -Wildcards can be used to specify more that one file in a command.\n\ +Wildcards can be used to specify more than one file in a command.\n\ You can specify more than one user in a command.\n\n\ Abbreviations:\n\ CI - Container Inherit.\n\ diff --git a/reactos/base/applications/imagesoft/lang/en-US.rc b/reactos/base/applications/imagesoft/lang/en-US.rc index 7e8272c1b16..a7718967e96 100644 --- a/reactos/base/applications/imagesoft/lang/en-US.rc +++ b/reactos/base/applications/imagesoft/lang/en-US.rc @@ -171,7 +171,7 @@ END STRINGTABLE DISCARDABLE BEGIN IDS_IMAGE_MONOCHROME "Monochrome (1 bit)" - IDS_IMAGE_GREYSCALE "Greyscale (8 bit)" + IDS_IMAGE_GREYSCALE "Grayscale (8 bit)" IDS_IMAGE_PALETTE "Palette or 256 color (8 bit)" IDS_IMAGE_TRUECOLOR "True color (24 bit)" From 44592e4e76c79546f1a58d4b062900515bde6e5c Mon Sep 17 00:00:00 2001 From: Christoph von Wittich Date: Thu, 11 Jan 2007 20:32:20 +0000 Subject: [PATCH 23/36] added a dependencymap backend (it doesn't do anything yet) svn path=/trunk/; revision=25429 --- .../rbuild/backend/codeblocks/codeblocks.cpp | 2 +- .../backend/dependencymap/dependencymap.cpp | 127 ++++++++++++++++++ .../backend/dependencymap/dependencymap.h | 57 ++++++++ reactos/tools/rbuild/rbuild.mak | 33 ++++- 4 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 reactos/tools/rbuild/backend/dependencymap/dependencymap.cpp create mode 100644 reactos/tools/rbuild/backend/dependencymap/dependencymap.h diff --git a/reactos/tools/rbuild/backend/codeblocks/codeblocks.cpp b/reactos/tools/rbuild/backend/codeblocks/codeblocks.cpp index 09b1b7ead42..8e935cd6655 100644 --- a/reactos/tools/rbuild/backend/codeblocks/codeblocks.cpp +++ b/reactos/tools/rbuild/backend/codeblocks/codeblocks.cpp @@ -747,7 +747,7 @@ CBBackend::_generate_cbproj ( const Module& module ) else if ( extension == ".idl" || extension == ".IDL" ) { fprintf ( OUT, "\t\t\t