4 * COPYRIGHT: See COPYING in the top level directory
5 * LICENSE: See LGPL.txt in the top level directory
6 * PROJECT: ReactOS system libraries
7 * FILE: reactos/lib/psapi/misc/win32.c
8 * PURPOSE: Win32 interfaces for PSAPI
9 * PROGRAMMER: KJK::Hyperion <noog@libero.it>
10 * Thomas Weidenmueller <w3seek@reactos.com>
22 DllMain(HINSTANCE hDllHandle
,
28 case DLL_PROCESS_ATTACH
:
29 DisableThreadLibraryCalls(hDllHandle
);
36 /* INTERNAL *******************************************************************/
38 typedef struct _ENUM_DEVICE_DRIVERS_CONTEXT
42 } ENUM_DEVICE_DRIVERS_CONTEXT
, *PENUM_DEVICE_DRIVERS_CONTEXT
;
45 EnumDeviceDriversCallback(IN PSYSTEM_MODULE_INFORMATION_ENTRY CurrentModule
,
46 IN OUT PVOID CallbackContext
)
48 PENUM_DEVICE_DRIVERS_CONTEXT Context
= (PENUM_DEVICE_DRIVERS_CONTEXT
)CallbackContext
;
50 /* no more buffer space */
51 if(Context
->nCount
== 0)
53 return STATUS_INFO_LENGTH_MISMATCH
;
56 /* return current module */
57 *Context
->lpImageBase
= CurrentModule
->Base
;
59 /* go to next array slot */
60 Context
->lpImageBase
++;
63 return STATUS_SUCCESS
;
67 typedef struct _ENUM_PROCESSES_CONTEXT
71 } ENUM_PROCESSES_CONTEXT
, *PENUM_PROCESSES_CONTEXT
;
74 EnumProcessesCallback(IN PSYSTEM_PROCESS_INFORMATION CurrentProcess
,
75 IN OUT PVOID CallbackContext
)
77 PENUM_PROCESSES_CONTEXT Context
= (PENUM_PROCESSES_CONTEXT
)CallbackContext
;
79 /* no more buffer space */
80 if(Context
->nCount
== 0)
82 return STATUS_INFO_LENGTH_MISMATCH
;
85 /* return current process */
86 *Context
->lpidProcess
= (DWORD
)CurrentProcess
->UniqueProcessId
;
88 /* go to next array slot */
89 Context
->lpidProcess
++;
92 return STATUS_SUCCESS
;
96 typedef struct _ENUM_PROCESS_MODULES_CONTEXT
100 } ENUM_PROCESS_MODULES_CONTEXT
, *PENUM_PROCESS_MODULES_CONTEXT
;
103 EnumProcessModulesCallback(IN HANDLE ProcessHandle
,
104 IN PLDR_DATA_TABLE_ENTRY CurrentModule
,
105 IN OUT PVOID CallbackContext
)
107 PENUM_PROCESS_MODULES_CONTEXT Context
= (PENUM_PROCESS_MODULES_CONTEXT
)CallbackContext
;
109 /* no more buffer space */
110 if(Context
->nCount
== 0)
112 return STATUS_INFO_LENGTH_MISMATCH
;
115 /* return current process */
116 *Context
->lphModule
= CurrentModule
->DllBase
;
118 /* go to next array slot */
119 Context
->lphModule
++;
122 return STATUS_SUCCESS
;
126 typedef struct _GET_DEVICE_DRIVER_NAME_CONTEXT
131 ULONG bFullName
: sizeof(ULONG
) * 8 / 2;
132 ULONG bUnicode
: sizeof(ULONG
) * 8 / 2;
139 LPWSTR lpUnicodeName
;
141 } GET_DEVICE_DRIVER_NAME_CONTEXT
, *PGET_DEVICE_DRIVER_NAME_CONTEXT
;
144 GetDeviceDriverNameCallback(IN PSYSTEM_MODULE_INFORMATION_ENTRY CurrentModule
,
145 IN OUT PVOID CallbackContext
)
147 PGET_DEVICE_DRIVER_NAME_CONTEXT Context
= (PGET_DEVICE_DRIVER_NAME_CONTEXT
)CallbackContext
;
150 if(Context
->ImageBase
== CurrentModule
->Base
)
155 /* get the full name or just the filename part */
156 if(Context
->bFullName
)
157 pcModuleName
= &CurrentModule
->ImageName
[0];
159 pcModuleName
= &CurrentModule
->ImageName
[CurrentModule
->PathLength
];
161 /* get the length of the name */
162 l
= strlen(pcModuleName
);
164 if(Context
->nSize
<= l
)
166 /* use the user buffer's length */
171 /* enough space for the null terminator */
172 Context
->nSize
= ++l
;
175 /* copy the string */
176 if(Context
->bUnicode
)
178 ANSI_STRING AnsiString
;
179 UNICODE_STRING UnicodeString
;
181 UnicodeString
.Length
= 0;
182 UnicodeString
.MaximumLength
= l
* sizeof(WCHAR
);
183 UnicodeString
.Buffer
= Context
->lpUnicodeName
;
185 RtlInitAnsiString(&AnsiString
, pcModuleName
);
186 /* driver names should always be in language-neutral ASCII, so we don't
187 bother calling AreFileApisANSI() */
188 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, FALSE
);
192 memcpy(Context
->lpAnsiName
, pcModuleName
, l
);
195 /* terminate the enumeration */
196 return STATUS_NO_MORE_FILES
;
200 /* continue searching */
201 return STATUS_SUCCESS
;
207 InternalGetDeviceDriverName(BOOLEAN bUnicode
,
213 GET_DEVICE_DRIVER_NAME_CONTEXT Context
;
216 if(lpName
== NULL
|| nSize
== 0)
221 if(ImageBase
== NULL
)
223 SetLastError(ERROR_INVALID_HANDLE
);
227 Context
.ImageBase
= ImageBase
;
228 Context
.bFullName
= bFullName
;
229 Context
.bUnicode
= bUnicode
;
230 Context
.nSize
= nSize
;
231 Context
.lpName
= lpName
;
233 /* start the enumeration */
234 Status
= PsaEnumerateSystemModules(GetDeviceDriverNameCallback
, &Context
);
236 if(Status
== STATUS_NO_MORE_FILES
)
238 /* module was found, return string size */
239 return Context
.nSize
;
241 else if(NT_SUCCESS(Status
))
243 /* module was not found */
244 SetLastError(ERROR_INVALID_HANDLE
);
248 /* an error occurred */
249 SetLastErrorByStatus(Status
);
256 InternalGetMappedFileName(BOOLEAN bUnicode
,
262 PMEMORY_SECTION_NAME pmsnName
;
266 if(nSize
== 0 || lpName
== NULL
)
271 if(nSize
> (0xFFFF / sizeof(WCHAR
)))
273 /* if the user buffer contains more characters than would fit in an
274 UNICODE_STRING, limit the buffer size. RATIONALE: we don't limit buffer
275 size elsewhere because here superfluous buffer size will mean a larger
277 nBufSize
= 0xFFFF / sizeof(WCHAR
);
281 nBufSize
= nSize
* sizeof(WCHAR
);
284 /* allocate the memory */
285 pmsnName
= PsaiMalloc(nBufSize
+ sizeof(MEMORY_SECTION_NAME
));
289 SetLastError(ERROR_OUTOFMEMORY
);
293 /* initialize the destination buffer */
294 pmsnName
->SectionFileName
.Length
= 0;
295 pmsnName
->SectionFileName
.Length
= nBufSize
;
302 Status
= NtQueryVirtualMemory(hProcess
,
308 if(!NT_SUCCESS(Status
))
311 SetLastErrorByStatus(Status
);
317 /* destination is an Unicode string: direct copy */
318 memcpy((LPWSTR
)lpName
, pmsnName
+ 1, pmsnName
->SectionFileName
.Length
);
322 if(pmsnName
->SectionFileName
.Length
< nSize
)
324 /* null-terminate the string */
325 ((LPWSTR
)lpName
)[pmsnName
->SectionFileName
.Length
] = 0;
326 return pmsnName
->SectionFileName
.Length
+ 1;
329 return pmsnName
->SectionFileName
.Length
;
333 ANSI_STRING AnsiString
;
335 AnsiString
.Length
= 0;
336 AnsiString
.MaximumLength
= nSize
;
337 AnsiString
.Buffer
= (LPSTR
)lpName
;
339 if(AreFileApisANSI())
340 RtlUnicodeStringToAnsiString(&AnsiString
, &pmsnName
->SectionFileName
, FALSE
);
342 RtlUnicodeStringToOemString(&AnsiString
, &pmsnName
->SectionFileName
, FALSE
);
346 if(AnsiString
.Length
< nSize
)
348 /* null-terminate the string */
349 ((LPSTR
)lpName
)[AnsiString
.Length
] = 0;
350 return AnsiString
.Length
+ 1;
353 return AnsiString
.Length
;
366 typedef struct _GET_MODULE_INFORMATION_FLAGS
368 ULONG bWantName
: sizeof(ULONG
) * 8 / 4;
369 ULONG bUnicode
: sizeof(ULONG
) * 8 / 4;
370 ULONG bFullName
: sizeof(ULONG
) * 8 / 4;
371 } GET_MODULE_INFORMATION_FLAGS
, *PGET_MODULE_INFORMATION_FLAGS
;
373 typedef struct _GET_MODULE_INFORMATION_CONTEXT
376 GET_MODULE_INFORMATION_FLAGS Flags
;
380 LPWSTR lpUnicodeName
;
382 LPMODULEINFO lpmodinfo
;
385 } GET_MODULE_INFORMATION_CONTEXT
, *PGET_MODULE_INFORMATION_CONTEXT
;
388 GetModuleInformationCallback(IN HANDLE ProcessHandle
,
389 IN PLDR_DATA_TABLE_ENTRY CurrentModule
,
390 IN OUT PVOID CallbackContext
)
392 PGET_MODULE_INFORMATION_CONTEXT Context
= (PGET_MODULE_INFORMATION_CONTEXT
)CallbackContext
;
394 /* found the module we were looking for */
395 if(CurrentModule
->DllBase
== Context
->hModule
)
397 /* we want the module name */
398 if(Context
->Flags
.bWantName
)
400 PUNICODE_STRING SourceString
;
404 if(Context
->Flags
.bFullName
)
405 SourceString
= &(CurrentModule
->FullDllName
);
407 SourceString
= &(CurrentModule
->BaseDllName
);
409 SourceString
->Length
-= SourceString
->Length
% sizeof(WCHAR
);
411 /* l is the byte size of the user buffer */
412 l
= Context
->nBufSize
* sizeof(WCHAR
);
414 /* if the user buffer has room for the string and a null terminator */
415 if(l
>= (SourceString
->Length
+ sizeof(WCHAR
)))
417 /* limit the buffer size */
418 l
= SourceString
->Length
;
420 /* null-terminate the string */
421 if(Context
->Flags
.bUnicode
)
422 Context
->lpUnicodeName
[l
/ sizeof(WCHAR
)] = 0;
424 Context
->lpAnsiName
[l
/ sizeof(WCHAR
)] = 0;
427 if(Context
->Flags
.bUnicode
)
429 /* Unicode: direct copy */
430 /* NOTE: I've chosen not to check for ProcessHandle == NtCurrentProcess(),
431 this function is complicated enough as it is */
432 Status
= NtReadVirtualMemory(ProcessHandle
,
433 SourceString
->Buffer
,
434 Context
->lpUnicodeName
,
438 if(!NT_SUCCESS(Status
))
440 Context
->nBufSize
= 0;
444 Context
->nBufSize
= l
/ sizeof(WCHAR
);
448 /* ANSI/OEM: convert and copy */
449 LPWSTR pwcUnicodeBuf
;
450 ANSI_STRING AnsiString
;
451 UNICODE_STRING UnicodeString
;
453 AnsiString
.Length
= 0;
454 AnsiString
.MaximumLength
= Context
->nBufSize
;
455 AnsiString
.Buffer
= Context
->lpAnsiName
;
457 /* allocate the local buffer */
458 pwcUnicodeBuf
= PsaiMalloc(SourceString
->Length
);
464 if(pwcUnicodeBuf
== NULL
)
466 Status
= STATUS_NO_MEMORY
;
470 /* copy the string in the local buffer */
471 Status
= NtReadVirtualMemory(ProcessHandle
,
472 SourceString
->Buffer
,
477 if(!NT_SUCCESS(Status
))
482 /* initialize Unicode string buffer */
483 UnicodeString
.Length
= UnicodeString
.MaximumLength
= l
;
484 UnicodeString
.Buffer
= pwcUnicodeBuf
;
486 /* convert and copy */
487 if(AreFileApisANSI())
488 RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, FALSE
);
490 RtlUnicodeStringToOemString(&AnsiString
, &UnicodeString
, FALSE
);
492 /* return the string size */
493 Context
->nBufSize
= AnsiString
.Length
;
498 /* free the buffer */
499 PsaiFree(pwcUnicodeBuf
);
502 Status
= STATUS_NO_MORE_FILES
;
505 /* free the buffer */
506 PsaiFree(pwcUnicodeBuf
);
513 /* we want other module information */
514 ULONG nSize
= Context
->nBufSize
;
517 if(nSize
>= sizeof(CurrentModule
->DllBase
))
519 Context
->lpmodinfo
->lpBaseOfDll
= CurrentModule
->DllBase
;
520 nSize
-= sizeof(CurrentModule
->DllBase
);
524 if(nSize
>= sizeof(CurrentModule
->SizeOfImage
))
526 Context
->lpmodinfo
->SizeOfImage
= CurrentModule
->SizeOfImage
;
527 nSize
-= sizeof(CurrentModule
->SizeOfImage
);
531 if(nSize
>= sizeof(CurrentModule
->EntryPoint
))
533 /* ??? FIXME? is "EntryPoint" just the offset, or the real address? */
534 Context
->lpmodinfo
->EntryPoint
= (PVOID
)CurrentModule
->EntryPoint
;
537 Context
->nBufSize
= TRUE
;
540 return STATUS_NO_MORE_FILES
;
543 return STATUS_SUCCESS
;
548 InternalGetModuleInformation(HANDLE hProcess
,
550 GET_MODULE_INFORMATION_FLAGS Flags
,
554 GET_MODULE_INFORMATION_CONTEXT Context
;
557 Context
.hModule
= hModule
;
558 Context
.Flags
= Flags
;
559 Context
.nBufSize
= nBufSize
;
560 Context
.lpBuffer
= lpBuffer
;
562 Status
= PsaEnumerateProcessModules(hProcess
, GetModuleInformationCallback
, &Context
);
564 if(Status
== STATUS_NO_MORE_FILES
)
566 /* module was found, return string size */
567 return Context
.nBufSize
;
569 else if(NT_SUCCESS(Status
))
571 /* module was not found */
572 SetLastError(ERROR_INVALID_HANDLE
);
576 /* an error occurred */
577 SetLastErrorByStatus(Status
);
583 typedef struct _INTERNAL_ENUM_PAGE_FILES_CONTEXT
585 PENUM_PAGE_FILE_CALLBACKA pCallbackRoutine
;
587 } INTERNAL_ENUM_PAGE_FILES_CONTEXT
, *PINTERNAL_ENUM_PAGE_FILES_CONTEXT
;
591 InternalAnsiPageFileCallback(LPVOID pContext
,
592 PENUM_PAGE_FILE_INFORMATION pPageFileInfo
,
597 PINTERNAL_ENUM_PAGE_FILES_CONTEXT Context
= (PINTERNAL_ENUM_PAGE_FILES_CONTEXT
)pContext
;
599 slen
= wcslen(lpFilename
);
601 AnsiFileName
= (LPSTR
)LocalAlloc(LMEM_FIXED
, (slen
+ 1) * sizeof(CHAR
));
602 if(AnsiFileName
!= NULL
)
606 WideCharToMultiByte(CP_ACP
,
609 -1, /* only works if the string is NULL-terminated!!! */
611 (slen
+ 1) * sizeof(CHAR
),
615 Ret
= Context
->pCallbackRoutine(Context
->lpContext
, pPageFileInfo
, AnsiFileName
);
617 LocalFree((HLOCAL
)AnsiFileName
);
625 /* PUBLIC *********************************************************************/
632 EmptyWorkingSet(HANDLE hProcess
)
634 QUOTA_LIMITS QuotaLimits
;
637 /* query the working set */
638 Status
= NtQueryInformationProcess(hProcess
,
644 if(!NT_SUCCESS(Status
))
646 SetLastErrorByStatus(Status
);
650 /* empty the working set */
651 QuotaLimits
.MinimumWorkingSetSize
= -1;
652 QuotaLimits
.MaximumWorkingSetSize
= -1;
654 /* set the working set */
655 Status
= NtSetInformationProcess(hProcess
,
658 sizeof(QuotaLimits
));
659 if(!NT_SUCCESS(Status
))
661 SetLastErrorByStatus(Status
);
674 EnumDeviceDrivers(LPVOID
*lpImageBase
,
678 ENUM_DEVICE_DRIVERS_CONTEXT Context
;
681 if(cb
== 0 || lpImageBase
== NULL
)
689 Context
.lpImageBase
= lpImageBase
;
692 Status
= PsaEnumerateSystemModules(EnumDeviceDriversCallback
, &Context
);
694 /* return the count of bytes returned */
695 *lpcbNeeded
= (cb
- Context
.nCount
) * sizeof(PVOID
);
697 if(!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
699 SetLastErrorByStatus(Status
);
712 EnumProcesses(DWORD
*lpidProcess
,
716 ENUM_PROCESSES_CONTEXT Context
;
721 if(cb
== 0 || lpidProcess
== NULL
)
727 Context
.lpidProcess
= lpidProcess
;
730 /* enumerate the process ids */
731 Status
= PsaEnumerateProcesses(EnumProcessesCallback
, &Context
);
733 *lpcbNeeded
= (cb
- Context
.nCount
) * sizeof(DWORD
);
735 if(!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
737 SetLastErrorByStatus(Status
);
750 EnumProcessModules(HANDLE hProcess
,
755 ENUM_PROCESS_MODULES_CONTEXT Context
;
758 cb
/= sizeof(HMODULE
);
760 if(cb
== 0 || lphModule
== NULL
)
766 Context
.lphModule
= lphModule
;
769 /* enumerate the process modules */
770 Status
= PsaEnumerateProcessModules(hProcess
, EnumProcessModulesCallback
, &Context
);
772 *lpcbNeeded
= (cb
- Context
.nCount
) * sizeof(DWORD
);
774 if(!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
776 SetLastErrorByStatus(Status
);
789 GetDeviceDriverBaseNameA(LPVOID ImageBase
,
793 return InternalGetDeviceDriverName(FALSE
, FALSE
, ImageBase
, lpBaseName
, nSize
);
802 GetDeviceDriverFileNameA(LPVOID ImageBase
,
806 return InternalGetDeviceDriverName(FALSE
, TRUE
, ImageBase
, lpFilename
, nSize
);
815 GetDeviceDriverBaseNameW(LPVOID ImageBase
,
819 return InternalGetDeviceDriverName(TRUE
, FALSE
, ImageBase
, lpBaseName
, nSize
);
828 GetDeviceDriverFileNameW(LPVOID ImageBase
,
832 return InternalGetDeviceDriverName(TRUE
, TRUE
, ImageBase
, lpFilename
, nSize
);
841 GetMappedFileNameA(HANDLE hProcess
,
846 return InternalGetMappedFileName(FALSE
, hProcess
, lpv
, lpFilename
, nSize
);
855 GetMappedFileNameW(HANDLE hProcess
,
860 return InternalGetMappedFileName(TRUE
, hProcess
, lpv
, lpFilename
, nSize
);
869 GetModuleBaseNameA(HANDLE hProcess
,
874 GET_MODULE_INFORMATION_FLAGS Flags
= {TRUE
, FALSE
, FALSE
};
875 return InternalGetModuleInformation(hProcess
, hModule
, Flags
, lpBaseName
, nSize
);
884 GetModuleBaseNameW(HANDLE hProcess
,
889 GET_MODULE_INFORMATION_FLAGS Flags
= {TRUE
, TRUE
, FALSE
};
890 return InternalGetModuleInformation(hProcess
, hModule
, Flags
, lpBaseName
, nSize
);
899 GetModuleFileNameExA(HANDLE hProcess
,
904 GET_MODULE_INFORMATION_FLAGS Flags
= {TRUE
, FALSE
, TRUE
};
905 return InternalGetModuleInformation(hProcess
, hModule
, Flags
, lpFilename
, nSize
);
914 GetModuleFileNameExW(HANDLE hProcess
,
919 GET_MODULE_INFORMATION_FLAGS Flags
= {TRUE
, TRUE
, TRUE
};
920 return InternalGetModuleInformation(hProcess
, hModule
, Flags
, lpFilename
, nSize
);
929 GetModuleInformation(HANDLE hProcess
,
931 LPMODULEINFO lpmodinfo
,
934 GET_MODULE_INFORMATION_FLAGS Flags
= {FALSE
, FALSE
, FALSE
};
935 return (BOOL
)InternalGetModuleInformation(hProcess
, hModule
, Flags
, lpmodinfo
, cb
);
944 InitializeProcessForWsWatch(HANDLE hProcess
)
948 Status
= NtSetInformationProcess(hProcess
,
949 ProcessWorkingSetWatch
,
952 if(!NT_SUCCESS(Status
))
954 SetLastErrorByStatus(Status
);
967 GetWsChanges(HANDLE hProcess
,
968 PPSAPI_WS_WATCH_INFORMATION lpWatchInfo
,
973 Status
= NtQueryInformationProcess(hProcess
,
974 ProcessWorkingSetWatch
,
978 if(!NT_SUCCESS(Status
))
980 SetLastErrorByStatus(Status
);
993 GetProcessImageFileNameW(HANDLE hProcess
,
994 LPWSTR lpImageFileName
,
997 PUNICODE_STRING ImageFileName
;
1002 BufferSize
= sizeof(UNICODE_STRING
) + (nSize
* sizeof(WCHAR
));
1004 ImageFileName
= (PUNICODE_STRING
)LocalAlloc(LMEM_FIXED
, BufferSize
);
1005 if(ImageFileName
!= NULL
)
1007 Status
= NtQueryInformationProcess(hProcess
,
1008 ProcessImageFileName
,
1012 if(NT_SUCCESS(Status
))
1014 memcpy(lpImageFileName
, ImageFileName
->Buffer
, ImageFileName
->Length
);
1016 /* make sure the string is null-terminated! */
1017 lpImageFileName
[ImageFileName
->Length
/ sizeof(WCHAR
)] = L
'\0';
1018 Ret
= ImageFileName
->Length
/ sizeof(WCHAR
);
1020 else if(Status
== STATUS_INFO_LENGTH_MISMATCH
)
1022 /* XP sets this error code for some reason if the buffer is too small */
1023 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1027 SetLastErrorByStatus(Status
);
1030 LocalFree((HLOCAL
)ImageFileName
);
1042 GetProcessImageFileNameA(HANDLE hProcess
,
1043 LPSTR lpImageFileName
,
1046 PUNICODE_STRING ImageFileName
;
1051 BufferSize
= sizeof(UNICODE_STRING
) + (nSize
* sizeof(WCHAR
));
1053 ImageFileName
= (PUNICODE_STRING
)LocalAlloc(LMEM_FIXED
, BufferSize
);
1054 if(ImageFileName
!= NULL
)
1056 Status
= NtQueryInformationProcess(hProcess
,
1057 ProcessImageFileName
,
1061 if(NT_SUCCESS(Status
))
1063 WideCharToMultiByte(CP_ACP
,
1065 ImageFileName
->Buffer
,
1066 ImageFileName
->Length
/ sizeof(WCHAR
),
1072 /* make sure the string is null-terminated! */
1073 lpImageFileName
[ImageFileName
->Length
/ sizeof(WCHAR
)] = '\0';
1074 Ret
= ImageFileName
->Length
/ sizeof(WCHAR
);
1076 else if(Status
== STATUS_INFO_LENGTH_MISMATCH
)
1078 /* XP sets this error code for some reason if the buffer is too small */
1079 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1083 SetLastErrorByStatus(Status
);
1086 LocalFree((HLOCAL
)ImageFileName
);
1098 EnumPageFilesA(PENUM_PAGE_FILE_CALLBACKA pCallbackRoutine
,
1101 INTERNAL_ENUM_PAGE_FILES_CONTEXT Context
;
1103 Context
.pCallbackRoutine
= pCallbackRoutine
;
1104 Context
.lpContext
= lpContext
;
1106 return EnumPageFilesW(InternalAnsiPageFileCallback
, &Context
);
1115 EnumPageFilesW(PENUM_PAGE_FILE_CALLBACKW pCallbackRoutine
,
1120 ULONG BufferSize
= 0;
1125 BufferSize
+= 0x1000;
1126 Buffer
= LocalAlloc(LMEM_FIXED
, BufferSize
);
1132 Status
= NtQuerySystemInformation(SystemPageFileInformation
,
1136 if(Status
== STATUS_INFO_LENGTH_MISMATCH
)
1138 LocalFree((HLOCAL
)Buffer
);
1146 if(NT_SUCCESS(Status
))
1148 ENUM_PAGE_FILE_INFORMATION Information
;
1149 PSYSTEM_PAGEFILE_INFORMATION pfi
= (PSYSTEM_PAGEFILE_INFORMATION
)Buffer
;
1156 pfi
= (PSYSTEM_PAGEFILE_INFORMATION
)((ULONG_PTR
)pfi
+ Offset
);
1158 Information
.cb
= sizeof(Information
);
1159 Information
.Reserved
= 0;
1160 Information
.TotalSize
= pfi
->TotalSize
;
1161 Information
.TotalInUse
= pfi
->TotalInUse
;
1162 Information
.PeakUsage
= pfi
->PeakUsage
;
1164 /* strip the \??\ prefix from the file name. We do this by searching for the first
1165 : character and then just change Buffer to point to the previous character. */
1167 Colon
= wcschr(pfi
->PageFileName
.Buffer
, L
':');
1170 pfi
->PageFileName
.Buffer
= --Colon
;
1173 /* FIXME - looks like the PageFileName string is always NULL-terminated on win.
1174 At least I haven't encountered a different case so far, we should
1175 propably manually NULL-terminate the string here... */
1177 if(!pCallbackRoutine(lpContext
, &Information
, pfi
->PageFileName
.Buffer
))
1182 Offset
= pfi
->NextEntryOffset
;
1183 } while(Offset
!= 0);
1189 SetLastErrorByStatus(Status
);
1192 LocalFree((HLOCAL
)Buffer
);
1203 GetPerformanceInfo(PPERFORMANCE_INFORMATION pPerformanceInformation
,
1206 SYSTEM_PERFORMANCE_INFORMATION spi
;
1207 SYSTEM_BASIC_INFORMATION sbi
;
1208 SYSTEM_HANDLE_INFORMATION shi
;
1209 PSYSTEM_PROCESS_INFORMATION ProcessInfo
;
1210 ULONG BufferSize
, ProcOffset
, ProcessCount
, ThreadCount
;
1214 Status
= NtQuerySystemInformation(SystemPerformanceInformation
,
1218 if(!NT_SUCCESS(Status
))
1220 SetLastErrorByStatus(Status
);
1224 Status
= NtQuerySystemInformation(SystemBasicInformation
,
1228 if(!NT_SUCCESS(Status
))
1230 SetLastErrorByStatus(Status
);
1235 * allocate enough memory to get a dump of all processes and threads
1240 BufferSize
+= 0x10000;
1241 Buffer
= (PVOID
)LocalAlloc(LMEM_FIXED
, BufferSize
);
1247 Status
= NtQuerySystemInformation(SystemProcessInformation
,
1251 if(Status
== STATUS_INFO_LENGTH_MISMATCH
)
1253 LocalFree((HLOCAL
)Buffer
);
1261 if(!NT_SUCCESS(Status
))
1263 LocalFree((HLOCAL
)Buffer
);
1264 SetLastErrorByStatus(Status
);
1269 * determine the process and thread count
1271 ProcessCount
= ThreadCount
= ProcOffset
= 0;
1272 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)Buffer
;
1275 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)((ULONG_PTR
)ProcessInfo
+ ProcOffset
);
1277 ThreadCount
+= ProcessInfo
->NumberOfThreads
;
1279 ProcOffset
= ProcessInfo
->NextEntryOffset
;
1280 } while(ProcOffset
!= 0);
1282 LocalFree((HLOCAL
)Buffer
);
1285 * it's enough to supply a SYSTEM_HANDLE_INFORMATION structure as buffer. Even
1286 * though it returns STATUS_INFO_LENGTH_MISMATCH, it already sets the NumberOfHandles
1287 * field which is all we're looking for anyway.
1289 Status
= NtQuerySystemInformation(SystemHandleInformation
,
1293 if(!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
1295 SetLastErrorByStatus(Status
);
1300 * all required information collected, fill the structure
1303 pPerformanceInformation
->cb
= sizeof(PERFORMANCE_INFORMATION
);
1304 pPerformanceInformation
->CommitTotal
= spi
.CommittedPages
;
1305 pPerformanceInformation
->CommitLimit
= spi
.CommitLimit
;
1306 pPerformanceInformation
->CommitPeak
= spi
.PeakCommitment
;
1307 pPerformanceInformation
->PhysicalTotal
= sbi
.NumberOfPhysicalPages
;
1308 pPerformanceInformation
->PhysicalAvailable
= spi
.AvailablePages
;
1309 pPerformanceInformation
->SystemCache
= 0; /* FIXME - where to get this information from? */
1310 pPerformanceInformation
->KernelTotal
= spi
.PagedPoolPages
+ spi
.NonPagedPoolPages
;
1311 pPerformanceInformation
->KernelPaged
= spi
.PagedPoolPages
;
1312 pPerformanceInformation
->KernelNonpaged
= spi
.NonPagedPoolPages
;
1313 pPerformanceInformation
->PageSize
= sbi
.PageSize
;
1314 pPerformanceInformation
->HandleCount
= shi
.NumberOfHandles
;
1315 pPerformanceInformation
->ProcessCount
= ProcessCount
;
1316 pPerformanceInformation
->ThreadCount
= ThreadCount
;
1327 GetProcessMemoryInfo(HANDLE Process
,
1328 PPROCESS_MEMORY_COUNTERS ppsmemCounters
,
1335 /* XP's implementation secures access to ppsmemCounters in SEH, we should behave
1336 similar so we can return the proper error codes when bad pointers are passed
1337 to this function! */
1341 if(cb
< sizeof(PROCESS_MEMORY_COUNTERS
))
1343 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1347 /* ppsmemCounters->cb isn't checked at all! */
1349 Status
= NtQueryInformationProcess(Process
,
1354 if(!NT_SUCCESS(Status
))
1356 SetLastErrorByStatus(Status
);
1360 /* fill the structure with the collected information, in case of bad pointers
1361 SEH will catch the exception and set the appropriate error code */
1362 ppsmemCounters
->cb
= sizeof(PROCESS_MEMORY_COUNTERS
);
1363 ppsmemCounters
->PageFaultCount
= vmc
.PageFaultCount
;
1364 ppsmemCounters
->PeakWorkingSetSize
= vmc
.PeakWorkingSetSize
;
1365 ppsmemCounters
->WorkingSetSize
= vmc
.WorkingSetSize
;
1366 ppsmemCounters
->QuotaPeakPagedPoolUsage
= vmc
.QuotaPeakPagedPoolUsage
;
1367 ppsmemCounters
->QuotaPagedPoolUsage
= vmc
.QuotaPagedPoolUsage
;
1368 ppsmemCounters
->QuotaPeakNonPagedPoolUsage
= vmc
.QuotaPeakNonPagedPoolUsage
;
1369 ppsmemCounters
->QuotaNonPagedPoolUsage
= vmc
.QuotaNonPagedPoolUsage
;
1370 ppsmemCounters
->PagefileUsage
= vmc
.PagefileUsage
;
1371 ppsmemCounters
->PeakPagefileUsage
= vmc
.PeakPagefileUsage
;
1377 SetLastErrorByStatus(_SEH_GetExceptionCode());
1390 QueryWorkingSet(HANDLE hProcess
,
1396 Status
= NtQueryVirtualMemory(hProcess
,
1398 MemoryWorkingSetList
,
1402 if(!NT_SUCCESS(Status
))
1404 SetLastErrorByStatus(Status
);