CVS: winex/dlls/ntdll nt.c,1.20,1.21

[email protected] 12 Sep 2007 12:46:35 -0000
Newsgroups gmane.comp.emulators.winex.cvs
Message-ID <[email protected]>
Subject: winex/dlls/ntdll nt.c,1.20,1.21Update of /var/lib/cvsd/cvsroot/winex/dlls/ntdll
In directory agravaine:/tmp/cvs-serv14019/dlls/ntdll

Modified Files:
	nt.c 
Log Message:
Implement SystemProcessInformation class.
TRAC #1971
Partially implement the SystemProcessInformation class for NtQuerySystemInformation, at least sufficiently for the dbghelp minidump requirements. Quite a few of the returned structure members are not filled in currently and are just zeroed.


Index: nt.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/ntdll/nt.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- nt.c	12 Sep 2007 12:40:02 -0000	1.20
+++ nt.c	12 Sep 2007 12:46:33 -0000	1.21
@@ -16,6 +16,7 @@
 
 #include "winternl.h"
 #include "ntdll_misc.h"
+#include "tlhelp32.h"
 #include "wine/server.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
@@ -765,34 +766,143 @@
 	return 0;
 }
 
+
 /******************************************************************************
- *  NtCreateMailslotFile	[NTDLL.@]
- *  ZwCreateMailslotFile	[NTDLL.@]
+ * Helper for NtQuerySystemInformation
  */
-NTSTATUS WINAPI NtCreateMailslotFile(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6,DWORD x7,DWORD x8)
+static NTSTATUS SnapCreate (HANDLE *pSnap)
 {
-	FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4,x5,x6,x7,x8);
-	return 0;
+   NTSTATUS Ret;
+
+   /* Create initial snapshot */
+   SERVER_START_REQ (create_snapshot)
+   {
+      req->flags = TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD;
+      req->inherit = 0;
+      req->pid = 0;
+      if ((Ret = wine_server_call_err (req)) == STATUS_SUCCESS)
+         *pSnap = reply->handle;
+   }
+   SERVER_END_REQ;
+
+   if (*pSnap == INVALID_HANDLE_VALUE)
+      ERR ("Unable to create process snapshot!\n");
+
+   return Ret;
 }
 
 
-static NTSTATUS collectProcessInformation(void *buf, ULONG length, ULONG *resultLength){
-    if (buf){
-        FIXME("gather process information\n");
+/******************************************************************************
+ * Helper for NtQuerySystemInformation
+ */
+static NTSTATUS SnapGetNextProcess (HANDLE hSnap, DWORD LenLeft,
+                                    PSYSTEM_PROCESS_INFORMATION pSPI)
+{
+   NTSTATUS Ret;
+   CHAR ProcName[1024];
+   CHAR *pExeName;
+   DWORD Len, ExeLen;
+   STRING AnsiStr;
 
-        /* FIXME!! return an error for now */
-        return STATUS_ACCESS_VIOLATION;
-    }
+   SERVER_START_REQ (next_process)
+   {
+      req->handle = hSnap;
+      req->reset = FALSE;
+      wine_server_set_reply (req, ProcName, sizeof (ProcName));
+      if ((Ret = wine_server_call_err (req)) == STATUS_SUCCESS)
+      {
+         ProcName[wine_server_reply_size (reply)] = 0;
+         memset (pSPI, 0, sizeof (*pSPI));
+         pSPI->dwThreadCount = reply->threads;
+         pSPI->dwBasePriority = reply->priority;
+         pSPI->dwProcessID = (DWORD)reply->pid;
+         pSPI->dwParentProcessID = (DWORD)reply->ppid;
+      }
+   }
+   SERVER_END_REQ;
 
-    else{
-        if (resultLength)
-            *resultLength = 1024;
- 
-        return STATUS_ACCESS_VIOLATION;
-    }
+   if (Ret != STATUS_SUCCESS)
+      return Ret;
 
+   if ((pExeName = strrchr (ProcName, '\\')))
+      pExeName++;
+   else
+      pExeName = ProcName;
 
-    return STATUS_SUCCESS;
+   ExeLen = (strlen (pExeName) + 1) * sizeof (WCHAR);
+   Len = sizeof (*pSPI) + ExeLen +
+      (pSPI->dwThreadCount * sizeof (SYSTEM_THREAD_INFORMATION));
+
+   if (LenLeft < Len)
+      return STATUS_INFO_LENGTH_MISMATCH;
+
+   /* Place the exe name after the thread information array to match Windows */
+   pSPI->ProcessName.MaximumLength = ExeLen;
+   pSPI->ProcessName.Buffer = (LPWSTR)((CHAR *)pSPI + Len - ExeLen);
+   RtlInitAnsiString (&AnsiStr, pExeName);
+   if (RtlAnsiStringToUnicodeString (&pSPI->ProcessName, &AnsiStr, FALSE) != STATUS_SUCCESS)
+   {
+      ERR ("Failed to create Unicode string!\n");
+      return STATUS_INFO_LENGTH_MISMATCH;
+   }
+
+   pSPI->dwOffset = Len;
+
+   return Ret;
+}
+
+
+/******************************************************************************
+ * Helper for NtQuerySystemInformation
+ */
+static NTSTATUS SnapWalkThreads (HANDLE hSnap, PSYSTEM_PROCESS_INFORMATION pSPI)
+{
+   NTSTATUS Ret = STATUS_SUCCESS;
+   DWORD CurThread = 0;
+   BOOL First = TRUE;
+
+   while (Ret == STATUS_SUCCESS)
+   {
+      SERVER_START_REQ (next_thread)
+      {
+         req->handle = hSnap;
+         req->reset = First;
+         Ret = wine_server_call_err (req);
+         First = FALSE;
+         if (Ret == STATUS_SUCCESS)
+         {
+            PSYSTEM_THREAD_INFORMATION pSTI = &pSPI->ti[CurThread];
+
+            if (reply->pid != pSPI->dwProcessID)
+               continue;
+
+            memset (pSTI, 0, sizeof (pSPI->ti[0]));
+            pSTI->dwOwningPID = (DWORD)reply->pid;
+            pSTI->dwThreadID = (DWORD)reply->tid;
+            pSTI->dwCurrentPriority = reply->base_pri + reply->delta_pri;
+            pSTI->dwBasePriority = reply->base_pri;
+
+            CurThread++;
+         }
+      }
+      SERVER_END_REQ;
+   }
+
+   if (Ret == STATUS_NO_MORE_FILES)
+      Ret = STATUS_SUCCESS;
+
+   return Ret;
+}
+
+
+/******************************************************************************
+ *  NtCreateMailslotFile	[NTDLL.@]
+ *  ZwCreateMailslotFile	[NTDLL.@]
+ */
+NTSTATUS WINAPI NtCreateMailslotFile(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6,DWORD x7,DWORD x8)
+{
+	FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4,x5,x6,x7,x8);
+	return 0;
 }
 
 
@@ -824,9 +934,9 @@
     NTSTATUS result = STATUS_SUCCESS;
 
 
-    FIXME("(0x%08x,%p,0x%08lx,%p), mostly-stub!\n",
-            SystemInformationClass, SystemInformation,
-            Length, ResultLength);
+    TRACE ("(0x%08x,%p,0x%08lx,%p)\n",
+           SystemInformationClass, SystemInformation,
+           Length, ResultLength);
 
 
     /* native checks if the buffer length is 0 before checking if the buffer is NULL 
@@ -892,10 +1002,48 @@
 
             break;
 
-        case SystemProcessInformation:
-            FIXME("implement the SystemProcessInformation case!\n");
-            result = collectProcessInformation(SystemInformation, Length, ResultLength);
+        case SystemProcessInformation: {
+            PSYSTEM_PROCESS_INFORMATION pSPI =
+               (PSYSTEM_PROCESS_INFORMATION)SystemInformation;
+            PSYSTEM_PROCESS_INFORMATION pPrev;
+            HANDLE hSnap = INVALID_HANDLE_VALUE;
+            ULONG InitialLen = Length;
+
+            /* FIXME - Check data alignment & return
+               STATUS_DATATYPE_MISALIGNMENT if necessary */
+
+            FIXME ("SystemProcessInformation class only partially implemented\n");
+
+            if ((result = SnapCreate (&hSnap)) != STATUS_SUCCESS)
+               break;
+
+            /* Iterate over processes */
+            pPrev = pSPI;
+            while ((result = SnapGetNextProcess (hSnap, Length,
+                                                 pSPI)) == STATUS_SUCCESS)
+            {
+               /* Iterate over all threads, and get info on those threads
+                  that are in the current process*/
+               if ((result = SnapWalkThreads (hSnap, pSPI)) != STATUS_SUCCESS)
+                  break;
+
+               pPrev = pSPI;
+               pSPI = (PSYSTEM_PROCESS_INFORMATION)((char *)pSPI + pSPI->dwOffset);
+               Length -= pPrev->dwOffset;
+            }
+
+            /* Clean up snapshot */
+            NtClose (hSnap);
+            pPrev->dwOffset = 0;
+
+            if (result == STATUS_NO_MORE_FILES)
+               result = STATUS_SUCCESS;
+
+            if ((result == STATUS_SUCCESS) && ResultLength)
+               *ResultLength = InitialLen - Length;
+
             break;
+        }
 
         default:
             FIXME("(0x%08x,%p,0x%08lx,%p) stub\n",