Implemented many console & registry functions to get registry explorer running.
authorCasper Hornstrup <chorns@users.sourceforge.net>
Sat, 1 Sep 2001 15:36:45 +0000 (15:36 +0000)
committerCasper Hornstrup <chorns@users.sourceforge.net>
Sat, 1 Sep 2001 15:36:45 +0000 (15:36 +0000)
Load services from registry - part 1 (disabled due to bug in registry).

svn path=/trunk/; revision=2216

23 files changed:
reactos/Makefile
reactos/include/csrss/csrss.h
reactos/include/ddk/rtl.h
reactos/include/debug.h
reactos/lib/advapi32/reg/reg.c
reactos/lib/kernel32/misc/console.c
reactos/lib/ntdll/rtl/registry.c
reactos/ntoskrnl/cm/ntfunc.c
reactos/ntoskrnl/cm/regfile.c
reactos/ntoskrnl/cm/rtlfunc.c
reactos/ntoskrnl/include/internal/io.h
reactos/ntoskrnl/include/internal/ldr.h
reactos/ntoskrnl/include/internal/registry.h
reactos/ntoskrnl/io/create.c
reactos/ntoskrnl/io/device.c
reactos/ntoskrnl/io/pnpmgr.c
reactos/ntoskrnl/io/pnproot.c
reactos/ntoskrnl/ke/main.c
reactos/ntoskrnl/ldr/loader.c
reactos/subsys/csrss/api.h
reactos/subsys/csrss/api/conio.c
reactos/subsys/csrss/api/process.c
reactos/subsys/csrss/api/wapi.c

index 70f82b1..5bcdcc7 100644 (file)
@@ -492,6 +492,7 @@ install_dirs:
 install_before:
        $(CP) boot.bat $(INSTALL_DIR)/boot.bat
        $(CP) aboot.bat $(INSTALL_DIR)/aboot.bat
+       $(CP) boot.hiv $(INSTALL_DIR)/system32/boot.hiv
        $(CP) media/fonts/helb____.ttf $(INSTALL_DIR)/media/fonts/helb____.ttf
        $(CP) media/fonts/timr____.ttf $(INSTALL_DIR)/media/fonts/timr____.ttf
 
index 2eb6209..c6a76a7 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __INCLUDE_CSRSS_CSRSS_H
 #define __INCLUDE_CSRSS_CSRSS_H
 
+#include <windows.h>
 #include <napi/lpc.h>
 #include <ddk/ntddblue.h>
 #include <ntos/keyboard.h>
@@ -215,6 +216,36 @@ typedef struct
   WCHAR Title[1];
 } CSRSS_GET_TITLE_REPLY, *PCSRSS_GET_TITLE_REPLY;
 
+typedef struct
+{
+  HANDLE ConsoleHandle;
+  COORD BufferSize;
+  COORD BufferCoord;
+  SMALL_RECT WriteRegion;
+  CHAR_INFO CharInfo[0];
+} CSRSS_WRITE_CONSOLE_OUTPUT_REQUEST, *PCSRSS_WRITE_CONSOLE_OUTPUT_REQUEST;
+
+typedef struct
+{
+  SMALL_RECT WriteRegion;
+} CSRSS_WRITE_CONSOLE_OUTPUT_REPLY, *PCSRSS_WRITE_CONSOLE_OUTPUT_REPLY;
+
+typedef struct
+{
+   HANDLE ConsoleInput;
+} CSRSS_FLUSH_INPUT_BUFFER_REQUEST, *PCSRSS_FLUSH_INPUT_BUFFER_REQUEST;
+
+typedef struct
+{
+   HANDLE     ConsoleHandle;
+   SMALL_RECT ScrollRectangle;
+   BOOLEAN    UseClipRectangle;
+        SMALL_RECT ClipRectangle;
+        COORD      DestinationOrigin;
+   CHAR_INFO  Fill;
+} CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER_REQUEST, *PCSRSS_SCROLL_CONSOLE_SCREEN_BUFFER_REQUEST;
+
+
 #define CSRSS_MAX_WRITE_CONSOLE_REQUEST       (MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_WRITE_CONSOLE_REQUEST))
 
 #define CSRSS_MAX_SET_TITLE_REQUEST           (MAX_MESSAGE_DATA - sizeof( HANDLE ) - sizeof( DWORD ) - sizeof( ULONG ) - sizeof( LPC_MESSAGE_HEADER ))
@@ -228,29 +259,33 @@ typedef struct
 // FIXME: it should be 80. Is this a limit due to LPC msg size?
 #define CSRSS_MAX_TITLE_LENGTH          50
 
-#define CSRSS_CREATE_PROCESS            (0x0)
-#define CSRSS_TERMINATE_PROCESS         (0x1)
-#define CSRSS_WRITE_CONSOLE             (0x2)
-#define CSRSS_READ_CONSOLE              (0x3)
-#define CSRSS_ALLOC_CONSOLE             (0x4)
-#define CSRSS_FREE_CONSOLE              (0x5)
-#define CSRSS_CONNECT_PROCESS           (0x6)
-#define CSRSS_SCREEN_BUFFER_INFO        (0x7)
-#define CSRSS_SET_CURSOR                (0x8)
-#define CSRSS_FILL_OUTPUT               (0x9)
-#define CSRSS_READ_INPUT                (0xA)
-#define CSRSS_WRITE_CONSOLE_OUTPUT_CHAR (0xB)
-#define CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB (0xC)
-#define CSRSS_FILL_OUTPUT_ATTRIB        (0xD)
-#define CSRSS_GET_CURSOR_INFO           (0xE)
-#define CSRSS_SET_CURSOR_INFO           (0xF)
-#define CSRSS_SET_ATTRIB                (0x10)
-#define CSRSS_GET_MODE                  (0x11)
-#define CSRSS_SET_MODE                  (0x12)
-#define CSRSS_CREATE_SCREEN_BUFFER      (0x13)
-#define CSRSS_SET_SCREEN_BUFFER         (0x14)
-#define CSRSS_SET_TITLE                 (0x15)
-#define CSRSS_GET_TITLE                 (0x16)
+#define CSRSS_CREATE_PROCESS                (0x0)
+#define CSRSS_TERMINATE_PROCESS             (0x1)
+#define CSRSS_WRITE_CONSOLE                 (0x2)
+#define CSRSS_READ_CONSOLE                  (0x3)
+#define CSRSS_ALLOC_CONSOLE                 (0x4)
+#define CSRSS_FREE_CONSOLE                  (0x5)
+#define CSRSS_CONNECT_PROCESS               (0x6)
+#define CSRSS_SCREEN_BUFFER_INFO            (0x7)
+#define CSRSS_SET_CURSOR                    (0x8)
+#define CSRSS_FILL_OUTPUT                   (0x9)
+#define CSRSS_READ_INPUT                    (0xA)
+#define CSRSS_WRITE_CONSOLE_OUTPUT_CHAR     (0xB)
+#define CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB   (0xC)
+#define CSRSS_FILL_OUTPUT_ATTRIB            (0xD)
+#define CSRSS_GET_CURSOR_INFO               (0xE)
+#define CSRSS_SET_CURSOR_INFO               (0xF)
+#define CSRSS_SET_ATTRIB                    (0x10)
+#define CSRSS_GET_MODE                      (0x11)
+#define CSRSS_SET_MODE                      (0x12)
+#define CSRSS_CREATE_SCREEN_BUFFER          (0x13)
+#define CSRSS_SET_SCREEN_BUFFER             (0x14)
+#define CSRSS_SET_TITLE                     (0x15)
+#define CSRSS_GET_TITLE                     (0x16)
+#define CSRSS_WRITE_CONSOLE_OUTPUT          (0x17)
+#define CSRSS_FLUSH_INPUT_BUFFER            (0x18)
+#define CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER  (0x19)
+
 
 typedef struct
 {
@@ -268,7 +303,7 @@ typedef struct
        CSRSS_READ_INPUT_REQUEST ReadInputRequest;
        CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST WriteConsoleOutputCharRequest;
        CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REQUEST WriteConsoleOutputAttribRequest;
-               CSRSS_FILL_OUTPUT_ATTRIB_REQUEST FillOutputAttribRequest;
+  CSRSS_FILL_OUTPUT_ATTRIB_REQUEST FillOutputAttribRequest;
        CSRSS_SET_CURSOR_INFO_REQUEST SetCursorInfoRequest;
        CSRSS_GET_CURSOR_INFO_REQUEST GetCursorInfoRequest;
        CSRSS_SET_ATTRIB_REQUEST SetAttribRequest;
@@ -276,8 +311,11 @@ typedef struct
        CSRSS_GET_CONSOLE_MODE_REQUEST GetConsoleModeRequest;
        CSRSS_CREATE_SCREEN_BUFFER_REQUEST CreateScreenBufferRequest;
        CSRSS_SET_ACTIVE_SCREEN_BUFFER_REQUEST SetActiveScreenBufferRequest;
-        CSRSS_SET_TITLE_REQUEST SetTitleRequest;
-        CSRSS_GET_TITLE_REQUEST GetTitleRequest;
+  CSRSS_SET_TITLE_REQUEST SetTitleRequest;
+  CSRSS_GET_TITLE_REQUEST GetTitleRequest;
+  CSRSS_WRITE_CONSOLE_OUTPUT_REQUEST WriteConsoleOutputRequest;
+  CSRSS_FLUSH_INPUT_BUFFER_REQUEST FlushInputBufferRequest;
+  CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER_REQUEST ScrollConsoleScreenBufferRequest;
      } Data;
 } CSRSS_API_REQUEST, *PCSRSS_API_REQUEST;
 
@@ -299,9 +337,9 @@ typedef struct
        CSRSS_GET_CURSOR_INFO_REPLY GetCursorInfoReply;
        CSRSS_GET_CONSOLE_MODE_REPLY GetConsoleModeReply;
        CSRSS_CREATE_SCREEN_BUFFER_REPLY CreateScreenBufferReply;
-        CSRSS_GET_TITLE_REPLY GetTitleReply;
+  CSRSS_GET_TITLE_REPLY GetTitleReply;
+  CSRSS_WRITE_CONSOLE_OUTPUT_REPLY WriteConsoleOutputReply;
      } Data;
 } CSRSS_API_REPLY, *PCSRSS_API_REPLY;
 
 #endif /* __INCLUDE_CSRSS_CSRSS_H */
-
index 9048b30..2dfc505 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: rtl.h,v 1.56 2001/08/03 17:07:56 ekohl Exp $
+/* $Id: rtl.h,v 1.57 2001/09/01 15:36:43 chorns Exp $
  * 
  */
 
@@ -190,7 +190,8 @@ typedef struct _RTL_QUERY_REGISTRY_TABLE
 #define RTL_REGISTRY_WINDOWS_NT 3
 #define RTL_REGISTRY_DEVICEMAP  4
 #define RTL_REGISTRY_USER       5
-#define RTL_REGISTRY_MAXIMUM    6
+#define RTL_REGISTRY_ENUM       6   // ReactOS specific: Used internally in kernel only
+#define RTL_REGISTRY_MAXIMUM    7
 
 #define RTL_REGISTRY_HANDLE     0x40000000
 #define RTL_REGISTRY_OPTIONAL   0x80000000
@@ -230,6 +231,15 @@ extern BOOLEAN NLS_MB_CODE_PAGE_TAG;
 extern BOOLEAN NLS_MB_OEM_CODE_PAGE_TAG;
 
 
+/*
+ * NOTE: ReactOS extensions
+ */
+#define RtlMin(X,Y) (((X) < (Y))? (X) : (Y))
+#define RtlMax(X,Y) (((X) > (Y))? (X) : (Y))
+#define RtlMin3(X,Y,Z) (((X) < (Y)) ? RtlMin(X,Z) : RtlMin(Y,Z))
+#define RtlMax3(X,Y,Z) (((X) > (Y)) ? RtlMax(X,Z) : RtlMax(Y,Z))
+
+
 /*
  * VOID
  * InitializeObjectAttributes (
index a3395b3..75d8798 100644 (file)
@@ -24,7 +24,7 @@
 #endif
 
 #ifndef NASSERT
-#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); }
+#define assert(x) if (!(x)) {RtlAssert("#x",__FILE__,__LINE__, ""); }
 #else
 #define assert(x)
 #endif
index d363d9c..b5d6022 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: reg.c,v 1.12 2001/07/01 17:54:07 ekohl Exp $
+/* $Id: reg.c,v 1.13 2001/09/01 15:36:43 chorns Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
 #define NDEBUG
 #include <debug.h>
 
+#define CHECK_STATUS \
+{ \
+       if (!NT_SUCCESS(Status)) \
+       { \
+               LONG _ErrorCode = RtlNtStatusToDosError(Status); \
+               SetLastError(_ErrorCode); \
+               return _ErrorCode; \
+       } \
+}
+
 /* GLOBALS *******************************************************************/
 
 #define MAX_DEFAULT_HANDLES   6
@@ -38,6 +48,12 @@ static NTSTATUS OpenCurrentConfigKey(PHANDLE KeyHandle);
 
 /* FUNCTIONS *****************************************************************/
 
+inline RegiTerminateWideString(LPWSTR String, DWORD Length)
+{
+  LPWSTR AfterString = String + Length;
+  *AfterString = 0;
+}
+
 /************************************************************************
  *     RegInitDefaultHandles
  */
@@ -741,8 +757,80 @@ RegEnumKeyExA(
        PFILETIME       lpftLastWriteTime
        )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  WCHAR Name[MAX_PATH+1];
+  UNICODE_STRING UnicodeStringName;
+  WCHAR Class[MAX_PATH+1];
+  UNICODE_STRING UnicodeStringClass;
+  ANSI_STRING AnsiString;
+  LONG ErrorCode;
+  DWORD NameLength;
+  DWORD ClassLength;
+
+  DPRINT("hKey 0x%x  dwIndex %d  lpName 0x%x  *lpcbName %d  lpClass 0x%x  lpcbClass %d\n",
+    hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass);
+
+  if ((lpClass) && (!lpcbClass))
+  {
+       SetLastError(ERROR_INVALID_PARAMETER);
+         return ERROR_INVALID_PARAMETER;
+  }
+
+  RtlInitUnicodeString(&UnicodeStringName, NULL);
+  UnicodeStringName.Buffer = &Name[0];
+  UnicodeStringName.MaximumLength = sizeof(Name);
+
+  RtlInitUnicodeString(&UnicodeStringClass, NULL);
+
+  if (lpClass)
+  {
+    UnicodeStringClass.Buffer = &Class[0];
+    UnicodeStringClass.MaximumLength = sizeof(Class);
+    ClassLength = *lpcbClass;
+  }
+  else
+  {
+    ClassLength = 0;
+  }
+
+  NameLength = *lpcbName;
+
+  ErrorCode = RegEnumKeyExW(
+         hKey,
+         dwIndex,
+         UnicodeStringName.Buffer,
+         &NameLength,
+    lpReserved,
+         UnicodeStringClass.Buffer,
+         &ClassLength,
+         lpftLastWriteTime);
+
+  if (ErrorCode != ERROR_SUCCESS)
+    return ErrorCode;
+
+  UnicodeStringName.Length = NameLength * sizeof(WCHAR);
+  UnicodeStringClass.Length = ClassLength * sizeof(WCHAR);
+
+  RtlInitAnsiString(&AnsiString, NULL);
+  AnsiString.Buffer = lpName;
+  AnsiString.MaximumLength = *lpcbName;
+  RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringName, FALSE);
+  *lpcbName = AnsiString.Length;
+
+  DPRINT("Key Namea0 Length %d\n", UnicodeStringName.Length);
+  DPRINT("Key Namea1 Length %d\n", NameLength);
+  DPRINT("Key Namea Length %d\n", *lpcbName);
+  DPRINT("Key Namea %s\n", lpName);
+
+  if (lpClass)
+  {
+    RtlInitAnsiString(&AnsiString, NULL);
+    AnsiString.Buffer = lpClass;
+    AnsiString.MaximumLength = *lpcbClass;
+    RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringClass, FALSE);
+    *lpcbClass = AnsiString.Length;
+  }
+
+  return ERROR_SUCCESS;
 }
 
 
@@ -762,65 +850,95 @@ RegEnumKeyExW(
        PFILETIME       lpftLastWriteTime
        )
 {
-       PKEY_NODE_INFORMATION KeyInfo;
+  PKEY_NODE_INFORMATION KeyInfo;
        NTSTATUS Status;
        DWORD dwError = ERROR_SUCCESS;
        ULONG BufferSize;
        ULONG ResultSize;
-       HANDLE KeyHandle;
+  HANDLE KeyHandle;
 
-       Status = MapDefaultKey(&KeyHandle,
-                              hKey);
+  Status = MapDefaultKey(&KeyHandle, hKey);
        if (!NT_SUCCESS(Status))
        {
                dwError = RtlNtStatusToDosError(Status);
-
                SetLastError (dwError);
                return dwError;
        }
 
-       BufferSize = sizeof (KEY_NODE_INFORMATION) +
-               *lpcbName * sizeof(WCHAR);
+       BufferSize = sizeof (KEY_NODE_INFORMATION) + *lpcbName * sizeof(WCHAR);
        if (lpClass)
                BufferSize += *lpcbClass;
-       KeyInfo = RtlAllocateHeap (RtlGetProcessHeap(),
-                                  0,
-                                  BufferSize);
-       if (KeyInfo == NULL)
-               return ERROR_OUTOFMEMORY;
-
-       Status = NtEnumerateKey (KeyHandle,
-                                (ULONG)dwIndex,
-                                KeyNodeInformation,
-                                KeyInfo,
-                                BufferSize,
-                                &ResultSize);
-       if (!NT_SUCCESS(Status))
-       {
-               dwError = RtlNtStatusToDosError(Status);
-               
-               SetLastError(dwError);
-       }
-       else
-       {
-               memcpy (lpName, KeyInfo->Name, KeyInfo->NameLength);
-               *lpcbName = (DWORD)(KeyInfo->NameLength / sizeof(WCHAR)) - 1;
+       KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
+
+  /* We don't know the exact size of the data returned, so call
+     NtEnumerateKey() with a buffer size determined from parameters
+     to this function. If that call fails with a status code of
+     STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
+  while (TRUE) {
+    KeyInfo = RtlAllocateHeap(
+      RtlGetProcessHeap(),
+               0,
+               BufferSize);
+         if (KeyInfo == NULL)
+    {
+      SetLastError(ERROR_OUTOFMEMORY);
+               return ERROR_OUTOFMEMORY;
+    }
 
-               if (lpClass)
-               {
-                       memcpy (lpClass,
-                               KeyInfo->Name + KeyInfo->ClassOffset,
-                               KeyInfo->ClassLength);
-                       *lpcbClass = (DWORD)(KeyInfo->ClassLength / sizeof(WCHAR)) - 1;
-               }
+         Status = NtEnumerateKey(
+      KeyHandle,
+               (ULONG)dwIndex,
+               KeyNodeInformation,
+               KeyInfo,
+               BufferSize,
+               &ResultSize);
 
-               if (lpftLastWriteTime)
-               {
+    DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
 
-               }
-       }
+    if (Status == STATUS_BUFFER_OVERFLOW)
+    {
+         RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
+      BufferSize = ResultSize;
+      continue;
+    }
 
-       RtlFreeHeap (RtlGetProcessHeap(), 0, KeyInfo);
+    if (!NT_SUCCESS(Status))
+         {
+               dwError = RtlNtStatusToDosError(Status);
+               SetLastError(dwError);
+      break;
+         }
+         else
+         {
+      if ((lpClass) && (*lpcbClass != 0) && (KeyInfo->ClassLength > *lpcbClass))
+      {
+                 dwError = ERROR_MORE_DATA;
+                 SetLastError(dwError);
+        break;
+      }
+
+      RtlMoveMemory(lpName, KeyInfo->Name, KeyInfo->NameLength);
+                 *lpcbName = (DWORD)(KeyInfo->NameLength / sizeof(WCHAR));
+      RegiTerminateWideString(lpName, *lpcbName);
+
+                 if (lpClass)
+                 {
+                       RtlMoveMemory(lpClass,
+                               (PVOID)((ULONG_PTR)KeyInfo->Name + KeyInfo->ClassOffset),
+                               KeyInfo->ClassLength);
+                       *lpcbClass = (DWORD)(KeyInfo->ClassLength / sizeof(WCHAR));
+                 }
+
+                 if (lpftLastWriteTime)
+                 {
+        /* FIXME: Fill lpftLastWriteTime */
+                 }
+
+      break;
+       }
+  }
+
+  RtlFreeHeap (RtlGetProcessHeap(), 0, KeyInfo);
 
        return dwError;
 }
@@ -867,8 +985,40 @@ RegEnumValueA(
        LPDWORD lpcbData
        )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  WCHAR ValueName[MAX_PATH+1];
+  UNICODE_STRING UnicodeString;
+  ANSI_STRING AnsiString;
+  LONG ErrorCode;
+  DWORD ValueNameLength;
+
+  RtlInitUnicodeString(&UnicodeString, NULL);
+  UnicodeString.Buffer = &ValueName[0];
+  UnicodeString.MaximumLength = sizeof(ValueName);
+
+  ValueNameLength = *lpcbValueName;
+
+  ErrorCode = RegEnumValueW(
+         hKey,
+         dwIndex,
+         UnicodeString.Buffer,
+         &ValueNameLength,
+         lpReserved,
+         lpType,
+         lpData,
+         lpcbData);
+
+  if (ErrorCode != ERROR_SUCCESS)
+    return ErrorCode;
+
+  UnicodeString.Length = ValueNameLength * sizeof(WCHAR);
+
+  RtlInitAnsiString(&AnsiString, NULL);
+  AnsiString.Buffer = lpValueName;
+  AnsiString.MaximumLength = *lpcbValueName;
+  RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
+  *lpcbValueName = AnsiString.Length;
+
+  return ERROR_SUCCESS;
 }
 
 
@@ -896,44 +1046,76 @@ RegEnumValueW(
 
        BufferSize = sizeof (KEY_VALUE_FULL_INFORMATION) +
                *lpcbValueName * sizeof(WCHAR);
-       if (lpcbData)
+  if (lpcbData)
                BufferSize += *lpcbData;
-       ValueInfo = RtlAllocateHeap (RtlGetProcessHeap(),
-                                    0,
-                                    BufferSize);
-       if (ValueInfo == NULL)
-               return ERROR_OUTOFMEMORY;
 
-       Status = NtEnumerateValueKey (hKey,
-                                     (ULONG)dwIndex,
-                                     KeyValueFullInformation,
-                                     ValueInfo,
-                                     BufferSize,
-                                     &ResultSize);
-       if (!NT_SUCCESS(Status))
-       {
-               dwError = RtlNtStatusToDosError(Status);
-               
-               SetLastError(dwError);
-       }
-       else
-       {
-               memcpy (lpValueName, ValueInfo->Name, ValueInfo->NameLength);
-               *lpcbValueName = (DWORD)(ValueInfo->NameLength / sizeof(WCHAR)) - 1;
-
-               if (lpType)
-                       *lpType = ValueInfo->Type;
-
-               if (lpData)
-               {
-                       memcpy (lpData,
-                               ValueInfo->Name + ValueInfo->DataOffset,
-                               ValueInfo->DataLength);
-                       *lpcbValueName = (DWORD)ValueInfo->DataLength;
-               }
-       }
+  /* We don't know the exact size of the data returned, so call
+     NtEnumerateValueKey() with a buffer size determined from parameters
+     to this function. If that call fails with a status code of
+     STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
+  while (TRUE) {
+    ValueInfo = RtlAllocateHeap(
+      RtlGetProcessHeap(),
+               0,
+               BufferSize);
+         if (ValueInfo == NULL)
+    {
+      SetLastError(ERROR_OUTOFMEMORY);
+               return ERROR_OUTOFMEMORY;
+    }
+
+         Status = NtEnumerateValueKey(
+      hKey,
+               (ULONG)dwIndex,
+               KeyValueFullInformation,
+               ValueInfo,
+               BufferSize,
+               &ResultSize);
+
+    DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
+
+    if (Status == STATUS_BUFFER_OVERFLOW)
+    {
+         RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
+      BufferSize = ResultSize;
+      continue;
+    }
 
-       RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo);
+    if (!NT_SUCCESS(Status))
+         {
+               dwError = RtlNtStatusToDosError(Status);
+               SetLastError(dwError);
+      break;
+         }
+         else
+         {
+      if ((lpData) && (*lpcbData != 0) && (ValueInfo->DataLength > *lpcbData))
+      {
+                 dwError = ERROR_MORE_DATA;
+                 SetLastError(dwError);
+        break;
+      }
+
+      memcpy(lpValueName, ValueInfo->Name, ValueInfo->NameLength);
+               *lpcbValueName = (DWORD)(ValueInfo->NameLength / sizeof(WCHAR));
+      RegiTerminateWideString(lpValueName, *lpcbValueName);
+
+               if (lpType)
+                       *lpType = ValueInfo->Type;
+
+               if (lpData)
+               {
+                       memcpy(lpData,
+                               (PVOID)((ULONG_PTR)ValueInfo->Name + ValueInfo->DataOffset),
+                               ValueInfo->DataLength);
+                       *lpcbData = (DWORD)ValueInfo->DataLength;
+               }
+
+      break;
+       }
+  }
+
+  RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo);
 
        return dwError;
 }
@@ -982,11 +1164,12 @@ LONG
 STDCALL
 RegGetKeySecurity (
        HKEY                    hKey,
-       SECURITY_INFORMATION    SecurityInformation,    /* FIXME: ULONG ? */
+       SECURITY_INFORMATION    SecurityInformation,
        PSECURITY_DESCRIPTOR    pSecurityDescriptor,
        LPDWORD                 lpcbSecurityDescriptor
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -1003,6 +1186,7 @@ RegLoadKey(
        LPCSTR  lpFile
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -1037,6 +1221,7 @@ RegNotifyChangeKeyValue(
        BOOL    fAsynchronous
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -1270,8 +1455,43 @@ RegQueryInfoKeyA(
        PFILETIME       lpftLastWriteTime
        )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  WCHAR ClassName[MAX_PATH];
+  UNICODE_STRING UnicodeString;
+  ANSI_STRING AnsiString;
+  LONG ErrorCode;
+
+  RtlInitUnicodeString(&UnicodeString, NULL);
+
+  if (lpClass)
+  {
+    UnicodeString.Buffer = &ClassName[0];
+    UnicodeString.MaximumLength = sizeof(ClassName);
+  }
+
+  ErrorCode = RegQueryInfoKeyW(
+         hKey,
+         UnicodeString.Buffer,
+         lpcbClass,
+         lpReserved,
+         lpcSubKeys,
+         lpcbMaxSubKeyLen,
+         lpcbMaxClassLen,
+         lpcValues,
+         lpcbMaxValueNameLen,
+         lpcbMaxValueLen,
+         lpcbSecurityDescriptor,
+         lpftLastWriteTime);
+
+  if ((ErrorCode == ERROR_SUCCESS) && (lpClass))
+  {
+    RtlInitAnsiString(&AnsiString, NULL);
+    AnsiString.Buffer = lpClass;
+    AnsiString.MaximumLength = *lpcbClass;
+    RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
+    *lpcbClass = AnsiString.Length;
+  }
+
+  return ErrorCode;
 }
 
 
@@ -1295,8 +1515,113 @@ RegQueryInfoKeyW(
        PFILETIME       lpftLastWriteTime
        )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  KEY_FULL_INFORMATION FullInfoBuffer;
+  PKEY_FULL_INFORMATION FullInfo;
+  ULONG FullInfoSize;
+  HANDLE KeyHandle;
+  NTSTATUS Status;
+  LONG ErrorCode;
+  ULONG Length;
+
+  if ((lpClass) && (!lpcbClass))
+  {
+       SetLastError(ERROR_INVALID_PARAMETER);
+         return ERROR_INVALID_PARAMETER;
+  }
+
+  Status = MapDefaultKey(&KeyHandle, hKey);
+  CHECK_STATUS;
+
+  if (lpClass)
+  {
+    FullInfoSize = sizeof(KEY_FULL_INFORMATION) + *lpcbClass;
+    FullInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullInfoSize);
+    if (!FullInfo)
+    {
+                 SetLastError(ERROR_OUTOFMEMORY);
+                 return ERROR_OUTOFMEMORY;
+       }
+
+    FullInfo->ClassLength = *lpcbClass;
+  }
+  else
+  {
+    FullInfoSize = sizeof(KEY_FULL_INFORMATION);
+    FullInfo = &FullInfoBuffer;
+    FullInfo->ClassLength = 1;
+  }
+
+  FullInfo->ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
+
+  Status = NtQueryKey(
+    KeyHandle,
+    KeyFullInformation,
+    FullInfo,
+    FullInfoSize,
+    &Length);
+
+  if (!NT_SUCCESS(Status))
+       {
+    if (lpClass)
+    {
+      RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo);
+    }
+
+               ErrorCode = RtlNtStatusToDosError(Status);
+               SetLastError(ErrorCode);
+               return ErrorCode;
+       }
+
+  if (lpcSubKeys)
+  {
+    *lpcSubKeys = FullInfo->SubKeys;
+  }
+
+  if (lpcbMaxSubKeyLen)
+  {
+    *lpcbMaxSubKeyLen = FullInfo->MaxNameLen;
+  }
+
+  if (lpcbMaxClassLen)
+  {
+    *lpcbMaxClassLen = FullInfo->MaxClassLen;
+  }
+
+  if (lpcValues)
+  {
+    *lpcValues = FullInfo->Values;
+  }
+
+  if (lpcbMaxValueNameLen)
+  {
+    *lpcbMaxValueNameLen = FullInfo->MaxValueNameLen;
+  }
+
+  if (lpcbMaxValueLen)
+  {
+    *lpcbMaxValueLen = FullInfo->MaxValueDataLen;
+  }
+
+  if (lpcbSecurityDescriptor)
+  {
+    *lpcbSecurityDescriptor = 0;
+    /* FIXME */
+  }
+
+  if (lpftLastWriteTime != NULL)
+  {
+    lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
+    lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
+  }
+
+  if (lpClass)
+  {
+    wcsncpy(lpClass, FullInfo->Class, *lpcbClass);
+    RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo);
+  }
+
+  SetLastError(ERROR_SUCCESS);
+       return ERROR_SUCCESS;
 }
 
 
@@ -1313,6 +1638,7 @@ RegQueryMultipleValuesA(
        LPDWORD ldwTotsize
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -1331,6 +1657,7 @@ RegQueryMultipleValuesW(
        LPDWORD ldwTotsize
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -1348,8 +1675,69 @@ RegQueryValueA(
        PLONG   lpcbValue
        )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  WCHAR SubKeyNameBuffer[MAX_PATH+1];
+  UNICODE_STRING SubKeyName;
+  UNICODE_STRING Value;
+  ANSI_STRING AnsiString;
+  LONG ValueSize;
+  LONG ErrorCode;
+
+  if ((lpValue) && (!lpcbValue))
+  {
+       SetLastError(ERROR_INVALID_PARAMETER);
+         return ERROR_INVALID_PARAMETER;
+  }
+
+  RtlInitUnicodeString(&SubKeyName, NULL);
+  RtlInitUnicodeString(&Value, NULL);
+
+  if ((lpSubKey) && (strlen(lpSubKey) != 0))
+  {
+    RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey);
+    SubKeyName.Buffer = &SubKeyNameBuffer[0];
+    SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
+    RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE);
+  }
+
+  if (lpValue)
+  {
+    ValueSize = *lpcbValue * sizeof(WCHAR);
+    Value.MaximumLength = ValueSize;
+    Value.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, ValueSize);
+    if (!Value.Buffer)
+    {
+           SetLastError(ERROR_OUTOFMEMORY);
+           return ERROR_OUTOFMEMORY;
+    }
+  }
+  else
+  {
+    ValueSize = 0;
+  }
+
+  ErrorCode = RegQueryValueW(
+       hKey,
+       (LPCWSTR)SubKeyName.Buffer,
+       Value.Buffer,
+       &ValueSize);
+
+  if (ErrorCode == ERROR_SUCCESS)
+  {
+    Value.Length = ValueSize;
+    RtlInitAnsiString(&AnsiString, NULL);
+    AnsiString.Buffer = lpValue;
+    AnsiString.MaximumLength = *lpcbValue;
+    RtlUnicodeStringToAnsiString(&AnsiString, &Value, FALSE);
+  }
+
+  *lpcbValue = ValueSize; 
+
+  if (Value.Buffer)
+  {
+    RtlFreeHeap(RtlGetProcessHeap(), 0, Value.Buffer);
+  }
+
+  return ErrorCode;
 }
 
 
@@ -1367,8 +1755,93 @@ RegQueryValueExA(
        LPDWORD lpcbData
        )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  WCHAR ValueNameBuffer[MAX_PATH+1];
+  UNICODE_STRING ValueName;
+  UNICODE_STRING ValueData;
+  ANSI_STRING AnsiString;
+  LONG ErrorCode;
+  DWORD ResultSize;
+  DWORD        Type;
+
+  /* FIXME: HKEY_PERFORMANCE_DATA is special, see MS SDK */
+
+  if ((lpData) && (!lpcbData))
+  {
+       SetLastError(ERROR_INVALID_PARAMETER);
+         return ERROR_INVALID_PARAMETER;
+  }
+
+  RtlInitUnicodeString(&ValueData, NULL);
+
+  if (lpData)
+  {
+    ValueData.MaximumLength = *lpcbData * sizeof(WCHAR);
+         ValueData.Buffer = RtlAllocateHeap(
+      RtlGetProcessHeap(),
+      0,
+      ValueData.MaximumLength);
+         if (!ValueData.Buffer)
+    {
+      SetLastError(ERROR_OUTOFMEMORY);
+               return ERROR_OUTOFMEMORY;
+    }
+  }
+
+  RtlInitAnsiString(&AnsiString, (LPSTR)lpValueName);
+  RtlInitUnicodeString(&ValueName, NULL);
+  ValueName.Buffer = &ValueNameBuffer[0];
+  ValueName.MaximumLength = sizeof(ValueNameBuffer);
+  RtlAnsiStringToUnicodeString(&ValueName, &AnsiString, FALSE);
+
+  if (lpcbData)
+  {
+    ResultSize = *lpcbData;
+  }
+  else
+  {
+    ResultSize = 0;
+  }
+
+  ErrorCode = RegQueryValueExW(
+         hKey,
+         ValueName.Buffer,
+         lpReserved,
+         &Type,
+         (LPBYTE)ValueData.Buffer,
+         &ResultSize);
+
+  if ((ErrorCode == ERROR_SUCCESS) && (ValueData.Buffer != NULL))
+  {
+    if (lpType)
+    {
+      *lpType = Type;
+    }
+
+    if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ))
+    {
+      ValueData.Length = ResultSize;
+      RtlInitAnsiString(&AnsiString, NULL);
+      AnsiString.Buffer = lpData;
+      AnsiString.MaximumLength = *lpcbData;
+      RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE);
+    }
+    else
+    {
+      RtlMoveMemory(lpData, ValueData.Buffer, ResultSize);
+    }
+  }
+
+  if (lpcbData)
+  {
+    *lpcbData = ResultSize;
+  }
+
+  if (ValueData.Buffer)
+  {
+    RtlFreeHeap(RtlGetProcessHeap(), 0, ValueData.Buffer);
+  }
+
+  return ErrorCode;
 }
 
 
@@ -1393,6 +1866,15 @@ RegQueryValueExW(
        ULONG BufferSize;
        ULONG ResultSize;
 
+  DPRINT("hKey 0x%X  lpValueName %S  lpData 0x%X  lpcbData %d\n",
+    hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
+
+  if ((lpData) && (!lpcbData))
+  {
+       SetLastError(ERROR_INVALID_PARAMETER);
+         return ERROR_INVALID_PARAMETER;
+  }
+
        RtlInitUnicodeString (&ValueName,
                              lpValueName);
 
@@ -1401,7 +1883,10 @@ RegQueryValueExW(
                                     0,
                                     BufferSize);
        if (ValueInfo == NULL)
+  {
+    SetLastError(ERROR_OUTOFMEMORY);
                return ERROR_OUTOFMEMORY;
+  }
 
        Status = NtQueryValueKey (hKey,
                                  &ValueName,
@@ -1409,22 +1894,40 @@ RegQueryValueExW(
                                  ValueInfo,
                                  BufferSize,
                                  &ResultSize);
-       if (!NT_SUCCESS(Status))
+
+  DPRINT("Status 0x%X\n", Status);
+
+  if (Status == STATUS_BUFFER_TOO_SMALL)
+  {
+    /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
+    dwError = ERROR_SUCCESS;
+  }
+  else if (!NT_SUCCESS(Status))
        {
                dwError = RtlNtStatusToDosError(Status);
-               
                SetLastError(dwError);
        }
        else
        {
-               *lpType = ValueInfo->Type;
-               memcpy (lpData, ValueInfo->Data, ValueInfo->DataLength);
-               if (ValueInfo->Type == REG_SZ)
+    if (lpType)
+    {
+           *lpType = ValueInfo->Type;
+    }
+
+               RtlMoveMemory(lpData, ValueInfo->Data, ValueInfo->DataLength);
+    if ((ValueInfo->Type == REG_SZ) ||
+      (ValueInfo->Type == REG_MULTI_SZ) ||
+      (ValueInfo->Type == REG_EXPAND_SZ))
+    {
                        ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
+    }
        }
+
+  DPRINT("Type %d  ResultSize %d\n", ValueInfo->Type, ResultSize);
+
        *lpcbData = (DWORD)ResultSize;
 
-       RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo);
+       RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
 
        return dwError;
 }
@@ -1442,8 +1945,67 @@ RegQueryValueW(
        PLONG   lpcbValue
        )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+       NTSTATUS                errCode;
+       UNICODE_STRING          SubKeyString;
+       OBJECT_ATTRIBUTES       ObjectAttributes;
+       HANDLE                  KeyHandle;
+  HANDLE                       RealKey;
+       LONG                      ErrorCode;
+  BOOL        CloseRealKey;
+
+       errCode = MapDefaultKey(&KeyHandle, hKey);
+       if (!NT_SUCCESS(errCode))
+       {
+               ErrorCode = RtlNtStatusToDosError(errCode);
+               SetLastError (ErrorCode);
+               return ErrorCode;
+       }
+
+  if ((lpSubKey) && (wcslen(lpSubKey) != 0))
+  {
+
+         RtlInitUnicodeString(&SubKeyString,
+                            (LPWSTR)lpSubKey);
+
+         InitializeObjectAttributes(&ObjectAttributes,
+                                  &SubKeyString,
+                                  OBJ_CASE_INSENSITIVE,
+                                  KeyHandle,
+                                  NULL);
+
+         errCode = NtOpenKey(
+                       &RealKey,
+                       KEY_ALL_ACCESS,
+                       & ObjectAttributes
+                       );
+         if ( !NT_SUCCESS(errCode) )
+         {
+               ErrorCode = RtlNtStatusToDosError(errCode);
+               SetLastError(ErrorCode);
+               return ErrorCode;
+         }
+    CloseRealKey = TRUE;
+  }
+  else
+  {
+    RealKey = hKey;
+    CloseRealKey = FALSE;
+  }
+
+  ErrorCode = RegQueryValueExW(
+         RealKey,
+         NULL,
+         NULL,
+         NULL,
+         (LPBYTE)lpValue,
+         (LPDWORD)lpcbValue);
+
+  if (CloseRealKey)
+  {
+    NtClose(RealKey);
+  }
+
+  return ErrorCode;
 }
 
 
@@ -1459,6 +2021,7 @@ RegReplaceKeyA(
        LPCSTR  lpOldFile
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -1476,6 +2039,7 @@ RegReplaceKeyW(
        LPCWSTR lpOldFile
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -1492,6 +2056,7 @@ RegRestoreKeyA(
        DWORD   dwFlags
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -1508,6 +2073,7 @@ RegRestoreKeyW(
        DWORD   dwFlags
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -1524,6 +2090,7 @@ RegSaveKeyA(
        LPSECURITY_ATTRIBUTES   lpSecurityAttributes
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -1540,6 +2107,7 @@ RegSaveKeyW(
        LPSECURITY_ATTRIBUTES   lpSecurityAttributes
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -1556,6 +2124,7 @@ RegSetKeySecurity(
        PSECURITY_DESCRIPTOR    pSecurityDescriptor
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -1574,8 +2143,49 @@ RegSetValueA(
        DWORD   cbData
        )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  WCHAR SubKeyNameBuffer[MAX_PATH+1];
+  UNICODE_STRING SubKeyName;
+  UNICODE_STRING Data;
+  ANSI_STRING AnsiString;
+  LONG DataSize;
+  LONG ErrorCode;
+
+  if (!lpData)
+  {
+       SetLastError(ERROR_INVALID_PARAMETER);
+         return ERROR_INVALID_PARAMETER;
+  }
+
+  RtlInitUnicodeString(&SubKeyName, NULL);
+  RtlInitUnicodeString(&Data, NULL);
+
+  if ((lpSubKey) && (strlen(lpSubKey) != 0))
+  {
+    RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey);
+    SubKeyName.Buffer = &SubKeyNameBuffer[0];
+    SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
+    RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE);
+  }
+
+  DataSize = cbData * sizeof(WCHAR);
+  Data.MaximumLength = DataSize;
+  Data.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, DataSize);
+  if (!Data.Buffer)
+  {
+         SetLastError(ERROR_OUTOFMEMORY);
+         return ERROR_OUTOFMEMORY;
+  }
+
+  ErrorCode = RegSetValueW(
+         hKey,
+         (LPCWSTR)SubKeyName.Buffer,
+         dwType,
+         Data.Buffer,
+         DataSize);
+
+  RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer);
+
+  return ErrorCode;
 }
 
 
@@ -1593,8 +2203,66 @@ RegSetValueExA(
        DWORD           cbData
        )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNICODE_STRING ValueName;
+  LPWSTR pValueName;
+  ANSI_STRING AnsiString;
+  UNICODE_STRING Data;
+  LONG ErrorCode;
+  LPBYTE pData;
+  DWORD DataSize;
+
+  if (!lpData)
+  {
+       SetLastError(ERROR_INVALID_PARAMETER);
+         return ERROR_INVALID_PARAMETER;
+  }
+
+  if ((lpValueName) && (strlen(lpValueName) != 0))
+  {
+    RtlCreateUnicodeStringFromAsciiz(&ValueName, (LPSTR)lpValueName);
+    pValueName = (LPWSTR)ValueName.Buffer;
+  }
+  else
+  {
+    pValueName = NULL;
+  }
+
+  if ((dwType == REG_SZ) || (dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ))
+  {
+    RtlInitAnsiString(&AnsiString, NULL);
+    AnsiString.Buffer = (LPSTR)lpData;
+    AnsiString.Length = cbData;
+    AnsiString.MaximumLength = cbData;
+    RtlAnsiStringToUnicodeString(&Data, &AnsiString, TRUE);
+    pData = (LPBYTE)Data.Buffer;
+    DataSize = cbData * sizeof(WCHAR);
+  }
+  else
+  {
+    RtlInitUnicodeString(&Data, NULL);
+    pData = (LPBYTE)lpData;
+    DataSize = cbData;
+  }
+
+  ErrorCode = RegSetValueExW(
+         hKey,
+         pValueName,
+         Reserved,
+         dwType,
+    pData,
+         DataSize);
+
+  if (pValueName)
+  {
+    RtlFreeHeap(RtlGetProcessHeap(), 0, ValueName.Buffer);
+  }
+
+  if (Data.Buffer)
+  {
+    RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer);
+  }
+
+  return ErrorCode;
 }
 
 
@@ -1613,21 +2281,39 @@ RegSetValueExW(
        )
 {
        UNICODE_STRING ValueName;
+  PUNICODE_STRING pValueName;
+  HANDLE KeyHandle;
        NTSTATUS Status;
+  LONG ErrorCode;
 
-       RtlInitUnicodeString (&ValueName,
-                             lpValueName);
+  Status = MapDefaultKey(&KeyHandle, hKey);
+       if (!NT_SUCCESS(Status))
+       {
+               ErrorCode = RtlNtStatusToDosError(Status);
+               SetLastError(ErrorCode);
+               return ErrorCode;
+       }
 
-       Status = NtSetValueKey (hKey,
-                               &ValueName,
-                               0,
-                               dwType,
-                               (PVOID)lpData,
-                               (ULONG)cbData);
+  if (lpValueName)
+  {
+         RtlInitUnicodeString(&ValueName, lpValueName);
+    pValueName = &ValueName;
+  }
+  else
+  {
+    pValueName = NULL;
+  }
+
+       Status = NtSetValueKey(
+    KeyHandle,
+         pValueName,
+               0,
+               dwType,
+               (PVOID)lpData,
+               (ULONG)cbData);
        if (!NT_SUCCESS(Status))
        {
                LONG ErrorCode = RtlNtStatusToDosError(Status);
-
                SetLastError (ErrorCode);
                return ErrorCode;
        }
@@ -1649,8 +2335,67 @@ RegSetValueW(
        DWORD   cbData
        )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+       NTSTATUS                errCode;
+       UNICODE_STRING          SubKeyString;
+       OBJECT_ATTRIBUTES       ObjectAttributes;
+       HANDLE                  KeyHandle;
+  HANDLE                       RealKey;
+       LONG                      ErrorCode;
+  BOOL        CloseRealKey;
+
+       errCode = MapDefaultKey(&KeyHandle, hKey);
+       if (!NT_SUCCESS(errCode))
+       {
+               ErrorCode = RtlNtStatusToDosError(errCode);
+               SetLastError (ErrorCode);
+               return ErrorCode;
+       }
+
+  if ((lpSubKey) && (wcslen(lpSubKey) != 0))
+  {
+
+         RtlInitUnicodeString(&SubKeyString,
+                            (LPWSTR)lpSubKey);
+
+         InitializeObjectAttributes(&ObjectAttributes,
+                                  &SubKeyString,
+                                  OBJ_CASE_INSENSITIVE,
+                                  KeyHandle,
+                                  NULL);
+
+         errCode = NtOpenKey(
+                       &RealKey,
+                       KEY_ALL_ACCESS,
+                       & ObjectAttributes
+                       );
+         if ( !NT_SUCCESS(errCode) )
+         {
+               ErrorCode = RtlNtStatusToDosError(errCode);
+               SetLastError(ErrorCode);
+               return ErrorCode;
+         }
+    CloseRealKey = TRUE;
+  }
+  else
+  {
+    RealKey = hKey;
+    CloseRealKey = FALSE;
+  }
+
+  ErrorCode = RegSetValueExW(
+         RealKey,
+         NULL,
+         0,
+         dwType,
+    (LPBYTE)lpData,
+         cbData);
+
+  if (CloseRealKey)
+  {
+    NtClose(RealKey);
+  }
+
+  return ErrorCode;
 }
 
 
@@ -1664,6 +2409,7 @@ RegUnLoadKeyA(
        LPCSTR  lpSubKey
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -1679,6 +2425,7 @@ RegUnLoadKeyW(
        LPCWSTR lpSubKey
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
index bf05053..00b2dfa 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: console.c,v 1.34 2001/08/14 12:57:15 ea Exp $
+/* $Id: console.c,v 1.35 2001/09/01 15:36:43 chorns Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -978,6 +978,7 @@ ReadConsoleInputA(
 {
    CSRSS_API_REQUEST Request;
    CSRSS_API_REPLY Reply;
+   DWORD NumEventsRead;
    NTSTATUS Status;
 
    Request.Type = CSRSS_READ_INPUT;
@@ -988,23 +989,54 @@ ReadConsoleInputA(
         SetLastErrorByStatus ( Status );
         return FALSE;
       }
-   while( Status == STATUS_PENDING )
+
+   while (Status == STATUS_PENDING)
       {
-        Status = NtWaitForSingleObject( Reply.Data.ReadInputReply.Event, FALSE, 0 );
+
+   Status = NtWaitForSingleObject( Reply.Data.ReadInputReply.Event, FALSE, 0 );
         if( !NT_SUCCESS( Status ) )
            {
               SetLastErrorByStatus ( Status );
               return FALSE;
            }
+
+   Request.Type = CSRSS_READ_INPUT;
+   Request.Data.ReadInputRequest.ConsoleHandle = hConsoleInput;
+   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
+   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
+      {
+        SetLastErrorByStatus ( Status );
+        return FALSE;
+      }
+      }
+
+   NumEventsRead = 0;
+   *lpBuffer = Reply.Data.ReadInputReply.Input;
+   lpBuffer++;
+   NumEventsRead++;
+
+   while( ( NumEventsRead < nLength ) && ( Reply.Data.ReadInputReply.MoreEvents ) )
+      {
+
         Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
         if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
            {
               SetLastErrorByStatus ( Status );
               return FALSE;
            }
-      }
-   *lpNumberOfEventsRead = 1;
+
+   if( Status == STATUS_PENDING )
+           {
+         break;
+           }
+
    *lpBuffer = Reply.Data.ReadInputReply.Input;
+   lpBuffer++;
+   NumEventsRead++;
+
+      }
+   *lpNumberOfEventsRead = NumEventsRead;
+
    return TRUE;
 }
 
@@ -1114,8 +1146,37 @@ WriteConsoleOutputA(
        PSMALL_RECT      lpWriteRegion
        )
 {
-/* TO DO */
-       return FALSE;
+   PCSRSS_API_REQUEST Request;
+   CSRSS_API_REPLY Reply;
+   NTSTATUS Status;
+   DWORD Size;
+
+   Size = dwBufferSize.Y * dwBufferSize.X * sizeof(CHAR_INFO);
+
+   Request = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CSRSS_API_REQUEST) + Size);
+   if( !Request )
+     {
+       SetLastError( ERROR_OUTOFMEMORY );
+       return FALSE;
+     }
+   Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT;
+   Request->Data.WriteConsoleOutputRequest.ConsoleHandle = hConsoleOutput;
+   Request->Data.WriteConsoleOutputRequest.BufferSize = dwBufferSize;
+   Request->Data.WriteConsoleOutputRequest.BufferCoord = dwBufferCoord;
+   Request->Data.WriteConsoleOutputRequest.WriteRegion = *lpWriteRegion;
+   RtlCopyMemory(&Request->Data.WriteConsoleOutputRequest.CharInfo, lpBuffer, Size);
+
+   Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + Size, sizeof( CSRSS_API_REPLY ) );
+        if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
+           {
+         RtlFreeHeap( GetProcessHeap(), 0, Request );
+              SetLastErrorByStatus ( Status );
+              return FALSE;
+           }
+
+   *lpWriteRegion = Reply.Data.WriteConsoleOutputReply.WriteRegion;
+
+   return TRUE;
 }
 
 
@@ -1237,6 +1298,7 @@ WriteConsoleOutputCharacterA(
         Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + Size, sizeof( CSRSS_API_REPLY ) );
         if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
            {
+         RtlFreeHeap( GetProcessHeap(), 0, Request );
               SetLastErrorByStatus ( Status );
               return FALSE;
            }
@@ -1310,6 +1372,7 @@ WriteConsoleOutputAttribute(
         Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + (Size * 2), sizeof( CSRSS_API_REPLY ) );
         if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
            {
+         RtlFreeHeap( GetProcessHeap(), 0, Request );
               SetLastErrorByStatus ( Status );
               return FALSE;
            }
@@ -1437,6 +1500,7 @@ GetConsoleCursorInfo(
    Request.Type = CSRSS_GET_CURSOR_INFO;
    Request.Data.GetCursorInfoRequest.ConsoleHandle = hConsoleOutput;
    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
+
    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
       {
         SetLastErrorByStatus ( Status );
@@ -1526,8 +1590,19 @@ FlushConsoleInputBuffer(
        HANDLE          hConsoleInput
        )
 {
-/* TO DO */
-       return FALSE;
+   CSRSS_API_REQUEST Request;
+   CSRSS_API_REPLY Reply;
+   NTSTATUS Status;
+
+   Request.Type = CSRSS_FLUSH_INPUT_BUFFER;
+   Request.Data.FlushInputBufferRequest.ConsoleInput = hConsoleInput;
+   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
+   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
+      {
+        SetLastErrorByStatus ( Status );
+        return FALSE;
+      }
+   return TRUE;
 }
 
 
@@ -1565,6 +1640,7 @@ SetConsoleCursorInfo(
    Request.Data.SetCursorInfoRequest.ConsoleHandle = hConsoleOutput;
    Request.Data.SetCursorInfoRequest.Info = *lpConsoleCursorInfo;
    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
+
    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
       {
         SetLastErrorByStatus ( Status );
@@ -1588,8 +1664,34 @@ ScrollConsoleScreenBufferA(
        CONST CHAR_INFO         *lpFill
        )
 {
-/* TO DO */
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+
+  Request.Type = CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER;
+  Request.Data.ScrollConsoleScreenBufferRequest.ConsoleHandle = hConsoleOutput;
+  Request.Data.ScrollConsoleScreenBufferRequest.ScrollRectangle = *lpScrollRectangle;
+
+  if (lpClipRectangle != NULL)
+    {
+  Request.Data.ScrollConsoleScreenBufferRequest.UseClipRectangle = TRUE;
+  Request.Data.ScrollConsoleScreenBufferRequest.ClipRectangle = *lpClipRectangle;
+    }
+  else
+    {
+  Request.Data.ScrollConsoleScreenBufferRequest.UseClipRectangle = FALSE;
+    }
+
+  Request.Data.ScrollConsoleScreenBufferRequest.DestinationOrigin = dwDestinationOrigin;
+  Request.Data.ScrollConsoleScreenBufferRequest.Fill = *lpFill;
+  Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
+
+  if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
+    {
+  SetLastErrorByStatus ( Status );
        return FALSE;
+    }
+  return TRUE;
 }
 
 
index 223a3c8..c3aed9d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: registry.c,v 1.6 2001/06/19 15:08:46 ekohl Exp $
+/* $Id: registry.c,v 1.7 2001/09/01 15:36:43 chorns Exp $
  *
  * COPYRIGHT:         See COPYING in the top level directory
  * PROJECT:           ReactOS kernel
@@ -176,7 +176,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
          (QueryEntry->Name != NULL))
      {
        if ((QueryEntry->QueryRoutine == NULL) &&
-           (QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_DIRECT) != 0))
+           ((QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY) != 0))
          {
             Status = STATUS_INVALID_PARAMETER;
             break;
@@ -244,9 +244,14 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
                       ValueString = (PUNICODE_STRING)QueryEntry->EntryContext;
                       if (ValueString->Buffer == 0)
                         {
-                           /* FIXME: allocate buffer !!! */
-//                         ValueString->MaximumLength =
-//                         ValueString->Buffer =
+          RtlInitUnicodeString(ValueString, NULL);
+                           ValueString->MaximumLength = 256 * sizeof(WCHAR);
+                           ValueString->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+                                         0,
+                                         ValueString->MaximumLength);
+          if (!ValueString->Buffer)
+            break;
+          ValueString->Buffer[0] = 0;
                         }
                       ValueString->Length = min(ValueInfo->DataLength,
                                                 ValueString->MaximumLength - sizeof(WCHAR));
@@ -514,8 +519,15 @@ RtlpGetRegistryHandle(ULONG RelativeTo,
    
    if (RelativeTo & RTL_REGISTRY_HANDLE)
      {
-       *KeyHandle = (HANDLE)Path;
-       return STATUS_SUCCESS;
+   Status = NtDuplicateObject(
+      NtCurrentProcess(),
+      (HANDLE)Path,
+      NtCurrentProcess(),
+      KeyHandle,
+      0,
+      FALSE,
+      DUPLICATE_SAME_ACCESS);
+   return Status;
      }
 
    if (RelativeTo & RTL_REGISTRY_OPTIONAL)
@@ -561,6 +573,13 @@ RtlpGetRegistryHandle(ULONG RelativeTo,
          if (!NT_SUCCESS(Status))
            return Status;
          break;
+
+  /* ReactOS specific */
+  case RTL_REGISTRY_ENUM:
+         RtlAppendUnicodeToString(&KeyName,
+                      L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
+         break;
+
      }
 
    if (Path[0] != L'\\')
index 3edef3b..9f093c7 100644 (file)
@@ -264,8 +264,9 @@ NtEnumerateKey (
     {
     case KeyBasicInformation:
       /*  Check size of buffer  */
-      if (Length < sizeof(KEY_BASIC_INFORMATION) + 
-          (SubKeyBlock->NameSize ) * sizeof(WCHAR))
+      *ResultLength = sizeof(KEY_BASIC_INFORMATION) + 
+          (SubKeyBlock->NameSize ) * sizeof(WCHAR);
+      if (Length < *ResultLength)
         {
           Status = STATUS_BUFFER_OVERFLOW;
         }
@@ -281,16 +282,15 @@ NtEnumerateKey (
                   SubKeyBlock->Name, 
                   SubKeyBlock->NameSize*2);
 //          BasicInformation->Name[SubKeyBlock->NameSize] = 0;
-          *ResultLength = sizeof(KEY_BASIC_INFORMATION) + 
-            SubKeyBlock->NameSize * sizeof(WCHAR);
         }
       break;
       
     case KeyNodeInformation:
       /*  Check size of buffer  */
-      if (Length < sizeof(KEY_NODE_INFORMATION) +
+      *ResultLength = sizeof(KEY_NODE_INFORMATION) +
           (SubKeyBlock->NameSize ) * sizeof(WCHAR) +
-          (SubKeyBlock->ClassSize ))
+          (SubKeyBlock->ClassSize );
+      if (Length < *ResultLength)
         {
           Status = STATUS_BUFFER_OVERFLOW;
         }
@@ -318,16 +318,14 @@ NtEnumerateKey (
                       SubKeyBlock->ClassSize);
               CmiReleaseBlock(RegistryFile, pClassData);
             }
-          *ResultLength = sizeof(KEY_NODE_INFORMATION) +
-            (SubKeyBlock->NameSize) * sizeof(WCHAR) +
-            (SubKeyBlock->ClassSize );
         }
       break;
       
     case KeyFullInformation:
       /*  check size of buffer  */
-      if (Length < sizeof(KEY_FULL_INFORMATION) +
-          SubKeyBlock->ClassSize)
+      *ResultLength = sizeof(KEY_FULL_INFORMATION) +
+          SubKeyBlock->ClassSize;
+      if (Length < *ResultLength)
         {
           Status = STATUS_BUFFER_OVERFLOW;
         }
@@ -360,8 +358,6 @@ NtEnumerateKey (
                       SubKeyBlock->ClassSize);
               CmiReleaseBlock(RegistryFile, pClassData);
             }
-          *ResultLength = sizeof(KEY_FULL_INFORMATION) +
-            SubKeyBlock->ClassSize ;
         }
       break;
     }
@@ -873,6 +869,9 @@ NtQueryValueKey (
   PKEY_VALUE_FULL_INFORMATION  ValueFullInformation;
   char ValueName2[MAX_PATH];
 
+  DPRINT("NtQueryValueKey(KeyHandle %x  ValueName %S  Length %x )\n",
+    KeyHandle, ValueName->Buffer, Length);
+
   wcstombs(ValueName2,ValueName->Buffer,ValueName->Length>>1);
   ValueName2[ValueName->Length>>1]=0;
 
@@ -885,6 +884,7 @@ NtQueryValueKey (
                                      NULL);
   if (!NT_SUCCESS(Status))
     {
+      DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status);
       return  Status;
     }
 
@@ -898,6 +898,7 @@ NtQueryValueKey (
                               &ValueBlock,NULL);
   if (!NT_SUCCESS(Status))
     {
+      DPRINT("CmiScanKeyForValue() failed with status %x\n", Status);
       ObDereferenceObject(KeyObject);
       return  Status;
     }
@@ -910,7 +911,7 @@ NtQueryValueKey (
             ValueBlock->NameSize * sizeof(WCHAR);
           if (Length < *ResultLength)
             {
-              Status = STATUS_BUFFER_OVERFLOW;
+              Status = STATUS_BUFFER_TOO_SMALL;
             }
           else
             {
@@ -930,7 +931,7 @@ NtQueryValueKey (
             (ValueBlock->DataSize & LONG_MAX);
           if (Length < *ResultLength)
             {
-              Status = STATUS_BUFFER_OVERFLOW;
+              Status = STATUS_BUFFER_TOO_SMALL;
             }
           else
             {
@@ -962,7 +963,7 @@ NtQueryValueKey (
                  + (ValueBlock->DataSize & LONG_MAX);
           if (Length < *ResultLength)
             {
-              Status = STATUS_BUFFER_OVERFLOW;
+              Status = STATUS_BUFFER_TOO_SMALL;
             }
           else
             {
@@ -1001,7 +1002,7 @@ NtQueryValueKey (
     }
   else
     {
-      Status = STATUS_UNSUCCESSFUL;
+      Status = STATUS_OBJECT_NAME_NOT_FOUND;
     }
   ObDereferenceObject(KeyObject);
   
@@ -1031,6 +1032,9 @@ NtSetValueKey (
  PHEAP_BLOCK pHeap;
 // KIRQL  OldIrql;
 
+  DPRINT1("KeyHandle %x  ValueName %S  Type %d\n",
+    KeyHandle, ValueName->Buffer, Type);
+
   wcstombs(ValueName2,ValueName->Buffer,ValueName->Length>>1);
   ValueName2[ValueName->Length>>1]=0;
 
@@ -1041,6 +1045,7 @@ NtSetValueKey (
                                      UserMode,
                                      (PVOID *)&KeyObject,
                                      NULL);
+  DPRINT1("Status 0x%X\n", Status);
   if (!NT_SUCCESS(Status))
     return  Status;
 
@@ -1053,6 +1058,8 @@ NtSetValueKey (
                               &ValueBlock, &VBOffset);
   if (!NT_SUCCESS(Status))
   {
+    DPRINT1("Not found Status 0x%X\n", Status);
+
     ObDereferenceObject (KeyObject);
     return  Status;
   }
@@ -1067,6 +1074,7 @@ NtSetValueKey (
   }
   if (!NT_SUCCESS(Status))
   {
+    DPRINT1("Cannot Add Status 0x%X\n", Status);
     ObDereferenceObject (KeyObject);
     return  Status;
   }
@@ -1123,6 +1131,8 @@ NtSetValueKey (
 //  KeReleaseSpinLock(&RegistryFile->RegLock, OldIrql);
   ObDereferenceObject (KeyObject);
   
+  DPRINT1("Return Status 0x%X\n", Status);
+
   return  Status;
 }
 
index 8f684d4..1f91f99 100644 (file)
@@ -627,6 +627,7 @@ CmiScanKeyForValue(IN PREGISTRY_FILE  RegistryFile,
                    OUT PVALUE_BLOCK  *ValueBlock,
                   OUT BLOCK_OFFSET *VBOffset)
 {
+  ULONG Length;
  ULONG  Idx;
  PVALUE_LIST_BLOCK  ValueListBlock;
  PVALUE_BLOCK  CurValueBlock;
@@ -635,6 +636,7 @@ CmiScanKeyForValue(IN PREGISTRY_FILE  RegistryFile,
   *ValueBlock = NULL;
   if (ValueListBlock == NULL)
     {
+      DPRINT("ValueListBlock is NULL\n");
       return  STATUS_SUCCESS;
     }
   for (Idx = 0; Idx < KeyBlock->NumberOfValues; Idx++)
@@ -643,12 +645,14 @@ CmiScanKeyForValue(IN PREGISTRY_FILE  RegistryFile,
                                   ValueListBlock->Values[Idx],NULL);
       /* FIXME : perhaps we must not ignore case if NtCreateKey has not been */
       /*         called with OBJ_CASE_INSENSITIVE flag ? */
-      if (CurValueBlock != NULL &&
-          CurValueBlock->NameSize == strlen(ValueName) &&
-          !_strnicmp(CurValueBlock->Name, ValueName,strlen(ValueName)))
+      Length = strlen(ValueName);
+      if ((CurValueBlock != NULL) &&
+          (CurValueBlock->NameSize == Length) &&
+          (_strnicmp(CurValueBlock->Name, ValueName, Length) == 0))
         {
           *ValueBlock = CurValueBlock;
          if(VBOffset) *VBOffset = ValueListBlock->Values[Idx];
+        DPRINT("Found value %s\n", ValueName);
           break;
         }
       CmiReleaseBlock(RegistryFile, CurValueBlock);
index 3114f8e..859323d 100644 (file)
@@ -133,7 +133,151 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
                       IN PVOID Context,
                       IN PVOID Environment)
 {
-       UNIMPLEMENTED;
+   NTSTATUS Status;
+   HANDLE BaseKeyHandle;
+   HANDLE CurrentKeyHandle;
+   PRTL_QUERY_REGISTRY_TABLE QueryEntry;
+   OBJECT_ATTRIBUTES ObjectAttributes;
+   UNICODE_STRING KeyName;
+   PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
+   ULONG BufferSize;
+   ULONG ResultSize;
+   
+   DPRINT("RtlQueryRegistryValues() called\n");
+   
+   Status = RtlpGetRegistryHandle(RelativeTo,
+                                 Path,
+                                 FALSE,
+                                 &BaseKeyHandle);
+   if (!NT_SUCCESS(Status))
+    {
+      DPRINT("RtlpGetRegistryHandle() failed with status %x\n", Status);
+      return Status;
+    }
+
+   CurrentKeyHandle = BaseKeyHandle;
+   QueryEntry = QueryTable;
+   while ((QueryEntry->QueryRoutine != NULL) ||
+         (QueryEntry->Name != NULL))
+     {
+    //CSH: Was:
+    //if ((QueryEntry->QueryRoutine == NULL) &&
+         //  ((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_DIRECT)) != 0))
+    // Which is more correct?
+       if ((QueryEntry->QueryRoutine == NULL) &&
+           ((QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY) != 0))
+         {
+       DPRINT("Bad parameters\n");
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+         }
+
+       DPRINT("Name: %S\n", QueryEntry->Name);
+
+       if (((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_TOPKEY)) != 0) &&
+           (BaseKeyHandle != CurrentKeyHandle))
+         {
+            NtClose(CurrentKeyHandle);
+            CurrentKeyHandle = BaseKeyHandle;
+         }
+
+       if (QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY)
+         {
+            DPRINT("Open new subkey: %S\n", QueryEntry->Name);
+         
+            RtlInitUnicodeString(&KeyName,
+                                 QueryEntry->Name);
+            InitializeObjectAttributes(&ObjectAttributes,
+                                       &KeyName,
+                                       OBJ_CASE_INSENSITIVE,
+                                       BaseKeyHandle,
+                                       NULL);
+            Status = NtOpenKey(&CurrentKeyHandle,
+                               KEY_ALL_ACCESS,
+                               &ObjectAttributes);
+            if (!NT_SUCCESS(Status))
+              break;
+         }
+       else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DIRECT)
+         {
+            DPRINT("Query value directly: %S\n", QueryEntry->Name);
+         
+            RtlInitUnicodeString(&KeyName,
+                                 QueryEntry->Name);
+         
+            BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + 4096;
+            ValueInfo = ExAllocatePool(PagedPool, BufferSize);
+            if (ValueInfo == NULL)
+              {
+                 Status = STATUS_NO_MEMORY;
+                 break;
+              }
+
+            Status = ZwQueryValueKey(CurrentKeyHandle,
+                                     &KeyName,
+                                     KeyValuePartialInformation,
+                                     ValueInfo,
+                                     BufferSize,
+                                     &ResultSize);
+            if (!NT_SUCCESS(Status))
+              {
+      DPRINT("ZwQueryValueKey() failed with status %x\n", Status);
+                 ExFreePool(ValueInfo);
+                 break;
+              }
+            else
+              {
+                 if (ValueInfo->Type == REG_SZ)
+                   {
+                      PUNICODE_STRING ValueString;
+                      ValueString = (PUNICODE_STRING)QueryEntry->EntryContext;
+                      if (ValueString->Buffer == 0)
+                        {
+          RtlInitUnicodeString(ValueString, NULL);
+                           ValueString->MaximumLength = 256 * sizeof(WCHAR);
+                           ValueString->Buffer = ExAllocatePool(PagedPool, ValueString->MaximumLength);
+          if (!ValueString->Buffer)
+            break;
+          ValueString->Buffer[0] = 0;
+                        }
+                      ValueString->Length = RtlMin(ValueInfo->DataLength,
+                                                ValueString->MaximumLength - sizeof(WCHAR));
+                      memcpy(ValueString->Buffer,
+                             ValueInfo->Data,
+                             ValueInfo->DataLength);
+                       ((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0;
+                   }
+                 else
+                   {
+                      memcpy(QueryEntry->EntryContext,
+                             ValueInfo->Data,
+                             ValueInfo->DataLength);
+                   }
+              }
+
+            ExFreePool (ValueInfo);
+         }
+       else
+         {
+            DPRINT("Query value via query routine: %S\n", QueryEntry->Name);
+            
+         }
+
+       if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE)
+         {
+            DPRINT("Delete value: %S\n", QueryEntry->Name);
+            
+         }
+
+       QueryEntry++;
+     }
+
+   if (CurrentKeyHandle != BaseKeyHandle)
+     NtClose(CurrentKeyHandle);
+
+   NtClose(BaseKeyHandle);
+
+   return Status;
 }
 
 
@@ -197,8 +341,15 @@ RtlpGetRegistryHandle(ULONG RelativeTo,
 
    if (RelativeTo & RTL_REGISTRY_HANDLE)
      {
-       *KeyHandle = (HANDLE)Path;
-       return STATUS_SUCCESS;
+   Status = NtDuplicateObject(
+      PsGetCurrentProcessId(),
+      (PHANDLE)&Path,
+      PsGetCurrentProcessId(),
+      KeyHandle,
+      0,
+      FALSE,
+      DUPLICATE_SAME_ACCESS);
+   return Status;
      }
 
    if (RelativeTo & RTL_REGISTRY_OPTIONAL)
@@ -239,14 +390,25 @@ RtlpGetRegistryHandle(ULONG RelativeTo,
          if (!NT_SUCCESS(Status))
            return Status;
          break;
+
+  /* ReactOS specific */
+  case RTL_REGISTRY_ENUM:
+         RtlAppendUnicodeToString(&KeyName,
+                      L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
+    break;
      }
 
    if (Path[0] != L'\\')
-     RtlAppendUnicodeToString(&KeyName,
-                             L"\\");
-
-   RtlAppendUnicodeToString(&KeyName,
-                           Path);
+     {
+       RtlAppendUnicodeToString(&KeyName,
+                                Path);
+     }
+   else
+     {
+       Path++;
+       RtlAppendUnicodeToString(&KeyName,
+                                Path);
+     }
 
    InitializeObjectAttributes(&ObjectAttributes,
                              &KeyName,
@@ -273,3 +435,77 @@ RtlpGetRegistryHandle(ULONG RelativeTo,
 
    return Status;
 }
+
+
+NTSTATUS
+RtlpCreateRegistryKeyPath(PWSTR Path)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  WCHAR KeyBuffer[MAX_PATH];
+  UNICODE_STRING KeyName;
+  HANDLE KeyHandle;
+  NTSTATUS Status;
+  PWCHAR Current;
+  PWCHAR Next;
+
+  if (_wcsnicmp(Path, L"\\Registry\\", 10) != 0)
+    {
+   return STATUS_INVALID_PARAMETER;
+    }
+
+  wcsncpy(KeyBuffer, Path, MAX_PATH-1);
+  RtlInitUnicodeString(&KeyName, KeyBuffer);
+
+  /* Skip \\Registry\\ */
+  Current = KeyName.Buffer;
+  Current = wcschr(Current, '\\') + 1;
+  Current = wcschr(Current, '\\') + 1;
+
+  do {
+    Next = wcschr(Current, '\\');
+    if (Next == NULL)
+      {
+    /* The end */
+      }
+    else
+      {
+    *Next = 0;
+      }
+
+    InitializeObjectAttributes(
+      &ObjectAttributes,
+           &KeyName,
+           OBJ_CASE_INSENSITIVE,
+           NULL,
+           NULL);
+
+    DPRINT("Create '%S'\n", KeyName.Buffer);
+
+    Status = NtCreateKey(
+      &KeyHandle,
+      KEY_ALL_ACCESS,
+           &ObjectAttributes,
+           0,
+           NULL,
+           0,
+           NULL);
+    if (!NT_SUCCESS(Status))
+      {
+        DPRINT("NtCreateKey() failed with status %x\n", Status);
+        return Status;
+      }
+
+    NtClose(KeyHandle);
+
+    if (Next != NULL)
+      {
+    *Next = L'\\';
+      }
+
+    Current = Next + 1;
+  } while (Next != NULL);
+
+  return STATUS_SUCCESS;
+}
+
+/* EOF */
index 86f47cf..d7fca62 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: io.h,v 1.12 2001/08/26 17:25:29 ekohl Exp $
+/* $Id: io.h,v 1.13 2001/09/01 15:36:44 chorns Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -39,6 +39,7 @@ typedef struct _DEVICE_NODE
   struct _DEVICE_NODE *PrevSibling;
   struct _DEVICE_NODE *NextSibling;
   struct _DEVICE_NODE *Child;
+  PDRIVER_OBJECT DriverObject;
   PDEVICE_OBJECT Pdo;
   UNICODE_STRING InstancePath;
   UNICODE_STRING ServiceName;
@@ -54,26 +55,53 @@ typedef struct _DEVICE_NODE
 } DEVICE_NODE, *PDEVICE_NODE;
 
 /* For Flags field */
-#define DNF_MADEUP                              0x0001
-#define DNF_HAL_NODE                            0x0002
-#define DNF_PROCESSED                           0x0004
-#define DNF_ENUMERATED                          0x0008
-#define DNF_ADDED                               0x0010
-#define DNF_HAS_BOOT_CONFIG                     0x0020
-#define DNF_BOOT_CONFIG_RESERVED                0x0040
-#define DNF_RESOURCE_ASSIGNED                   0x0080
-#define DNF_NO_RESOURCE_REQUIRED                0x0100
-#define DNF_STARTED                             0x0200
-#define DNF_LEGACY_DRIVER                       0x0400
-#define DNF_RESOURCE_REQUIREMENTS_NEED_FILTERED 0x0800
-#define DNF_HAS_PROBLEM                         0x1000
+#define DNF_PROCESSED                           0x00000001
+#define DNF_STARTED                             0x00000002
+#define DNF_START_FAILED                        0x00000004
+#define DNF_ENUMERATED                          0x00000008
+#define DNF_DELETED                             0x00000010
+#define DNF_MADEUP                              0x00000020
+#define DNF_START_REQUEST_PENDING               0x00000040
+#define DNF_NO_RESOURCE_REQUIRED                0x00000080
+#define DNF_INSUFFICIENT_RESOURCES              0x00000100
+#define DNF_RESOURCE_ASSIGNED                   0x00000200
+#define DNF_RESOURCE_REPORTED                   0x00000400
+#define DNF_HAL_NODE                            0x00000800 // ???
+#define DNF_ADDED                               0x00001000
+#define DNF_ADD_FAILED                          0x00002000
+#define DNF_LEGACY_DRIVER                       0x00004000
+#define DNF_STOPPED                             0x00008000
+#define DNF_WILL_BE_REMOVED                     0x00010000
+#define DNF_NEED_TO_ENUM                        0x00020000
+#define DNF_NOT_CONFIGURED                      0x00040000
+#define DNF_REINSTALL                           0x00080000
+#define DNF_RESOURCE_REQUIREMENTS_NEED_FILTERED 0x00100000 // ???
+#define DNF_DISABLED                            0x00200000
+#define DNF_RESTART_OK                          0x00400000
+#define DNF_NEED_RESTART                        0x00800000
+#define DNF_VISITED                             0x01000000
+#define DNF_ASSIGNING_RESOURCES                 0x02000000
+#define DNF_BEEING_ENUMERATED                   0x04000000
+#define DNF_NEED_ENUMERATION_ONLY               0x08000000
+#define DNF_LOCKED                              0x10000000
+#define DNF_HAS_BOOT_CONFIG                     0x20000000
+#define DNF_BOOT_CONFIG_RESERVED                0x40000000
+#define DNF_HAS_PROBLEM                         0x80000000 // ???
 
 /* For UserFlags field */
 #define DNUF_DONT_SHOW_IN_UI    0x0002
 #define DNUF_NOT_DISABLEABLE    0x0008
 
 /* For Problem field */
-#define CM_PROB_FAILED_INSTALL  0x0001
+#define CM_PROB_NOT_CONFIGURED  1
+#define CM_PROB_FAILED_START    10
+#define CM_PROB_NORMAL_CONFLICT 12
+#define CM_PROB_NEED_RESTART    14
+#define CM_PROB_REINSTALL       18
+#define CM_PROB_WILL_BE_REMOVED 21
+#define CM_PROB_DISABLED        22
+#define CM_PROB_FAILED_INSTALL  28
+#define CM_PROB_FAILED_ADD      31
 
 extern PDEVICE_NODE IopRootDeviceNode;
 
@@ -109,10 +137,10 @@ IopLoadBootStartDrivers(VOID);
 NTSTATUS
 IopCreateDriverObject(PDRIVER_OBJECT *DriverObject);
 NTSTATUS
+IopInitializeDeviceNodeService(PDEVICE_NODE DeviceNode);
+NTSTATUS
 IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry,
-                    PDEVICE_NODE ParentDeviceNode,
-                    PUNICODE_STRING Filename,
-                    BOOLEAN BootDriversOnly);
+                    PDEVICE_NODE DeviceNode);
 VOID 
 IoInitCancelHandling(VOID);
 VOID 
@@ -168,4 +196,11 @@ NTSTATUS STDCALL IoPageWrite (PFILE_OBJECT         FileObject,
                              PLARGE_INTEGER            Offset,
                              PIO_STATUS_BLOCK  StatusBlock);
 
+NTSTATUS
+IopInitiatePnpIrp(
+  PDEVICE_OBJECT DeviceObject,
+  PIO_STATUS_BLOCK IoStatusBlock,
+  ULONG MinorFunction,
+  PIO_STACK_LOCATION Stack);
+
 #endif
index 1b79c9c..089cce2 100644 (file)
@@ -11,6 +11,7 @@
 #include <pe.h>
 #include <internal/io.h>
 #include <ntdll/ldr.h>
+#include <internal/module.h>
 
 NTSTATUS
 LdrLoadDriver (
@@ -90,6 +91,13 @@ PVOID LdrSafePEProcessModule(
        PVOID ImportModuleBase,
        PULONG DriverSize);
 
+PMODULE_OBJECT
+LdrLoadModule(PUNICODE_STRING Filename);
+
+NTSTATUS LdrFindModuleObject(
+  PUNICODE_STRING ModuleName,
+  PMODULE_OBJECT *ModuleObject);
+
 extern ULONG_PTR LdrHalBase;
 
 #endif /* __INCLUDE_INTERNAL_LDR_H */
index 1f521b2..1921071 100644 (file)
@@ -8,4 +8,7 @@ RtlpGetRegistryHandle(ULONG RelativeTo,
                      BOOLEAN Create,
                      PHANDLE KeyHandle);
 
+NTSTATUS
+RtlpCreateRegistryKeyPath(PWSTR Path);
+
 #endif /* __INCLUDE_INTERNAL_REGISTRY_H */
index ee8f1db..26dd5f2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: create.c,v 1.47 2001/08/26 17:27:00 ekohl Exp $
+/* $Id: create.c,v 1.48 2001/09/01 15:36:44 chorns Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -125,7 +125,6 @@ IopCreateFile(PVOID                 ObjectBody,
            && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
          {
             CPRINT ("Device was wrong type\n");
-            assert(FALSE);
             return (STATUS_UNSUCCESSFUL);
          }
 
index 7ba8ec4..06886b7 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: device.c,v 1.32 2001/08/30 20:38:19 dwelch Exp $
+/* $Id: device.c,v 1.33 2001/09/01 15:36:44 chorns Exp $
  *
  * COPYRIGHT:      See COPYING in the top level directory
  * PROJECT:        ReactOS kernel
@@ -19,6 +19,8 @@
 #include <internal/id.h>
 #include <internal/ps.h>
 #include <internal/pool.h>
+#include <internal/registry.h>
+
 #include <roscfg.h>
 
 #define NDEBUG
@@ -324,64 +326,24 @@ IopCreateDriverObject(PDRIVER_OBJECT *DriverObject)
   return STATUS_SUCCESS;
 }
 
+NTSTATUS
+IopAttachFilterDrivers(PDEVICE_NODE DeviceNode,
+                       BOOLEAN Lower)
+{
+  return STATUS_SUCCESS;
+}
+
 NTSTATUS 
-IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry,
-                    PDEVICE_NODE DeviceNode,
-                    PUNICODE_STRING Filename,
+IopInitializeDevice(PDEVICE_NODE DeviceNode,
                     BOOLEAN BootDriversOnly)
-/*
- * FUNCTION: Called to initalize a loaded driver
- * ARGUMENTS:
- */
 {
   IO_STATUS_BLOCK      IoStatusBlock;
   PDRIVER_OBJECT DriverObject;
-  PIO_STACK_LOCATION IrpSp;
+  IO_STACK_LOCATION Stack;
   PDEVICE_OBJECT Fdo;
   NTSTATUS Status;
-  KEVENT Event;
-  PIRP Irp;
-  WCHAR DriverName [MAX_PATH];
-  WCHAR RegistryKeyBuffer [MAX_PATH];
-  UNICODE_STRING  RegistryKey;
 
-  DPRINT("IopInitializeDriver (DriverEntry %08lx, DeviceNode %08lx, "
-    "BootDriversOnly %d)\n", DriverEntry, DeviceNode, BootDriversOnly);
-
-  Status = IopCreateDriverObject(&DriverObject);
-  if (!NT_SUCCESS(Status))
-    {
-  return(Status);
-    }
-
-  if (Filename != 0)
-  {
-    if (wcsrchr (Filename->Buffer, '\\') != 0)
-    {
-      wcscpy (DriverName, wcsrchr (Filename->Buffer, '\\'));
-    }
-    else
-    {
-      wcscpy (DriverName, Filename->Buffer);
-    }
-    if (wcsrchr (DriverName, '.') != 0)
-    {
-      *(wcsrchr (DriverName, '.')) = 0;
-    }
-    wcscpy (RegistryKeyBuffer, DRIVER_REGISTRY_KEY_BASENAME);
-    wcscpy (RegistryKeyBuffer, DriverName);
-    RtlInitUnicodeString (&RegistryKey, RegistryKeyBuffer);
-    DPRINT("RegistryKey: %wZ\n", &RegistryKey);
-  }
-
-  DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry);
-  Status = DriverEntry(DriverObject, Filename != 0 ? &RegistryKey : 0);
-  if (!NT_SUCCESS(Status))
-    {
-  ExFreePool(DriverObject->DriverExtension);
-       ExFreePool(DriverObject);
-       return(Status);
-    }
+  DriverObject = DeviceNode->DriverObject;
 
   if (DriverObject->DriverExtension->AddDevice)
     {
@@ -411,36 +373,18 @@ IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry,
           KeBugCheck(0);
         }
 
-      KeInitializeEvent(&Event,
-             NotificationEvent,
-             FALSE);
-
-      Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
-        Fdo,
-             NULL,
-             0,
-             NULL,
-             &Event,
-             &IoStatusBlock);
-
-      IrpSp = IoGetNextIrpStackLocation(Irp);
-      IrpSp->MinorFunction = IRP_MN_START_DEVICE;
-
       /* FIXME: Put some resources in the IRP for the device */
+      Stack.Parameters.StartDevice.AllocatedResources = NULL;
+      Stack.Parameters.StartDevice.AllocatedResourcesTranslated = NULL;
 
-           Status = IoCallDriver(Fdo, Irp);
-
-           if (Status == STATUS_PENDING)
-             {
-                     KeWaitForSingleObject(&Event,
-                                      Executive,
-                                      KernelMode,
-                                      FALSE,
-                                      NULL);
-          Status = IoStatusBlock.Status;
-             }
+      Status = IopInitiatePnpIrp(
+        Fdo,
+        &IoStatusBlock,
+        IRP_MN_START_DEVICE,
+        &Stack);
       if (!NT_SUCCESS(Status))
         {
+          DPRINT("IopInitiatePnpIrp() failed\n");
           ObDereferenceObject(Fdo);
           ExFreePool(DriverObject->DriverExtension);
                ExFreePool(DriverObject);
@@ -466,8 +410,7 @@ IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry,
 #ifdef ACPI
           static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
 
-          /* The system power device node is the first bus enumerator
-             device node created after the root device node */
+          /* There can be only one system power device */
           if (!SystemPowerDeviceNodeCreated)
             {
               PopSystemPowerDeviceNode = DeviceNode;
@@ -478,6 +421,143 @@ IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry,
       ObDereferenceObject(Fdo);
     }
 
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS
+IopInitializeService(
+  PDEVICE_NODE DeviceNode,
+  PUNICODE_STRING ImagePath)
+{
+  PMODULE_OBJECT ModuleObject;
+  NTSTATUS Status;
+
+  Status = LdrFindModuleObject(&DeviceNode->ServiceName, &ModuleObject);
+  if (!NT_SUCCESS(Status))
+  {
+    /* The module is currently not loaded, so load it now */
+
+    ModuleObject = LdrLoadModule(ImagePath);
+    if (!ModuleObject)
+    {
+      /* FIXME: Log the error */
+           CPRINT("Driver load failed\n");
+      return STATUS_UNSUCCESSFUL;
+    }
+
+    Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode);
+    if (!NT_SUCCESS(Status))
+    {
+      /* FIXME: Log the error */
+           CPRINT("A driver failed to initialize\n");
+      return Status;
+    }
+  }
+
+  ObDereferenceObject(ModuleObject);
+
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS
+IopInitializeDeviceNodeService(
+  PDEVICE_NODE DeviceNode)
+{
+  RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+  UNICODE_STRING ImagePath;
+  HANDLE KeyHandle;
+  NTSTATUS Status; 
+
+  Status = RtlpGetRegistryHandle(
+    RTL_REGISTRY_SERVICES,
+         DeviceNode->ServiceName.Buffer,
+               TRUE,
+               &KeyHandle);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status);
+  return Status;
+    }
+
+  RtlZeroMemory(QueryTable, sizeof(QueryTable));
+
+  RtlInitUnicodeString(&ImagePath, NULL);
+
+  QueryTable[0].Name = L"ImagePath";
+  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+  QueryTable[0].EntryContext = &ImagePath;
+
+  Status = RtlQueryRegistryValues(
+    RTL_REGISTRY_HANDLE,
+               (PWSTR)KeyHandle,
+               QueryTable,
+               NULL,
+               NULL);
+  NtClose(KeyHandle);
+
+  DPRINT("RtlQueryRegistryValues() returned status %x\n", Status);
+
+  if (NT_SUCCESS(Status))
+  {
+    DPRINT("Got ImagePath %S\n", ImagePath.Buffer);
+
+    Status = IopInitializeService(DeviceNode, &ImagePath);
+
+    RtlFreeUnicodeString(&ImagePath);
+  }
+
+  return Status;
+}
+
+NTSTATUS 
+IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry,
+                    PDEVICE_NODE DeviceNode)
+/*
+ * FUNCTION: Called to initalize a loaded driver
+ * ARGUMENTS:
+ */
+{
+  WCHAR RegistryKeyBuffer[MAX_PATH];
+  PDRIVER_OBJECT DriverObject;
+  UNICODE_STRING RegistryKey;
+  NTSTATUS Status;
+
+  DPRINT("IopInitializeDriver(DriverEntry %08lx, DeviceNode %08lx)\n",
+    DriverEntry, DeviceNode);
+
+  Status = IopCreateDriverObject(&DriverObject);
+  if (!NT_SUCCESS(Status))
+    {
+  return(Status);
+    }
+
+  DeviceNode->DriverObject = DriverObject;
+
+  if (DeviceNode->ServiceName.Buffer)
+  {
+    wcscpy(RegistryKeyBuffer, DRIVER_REGISTRY_KEY_BASENAME);
+    wcscat(RegistryKeyBuffer, DeviceNode->ServiceName.Buffer);
+    RtlInitUnicodeString(&RegistryKey, RegistryKeyBuffer);
+  }
+  else
+  {
+    RtlInitUnicodeString(&RegistryKey, NULL);
+  }
+
+  DPRINT("RegistryKey: %wZ\n", &RegistryKey);
+  DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry);
+
+  Status = DriverEntry(DriverObject, &RegistryKey);
+  if (!NT_SUCCESS(Status))
+    {
+  DeviceNode->DriverObject = NULL;
+  ExFreePool(DriverObject->DriverExtension);
+       ExFreePool(DriverObject);
+       return(Status);
+    }
+
+  Status = IopInitializeDevice(DeviceNode, TRUE);
+
   return(Status);
 }
 
index e4ac58d..75b2870 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pnpmgr.c,v 1.2 2001/05/01 23:08:19 chorns Exp $
+/* $Id: pnpmgr.c,v 1.3 2001/09/01 15:36:44 chorns Exp $
  *
  * COPYRIGHT:      See COPYING in the top level directory
  * PROJECT:        ReactOS kernel
@@ -280,13 +280,13 @@ NTSTATUS
 IopCreateDeviceNode(PDEVICE_NODE ParentNode,
   PDEVICE_OBJECT PhysicalDeviceObject,
   PDEVICE_NODE *DeviceNode)
-/* */
 {
   PDEVICE_NODE Node;
   NTSTATUS Status;
   KIRQL OldIrql;
 
-  DPRINT("ParentNode %x PhysicalDeviceObject %x\n");
+  DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
+    ParentNode, PhysicalDeviceObject);
 
   Node = (PDEVICE_NODE)ExAllocatePool(PagedPool, sizeof(DEVICE_NODE));
   if (!Node)
@@ -358,92 +358,226 @@ IopFreeDeviceNode(PDEVICE_NODE DeviceNode)
 
   KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
 
+  RtlFreeUnicodeString(&DeviceNode->InstancePath);
+
+  RtlFreeUnicodeString(&DeviceNode->ServiceName);
+
+  /* FIXME: Other fields may need to be released */
+
   ExFreePool(DeviceNode);
 
   return STATUS_SUCCESS;
 }
 
 NTSTATUS
-IopInterrogateBusExtender(PDEVICE_NODE DeviceNode,
-  PDEVICE_OBJECT FunctionDeviceObject,
-  BOOLEAN BootDriversOnly)
+IopInitiatePnpIrp(
+  PDEVICE_OBJECT DeviceObject,
+  PIO_STATUS_BLOCK IoStatusBlock,
+  ULONG MinorFunction,
+  PIO_STACK_LOCATION Stack)
 {
-       IO_STATUS_BLOCK IoStatusBlock;
+  PDEVICE_OBJECT TopDeviceObject;
   PIO_STACK_LOCATION IrpSp;
   NTSTATUS Status;
   KEVENT Event;
   PIRP Irp;
 
-  DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to bus driver\n");
+  /* Always call the top of the device stack */
+  TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
 
-  KeInitializeEvent(&Event,
+  KeInitializeEvent(
+    &Event,
          NotificationEvent,
          FALSE);
 
-  Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
-    FunctionDeviceObject,
+  /* PNP IRPs are always initialized with a status code of
+     STATUS_NOT_IMPLEMENTED */
+  IoStatusBlock->Status = STATUS_NOT_IMPLEMENTED;
+
+  Irp = IoBuildSynchronousFsdRequest(
+    IRP_MJ_PNP,
+    TopDeviceObject,
          NULL,
          0,
          NULL,
          &Event,
-         &IoStatusBlock);
+         IoStatusBlock);
 
   IrpSp = IoGetNextIrpStackLocation(Irp);
-  IrpSp->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
-  IrpSp->Parameters.QueryDeviceRelations.Type = BusRelations;
+  IrpSp->MinorFunction = MinorFunction;
+  RtlMoveMemory(
+    &IrpSp->Parameters,
+    &Stack->Parameters,
+    sizeof(Stack->Parameters));
 
-       Status = IoCallDriver(FunctionDeviceObject, Irp);
+       Status = IoCallDriver(TopDeviceObject, Irp);
        if (Status == STATUS_PENDING)
          {
-                 KeWaitForSingleObject(&Event,
+                 KeWaitForSingleObject(
+        &Event,
         Executive,
                    KernelMode,
                    FALSE,
                    NULL);
-        Status = IoStatusBlock.Status;
+      Status = IoStatusBlock->Status;
+    }
+
+  return Status;
+}
+
+NTSTATUS
+IopInterrogateBusExtender(
+  PDEVICE_NODE DeviceNode,
+  PDEVICE_OBJECT FunctionDeviceObject,
+  BOOLEAN BootDriversOnly)
+{
+  PDEVICE_RELATIONS DeviceRelations;
+       IO_STATUS_BLOCK IoStatusBlock;
+  UNICODE_STRING DriverName;
+  IO_STACK_LOCATION Stack;
+  NTSTATUS Status;
+
+  DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to bus driver\n");
+
+  Stack.Parameters.QueryDeviceRelations.Type = BusRelations;
+
+  Status = IopInitiatePnpIrp(
+    FunctionDeviceObject,
+    &IoStatusBlock,
+    IRP_MN_QUERY_DEVICE_RELATIONS,
+    &Stack);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("IopInitiatePnpIrp() failed\n");
+    }
+
+  DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
+
+  DPRINT("Got %d PDOs\n", DeviceRelations->Count);
+
+  if (DeviceRelations->Count <= 0)
+    {
+      DPRINT("No PDOs\n");
+      ExFreePool(DeviceRelations);
+      return STATUS_SUCCESS;
     }
+
+  Status = IopCreateDeviceNode(DeviceNode, NULL, &DeviceNode);
   if (!NT_SUCCESS(Status))
     {
-      CPRINT("IoCallDriver() failed\n");
+      DPRINT("No resources\n");
+      ExFreePool(DeviceRelations);
+      return STATUS_INSUFFICIENT_RESOURCES;
     }
 
+  /* FIXME: Use registry to find name of driver and only load driver if not
+            already loaded. If loaded, just call AddDevice() */
+  Status = LdrLoadDriver(&DriverName, DeviceNode, FALSE);
+  if (!NT_SUCCESS(Status))
+    {
+      /* Don't free the device node, just log the error and return */
+      /* FIXME: Log the error */
+           CPRINT("Driver load failed, status (%x)\n", Status);
+      ExFreePool(DeviceRelations);
+      return Status;
+    }
+
+  ExFreePool(DeviceRelations);
+
   return Status;
 }
 
 VOID IopLoadBootStartDrivers(VOID)
 {
-  UNICODE_STRING DriverName;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  PKEY_BASIC_INFORMATION KeyInfo;
   PDEVICE_NODE DeviceNode;
+  UNICODE_STRING KeyName;
+  HANDLE KeyHandle;
+  ULONG BufferSize;
+  ULONG ResultSize;
   NTSTATUS Status;
+  ULONG Index;
 
   DPRINT("Loading boot start drivers\n");
 
-return;
-
-  /* FIXME: Get these from registry */
-
-  /* Use IopRootDeviceNode for now */
-  Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
+  BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH+1) * sizeof(WCHAR);
+  KeyInfo = ExAllocatePool(PagedPool, BufferSize);
+  if (!KeyInfo)
+  {
+    return;
+  }
+
+  RtlInitUnicodeString(
+    &KeyName,
+    L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
+
+  InitializeObjectAttributes(
+    &ObjectAttributes,
+               &KeyName,
+               OBJ_CASE_INSENSITIVE,
+               NULL,
+               NULL);
+
+  Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
   if (!NT_SUCCESS(Status))
     {
+  DPRINT("NtOpenKey() failed (Status %x)\n", Status);
+  ExFreePool(KeyInfo);
   return;
     }
 
-  /*
-   * ISA Plug and Play driver
-   */
-  RtlInitUnicodeString(&DriverName,
-    L"\\SystemRoot\\system32\\drivers\\isapnp.sys");
-  Status = LdrLoadDriver(&DriverName, DeviceNode, TRUE);
-  if (!NT_SUCCESS(Status))
+  Index = 0;
+  do {
+    Status = ZwEnumerateKey(
+      KeyHandle,
+      Index,
+      KeyBasicInformation,
+      KeyInfo,
+      BufferSize,
+      &ResultSize);
+    if (!NT_SUCCESS(Status))
     {
-           IopFreeDeviceNode(DeviceNode);
+      DPRINT("ZwEnumerateKey() (Status %x)\n", Status);
+      break;
+    }
+
+    /* Terminate the string */
+    KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0;
+
+    /* Use IopRootDeviceNode for now */
+    Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
+    if (!NT_SUCCESS(Status))
+    {
+      CPRINT("IopCreateDeviceNode() failed with status 0x%X\n", Status);
+      break;
+    }
+
+    if (!RtlCreateUnicodeString(&DeviceNode->ServiceName, KeyInfo->Name))
+    {
+      CPRINT("RtlCreateUnicodeString() failed\n");
+      IopFreeDeviceNode(DeviceNode);
+      break;
+    }
 
+    Status = IopInitializeDeviceNodeService(DeviceNode);
+    if (!NT_SUCCESS(Status))
+    {
       /* FIXME: Write an entry in the system error log */
-      DbgPrint("Could not load boot start driver: %wZ, status 0x%X\n",
-        &DriverName, Status);
-      return;
+      CPRINT("Could not load boot start driver: %wZ, status 0x%X\n",
+        &DeviceNode->ServiceName, Status);
+
+      IopFreeDeviceNode(DeviceNode);
     }
+
+    Index++;
+  } while (TRUE);
+
+  DPRINT("Services found: %d\n", Index);
+
+  NtClose(KeyHandle);
+
+  ExFreePool(KeyInfo);
 }
 
 VOID PnpInit(VOID)
@@ -457,7 +591,7 @@ VOID PnpInit(VOID)
   Status = IopCreateDriverObject(&IopRootDriverObject);
   if (!NT_SUCCESS(Status))
     {
-      DbgPrint("IoCreateDriverObject() failed\n");
+      CPRINT("IoCreateDriverObject() failed\n");
       KeBugCheck(0);
     }
 
@@ -467,7 +601,7 @@ VOID PnpInit(VOID)
     FILE_DEVICE_CONTROLLER, 0, FALSE, &IopRootDeviceNode->Pdo);
   if (!NT_SUCCESS(Status))
     {
-      DbgPrint("IoCreateDevice() failed\n");
+      CPRINT("IoCreateDevice() failed\n");
       KeBugCheck(0);
     }
 
index c3e4801..9dd2e65 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pnproot.c,v 1.4 2001/08/27 01:20:50 ekohl Exp $
+/* $Id: pnproot.c,v 1.5 2001/09/01 15:36:44 chorns Exp $
  *
  * COPYRIGHT:      See COPYING in the top level directory
  * PROJECT:        ReactOS kernel
@@ -163,7 +163,10 @@ PnpRootPnpControl(
 
   DPRINT("Called\n");
 
+  Status = Irp->IoStatus.Status;
+
   IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
   switch (IrpSp->MinorFunction)
     {
   case IRP_MN_QUERY_DEVICE_RELATIONS:
index 034a328..b51ae8f 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: main.c,v 1.103 2001/09/01 11:55:37 dwelch Exp $
+/* $Id: main.c,v 1.104 2001/09/01 15:36:44 chorns Exp $
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/main.c
@@ -45,6 +45,7 @@
 #include <internal/kd.h>
 #include <internal/trap.h>
 #include "../dbg/kdb.h"
+#include <internal/registry.h>
 
 #ifdef HALDBG
 #include <internal/ntosdbg.h>
@@ -73,8 +74,297 @@ volatile BOOLEAN Initialized = FALSE;
 
 extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
 
+typedef struct
+{
+  LPWSTR ServiceName;
+  LPWSTR DeviceDesc;
+  LPWSTR Group;
+  DWORD Start;
+  DWORD Type;
+} SERVICE, *PSERVICE;
+
+SERVICE Services[] = {
+  {L"keyboard", L"Standard Keyboard Driver", L"Base", 0, 1},
+  {L"blue", L"Bluescreen Driver", L"Base", 0, 1},
+  {L"vidport", L"Video Port Driver", L"Base", 0, 1},
+  {L"vgamp", L"VGA Miniport", L"Base", 0, 1},
+  {L"minixfs", L"Minix File System", L"File system", 0, 1},
+  {L"msfs", L"Mail Slot File System", L"File system", 0, 1},
+  {L"npfs", L"Named Pipe File System", L"File system", 0, 1},
+  {L"psaux", L"PS/2 Auxillary Port Driver", L"", 0, 1},
+  {L"mouclass", L"Mouse Class Driver", L"Pointer Class", 0, 1},
+  {L"ndis", L"NDIS System Driver", L"NDIS Wrapper", 0, 1},
+  {L"ne2000", L"Novell Eagle 2000 Driver", L"NDIS", 0, 1},
+  {L"afd", L"AFD Networking Support Environment", L"TDI", 0, 1},
+  {NULL,}
+};
+
 /* FUNCTIONS ****************************************************************/
 
+VOID CreateDefaultRegistryForLegacyDriver(
+  PSERVICE Service)
+{
+  WCHAR LegacyDriver[] = L"LegacyDriver";
+  WCHAR InstancePath[MAX_PATH];
+  WCHAR KeyNameBuffer[MAX_PATH];
+  WCHAR Name[MAX_PATH];
+  UNICODE_STRING KeyName;
+  HANDLE KeyHandle;
+  DWORD DwordData;
+  ULONG Length;
+  NTSTATUS Status;
+  WCHAR ImagePath[MAX_PATH];
+  /* Enum section */
+  wcscpy(Name, Service->ServiceName);
+  _wcsupr(Name);
+  wcscpy(InstancePath, L"Root\\LEGACY_");
+  wcscat(InstancePath, Name);
+  wcscat(InstancePath, L"\\0000");
+
+  wcscpy(KeyNameBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
+  wcscat(KeyNameBuffer, InstancePath);
+
+  RtlInitUnicodeString(&KeyName, KeyNameBuffer);
+
+  DPRINT("Key name is %S\n", KeyName.Buffer);
+
+  Status = RtlpCreateRegistryKeyPath(KeyName.Buffer);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlpCreateRegistryKeyPath() failed with status %x\n", Status);
+  return;
+    }
+
+  Status = RtlpGetRegistryHandle(
+    RTL_REGISTRY_ENUM,
+         InstancePath,
+               TRUE,
+               &KeyHandle);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlpGetRegistryHandle() failed (Status %x)\n", Status);
+  return;
+    }
+
+  DwordData = 0;
+  Length = sizeof(DWORD);
+  Status = RtlWriteRegistryValue(
+    RTL_REGISTRY_HANDLE,
+    (PWSTR)KeyHandle,
+               L"Capabilities",
+               REG_DWORD,
+               (LPWSTR)&DwordData,
+               Length);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlWriteRegistryValue() failed (Status %x)\n", Status);
+       NtClose(KeyHandle);
+       return;
+    }
+
+  Length = (wcslen(LegacyDriver) + 1) * sizeof(WCHAR);
+  Status = RtlWriteRegistryValue(
+    RTL_REGISTRY_HANDLE,
+    (PWSTR)KeyHandle,
+               L"Class",
+               REG_SZ,
+               LegacyDriver,
+               Length);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlWriteRegistryValue() failed (Status %x)\n", Status);
+       NtClose(KeyHandle);
+       return;
+    }
+
+  Length = (wcslen(Service->DeviceDesc) + 1) * sizeof(WCHAR);
+  Status = RtlWriteRegistryValue(
+    RTL_REGISTRY_HANDLE,
+               (PWSTR)KeyHandle,
+               L"DeviceDesc",
+               REG_SZ,
+               Service->DeviceDesc,
+               Length);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlWriteRegistryValue() failed (Status %x)\n", Status);
+       NtClose(KeyHandle);
+       return;
+    }
+
+  DwordData = 0;
+  Length = Length = sizeof(DWORD);
+  Status = RtlWriteRegistryValue(
+    RTL_REGISTRY_HANDLE,
+    (PWSTR)KeyHandle,
+               L"Legacy",
+               REG_DWORD,
+               (LPWSTR)&DwordData,
+               sizeof(DWORD));
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlWriteRegistryValue() failed (Status %x)\n", Status);
+       NtClose(KeyHandle);
+       return;
+    }
+
+  Length = (wcslen(Service->ServiceName) + 1) * sizeof(WCHAR);
+  Status = RtlWriteRegistryValue(
+    RTL_REGISTRY_HANDLE,
+               (PWSTR)KeyHandle,
+               L"Service",
+               REG_SZ,
+               Service->ServiceName,
+               Length);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlWriteRegistryValue() failed (Status %x)\n", Status);
+       NtClose(KeyHandle);
+       return;
+    }
+
+  NtClose(KeyHandle);
+
+  /* Services section */
+
+  Status = RtlpGetRegistryHandle(
+    RTL_REGISTRY_SERVICES,
+         Service->ServiceName,
+               TRUE,
+               &KeyHandle);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlpGetRegistryHandle() failed (Status %x)\n", Status);
+  return;
+    }
+
+  Length = (wcslen(Service->DeviceDesc) + 1) * sizeof(WCHAR);
+  Status = RtlWriteRegistryValue(
+    RTL_REGISTRY_HANDLE,
+               (PWSTR)KeyHandle,
+               L"DisplayName",
+               REG_SZ,
+               Service->DeviceDesc,
+               Length);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlWriteRegistryValue() failed (Status %x)\n", Status);
+       NtClose(KeyHandle);
+       return;
+    }
+
+  DwordData = 1;
+  Length = sizeof(DWORD);
+  Status = RtlWriteRegistryValue(
+    RTL_REGISTRY_HANDLE,
+    (PWSTR)KeyHandle,
+               L"ErrorControl",
+               REG_DWORD,
+               (LPWSTR)&DwordData,
+               Length);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlWriteRegistryValue() failed (Status %x)\n", Status);
+       NtClose(KeyHandle);
+       return;
+    }
+
+  Length = (wcslen(Service->Group) + 1) * sizeof(WCHAR);
+  Status = RtlWriteRegistryValue(
+    RTL_REGISTRY_HANDLE,
+               (PWSTR)KeyHandle,
+               L"Group",
+               REG_SZ,
+               Service->Group,
+               Length);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlWriteRegistryValue() failed (Status %x)\n", Status);
+       NtClose(KeyHandle);
+       return;
+    }
+
+  wcscpy(ImagePath, L"\\SystemRoot\\System32\\drivers\\");
+  wcscat(ImagePath, Service->ServiceName);
+  wcscat(ImagePath, L".sys");
+
+  Length = (wcslen(ImagePath) + 1) * sizeof(WCHAR);
+  Status = RtlWriteRegistryValue(
+    RTL_REGISTRY_HANDLE,
+               (PWSTR)KeyHandle,
+               L"ImagePath",
+               REG_SZ,
+               ImagePath,
+               Length);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlWriteRegistryValue() failed (Status %x)\n", Status);
+       NtClose(KeyHandle);
+       return;
+    }
+
+  DwordData = Service->Start;
+  Length = sizeof(DWORD);
+  Status = RtlWriteRegistryValue(
+    RTL_REGISTRY_HANDLE,
+    (PWSTR)KeyHandle,
+               L"Start",
+               REG_DWORD,
+               (LPWSTR)&DwordData,
+               Length);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlWriteRegistryValue() failed (Status %x)\n", Status);
+       NtClose(KeyHandle);
+       return;
+    }
+
+  DwordData = Service->Type;
+  Length = sizeof(DWORD);
+  Status = RtlWriteRegistryValue(
+    RTL_REGISTRY_HANDLE,
+    (PWSTR)KeyHandle,
+               L"Type",
+               REG_DWORD,
+               (LPWSTR)&DwordData,
+               Length);
+  if (!NT_SUCCESS(Status))
+    {
+  DPRINT1("RtlWriteRegistryValue() failed (Status %x)\n", Status);
+       NtClose(KeyHandle);
+       return;
+    }
+
+  NtClose(KeyHandle);
+}
+
+VOID CreateDefaultRegistry()
+{
+  NTSTATUS Status;
+  ULONG i;
+
+  Status = RtlpCreateRegistryKeyPath(L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("RtlpCreateRegistryKeyPath() (Status %x)\n", Status);
+    return;
+  }
+
+  Status = RtlpCreateRegistryKeyPath(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("RtlpCreateRegistryKeyPath() (Status %x)\n", Status);
+    return;
+  }
+
+  for (i = 0; Services[i].ServiceName != NULL; i++)
+  {
+    CreateDefaultRegistryForLegacyDriver(&Services[i]);
+  }
+}
+
+
 static BOOLEAN
 RtlpCheckFileNameExtension(PCHAR FileName,
                           PCHAR Extension)
@@ -660,23 +950,27 @@ ExpInitializeExecutive(VOID)
 
   CmInitializeRegistry2();
 
+#if 0
+  CreateDefaultRegistry();
+#endif
+
   PiInitDefaultLocale();
 
   /*
    * Start the motherboard enumerator (the HAL)
    */
   HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-
+#if 0
   /*
    * Load boot start drivers
    */
   IopLoadBootStartDrivers();
-
+#else
   /*
    * Load Auto configured drivers
    */
   LdrLoadAutoConfigDrivers();
-
+#endif
   /*
    * Assign drive letters
    */
@@ -756,7 +1050,7 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
    * This should be done by the boot loader.
    */
   strcpy (KeLoaderCommandLine,
-         "multi(0)disk(0)rdisk(0)partition(1)\\reactos /DEBUGPORT=SCREEN");
+         "multi(0)disk(0)rdisk(0)partition(1)\\reactos /DEBUGPORT=COM1");
   strcat (KeLoaderCommandLine, (PUCHAR)KeLoaderBlock.CommandLine);
   
   KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
index 2c898cf..9037f22 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: loader.c,v 1.88 2001/08/30 20:38:20 dwelch Exp $
+/* $Id: loader.c,v 1.89 2001/09/01 15:36:44 chorns Exp $
  * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -814,7 +814,10 @@ VOID LdrLoadUserModuleSymbols(PLDR_MODULE ModuleObject)
   ExFreePool(FileBuffer);
 }
 
-NTSTATUS LdrpFindModuleObject(
+#endif /* KDBG */
+
+
+NTSTATUS LdrFindModuleObject(
   PUNICODE_STRING ModuleName,
   PMODULE_OBJECT *ModuleObject)
 {
@@ -851,8 +854,6 @@ NTSTATUS LdrpFindModuleObject(
   return STATUS_SUCCESS;
 }
 
-#endif /* KDBG */
-
 VOID LdrLoadAutoConfigDrivers (VOID)
 {
 
@@ -866,18 +867,19 @@ VOID LdrLoadAutoConfigDrivers (VOID)
      is created after their module entries */
 
   RtlInitUnicodeString(&ModuleName, KERNEL_MODULE_NAME);
-  Status = LdrpFindModuleObject(&ModuleName, &ModuleObject);
+  Status = LdrFindModuleObject(&ModuleName, &ModuleObject);
   if (NT_SUCCESS(Status))
   {
     LdrpLoadModuleSymbols(ModuleObject);
   }
 
   RtlInitUnicodeString(&ModuleName, HAL_MODULE_NAME);
-  Status = LdrpFindModuleObject(&ModuleName, &ModuleObject);
+  Status = LdrFindModuleObject(&ModuleName, &ModuleObject);
   if (NT_SUCCESS(Status))
   {
     LdrpLoadModuleSymbols(ModuleObject);
   }
+
 #endif /* KDBG */
 
    /*
@@ -949,7 +951,7 @@ VOID LdrLoadAutoConfigDrivers (VOID)
    /*
     * Ancillary Function Driver
     */
-   LdrLoadAutoConfigDriver(L"afd.sys");
+   //LdrLoadAutoConfigDriver(L"afd.sys");
 #endif
 }
 
@@ -996,8 +998,7 @@ NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename,
       return STATUS_UNSUCCESSFUL;
     }
 
-  Status = IopInitializeDriver(ModuleObject->EntryPoint,
-    DeviceNode, Filename, BootDriversOnly);
+  Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode);
   if (!NT_SUCCESS(Status))
     {
       ObDereferenceObject(ModuleObject);
@@ -1180,7 +1181,7 @@ LdrProcessDriver(PVOID ModuleLoadBase, PCHAR FileName, ULONG ModuleLength)
   DPRINT("dasdsad: %s\n", TmpFileName);
 
   RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
-  Status = LdrpFindModuleObject(&ModuleName, &ModuleObject);
+  Status = LdrFindModuleObject(&ModuleName, &ModuleObject);
   RtlFreeUnicodeString(&ModuleName);
   if (!NT_SUCCESS(Status))
     {
@@ -1188,7 +1189,7 @@ LdrProcessDriver(PVOID ModuleLoadBase, PCHAR FileName, ULONG ModuleLength)
       strcat(TmpFileName, ".exe");
       RtlInitAnsiString(&AnsiString, TmpFileName);
       RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
-      Status = LdrpFindModuleObject(&ModuleName, &ModuleObject);
+      Status = LdrFindModuleObject(&ModuleName, &ModuleObject);
       RtlFreeUnicodeString(&ModuleName);
     }
   if (NT_SUCCESS(Status))
@@ -1227,7 +1228,7 @@ LdrProcessDriver(PVOID ModuleLoadBase, PCHAR FileName, ULONG ModuleLength)
    return(STATUS_UNSUCCESSFUL);
      }
 
-   Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode, NULL, FALSE);
+   Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode);
    if (!NT_SUCCESS(Status))
      {
         IopFreeDeviceNode(DeviceNode);
index eb5125c..d1aea48 100644 (file)
@@ -81,7 +81,6 @@ typedef struct
    HANDLE ConsoleEvent;
 } CSRSS_PROCESS_DATA, *PCSRSS_PROCESS_DATA;
 
-
 #define CSR_API(n) NTSTATUS n (\
 PCSRSS_PROCESS_DATA ProcessData,\
 PCSRSS_API_REQUEST Request,\
@@ -114,6 +113,9 @@ CSR_API(CsrCreateScreenBuffer);
 CSR_API(CsrSetScreenBuffer);
 CSR_API(CsrSetTitle);
 CSR_API(CsrGetTitle);
+CSR_API(CsrWriteConsoleOutput);
+CSR_API(CsrFlushInputBuffer);
+CSR_API(CsrScrollConsoleScreenBuffer);
 
 /* print.c */
 VOID STDCALL DisplayString(LPCWSTR lpwString);
index 40d454e..16f18f4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: conio.c,v 1.24 2001/08/14 22:00:21 ea Exp $
+/* $Id: conio.c,v 1.25 2001/09/01 15:36:45 chorns Exp $
  *
  * reactos/subsys/csrss/api/conio.c
  *
@@ -20,6 +20,9 @@
 #define LOCK   RtlEnterCriticalSection(&ActiveConsoleLock)
 #define UNLOCK RtlLeaveCriticalSection(&ActiveConsoleLock)
 
+/* FIXME: Is there a way to create real aliasses with gcc? [CSH] */
+#define ALIAS(Name, Target) typeof(Target) Name = Target
+
 
 /* GLOBALS *******************************************************************/
 
@@ -118,6 +121,7 @@ CSR_API(CsrFreeConsole)
 
 CSR_API(CsrReadConsole)
 {
+   PLIST_ENTRY CurrentEntry;
    ConsoleInput *Input;
    PCHAR Buffer;
    int   i = 0;
@@ -149,10 +153,9 @@ CSR_API(CsrReadConsole)
    for (; i<nNumberOfCharsToRead && Console->InputEvents.Flink != &Console->InputEvents; i++ )     
       {
         // remove input event from queue
-        Input = (ConsoleInput *)Console->InputEvents.Flink;
-        
-        Input->ListEntry.Blink->Flink = Input->ListEntry.Flink;
-        Input->ListEntry.Flink->Blink = Input->ListEntry.Blink;
+   CurrentEntry = RemoveHeadList(&Console->InputEvents);
+   Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
+
         // only pay attention to valid ascii chars, on key down
         if( Input->InputEvent.EventType == KEY_EVENT &&
             Input->InputEvent.Event.KeyEvent.bKeyDown == TRUE &&
@@ -215,6 +218,9 @@ CSR_API(CsrReadConsole)
    return Reply->Status;
 }
 
+#define GET_CELL_BUFFER(b,o)\
+(b)->Buffer[(o)++];
+
 #define SET_CELL_BUFFER(b,o,c,a)\
 (b)->Buffer[(o)++]=(c);\
 (b)->Buffer[(o)++]=(a);
@@ -327,6 +333,278 @@ NTSTATUS STDCALL CsrpWriteConsole( PCSRSS_SCREEN_BUFFER Buff, CHAR *Buffer, DWOR
    return(STATUS_SUCCESS);
 }
 
+#define CsrpInitRect(_Rect, _Top, _Left, _Bottom, _Right) \
+{ \
+  ((_Rect).Top) = _Top; \
+  ((_Rect).Left) = _Left; \
+  ((_Rect).Bottom) = _Bottom; \
+  ((_Rect).Right) = _Right; \
+}
+
+#define CsrpRectHeight(Rect) \
+  ((Rect.Bottom) - (Rect.Top) + 1)
+
+#define CsrpRectWidth(Rect) \
+  ((Rect.Right) - (Rect.Left) + 1)
+
+#define CsrpIsRectEmpty(Rect) \
+  ((Rect.Left >= Rect.Right) || (Rect.Top >= Rect.Bottom))
+
+
+inline BOOLEAN CsrpIsEqualRect(
+  SMALL_RECT Rect1,
+  SMALL_RECT Rect2)
+{
+  return ((Rect1.Left == Rect2.Left) && (Rect1.Right == Rect2.Right) &&
+         (Rect1.Top == Rect2.Top) && (Rect1.Bottom == Rect2.Bottom));
+}
+
+inline BOOLEAN CsrpGetIntersection(
+  PSMALL_RECT Intersection,
+  SMALL_RECT Rect1,
+  SMALL_RECT Rect2)
+{
+  if (CsrpIsRectEmpty(Rect1) ||
+    (CsrpIsRectEmpty(Rect2)) ||
+    (Rect1.Top >= Rect2.Bottom) ||
+    (Rect1.Left >= Rect2.Right) ||
+    (Rect1.Bottom <= Rect2.Top) ||
+    (Rect1.Right <= Rect2.Left))
+  {
+    /* The rectangles do not intersect */
+    CsrpInitRect(*Intersection, 0, 0, 0, 0)
+    return FALSE;
+  }
+
+  CsrpInitRect(
+    *Intersection,
+    RtlMax(Rect1.Top, Rect2.Top),
+    RtlMax(Rect1.Left, Rect2.Left),
+    RtlMin(Rect1.Bottom, Rect2.Bottom),
+    RtlMin(Rect1.Right, Rect2.Right));
+  return TRUE;
+}
+
+inline BOOLEAN CsrpGetUnion(
+  PSMALL_RECT Union,
+  SMALL_RECT Rect1,
+  SMALL_RECT Rect2)
+{
+  if (CsrpIsRectEmpty(Rect1))
+    {
+           if (CsrpIsRectEmpty(Rect2))
+           {
+             CsrpInitRect(*Union, 0, 0, 0, 0);
+             return FALSE;
+           }
+         else
+      *Union = Rect2;
+    }
+  else
+    {
+           if (CsrpIsRectEmpty(Rect2))
+        {
+        *Union = Rect1;
+        }
+           else
+             {
+          CsrpInitRect(
+            *Union,
+            RtlMin(Rect1.Top, Rect2.Top),
+            RtlMin(Rect1.Left, Rect2.Left),
+            RtlMax(Rect1.Bottom, Rect2.Bottom),
+            RtlMax(Rect1.Right, Rect2.Right));
+             }
+    }
+  return TRUE;
+}
+
+inline BOOLEAN CsrpSubtractRect(
+  PSMALL_RECT Subtraction,
+  SMALL_RECT Rect1,
+  SMALL_RECT Rect2)
+{
+  SMALL_RECT tmp;
+
+  if (CsrpIsRectEmpty(Rect1))
+    {
+           CsrpInitRect(*Subtraction, 0, 0, 0, 0);
+           return FALSE;
+    }
+  *Subtraction = Rect1;
+  if (CsrpGetIntersection(&tmp, Rect1, Rect2))
+    {
+           if (CsrpIsEqualRect(tmp, *Subtraction))
+             {
+               CsrpInitRect(*Subtraction, 0, 0, 0, 0);
+               return FALSE;
+             }
+           if ((tmp.Top == Subtraction->Top) && (tmp.Bottom == Subtraction->Bottom))
+             {
+               if (tmp.Left == Subtraction->Left)
+            Subtraction->Left = tmp.Right;
+               else if (tmp.Right == Subtraction->Right)
+            Subtraction->Right = tmp.Left;
+             }
+           else if ((tmp.Left == Subtraction->Left) && (tmp.Right == Subtraction->Right))
+             {
+               if (tmp.Top == Subtraction->Top)
+            Subtraction->Top = tmp.Bottom;
+               else if (tmp.Bottom == Subtraction->Bottom)
+            Subtraction->Bottom = tmp.Top;
+             }
+    }
+  return TRUE;
+}
+
+/*
+ * Screen buffer must be locked when this function is called
+ */
+static VOID CsrpCopyRegion(
+  PCSRSS_SCREEN_BUFFER ScreenBuffer,
+  SMALL_RECT SrcRegion,
+  SMALL_RECT DstRegion)
+{
+  SHORT SrcY, DstY;
+  DWORD SrcOffset;
+  DWORD DstOffset;
+  DWORD BytesPerLine;
+
+  DstY = DstRegion.Top;
+  BytesPerLine = CsrpRectWidth(DstRegion) * 2;
+  for (SrcY = SrcRegion.Top; SrcY <= SrcRegion.Bottom; SrcY++)
+  {
+    SrcOffset = (SrcY * ScreenBuffer->MaxX * 2) + (SrcRegion.Left * 2);
+    DstOffset = (DstY * ScreenBuffer->MaxX * 2) + (DstRegion.Left * 2);
+    RtlCopyMemory(
+      &ScreenBuffer->Buffer[DstOffset],
+      &ScreenBuffer->Buffer[SrcOffset],
+      BytesPerLine);
+    DstY++;
+  }
+}
+
+/*
+ * Screen buffer must be locked when this function is called
+ */
+static VOID CsrpFillRegion(
+  PCSRSS_SCREEN_BUFFER ScreenBuffer,
+  SMALL_RECT Region,
+  CHAR_INFO CharInfo)
+{
+  SHORT X, Y;
+  DWORD Offset;
+
+  for (Y = Region.Top; Y <= Region.Bottom; Y++)
+  {
+    Offset = (Y * ScreenBuffer->MaxX + Region.Left) * 2;
+    for (X = Region.Left; X <= Region.Right; X++)
+    {
+      SET_CELL_BUFFER(ScreenBuffer, Offset, CharInfo.Char.AsciiChar, CharInfo.Attributes);
+    }
+  }
+}
+
+/*
+ * Screen buffer must be locked when this function is called
+ */
+inline NTSTATUS CsrpSetConsoleDeviceCursor(PCSRSS_SCREEN_BUFFER ScreenBuffer, SHORT X, SHORT Y)
+{
+   CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
+   IO_STATUS_BLOCK Iosb;
+
+   ScrInfo.dwCursorPosition.X = X;
+   ScrInfo.dwCursorPosition.Y = Y;
+   ScrInfo.wAttributes = ScreenBuffer->DefaultAttrib;
+
+   return NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
+     IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 );
+}
+
+/*
+ * Region - Region of virtual screen buffer to draw onto the physical console
+ * Screen buffer must be locked when this function is called
+ */
+static VOID CsrpDrawRegion(
+  PCSRSS_SCREEN_BUFFER ScreenBuffer,
+  SMALL_RECT Region)
+{
+   IO_STATUS_BLOCK Iosb;
+   NTSTATUS Status;
+   CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
+   CONSOLE_MODE Mode;
+   int i, y;
+   DWORD BytesPerLine;
+   DWORD SrcOffset;
+   DWORD SrcDelta;
+
+   Mode.dwMode = 0; /* clear ENABLE_PROCESSED_OUTPUT mode */
+   Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
+     IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 );
+   if( !NT_SUCCESS( Status ) )
+     {
+       DbgPrint( "CSR: Failed to set console mode\n" );
+       return;
+     }
+
+   /* blast out buffer */
+   BytesPerLine = CsrpRectWidth(Region) * 2;
+   SrcOffset = (Region.Top * ScreenBuffer->MaxX + Region.Left) * 2;
+   SrcDelta = ScreenBuffer->MaxX * 2;
+   for( i = Region.Top - ScreenBuffer->ShowY, y = ScreenBuffer->ShowY;
+        i <= Region.Bottom - ScreenBuffer->ShowY; i++ )
+     {
+        /* Position the cursor correctly */
+        Status = CsrpSetConsoleDeviceCursor(ScreenBuffer, Region.Left - ScreenBuffer->ShowX, i);
+        if( !NT_SUCCESS( Status ) )
+          {
+            DbgPrint( "CSR: Failed to set console info\n" );
+            return;
+          }
+
+        Status = NtWriteFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
+         &ScreenBuffer->Buffer[ SrcOffset ],
+         BytesPerLine, 0, 0 );
+       if( !NT_SUCCESS( Status ) )
+             {
+               DbgPrint( "CSR: Write to console failed\n" );
+               return;
+             }
+
+      /* wrap back around the end of the buffer */
+      if( ++y == ScreenBuffer->MaxY )
+             y = 0;
+
+      SrcOffset += SrcDelta;
+     }
+   Mode.dwMode = ENABLE_PROCESSED_OUTPUT;
+   Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
+     IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 );
+   if( !NT_SUCCESS( Status ) )
+     {
+       DbgPrint( "CSR: Failed to set console mode\n" );
+       return;
+     }
+   Status = CsrpSetConsoleDeviceCursor(
+     ScreenBuffer,
+     ScreenBuffer->CurrentX - ScreenBuffer->ShowX,
+     ((ScreenBuffer->CurrentY + ScreenBuffer->MaxY) - ScreenBuffer->ShowY) % ScreenBuffer->MaxY);
+   if( !NT_SUCCESS( Status ) )
+     {
+       DbgPrint( "CSR: Failed to set console info\n" );
+       return;
+     }
+   Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
+     IOCTL_CONSOLE_SET_CURSOR_INFO, &ScreenBuffer->CursorInfo,
+     sizeof( ScreenBuffer->CursorInfo ), 0, 0 );
+   if( !NT_SUCCESS( Status ) )
+     {
+       DbgPrint( "CSR: Failed to set cursor info\n" );
+       return;
+     }
+}
+
+
 CSR_API(CsrWriteConsole)
 {
    BYTE *Buffer = Request->Data.WriteConsoleRequest.Buffer;
@@ -337,7 +615,8 @@ CSR_API(CsrWriteConsole)
      sizeof(LPC_MESSAGE_HEADER);
 
    LOCK;
-   if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle, (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC )
+   if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle,
+     (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC )
       {
         UNLOCK;
         return Reply->Status = STATUS_INVALID_HANDLE;
@@ -396,7 +675,7 @@ NTSTATUS STDCALL CsrInitConsole(PCSRSS_CONSOLE Console)
   Console->EchoCount = 0;
   Console->Header.Type = CSRSS_CONSOLE_MAGIC;
   Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
-  Console->InputEvents.Flink = Console->InputEvents.Blink = &Console->InputEvents;
+  InitializeListHead(&Console->InputEvents);
   Status = NtCreateEvent( &Console->ActiveEvent, STANDARD_RIGHTS_ALL, 0, FALSE, FALSE );
   if( !NT_SUCCESS( Status ) )
     {
@@ -443,63 +722,16 @@ NTSTATUS STDCALL CsrInitConsole(PCSRSS_CONSOLE Console)
  **************************************************************/
 VOID STDCALL CsrDrawConsole( PCSRSS_SCREEN_BUFFER Buff )
 {
-   IO_STATUS_BLOCK Iosb;
-   NTSTATUS Status;
-   CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
-   CONSOLE_MODE Mode;
-   int i, y;
+   SMALL_RECT Region;
 
-   /* first set position to 0,0 */
-   ScrInfo.dwCursorPosition.X = 0;
-   ScrInfo.dwCursorPosition.Y = 0;
-   ScrInfo.wAttributes = Buff->DefaultAttrib;
-   Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 );
-   if( !NT_SUCCESS( Status ) )
-     {
-       DbgPrint( "CSR: Failed to set console info\n" );
-       return;
-     }
-   Mode.dwMode = 0; /* clear ENABLE_PROCESSED_OUTPUT mode */
-   Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 );
-   if( !NT_SUCCESS( Status ) )
-     {
-       DbgPrint( "CSR: Failed to set console mode\n" );
-       return;
-     }
-   /* blast out buffer */
-   for( i = 0, y = Buff->ShowY; i < PhysicalConsoleSize.Y; i++ )
-     {
-       Status = NtWriteFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, &Buff->Buffer[ (Buff->ShowX * 2) + (y * Buff->MaxX * 2) ], PhysicalConsoleSize.X * 2, 0, 0 );
-       if( !NT_SUCCESS( Status ) )
-        {
-          DbgPrint( "CSR: Write to console failed\n" );
-          return;
-        }
-       /* wrap back around the end of the buffer */
-       if( ++y == Buff->MaxY )
-        y = 0;
-     }
-   Mode.dwMode = ENABLE_PROCESSED_OUTPUT;
-   Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 );
-   if( !NT_SUCCESS( Status ) )
-     {
-       DbgPrint( "CSR: Failed to set console mode\n" );
-       return;
-     }
-   ScrInfo.dwCursorPosition.X = Buff->CurrentX - Buff->ShowX;
-   ScrInfo.dwCursorPosition.Y = ((Buff->CurrentY + Buff->MaxY) - Buff->ShowY) % Buff->MaxY;
-   Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 );
-   if( !NT_SUCCESS( Status ) )
-     {
-       DbgPrint( "CSR: Failed to set console info\n" );
-       return;
-     }
-   Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_CURSOR_INFO, &Buff->CursorInfo, sizeof( Buff->CursorInfo ), 0, 0 );
-   if( !NT_SUCCESS( Status ) )
-     {
-       DbgPrint( "CSR: Failed to set cursor info\n" );
-       return;
-     }
+   CsrpInitRect(
+     Region,
+     Buff->ShowY,
+     Buff->ShowX,
+     Buff->ShowY + PhysicalConsoleSize.Y - 1,
+     Buff->ShowX + PhysicalConsoleSize.X - 1);
+
+   CsrpDrawRegion(Buff, Region);
 }
 
 
@@ -563,8 +795,7 @@ VOID STDCALL CsrInitConsoleSupport(VOID)
      {
        DbgPrint("CSR: Failed to open console. Expect problems.\n");
      }
-//   DbgPrint("CSR: ConsoleDeviceHandle %x\n", ConsoleDeviceHandle);
-   
+
    RtlInitUnicodeString(&DeviceName, L"\\??\\Keyboard");
    InitializeObjectAttributes(&ObjectAttributes,
                              &DeviceName,
@@ -625,7 +856,8 @@ VOID Console_Api( DWORD RefreshEvent )
          continue;
        }
       KeyEventRecord->InputEvent.EventType = KEY_EVENT;
-      Status = NtReadFile( KeyboardDeviceHandle, Events[0], NULL, NULL, &Iosb, &KeyEventRecord->InputEvent.Event.KeyEvent, sizeof( KEY_EVENT_RECORD ), NULL, 0 );
+      Status = NtReadFile( KeyboardDeviceHandle, Events[0], NULL, NULL, &Iosb,
+        &KeyEventRecord->InputEvent.Event.KeyEvent, sizeof( KEY_EVENT_RECORD ), NULL, 0 );
       if( !NT_SUCCESS( Status ) )
        {
          DbgPrint( "CSR: ReadFile on keyboard device failed\n" );
@@ -652,7 +884,9 @@ VOID Console_Api( DWORD RefreshEvent )
              else break;
            }
        }
-      if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED )&&  KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_TAB )
+      if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState &
+        ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED )&&
+          KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_TAB )
         if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
            {
              ANSI_STRING Title;
@@ -736,7 +970,10 @@ VOID Console_Api( DWORD RefreshEvent )
 
          UNLOCK;
        }
-      if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) && (KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP || KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) )
+      if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState &
+        ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) &&
+        ( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP ||
+          KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) )
         {
            if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
               {
@@ -752,14 +989,20 @@ VOID Console_Api( DWORD RefreshEvent )
                  if( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP )
                     {
                        /* only scroll up if there is room to scroll up into */
-                       if( ActiveConsole->ActiveBuffer->ShowY != ((ActiveConsole->ActiveBuffer->CurrentY + 1) % ActiveConsole->ActiveBuffer->MaxY) )
-                          ActiveConsole->ActiveBuffer->ShowY = (ActiveConsole->ActiveBuffer->ShowY + ActiveConsole->ActiveBuffer->MaxY - 1) % ActiveConsole->ActiveBuffer->MaxY;
+                       if( ActiveConsole->ActiveBuffer->ShowY != ((ActiveConsole->ActiveBuffer->CurrentY + 1) %
+        ActiveConsole->ActiveBuffer->MaxY) )
+                          ActiveConsole->ActiveBuffer->ShowY = (ActiveConsole->ActiveBuffer->ShowY +
+         ActiveConsole->ActiveBuffer->MaxY - 1) % ActiveConsole->ActiveBuffer->MaxY;
                     }
                  else if( ActiveConsole->ActiveBuffer->ShowY != ActiveConsole->ActiveBuffer->CurrentY )
                     /* only scroll down if there is room to scroll down into */
-                    if( ActiveConsole->ActiveBuffer->ShowY % ActiveConsole->ActiveBuffer->MaxY != ActiveConsole->ActiveBuffer->CurrentY )
-                       if( ((ActiveConsole->ActiveBuffer->CurrentY + 1) % ActiveConsole->ActiveBuffer->MaxY) != (ActiveConsole->ActiveBuffer->ShowY + PhysicalConsoleSize.Y) % ActiveConsole->ActiveBuffer->MaxY )
-                          ActiveConsole->ActiveBuffer->ShowY = (ActiveConsole->ActiveBuffer->ShowY + 1) % ActiveConsole->ActiveBuffer->MaxY;
+                    if( ActiveConsole->ActiveBuffer->ShowY % ActiveConsole->ActiveBuffer->MaxY != 
+           ActiveConsole->ActiveBuffer->CurrentY )
+
+                       if( ((ActiveConsole->ActiveBuffer->CurrentY + 1) % ActiveConsole->ActiveBuffer->MaxY) != 
+        (ActiveConsole->ActiveBuffer->ShowY + PhysicalConsoleSize.Y) % ActiveConsole->ActiveBuffer->MaxY )
+                          ActiveConsole->ActiveBuffer->ShowY = (ActiveConsole->ActiveBuffer->ShowY + 1) %
+         ActiveConsole->ActiveBuffer->MaxY;
                  CsrDrawConsole( ActiveConsole->ActiveBuffer );
                  UNLOCK;
               }
@@ -784,10 +1027,7 @@ VOID Console_Api( DWORD RefreshEvent )
              updown = KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown;
              KeyEventRecord->Echoed = FALSE;
              KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\r';
-             KeyEventRecord->ListEntry.Flink = &ActiveConsole->InputEvents;
-             KeyEventRecord->ListEntry.Blink = ActiveConsole->InputEvents.Blink;
-             ActiveConsole->InputEvents.Blink->Flink = &KeyEventRecord->ListEntry;
-             ActiveConsole->InputEvents.Blink = &KeyEventRecord->ListEntry;
+        InsertTailList(&ActiveConsole->InputEvents, &KeyEventRecord->ListEntry);
              ActiveConsole->WaitingChars++;
              KeyEventRecord = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( ConsoleInput ) );
              if( !KeyEventRecord )
@@ -803,10 +1043,7 @@ VOID Console_Api( DWORD RefreshEvent )
              KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\n';
            }
       // add event to the queue
-      KeyEventRecord->ListEntry.Flink = &ActiveConsole->InputEvents;
-      KeyEventRecord->ListEntry.Blink = ActiveConsole->InputEvents.Blink;
-      ActiveConsole->InputEvents.Blink->Flink = &KeyEventRecord->ListEntry;
-      ActiveConsole->InputEvents.Blink = &KeyEventRecord->ListEntry;
+      InsertTailList(&ActiveConsole->InputEvents, &KeyEventRecord->ListEntry);
       // if line input mode is enabled, only wake the client on enter key down
       if( !(ActiveConsole->Mode & ENABLE_LINE_INPUT ) ||
          ( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' &&
@@ -823,30 +1060,28 @@ VOID Console_Api( DWORD RefreshEvent )
         {
            // walk the input queue looking for a char to backspace
            for( TempInput = (ConsoleInput *)ActiveConsole->InputEvents.Blink;
-                TempInput != (ConsoleInput *)&ActiveConsole->InputEvents &&
-                (TempInput->InputEvent.EventType != KEY_EVENT ||
-                TempInput->InputEvent.Event.KeyEvent.bKeyDown == FALSE ||
-                TempInput->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' );
-                TempInput = (ConsoleInput *)TempInput->ListEntry.Blink );
+                 TempInput != (ConsoleInput *)&ActiveConsole->InputEvents &&
+                 (TempInput->InputEvent.EventType != KEY_EVENT ||
+                 TempInput->InputEvent.Event.KeyEvent.bKeyDown == FALSE ||
+                 TempInput->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' );
+                 TempInput = (ConsoleInput *)TempInput->ListEntry.Blink );
            // if we found one, delete it, otherwise, wake the client
            if( TempInput != (ConsoleInput *)&ActiveConsole->InputEvents )
               {
                  // delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue
-                 TempInput->ListEntry.Blink->Flink = TempInput->ListEntry.Flink;
-                 TempInput->ListEntry.Flink->Blink = TempInput->ListEntry.Blink;
+      RemoveEntryList(&TempInput->ListEntry);
                  if( TempInput->Echoed )
                     CsrpWriteConsole( ActiveConsole->ActiveBuffer, &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE );
                  RtlFreeHeap( CsrssApiHeap, 0, TempInput );
-                 KeyEventRecord->ListEntry.Blink->Flink = KeyEventRecord->ListEntry.Flink;
-                 KeyEventRecord->ListEntry.Flink->Blink = KeyEventRecord->ListEntry.Blink;
+      RemoveEntryList(&KeyEventRecord->ListEntry);
                  RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
                  ActiveConsole->WaitingChars -= 2;
               }
            else NtSetEvent( ActiveConsole->ActiveEvent, 0 );
-        }
+   }
       else {
         // echo chars if we are supposed to and client is waiting for some
-        if( ActiveConsole->Mode & ENABLE_ECHO_INPUT && ActiveConsole->EchoCount &&
+        if( ( ActiveConsole->Mode & ENABLE_ECHO_INPUT ) && ActiveConsole->EchoCount &&
             KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar &&
             KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE &&
             KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\r' )
@@ -876,7 +1111,8 @@ CSR_API(CsrGetScreenBufferInfo)
      sizeof(LPC_MESSAGE_HEADER);
 
    LOCK;
-   if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle, (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC )
+   if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle,
+     (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC )
       {
         UNLOCK;
         return Reply->Status = STATUS_INVALID_HANDLE;
@@ -884,7 +1120,8 @@ CSR_API(CsrGetScreenBufferInfo)
    pInfo = &Reply->Data.ScreenBufferInfoReply.Info;
    if( Buff == ActiveConsole->ActiveBuffer )
      {
-       Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 0, 0, pInfo, sizeof( *pInfo ) );
+       Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
+    IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 0, 0, pInfo, sizeof( *pInfo ) );
        if( !NT_SUCCESS( Status ) )
           DbgPrint( "CSR: Failed to get console info, expect trouble\n" );
        Reply->Status = Status;
@@ -917,7 +1154,8 @@ CSR_API(CsrSetCursor)
      sizeof(LPC_MESSAGE_HEADER);
 
    LOCK;
-   if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC )
+   if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.SetCursorRequest.ConsoleHandle,
+     (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC )
       {
         UNLOCK;
         return Reply->Status = STATUS_INVALID_HANDLE;
@@ -926,10 +1164,12 @@ CSR_API(CsrSetCursor)
    Info.wAttributes = Buff->DefaultAttrib;
    if( Buff == ActiveConsole->ActiveBuffer )
       {
-        Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &Info, sizeof( Info ), 0, 0 );
+        Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
+     IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &Info, sizeof( Info ), 0, 0 );
        if( !NT_SUCCESS( Status ) )
           DbgPrint( "CSR: Failed to set console info, expect trouble\n" );
       }
+
    Buff->CurrentX = Info.dwCursorPosition.X + Buff->ShowX;
    Buff->CurrentY = (Info.dwCursorPosition.Y + Buff->ShowY) % Buff->MaxY;
    UNLOCK;
@@ -1018,6 +1258,7 @@ CSR_API(CsrFillOutputChar)
 
 CSR_API(CsrReadInputEvent)
 {
+   PLIST_ENTRY CurrentEntry;
    PCSRSS_CONSOLE Console;
    NTSTATUS Status;
    ConsoleInput *Input;
@@ -1035,15 +1276,16 @@ CSR_API(CsrReadInputEvent)
         UNLOCK;
         return Status;
       }
+
    // only get input if there is input, and we are not in line input mode, or if we are, if we have a whole line
-   if( Console->InputEvents.Flink != &Console->InputEvents &&
-       ( !Console->Mode & ENABLE_LINE_INPUT || Console->WaitingLines ) )     
+   if( ( Console->InputEvents.Flink != &Console->InputEvents ) &&
+       ( !( Console->Mode & ENABLE_LINE_INPUT ) || ( Console->WaitingLines > 0 ) ) )
      {
-       Input = (ConsoleInput *)Console->InputEvents.Flink;
-       Input->ListEntry.Blink->Flink = Input->ListEntry.Flink;
-       Input->ListEntry.Flink->Blink = Input->ListEntry.Blink;
+  CurrentEntry = RemoveHeadList(&Console->InputEvents);
+  Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
        Reply->Data.ReadInputReply.Input = Input->InputEvent;
-       if( Console->Mode & ENABLE_LINE_INPUT &&
+
+  if( Console->Mode & ENABLE_LINE_INPUT &&
            Input->InputEvent.Event.KeyEvent.bKeyDown == FALSE &&
            Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' )
          Console->WaitingLines--;
@@ -1204,7 +1446,9 @@ CSR_API(CsrSetCursorInfo)
    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
       sizeof(LPC_MESSAGE_HEADER);
    LOCK;
-   Status = CsrGetObject( ProcessData, Request->Data.SetCursorInfoRequest.ConsoleHandle, (Object_t **)&Buff );
+   Status = CsrGetObject( ProcessData,
+     Request->Data.SetCursorInfoRequest.ConsoleHandle, (Object_t **)&Buff );
+
    if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE ))
       {
         Reply->Status = Status;
@@ -1270,13 +1514,16 @@ CSR_API(CsrSetConsoleMode)
    Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER);
    LOCK;
-   Status = CsrGetObject( ProcessData, Request->Data.SetConsoleModeRequest.ConsoleHandle, (Object_t **)&Console );
+   Status = CsrGetObject( ProcessData,
+     Request->Data.SetConsoleModeRequest.ConsoleHandle,
+     (Object_t **)&Console );
    if( !NT_SUCCESS( Status ) )
       {
         Reply->Status = Status;
         UNLOCK;
         return Status;
       }
+
    Buff = (PCSRSS_SCREEN_BUFFER)Console;
    if( Console->Header.Type == CSRSS_CONSOLE_MAGIC )
       Console->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_INPUT_MODE_VALID;
@@ -1301,7 +1548,9 @@ CSR_API(CsrGetConsoleMode)
    Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER);
    LOCK;
-   Status = CsrGetObject( ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle, (Object_t **)&Console );
+   Status = CsrGetObject( ProcessData,
+     Request->Data.GetConsoleModeRequest.ConsoleHandle,
+     (Object_t **)&Console );
    if( !NT_SUCCESS( Status ) )
       {
         Reply->Status = Status;
@@ -1310,9 +1559,9 @@ CSR_API(CsrGetConsoleMode)
       }
    Reply->Status = STATUS_SUCCESS;
    Buff = (PCSRSS_SCREEN_BUFFER)Console;
-   if( Console->Header.Type = CSRSS_CONSOLE_MAGIC )
+   if( Console->Header.Type == CSRSS_CONSOLE_MAGIC )
       Reply->Data.GetConsoleModeReply.ConsoleMode = Console->Mode;
-   else if( Buff->Header.Type = CSRSS_SCREEN_BUFFER_MAGIC )
+   else if( Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC )
       Reply->Data.GetConsoleModeReply.ConsoleMode = Buff->Mode;
    else Status = STATUS_INVALID_HANDLE;
    UNLOCK;
@@ -1428,4 +1677,204 @@ CSR_API(CsrGetTitle)
        return Reply->Status;
 }
 
+CSR_API(CsrWriteConsoleOutput)
+{
+   SHORT i, X, Y, SizeX, SizeY;
+   PCSRSS_SCREEN_BUFFER Buff;
+   SMALL_RECT ScreenBuffer;
+   CHAR_INFO* CurCharInfo;
+   SMALL_RECT WriteRegion;
+   CHAR_INFO* CharInfo;
+   COORD BufferCoord;
+   COORD BufferSize;
+   NTSTATUS Status;
+   DWORD Offset;
+
+   Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
+   Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER);
+   LOCK;
+   Status = CsrGetObject( ProcessData, Request->Data.WriteConsoleOutputRequest.ConsoleHandle, (Object_t **)&Buff );
+   if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? STATUS_SUCCESS : STATUS_INVALID_HANDLE ))
+      {
+        Reply->Status = Status;
+        UNLOCK;
+        return Status;
+      }
+
+   BufferSize = Request->Data.WriteConsoleOutputRequest.BufferSize;
+   BufferCoord = Request->Data.WriteConsoleOutputRequest.BufferCoord;
+   CharInfo = (CHAR_INFO*)&Request->Data.WriteConsoleOutputRequest.CharInfo;
+   WriteRegion = Request->Data.WriteConsoleOutputRequest.WriteRegion;
+
+   SizeY = RtlMin(BufferSize.Y - BufferCoord.Y, CsrpRectHeight(WriteRegion));
+   SizeX = RtlMin(BufferSize.X - BufferCoord.X, CsrpRectWidth(WriteRegion));
+   WriteRegion.Bottom = WriteRegion.Top + SizeY;
+   WriteRegion.Right = WriteRegion.Left + SizeX;
+
+   /* Make sure WriteRegion is inside the screen buffer */
+   CsrpInitRect(ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
+   if (!CsrpGetIntersection(&WriteRegion, ScreenBuffer, WriteRegion))
+      {
+         UNLOCK;
+         /* It is okay to have a WriteRegion completely outside the screen buffer.
+            No data is written then. */
+         return (Reply->Status = STATUS_SUCCESS);
+      }
+
+   for ( i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++ )
+   {
+     CurCharInfo = CharInfo + (i * BufferSize.Y);
+     Offset = (Y * Buff->MaxX + WriteRegion.Left) * 2;
+     for ( X = WriteRegion.Left; X <= WriteRegion.Right; X++ )
+      {
+        SET_CELL_BUFFER(Buff, Offset, CurCharInfo->Char.AsciiChar, CurCharInfo->Attributes);
+        CurCharInfo++;
+      }
+   }
+
+   if( Buff == ActiveConsole->ActiveBuffer )
+     {
+        CsrpDrawRegion( ActiveConsole->ActiveBuffer, WriteRegion );
+     }
+
+   UNLOCK;
+   Reply->Data.WriteConsoleOutputReply.WriteRegion.Right = WriteRegion.Left + SizeX - 1;
+   Reply->Data.WriteConsoleOutputReply.WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
+   return (Reply->Status = STATUS_SUCCESS);
+}
+
+CSR_API(CsrFlushInputBuffer)
+{
+  PLIST_ENTRY CurrentEntry;
+  PLIST_ENTRY NextEntry;
+  PCSRSS_CONSOLE Console;
+  ConsoleInput* Input;
+  NTSTATUS Status;
+
+  Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
+  Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER);
+  LOCK;
+  Status = CsrGetObject( ProcessData, Request->Data.FlushInputBufferRequest.ConsoleInput, (Object_t **)&Console );
+  if( !NT_SUCCESS( Status ) || (Status = Console->Header.Type == CSRSS_CONSOLE_MAGIC ? STATUS_SUCCESS : STATUS_INVALID_HANDLE ))
+    {
+       Reply->Status = Status;
+       UNLOCK;
+       return Status;
+    }
+
+  /* Discard all entries in the input event queue */
+  CurrentEntry = Console->InputEvents.Flink;
+  while (IsListEmpty(&Console->InputEvents))
+    {
+  NextEntry = CurrentEntry->Flink;
+  Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
+  /* Destroy the event */
+  Console->WaitingChars--;
+       RtlFreeHeap( CsrssApiHeap, 0, Input );
+  CurrentEntry = NextEntry;
+    }
+  UNLOCK;
+
+  return (Reply->Status = STATUS_SUCCESS);
+}
+
+CSR_API(CsrScrollConsoleScreenBuffer)
+{
+  SHORT i, X, Y, SizeX, SizeY;
+  PCSRSS_SCREEN_BUFFER Buff;
+  SMALL_RECT ScreenBuffer;
+  SMALL_RECT SrcRegion;
+  SMALL_RECT DstRegion;
+  SMALL_RECT FillRegion;
+  IO_STATUS_BLOCK Iosb;
+  CHAR_INFO* CharInfo;
+  NTSTATUS Status;
+  DWORD SrcOffset;
+  DWORD DstOffset;
+  BOOLEAN DoFill;
+
+  ALIAS(ConsoleHandle,Request->Data.ScrollConsoleScreenBufferRequest.ConsoleHandle);
+  ALIAS(ScrollRectangle,Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle);
+  ALIAS(UseClipRectangle,Request->Data.ScrollConsoleScreenBufferRequest.UseClipRectangle);
+  ALIAS(ClipRectangle,Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle);
+  ALIAS(DestinationOrigin,Request->Data.ScrollConsoleScreenBufferRequest.DestinationOrigin);
+  ALIAS(Fill,Request->Data.ScrollConsoleScreenBufferRequest.Fill);
+
+  Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
+  Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER);
+  LOCK;
+  Status = CsrGetObject( ProcessData, ConsoleHandle, (Object_t **)&Buff );
+  if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? STATUS_SUCCESS : STATUS_INVALID_HANDLE ))
+  {
+    Reply->Status = Status;
+    UNLOCK;
+    return Status;
+  }
+
+  /* Make sure source rectangle is inside the screen buffer */
+  CsrpInitRect(ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
+  if (!CsrpGetIntersection(&SrcRegion, ScreenBuffer, ScrollRectangle))
+    {
+      UNLOCK;
+      return (Reply->Status = STATUS_INVALID_PARAMETER);
+    }
+
+  if (UseClipRectangle)
+    {
+      if (!CsrpGetIntersection(&SrcRegion, SrcRegion, ClipRectangle))
+        {
+          UNLOCK;
+          return (Reply->Status = STATUS_SUCCESS);
+        }
+    }
+
+
+  CsrpInitRect(
+    DstRegion,
+    DestinationOrigin.Y,
+    DestinationOrigin.X,
+    DestinationOrigin.Y + CsrpRectHeight(ScrollRectangle) - 1,
+    DestinationOrigin.X + CsrpRectWidth(ScrollRectangle) - 1)
+
+  /* Make sure destination rectangle is inside the screen buffer */
+  if (!CsrpGetIntersection(&DstRegion, DstRegion, ScreenBuffer))
+    {
+      UNLOCK;
+      return (Reply->Status = STATUS_INVALID_PARAMETER);
+    }
+
+  CsrpCopyRegion(Buff, SrcRegion, DstRegion);
+
+
+  /* Get the region that should be filled with the specified character and attributes */
+
+  DoFill = FALSE;
+
+  CsrpGetUnion(&FillRegion, SrcRegion, DstRegion);
+
+  if (CsrpSubtractRect(&FillRegion, FillRegion, DstRegion))
+    {
+      /* FIXME: The subtracted rectangle is off by one line */
+      FillRegion.Top += 1;
+
+      CsrpFillRegion(Buff, FillRegion, Fill);
+      DoFill = TRUE;
+    }
+
+  if( Buff == ActiveConsole->ActiveBuffer )
+    {
+      /* Draw destination region */
+      CsrpDrawRegion(ActiveConsole->ActiveBuffer, DstRegion);
+
+      if (DoFill)
+        {
+          /* Draw filled region */
+          CsrpDrawRegion(ActiveConsole->ActiveBuffer, FillRegion);
+        }
+    }
+
+   UNLOCK;
+   return (Reply->Status = STATUS_SUCCESS);
+}
+
 /* EOF */
index 069e8da..6929682 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.13 2001/08/14 12:57:16 ea Exp $
+/* $Id: process.c,v 1.14 2001/09/01 15:36:45 chorns Exp $
  *
  * reactos/subsys/csrss/api/process.c
  *
@@ -156,7 +156,7 @@ CSR_API(CsrCreateProcess)
        NewProcessData->Console = ProcessData->Console;
        InterlockedIncrement( &(ProcessData->Console->Header.ReferenceCount) );
      }
-   
+   DbgPrint("Before type\n");
    if( NewProcessData->Console )
      {
        CLIENT_ID ClientId;
@@ -164,7 +164,17 @@ CSR_API(CsrCreateProcess)
                       &Reply->Data.CreateProcessReply.InputHandle,
                       (Object_t *)NewProcessData->Console);
        RtlEnterCriticalSection( &ActiveConsoleLock );
-       CsrInsertObject( NewProcessData, &Reply->Data.CreateProcessReply.OutputHandle, &(NewProcessData->Console->ActiveBuffer->Header) );
+       CsrInsertObject( NewProcessData,
+          &Reply->Data.CreateProcessReply.OutputHandle,
+          &(NewProcessData->Console->ActiveBuffer->Header) );
+
+
+       DbgPrint("OutputHandle %x\n", Reply->Data.CreateProcessReply.OutputHandle);
+       DbgPrint("Console %x\n", NewProcessData->Console);
+       DbgPrint("Console->ActiveBuffer %x\n", NewProcessData->Console->ActiveBuffer);
+       DbgPrint("Type %x\n", NewProcessData->Console->ActiveBuffer->Header.Type);
+
+
        RtlLeaveCriticalSection( &ActiveConsoleLock );
        ClientId.UniqueProcess = (HANDLE)NewProcessData->ProcessId;
        Status = NtOpenProcess( &Process, PROCESS_DUP_HANDLE, 0, &ClientId );
index 535f875..3d73ec6 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: wapi.c,v 1.14 2001/08/14 12:57:16 ea Exp $
+/* $Id: wapi.c,v 1.15 2001/09/01 15:36:45 chorns Exp $
  * 
  * reactos/subsys/csrss/api/wapi.c
  *
@@ -11,6 +11,7 @@
 /* INCLUDES ******************************************************************/
 
 #include <ddk/ntddk.h>
+#include <windows.h>
 #include <ntdll/rtl.h>
 #include <csrss/csrss.h>
 #include <debug.h>
@@ -49,6 +50,9 @@ static const CsrFunc CsrFuncs[] = {
    CsrSetScreenBuffer,
    CsrSetTitle,
    CsrGetTitle,
+   CsrWriteConsoleOutput,
+   CsrFlushInputBuffer,
+   CsrScrollConsoleScreenBuffer,
    0 };
 
 static void Thread_Api2(HANDLE ServerPort)