CVS: winex/dlls/ntdll nt.c,1.21,1.22
[email protected] 12 Sep 2007 12:48:36 -0000
| Newsgroups | gmane.comp.emulators.winex.cvs |
|---|---|
| Message-ID | <[email protected]> |
Subject: winex/dlls/ntdll nt.c,1.21,1.22Update of /var/lib/cvsd/cvsroot/winex/dlls/ntdll
In directory agravaine:/tmp/cvs-serv14452/dlls/ntdll
Modified Files:
nt.c
Log Message:
made NtQuerySystemInformation()'s behaviour closer to native
trac #1971
- changed the process information gathering so that it could be passed NULL for the destination buffer. This would just calculate the [approximate] required size of the buffer.
- fixed up some of the function return values to match native.
Index: nt.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/ntdll/nt.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- nt.c 12 Sep 2007 12:46:33 -0000 1.21
+++ nt.c 12 Sep 2007 12:48:34 -0000 1.22
@@ -766,6 +766,16 @@
return 0;
}
+/******************************************************************************
+ * 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;
+}
+
/******************************************************************************
* Helper for NtQuerySystemInformation
@@ -792,117 +802,257 @@
}
+
/******************************************************************************
* Helper for NtQuerySystemInformation
+ *
+ * <hSnap> is the handle to an open process snapshot
+ * <processID> is the ID of the parent process of the threads to be enumerated
+ * <length> is the size of the buffer <pSTI> in bytes
+ * <pSTI> is the buffer to start storing the thread information blocks at
*/
-static NTSTATUS SnapGetNextProcess (HANDLE hSnap, DWORD LenLeft,
- PSYSTEM_PROCESS_INFORMATION pSPI)
+static NTSTATUS SnapWalkThreads(HANDLE hSnap, DWORD processID, DWORD length, SYSTEM_THREAD_INFORMATION *pSTI)
{
- NTSTATUS Ret;
- CHAR ProcName[1024];
- CHAR *pExeName;
- DWORD Len, ExeLen;
- STRING AnsiStr;
+ NTSTATUS Ret = STATUS_SUCCESS;
+ DWORD CurThread = 0;
- 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;
- if (Ret != STATUS_SUCCESS)
- return Ret;
+ while (Ret == STATUS_SUCCESS){
- if ((pExeName = strrchr (ProcName, '\\')))
- pExeName++;
- else
- pExeName = ProcName;
+ SERVER_START_REQ (next_thread){
+ req->handle = hSnap;
+ req->reset = (CurThread == 0);
+ Ret = wine_server_call_err (req);
- ExeLen = (strlen (pExeName) + 1) * sizeof (WCHAR);
- Len = sizeof (*pSPI) + ExeLen +
- (pSPI->dwThreadCount * sizeof (SYSTEM_THREAD_INFORMATION));
- if (LenLeft < Len)
- return STATUS_INFO_LENGTH_MISMATCH;
+ if (Ret == STATUS_SUCCESS){
- /* 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;
- }
+ /* only write the thread info if there is enough room in the buffer for another full block */
+ if (pSTI && length >= sizeof(*pSTI)){
- pSPI->dwOffset = Len;
+ /* not my thread => get next thread */
+ if (reply->pid != processID)
+ continue;
- return Ret;
-}
+ memset (pSTI, 0, sizeof(*pSTI));
+ pSTI->dwOwningPID = (DWORD)reply->pid;
+ pSTI->dwThreadID = (DWORD)reply->tid;
+ pSTI->dwCurrentPriority = reply->base_pri + reply->delta_pri;
+ pSTI->dwBasePriority = reply->base_pri;
+ /* FIXME: several members of this struct are being left as 0 */
+
+ /* add a bad food marker to the end of the thread info block (native does it;
+ perhaps for identification/sync/marking purposes?) */
+ pSTI->dwUnknown = 0xbaadf00d;
+
+ /* update the buffer size and move to the next thread info block */
+ length -= sizeof(*pSTI);
+ pSTI++;
+ }
+
+ CurThread++;
+ }
+ }
+ SERVER_END_REQ;
+ }
+ if (Ret == STATUS_NO_MORE_FILES)
+ Ret = STATUS_SUCCESS;
+
+ return Ret;
+}
/******************************************************************************
* Helper for NtQuerySystemInformation
*/
-static NTSTATUS SnapWalkThreads (HANDLE hSnap, PSYSTEM_PROCESS_INFORMATION pSPI)
+static NTSTATUS SnapGetNextProcess (HANDLE hSnap, DWORD LenLeft,
+ PSYSTEM_PROCESS_INFORMATION pSPI, ULONG *returnLength)
{
- NTSTATUS Ret = STATUS_SUCCESS;
- DWORD CurThread = 0;
- BOOL First = TRUE;
+ NTSTATUS Ret;
+ CHAR ProcName[1024];
+ CHAR * pExeName;
+ DWORD Len;
+ STRING AnsiStr;
+ DWORD threadCount;
+ DWORD processID;
+ size_t nameLen;
+ size_t nameSize;
- 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;
+ 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 (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;
+ /* save these since we can't necessarily access them from the <pSPI> block */
+ threadCount = reply->threads;
+ processID = (DWORD)reply->pid;
- CurThread++;
- }
- }
- SERVER_END_REQ;
- }
+ if (pSPI && LenLeft >= sizeof(*pSPI)){
+ 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;
- if (Ret == STATUS_NO_MORE_FILES)
- Ret = STATUS_SUCCESS;
- return Ret;
+ if (Ret != STATUS_SUCCESS){
+ if (returnLength)
+ *returnLength = 0;
+
+ return Ret;
+ }
+
+
+ if ((pExeName = strrchr(ProcName, '\\')))
+ pExeName++;
+
+ else
+ pExeName = ProcName;
+
+
+ nameLen = strlen(pExeName);
+ nameSize = ((((nameLen + 1) * sizeof(WCHAR)) + 7) & ~7);
+
+ /* the size of the string buffer is aligned to an 8-byte boundary in native */
+ Len = sizeof(*pSPI) + nameSize + (threadCount * sizeof (SYSTEM_THREAD_INFORMATION));
+
+
+ /* write the thread information blocks to the buffer as long as we can fit at least one */
+ if (pSPI && LenLeft > sizeof(*pSPI) + sizeof(SYSTEM_THREAD_INFORMATION)){
+
+ /* grab the thread info blocks */
+ Ret = SnapWalkThreads( hSnap,
+ processID,
+ LenLeft >= sizeof(*pSPI) ? LenLeft - sizeof(*pSPI) : 0,
+ pSPI ? pSPI->ti : NULL);
+
+
+ /* write the process name at the end of the thread info blocks */
+ if (LenLeft >= Len){
+ NTSTATUS result;
+
+
+ /* the <Length> member of the process's name is the string length in bytes, not
+ including the terminating null. The <MaximumLength> member is the string's
+ size in bytes, including the terminating null, and aligned to an 8-byte
+ boundary. */
+ pSPI->ProcessName.MaximumLength = nameSize;
+ pSPI->ProcessName.Buffer = (LPWSTR)((CHAR *)pSPI + Len - nameSize);
+
+ RtlInitAnsiString (&AnsiStr, pExeName);
+ TRACE("pExeName = {'%s', length = %d, maxLength = %d}\n", AnsiStr.Buffer, AnsiStr.Length, AnsiStr.MaximumLength);
+
+
+ result = RtlAnsiStringToUnicodeString (&pSPI->ProcessName, &AnsiStr, FALSE);
+
+ /* couldn't convert the name string to unicode => clear out the name buffer
+ and set its length to 0. This is not an error case */
+ if (result != STATUS_SUCCESS){
+ ERR("Failed to create Unicode string! {result = 0x%08lx}\n", result);
+
+ pSPI->ProcessName.Length = 0;
+ memset(pSPI->ProcessName.Buffer, 0, pSPI->ProcessName.MaximumLength);
+ }
+
+ TRACE("pSPI->ProcessName = {'%s', length = %d, maxLength = %d}, nameSize = %ld\n", debugstr_w(pSPI->ProcessName.Buffer), pSPI->ProcessName.Length, pSPI->ProcessName.MaximumLength, nameLen * sizeof(WCHAR));
+ }
+
+ pSPI->dwOffset = Len;
+ }
+
+
+ if (returnLength)
+ *returnLength = Len;
+
+ return STATUS_SUCCESS;
}
-/******************************************************************************
- * 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;
+
+
+
+static NTSTATUS collectProcessInformation(void *buf, ULONG length, ULONG *resultLength){
+ ULONG resLength = 0;
+ ULONG processLength;
+ BOOL writeToBuffer = TRUE;
+ PSYSTEM_PROCESS_INFORMATION pSPI = (PSYSTEM_PROCESS_INFORMATION)buf;
+ PSYSTEM_PROCESS_INFORMATION pPrev;
+ HANDLE hSnap = INVALID_HANDLE_VALUE;
+
+
+ /* no buffer to write in and no return length to write in -> no point doing work => fail */
+ if (buf == NULL && (resultLength == NULL || length != 0)){
+ WARN("nothing to do! {buf = %p, resultLength = %p, length = %lu}\n", buf, resultLength, length);
+
+ return STATUS_ACCESS_VIOLATION;
+ }
+
+
+ /* no output buffer => turn off buffer writing immediately */
+ if (buf == NULL)
+ writeToBuffer = FALSE;
+
+
+ if (SnapCreate (&hSnap) != STATUS_SUCCESS){
+ ERR("snapshot failed!\n");
+
+ if (resultLength)
+ *resultLength = 0;
+
+ return STATUS_ACCESS_VIOLATION;
+ }
+
+
+ /* Iterate over processes */
+ pPrev = pSPI;
+ while (SnapGetNextProcess(hSnap, length - resLength, pSPI, &processLength) == STATUS_SUCCESS){
+
+ /* accumulate the size of this process's buffer. This value includes space for the
+ main process info, all the thread info blocks, and the process's name */
+ resLength += processLength;
+
+
+ /* if we ran out of buffer space we can't trust the <pSPI->dwOffset> value. Use the
+ value returned through <callLength> instead. */
+ if (resLength > length){
+ if (pSPI)
+ pSPI->dwOffset = 0;
+
+ length = 0;
+ pSPI = NULL;
+ pPrev = NULL;
+ }
+
+ else{
+ pPrev = pSPI;
+ pSPI = (PSYSTEM_PROCESS_INFORMATION)((char *)pSPI + pSPI->dwOffset);
+ }
+ }
+
+ /* Clean up snapshot */
+ NtClose (hSnap);
+
+ if (pPrev)
+ pPrev->dwOffset = 0;
+
+ if (resultLength)
+ *resultLength = resLength;
+
+
+ /* the buffer wasn't sufficiently large to store the result => return size mismatch */
+ if (length < resLength)
+ return STATUS_INFO_LENGTH_MISMATCH;
+
+ return STATUS_SUCCESS;
}
@@ -911,19 +1061,20 @@
* ZwQuerySystemInformation [NTDLL.@]
*
* ARGUMENTS:
- * SystemInformationClass Index to a certain information structure
- * SystemTimeAdjustmentInformation SYSTEM_TIME_ADJUSTMENT
- * SystemCacheInformation SYSTEM_CACHE_INFORMATION
- * SystemConfigurationInformation CONFIGURATION_INFORMATION
- * observed (class/len):
- * 0x0/0x2c
- * 0x12/0x18
- * 0x2/0x138
- * 0x8/0x600
- * 0x25/0xc
- * SystemInformation caller supplies storage for the information structure
- * Length size of the structure
- * ResultLength Data written
+ * SystemInformationClass Index to a certain information structure Size
+ * SystemTimeAdjustmentInformation SYSTEM_TIME_ADJUSTMENT 0x0008
+ * SystemCacheInformation SYSTEM_CACHE_INFORMATION 0x0018
+ * SystemConfigurationInformation CONFIGURATION_INFORMATION ?
+ * SystemProcessInformation SYSTEM_PROCESS_INFORMATION 0x0160+
+ * SystemRegistryQuotaInformation SYSTEM_REGISTRY_QUOTA_INFORMATION 0x000c
+ * SystemBasicInformation SYSTEM_BASIC_INFORMATION 0x002c
+ * SystemPagefileInformation ? 0x0018
+ * SystemPerformanceInformation SYSTEM_PERFORMANCE_INFORMATION 0x0138
+ * SystemProcessorCounters ? 0x0600
+ *
+ * SystemInformation caller supplies storage for the information structure
+ * Length size of the structure
+ * ResultLength Data written
*/
NTSTATUS WINAPI NtQuerySystemInformation(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
@@ -934,23 +1085,34 @@
NTSTATUS result = STATUS_SUCCESS;
- TRACE ("(0x%08x,%p,0x%08lx,%p)\n",
- SystemInformationClass, SystemInformation,
- Length, ResultLength);
+ FIXME("(0x%08x,%p,0x%08lx,%p), mostly-stub!\n",
+ SystemInformationClass, SystemInformation,
+ Length, ResultLength);
/* native checks if the buffer length is 0 before checking if the buffer is NULL
(<ResultLength> is not modified in this case) => fail */
- if (Length == 0)
- return STATUS_INFO_LENGTH_MISMATCH;
+ if (Length == 0){
+
+ /* NOTE: SystemProcessInformation handles this case differently - it returns the
+ required buffer size in ResultLength */
+ if (!(SystemInformationClass == SystemProcessInformation && ResultLength))
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
/* native checks if this buffer is NULL on a case-by-case basis. For now we'll just
do the same thing for all information classes */
if (SystemInformation == NULL){
- if (ResultLength)
- *ResultLength = 0;
- return STATUS_ACCESS_VIOLATION;
+ /* SystemProcessInformation handles this case differently - it calculates the required
+ buffer size and returns that in <ResultLength> */
+ if (!(Length == 0 && SystemInformationClass == SystemProcessInformation && ResultLength)){
+
+ if (ResultLength && SystemInformationClass != SystemProcessInformation)
+ *ResultLength = 0;
+
+ return STATUS_ACCESS_VIOLATION;
+ }
}
@@ -979,12 +1141,12 @@
return STATUS_INFO_LENGTH_MISMATCH;
- FIXME("(0x%08x,%p,0x%08lx,%p) faking max registry size of 32 MB\n",
+ FIXME("(0x%08x,%p,0x%08lx,%p) faking max registry size of 32 MB and used size of 2MB\n",
SystemInformationClass, SystemInformation, Length, ResultLength);
quota->RegistryQuotaAllowed = 0x02000000;
quota->RegistryQuotaUsed = 0x00200000;
- quota->Reserved1 = 0x16800000;
+ quota->Reserved1 = (VOID *)0x16800000;
if (ResultLength)
*ResultLength = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION);
@@ -1002,48 +1164,12 @@
break;
- 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;
+ case SystemProcessInformation:
+ TRACE("(0x%08x, %p, 0x%08lx, %p) gathering information about all running processes\n",
+ SystemInformationClass,SystemInformation,Length,ResultLength);
+ result = collectProcessInformation(SystemInformation, Length, ResultLength);
break;
- }
default:
FIXME("(0x%08x,%p,0x%08lx,%p) stub\n",