Extension of ntdll.NtQuerySystemInformation implementation

Eric Pouech pouech-eric at wanadoo.fr
Sat Sep 13 07:59:50 CDT 2003


A+
-- 
Eric Pouech
-------------- next part --------------
Name:          ntsys
ChangeLog:     
- Implemented a few information classes in NtQuerySystemInformation
- Added handle information to (wineserver) process snapshop
License:       X11
GenDate:       2003/09/13 12:54:02 UTC
ModifiedFiles: include/winternl.h dlls/ntdll/nt.c server/handle.c server/handle.h server/process.c server/process.h server/protocol.def server/snapshot.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/include/winternl.h,v
retrieving revision 1.54
diff -u -u -r1.54 winternl.h
--- include/winternl.h	8 Sep 2003 19:02:01 -0000	1.54
+++ include/winternl.h	13 Sep 2003 08:14:38 -0000
@@ -482,17 +482,18 @@
 /* This is used by NtQuerySystemInformation */
 /* FIXME: Isn't THREAD_INFO and THREADINFO the same structure? */
 typedef struct {
-    FILETIME ftCreationTime;
-    DWORD dwUnknown1;
-    DWORD dwStartAddress;
-    DWORD dwOwningPID;
-    DWORD dwThreadID;
-    DWORD dwCurrentPriority;
-    DWORD dwBasePriority;
-    DWORD dwContextSwitches;
-    DWORD dwThreadState;
-    DWORD dwWaitReason;
-    DWORD dwUnknown2[5];
+    FILETIME    ftKernelTime;
+    FILETIME    ftUserTime;
+    FILETIME    ftCreateTime;
+    DWORD       dwTickCount;
+    DWORD       dwStartAddress;
+    DWORD       dwOwningPID;
+    DWORD       dwThreadID;
+    DWORD       dwCurrentPriority;
+    DWORD       dwBasePriority;
+    DWORD       dwContextSwitches;
+    DWORD       dwThreadState;
+    DWORD       dwWaitReason;
 } THREADINFO, *PTHREADINFO;
 
 /* FIXME: Isn't THREAD_INFO and THREADINFO the same structure? */
@@ -771,7 +772,7 @@
 typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
 #ifdef __WINESRC__
     LARGE_INTEGER liIdleTime;
-    DWORD dwSpare[76];
+    DWORD dwSpare[10];
 #else
     LARGE_INTEGER IdleTime;
     LARGE_INTEGER KernelTime;
Index: dlls/ntdll/nt.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/ntdll/nt.c,v
retrieving revision 1.56
diff -u -u -r1.56 nt.c
--- dlls/ntdll/nt.c	8 Sep 2003 19:02:01 -0000	1.56
+++ dlls/ntdll/nt.c	13 Sep 2003 09:46:12 -0000
@@ -139,6 +139,7 @@
 			ProcessInformation,ProcessInformationLength,
 			ReturnLength
 		);
+                ret = STATUS_NOT_IMPLEMENTED;
 		break;
 	}
 
@@ -316,7 +317,7 @@
     *retlen = len;
 
     if (tokeninfolength < len)
-        return STATUS_BUFFER_TOO_SMALL;
+        return STATUS_INFO_LENGTH_MISMATCH;
 
     switch (tokeninfoclass)
     {
@@ -542,28 +543,226 @@
 	IN ULONG Length,
 	OUT PULONG ResultLength)
 {
-    switch(SystemInformationClass)
+    NTSTATUS    ret = STATUS_SUCCESS;
+    ULONG       len = 0;
+
+    TRACE("(0x%08x,%p,0x%08lx,%p)\n",
+          SystemInformationClass,SystemInformation,Length,ResultLength);
+
+    switch (SystemInformationClass)
     {
-    case 0x25:
+    case SystemBasicInformation:
+        {
+            SYSTEM_BASIC_INFORMATION* sbi = (SYSTEM_BASIC_INFORMATION*)SystemInformation;
+            if (Length >= sizeof(*sbi))
+            {
+                sbi->dwUnknown1 = 0;
+                sbi->uKeMaximumIncrement = 0;
+                sbi->uPageSize = 1024; /* FIXME */
+                sbi->uMmNumberOfPhysicalPages = 12345; /* FIXME */
+                sbi->uMmLowestPhysicalPage = 0; /* FIXME */
+                sbi->uMmHighestPhysicalPage = 12345; /* FIXME */
+                sbi->uAllocationGranularity = 65536; /* FIXME */
+                sbi->pLowestUserAddress = 0; /* FIXME */
+                sbi->pMmHighestUserAddress = (void*)~0; /* FIXME */
+                sbi->uKeActiveProcessors = 1; /* FIXME */
+                sbi->bKeNumberProcessors = 1; /* FIXME */
+                len = sizeof(*sbi);
+            }
+            else ret = STATUS_INFO_LENGTH_MISMATCH;
+        }
+        break;
+    case SystemPerformanceInformation:
+        {
+            SYSTEM_PERFORMANCE_INFORMATION* spi = (SYSTEM_PERFORMANCE_INFORMATION*)SystemInformation;
+            if (Length >= sizeof(*spi))
+            {
+                memset(spi, 0, sizeof(*spi)); /* FIXME */
+                len = sizeof(*spi);
+            }
+            else ret = STATUS_INFO_LENGTH_MISMATCH;
+        }
+        break;
+    case SystemTimeOfDayInformation:
+        {
+            SYSTEM_TIMEOFDAY_INFORMATION* sti = (SYSTEM_TIMEOFDAY_INFORMATION*)SystemInformation;
+            if (Length >= sizeof(*sti))
+            {
+                sti->liKeBootTime.QuadPart = 0; /* FIXME */
+                sti->liKeSystemTime.QuadPart = 0; /* FIXME */
+                sti->liExpTimeZoneBias.QuadPart  = 0; /* FIXME */
+                sti->uCurrentTimeZoneId = 0; /* FIXME */
+                sti->dwReserved = 0;
+                len = sizeof(*sti);
+            }
+            else ret = STATUS_INFO_LENGTH_MISMATCH;
+        }
+        break;
+    case SystemProcessInformation:
+        {
+            SYSTEM_PROCESS_INFORMATION* spi = (SYSTEM_PROCESS_INFORMATION*)SystemInformation;
+            SYSTEM_PROCESS_INFORMATION* last = NULL;
+            HANDLE hSnap = 0;
+            char procname[1024];
+            DWORD wlen;
+
+            SERVER_START_REQ( create_snapshot )
+            {
+                req->flags   = SNAP_PROCESS | SNAP_THREAD;
+                req->inherit = FALSE;
+                req->pid     = 0;
+                if (!(ret = wine_server_call( req ))) hSnap = reply->handle;
+            }
+            SERVER_END_REQ;
+            len = 0;
+            while (ret == STATUS_SUCCESS)
+            {
+                SERVER_START_REQ( next_process )
+                {
+                    req->handle = hSnap;
+                    req->reset = (len == 0);
+                    wine_server_set_reply( req, procname, sizeof(procname)-1 );
+                    if (!(ret = wine_server_call( req )))
+                    {
+                        procname[wine_server_reply_size(reply)] = 0;
+                        if (Length >= len + sizeof(*spi))
+                        {
+                            memset(spi, 0, sizeof(*spi));
+                            spi->dwOffset = sizeof(*spi);
+                            spi->dwThreadCount = reply->threads;
+                            memset(&spi->ftCreationTime, 0, sizeof(spi->ftCreationTime));
+                            /* spi->pszProcessName will be set later on */
+                            spi->dwBasePriority = reply->priority;
+                            spi->dwProcessID = (DWORD)reply->pid;
+                            spi->dwParentProcessID = (DWORD)reply->ppid;
+                            spi->dwHandleCount = reply->handles;
+                            spi->dwVirtualBytesPeak = 0; /* FIXME */
+                            spi->dwVirtualBytes = 0; /* FIXME */
+                            spi->dwPageFaults = 0; /* FIXME */
+                            spi->dwWorkingSetPeak = 0; /* FIXME */
+                            spi->dwWorkingSet = 0; /* FIXME */
+                            spi->dwUnknown5 = 0; /* FIXME */
+                            spi->dwPagedPool = 0; /* FIXME */
+                            spi->dwUnknown6 = 0; /* FIXME */
+                            spi->dwNonPagedPool = 0; /* FIXME */
+                            spi->dwPageFileBytesPeak = 0; /* FIXME */
+                            spi->dwPrivateBytes = 0; /* FIXME */
+                            spi->dwPageFileBytes = 0; /* FIXME */
+                            /* spi->ti will be set later on */
+                            len += sizeof(*spi) - sizeof(spi->ti);
+                        }
+                        else ret = STATUS_INFO_LENGTH_MISMATCH;
+                    }
+                }
+                SERVER_END_REQ;
+                if (ret != STATUS_SUCCESS)
+                {
+                    if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS;
+                    break;
+                }
+                RtlMultiByteToUnicodeN(NULL, 0, &wlen, procname, strlen(procname) + 1);
+                if (Length >= len + wlen + spi->dwThreadCount * sizeof(THREAD_INFO))
+                {
+                    int     i, j;
+
+                    /* set thread info */
+                    spi->dwOffset += spi->dwThreadCount * sizeof(THREAD_INFO);
+                    len += spi->dwThreadCount * sizeof(THREAD_INFO);
+                    i = j = 0;
+                    while (ret == STATUS_SUCCESS)
+                    {
+                        SERVER_START_REQ( next_thread )
+                        {
+                            req->handle = hSnap;
+                            req->reset = (j == 0);
+                            if (!(ret = wine_server_call( req )))
+                            {
+                                j++;
+                                if (reply->pid == spi->dwProcessID)
+                                {
+                                    /* ftKernelTime, ftUserTime, ftCreateTime;
+                                     * dwTickCount, dwStartAddress
+                                     */
+                                    spi->ti[i].dwOwningPID = reply->pid;
+                                    spi->ti[i].dwThreadID  = reply->tid;
+                                    spi->ti[i].dwCurrentPriority = reply->base_pri + reply->delta_pri;
+                                    spi->ti[i].dwBasePriority = reply->base_pri;
+                                    i++;
+                                }
+                            }
+                        }
+                        SERVER_END_REQ;
+                    }
+                    if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS;
+
+                    /* now append process name */
+                    spi->pszProcessName = (WCHAR*)((char*)spi + spi->dwOffset);
+                    RtlMultiByteToUnicodeN( spi->pszProcessName, wlen, NULL, procname, strlen(procname) + 1);
+                    len += wlen;
+                    spi->dwOffset += wlen;
+
+                    last = spi;
+                    spi = (SYSTEM_PROCESS_INFORMATION*)((char*)spi + spi->dwOffset);
+                }
+                else ret = STATUS_INFO_LENGTH_MISMATCH;
+            }
+            if (ret == STATUS_SUCCESS && last) last->dwOffset = 0;
+            if (hSnap) NtClose(hSnap);
+        }
+        break;
+    case SystemProcessorPerformanceInformation:
+        {
+            SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*)SystemInformation;
+            if (Length >= sizeof(*sppi))
+            {
+                memset(sppi, 0, sizeof(*sppi)); /* FIXME */
+                len = sizeof(*sppi);
+            }
+            else ret = STATUS_INFO_LENGTH_MISMATCH;
+        }
+        break;
+
+    case SystemCacheInformation:
+        {
+            SYSTEM_CACHE_INFORMATION* sci = (SYSTEM_CACHE_INFORMATION*)SystemInformation;
+            if (Length >= sizeof(*sci))
+            {
+                memset(sci, 0, sizeof(*sci)); /* FIXME */
+                len = sizeof(*sci);
+            }
+            else ret = STATUS_INFO_LENGTH_MISMATCH;
+        }
+        break;
+    case SystemRegistryQuotaInformation:
 	/* Something to do with the size of the registry             *
 	 * Since we don't have a size limitation, fake it            *
 	 * This is almost certainly wrong.                           *
 	 * This sets each of the three words in the struct to 32 MB, *
 	 * which is enough to make the IE 5 installer happy.         */
-	FIXME("(0x%08x,%p,0x%08lx,%p) faking max registry size of 32 MB\n",
-	      SystemInformationClass,SystemInformation,Length,ResultLength);
-	*(DWORD *)SystemInformation = 0x2000000;
-	*(((DWORD *)SystemInformation)+1) = 0x200000;
-	*(((DWORD *)SystemInformation)+2) = 0x200000;
+        {
+            SYSTEM_REGISTRY_QUOTA_INFORMATION* srqi = (SYSTEM_REGISTRY_QUOTA_INFORMATION*)SystemInformation;
+            if (Length >= sizeof(*srqi))
+            {
+                FIXME("(0x%08x,%p,0x%08lx,%p) faking max registry size of 32 MB\n",
+                      SystemInformationClass,SystemInformation,Length,ResultLength);
+                srqi->RegistryQuotaAllowed = 0x2000000;
+                srqi->RegistryQuotaUsed = 0x200000;
+                srqi->Reserved1 = (void*)0x200000;
+                if (ResultLength) *ResultLength = sizeof(*srqi);
+            }
+            else ret = STATUS_INFO_LENGTH_MISMATCH;
+        }
 	break;
 
     default:
 	FIXME("(0x%08x,%p,0x%08lx,%p) stub\n",
 	      SystemInformationClass,SystemInformation,Length,ResultLength);
-	ZeroMemory (SystemInformation, Length);
+	memset(SystemInformation, 0, Length);
+        ret = STATUS_NOT_IMPLEMENTED;
     }
+    if (ResultLength) *ResultLength = len;
 
-    return STATUS_SUCCESS;
+    return ret;
 }
 
 
Index: server/handle.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/server/handle.c,v
retrieving revision 1.28
diff -u -u -r1.28 handle.c
--- server/handle.c	5 Sep 2003 23:15:41 -0000	1.28
+++ server/handle.c	13 Sep 2003 08:52:56 -0000
@@ -503,6 +503,11 @@
     return handle;
 }
 
+unsigned get_handle_table_count( struct process *process )
+{
+    return process->handles->count;
+}
+
 /* close a handle */
 DECL_HANDLER(close_handle)
 {
Index: server/handle.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/server/handle.h,v
retrieving revision 1.12
diff -u -u -r1.12 handle.h
--- server/handle.h	14 Feb 2003 20:27:10 -0000	1.12
+++ server/handle.h	13 Sep 2003 08:52:16 -0000
@@ -47,6 +47,8 @@
 extern obj_handle_t find_inherited_handle( struct process *process, const struct object_ops *ops );
 extern struct handle_table *alloc_handle_table( struct process *process, int count );
 extern struct handle_table *copy_handle_table( struct process *process, struct process *parent );
+extern unsigned get_handle_table_count( struct process *process);
+
 extern void close_global_handles(void);
 
 #endif  /* __WINE_SERVER_HANDLE_H */
Index: server/process.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/server/process.c,v
retrieving revision 1.109
diff -u -u -r1.109 process.c
--- server/process.c	5 Sep 2003 23:15:41 -0000	1.109
+++ server/process.c	13 Sep 2003 09:10:07 -0000
@@ -845,6 +846,7 @@
         ptr->threads  = process->running_threads;
         ptr->count    = process->obj.refcount;
         ptr->priority = process->priority;
+        ptr->handles  = get_handle_table_count(process);
         grab_object( process );
         ptr++;
     }
Index: server/process.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/server/process.h,v
retrieving revision 1.38
diff -u -u -r1.38 process.h
--- server/process.h	24 Jul 2003 00:07:00 -0000	1.38
+++ server/process.h	13 Sep 2003 08:49:52 -0000
@@ -86,6 +87,7 @@
     int             count;    /* process refcount */
     int             threads;  /* number of threads */
     int             priority; /* priority class */
+    int             handles;  /* handles */
 };
 
 struct module_snapshot
Index: server/protocol.def
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/server/protocol.def,v
retrieving revision 1.81
diff -u -u -r1.81 protocol.def
--- server/protocol.def	8 Sep 2003 19:04:01 -0000	1.81
+++ server/protocol.def	13 Sep 2003 08:48:53 -0000
@@ -1175,6 +1177,7 @@
     void*        module;        /* main module */
     int          threads;       /* number of threads */
     int          priority;      /* process priority */
+    int          handles;       /* number of handles */
     VARARG(filename,string);    /* file name of main exe */
 @END
 
Index: server/snapshot.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/server/snapshot.c,v
retrieving revision 1.21
diff -u -u -r1.21 snapshot.c
--- server/snapshot.c	19 Feb 2003 00:33:33 -0000	1.21
+++ server/snapshot.c	13 Sep 2003 09:28:08 -0000
@@ -128,6 +128,7 @@
     reply->module   = 0;  /* FIXME */
     reply->threads  = ptr->threads;
     reply->priority = ptr->priority;
+    reply->handles  = ptr->handles;
     if (ptr->process->exe.filename)
     {
         size_t len = min( ptr->process->exe.namelen, get_reply_max_size() );


More information about the wine-patches mailing list