ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

psapi.c
Go to the documentation of this file.
00001 /* $Id: psapi.c 44602 2009-12-15 15:16:01Z tkreuzer $
00002  */
00003 /*
00004  * COPYRIGHT:   See COPYING in the top level directory
00005  * LICENSE:     See LGPL.txt in the top level directory
00006  * PROJECT:     ReactOS system libraries
00007  * FILE:        reactos/lib/psapi/misc/win32.c
00008  * PURPOSE:     Win32 interfaces for PSAPI
00009  * PROGRAMMER:  KJK::Hyperion <noog@libero.it>
00010  *              Thomas Weidenmueller <w3seek@reactos.com>
00011  * UPDATE HISTORY:
00012  *              10/06/2002: Created
00013  */
00014 
00015 #include "precomp.h"
00016 
00017 #define NDEBUG
00018 #include <debug.h>
00019 
00020 BOOLEAN
00021 WINAPI
00022 DllMain(HINSTANCE hDllHandle,
00023         DWORD nReason,
00024         LPVOID Reserved)
00025 {
00026   switch(nReason)
00027   {
00028     case DLL_PROCESS_ATTACH:
00029       DisableThreadLibraryCalls(hDllHandle);
00030       break;
00031   }
00032 
00033   return TRUE;
00034 }
00035 
00036 /* INTERNAL *******************************************************************/
00037 
00038 typedef struct _ENUM_DEVICE_DRIVERS_CONTEXT
00039 {
00040   LPVOID *lpImageBase;
00041   DWORD nCount;
00042   DWORD nTotal;
00043 } ENUM_DEVICE_DRIVERS_CONTEXT, *PENUM_DEVICE_DRIVERS_CONTEXT;
00044 
00045 NTSTATUS WINAPI
00046 EnumDeviceDriversCallback(IN PRTL_PROCESS_MODULE_INFORMATION CurrentModule,
00047                           IN OUT PVOID CallbackContext)
00048 {
00049   PENUM_DEVICE_DRIVERS_CONTEXT Context = (PENUM_DEVICE_DRIVERS_CONTEXT)CallbackContext;
00050 
00051   /* check if more buffer space is available */
00052   if(Context->nCount != 0)
00053   {
00054     /* return current module */
00055     *Context->lpImageBase = CurrentModule->ImageBase;
00056 
00057     /* go to next array slot */
00058     Context->lpImageBase++;
00059     Context->nCount--;
00060   }
00061 
00062   Context->nTotal++;
00063   return STATUS_SUCCESS;
00064 }
00065 
00066 
00067 typedef struct _ENUM_PROCESSES_CONTEXT
00068 {
00069   DWORD *lpidProcess;
00070   DWORD nCount;
00071 } ENUM_PROCESSES_CONTEXT, *PENUM_PROCESSES_CONTEXT;
00072 
00073 NTSTATUS WINAPI
00074 EnumProcessesCallback(IN PSYSTEM_PROCESS_INFORMATION CurrentProcess,
00075                       IN OUT PVOID CallbackContext)
00076 {
00077   PENUM_PROCESSES_CONTEXT Context = (PENUM_PROCESSES_CONTEXT)CallbackContext;
00078 
00079   /* no more buffer space */
00080   if(Context->nCount == 0)
00081   {
00082     return STATUS_INFO_LENGTH_MISMATCH;
00083   }
00084 
00085   /* return current process */
00086   *Context->lpidProcess = (DWORD_PTR)CurrentProcess->UniqueProcessId;
00087 
00088   /* go to next array slot */
00089   Context->lpidProcess++;
00090   Context->nCount--;
00091 
00092   return STATUS_SUCCESS;
00093 }
00094 
00095 
00096 typedef struct _ENUM_PROCESS_MODULES_CONTEXT
00097 {
00098   HMODULE *lphModule;
00099   DWORD nCount;
00100   DWORD nTotal;
00101 } ENUM_PROCESS_MODULES_CONTEXT, *PENUM_PROCESS_MODULES_CONTEXT;
00102 
00103 NTSTATUS WINAPI
00104 EnumProcessModulesCallback(IN HANDLE ProcessHandle,
00105                            IN PLDR_DATA_TABLE_ENTRY CurrentModule,
00106                            IN OUT PVOID CallbackContext)
00107 {
00108   PENUM_PROCESS_MODULES_CONTEXT Context = (PENUM_PROCESS_MODULES_CONTEXT)CallbackContext;
00109 
00110   /* check if more buffer space is available */
00111   if(Context->nCount != 0)
00112   {
00113     /* return current process */
00114     *Context->lphModule = CurrentModule->DllBase;
00115 
00116     /* go to next array slot */
00117     Context->lphModule++;
00118     Context->nCount--;
00119   }
00120 
00121   Context->nTotal++;
00122   return STATUS_SUCCESS;
00123 }
00124 
00125 
00126 typedef struct _GET_DEVICE_DRIVER_NAME_CONTEXT
00127 {
00128   LPVOID ImageBase;
00129   struct
00130   {
00131     ULONG bFullName : sizeof(ULONG) * 8 / 2;
00132     ULONG bUnicode : sizeof(ULONG) * 8 / 2;
00133   };
00134   DWORD nSize;
00135   union
00136   {
00137     LPVOID lpName;
00138     LPSTR lpAnsiName;
00139     LPWSTR lpUnicodeName;
00140   };
00141 } GET_DEVICE_DRIVER_NAME_CONTEXT, *PGET_DEVICE_DRIVER_NAME_CONTEXT;
00142 
00143 NTSTATUS WINAPI
00144 GetDeviceDriverNameCallback(IN PRTL_PROCESS_MODULE_INFORMATION CurrentModule,
00145                             IN OUT PVOID CallbackContext)
00146 {
00147   PGET_DEVICE_DRIVER_NAME_CONTEXT Context = (PGET_DEVICE_DRIVER_NAME_CONTEXT)CallbackContext;
00148 
00149   /* module found */
00150   if(Context->ImageBase == CurrentModule->ImageBase)
00151   {
00152     PCHAR pcModuleName;
00153     ULONG l;
00154 
00155     /* get the full name or just the filename part */
00156     if(Context->bFullName)
00157       pcModuleName = &CurrentModule->FullPathName[0];
00158     else
00159       pcModuleName = &CurrentModule->FullPathName[CurrentModule->OffsetToFileName];
00160 
00161     /* get the length of the name */
00162     l = strlen(pcModuleName);
00163 
00164     if(Context->nSize <= l)
00165     {
00166       /* use the user buffer's length */
00167       l = Context->nSize;
00168     }
00169     else
00170     {
00171       /* enough space for the null terminator */
00172       Context->nSize = ++l;
00173     }
00174 
00175     /* copy the string */
00176     if(Context->bUnicode)
00177     {
00178       ANSI_STRING AnsiString;
00179       UNICODE_STRING UnicodeString;
00180 
00181       UnicodeString.Length = 0;
00182       UnicodeString.MaximumLength = l * sizeof(WCHAR);
00183       UnicodeString.Buffer = Context->lpUnicodeName;
00184 
00185       RtlInitAnsiString(&AnsiString, pcModuleName);
00186       /* driver names should always be in language-neutral ASCII, so we don't
00187          bother calling AreFileApisANSI() */
00188       RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE);
00189     }
00190     else
00191     {
00192       memcpy(Context->lpAnsiName, pcModuleName, l);
00193     }
00194 
00195     /* terminate the enumeration */
00196     return STATUS_NO_MORE_FILES;
00197   }
00198   else
00199   {
00200     /* continue searching */
00201     return STATUS_SUCCESS;
00202   }
00203 }
00204 
00205 
00206 static DWORD
00207 InternalGetDeviceDriverName(BOOLEAN bUnicode,
00208                             BOOLEAN bFullName,
00209                             LPVOID ImageBase,
00210                             LPVOID lpName,
00211                             DWORD nSize)
00212 {
00213   GET_DEVICE_DRIVER_NAME_CONTEXT Context;
00214   NTSTATUS Status;
00215 
00216   if(lpName == NULL || nSize == 0)
00217   {
00218     return 0;
00219   }
00220 
00221   if(ImageBase == NULL)
00222   {
00223     SetLastError(ERROR_INVALID_HANDLE);
00224     return 0;
00225   }
00226 
00227   Context.ImageBase = ImageBase;
00228   Context.bFullName = bFullName;
00229   Context.bUnicode = bUnicode;
00230   Context.nSize = nSize;
00231   Context.lpName = lpName;
00232 
00233   /* start the enumeration */
00234   Status = PsaEnumerateSystemModules(GetDeviceDriverNameCallback, &Context);
00235 
00236   if(Status == STATUS_NO_MORE_FILES)
00237   {
00238     /* module was found, return string size */
00239     return Context.nSize;
00240   }
00241   else if(NT_SUCCESS(Status))
00242   {
00243     /* module was not found */
00244     SetLastError(ERROR_INVALID_HANDLE);
00245   }
00246   else
00247   {
00248     /* an error occurred */
00249     SetLastErrorByStatus(Status);
00250   }
00251   return 0;
00252 }
00253 
00254 
00255 static DWORD
00256 InternalGetMappedFileName(BOOLEAN bUnicode,
00257                           HANDLE hProcess,
00258                           LPVOID lpv,
00259                           LPVOID lpName,
00260                           DWORD nSize)
00261 {
00262   PMEMORY_SECTION_NAME pmsnName;
00263   ULONG nBufSize;
00264   NTSTATUS Status;
00265 
00266   if(nSize == 0 || lpName == NULL)
00267   {
00268     return 0;
00269   }
00270 
00271   if(nSize > (0xFFFF / sizeof(WCHAR)))
00272   {
00273     /* if the user buffer contains more characters than would fit in an
00274        UNICODE_STRING, limit the buffer size. RATIONALE: we don't limit buffer
00275        size elsewhere because here superfluous buffer size will mean a larger
00276        temporary buffer */
00277     nBufSize = 0xFFFF / sizeof(WCHAR);
00278   }
00279   else
00280   {
00281     nBufSize = nSize * sizeof(WCHAR);
00282   }
00283 
00284   /* allocate the memory */
00285   pmsnName = PsaiMalloc(nBufSize + sizeof(MEMORY_SECTION_NAME));
00286 
00287   if(pmsnName == NULL)
00288   {
00289     SetLastError(ERROR_OUTOFMEMORY);
00290     return 0;
00291   }
00292 
00293    /* initialize the destination buffer */
00294    pmsnName->SectionFileName.Length = 0;
00295    pmsnName->SectionFileName.Length = nBufSize;
00296 
00297 #if 0
00298    __try
00299    {
00300 #endif
00301    /* query the name */
00302    Status = NtQueryVirtualMemory(hProcess,
00303                                  lpv,
00304                                  MemorySectionName,
00305                                  pmsnName,
00306                                  nBufSize,
00307                                  NULL);
00308    if(!NT_SUCCESS(Status))
00309    {
00310      PsaiFree(pmsnName);
00311      SetLastErrorByStatus(Status);
00312      return 0;
00313    }
00314 
00315    if(bUnicode)
00316    {
00317      /* destination is an Unicode string: direct copy */
00318      memcpy((LPWSTR)lpName, pmsnName + 1, pmsnName->SectionFileName.Length);
00319 
00320      PsaiFree(pmsnName);
00321 
00322      if(pmsnName->SectionFileName.Length < nSize)
00323      {
00324        /* null-terminate the string */
00325        ((LPWSTR)lpName)[pmsnName->SectionFileName.Length] = 0;
00326        return pmsnName->SectionFileName.Length + 1;
00327      }
00328 
00329      return pmsnName->SectionFileName.Length;
00330    }
00331    else
00332    {
00333      ANSI_STRING AnsiString;
00334 
00335      AnsiString.Length = 0;
00336      AnsiString.MaximumLength = nSize;
00337      AnsiString.Buffer = (LPSTR)lpName;
00338 
00339      if(AreFileApisANSI())
00340        RtlUnicodeStringToAnsiString(&AnsiString, &pmsnName->SectionFileName, FALSE);
00341      else
00342        RtlUnicodeStringToOemString(&AnsiString, &pmsnName->SectionFileName, FALSE);
00343 
00344      PsaiFree(pmsnName);
00345 
00346      if(AnsiString.Length < nSize)
00347      {
00348        /* null-terminate the string */
00349        ((LPSTR)lpName)[AnsiString.Length] = 0;
00350        return AnsiString.Length + 1;
00351      }
00352 
00353      return AnsiString.Length;
00354    }
00355 
00356 #if 0
00357    }
00358    __finally
00359    {
00360      PsaiFree(pmsnName);
00361    }
00362 #endif
00363 }
00364 
00365 
00366 typedef struct _GET_MODULE_INFORMATION_FLAGS
00367 {
00368   ULONG bWantName : sizeof(ULONG) * 8 / 4;
00369   ULONG bUnicode : sizeof(ULONG) * 8 / 4;
00370   ULONG bFullName : sizeof(ULONG) * 8 / 4;
00371 } GET_MODULE_INFORMATION_FLAGS, *PGET_MODULE_INFORMATION_FLAGS;
00372 
00373 typedef struct _GET_MODULE_INFORMATION_CONTEXT
00374 {
00375   HMODULE hModule;
00376   GET_MODULE_INFORMATION_FLAGS Flags;
00377   DWORD nBufSize;
00378   union
00379   {
00380     LPWSTR lpUnicodeName;
00381     LPSTR lpAnsiName;
00382     LPMODULEINFO lpmodinfo;
00383     LPVOID lpBuffer;
00384   };
00385 } GET_MODULE_INFORMATION_CONTEXT, *PGET_MODULE_INFORMATION_CONTEXT;
00386 
00387 NTSTATUS WINAPI
00388 GetModuleInformationCallback(IN HANDLE ProcessHandle,
00389                              IN PLDR_DATA_TABLE_ENTRY CurrentModule,
00390                              IN OUT PVOID CallbackContext)
00391 {
00392   PGET_MODULE_INFORMATION_CONTEXT Context = (PGET_MODULE_INFORMATION_CONTEXT)CallbackContext;
00393 
00394   /* found the module we were looking for */
00395   if(CurrentModule->DllBase == Context->hModule)
00396   {
00397     /* we want the module name */
00398     if(Context->Flags.bWantName)
00399     {
00400       PUNICODE_STRING SourceString;
00401       ULONG l;
00402       NTSTATUS Status;
00403 
00404       if(Context->Flags.bFullName)
00405         SourceString = &(CurrentModule->FullDllName);
00406       else
00407         SourceString = &(CurrentModule->BaseDllName);
00408 
00409       SourceString->Length -= SourceString->Length % sizeof(WCHAR);
00410 
00411       /* l is the byte size of the user buffer */
00412       l = Context->nBufSize * sizeof(WCHAR);
00413 
00414       /* if the user buffer has room for the string and a null terminator */
00415       if(l >= (SourceString->Length + sizeof(WCHAR)))
00416       {
00417         /* limit the buffer size */
00418         l = SourceString->Length;
00419 
00420         /* null-terminate the string */
00421         if(Context->Flags.bUnicode)
00422           Context->lpUnicodeName[l / sizeof(WCHAR)] = 0;
00423         else
00424           Context->lpAnsiName[l / sizeof(WCHAR)] = 0;
00425       }
00426 
00427       if(Context->Flags.bUnicode)
00428       {
00429         /* Unicode: direct copy */
00430         /* NOTE: I've chosen not to check for ProcessHandle == NtCurrentProcess(),
00431                  this function is complicated enough as it is */
00432         Status = NtReadVirtualMemory(ProcessHandle,
00433                                      SourceString->Buffer,
00434                                      Context->lpUnicodeName,
00435                                      l,
00436                                      NULL);
00437 
00438         if(!NT_SUCCESS(Status))
00439         {
00440           Context->nBufSize = 0;
00441           return Status;
00442         }
00443 
00444         Context->nBufSize = l / sizeof(WCHAR);
00445       }
00446       else
00447       {
00448         /* ANSI/OEM: convert and copy */
00449         LPWSTR pwcUnicodeBuf;
00450         ANSI_STRING AnsiString;
00451         UNICODE_STRING UnicodeString;
00452 
00453         AnsiString.Length = 0;
00454         AnsiString.MaximumLength = Context->nBufSize;
00455         AnsiString.Buffer = Context->lpAnsiName;
00456 
00457         /* allocate the local buffer */
00458         pwcUnicodeBuf = PsaiMalloc(SourceString->Length);
00459 
00460 #if 0
00461         __try
00462         {
00463 #endif
00464         if(pwcUnicodeBuf == NULL)
00465         {
00466           Status = STATUS_NO_MEMORY;
00467           goto exitWithStatus;
00468         }
00469 
00470         /* copy the string in the local buffer */
00471         Status = NtReadVirtualMemory(ProcessHandle,
00472                                      SourceString->Buffer,
00473                                      pwcUnicodeBuf,
00474                                      l,
00475                                      NULL);
00476 
00477         if(!NT_SUCCESS(Status))
00478         {
00479           goto exitWithStatus;
00480         }
00481 
00482         /* initialize Unicode string buffer */
00483         UnicodeString.Length = UnicodeString.MaximumLength = l;
00484         UnicodeString.Buffer = pwcUnicodeBuf;
00485 
00486         /* convert and copy */
00487         if(AreFileApisANSI())
00488           RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
00489         else
00490           RtlUnicodeStringToOemString(&AnsiString, &UnicodeString, FALSE);
00491 
00492         /* return the string size */
00493         Context->nBufSize = AnsiString.Length;
00494 #if 0
00495         }
00496         __finally
00497         {
00498           /* free the buffer */
00499           PsaiFree(pwcUnicodeBuf);
00500         }
00501 #else
00502         Status = STATUS_NO_MORE_FILES;
00503 
00504 exitWithStatus:
00505         /* free the buffer */
00506         PsaiFree(pwcUnicodeBuf);
00507         return Status;
00508 #endif
00509       }
00510     }
00511     else
00512     {
00513       /* we want other module information */
00514       ULONG nSize = Context->nBufSize;
00515 
00516       /* base address */
00517       if(nSize >= sizeof(CurrentModule->DllBase))
00518       {
00519         Context->lpmodinfo->lpBaseOfDll = CurrentModule->DllBase;
00520         nSize -= sizeof(CurrentModule->DllBase);
00521       }
00522 
00523       /* image size */
00524       if(nSize >= sizeof(CurrentModule->SizeOfImage))
00525       {
00526         Context->lpmodinfo->SizeOfImage = CurrentModule->SizeOfImage;
00527         nSize -= sizeof(CurrentModule->SizeOfImage);
00528       }
00529 
00530       /* entry point */
00531       if(nSize >= sizeof(CurrentModule->EntryPoint))
00532       {
00533         /* ??? FIXME? is "EntryPoint" just the offset, or the real address? */
00534         Context->lpmodinfo->EntryPoint = (PVOID)CurrentModule->EntryPoint;
00535       }
00536 
00537       Context->nBufSize = TRUE;
00538     }
00539 
00540     return STATUS_NO_MORE_FILES;
00541   }
00542 
00543   return STATUS_SUCCESS;
00544 }
00545 
00546 
00547 static DWORD
00548 InternalGetModuleInformation(HANDLE hProcess,
00549                              HMODULE hModule,
00550                              GET_MODULE_INFORMATION_FLAGS Flags,
00551                              LPVOID lpBuffer,
00552                              DWORD nBufSize)
00553 {
00554   GET_MODULE_INFORMATION_CONTEXT Context;
00555   NTSTATUS Status;
00556 
00557   Context.hModule = hModule;
00558   Context.Flags = Flags;
00559   Context.nBufSize = nBufSize;
00560   Context.lpBuffer = lpBuffer;
00561 
00562   Status = PsaEnumerateProcessModules(hProcess, GetModuleInformationCallback, &Context);
00563 
00564   if(Status == STATUS_NO_MORE_FILES)
00565   {
00566     /* module was found, return string size */
00567     return Context.nBufSize;
00568   }
00569   else if(NT_SUCCESS(Status))
00570   {
00571     /* module was not found */
00572     SetLastError(ERROR_INVALID_HANDLE);
00573   }
00574   else
00575   {
00576     /* an error occurred */
00577     SetLastErrorByStatus(Status);
00578   }
00579   return 0;
00580 }
00581 
00582 
00583 typedef struct _INTERNAL_ENUM_PAGE_FILES_CONTEXT
00584 {
00585   PENUM_PAGE_FILE_CALLBACKA pCallbackRoutine;
00586   LPVOID lpContext;
00587 } INTERNAL_ENUM_PAGE_FILES_CONTEXT, *PINTERNAL_ENUM_PAGE_FILES_CONTEXT;
00588 
00589 
00590 static BOOL CALLBACK
00591 InternalAnsiPageFileCallback(LPVOID pContext,
00592                              PENUM_PAGE_FILE_INFORMATION pPageFileInfo,
00593                              LPCWSTR lpFilename)
00594 {
00595   size_t slen;
00596   LPSTR AnsiFileName;
00597   PINTERNAL_ENUM_PAGE_FILES_CONTEXT Context = (PINTERNAL_ENUM_PAGE_FILES_CONTEXT)pContext;
00598 
00599   slen = wcslen(lpFilename);
00600 
00601   AnsiFileName = (LPSTR)LocalAlloc(LMEM_FIXED, (slen + 1) * sizeof(CHAR));
00602   if(AnsiFileName != NULL)
00603   {
00604     BOOL Ret;
00605 
00606     WideCharToMultiByte(CP_ACP,
00607                         0,
00608                         lpFilename,
00609                         -1, /* only works if the string is NULL-terminated!!! */
00610                         AnsiFileName,
00611                         (slen + 1) * sizeof(CHAR),
00612                         NULL,
00613                         NULL);
00614 
00615     Ret = Context->pCallbackRoutine(Context->lpContext, pPageFileInfo, AnsiFileName);
00616 
00617     LocalFree((HLOCAL)AnsiFileName);
00618 
00619     return Ret;
00620   }
00621 
00622   return FALSE;
00623 }
00624 
00625 /* PUBLIC *********************************************************************/
00626 
00627 /*
00628  * @implemented
00629  */
00630 BOOL
00631 WINAPI
00632 EmptyWorkingSet(HANDLE hProcess)
00633 {
00634   QUOTA_LIMITS QuotaLimits;
00635   NTSTATUS Status;
00636 
00637   /* query the working set */
00638   Status = NtQueryInformationProcess(hProcess,
00639                                      ProcessQuotaLimits,
00640                                      &QuotaLimits,
00641                                      sizeof(QuotaLimits),
00642                                      NULL);
00643 
00644   if(!NT_SUCCESS(Status))
00645   {
00646     SetLastErrorByStatus(Status);
00647     return FALSE;
00648   }
00649 
00650   /* empty the working set */
00651   QuotaLimits.MinimumWorkingSetSize = -1;
00652   QuotaLimits.MaximumWorkingSetSize = -1;
00653 
00654   /* set the working set */
00655   Status = NtSetInformationProcess(hProcess,
00656                                    ProcessQuotaLimits,
00657                                    &QuotaLimits,
00658                                    sizeof(QuotaLimits));
00659   if(!NT_SUCCESS(Status))
00660   {
00661     SetLastErrorByStatus(Status);
00662     return FALSE;
00663   }
00664 
00665   return TRUE;
00666 }
00667 
00668 
00669 /*
00670  * @implemented
00671  */
00672 BOOL
00673 WINAPI
00674 EnumDeviceDrivers(LPVOID *lpImageBase,
00675                   DWORD cb,
00676                   LPDWORD lpcbNeeded)
00677 {
00678   ENUM_DEVICE_DRIVERS_CONTEXT Context;
00679   NTSTATUS Status;
00680 
00681   cb /= sizeof(PVOID);
00682 
00683   Context.lpImageBase = lpImageBase;
00684   Context.nCount = cb;
00685   Context.nTotal = 0;
00686 
00687   Status = PsaEnumerateSystemModules(EnumDeviceDriversCallback, &Context);
00688 
00689   /* return the count of bytes that would be needed for a complete enumeration */
00690   *lpcbNeeded = Context.nTotal * sizeof(PVOID);
00691 
00692   if(!NT_SUCCESS(Status))
00693   {
00694     SetLastErrorByStatus(Status);
00695     return FALSE;
00696   }
00697 
00698   return TRUE;
00699 }
00700 
00701 
00702 /*
00703  * @implemented
00704  */
00705 BOOL
00706 WINAPI
00707 EnumProcesses(DWORD *lpidProcess,
00708               DWORD cb,
00709               LPDWORD lpcbNeeded)
00710 {
00711   ENUM_PROCESSES_CONTEXT Context;
00712   NTSTATUS Status;
00713 
00714   cb /= sizeof(DWORD);
00715 
00716   if(cb == 0 || lpidProcess == NULL)
00717   {
00718     *lpcbNeeded = 0;
00719     return TRUE;
00720   }
00721 
00722   Context.lpidProcess = lpidProcess;
00723   Context.nCount = cb;
00724 
00725   /* enumerate the process ids */
00726   Status = PsaEnumerateProcesses(EnumProcessesCallback, &Context);
00727 
00728   *lpcbNeeded = (cb - Context.nCount) * sizeof(DWORD);
00729 
00730   if(!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH))
00731   {
00732     SetLastErrorByStatus(Status);
00733     return FALSE;
00734   }
00735 
00736   return TRUE;
00737 }
00738 
00739 
00740 /*
00741  * @implemented
00742  */
00743 BOOL
00744 WINAPI
00745 EnumProcessModules(HANDLE hProcess,
00746                    HMODULE *lphModule,
00747                    DWORD cb,
00748                    LPDWORD lpcbNeeded)
00749 {
00750   ENUM_PROCESS_MODULES_CONTEXT Context;
00751   NTSTATUS Status;
00752 
00753   cb /= sizeof(HMODULE);
00754 
00755   Context.lphModule = lphModule;
00756   Context.nCount = cb;
00757   Context.nTotal = 0;
00758 
00759   /* enumerate the process modules */
00760   Status = PsaEnumerateProcessModules(hProcess, EnumProcessModulesCallback, &Context);
00761 
00762   *lpcbNeeded = Context.nTotal * sizeof(HMODULE);
00763 
00764   if(!NT_SUCCESS(Status))
00765   {
00766     SetLastErrorByStatus(Status);
00767     return FALSE;
00768   }
00769 
00770   return TRUE;
00771 }
00772 
00773 
00774 /*
00775  * @implemented
00776  */
00777 DWORD
00778 WINAPI
00779 GetDeviceDriverBaseNameA(LPVOID ImageBase,
00780                          LPSTR lpBaseName,
00781                          DWORD nSize)
00782 {
00783   return InternalGetDeviceDriverName(FALSE, FALSE, ImageBase, lpBaseName, nSize);
00784 }
00785 
00786 
00787 /*
00788  * @implemented
00789  */
00790 DWORD
00791 WINAPI
00792 GetDeviceDriverFileNameA(LPVOID ImageBase,
00793                          LPSTR lpFilename,
00794                          DWORD nSize)
00795 {
00796   return InternalGetDeviceDriverName(FALSE, TRUE, ImageBase, lpFilename, nSize);
00797 }
00798 
00799 
00800 /*
00801  * @implemented
00802  */
00803 DWORD
00804 WINAPI
00805 GetDeviceDriverBaseNameW(LPVOID ImageBase,
00806                          LPWSTR lpBaseName,
00807                          DWORD nSize)
00808 {
00809   return InternalGetDeviceDriverName(TRUE, FALSE, ImageBase, lpBaseName, nSize);
00810 }
00811 
00812 
00813 /*
00814  * @implemented
00815  */
00816 DWORD
00817 WINAPI
00818 GetDeviceDriverFileNameW(LPVOID ImageBase,
00819                          LPWSTR lpFilename,
00820                          DWORD nSize)
00821 {
00822   return InternalGetDeviceDriverName(TRUE, TRUE, ImageBase, lpFilename, nSize);
00823 }
00824 
00825 
00826 /*
00827  * @implemented
00828  */
00829 DWORD
00830 WINAPI
00831 GetMappedFileNameA(HANDLE hProcess,
00832                    LPVOID lpv,
00833                    LPSTR lpFilename,
00834                    DWORD nSize)
00835 {
00836   return InternalGetMappedFileName(FALSE, hProcess, lpv, lpFilename, nSize);
00837 }
00838 
00839 
00840 /*
00841  * @implemented
00842  */
00843 DWORD
00844 WINAPI
00845 GetMappedFileNameW(HANDLE hProcess,
00846                    LPVOID lpv,
00847                    LPWSTR lpFilename,
00848                    DWORD nSize)
00849 {
00850   return InternalGetMappedFileName(TRUE, hProcess, lpv, lpFilename, nSize);
00851 }
00852 
00853 
00854 /*
00855  * @implemented
00856  */
00857 DWORD
00858 WINAPI
00859 GetModuleBaseNameA(HANDLE hProcess,
00860                    HMODULE hModule,
00861                    LPSTR lpBaseName,
00862                    DWORD nSize)
00863 {
00864   GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, FALSE, FALSE};
00865   return InternalGetModuleInformation(hProcess, hModule, Flags, lpBaseName, nSize);
00866 }
00867 
00868 
00869 /*
00870  * @implemented
00871  */
00872 DWORD
00873 WINAPI
00874 GetModuleBaseNameW(HANDLE hProcess,
00875                    HMODULE hModule,
00876                    LPWSTR lpBaseName,
00877                    DWORD nSize)
00878 {
00879   GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, TRUE, FALSE};
00880   return InternalGetModuleInformation(hProcess, hModule, Flags, lpBaseName, nSize);
00881 }
00882 
00883 
00884 /*
00885  * @implemented
00886  */
00887 DWORD
00888 WINAPI
00889 GetModuleFileNameExA(HANDLE hProcess,
00890                      HMODULE hModule,
00891                      LPSTR lpFilename,
00892                      DWORD nSize)
00893 {
00894   GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, FALSE, TRUE};
00895   return InternalGetModuleInformation(hProcess, hModule, Flags, lpFilename, nSize);
00896 }
00897 
00898 
00899 /*
00900  * @implemented
00901  */
00902 DWORD
00903 WINAPI
00904 GetModuleFileNameExW(HANDLE hProcess,
00905                      HMODULE hModule,
00906                      LPWSTR lpFilename,
00907                      DWORD nSize)
00908 {
00909   GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, TRUE, TRUE};
00910   return InternalGetModuleInformation(hProcess, hModule, Flags, lpFilename, nSize);
00911 }
00912 
00913 
00914 /*
00915  * @implemented
00916  */
00917 BOOL
00918 WINAPI
00919 GetModuleInformation(HANDLE hProcess,
00920                      HMODULE hModule,
00921                      LPMODULEINFO lpmodinfo,
00922                      DWORD cb)
00923 {
00924   GET_MODULE_INFORMATION_FLAGS Flags = {FALSE, FALSE, FALSE};
00925 
00926   if (cb < sizeof(MODULEINFO)) 
00927   {
00928     SetLastError(ERROR_INSUFFICIENT_BUFFER);
00929     return FALSE;
00930   }
00931   return (BOOL)InternalGetModuleInformation(hProcess, hModule, Flags, lpmodinfo, cb);
00932 }
00933 
00934 
00935 /*
00936  * @implemented
00937  */
00938 BOOL
00939 WINAPI
00940 InitializeProcessForWsWatch(HANDLE hProcess)
00941 {
00942   NTSTATUS Status;
00943 
00944   Status = NtSetInformationProcess(hProcess,
00945                                    ProcessWorkingSetWatch,
00946                                    NULL,
00947                                    0);
00948   if(!NT_SUCCESS(Status))
00949   {
00950     SetLastErrorByStatus(Status);
00951     return FALSE;
00952   }
00953 
00954   return TRUE;
00955 }
00956 
00957 
00958 /*
00959  * @implemented
00960  */
00961 BOOL
00962 WINAPI
00963 GetWsChanges(HANDLE hProcess,
00964              PPSAPI_WS_WATCH_INFORMATION lpWatchInfo,
00965              DWORD cb)
00966 {
00967   NTSTATUS Status;
00968 
00969   Status = NtQueryInformationProcess(hProcess,
00970                                      ProcessWorkingSetWatch,
00971                                      (PVOID)lpWatchInfo,
00972                                      cb,
00973                                      NULL);
00974   if(!NT_SUCCESS(Status))
00975   {
00976     SetLastErrorByStatus(Status);
00977     return FALSE;
00978   }
00979 
00980   return TRUE;
00981 }
00982 
00983 
00984 /*
00985  * @implemented
00986  */
00987 DWORD
00988 WINAPI
00989 GetProcessImageFileNameW(HANDLE hProcess,
00990                          LPWSTR lpImageFileName,
00991                          DWORD nSize)
00992 {
00993   PUNICODE_STRING ImageFileName;
00994   SIZE_T BufferSize;
00995   NTSTATUS Status;
00996   DWORD Ret = 0;
00997 
00998   BufferSize = sizeof(UNICODE_STRING) + (nSize * sizeof(WCHAR));
00999 
01000   ImageFileName = (PUNICODE_STRING)LocalAlloc(LMEM_FIXED, BufferSize);
01001   if(ImageFileName != NULL)
01002   {
01003     Status = NtQueryInformationProcess(hProcess,
01004                                        ProcessImageFileName,
01005                                        ImageFileName,
01006                                        BufferSize,
01007                                        NULL);
01008     if(NT_SUCCESS(Status))
01009     {
01010       memcpy(lpImageFileName, ImageFileName->Buffer, ImageFileName->Length);
01011 
01012       /* make sure the string is null-terminated! */
01013       lpImageFileName[ImageFileName->Length / sizeof(WCHAR)] = L'\0';
01014       Ret = ImageFileName->Length / sizeof(WCHAR);
01015     }
01016     else if(Status == STATUS_INFO_LENGTH_MISMATCH)
01017     {
01018       /* XP sets this error code for some reason if the buffer is too small */
01019       SetLastError(ERROR_INSUFFICIENT_BUFFER);
01020     }
01021     else
01022     {
01023       SetLastErrorByStatus(Status);
01024     }
01025 
01026     LocalFree((HLOCAL)ImageFileName);
01027   }
01028 
01029   return Ret;
01030 }
01031 
01032 
01033 /*
01034  * @implemented
01035  */
01036 DWORD
01037 WINAPI
01038 GetProcessImageFileNameA(HANDLE hProcess,
01039                          LPSTR lpImageFileName,
01040                          DWORD nSize)
01041 {
01042   PUNICODE_STRING ImageFileName;
01043   SIZE_T BufferSize;
01044   NTSTATUS Status;
01045   DWORD Ret = 0;
01046 
01047   BufferSize = sizeof(UNICODE_STRING) + (nSize * sizeof(WCHAR));
01048 
01049   ImageFileName = (PUNICODE_STRING)LocalAlloc(LMEM_FIXED, BufferSize);
01050   if(ImageFileName != NULL)
01051   {
01052     Status = NtQueryInformationProcess(hProcess,
01053                                        ProcessImageFileName,
01054                                        ImageFileName,
01055                                        BufferSize,
01056                                        NULL);
01057     if(NT_SUCCESS(Status))
01058     {
01059       WideCharToMultiByte(CP_ACP,
01060                           0,
01061                           ImageFileName->Buffer,
01062                           ImageFileName->Length / sizeof(WCHAR),
01063                           lpImageFileName,
01064                           nSize,
01065                           NULL,
01066                           NULL);
01067 
01068       /* make sure the string is null-terminated! */
01069       lpImageFileName[ImageFileName->Length / sizeof(WCHAR)] = '\0';
01070       Ret = ImageFileName->Length / sizeof(WCHAR);
01071     }
01072     else if(Status == STATUS_INFO_LENGTH_MISMATCH)
01073     {
01074       /* XP sets this error code for some reason if the buffer is too small */
01075       SetLastError(ERROR_INSUFFICIENT_BUFFER);
01076     }
01077     else
01078     {
01079       SetLastErrorByStatus(Status);
01080     }
01081 
01082     LocalFree((HLOCAL)ImageFileName);
01083   }
01084 
01085   return Ret;
01086 }
01087 
01088 
01089 /*
01090  * @implemented
01091  */
01092 BOOL
01093 WINAPI
01094 EnumPageFilesA(PENUM_PAGE_FILE_CALLBACKA pCallbackRoutine,
01095                LPVOID lpContext)
01096 {
01097   INTERNAL_ENUM_PAGE_FILES_CONTEXT Context;
01098 
01099   Context.pCallbackRoutine = pCallbackRoutine;
01100   Context.lpContext = lpContext;
01101 
01102   return EnumPageFilesW(InternalAnsiPageFileCallback, &Context);
01103 }
01104 
01105 
01106 /*
01107  * @implemented
01108  */
01109 BOOL
01110 WINAPI
01111 EnumPageFilesW(PENUM_PAGE_FILE_CALLBACKW pCallbackRoutine,
01112                LPVOID lpContext)
01113 {
01114   NTSTATUS Status;
01115   PVOID Buffer;
01116   ULONG BufferSize = 0;
01117   BOOL Ret = FALSE;
01118 
01119   for(;;)
01120   {
01121     BufferSize += 0x1000;
01122     Buffer = LocalAlloc(LMEM_FIXED, BufferSize);
01123     if(Buffer == NULL)
01124     {
01125       return FALSE;
01126     }
01127 
01128     Status = NtQuerySystemInformation(SystemPageFileInformation,
01129                                       Buffer,
01130                                       BufferSize,
01131                                       NULL);
01132     if(Status == STATUS_INFO_LENGTH_MISMATCH)
01133     {
01134       LocalFree((HLOCAL)Buffer);
01135     }
01136     else
01137     {
01138       break;
01139     }
01140   }
01141 
01142   if(NT_SUCCESS(Status))
01143   {
01144     ENUM_PAGE_FILE_INFORMATION Information;
01145     PSYSTEM_PAGEFILE_INFORMATION pfi = (PSYSTEM_PAGEFILE_INFORMATION)Buffer;
01146     ULONG Offset = 0;
01147 
01148     do
01149     {
01150       PWCHAR Colon;
01151 
01152       pfi = (PSYSTEM_PAGEFILE_INFORMATION)((ULONG_PTR)pfi + Offset);
01153 
01154       Information.cb = sizeof(Information);
01155       Information.Reserved = 0;
01156       Information.TotalSize = pfi->TotalSize;
01157       Information.TotalInUse = pfi->TotalInUse;
01158       Information.PeakUsage = pfi->PeakUsage;
01159 
01160       /* strip the \??\ prefix from the file name. We do this by searching for the first
01161          : character and then just change Buffer to point to the previous character. */
01162 
01163       Colon = wcschr(pfi->PageFileName.Buffer, L':');
01164       if(Colon != NULL)
01165       {
01166         pfi->PageFileName.Buffer = --Colon;
01167       }
01168 
01169       /* FIXME - looks like the PageFileName string is always NULL-terminated on win.
01170                  At least I haven't encountered a different case so far, we should
01171                  propably manually NULL-terminate the string here... */
01172 
01173       if(!pCallbackRoutine(lpContext, &Information, pfi->PageFileName.Buffer))
01174       {
01175         break;
01176       }
01177 
01178       Offset = pfi->NextEntryOffset;
01179     } while(Offset != 0);
01180 
01181     Ret = TRUE;
01182   }
01183   else
01184   {
01185     SetLastErrorByStatus(Status);
01186   }
01187 
01188   LocalFree((HLOCAL)Buffer);
01189 
01190   return Ret;
01191 }
01192 
01193 
01194 /*
01195  * @implemented
01196  */
01197 BOOL
01198 WINAPI
01199 GetPerformanceInfo(PPERFORMANCE_INFORMATION pPerformanceInformation,
01200                    DWORD cb)
01201 {
01202   SYSTEM_PERFORMANCE_INFORMATION spi;
01203   SYSTEM_BASIC_INFORMATION sbi;
01204   SYSTEM_HANDLE_INFORMATION shi;
01205   PSYSTEM_PROCESS_INFORMATION ProcessInfo;
01206   ULONG BufferSize, ProcOffset, ProcessCount, ThreadCount;
01207   PVOID Buffer;
01208   NTSTATUS Status;
01209 
01210   Status = NtQuerySystemInformation(SystemPerformanceInformation,
01211                                     &spi,
01212                                     sizeof(spi),
01213                                     NULL);
01214   if(!NT_SUCCESS(Status))
01215   {
01216     SetLastErrorByStatus(Status);
01217     return FALSE;
01218   }
01219 
01220   Status = NtQuerySystemInformation(SystemBasicInformation,
01221                                     &sbi,
01222                                     sizeof(sbi),
01223                                     NULL);
01224   if(!NT_SUCCESS(Status))
01225   {
01226     SetLastErrorByStatus(Status);
01227     return FALSE;
01228   }
01229 
01230   /*
01231    * allocate enough memory to get a dump of all processes and threads
01232    */
01233   BufferSize = 0;
01234   for(;;)
01235   {
01236     BufferSize += 0x10000;
01237     Buffer = (PVOID)LocalAlloc(LMEM_FIXED, BufferSize);
01238     if(Buffer == NULL)
01239     {
01240       return FALSE;
01241     }
01242 
01243     Status = NtQuerySystemInformation(SystemProcessInformation,
01244                                       Buffer,
01245                                       BufferSize,
01246                                       NULL);
01247     if(Status == STATUS_INFO_LENGTH_MISMATCH)
01248     {
01249       LocalFree((HLOCAL)Buffer);
01250     }
01251     else
01252     {
01253       break;
01254     }
01255   }
01256 
01257   if(!NT_SUCCESS(Status))
01258   {
01259     LocalFree((HLOCAL)Buffer);
01260     SetLastErrorByStatus(Status);
01261     return FALSE;
01262   }
01263 
01264   /*
01265    * determine the process and thread count
01266    */
01267   ProcessCount = ThreadCount = ProcOffset = 0;
01268   ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)Buffer;
01269   do
01270   {
01271     ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset);
01272     ProcessCount++;
01273     ThreadCount += ProcessInfo->NumberOfThreads;
01274 
01275     ProcOffset = ProcessInfo->NextEntryOffset;
01276   } while(ProcOffset != 0);
01277 
01278   LocalFree((HLOCAL)Buffer);
01279 
01280   /*
01281    * it's enough to supply a SYSTEM_HANDLE_INFORMATION structure as buffer. Even
01282    * though it returns STATUS_INFO_LENGTH_MISMATCH, it already sets the NumberOfHandles
01283    * field which is all we're looking for anyway.
01284    */
01285   Status = NtQuerySystemInformation(SystemHandleInformation,
01286                                     &shi,
01287                                     sizeof(shi),
01288                                     NULL);
01289   if(!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH))
01290   {
01291     SetLastErrorByStatus(Status);
01292     return FALSE;
01293   }
01294 
01295   /*
01296    * all required information collected, fill the structure
01297    */
01298 
01299   pPerformanceInformation->cb = sizeof(PERFORMANCE_INFORMATION);
01300   pPerformanceInformation->CommitTotal = spi.CommittedPages;
01301   pPerformanceInformation->CommitLimit = spi.CommitLimit;
01302   pPerformanceInformation->CommitPeak = spi.PeakCommitment;
01303   pPerformanceInformation->PhysicalTotal = sbi.NumberOfPhysicalPages;
01304   pPerformanceInformation->PhysicalAvailable = spi.AvailablePages;
01305   pPerformanceInformation->SystemCache = 0; /* FIXME - where to get this information from? */
01306   pPerformanceInformation->KernelTotal = spi.PagedPoolPages + spi.NonPagedPoolPages;
01307   pPerformanceInformation->KernelPaged = spi.PagedPoolPages;
01308   pPerformanceInformation->KernelNonpaged = spi.NonPagedPoolPages;
01309   pPerformanceInformation->PageSize = sbi.PageSize;
01310   pPerformanceInformation->HandleCount = shi.NumberOfHandles;
01311   pPerformanceInformation->ProcessCount = ProcessCount;
01312   pPerformanceInformation->ThreadCount = ThreadCount;
01313 
01314   return TRUE;
01315 }
01316 
01317 
01318 /*
01319  * @implemented
01320  */
01321 BOOL
01322 WINAPI
01323 GetProcessMemoryInfo(HANDLE Process,
01324                      PPROCESS_MEMORY_COUNTERS ppsmemCounters,
01325                      DWORD cb)
01326 {
01327   NTSTATUS Status;
01328   VM_COUNTERS vmc;
01329   BOOL Ret = FALSE;
01330 
01331   /* XP's implementation secures access to ppsmemCounters in SEH, we should behave
01332      similar so we can return the proper error codes when bad pointers are passed
01333      to this function! */
01334 
01335   _SEH2_TRY
01336   {
01337     if(cb < sizeof(PROCESS_MEMORY_COUNTERS))
01338     {
01339       SetLastError(ERROR_INSUFFICIENT_BUFFER);
01340       _SEH2_LEAVE;
01341     }
01342 
01343     /* ppsmemCounters->cb isn't checked at all! */
01344 
01345     Status = NtQueryInformationProcess(Process,
01346                                        ProcessVmCounters,
01347                                        &vmc,
01348                                        sizeof(vmc),
01349                                        NULL);
01350     if(!NT_SUCCESS(Status))
01351     {
01352       SetLastErrorByStatus(Status);
01353       _SEH2_LEAVE;
01354     }
01355 
01356     /* fill the structure with the collected information, in case of bad pointers
01357        SEH will catch the exception and set the appropriate error code */
01358     ppsmemCounters->cb = sizeof(PROCESS_MEMORY_COUNTERS);
01359     ppsmemCounters->PageFaultCount = vmc.PageFaultCount;
01360     ppsmemCounters->PeakWorkingSetSize = vmc.PeakWorkingSetSize;
01361     ppsmemCounters->WorkingSetSize = vmc.WorkingSetSize;
01362     ppsmemCounters->QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage;
01363     ppsmemCounters->QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage;
01364     ppsmemCounters->QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage;
01365     ppsmemCounters->QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage;
01366     ppsmemCounters->PagefileUsage = vmc.PagefileUsage;
01367     ppsmemCounters->PeakPagefileUsage = vmc.PeakPagefileUsage;
01368 
01369     Ret = TRUE;
01370   }
01371   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01372   {
01373     SetLastErrorByStatus(_SEH2_GetExceptionCode());
01374   }
01375   _SEH2_END;
01376 
01377   return Ret;
01378 }
01379 
01380 
01381 /*
01382  * @implemented
01383  */
01384 BOOL
01385 WINAPI
01386 QueryWorkingSet(HANDLE hProcess,
01387                 PVOID pv,
01388                 DWORD cb)
01389 {
01390   NTSTATUS Status;
01391 
01392   Status = NtQueryVirtualMemory(hProcess,
01393                                 NULL,
01394                                 MemoryWorkingSetList,
01395                                 pv,
01396                                 cb,
01397                                 NULL);
01398   if(!NT_SUCCESS(Status))
01399   {
01400     SetLastErrorByStatus(Status);
01401     return FALSE;
01402   }
01403 
01404   return TRUE;
01405 }
01406 
01407 /*
01408  * @unimplemented
01409  */
01410 BOOL
01411 WINAPI
01412 QueryWorkingSetEx(IN HANDLE hProcess,
01413                   IN OUT PVOID pv,
01414                   IN DWORD cb)
01415 {
01416     UNIMPLEMENTED;
01417     return FALSE;
01418 }
01419 
01420 /* EOF */

Generated on Sun May 27 2012 04:25:55 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.