Skip to content
ufrisk edited this page Dec 20, 2021 · 38 revisions

Native C/C++ API

All functionality in the Memory Process File System is exported in a C/C++ API for use by developers. The header file is named: vmmdll.h which use vmm.dll / vmm.lib (Windows) or vmm.so (Linux).

It may also be interesting to look into the more basic API related to read/write physical memory exported by the LeechCore library.

The complete documentation is found in vmmdll.h. This wiki entry contains an overview of the C/C++ API.

Linux is supported on x64 and ARM64 in addition to Windows x64. Wide-Char *W versions of API functions are only supported on Windows while UTF-8 *U versions of API functions are supported on both Linux and Windows.

Example:

An example file containing a lot of use cases are found in the file vmmdll_example.c in the vmmdll_example project in the visual studio solution.

Functionality:

Initialization API

After vmm.dll is loaded it has to be initialized.

Depending on whether it should be initialized from file, fpga or something else different VMMDLL_Initialize should be called with a different list of string parameters in the first argument. The arguments are the same as given as options when starting The Memory Process File System except for argv[0] which is recommended to set to blank.

BOOL VMMDLL_Initialize(_In_ DWORD argc, _In_ LPSTR argv[]);
BOOL VMMDLL_InitializeEx(_In_ DWORD argc, _In_ LPSTR argv[], _Out_opt_ PPLC_CONFIG_ERRORINFO ppLcErrorInfo);
BOOL VMMDLL_InitializePlugins();
BOOL VMMDLL_Close();
VOID VMMDLL_MemFree(_Frees_ptr_opt_ PVOID pvMem);

Configuration API

BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);

File System API

The MemProcFS.exe file is just a wrapper around the API below:

BOOL VMMDLL_VfsListU(
    _In_ LPSTR  uszPath,
    _Inout_ PVMMDLL_VFS_FILELIST2 pFileList
);

BOOL VMMDLL_VfsListW(
    _In_ LPWSTR wszPath,
    _Inout_ PVMMDLL_VFS_FILELIST2 pFileList
);

NTSTATUS VMMDLL_VfsReadU(
    _In_ LPSTR  uszFileName,
    _Out_writes_to_(cb, *pcbRead) PBYTE pb,
    _In_ DWORD cb,
    _Out_ PDWORD pcbRead,
    _In_ ULONG64 cbOffset
);

NTSTATUS VMMDLL_VfsReadW(
    _In_ LPWSTR wszFileName,
    _Out_writes_to_(cb, *pcbRead) PBYTE pb,
    _In_ DWORD cb,
    _Out_ PDWORD pcbRead,
    _In_ ULONG64 cbOffset
);

NTSTATUS VMMDLL_VfsWriteU(
    _In_ LPSTR  uszFileName,
    _In_reads_(cb) PBYTE pb,
    _In_ DWORD cb,
    _Out_ PDWORD pcbWrite,
    _In_ ULONG64 cbOffset
);

NTSTATUS VMMDLL_VfsWriteW(
    _In_ LPWSTR wszFileName,
    _In_reads_(cb) PBYTE pb,
    _In_ DWORD cb,
    _Out_ PDWORD pcbWrite,
    _In_ ULONG64 cbOffset
);

NTSTATUS VMMDLL_UtilVfsReadFile_FromPBYTE(
    _In_ PBYTE pbFile,
    _In_ ULONG64 cbFile,
    _Out_writes_to_(cb, *pcbRead) PBYTE pb,
    _In_ DWORD cb,
    _Out_ PDWORD pcbRead,
    _In_ ULONG64 cbOffset
);

NTSTATUS VMMDLL_UtilVfsReadFile_FromQWORD(
    _In_ ULONG64 qwValue,
    _Out_writes_to_(cb, *pcbRead) PBYTE pb,
    _In_ DWORD cb,
    _Out_ PDWORD pcbRead,
    _In_ ULONG64 cbOffset,
    _In_ BOOL fPrefix
);

NTSTATUS VMMDLL_UtilVfsReadFile_FromDWORD(
    _In_ DWORD dwValue,
    _Out_writes_to_(cb, *pcbRead) PBYTE pb,
    _In_ DWORD cb,
    _Out_ PDWORD pcbRead,
    _In_ ULONG64 cbOffset,
    _In_ BOOL fPrefix
);

NTSTATUS VMMDLL_UtilVfsReadFile_FromBOOL(
    _In_ BOOL fValue,
    _Out_writes_to_(cb, *pcbRead) PBYTE pb,
    _In_ DWORD cb,
    _Out_ PDWORD pcbRead,
    _In_ ULONG64 cbOffset
);

NTSTATUS VMMDLL_UtilVfsWriteFile_BOOL(
    _Inout_ PBOOL pfTarget,
    _In_reads_(cb) PBYTE pb,
    _In_ DWORD cb,
    _Out_ PDWORD pcbWrite,
    _In_ ULONG64 cbOffset
);

NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(
    _Inout_ PDWORD pdwTarget,
    _In_reads_(cb) PBYTE pb,
    _In_ DWORD cb,
    _Out_ PDWORD pcbWrite,
    _In_ ULONG64 cbOffset,
    _In_ DWORD dwMinAllow
);

Memory Read/Write API:

Read and write both physical and virtual memory via the functions listed below. In most instances it's possible to specify (DWORD)-1 instead of the process pid to read physical memory instead of process virtual memory.

DWORD VMMDLL_MemReadScatter(
    _In_ DWORD dwPID,
    _Inout_ PPMEM_SCATTER ppMEMs,
    _In_ DWORD cpMEMs,
    _In_ DWORD flags
);

BOOL VMMDLL_MemReadPage(
    _In_ DWORD dwPID,
    _In_ ULONG64 qwA,
    _Inout_bytecount_(4096) PBYTE pbPage
);

BOOL VMMDLL_MemRead(
    _In_ DWORD dwPID,
    _In_ ULONG64 qwA,
    _Out_writes_(cb) PBYTE pb,
    _In_ DWORD cb
);

BOOL VMMDLL_MemReadEx(
    _In_ DWORD dwPID,
    _In_ ULONG64 qwA,
    _Out_writes_(cb) PBYTE pb,
    _In_ DWORD cb,
    _Out_opt_ PDWORD pcbReadOpt,
    _In_ ULONG64 flags
);

BOOL VMMDLL_MemPrefetchPages(
    _In_ DWORD dwPID,
    _In_reads_(cPrefetchAddresses) PULONG64 pPrefetchAddresses,
    _In_ DWORD cPrefetchAddresses
);

BOOL VMMDLL_MemWrite(
    _In_ DWORD dwPID,
    _In_ ULONG64 qwA,
    _In_reads_(cb) PBYTE pb,
    _In_ DWORD cb
);

BOOL VMMDLL_MemVirt2Phys(
    _In_ DWORD dwPID,
    _In_ ULONG64 qwVA,
    _Out_ PULONG64 pqwPA
);

Memory Read/Write API:

Read physical and virtual memory in an efficient way using the Scatter API using the functions listed below. In most instances it's possible to specify (DWORD)-1 instead of the process pid to read physical memory instead of process virtual memory.

Flow is as follows:

  1. Call VMMDLL_Scatter_Initialize to initialize handle.
  2. Populate memory ranges with multiple calls to VMMDLL_Scatter_Prepare and/or VMMDLL_Scatter_PrepareEx functions. The memory buffer given to VMMDLL_Scatter_PrepareEx will be populated with contents in step (3).
  3. Retrieve the memory by calling VMMDLL_Scatter_ExecuteRead function.
  4. If VMMDLL_Scatter_Prepare was used (i.e. not VMMDLL_Scatter_PrepareEx) then retrieve the memory read in (3).
  5. Clear the handle for reuse by calling VMMDLL_Scatter_Clear alternatively close the handle to free resources with VMMDLL_Scatter_CloseHandle.
VMMDLL_SCATTER_HANDLE VMMDLL_Scatter_Initialize(
    _In_ DWORD dwPID,
    _In_ DWORD flags
);

BOOL VMMDLL_Scatter_Prepare(
    _In_ VMMDLL_SCATTER_HANDLE hS,
    _In_ QWORD va,
    _In_ DWORD cb
);

BOOL VMMDLL_Scatter_PrepareEx(
    _In_ VMMDLL_SCATTER_HANDLE hS,
    _In_ QWORD va,
    _In_ DWORD cb,
    _Out_writes_opt_(cb) PBYTE pb,
    _Out_opt_ PDWORD pcbRead
);

BOOL VMMDLL_Scatter_ExecuteRead(
_In_ VMMDLL_SCATTER_HANDLE hS
);

BOOL VMMDLL_Scatter_Read(
    _In_ VMMDLL_SCATTER_HANDLE hS,
    _In_ QWORD va,
    _In_ DWORD cb,
    _Out_writes_opt_(cb) PBYTE pb,
    _Out_opt_ PDWORD pcbRead
);

BOOL VMMDLL_Scatter_Clear(
    _In_ VMMDLL_SCATTER_HANDLE hS,
    _In_ DWORD dwPID,
    _In_ DWORD flags
);

VOID VMMDLL_Scatter_CloseHandle(
    _In_opt_ _Post_ptr_invalid_ VMMDLL_SCATTER_HANDLE hS
);

Process API:

Functionality related to processes running on the target system are exposed in via the functions below:

BOOL VMMDLL_PidGetFromName(
    _In_ LPSTR szProcName,
    _Out_ PDWORD pdwPID
);

BOOL VMMDLL_PidList(
    _Out_writes_opt_(*pcPIDs) PDWORD pPIDs,
    _Inout_ PULONG64 pcPIDs
);


BOOL VMMDLL_PidGetFromName(
    _In_ LPSTR szProcName,
    _Out_ PDWORD pdwPID
);

BOOL VMMDLL_PidList(
    _Out_writes_opt_(*pcPIDs) PDWORD pPIDs,
    _Inout_ PULONG64 pcPIDs
);

BOOL VMMDLL_ProcessGetInformation(
    _In_ DWORD dwPID,
    _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation,
    _In_ PSIZE_T pcbProcessInformation
);

LPSTR VMMDLL_ProcessGetInformationString(
    _In_ DWORD dwPID,
    _In_ DWORD fOptionString
);

ULONG64 VMMDLL_ProcessGetProcAddressU(
    _In_ DWORD dwPID,
    _In_ LPSTR  uszModuleName,
    _In_ LPSTR szFunctionName
);

ULONG64 VMMDLL_ProcessGetProcAddressW(
    _In_ DWORD dwPID,
    _In_ LPWSTR wszModuleName,
    _In_ LPSTR szFunctionName
);

ULONG64 VMMDLL_ProcessGetModuleBaseU(
    _In_ DWORD dwPID,
    _In_ LPSTR  uszModuleName
);

ULONG64 VMMDLL_ProcessGetModuleBaseW(
    _In_ DWORD dwPID,
    _In_ LPWSTR wszModuleName
);

BOOL VMMDLL_Map_GetPteU(
    _In_ DWORD dwPID,
    _Out_writes_bytes_opt_(*pcbPteMap) PVMMDLL_MAP_PTE pPteMap,
    _Inout_ PDWORD pcbPteMap,
    _In_ BOOL fIdentifyModules
);

BOOL VMMDLL_Map_GetPteW(
    _In_ DWORD dwPID,
    _Out_writes_bytes_opt_(*pcbPteMap) PVMMDLL_MAP_PTE pPteMap,
    _Inout_ PDWORD pcbPteMap,
    _In_ BOOL fIdentifyModules
);

BOOL VMMDLL_Map_GetVadU(
    _In_ DWORD dwPID,
    _Out_writes_bytes_opt_(*pcbVadMap) PVMMDLL_MAP_VAD pVadMap,
    _Inout_ PDWORD pcbVadMap,
    _In_ BOOL fIdentifyModules
);

BOOL VMMDLL_Map_GetVadW(
    _In_ DWORD dwPID,
    _Out_writes_bytes_opt_(*pcbVadMap) PVMMDLL_MAP_VAD pVadMap,
    _Inout_ PDWORD pcbVadMap,
    _In_ BOOL fIdentifyModules
);

BOOL VMMDLL_Map_GetVadEx(
    _In_ DWORD dwPID,
    _Out_writes_bytes_opt_(*pcbVadExMap) PVMMDLL_MAP_VADEX pVadExMap,
    _Inout_ PDWORD pcbVadExMap,
    _In_ DWORD oPage,
    _In_ DWORD cPage
);

BOOL VMMDLL_Map_GetModuleU(
    _In_ DWORD dwPID,
    _Out_writes_bytes_opt_(*pcbModuleMap) PVMMDLL_MAP_MODULE pModuleMap,
    _Inout_ PDWORD pcbModuleMap
);

BOOL VMMDLL_Map_GetModuleW(
    _In_ DWORD dwPID,
    _Out_writes_bytes_opt_(*pcbModuleMap) PVMMDLL_MAP_MODULE pModuleMap,
    _Inout_ PDWORD pcbModuleMap
);

BOOL VMMDLL_Map_GetModuleFromNameU(
    _In_ DWORD dwPID,
    _In_ LPSTR  uszModuleName,
    _Out_writes_bytes_opt_(*pcbModuleMapEntry) PVMMDLL_MAP_MODULEENTRY pModuleMapEntry,
    _Inout_opt_ PDWORD pcbModuleMapEntry
);

BOOL VMMDLL_Map_GetModuleFromNameW(
    _In_ DWORD dwPID,
    _In_ LPWSTR wszModuleName,
    _Out_writes_bytes_opt_(*pcbModuleMapEntry) PVMMDLL_MAP_MODULEENTRY pModuleMapEntry,
    _Inout_opt_ PDWORD pcbModuleMapEntry
);

BOOL VMMDLL_Map_GetUnloadedModuleU(
    _In_ DWORD dwPID,
    _Out_writes_bytes_opt_(*pcbUnloadedModuleMap) PVMMDLL_MAP_UNLOADEDMODULE pUnloadedModuleMap,
    _Inout_ PDWORD pcbUnloadedModuleMap
);

BOOL VMMDLL_Map_GetUnloadedModuleW(
    _In_ DWORD dwPID,
    _Out_writes_bytes_opt_(*pcbUnloadedModuleMap) PVMMDLL_MAP_UNLOADEDMODULE pUnloadedModuleMap,
    _Inout_ PDWORD pcbUnloadedModuleMap
);

BOOL VMMDLL_Map_GetEATU(
    _In_ DWORD dwPID,
    _In_ LPSTR  uszModuleName,
    _Out_writes_bytes_opt_(*pcbEatMap) PVMMDLL_MAP_EAT pEatMap,
    _Inout_ PDWORD pcbEatMap
);

BOOL VMMDLL_Map_GetEATW(
    _In_ DWORD dwPID,
    _In_ LPWSTR wszModuleName,
    _Out_writes_bytes_opt_(*pcbEatMap) PVMMDLL_MAP_EAT pEatMap,
    _Inout_ PDWORD pcbEatMap
);

BOOL VMMDLL_Map_GetIATU(
    _In_ DWORD dwPID,
    _In_ LPSTR uszModuleName,
    _Out_writes_bytes_opt_(*pcbIatMap) PVMMDLL_MAP_IAT pIatMap,
    _Inout_ PDWORD pcbIatMap
);

BOOL VMMDLL_Map_GetIATW(
    _In_ DWORD dwPID,
    _In_ LPWSTR wszModuleName,
    _Out_writes_bytes_opt_(*pcbIatMap) PVMMDLL_MAP_IAT pIatMap,
    _Inout_ PDWORD pcbIatMap
);

BOOL VMMDLL_Map_GetHeap(
    _In_ DWORD dwPID,
    _Out_writes_bytes_opt_(*pcbHeapMap) PVMMDLL_MAP_HEAP pHeapMap,
    _Inout_ PDWORD pcbHeapMap
);

BOOL VMMDLL_Map_GetThread(
    _In_ DWORD dwPID,
    _Out_writes_bytes_opt_(*pcbThreadMap) PVMMDLL_MAP_THREAD pThreadMap,
    _Inout_ PDWORD pcbThreadMap
);

BOOL VMMDLL_Map_GetHandleU(
    _In_ DWORD dwPID,
    _Out_writes_bytes_opt_(*pcbHandleMap) PVMMDLL_MAP_HANDLE pHandleMap,
    _Inout_ PDWORD pcbHandleMap
);

BOOL VMMDLL_Map_GetHandleW(
    _In_ DWORD dwPID,
    _Out_writes_bytes_opt_(*pcbHandleMap) PVMMDLL_MAP_HANDLE pHandleMap,
    _Inout_ PDWORD pcbHandleMap
);

BOOL VMMDLL_ProcessGetDirectoriesU(
    _In_ DWORD dwPID,
    _In_ LPSTR  uszModule,
    _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData,
    _In_ DWORD cData,
    _Out_ PDWORD pcData
);

BOOL VMMDLL_ProcessGetDirectoriesW(
    _In_ DWORD dwPID,
    _In_ LPWSTR wszModule,
    _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData,
    _In_ DWORD cData,
    _Out_ PDWORD pcData
);

BOOL VMMDLL_ProcessGetSectionsU(
    _In_ DWORD dwPID,
    _In_ LPSTR  uszModule,
    _Out_opt_ PIMAGE_SECTION_HEADER pData,
    _In_ DWORD cData,
    _Out_ PDWORD pcData
);

BOOL VMMDLL_ProcessGetSectionsW(
    _In_ DWORD dwPID,
    _In_ LPWSTR wszModule,
    _Out_opt_ PIMAGE_SECTION_HEADER pData,
    _In_ DWORD cData,
    _Out_ PDWORD pcData
);

BOOL VMMDLL_WinGetThunkInfoIATU(
    _In_ DWORD dwPID,
    _In_ LPSTR  uszModuleName,
    _In_ LPSTR szImportModuleName,
    _In_ LPSTR szImportFunctionName,
    _Out_ PVMMDLL_WIN_THUNKINFO_IAT pThunkInfoIAT
);

BOOL VMMDLL_WinGetThunkInfoIATW(
    _In_ DWORD dwPID,
    _In_ LPWSTR wszModuleName,
    _In_ LPSTR szImportModuleName,
    _In_ LPSTR szImportFunctionName,
    _Out_ PVMMDLL_WIN_THUNKINFO_IAT pThunkInfoIAT
);

Windows Registry API:

The registry API supports enumerating registry hives and the reading/writing of their memory space. Reading and writing individual registry keys are not supported at the moment.

BOOL VMMDLL_WinReg_HiveList(
    _Out_writes_(cHives) PVMMDLL_REGISTRY_HIVE_INFORMATION pHives,
    _In_ DWORD cHives,
    _Out_ PDWORD pcHives
);

BOOL VMMDLL_WinReg_HiveReadEx(
    _In_ ULONG64 vaCMHive,
    _In_ DWORD ra,
    _Out_ PBYTE pb,
    _In_ DWORD cb,
    _Out_opt_ PDWORD pcbReadOpt,
    _In_ ULONG64 flags
);

BOOL VMMDLL_WinReg_HiveWrite(
    _In_ ULONG64 vaCMHive,
    _In_ DWORD ra,
    _In_ PBYTE pb,
    _In_ DWORD cb
);

BOOL VMMDLL_WinReg_EnumKeyExU(
    _In_ LPSTR uszFullPathKey,
    _In_ DWORD dwIndex,
    _Out_writes_opt_(*lpcchName) LPSTR lpName,
    _Inout_ LPDWORD lpcchName,
    _Out_opt_ PFILETIME lpftLastWriteTime
);

BOOL VMMDLL_WinReg_EnumKeyExW(
    _In_ LPWSTR wszFullPathKey,
    _In_ DWORD dwIndex,
    _Out_writes_opt_(*lpcchName) LPWSTR lpName,
    _Inout_ LPDWORD lpcchName,
    _Out_opt_ PFILETIME lpftLastWriteTime
);

BOOL VMMDLL_WinReg_EnumValueU(
    _In_ LPSTR uszFullPathKey,
    _In_ DWORD dwIndex,
    _Out_writes_opt_(*lpcchValueName) LPSTR lpValueName,
    _Inout_ LPDWORD lpcchValueName,
    _Out_opt_ LPDWORD lpType,
    _Out_writes_opt_(*lpcbData) LPBYTE lpData,
    _Inout_opt_ LPDWORD lpcbData
);


BOOL VMMDLL_WinReg_EnumValueW(
    _In_ LPWSTR wszFullPathKey,
    _In_ DWORD dwIndex,
    _Out_writes_opt_(*lpcchValueName) LPWSTR lpValueName,
    _Inout_ LPDWORD lpcchValueName,
    _Out_opt_ LPDWORD lpType,
    _Out_writes_opt_(*lpcbData) LPBYTE lpData,
    _Inout_opt_ LPDWORD lpcbData
);

BOOL VMMDLL_WinReg_QueryValueExU(
    _In_ LPSTR uszFullPathKeyValue,
    _Out_opt_ LPDWORD lpType,
    _Out_writes_opt_(*lpcbData) LPBYTE lpData,
    _When_(lpData == NULL, _Out_opt_) _When_(lpData != NULL, _Inout_opt_) LPDWORD lpcbData
);

BOOL VMMDLL_WinReg_QueryValueExW(
    _In_ LPWSTR wszFullPathKeyValue,
    _Out_opt_ LPDWORD lpType,
    _Out_writes_opt_(*lpcbData) LPBYTE lpData,
    _When_(lpData == NULL, _Out_opt_) _When_(lpData != NULL, _Inout_opt_) LPDWORD lpcbData
);

Windows specific symbol debugging API:

Limited functionality for debugging symbols retrieved from the Microsoft symbol server.

BOOL VMMDLL_PdbLoad(
    _In_ DWORD dwPID,
    _In_ ULONG64 vaModuleBase,
    _Out_writes_(MAX_PATH) LPSTR szModuleName
);

BOOL VMMDLL_PdbSymbolName(
    _In_ LPSTR szModule,
    _In_ QWORD cbSymbolAddressOrOffset,
    _Out_writes_(MAX_PATH) LPSTR szSymbolName,
    _Out_opt_ PDWORD pdwSymbolDisplacement
);

BOOL VMMDLL_PdbSymbolAddress(
    _In_ LPSTR szModule,
    _In_ LPSTR szSymbolName,
    _Out_ PULONG64 pvaSymbolAddress
);

BOOL VMMDLL_PdbTypeSize(
    _In_ LPSTR szModule,
    _In_ LPSTR szTypeName,    
    _Out_ PDWORD pcbTypeSize
);

BOOL VMMDLL_PdbTypeChildOffset(
    _In_ LPSTR szModule,
    _In_ LPSTR szTypeName,
    _In_ LPWSTR wszTypeChildName,    
    _Out_ PDWORD pcbTypeChildOffset
);

Windows specific API:

BOOL VMMDLL_Map_GetPfn(
    _In_ DWORD pPfns[],
    _In_ DWORD cPfns,
    _Out_writes_bytes_opt_(*pcbPfnMap) PVMMDLL_MAP_PFN pPfnMap,
    _Inout_ PDWORD pcbPfnMap
);

BOOL VMMDLL_Map_GetPool(
    _Out_writes_bytes_opt_(*pcbPoolMap) PVMMDLL_MAP_POOL pPoolMap,
    _Inout_ PDWORD pcbPoolMap
);

BOOL VMMDLL_Map_GetPhysMem(
    _Out_writes_bytes_opt_(*pcbPhysMemMap) PVMMDLL_MAP_PHYSMEM pPhysMemMap,
    _Inout_ PDWORD pcbPhysMemMap
);

BOOL VMMDLL_Map_GetNetU(
    _Out_writes_bytes_opt_(*pcbNetMap) PVMMDLL_MAP_NET pNetMap,
    _Inout_ PDWORD pcbNetMap
);

BOOL VMMDLL_Map_GetNetW(
    _Out_writes_bytes_opt_(*pcbNetMap) PVMMDLL_MAP_NET pNetMap,
    _Inout_ PDWORD pcbNetMap
);

BOOL VMMDLL_Map_GetUsersU(
    _Out_writes_bytes_opt_(*pcbUserMap) PVMMDLL_MAP_USER pUserMap,
    _Inout_ PDWORD pcbUserMap
);

BOOL VMMDLL_Map_GetUsersW(
    _Out_writes_bytes_opt_(*pcbUserMap) PVMMDLL_MAP_USER pUserMap,
    _Inout_ PDWORD pcbUserMap
);

BOOL VMMDLL_Map_GetServicesU(
    _Out_writes_bytes_opt_(*pcbServiceMap) PVMMDLL_MAP_SERVICE pServiceMap,
    _Inout_ PDWORD pcbServiceMap
);

BOOL VMMDLL_Map_GetServicesW(
    _Out_writes_bytes_opt_(*pcbServiceMap) PVMMDLL_MAP_SERVICE pServiceMap,
    _Inout_ PDWORD pcbServiceMap
);

Utility API:

BOOL VMMDLL_UtilFillHexAscii(
    _In_reads_opt_(cb) PBYTE pb,
    _In_ DWORD cb,
    _In_ DWORD cbInitialOffset,
    _Out_writes_opt_(*pcsz) LPSTR sz,
    _Inout_ PDWORD pcsz
);
Clone this wiki locally