psapi_main.c 17.4 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3
/*
 *      PSAPI library
 *
4 5
 * Copyright 1998 Patrik Stridvall
 * Copyright 2003 Eric Pouech
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard's avatar
Alexandre Julliard committed
20 21
 */

22 23
#include <stdarg.h>

24 25
#include "ntstatus.h"
#define WIN32_NO_STATUS
26
#include "windef.h"
27
#include "winbase.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
28
#include "winerror.h"
29
#include "wine/unicode.h"
30
#include "wine/debug.h"
31
#include "winnls.h"
32
#include "winternl.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
33 34
#include "psapi.h"

35
WINE_DEFAULT_DEBUG_CHANNEL(psapi);
36

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
typedef struct
{
    HANDLE hProcess;             
    PLIST_ENTRY pHead, pCurrent;
    LDR_MODULE LdrModule;
} MODULE_ITERATOR;

/***********************************************************************
 *           PSAPI_ModuleIteratorInit [internal]
 *
 * Prepares to iterate through the loaded modules of the given process.
 *
 * RETURNS
 *  Success: TRUE
 *  Failure: FALSE
 */
static BOOL PSAPI_ModuleIteratorInit(MODULE_ITERATOR *iter, HANDLE hProcess)
{
    PROCESS_BASIC_INFORMATION pbi;
    PPEB_LDR_DATA pLdrData;
    NTSTATUS status;

    /* Get address of PEB */
    status = NtQueryInformationProcess(hProcess, ProcessBasicInformation,
                                       &pbi, sizeof(pbi), NULL);
    if (status != STATUS_SUCCESS)
    {
        SetLastError(RtlNtStatusToDosError(status));
        return FALSE;
    }

    /* Read address of LdrData from PEB */
69
    if (!ReadProcessMemory(hProcess, &pbi.PebBaseAddress->LdrData,
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
                           &pLdrData, sizeof(pLdrData), NULL))
        return FALSE;

    /* Read address of first module from LdrData */
    if (!ReadProcessMemory(hProcess,
                           &pLdrData->InLoadOrderModuleList.Flink,
                           &iter->pCurrent, sizeof(iter->pCurrent), NULL))
        return FALSE;

    iter->pHead = &pLdrData->InLoadOrderModuleList;
    iter->hProcess = hProcess;

    return TRUE;
}

/***********************************************************************
 *           PSAPI_ModuleIteratorNext [internal]
 *
 * Iterates to the next module.
 *
 * RETURNS
 *   1 : Success
 *   0 : No more modules
 *  -1 : Failure
 *
 * NOTES
 *  Every function which uses this routine suffers from a race condition 
 *  when a module is unloaded during the enumeration which can cause the
 *  function to fail. As there is no way to lock the loader of another 
 *  process we can't avoid that.
 */
static INT PSAPI_ModuleIteratorNext(MODULE_ITERATOR *iter)
{
    if (iter->pCurrent == iter->pHead)
        return 0;

    if (!ReadProcessMemory(iter->hProcess, CONTAINING_RECORD(iter->pCurrent,
                           LDR_MODULE, InLoadOrderModuleList),
                           &iter->LdrModule, sizeof(iter->LdrModule), NULL))
         return -1;
    else
         iter->pCurrent = iter->LdrModule.InLoadOrderModuleList.Flink;

    return 1;
}

/***********************************************************************
 *           PSAPI_GetLdrModule [internal]
 *
 * Reads the LDR_MODULE structure of the given module.
 *
 * RETURNS
 *  Success: TRUE
 *  Failure: FALSE
 */

static BOOL PSAPI_GetLdrModule(HANDLE hProcess, HMODULE hModule, 
                               LDR_MODULE *pLdrModule)
{
    MODULE_ITERATOR iter;
    INT ret;

    if (!PSAPI_ModuleIteratorInit(&iter, hProcess))
        return FALSE;

    while ((ret = PSAPI_ModuleIteratorNext(&iter)) > 0)
        /* When hModule is NULL we return the process image - which will be
         * the first module since our iterator uses InLoadOrderModuleList */
        if (!hModule || hModule == (HMODULE)iter.LdrModule.BaseAddress)
        {
            *pLdrModule = iter.LdrModule;
            return TRUE;
        }

    if (ret == 0)
        SetLastError(ERROR_INVALID_HANDLE);

    return FALSE;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
150
/***********************************************************************
151
 *           EmptyWorkingSet (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
152
 */
153
BOOL WINAPI EmptyWorkingSet(HANDLE hProcess)
Alexandre Julliard's avatar
Alexandre Julliard committed
154
{
155
    return SetProcessWorkingSetSize(hProcess, 0xFFFFFFFF, 0xFFFFFFFF);
Alexandre Julliard's avatar
Alexandre Julliard committed
156 157 158
}

/***********************************************************************
159
 *           EnumDeviceDrivers (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
160
 */
161
BOOL WINAPI EnumDeviceDrivers(LPVOID *lpImageBase, DWORD cb, LPDWORD lpcbNeeded)
Alexandre Julliard's avatar
Alexandre Julliard committed
162
{
163
    FIXME("(%p, %d, %p): stub\n", lpImageBase, cb, lpcbNeeded);
Alexandre Julliard's avatar
Alexandre Julliard committed
164

165 166
    if (lpcbNeeded)
        *lpcbNeeded = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
167

168
    return TRUE;
169
}
Alexandre Julliard's avatar
Alexandre Julliard committed
170

171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
/***********************************************************************
 *           EnumPageFilesA (PSAPI.@)
 */
BOOL WINAPI EnumPageFilesA( PENUM_PAGE_FILE_CALLBACKA callback, LPVOID context )
{
    FIXME("(%p, %p) stub\n", callback, context );
    return FALSE;
}

/***********************************************************************
 *           EnumPageFilesW (PSAPI.@)
 */
BOOL WINAPI EnumPageFilesW( PENUM_PAGE_FILE_CALLBACKW callback, LPVOID context )
{
    FIXME("(%p, %p) stub\n", callback, context );
    return FALSE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
188 189

/***********************************************************************
190
 *           EnumProcesses (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
191
 */
192
BOOL WINAPI EnumProcesses(DWORD *lpdwProcessIDs, DWORD cb, DWORD *lpcbUsed)
Alexandre Julliard's avatar
Alexandre Julliard committed
193
{
194 195 196 197
    SYSTEM_PROCESS_INFORMATION *spi;
    NTSTATUS status;
    PVOID pBuf = NULL;
    ULONG nAlloc = 0x8000;
198

199 200 201 202 203 204
    do {
        if (pBuf != NULL) 
        {
            HeapFree(GetProcessHeap(), 0, pBuf);
            nAlloc *= 2;
        }
205

206 207 208
        pBuf = HeapAlloc(GetProcessHeap(), 0, nAlloc);
        if (pBuf == NULL)
            return FALSE;
209

210 211 212
        status = NtQuerySystemInformation(SystemProcessInformation, pBuf,
                                          nAlloc, NULL);
    } while (status == STATUS_INFO_LENGTH_MISMATCH);
213

214
    if (status != STATUS_SUCCESS)
215
    {
216 217
        HeapFree(GetProcessHeap(), 0, pBuf);
        SetLastError(RtlNtStatusToDosError(status));
218 219
        return FALSE;
    }
220 221 222

    spi = pBuf;

223
    for (*lpcbUsed = 0; cb >= sizeof(DWORD); cb -= sizeof(DWORD))
224
    {
225 226
        *lpdwProcessIDs++ = spi->dwProcessID;
        *lpcbUsed += sizeof(DWORD);
227

228
        if (spi->dwOffset == 0)
229
            break;
230

231 232
        spi = (SYSTEM_PROCESS_INFORMATION *)(((PCHAR)spi) + spi->dwOffset);
    }
233

234
    HeapFree(GetProcessHeap(), 0, pBuf);
235
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
236 237 238
}

/***********************************************************************
239
 *           EnumProcessModules (PSAPI.@)
240 241 242
 *
 * NOTES
 *  Returned list is in load order.
Alexandre Julliard's avatar
Alexandre Julliard committed
243
 */
244
BOOL WINAPI EnumProcessModules(HANDLE hProcess, HMODULE *lphModule,
245
                               DWORD cb, LPDWORD lpcbNeeded)
Alexandre Julliard's avatar
Alexandre Julliard committed
246
{
247 248
    MODULE_ITERATOR iter;
    INT ret;
249

250
    if (!PSAPI_ModuleIteratorInit(&iter, hProcess))
251 252
        return FALSE;

253 254 255
    *lpcbNeeded = 0;
        
    while ((ret = PSAPI_ModuleIteratorNext(&iter)) > 0)
256
    {
257
        if (cb >= sizeof(HMODULE))
258
        {
259 260
            *lphModule++ = (HMODULE)iter.LdrModule.BaseAddress;
            cb -= sizeof(HMODULE);
261
        }
262
        *lpcbNeeded += sizeof(HMODULE);
263 264
    }

265
    return (ret == 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
266 267 268
}

/***********************************************************************
269
 *          GetDeviceDriverBaseNameA (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
270
 */
271 272
DWORD WINAPI GetDeviceDriverBaseNameA(LPVOID ImageBase, LPSTR lpBaseName, 
                                      DWORD nSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
273
{
274
    FIXME("(%p, %p, %d): stub\n", ImageBase, lpBaseName, nSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
275

276 277
    if (lpBaseName && nSize)
        lpBaseName[0] = '\0';
Alexandre Julliard's avatar
Alexandre Julliard committed
278

279
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
280 281 282
}

/***********************************************************************
283
 *           GetDeviceDriverBaseNameW (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
284
 */
285 286
DWORD WINAPI GetDeviceDriverBaseNameW(LPVOID ImageBase, LPWSTR lpBaseName, 
                                      DWORD nSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
287
{
288
    FIXME("(%p, %p, %d): stub\n", ImageBase, lpBaseName, nSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
289

290 291
    if (lpBaseName && nSize)
        lpBaseName[0] = '\0';
Alexandre Julliard's avatar
Alexandre Julliard committed
292

293
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
294 295 296
}

/***********************************************************************
297
 *           GetDeviceDriverFileNameA (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
298
 */
299 300
DWORD WINAPI GetDeviceDriverFileNameA(LPVOID ImageBase, LPSTR lpFilename, 
                                      DWORD nSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
301
{
302
    FIXME("(%p, %p, %d): stub\n", ImageBase, lpFilename, nSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
303

304 305
    if (lpFilename && nSize)
        lpFilename[0] = '\0';
Alexandre Julliard's avatar
Alexandre Julliard committed
306

307
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
308 309 310
}

/***********************************************************************
311
 *           GetDeviceDriverFileNameW (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
312
 */
313 314
DWORD WINAPI GetDeviceDriverFileNameW(LPVOID ImageBase, LPWSTR lpFilename, 
                                      DWORD nSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
315
{
316
    FIXME("(%p, %p, %d): stub\n", ImageBase, lpFilename, nSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
317

318 319
    if (lpFilename && nSize)
        lpFilename[0] = '\0';
Alexandre Julliard's avatar
Alexandre Julliard committed
320

321
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
322 323 324
}

/***********************************************************************
325
 *           GetMappedFileNameA (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
326
 */
327 328
DWORD WINAPI GetMappedFileNameA(HANDLE hProcess, LPVOID lpv, LPSTR lpFilename, 
                                DWORD nSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
329
{
330
    FIXME("(%p, %p, %p, %d): stub\n", hProcess, lpv, lpFilename, nSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
331

332 333
    if (lpFilename && nSize)
        lpFilename[0] = '\0';
Alexandre Julliard's avatar
Alexandre Julliard committed
334

335
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
336 337 338
}

/***********************************************************************
339
 *           GetMappedFileNameW (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
340
 */
341 342
DWORD WINAPI GetMappedFileNameW(HANDLE hProcess, LPVOID lpv, LPWSTR lpFilename, 
                                DWORD nSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
343
{
344
    FIXME("(%p, %p, %p, %d): stub\n", hProcess, lpv, lpFilename, nSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
345

346 347
    if (lpFilename && nSize)
        lpFilename[0] = '\0';
Alexandre Julliard's avatar
Alexandre Julliard committed
348

349
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
350 351 352
}

/***********************************************************************
353
 *           GetModuleBaseNameA (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
354
 */
355 356
DWORD WINAPI GetModuleBaseNameA(HANDLE hProcess, HMODULE hModule, 
                                LPSTR lpBaseName, DWORD nSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
357
{
358 359
    WCHAR *lpBaseNameW;
    DWORD buflenW, ret = 0;
360

361 362
    if(!lpBaseName || !nSize) {
        SetLastError(ERROR_INVALID_PARAMETER);
363
        return 0;
364 365 366
    }
    lpBaseNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * nSize);
    buflenW = GetModuleBaseNameW(hProcess, hModule, lpBaseNameW, nSize);
367
    TRACE("%d, %s\n", buflenW, debugstr_w(lpBaseNameW));
368 369 370 371 372 373 374 375
    if (buflenW)
    {
        ret = WideCharToMultiByte(CP_ACP, 0, lpBaseNameW, buflenW,
                                  lpBaseName, nSize, NULL, NULL);
        if (ret < nSize) lpBaseName[ret] = 0;
    }
    HeapFree(GetProcessHeap(), 0, lpBaseNameW);
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
376 377 378
}

/***********************************************************************
379
 *           GetModuleBaseNameW (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
380
 */
381 382
DWORD WINAPI GetModuleBaseNameW(HANDLE hProcess, HMODULE hModule, 
                                LPWSTR lpBaseName, DWORD nSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
383
{
384
    LDR_MODULE LdrModule;
385

386
    if (!PSAPI_GetLdrModule(hProcess, hModule, &LdrModule))
387
        return 0;
388

389 390 391
    nSize = min(LdrModule.BaseDllName.Length / sizeof(WCHAR), nSize);
    if (!ReadProcessMemory(hProcess, LdrModule.BaseDllName.Buffer,
                           lpBaseName, nSize * sizeof(WCHAR), NULL))
392
        return 0;
393 394 395

    lpBaseName[nSize] = 0;
    return nSize;
Alexandre Julliard's avatar
Alexandre Julliard committed
396 397 398
}

/***********************************************************************
399
 *           GetModuleFileNameExA (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
400
 */
401 402
DWORD WINAPI GetModuleFileNameExA(HANDLE hProcess, HMODULE hModule, 
                                  LPSTR lpFileName, DWORD nSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
403
{
404
    WCHAR *ptr;
405

406
    TRACE("(hProcess=%p, hModule=%p, %p, %d)\n",
407 408 409
          hProcess, hModule, lpFileName, nSize);

    if (!lpFileName || !nSize) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
410

411
    if ( hProcess == GetCurrentProcess() )
412 413 414 415 416
    {
        DWORD len = GetModuleFileNameA( hModule, lpFileName, nSize );
        if (nSize) lpFileName[nSize - 1] = '\0';
        return len;
    }
417

418
    if (!(ptr = HeapAlloc(GetProcessHeap(), 0, nSize * sizeof(WCHAR)))) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
419

420
    if (!GetModuleFileNameExW(hProcess, hModule, ptr, nSize))
421
    {
422 423 424 425 426 427
        lpFileName[0] = '\0';
    }
    else
    {
        if (!WideCharToMultiByte( CP_ACP, 0, ptr, -1, lpFileName, nSize, NULL, NULL ))
            lpFileName[nSize - 1] = 0;
428 429
    }

430 431
    HeapFree(GetProcessHeap(), 0, ptr);
    return strlen(lpFileName);
Alexandre Julliard's avatar
Alexandre Julliard committed
432 433 434
}

/***********************************************************************
435
 *           GetModuleFileNameExW (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
436
 */
437 438
DWORD WINAPI GetModuleFileNameExW(HANDLE hProcess, HMODULE hModule, 
                                  LPWSTR lpFileName, DWORD nSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
439
{
440 441 442 443 444 445 446 447 448
    LDR_MODULE LdrModule;
    
    if(!PSAPI_GetLdrModule(hProcess, hModule, &LdrModule))
        return 0;
        
    nSize = min(LdrModule.FullDllName.Length / sizeof(WCHAR), nSize);
    if (!ReadProcessMemory(hProcess, LdrModule.FullDllName.Buffer,
                           lpFileName, nSize * sizeof(WCHAR), NULL))
        return 0;
449

450 451
    lpFileName[nSize] = 0;
    return nSize;
Alexandre Julliard's avatar
Alexandre Julliard committed
452 453 454
}

/***********************************************************************
455
 *           GetModuleInformation (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
456
 */
457 458
BOOL WINAPI GetModuleInformation(HANDLE hProcess, HMODULE hModule, 
                                 LPMODULEINFO lpmodinfo, DWORD cb)
Alexandre Julliard's avatar
Alexandre Julliard committed
459
{
460
    LDR_MODULE LdrModule;
461

462
    if (cb < sizeof(MODULEINFO)) 
463
    {
464 465
        SetLastError(ERROR_INSUFFICIENT_BUFFER);
        return FALSE;
466 467
    }

468 469 470 471 472 473
    if (!PSAPI_GetLdrModule(hProcess, hModule, &LdrModule))
        return FALSE;

    lpmodinfo->lpBaseOfDll = LdrModule.BaseAddress;
    lpmodinfo->SizeOfImage = LdrModule.SizeOfImage;
    lpmodinfo->EntryPoint  = LdrModule.EntryPoint;
474
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
475 476
}

477 478 479 480 481 482 483
/***********************************************************************
 *           GetPerformanceInfo (PSAPI.@)
 */
BOOL WINAPI GetPerformanceInfo( PPERFORMANCE_INFORMATION info, DWORD size )
{
    NTSTATUS status;

484
    TRACE( "(%p, %d)\n", info, size );
485

486
    status = NtQuerySystemInformation( SystemPerformanceInformation, info, size, NULL );
487 488 489 490 491 492 493 494 495 496 497 498 499 500

    if (status)
    {
        SetLastError( RtlNtStatusToDosError( status ) );
        return FALSE;
    }
    return TRUE;
}

/***********************************************************************
 *           GetProcessImageFileNameA (PSAPI.@)
 */
DWORD WINAPI GetProcessImageFileNameA( HANDLE process, LPSTR file, DWORD size )
{
501
    FIXME("(%p, %p, %d) stub\n", process, file, size );
502 503 504 505 506 507 508 509
    return 0;
}

/***********************************************************************
 *           GetProcessImageFileNameW (PSAPI.@)
 */
DWORD WINAPI GetProcessImageFileNameW( HANDLE process, LPWSTR file, DWORD size )
{
510
    FIXME("(%p, %p, %d) stub\n", process, file, size );
511 512 513
    return 0;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
514
/***********************************************************************
515
 *           GetProcessMemoryInfo (PSAPI.@)
516 517 518
 *
 * Retrieve memory usage information for a given process
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
519
 */
520 521
BOOL WINAPI GetProcessMemoryInfo(HANDLE hProcess, 
                                 PPROCESS_MEMORY_COUNTERS pmc, DWORD cb)
Alexandre Julliard's avatar
Alexandre Julliard committed
522
{
523 524 525
    NTSTATUS status;
    VM_COUNTERS vmc;

526 527 528 529 530
    if (cb < sizeof(PROCESS_MEMORY_COUNTERS))
    {
        SetLastError(ERROR_INSUFFICIENT_BUFFER);
        return FALSE;
    }
531

532 533
    status = NtQueryInformationProcess(hProcess, ProcessVmCounters, 
                                       &vmc, sizeof(vmc), NULL);
534 535 536

    if (status)
    {
537
        SetLastError(RtlNtStatusToDosError(status));
538 539 540
        return FALSE;
    }

541 542 543 544 545 546 547 548 549 550
    pmc->cb = sizeof(PROCESS_MEMORY_COUNTERS);
    pmc->PageFaultCount = vmc.PageFaultCount;
    pmc->PeakWorkingSetSize = vmc.PeakWorkingSetSize;
    pmc->WorkingSetSize = vmc.WorkingSetSize;
    pmc->QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage;
    pmc->QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage;
    pmc->QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage;
    pmc->QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage;
    pmc->PagefileUsage = vmc.PagefileUsage;
    pmc->PeakPagefileUsage = vmc.PeakPagefileUsage;
Alexandre Julliard's avatar
Alexandre Julliard committed
551

552
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
553 554 555
}

/***********************************************************************
556
 *           GetWsChanges (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
557
 */
558
BOOL WINAPI GetWsChanges( HANDLE process, PPSAPI_WS_WATCH_INFORMATION watchinfo, DWORD size )
Alexandre Julliard's avatar
Alexandre Julliard committed
559
{
560 561
    NTSTATUS status;

562
    TRACE( "(%p, %p, %d)\n", process, watchinfo, size );
Alexandre Julliard's avatar
Alexandre Julliard committed
563

564
    status = NtQueryInformationProcess( process, ProcessWorkingSetWatch, watchinfo, size, NULL );
Alexandre Julliard's avatar
Alexandre Julliard committed
565

566 567 568 569 570
    if (status)
    {
        SetLastError( RtlNtStatusToDosError( status ) );
        return FALSE;
    }
571
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
572 573 574
}

/***********************************************************************
575
 *           InitializeProcessForWsWatch (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
576
 */
577
BOOL WINAPI InitializeProcessForWsWatch(HANDLE hProcess)
Alexandre Julliard's avatar
Alexandre Julliard committed
578
{
579
    FIXME("(hProcess=%p): stub\n", hProcess);
Alexandre Julliard's avatar
Alexandre Julliard committed
580

581
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
582 583 584
}

/***********************************************************************
Kevin Koltzau's avatar
Kevin Koltzau committed
585
 *           QueryWorkingSet (PSAPI.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
586
 */
587
BOOL WINAPI QueryWorkingSet( HANDLE process, LPVOID buffer, DWORD size )
Alexandre Julliard's avatar
Alexandre Julliard committed
588
{
589 590
    NTSTATUS status;

591
    TRACE( "(%p, %p, %d)\n", process, buffer, size );
Alexandre Julliard's avatar
Alexandre Julliard committed
592

593
    status = NtQueryVirtualMemory( process, NULL, MemoryWorkingSetList, buffer, size, NULL );
Alexandre Julliard's avatar
Alexandre Julliard committed
594

595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
    if (status)
    {
        SetLastError( RtlNtStatusToDosError( status ) );
        return FALSE;
    }
    return TRUE;
}

/***********************************************************************
 *           QueryWorkingSetEx (PSAPI.@)
 */
BOOL WINAPI QueryWorkingSetEx( HANDLE process, LPVOID buffer, DWORD size )
{
    NTSTATUS status;

610
    TRACE( "(%p, %p, %d)\n", process, buffer, size );
611 612 613 614 615 616 617 618

    status = NtQueryVirtualMemory( process, NULL, MemoryWorkingSetList, buffer,  size, NULL );

    if (status)
    {
        SetLastError( RtlNtStatusToDosError( status ) );
        return FALSE;
    }
619
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
620
}