├── VERSION ├── VmBusPipeTest ├── CMakeLists.txt └── Main.c ├── VmBusPipe ├── CMakeLists.txt ├── VmBusPipe.c ├── VmBusPipeHost.c ├── VmBusPipeGuest.c └── VmBusPipe.h ├── .gitignore ├── VmBusPipeStub ├── VmBusPipeStub.h ├── vmbuspipe.def ├── vmbuspiper.def ├── CMakeLists.txt ├── Helpers.h ├── Helpers.cpp └── VmBusPipeStub.cpp ├── Logs ├── VmBusPipeStub031C.txt ├── VmBusPipeStub0130.txt └── VmBusPipeStub0594.txt ├── LICENSE ├── CMakeLists.txt ├── cmake ├── MSVCRuntime.cmake └── WindowsRC.cmake └── README.md /VERSION: -------------------------------------------------------------------------------- 1 | 1.0.0 2 | -------------------------------------------------------------------------------- /VmBusPipeTest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(VMBusPipeTest main.c) 3 | 4 | target_link_libraries(VMBusPipeTest VMBusPipeCore) 5 | -------------------------------------------------------------------------------- /VmBusPipe/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(VMBusPipeCore STATIC 3 | VmBusPipe.c 4 | VmBusPipe.h 5 | VmBusPipeGuest.c 6 | VmBusPipeHost.c) 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Debug/ 2 | Release/ 3 | .vs/ 4 | build/ 5 | 6 | *.sdf 7 | *.suo 8 | *.user 9 | *.filters 10 | *.opensdf 11 | *.vcxproj 12 | *.sln 13 | 14 | -------------------------------------------------------------------------------- /VmBusPipeStub/VmBusPipeStub.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef VMBUS_PIPE_STUB_H 3 | #define VMBUS_PIPE_STUB_H 4 | 5 | #include "VmBusPipe.h" 6 | 7 | //#define VMBUS_PIPER_STUB 1 8 | 9 | #endif /* VMBUS_PIPE_STUB_H */ -------------------------------------------------------------------------------- /VmBusPipeStub/vmbuspipe.def: -------------------------------------------------------------------------------- 1 | LIBRARY "vmbuspipe" 2 | EXPORTS 3 | VmbusPipeClientEnumeratePipes 4 | VmbusPipeClientOpenChannel 5 | VmbusPipeClientReadyForChannelNotification 6 | VmbusPipeClientRegisterChannelNotification 7 | VmbusPipeClientUnregisterChannelNotification 8 | VmbusPipeClientWaitChannel 9 | VmbusPipeServerConnectPipe 10 | VmbusPipeServerOfferChannel 11 | -------------------------------------------------------------------------------- /VmBusPipeStub/vmbuspiper.def: -------------------------------------------------------------------------------- 1 | LIBRARY "vmbuspiper" 2 | EXPORTS 3 | VmbusPipeClientEnumeratePipes 4 | VmbusPipeClientOpenChannel 5 | VmbusPipeClientReadyForChannelNotification 6 | VmbusPipeClientRegisterChannelNotification 7 | VmbusPipeClientUnregisterChannelNotification 8 | VmbusPipeClientWaitChannel 9 | VmbusPipeServerConnectPipe 10 | VmbusPipeServerOfferChannel 11 | -------------------------------------------------------------------------------- /VmBusPipeStub/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(vmbuspipe SHARED 3 | Helpers.cpp 4 | Helpers.h 5 | VMBusPipeStub.cpp 6 | VMBusPipeStub.h 7 | vmbuspipe.def) 8 | 9 | set_target_properties(vmbuspipe PROPERTIES OUTPUT_NAME "vmbuspipe") 10 | target_link_libraries(vmbuspipe VMBusPipeCore) 11 | 12 | add_library(vmbuspiper SHARED 13 | Helpers.cpp 14 | Helpers.h 15 | VMBusPipeStub.cpp 16 | VMBusPipeStub.h 17 | vmbuspiper.def) 18 | 19 | target_compile_definitions(vmbuspiper PRIVATE VMBUS_PIPER_STUB=1) 20 | set_target_properties(vmbuspiper PROPERTIES OUTPUT_NAME "vmbuspiper") 21 | target_link_libraries(vmbuspiper VMBusPipeCore) 22 | -------------------------------------------------------------------------------- /VmBusPipe/VmBusPipe.c: -------------------------------------------------------------------------------- 1 | 2 | #include "VmBusPipe.h" 3 | 4 | DWORD VmbusPipeOfferChannelInternal(LPVOID lpInBuffer, DWORD dwIoControlCode, PHANDLE phHandle) 5 | { 6 | HANDLE handle; 7 | BOOL bSuccess; 8 | DWORD error = 0; 9 | DWORD BytesReturned; 10 | 11 | handle = CreateFileW(L"\\\\.\\VMBus", 0x1F01FFu, 3, 0, 3, dwIoControlCode | 0x100000, 0); 12 | 13 | bSuccess = DeviceIoControl(handle, 0x3EC03Cu, lpInBuffer, 176, 0, 0, &BytesReturned, 0); 14 | 15 | if (bSuccess && (handle != INVALID_HANDLE_VALUE)) 16 | { 17 | *phHandle = handle; 18 | } 19 | else 20 | { 21 | error = GetLastError(); 22 | } 23 | 24 | if (error && (handle != INVALID_HANDLE_VALUE)) 25 | CloseHandle(handle); 26 | 27 | return error; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /Logs/VmBusPipeStub031C.txt: -------------------------------------------------------------------------------- 1 | 2014/01/27 14:16:53: DllMain: C:\Windows\system32\svchost.exe, fdwReason: 1 2 | 2014/01/27 14:16:54: VmbusPipeClientEnumeratePipe: pContext: 000000BC6B01F960 3 | 2014/01/27 14:16:54: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 4 | 2014/01/27 14:16:54: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{276aacf4-ac15-426c-98dd-7521ad3f01fe}#{f5bee29c-1741-4aad-a4c2-8fdedb46dcc2}#{276aacf4-ac15-426c-98dd-7521ad3f01fe} 5 | 2014/01/27 14:16:54: pGuid: {f5bee29c-1741-4aad-a4c2-8fdedb46dcc2} 6 | 2014/01/27 14:16:54: VmbusPipeClientEnumeratePipes: ClassGuid: {276aacf4-ac15-426c-98dd-7521ad3f01fe} pContext: 000000BC69427B60 pfn: 00007FFF5D68CDBC bSuccess: 1 7 | -------------------------------------------------------------------------------- /VmBusPipeStub/Helpers.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LOG_FILE_H 3 | #define LOG_FILE_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | int ConvertToUnicode(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, 13 | int cbMultiByte, LPWSTR* lpWideCharStr, int cchWideChar); 14 | 15 | int ConvertFromUnicode(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, 16 | LPSTR* lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar); 17 | 18 | char* BinToHexString(BYTE* data, int length); 19 | 20 | class CLogFile 21 | { 22 | public: 23 | CLogFile(); 24 | ~CLogFile(); 25 | 26 | void OpenFile(const char* strFile, bool bAppend = TRUE, long lTruncate = 16384); 27 | void CloseFile(); 28 | 29 | void Write(const char* pszFormat, ...); 30 | 31 | private: 32 | void CreateDirectories(const char* filename); 33 | 34 | bool m_enabled; 35 | FILE* m_pLogFile; 36 | long m_lTruncate; 37 | CRITICAL_SECTION m_cs; 38 | char m_filename[MAX_PATH]; 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /VmBusPipe/VmBusPipeHost.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "VmBusPipe.h" 6 | 7 | VmBusPipeHost* VmBusPipeHostInit(const char* filename) 8 | { 9 | HMODULE hModule; 10 | VmBusPipeHost* host; 11 | 12 | hModule = LoadLibraryA(filename ? filename : "vmbuspiper.dll"); 13 | 14 | if (!hModule) 15 | { 16 | printf("LoadLibrary failure: %d\n", (int) GetLastError()); 17 | return NULL; 18 | } 19 | 20 | host = (VmBusPipeHost*) malloc(sizeof(VmBusPipeHost)); 21 | 22 | if (!host) 23 | return NULL; 24 | 25 | ZeroMemory(host, sizeof(VmBusPipeHost)); 26 | 27 | host->VmBusPipeHostModule = hModule; 28 | 29 | host->VmbusPipeClientEnumeratePipes = (fnVmbusPipeClientEnumeratePipes) GetProcAddress(hModule, "VmbusPipeClientEnumeratePipes"); 30 | host->VmbusPipeClientOpenChannel = (fnVmbusPipeClientOpenChannel) GetProcAddress(hModule, "VmbusPipeClientOpenChannel"); 31 | host->VmbusPipeClientWaitChannel = (fnVmbusPipeClientWaitChannel) GetProcAddress(hModule, "VmbusPipeClientWaitChannel"); 32 | host->VmbusPipeServerConnectPipe = (fnVmbusPipeServerConnectPipe) GetProcAddress(hModule, "VmbusPipeServerConnectPipe"); 33 | host->VmbusPipeServerOfferChannel = (fnVmbusPipeServerOfferChannel) GetProcAddress(hModule, "VmbusPipeServerOfferChannel"); 34 | 35 | return host; 36 | } 37 | 38 | void VmBusPipeHostFree(VmBusPipeHost* host) 39 | { 40 | if (host) 41 | { 42 | FreeLibrary(host->VmBusPipeHostModule); 43 | free(host); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(VMBusPipe C CXX) 4 | 5 | set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 6 | 7 | include(CMakePackageConfigHelpers) 8 | 9 | file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION_STRINGS) 10 | list(GET VERSION_STRINGS 0 VERSION_STRING) 11 | 12 | string(REGEX REPLACE "([0-9]+).[0-9]+.[0-9]+" "\\1" VMBUSPIPE_VERSION_MAJOR ${VERSION_STRING}) 13 | string(REGEX REPLACE "[0-9]+.([0-9]+).[0-9]+" "\\1" VMBUSPIPE_VERSION_MINOR ${VERSION_STRING}) 14 | string(REGEX REPLACE "[0-9]+.[0-9]+.([0-9]+)" "\\1" VMBUSPIPE_VERSION_PATCH ${VERSION_STRING}) 15 | set(VMBUSPIPE_VERSION "${VMBUSPIPE_VERSION_MAJOR}.${VMBUSPIPE_VERSION_MINOR}.${VMBUSPIPE_VERSION_PATCH}") 16 | 17 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 18 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 19 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 20 | 21 | if(MSVC) 22 | include(MSVCRuntime) 23 | 24 | if(NOT DEFINED MSVC_RUNTIME) 25 | set(MSVC_RUNTIME "static") 26 | endif() 27 | 28 | configure_msvc_runtime() 29 | endif() 30 | 31 | if(WIN32) 32 | set(C_FLAGS "") 33 | set(C_FLAGS "${C_FLAGS} -D_UNICODE") 34 | set(C_FLAGS "${C_FLAGS} -D_CRT_SECURE_NO_WARNINGS") 35 | set(C_FLAGS "${C_FLAGS} -DWIN32_LEAN_AND_MEAN") 36 | set(C_FLAGS "${C_FLAGS} -D_WINSOCK_DEPRECATED_NO_WARNINGS") 37 | set(C_FLAGS "${C_FLAGS} -DWINVER=0x0602 -D_WIN32_WINNT=0x0602") 38 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS}") 39 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_FLAGS}") 40 | endif() 41 | 42 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}/VmBusPipe") 43 | 44 | add_subdirectory(VmBusPipe) 45 | add_subdirectory(VmBusPipeStub) 46 | add_subdirectory(VmBusPipeTest) 47 | -------------------------------------------------------------------------------- /VmBusPipe/VmBusPipeGuest.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "VmBusPipe.h" 6 | 7 | VmBusPipeGuest* VmBusPipeGuestInit(const char* filename) 8 | { 9 | HMODULE hModule; 10 | VmBusPipeGuest* guest; 11 | 12 | hModule = LoadLibraryA(filename ? filename : "vmbuspipe.dll"); 13 | 14 | if (!hModule) 15 | { 16 | printf("LoadLibrary failure: %d\n", (int) GetLastError()); 17 | return NULL; 18 | } 19 | 20 | guest = (VmBusPipeGuest*) malloc(sizeof(VmBusPipeGuest)); 21 | 22 | if (!guest) 23 | return NULL; 24 | 25 | ZeroMemory(guest, sizeof(VmBusPipeGuest)); 26 | 27 | guest->VmBusPipeGuestModule = hModule; 28 | 29 | guest->VmbusPipeClientEnumeratePipes = (fnVmbusPipeClientEnumeratePipes) GetProcAddress(hModule, "VmbusPipeClientEnumeratePipes"); 30 | guest->VmbusPipeClientOpenChannel = (fnVmbusPipeClientOpenChannel) GetProcAddress(hModule, "VmbusPipeClientOpenChannel"); 31 | guest->VmbusPipeClientReadyForChannelNotification = (fnVmbusPipeClientReadyForChannelNotification) GetProcAddress(hModule, "VmbusPipeClientReadyForChannelNotification"); 32 | guest->VmbusPipeClientRegisterChannelNotification = (fnVmbusPipeClientRegisterChannelNotification) GetProcAddress(hModule, "VmbusPipeClientRegisterChannelNotification"); 33 | guest->VmbusPipeClientUnregisterChannelNotification = (fnVmbusPipeClientUnregisterChannelNotification) GetProcAddress(hModule, "VmbusPipeClientUnregisterChannelNotification"); 34 | guest->VmbusPipeClientWaitChannel = (fnVmbusPipeClientWaitChannel) GetProcAddress(hModule, "VmbusPipeClientWaitChannel"); 35 | guest->VmbusPipeServerConnectPipe = (fnVmbusPipeServerConnectPipe) GetProcAddress(hModule, "VmbusPipeServerConnectPipe"); 36 | guest->VmbusPipeServerOfferChannel = (fnVmbusPipeServerOfferChannel) GetProcAddress(hModule, "VmbusPipeServerOfferChannel"); 37 | 38 | return guest; 39 | } 40 | 41 | void VmBusPipeGuestFree(VmBusPipeGuest* guest) 42 | { 43 | if (guest) 44 | { 45 | FreeLibrary(guest->VmBusPipeGuestModule); 46 | free(guest); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /cmake/MSVCRuntime.cmake: -------------------------------------------------------------------------------- 1 | 2 | macro(configure_msvc_runtime) 3 | if(MSVC) 4 | # Default to statically-linked runtime. 5 | if("${MSVC_RUNTIME}" STREQUAL "") 6 | set(MSVC_RUNTIME "dynamic") 7 | endif() 8 | 9 | # Set compiler options. 10 | set(variables 11 | CMAKE_C_FLAGS 12 | CMAKE_C_FLAGS_DEBUG 13 | CMAKE_C_FLAGS_MINSIZEREL 14 | CMAKE_C_FLAGS_RELEASE 15 | CMAKE_C_FLAGS_RELWITHDEBINFO 16 | CMAKE_CXX_FLAGS 17 | CMAKE_CXX_FLAGS_DEBUG 18 | CMAKE_CXX_FLAGS_MINSIZEREL 19 | CMAKE_CXX_FLAGS_RELEASE 20 | CMAKE_CXX_FLAGS_RELWITHDEBINFO) 21 | 22 | if(${MSVC_RUNTIME} STREQUAL "static") 23 | message(STATUS "MSVC: using statically-linked runtime (/MT and /MTd).") 24 | foreach(variable ${variables}) 25 | if(${variable} MATCHES "/MD") 26 | string(REGEX REPLACE "/MD" "/MT" ${variable} "${${variable}}") 27 | endif() 28 | endforeach() 29 | else() 30 | message(STATUS "MSVC: using dynamically-linked runtime (/MD and /MDd).") 31 | foreach(variable ${variables}) 32 | if(${variable} MATCHES "/MT") 33 | string(REGEX REPLACE "/MT" "/MD" ${variable} "${${variable}}") 34 | endif() 35 | endforeach() 36 | endif() 37 | 38 | foreach(variable ${variables}) 39 | if(${variable} MATCHES "/Ob0") 40 | string(REGEX REPLACE "/Ob0" "/Ob2" ${variable} "${${variable}}") 41 | endif() 42 | endforeach() 43 | 44 | foreach(variable ${variables}) 45 | if(${variable} MATCHES "/W3") 46 | string(REGEX REPLACE "/W3" "/W2" ${variable} "${${variable}}") 47 | endif() 48 | endforeach() 49 | 50 | set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") 51 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") 52 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") 53 | set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}") 54 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") 55 | 56 | foreach(variable ${variables}) 57 | set(${variable} "${${variable}}" CACHE STRING "MSVC_${variable}" FORCE) 58 | endforeach() 59 | endif() 60 | endmacro(configure_msvc_runtime) 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hyper-V VMBusPipe Reversing 2 | 3 | Many Hyper-V host-to-guest extensions communicate over a special named pipe transport that goes over the VMBus, called the VMBus pipe. One such feature is the Hyper-V enhanced session mode that opens a named pipe transport to the guest VM to use a special listener inside the RDP server, making it possible to connect without TCP networking available. 4 | 5 | This reversing project was done in 2014 as an effort to find ways to create third-party VMBus extensions. This is fortunately no longer necessary because Microsoft came out with [Hyper-V sockets](https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service) years later exactly for this type of use case, opening up the VMBus as a transport for anyone wanting to leverage it. 6 | 7 | Even with Hyper-V sockets, this project can serve as the basis for new work meant to intercept and inspect traffic happening over the VMBus pipe for extensions that use it. The VMBusPipe library contains the core API definitions and structures I reversed. The VMBusPipeStub project is meant to be compiled as vmbuspipe.dll and vmbuspiper.dll exposing the same API as the original libraries. Those stub libraries load the original unmodified libraries and forward all the API calls while logging them. The easiest way to install the replacement DLLs is to use a VM with nested virtualization, and copy the modified DLL by mounting the VHD while the VM is offline. Old test log captures can be found in the logs directory of this repository. As for the VMBusPipeTest project, it is an executable that attempts using the APIs I reversed, but from what I recall it had limited success being called outside of the Hyper-V processes. If there's a chance of making it work, it's probably through psexec. 8 | 9 | Generate and build the project using cmake: 10 | 11 | ``` 12 | mkdir build && cd build 13 | cmake "Visual Studio 16 2019" -A x64 .. 14 | cmake --build . --config Release 15 | ``` 16 | 17 | In the build directory, look under bin\Release to find the vmbuspipe.dll and vmbuspiper.dll stub DLLs. These stub DLLs export the same API as the original DLLs, but instead of implementing it they load the real DLL (rename them both to vmbuspipe_.dll and vmbuspiper_.dll) and forward the API calls while logging them to a text file. In order to replace the VMBusPipe DLLs, it is recommended to create a virtual machine with nested virtualization and Hyper-V installed, and simply mount the VHD while the VM is offline to modify the files. The logs files are created under "C:\Windows\Temp" by default and begin with "VmBusPipeStub". 18 | 19 | I am publishing these sources years after they've been taking the dust as a private reversing project, in hope of helping security researchers and reversers in their work. Go and have fun with Hyper-V and the VMBusPipe, and let me know if you manage to make anything useful out of this! 20 | -------------------------------------------------------------------------------- /Logs/VmBusPipeStub0130.txt: -------------------------------------------------------------------------------- 1 | 2014/01/27 14:16:52: DllMain: C:\Windows\System32\svchost.exe, fdwReason: 1 2 | 2014/01/27 14:16:52: VmbusPipeClientEnumeratePipe: pContext: 00000072F1D5FBE0 3 | 2014/01/27 14:16:52: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 4 | 2014/01/27 14:16:52: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{34d14be3-dee4-41c8-9ae7-6b174977c192}#{eb765408-105f-49b6-b4aa-c123b64d17d4}#{34d14be3-dee4-41c8-9ae7-6b174977c192} 5 | 2014/01/27 14:16:52: pGuid: {eb765408-105f-49b6-b4aa-c123b64d17d4} 6 | 2014/01/27 14:16:52: VmbusPipeClientEnumeratePipe: pContext: 00000072F236FB30 7 | 2014/01/27 14:16:52: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 8 | 2014/01/27 14:16:52: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{0e0b6031-5213-4934-818b-38d90ced39db}#{b6650ff7-33bc-4840-8048-e0676786f393}#{0e0b6031-5213-4934-818b-38d90ced39db} 9 | 2014/01/27 14:16:52: pGuid: {b6650ff7-33bc-4840-8048-e0676786f393} 10 | 2014/01/27 14:16:52: VmbusPipeClientOpenChannel: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{34d14be3-dee4-41c8-9ae7-6b174977c192}#{eb765408-105f-49b6-b4aa-c123b64d17d4}#{34d14be3-dee4-41c8-9ae7-6b174977c192} 11 | 2014/01/27 14:16:52: VmbusPipeClientOpenChannel: flags: 0x40000000 12 | 2014/01/27 14:16:52: VmbusPipeClientOpenChannel: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{0e0b6031-5213-4934-818b-38d90ced39db}#{b6650ff7-33bc-4840-8048-e0676786f393}#{0e0b6031-5213-4934-818b-38d90ced39db} 13 | 2014/01/27 14:16:52: VmbusPipeClientOpenChannel: flags: 0x40000000 14 | 2014/01/27 14:16:52: VmbusPipeClientEnumeratePipes: ClassGuid: {34d14be3-dee4-41c8-9ae7-6b174977c192} pContext: 00000072F1387BB0 pfn: 00007FFF5E7C1ADC bSuccess: 1 15 | 2014/01/27 14:16:52: VmbusPipeClientEnumeratePipes: ClassGuid: {0e0b6031-5213-4934-818b-38d90ced39db} pContext: 00000072F138B960 pfn: 00007FFF5E7C1ADC bSuccess: 1 16 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipe: pContext: 00000072F20BFA00 17 | 2014/01/27 14:16:53: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 18 | 2014/01/27 14:16:53: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{35fa2e29-ea23-4236-96ae-3a6ebacba440}#{2450ee40-33bf-4fbd-892e-9fb06e9214cf}#{35fa2e29-ea23-4236-96ae-3a6ebacba440} 19 | 2014/01/27 14:16:53: pGuid: {2450ee40-33bf-4fbd-892e-9fb06e9214cf} 20 | 2014/01/27 14:16:53: VmbusPipeClientOpenChannel: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{35fa2e29-ea23-4236-96ae-3a6ebacba440}#{2450ee40-33bf-4fbd-892e-9fb06e9214cf}#{35fa2e29-ea23-4236-96ae-3a6ebacba440} 21 | 2014/01/27 14:16:53: VmbusPipeClientOpenChannel: flags: 0x40000000 22 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipes: ClassGuid: {35fa2e29-ea23-4236-96ae-3a6ebacba440} pContext: 00000072F138B770 pfn: 00007FFF5E7C1ADC bSuccess: 1 23 | 2014/01/27 14:16:56: VmbusPipeClientEnumeratePipe: pContext: 00000072F23EF640 24 | 2014/01/27 14:16:56: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 25 | 2014/01/27 14:16:56: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}#{242ff919-07db-4180-9c2e-b86cb68c8c55}#{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6} 26 | 2014/01/27 14:16:56: pGuid: {242ff919-07db-4180-9c2e-b86cb68c8c55} 27 | 2014/01/27 14:16:56: VmbusPipeClientOpenChannel: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}#{242ff919-07db-4180-9c2e-b86cb68c8c55}#{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6} 28 | 2014/01/27 14:16:56: VmbusPipeClientOpenChannel: flags: 0x40000000 29 | 2014/01/27 14:16:56: VmbusPipeClientEnumeratePipes: ClassGuid: {a9a0f4e7-5a45-4d96-b827-8a841e8c03e6} pContext: 00000072F1387B20 pfn: 00007FFF5E7C1ADC bSuccess: 1 30 | -------------------------------------------------------------------------------- /cmake/WindowsRC.cmake: -------------------------------------------------------------------------------- 1 | 2 | function(windows_rc_generate_version_info) 3 | 4 | set(RC_ARGS_OPTIONS "") 5 | set(RC_ARGS_SINGLE "NAME;TYPE;VERSION;VENDOR;FILENAME;COPYRIGHT;OUTPUT") 6 | set(RC_ARGS_MULTI "") 7 | 8 | cmake_parse_arguments(RC "${RC_ARGS_OPTIONS}" "${RC_ARGS_SINGLE}" "${RC_ARGS_MULTI}" ${ARGN}) 9 | 10 | if(NOT DEFINED RC_TYPE OR "${RC_TYPE}" STREQUAL "") 11 | set(RC_TYPE "APP") 12 | endif() 13 | 14 | if(NOT DEFINED RC_VERSION OR "${RC_VERSION}" STREQUAL "") 15 | set(RC_VERSION "1.0.0") 16 | endif() 17 | 18 | # File Version 19 | 20 | if(NOT DEFINED RC_FILE_VERSION OR "${RC_FILE_VERSION}" STREQUAL "") 21 | set(RC_FILE_VERSION ${RC_VERSION}) 22 | endif() 23 | 24 | string(REPLACE "." ";" RC_FILE_VERSION_NUMBERS ${RC_FILE_VERSION}) 25 | list(LENGTH RC_FILE_VERSION_NUMBERS RC_FILE_VERSION_LENGTH) 26 | 27 | if(RC_FILE_VERSION_LENGTH LESS 4) 28 | list(APPEND RC_FILE_VERSION_NUMBERS "0") 29 | endif() 30 | 31 | string(REPLACE ";" "," RC_FILE_VERSION_NUMBER "${RC_FILE_VERSION_NUMBERS}") 32 | string(REPLACE ";" "." RC_FILE_VERSION_STRING "${RC_FILE_VERSION_NUMBERS}") 33 | 34 | # Product Version 35 | 36 | if(NOT DEFINED RC_PRODUCT_VERSION OR "${RC_PRODUCT_VERSION}" STREQUAL "") 37 | set(RC_PRODUCT_VERSION ${RC_VERSION}) 38 | endif() 39 | 40 | string(REPLACE "." ";" RC_PRODUCT_VERSION_NUMBERS ${RC_PRODUCT_VERSION}) 41 | list(LENGTH RC_PRODUCT_VERSION_NUMBERS RC_PRODUCT_VERSION_LENGTH) 42 | 43 | if(RC_PRODUCT_VERSION_LENGTH LESS 4) 44 | list(APPEND RC_PRODUCT_VERSION_NUMBERS "0") 45 | endif() 46 | 47 | string(REPLACE ";" "," RC_PRODUCT_VERSION_NUMBER "${RC_PRODUCT_VERSION_NUMBERS}") 48 | string(REPLACE ";" "." RC_PRODUCT_VERSION_STRING "${RC_PRODUCT_VERSION_NUMBERS}") 49 | 50 | set(RC_FILEOS "0x40004L") 51 | 52 | if(RC_TYPE STREQUAL "APP") 53 | set(RC_FILETYPE "0x1L") # VFT_APP 54 | elseif(RC_TYPE STREQUAL "DLL") 55 | set(RC_FILETYPE "0x2L") # VFT_DLL 56 | elseif(RC_TYPE STREQUAL "DRV") 57 | set(RC_FILETYPE "0x3L") # VFT_DRV 58 | else() 59 | set(RC_FILETYPE "0x0L") # VFT_UNKNOWN 60 | endif() 61 | 62 | set(RC_FILESUBTYPE "0x0L") 63 | 64 | set(RC_COMPANY_NAME "${RC_VENDOR}") 65 | set(RC_FILE_DESCRIPTION "${RC_NAME}") 66 | set(RC_PRODUCT_NAME "${RC_NAME}") 67 | set(RC_INTERNAL_NAME ${RC_FILENAME}) 68 | set(RC_ORIGINAL_FILENAME ${RC_FILENAME}) 69 | set(RC_LEGAL_COPYRIGHT ${RC_COPYRIGHT}) 70 | 71 | # VERSIONINFO resource 72 | # https://msdn.microsoft.com/en-us/library/windows/desktop/aa381058 73 | 74 | set(LINES "") 75 | list(APPEND LINES "") 76 | list(APPEND LINES "#include ") 77 | list(APPEND LINES "") 78 | list(APPEND LINES "VS_VERSION_INFO VERSIONINFO") 79 | list(APPEND LINES " FILEVERSION ${RC_FILE_VERSION_NUMBER}") 80 | list(APPEND LINES " PRODUCTVERSION ${RC_PRODUCT_VERSION_NUMBER}") 81 | list(APPEND LINES " FILEFLAGSMASK 0x3fL") 82 | list(APPEND LINES "#ifdef _DEBUG") 83 | list(APPEND LINES " FILEFLAGS 0x1L") 84 | list(APPEND LINES "#else") 85 | list(APPEND LINES " FILEFLAGS 0x0L") 86 | list(APPEND LINES "#endif") 87 | list(APPEND LINES " FILEOS ${RC_FILEOS}") 88 | list(APPEND LINES " FILETYPE ${RC_FILETYPE}") 89 | list(APPEND LINES " FILESUBTYPE ${RC_FILESUBTYPE}") 90 | list(APPEND LINES "BEGIN") 91 | list(APPEND LINES " BLOCK \"StringFileInfo\"") 92 | list(APPEND LINES " BEGIN") 93 | list(APPEND LINES " BLOCK \"040904b0\"") 94 | list(APPEND LINES " BEGIN") 95 | list(APPEND LINES " VALUE \"CompanyName\", \"${RC_COMPANY_NAME}\"") 96 | list(APPEND LINES " VALUE \"FileDescription\", \"${RC_FILE_DESCRIPTION}\"") 97 | list(APPEND LINES " VALUE \"FileVersion\", \"${RC_FILE_VERSION_STRING}\"") 98 | list(APPEND LINES " VALUE \"InternalName\", \"${RC_INTERNAL_NAME}\"") 99 | list(APPEND LINES " VALUE \"LegalCopyright\", \"${RC_LEGAL_COPYRIGHT}\"") 100 | list(APPEND LINES " VALUE \"OriginalFilename\", \"${RC_ORIGINAL_FILENAME}\"") 101 | list(APPEND LINES " VALUE \"ProductName\", \"${RC_PRODUCT_NAME}\"") 102 | list(APPEND LINES " VALUE \"ProductVersion\", \"${RC_PRODUCT_VERSION_STRING}\"") 103 | list(APPEND LINES " END") 104 | list(APPEND LINES " END") 105 | list(APPEND LINES " BLOCK \"VarFileInfo\"") 106 | list(APPEND LINES " BEGIN") 107 | list(APPEND LINES " VALUE \"Translation\", 0x409, 1200") 108 | list(APPEND LINES " END") 109 | list(APPEND LINES "END") 110 | list(APPEND LINES "") 111 | 112 | set(RC_FILE "") 113 | foreach(LINE ${LINES}) 114 | set(RC_FILE "${RC_FILE}${LINE}\n") 115 | endforeach() 116 | 117 | file(WRITE "${RC_OUTPUT}" ${RC_FILE}) 118 | endfunction() 119 | -------------------------------------------------------------------------------- /VmBusPipe/VmBusPipe.h: -------------------------------------------------------------------------------- 1 | #ifndef VMBUS_PIPE_H 2 | #define VMBUS_PIPE_H 3 | 4 | #include 5 | #include 6 | 7 | #define VMBUSAPI __stdcall 8 | 9 | /* 10 | * Based on CM_NOTIFY_FILTER 11 | * 416 bytes in 32-bit 12 | */ 13 | 14 | struct _VMBUS_CM_NOTIFY_FILTER 15 | { 16 | DWORD cbSize; 17 | DWORD Flags; 18 | CM_NOTIFY_FILTER_TYPE FilterType; 19 | DWORD Reserved; 20 | const GUID ClassGuid; 21 | DWORD data[96]; 22 | }; 23 | typedef struct _VMBUS_CM_NOTIFY_FILTER VMBUS_CM_NOTIFY_FILTER; 24 | 25 | struct _VMBUS_CHANNEL_NOTIFICATION 26 | { 27 | DWORD flags00; 28 | HMODULE hModuleCfgmgr32; 29 | HMODULE hModuleKernel32; 30 | HANDLE CmNotificationHandle; 31 | void* pContext; 32 | GUID* pClassGuid; 33 | GUID* pGuid2; 34 | DWORD field_1C; 35 | DWORD field_20; 36 | DWORD field_24; 37 | DWORD field_28; 38 | DWORD context[130]; 39 | DWORD field_234; 40 | DWORD field_238; 41 | const GUID ClassGuid; 42 | const GUID Guid2; 43 | DWORD notificationFlags; 44 | CRITICAL_SECTION lock01; 45 | DWORD ptrOrBool278; 46 | DWORD bBool27C; 47 | DWORD bThreadpoolWorkSubmitted; 48 | DWORD interlockedExch01; 49 | DWORD field_288; 50 | DWORD dispatchFlags; 51 | void* pfnCM_Register_Notification; 52 | void* pfnCM_Unregister_Notification; 53 | void* pfnCreateThreadpoolWork; 54 | void* pfnSubmitThreadpoolWork; 55 | void* pfnWaitForThreadpoolWorkCallbacks; 56 | void* pfnCloseThreadpoolWork; 57 | PTP_WORK pWorkObject; 58 | CRITICAL_SECTION lock02; 59 | void* pfnDispatchCallback; 60 | void* pDispatchContext; 61 | }; 62 | typedef struct _VMBUS_CHANNEL_NOTIFICATION VMBUS_CHANNEL_NOTIFICATION; 63 | 64 | /* Based on SP_DEVICE_INTERFACE_DETAIL_DATA */ 65 | 66 | struct _VMBUS_DEVICE_INTERFACE_DETAIL_DATA 67 | { 68 | DWORD cbSize; 69 | WCHAR DevicePath[260 + 1]; 70 | }; 71 | typedef struct _VMBUS_DEVICE_INTERFACE_DETAIL_DATA VMBUS_DEVICE_INTERFACE_DETAIL_DATA; 72 | typedef struct _VMBUS_DEVICE_INTERFACE_DETAIL_DATA* PVMBUS_DEVICE_INTERFACE_DETAIL_DATA; 73 | 74 | struct _VMBUS_CHANNEL_INFO 75 | { 76 | GUID VirtualMachineGuid; 77 | DWORD unknown01; 78 | GUID InterfaceTypeGuid; 79 | GUID InterfaceInstanceGuid; 80 | PHANDLE phChannel; 81 | UINT16 field_38; 82 | UINT16 flags3A; 83 | BYTE UserDefined[116]; 84 | }; 85 | typedef struct _VMBUS_CHANNEL_INFO VMBUS_CHANNEL_INFO; 86 | typedef struct _VMBUS_CHANNEL_INFO* PVMBUS_CHANNEL_INFO; 87 | 88 | typedef void (VMBUSAPI * fnVmbusPipeClientEnumeratePipe)(void* pContext, BYTE* pUserDefined, PVMBUS_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData, const GUID* pGuid); 89 | typedef void (VMBUSAPI * fnVmbusPipeClientChannelNotification)(void* pDispatchContext, void* pContext, DWORD notificationFlags); 90 | 91 | typedef BOOL (VMBUSAPI * fnVmbusPipeClientEnumeratePipes)(const GUID* ClassGuid, void* pContext, fnVmbusPipeClientEnumeratePipe pfn); 92 | typedef HANDLE (VMBUSAPI * fnVmbusPipeClientOpenChannel)(PVMBUS_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData, DWORD flags); 93 | 94 | typedef void (VMBUSAPI * fnVmbusPipeClientReadyForChannelNotification)(VMBUS_CHANNEL_NOTIFICATION* pChannelNotification, BOOL bEnumeratePipes); 95 | typedef VMBUS_CHANNEL_NOTIFICATION* (VMBUSAPI * fnVmbusPipeClientRegisterChannelNotification)(GUID* ClassGuid, GUID* Guid2, DWORD notificationFlags, 96 | fnVmbusPipeClientChannelNotification pfnDispatchCallback, void* pDispatchContext); 97 | typedef int (VMBUSAPI * fnVmbusPipeClientUnregisterChannelNotification)(VMBUS_CHANNEL_NOTIFICATION* pChannelNotification, BOOL bWait); 98 | 99 | typedef BOOL (VMBUSAPI * fnVmbusPipeClientWaitChannel)(GUID* pGuid1, DWORD arg2, DWORD uElapse, UINT_PTR param); 100 | typedef BOOL (VMBUSAPI * fnVmbusPipeServerConnectPipe)(HANDLE hDevice, LPOVERLAPPED lpOverlapped); 101 | typedef int (VMBUSAPI * fnVmbusPipeServerOfferChannel)(PVMBUS_CHANNEL_INFO pVmbusChannelInfo, DWORD dwFlagsAndAttributes, PHANDLE phChannel); 102 | 103 | struct _VmBusPipeHost 104 | { 105 | HMODULE VmBusPipeHostModule; 106 | fnVmbusPipeClientEnumeratePipes VmbusPipeClientEnumeratePipes; 107 | fnVmbusPipeClientOpenChannel VmbusPipeClientOpenChannel; 108 | fnVmbusPipeClientWaitChannel VmbusPipeClientWaitChannel; 109 | fnVmbusPipeServerConnectPipe VmbusPipeServerConnectPipe; 110 | fnVmbusPipeServerOfferChannel VmbusPipeServerOfferChannel; 111 | }; 112 | typedef struct _VmBusPipeHost VmBusPipeHost; 113 | 114 | struct _VmBusPipeGuest 115 | { 116 | HMODULE VmBusPipeGuestModule; 117 | fnVmbusPipeClientEnumeratePipes VmbusPipeClientEnumeratePipes; 118 | fnVmbusPipeClientOpenChannel VmbusPipeClientOpenChannel; 119 | fnVmbusPipeClientReadyForChannelNotification VmbusPipeClientReadyForChannelNotification; 120 | fnVmbusPipeClientRegisterChannelNotification VmbusPipeClientRegisterChannelNotification; 121 | fnVmbusPipeClientUnregisterChannelNotification VmbusPipeClientUnregisterChannelNotification; 122 | fnVmbusPipeClientWaitChannel VmbusPipeClientWaitChannel; 123 | fnVmbusPipeServerConnectPipe VmbusPipeServerConnectPipe; 124 | fnVmbusPipeServerOfferChannel VmbusPipeServerOfferChannel; 125 | }; 126 | typedef struct _VmBusPipeGuest VmBusPipeGuest; 127 | 128 | #ifdef __cplusplus 129 | extern "C" { 130 | #endif 131 | 132 | VmBusPipeHost* VmBusPipeHostInit(const char* filename); 133 | void VmBusPipeHostFree(VmBusPipeHost* host); 134 | 135 | VmBusPipeGuest* VmBusPipeGuestInit(const char* filename); 136 | void VmBusPipeGuestFree(VmBusPipeGuest* guest); 137 | 138 | #ifdef __cplusplus 139 | } 140 | #endif 141 | 142 | #endif /* VMBUS_PIPE_H */ 143 | -------------------------------------------------------------------------------- /VmBusPipeStub/Helpers.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Helpers.h" 3 | 4 | int ConvertToUnicode(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, 5 | int cbMultiByte, LPWSTR* lpWideCharStr, int cchWideChar) 6 | { 7 | int status; 8 | BOOL allocate = FALSE; 9 | 10 | if (!lpMultiByteStr) 11 | return 0; 12 | 13 | if (!lpWideCharStr) 14 | return 0; 15 | 16 | if (cbMultiByte == -1) 17 | cbMultiByte = (int) strlen(lpMultiByteStr) + 1; 18 | 19 | if (cchWideChar == 0) 20 | { 21 | cchWideChar = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0); 22 | allocate = TRUE; 23 | } 24 | 25 | if (cchWideChar < 1) 26 | return 0; 27 | 28 | if (!(*lpWideCharStr)) 29 | allocate = TRUE; 30 | 31 | if (allocate) 32 | *lpWideCharStr = (LPWSTR) malloc(cchWideChar * sizeof(WCHAR)); 33 | 34 | status = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, *lpWideCharStr, cchWideChar); 35 | 36 | if (status != cchWideChar) 37 | status = 0; 38 | 39 | return status; 40 | } 41 | 42 | int ConvertFromUnicode(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, 43 | LPSTR* lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar) 44 | { 45 | int status; 46 | BOOL allocate = FALSE; 47 | 48 | if (!lpWideCharStr) 49 | return 0; 50 | 51 | if (!lpMultiByteStr) 52 | return 0; 53 | 54 | if (cchWideChar == -1) 55 | cchWideChar = (int) wcslen(lpWideCharStr) + 1; 56 | 57 | if (cbMultiByte == 0) 58 | { 59 | cbMultiByte = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, NULL, NULL); 60 | allocate = TRUE; 61 | } 62 | 63 | if (cbMultiByte < 1) 64 | return 0; 65 | 66 | if (!(*lpMultiByteStr)) 67 | allocate = TRUE; 68 | 69 | if (allocate) 70 | { 71 | *lpMultiByteStr = (LPSTR) malloc(cbMultiByte + 1); 72 | ZeroMemory(*lpMultiByteStr, cbMultiByte + 1); 73 | } 74 | 75 | status = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, 76 | *lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar); 77 | 78 | if (status != cbMultiByte) 79 | status = 0; 80 | 81 | if ((status <= 0) && allocate) 82 | { 83 | free(*lpMultiByteStr); 84 | *lpMultiByteStr = NULL; 85 | } 86 | 87 | return status; 88 | } 89 | 90 | char* BinToHexString(BYTE* data, int length) 91 | { 92 | int i; 93 | char* p; 94 | int ln, hn; 95 | char bin2hex[] = "0123456789ABCDEF"; 96 | 97 | p = (char*) malloc((length + 1) * 2); 98 | 99 | if (!p) 100 | return NULL; 101 | 102 | for (i = 0; i < length; i++) 103 | { 104 | ln = data[i] & 0xF; 105 | hn = (data[i] >> 4) & 0xF; 106 | p[i * 2] = bin2hex[hn]; 107 | p[(i * 2) + 1] = bin2hex[ln]; 108 | } 109 | 110 | p[length * 2] = '\0'; 111 | 112 | return p; 113 | } 114 | 115 | /* Logger Class */ 116 | 117 | CLogFile::CLogFile() 118 | { 119 | m_enabled = true; 120 | m_lTruncate = 0; 121 | m_pLogFile = NULL; 122 | ZeroMemory(m_filename, sizeof(m_filename)); 123 | } 124 | 125 | CLogFile::~CLogFile() 126 | { 127 | if (m_enabled) 128 | CloseFile(); 129 | } 130 | 131 | void CLogFile::OpenFile(const char* strFile, bool bAppend, long lTruncate) 132 | { 133 | m_lTruncate = lTruncate; 134 | 135 | if (!m_enabled) 136 | return; 137 | 138 | memcpy(m_filename, strFile, strlen(strFile)); 139 | 140 | char szFile[MAX_PATH + 1]; 141 | 142 | if (strlen(strFile) > 3 && strFile[1] != ':') 143 | { 144 | GetModuleFileNameA(NULL, szFile, MAX_PATH); 145 | 146 | long llength = (long) strlen(szFile); 147 | char* pcat = szFile + (llength - 1); 148 | 149 | while (llength--) 150 | { 151 | pcat--; 152 | 153 | if (*pcat == '\\') 154 | break; 155 | } 156 | 157 | if (*pcat == '\\') 158 | { 159 | pcat++; 160 | strcpy(pcat, strFile); 161 | } 162 | else 163 | { 164 | strcpy(szFile, strFile); 165 | } 166 | } 167 | else 168 | { 169 | strcpy(szFile, strFile); 170 | } 171 | 172 | m_pLogFile = fopen(szFile, bAppend ? "a" : "w"); 173 | 174 | if (!m_pLogFile) 175 | { 176 | CreateDirectories(szFile); 177 | m_pLogFile = fopen(szFile, bAppend ? "a" : "w"); 178 | } 179 | 180 | InitializeCriticalSection(&m_cs); 181 | } 182 | 183 | void CLogFile::CloseFile() 184 | { 185 | if (!m_enabled) 186 | return; 187 | 188 | if (m_pLogFile) 189 | { 190 | fclose(m_pLogFile); 191 | } 192 | 193 | DeleteCriticalSection(&m_cs); 194 | } 195 | 196 | void CLogFile::CreateDirectories(const char* filename) 197 | { 198 | char drivename[4]; 199 | char path[MAX_PATH + 1]; 200 | char name[MAX_PATH + 1]; 201 | char ext[MAX_PATH + 1]; 202 | char seps[] = "/\\"; 203 | char* token; 204 | 205 | if (!m_enabled) 206 | return; 207 | 208 | _splitpath(filename, drivename, path, name, ext); 209 | 210 | sprintf(drivename, "%s\\", drivename); 211 | _chdir(drivename); 212 | 213 | token = strtok(path, seps); 214 | 215 | while (token != NULL) 216 | { 217 | if (_chdir(token) == -1) 218 | { 219 | _mkdir(token); 220 | _chdir(token); 221 | } 222 | 223 | token = strtok(NULL, seps); 224 | } 225 | } 226 | 227 | void CLogFile::Write(const char* pszFormat, ...) 228 | { 229 | if (!m_enabled) 230 | return; 231 | 232 | if (!m_pLogFile) 233 | return; 234 | 235 | EnterCriticalSection(&m_cs); 236 | 237 | char szLog[4096]; 238 | va_list argList; 239 | va_start(argList, pszFormat); 240 | vsprintf(szLog, pszFormat, argList); 241 | va_end(argList); 242 | 243 | SYSTEMTIME time; 244 | ::GetLocalTime(&time); 245 | char szLine[256]; 246 | 247 | sprintf(szLine, "%04d/%02d/%02d %02d:%02d:%02d: %s\n", 248 | time.wYear, time.wMonth, time.wDay, 249 | time.wHour, time.wMinute, time.wSecond, szLog); 250 | 251 | fputs(szLine, m_pLogFile); 252 | 253 | fflush(m_pLogFile); 254 | 255 | LeaveCriticalSection(&m_cs); 256 | } 257 | -------------------------------------------------------------------------------- /Logs/VmBusPipeStub0594.txt: -------------------------------------------------------------------------------- 1 | 2014/01/27 14:16:52: DllMain: C:\Windows\system32\svchost.exe, fdwReason: 1 2 | 2014/01/27 14:16:52: VmbusPipeClientEnumeratePipe: pContext: 000000FA8F7DF7C0 3 | 2014/01/27 14:16:52: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 4 | 2014/01/27 14:16:52: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{276aacf4-ac15-426c-98dd-7521ad3f01fe}#{f5bee29c-1741-4aad-a4c2-8fdedb46dcc2}#{276aacf4-ac15-426c-98dd-7521ad3f01fe} 5 | 2014/01/27 14:16:52: pGuid: {f5bee29c-1741-4aad-a4c2-8fdedb46dcc2} 6 | 2014/01/27 14:16:52: VmbusPipeClientOpenChannel: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{276aacf4-ac15-426c-98dd-7521ad3f01fe}#{f5bee29c-1741-4aad-a4c2-8fdedb46dcc2}#{276aacf4-ac15-426c-98dd-7521ad3f01fe} 7 | 2014/01/27 14:16:52: VmbusPipeClientOpenChannel: flags: 0x40000000 8 | 2014/01/27 14:16:52: VmbusPipeClientEnumeratePipes: ClassGuid: {276aacf4-ac15-426c-98dd-7521ad3f01fe} pContext: 000000FA8EBD6BC0 pfn: 00007FFF5E7C1ADC bSuccess: 1 9 | 2014/01/27 14:16:52: VmbusPipeClientEnumeratePipe: pContext: 000000FA8F47F8C0 10 | 2014/01/27 14:16:52: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 11 | 2014/01/27 14:16:52: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{57164f39-9115-4e78-ab55-382f3bd5422d}#{fd149e91-82e0-4a7d-afa6-2a4166cbd7c0}#{57164f39-9115-4e78-ab55-382f3bd5422d} 12 | 2014/01/27 14:16:52: pGuid: {fd149e91-82e0-4a7d-afa6-2a4166cbd7c0} 13 | 2014/01/27 14:16:52: VmbusPipeClientOpenChannel: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{57164f39-9115-4e78-ab55-382f3bd5422d}#{fd149e91-82e0-4a7d-afa6-2a4166cbd7c0}#{57164f39-9115-4e78-ab55-382f3bd5422d} 14 | 2014/01/27 14:16:52: VmbusPipeClientOpenChannel: flags: 0x40000000 15 | 2014/01/27 14:16:52: VmbusPipeClientEnumeratePipes: ClassGuid: {57164f39-9115-4e78-ab55-382f3bd5422d} pContext: 000000FA8EBD6740 pfn: 00007FFF5E7C1ADC bSuccess: 1 16 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipe: pContext: 000000FA8FB1F4D0 17 | 2014/01/27 14:16:53: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 18 | 2014/01/27 14:16:53: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{276aacf4-ac15-426c-98dd-7521ad3f01fe}#{f5bee29c-1741-4aad-a4c2-8fdedb46dcc2}#{276aacf4-ac15-426c-98dd-7521ad3f01fe} 19 | 2014/01/27 14:16:53: pGuid: {f5bee29c-1741-4aad-a4c2-8fdedb46dcc2} 20 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipes: ClassGuid: {276aacf4-ac15-426c-98dd-7521ad3f01fe} pContext: 000000FA8EBDE810 pfn: 00007FFF5E59A168 bSuccess: 1 21 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipe: pContext: 000000FA8FC9F590 22 | 2014/01/27 14:16:53: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 23 | 2014/01/27 14:16:53: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{276aacf4-ac15-426c-98dd-7521ad3f01fe}#{f5bee29c-1741-4aad-a4c2-8fdedb46dcc2}#{276aacf4-ac15-426c-98dd-7521ad3f01fe} 24 | 2014/01/27 14:16:53: pGuid: {f5bee29c-1741-4aad-a4c2-8fdedb46dcc2} 25 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipes: ClassGuid: {276aacf4-ac15-426c-98dd-7521ad3f01fe} pContext: 000000FA8FB20BB0 pfn: 00007FFF5E59A168 bSuccess: 1 26 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipe: pContext: 000000FA8FE1F820 27 | 2014/01/27 14:16:53: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 28 | 2014/01/27 14:16:53: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{276aacf4-ac15-426c-98dd-7521ad3f01fe}#{f5bee29c-1741-4aad-a4c2-8fdedb46dcc2}#{276aacf4-ac15-426c-98dd-7521ad3f01fe} 29 | 2014/01/27 14:16:53: pGuid: {f5bee29c-1741-4aad-a4c2-8fdedb46dcc2} 30 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipes: ClassGuid: {276aacf4-ac15-426c-98dd-7521ad3f01fe} pContext: 000000FA8FB21D20 pfn: 00007FFF5E59A168 bSuccess: 1 31 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipe: pContext: 000000FA8FE9F6E0 32 | 2014/01/27 14:16:53: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 33 | 2014/01/27 14:16:53: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{276aacf4-ac15-426c-98dd-7521ad3f01fe}#{f5bee29c-1741-4aad-a4c2-8fdedb46dcc2}#{276aacf4-ac15-426c-98dd-7521ad3f01fe} 34 | 2014/01/27 14:16:53: pGuid: {f5bee29c-1741-4aad-a4c2-8fdedb46dcc2} 35 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipes: ClassGuid: {276aacf4-ac15-426c-98dd-7521ad3f01fe} pContext: 000000FA8FB22830 pfn: 00007FFF5E59A168 bSuccess: 1 36 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipe: pContext: 000000FA8FF1F7D0 37 | 2014/01/27 14:16:53: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 38 | 2014/01/27 14:16:53: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{276aacf4-ac15-426c-98dd-7521ad3f01fe}#{f5bee29c-1741-4aad-a4c2-8fdedb46dcc2}#{276aacf4-ac15-426c-98dd-7521ad3f01fe} 39 | 2014/01/27 14:16:53: pGuid: {f5bee29c-1741-4aad-a4c2-8fdedb46dcc2} 40 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipes: ClassGuid: {276aacf4-ac15-426c-98dd-7521ad3f01fe} pContext: 000000FA8FB237C0 pfn: 00007FFF5E59A168 bSuccess: 1 41 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipe: pContext: 000000FA8FF9F7C0 42 | 2014/01/27 14:16:53: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 43 | 2014/01/27 14:16:53: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{276aacf4-ac15-426c-98dd-7521ad3f01fe}#{f5bee29c-1741-4aad-a4c2-8fdedb46dcc2}#{276aacf4-ac15-426c-98dd-7521ad3f01fe} 44 | 2014/01/27 14:16:53: pGuid: {f5bee29c-1741-4aad-a4c2-8fdedb46dcc2} 45 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipes: ClassGuid: {276aacf4-ac15-426c-98dd-7521ad3f01fe} pContext: 000000FA8FB24460 pfn: 00007FFF5E59A168 bSuccess: 1 46 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipe: pContext: 000000FA9001F4C0 47 | 2014/01/27 14:16:53: pUserDefined: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 48 | 2014/01/27 14:16:53: pDeviceInterfaceDetailData: cbSize: 8 DevicePath: \\?\vmbus#{276aacf4-ac15-426c-98dd-7521ad3f01fe}#{f5bee29c-1741-4aad-a4c2-8fdedb46dcc2}#{276aacf4-ac15-426c-98dd-7521ad3f01fe} 49 | 2014/01/27 14:16:53: pGuid: {f5bee29c-1741-4aad-a4c2-8fdedb46dcc2} 50 | 2014/01/27 14:16:53: VmbusPipeClientEnumeratePipes: ClassGuid: {276aacf4-ac15-426c-98dd-7521ad3f01fe} pContext: 000000FA8FB26710 pfn: 00007FFF5E59A168 bSuccess: 1 51 | -------------------------------------------------------------------------------- /VmBusPipeTest/Main.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "VmBusPipe.h" 9 | 10 | struct _VmBusPipeContext 11 | { 12 | BOOL bGuestMode; 13 | VmBusPipeHost* host; 14 | VmBusPipeGuest* guest; 15 | }; 16 | typedef struct _VmBusPipeContext VmBusPipeContext; 17 | 18 | static VmBusPipeContext* g_VmBusPipeContext; 19 | 20 | // {f9e9c0d3-b511-4a48-8046-d38079a8830c} "Microsoft Hyper-V Remote Desktop Data Channel" 21 | DEFINE_GUID(GUID_VMBUS_REMOTE_DESKTOP_DATA_CHANNEL, 0xf9e9c0d3, 0xb511, 0x4a48, 0x80, 0x46, 0xd3, 0x80, 0x79, 0xa8, 0x83, 0x0c); 22 | 23 | // {276aacf4-ac15-426c-98dd-7521ad3f01fe} "Microsoft Hyper-V Remote Desktop Virtualization" 24 | DEFINE_GUID(GUID_VMBUS_REMOTE_DESKTOP_VIRTUALIZATION, 0x276aacf4, 0xac15, 0x426c, 0x98, 0xdd, 0x75, 0x21, 0xad, 0x3f, 0x01, 0xfe); 25 | 26 | // {57164f39-9115-4e78-ab55-382f3bd5422d} "Microsoft Hyper-V Heartbeat" 27 | DEFINE_GUID(GUID_VMBUS_HEARTBEAT, 0x57164f39, 0x9115, 0x4e78, 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d); 28 | 29 | // {1DAE6E2C-D5EF-4085-8C3C-00FC462F181A} 30 | DEFINE_GUID(GUID_VMBUS_PIPE_TEST, 0x1dae6e2c, 0xd5ef, 0x4085, 0x8c, 0x3c, 0x0, 0xfc, 0x46, 0x2f, 0x18, 0x1a); 31 | 32 | //DEFINE_GUID(GUID_VMBUS_, 0x, 0x, 0x, 0x, 0x, 0x, 0x, 0x, 0x, 0x, 0x); 33 | 34 | // {7563c5a0-025e-4a49-ad24-df8341a577bd} "Windows Server 2012 R2" Virtual Machine Id 35 | DEFINE_GUID(GUID_VIRTUAL_MACHINE_ID, 0x7563c5a0, 0x025e, 0x4a49, 0xad, 0x24, 0xdf, 0x83, 0x41, 0xa5, 0x77, 0xbd); 36 | 37 | // {3ed8401b-88a1-409a-9cd6-a0f83ae83c81} "Ubuntu 13.10" Virtual Machine Id 38 | DEFINE_GUID(GUID_VM_UBUNTU, 0x3ed8401b, 0x88a1, 0x409a, 0x9c, 0xd6, 0xa0, 0xf8, 0x3a, 0xe8, 0x3c, 0x81); 39 | 40 | void HexDump(BYTE* data, int length) 41 | { 42 | BYTE* p = data; 43 | int i, line, offset = 0; 44 | 45 | while (offset < length) 46 | { 47 | fprintf(stderr, "%04x ", offset); 48 | 49 | line = length - offset; 50 | 51 | if (line > 16) 52 | line = 16; 53 | 54 | for (i = 0; i < line; i++) 55 | fprintf(stderr, "%02x ", p[i]); 56 | 57 | for (; i < 16; i++) 58 | fprintf(stderr, " "); 59 | 60 | for (i = 0; i < line; i++) 61 | fprintf(stderr, "%c", (p[i] >= 0x20 && p[i] < 0x7F) ? p[i] : '.'); 62 | 63 | fprintf(stderr, "\n"); 64 | 65 | offset += line; 66 | p += line; 67 | } 68 | } 69 | 70 | char* BinToHexString(BYTE* data, int length) 71 | { 72 | int i; 73 | char* p; 74 | int ln, hn; 75 | char bin2hex[] = "0123456789abcdef"; 76 | 77 | p = (char*) malloc((length + 1) * 2); 78 | 79 | for (i = 0; i < length; i++) 80 | { 81 | ln = data[i] & 0xF; 82 | hn = (data[i] >> 4) & 0xF; 83 | p[i * 2] = bin2hex[hn]; 84 | p[(i * 2) + 1] = bin2hex[ln]; 85 | } 86 | 87 | p[length * 2] = '\0'; 88 | 89 | return p; 90 | } 91 | 92 | int ConvertToUnicode(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, 93 | int cbMultiByte, LPWSTR* lpWideCharStr, int cchWideChar) 94 | { 95 | int status; 96 | BOOL allocate = FALSE; 97 | 98 | if (!lpMultiByteStr) 99 | return 0; 100 | 101 | if (!lpWideCharStr) 102 | return 0; 103 | 104 | if (cbMultiByte == -1) 105 | cbMultiByte = (int) strlen(lpMultiByteStr) + 1; 106 | 107 | if (cchWideChar == 0) 108 | { 109 | cchWideChar = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0); 110 | allocate = TRUE; 111 | } 112 | 113 | if (cchWideChar < 1) 114 | return 0; 115 | 116 | if (!(*lpWideCharStr)) 117 | allocate = TRUE; 118 | 119 | if (allocate) 120 | *lpWideCharStr = (LPWSTR) malloc(cchWideChar * sizeof(WCHAR)); 121 | 122 | status = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, *lpWideCharStr, cchWideChar); 123 | 124 | if (status != cchWideChar) 125 | status = 0; 126 | 127 | return status; 128 | } 129 | 130 | int ConvertFromUnicode(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, 131 | LPSTR* lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar) 132 | { 133 | int status; 134 | BOOL allocate = FALSE; 135 | 136 | if (!lpWideCharStr) 137 | return 0; 138 | 139 | if (!lpMultiByteStr) 140 | return 0; 141 | 142 | if (cchWideChar == -1) 143 | cchWideChar = (int) wcslen(lpWideCharStr) + 1; 144 | 145 | if (cbMultiByte == 0) 146 | { 147 | cbMultiByte = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, NULL, NULL); 148 | allocate = TRUE; 149 | } 150 | 151 | if (cbMultiByte < 1) 152 | return 0; 153 | 154 | if (!(*lpMultiByteStr)) 155 | allocate = TRUE; 156 | 157 | if (allocate) 158 | { 159 | *lpMultiByteStr = (LPSTR) malloc(cbMultiByte + 1); 160 | ZeroMemory(*lpMultiByteStr, cbMultiByte + 1); 161 | } 162 | 163 | status = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, 164 | *lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar); 165 | 166 | if (status != cbMultiByte) 167 | status = 0; 168 | 169 | if ((status <= 0) && allocate) 170 | { 171 | free(*lpMultiByteStr); 172 | *lpMultiByteStr = NULL; 173 | } 174 | 175 | return status; 176 | } 177 | 178 | static void VMBUSAPI VmbusPipeClientEnumeratePipe(void* pContext, BYTE* pUserDefined, PVMBUS_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData, const GUID* pGuid) 179 | { 180 | HANDLE hChannel; 181 | char* VmBusStringA = NULL; 182 | WCHAR* VmBusStringW = NULL; 183 | char* pUserDefinedString = NULL; 184 | VmBusPipeContext* vmbus = (VmBusPipeContext*) pContext; 185 | 186 | /** 187 | * pUserDefined: 116-byte UserDefined registry key 188 | * 189 | * pDeviceInterfaceDetailData: pointer to SP_DEVICE_INTERFACE_DETAIL_DATA (526-byte) 190 | * http://msdn.microsoft.com/en-us/library/windows/hardware/ff552343/ 191 | */ 192 | 193 | printf("VmbusPipeClientEnumeratePipe: pContext: %p\n", pContext); 194 | 195 | pUserDefinedString = BinToHexString(pUserDefined, 116); 196 | 197 | printf("\tpUserDefined: %s\n", pUserDefinedString); 198 | 199 | VmBusStringW = (WCHAR*) pDeviceInterfaceDetailData->DevicePath; 200 | ConvertFromUnicode(CP_UTF8, 0, VmBusStringW, -1, &VmBusStringA, 0, NULL, NULL); 201 | 202 | printf("\tpDeviceInterfaceDetailData: cbSize: %d DevicePath: %s\n", 203 | pDeviceInterfaceDetailData->cbSize, VmBusStringA); 204 | 205 | printf("\tpGuid: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", 206 | pGuid->Data1, pGuid->Data2, pGuid->Data3, 207 | pGuid->Data4[0], pGuid->Data4[1], 208 | pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], 209 | pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7]); 210 | 211 | free(pUserDefinedString); 212 | free(VmBusStringA); 213 | 214 | if (vmbus->bGuestMode) 215 | { 216 | hChannel = vmbus->guest->VmbusPipeClientOpenChannel(pDeviceInterfaceDetailData, 0x40000000); 217 | } 218 | else 219 | { 220 | hChannel = vmbus->host->VmbusPipeClientOpenChannel(pDeviceInterfaceDetailData, 0x40000000); 221 | } 222 | 223 | printf("VmbusPipeClientOpenChannel: 0x%04X\n", (unsigned int) (size_t) hChannel); 224 | } 225 | 226 | int test_VmBusPipeHost(VmBusPipeHost* host) 227 | { 228 | int status; 229 | BOOL bSuccess; 230 | HANDLE hChannel; 231 | DWORD dwFlagsAndAttributes; 232 | PVMBUS_CHANNEL_INFO pVmChannelInfo; 233 | 234 | printf("VmBusPipeHost: %d\n", host ? 1 : 0); 235 | 236 | /** 237 | * VmbusPipeServerOfferChannel 238 | * VmbusPipeServerConnectPipe 239 | */ 240 | 241 | pVmChannelInfo = (PVMBUS_CHANNEL_INFO) malloc(sizeof(VMBUS_CHANNEL_INFO)); 242 | ZeroMemory(pVmChannelInfo, sizeof(VMBUS_CHANNEL_INFO)); 243 | 244 | bSuccess = host->VmbusPipeClientEnumeratePipes(&GUID_VMBUS_REMOTE_DESKTOP_VIRTUALIZATION, 245 | g_VmBusPipeContext, VmbusPipeClientEnumeratePipe); 246 | 247 | printf("VmbusPipeClientEnumeratePipes: %d\n", bSuccess); 248 | 249 | hChannel = NULL; 250 | dwFlagsAndAttributes = 0x40000000; 251 | 252 | CopyMemory(&(pVmChannelInfo->VirtualMachineGuid), &GUID_VIRTUAL_MACHINE_ID, sizeof(GUID)); 253 | CopyMemory(&(pVmChannelInfo->VirtualMachineGuid), &GUID_VM_UBUNTU, sizeof(GUID)); 254 | 255 | status = host->VmbusPipeServerOfferChannel(pVmChannelInfo, dwFlagsAndAttributes, &hChannel); 256 | 257 | printf("VmbusPipeServerOfferChannel: %d\n", status); 258 | 259 | if (status < 0) 260 | { 261 | DWORD dwIoControlCode = 0x3EC03C; 262 | 263 | /** 264 | * Host: ERROR_INVALID_FUNCTION (1) 265 | * DeviceIoControl is called with dwIoControlCode 0x3EC03C 266 | * 267 | * DeviceType: 0x003E (FILE_DEVICE_VMBUS) 268 | * Access: 0x3 269 | * Function: 0xF 270 | * Method: 0 271 | */ 272 | 273 | printf("VmbusPipeServerOfferChannel: GetLastError() = %d\n", GetLastError()); 274 | } 275 | 276 | return 0; 277 | } 278 | 279 | int test_VmBusPipeGuest(VmBusPipeGuest* guest) 280 | { 281 | //int status; 282 | BOOL bSuccess; 283 | HANDLE hChannel; 284 | DWORD dwFlagsAndAttributes; 285 | PVMBUS_CHANNEL_INFO pVmChannelInfo; 286 | 287 | printf("VmBusPipeGuest: %d\n", guest ? 1 : 0); 288 | 289 | /** 290 | * VmbusPipeClientOpenChannel 291 | * VmbusPipeServerOfferChannel 292 | * VmbusPipeServerConnectPipe 293 | * VmbusPipeClientEnumeratePipes 294 | */ 295 | 296 | pVmChannelInfo = (PVMBUS_CHANNEL_INFO) malloc(sizeof(VMBUS_CHANNEL_INFO)); 297 | ZeroMemory(pVmChannelInfo, sizeof(VMBUS_CHANNEL_INFO)); 298 | 299 | bSuccess = guest->VmbusPipeClientEnumeratePipes(&GUID_VMBUS_REMOTE_DESKTOP_VIRTUALIZATION, 300 | g_VmBusPipeContext, VmbusPipeClientEnumeratePipe); 301 | 302 | printf("VmbusPipeClientEnumeratePipes: %d\n", bSuccess); 303 | 304 | dwFlagsAndAttributes = 0; 305 | hChannel = NULL; 306 | 307 | #if 0 308 | /** 309 | * CreateFile dwFlagsAndAttributes: 310 | * http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858/ 311 | * FILE_FLAG_POSIX_SEMANTICS (0x0100000) is added 312 | */ 313 | 314 | status = guest->VmbusPipeServerOfferChannel(pDeviceInterfaceDetailData, dwFlagsAndAttributes, &hChannel); 315 | 316 | printf("VmbusPipeServerOfferChannel: %d\n", status); 317 | 318 | if (status < 0) 319 | { 320 | /** 321 | * Guest: ERROR_FILE_NOT_FOUND (2) 322 | * 323 | * Host: ERROR_ACCESS_DENIED (5) 324 | * Host + Admin: ERROR_INVALID_FUNCTION (1) 325 | * ERROR_NOT_SUPPORTED (50) 326 | */ 327 | 328 | printf("VmbusPipeServerOfferChannel: GetLastError() = %d\n", GetLastError()); 329 | } 330 | #endif 331 | 332 | return 0; 333 | } 334 | 335 | int main(int argc, char** argv) 336 | { 337 | BOOL bGuestMode; 338 | VmBusPipeHost* host; 339 | VmBusPipeGuest* guest; 340 | 341 | bGuestMode = FALSE; 342 | host = VmBusPipeHostInit(NULL); 343 | guest = VmBusPipeGuestInit(NULL); 344 | 345 | if (argc > 1) 346 | { 347 | if (strcmp(argv[1], "guest") == 0) 348 | { 349 | bGuestMode = TRUE; 350 | } 351 | } 352 | 353 | g_VmBusPipeContext = (VmBusPipeContext*) malloc(sizeof(VmBusPipeContext)); 354 | g_VmBusPipeContext->bGuestMode = bGuestMode; 355 | g_VmBusPipeContext->host = host; 356 | g_VmBusPipeContext->guest = guest; 357 | 358 | if (host && !bGuestMode) 359 | { 360 | test_VmBusPipeHost(host); 361 | } 362 | else if (guest && bGuestMode) 363 | { 364 | test_VmBusPipeGuest(guest); 365 | } 366 | else 367 | { 368 | printf("VmBusPipe not found!\n"); 369 | } 370 | 371 | VmBusPipeHostFree(host); 372 | VmBusPipeGuestFree(guest); 373 | 374 | return 0; 375 | } 376 | -------------------------------------------------------------------------------- /VmBusPipeStub/VmBusPipeStub.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Helpers.h" 3 | #include "VmBusPipeStub.h" 4 | 5 | CLogFile log; 6 | static VmBusPipeGuest* guest = NULL; 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | struct _VmBusPipeEnumWrapper 13 | { 14 | void* pContext; 15 | fnVmbusPipeClientEnumeratePipe pfnVmbusPipeClientEnumeratePipe; 16 | }; 17 | typedef struct _VmBusPipeEnumWrapper VmBusPipeEnumWrapper; 18 | 19 | static void VMBUSAPI VmbusPipeClientEnumeratePipe(void* pContext, BYTE* pUserDefined, PVMBUS_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData, const GUID* pGuid) 20 | { 21 | char* VmBusStringA = NULL; 22 | WCHAR* VmBusStringW = NULL; 23 | char* pUserDefinedString = NULL; 24 | VmBusPipeEnumWrapper* wrapper = (VmBusPipeEnumWrapper*) pContext; 25 | 26 | /** 27 | * pUserDefined: 116-byte UserDefined registry key 28 | * 29 | * pDeviceInterfaceDetailData: pointer to SP_DEVICE_INTERFACE_DETAIL_DATA (526 bytes) 30 | * http://msdn.microsoft.com/en-us/library/windows/hardware/ff552343/ 31 | */ 32 | 33 | log.Write("VmbusPipeClientEnumeratePipe: pContext: %p", wrapper->pContext); 34 | 35 | pUserDefinedString = BinToHexString(pUserDefined, 116); 36 | 37 | log.Write("\tpUserDefined: %s", pUserDefinedString); 38 | 39 | VmBusStringW = (WCHAR*) pDeviceInterfaceDetailData->DevicePath; 40 | ConvertFromUnicode(CP_UTF8, 0, VmBusStringW, -1, &VmBusStringA, 0, NULL, NULL); 41 | 42 | log.Write("\tpDeviceInterfaceDetailData: cbSize: %d DevicePath: %s", 43 | pDeviceInterfaceDetailData->cbSize, VmBusStringA); 44 | 45 | log.Write("\tpGuid: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 46 | pGuid->Data1, pGuid->Data2, pGuid->Data3, 47 | pGuid->Data4[0], pGuid->Data4[1], 48 | pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], 49 | pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7]); 50 | 51 | wrapper->pfnVmbusPipeClientEnumeratePipe(wrapper->pContext, pUserDefined, pDeviceInterfaceDetailData, pGuid); 52 | 53 | free(pUserDefinedString); 54 | free(VmBusStringA); 55 | } 56 | 57 | BOOL VMBUSAPI VmbusPipeClientEnumeratePipes(const GUID* ClassGuid, void* pContext, fnVmbusPipeClientEnumeratePipe pfn) 58 | { 59 | BOOL bSuccess; 60 | char* pContextString; 61 | VmBusPipeEnumWrapper wrapper; 62 | 63 | log.Write(""); 64 | 65 | wrapper.pContext = pContext; 66 | wrapper.pfnVmbusPipeClientEnumeratePipe = pfn; 67 | 68 | if (!guest || !guest->VmbusPipeClientEnumeratePipes) 69 | return FALSE; 70 | 71 | pContextString = BinToHexString((BYTE*) pContext, 64); 72 | 73 | log.Write("VmbusPipeClientEnumeratePipes: ClassGuid: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x} pContext: %p / %s pfn: %p", 74 | ClassGuid->Data1, ClassGuid->Data2, ClassGuid->Data3, 75 | ClassGuid->Data4[0], ClassGuid->Data4[1], 76 | ClassGuid->Data4[2], ClassGuid->Data4[3], ClassGuid->Data4[4], 77 | ClassGuid->Data4[5], ClassGuid->Data4[6], ClassGuid->Data4[7], 78 | pContext, pContextString, pfn); 79 | 80 | //bSuccess = guest->VmbusPipeClientEnumeratePipes(ClassGuid, (void*) &wrapper, VmbusPipeClientEnumeratePipe); 81 | bSuccess = guest->VmbusPipeClientEnumeratePipes(ClassGuid, pContext, pfn); 82 | 83 | log.Write("VmbusPipeClientEnumeratePipes: bSuccess: %d", bSuccess); 84 | 85 | free(pContextString); 86 | 87 | log.Write(""); 88 | 89 | return bSuccess; 90 | } 91 | 92 | HANDLE VMBUSAPI VmbusPipeClientOpenChannel(PVMBUS_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData, DWORD flags) 93 | { 94 | HANDLE hChannel; 95 | char* VmBusStringA = NULL; 96 | WCHAR* VmBusStringW = NULL; 97 | 98 | log.Write(""); 99 | 100 | if (!guest || !guest->VmbusPipeClientOpenChannel) 101 | return INVALID_HANDLE_VALUE; 102 | 103 | hChannel = guest->VmbusPipeClientOpenChannel(pDeviceInterfaceDetailData, flags); 104 | 105 | VmBusStringW = (WCHAR*) pDeviceInterfaceDetailData->DevicePath; 106 | ConvertFromUnicode(CP_UTF8, 0, VmBusStringW, -1, &VmBusStringA, 0, NULL, NULL); 107 | 108 | log.Write("VmbusPipeClientOpenChannel: pDeviceInterfaceDetailData: cbSize: %d DevicePath: %s", 109 | pDeviceInterfaceDetailData->cbSize, VmBusStringA); 110 | log.Write("VmbusPipeClientOpenChannel: flags: 0x%04X", flags); 111 | 112 | free(VmBusStringA); 113 | 114 | log.Write(""); 115 | 116 | return hChannel; 117 | } 118 | 119 | void VMBUSAPI VmbusPipeClientReadyForChannelNotification(VMBUS_CHANNEL_NOTIFICATION* pChannelNotification, BOOL bEnumeratePipes) 120 | { 121 | log.Write(""); 122 | 123 | DWORD test = WM_CREATE; 124 | 125 | if (!guest || !guest->VmbusPipeClientReadyForChannelNotification) 126 | return; 127 | 128 | guest->VmbusPipeClientReadyForChannelNotification(pChannelNotification, bEnumeratePipes); 129 | 130 | log.Write(""); 131 | } 132 | 133 | VMBUS_CHANNEL_NOTIFICATION* VMBUSAPI VmbusPipeClientRegisterChannelNotification(GUID* ClassGuid, GUID* Guid2, 134 | DWORD notificationFlags, fnVmbusPipeClientChannelNotification pfnDispatchCallback, void* pDispatchContext) 135 | { 136 | GUID* pGuid; 137 | VMBUS_CHANNEL_NOTIFICATION* pChannelNotification; 138 | 139 | log.Write(""); 140 | 141 | if (!guest || !guest->VmbusPipeClientRegisterChannelNotification) 142 | return NULL; 143 | 144 | pGuid = ClassGuid; 145 | 146 | log.Write("\tpClassGuid: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 147 | pGuid->Data1, pGuid->Data2, pGuid->Data3, 148 | pGuid->Data4[0], pGuid->Data4[1], 149 | pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], 150 | pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7]); 151 | 152 | pGuid = Guid2; 153 | 154 | log.Write("\tpGuid2: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 155 | pGuid->Data1, pGuid->Data2, pGuid->Data3, 156 | pGuid->Data4[0], pGuid->Data4[1], 157 | pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], 158 | pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7]); 159 | 160 | log.Write("\tnotificationFlags: 0x%04X", notificationFlags); 161 | 162 | log.Write("\tpfnDispatchCallback: %p pDispatchContext: %p", pfnDispatchCallback, pDispatchContext); 163 | 164 | /** 165 | * Using Device Interfaces: 166 | * http://msdn.microsoft.com/en-us/library/windows/hardware/ff545432/ 167 | */ 168 | 169 | pChannelNotification = guest->VmbusPipeClientRegisterChannelNotification(ClassGuid, Guid2, notificationFlags, 170 | pfnDispatchCallback, pDispatchContext); 171 | 172 | log.Write(""); 173 | 174 | return pChannelNotification; 175 | } 176 | 177 | int VMBUSAPI VmbusPipeClientUnregisterChannelNotification(VMBUS_CHANNEL_NOTIFICATION* pChannelNotification, BOOL bWait) 178 | { 179 | int status; 180 | 181 | log.Write(""); 182 | 183 | if (!guest || !guest->VmbusPipeClientUnregisterChannelNotification) 184 | return -1; 185 | 186 | log.Write("\tbWait: %d", bWait); 187 | 188 | status = guest->VmbusPipeClientUnregisterChannelNotification(pChannelNotification, bWait); 189 | 190 | log.Write(""); 191 | 192 | return status; 193 | } 194 | 195 | BOOL VMBUSAPI VmbusPipeClientWaitChannel(GUID* pGuid1, DWORD arg2, DWORD uElapse, UINT_PTR param) 196 | { 197 | GUID* pGuid; 198 | BOOL bSuccess; 199 | 200 | log.Write(""); 201 | 202 | if (!guest || !guest->VmbusPipeClientWaitChannel) 203 | return FALSE; 204 | 205 | pGuid = pGuid1; 206 | 207 | log.Write("\tpGuid1: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 208 | pGuid->Data1, pGuid->Data2, pGuid->Data3, 209 | pGuid->Data4[0], pGuid->Data4[1], 210 | pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], 211 | pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7]); 212 | 213 | log.Write("\targ2: 0x%4X uElapse: 0x%04X param: 0x%04X\n", arg2, uElapse, param); 214 | 215 | bSuccess = guest->VmbusPipeClientWaitChannel(pGuid1, arg2, uElapse, param); 216 | 217 | log.Write(""); 218 | 219 | return bSuccess; 220 | } 221 | 222 | BOOL VMBUSAPI VmbusPipeServerConnectPipe(HANDLE hDevice, LPOVERLAPPED lpOverlapped) 223 | { 224 | BOOL bSuccess; 225 | 226 | log.Write(""); 227 | 228 | if (!guest || !guest->VmbusPipeServerConnectPipe) 229 | return FALSE; 230 | 231 | log.Write("\thDevice: %p lpOverlapped: %p", hDevice, lpOverlapped); 232 | 233 | bSuccess = guest->VmbusPipeServerConnectPipe(hDevice, lpOverlapped); 234 | 235 | log.Write(""); 236 | 237 | return bSuccess; 238 | } 239 | 240 | int VMBUSAPI VmbusPipeServerOfferChannel(PVMBUS_CHANNEL_INFO pVmbusChannelInfo, DWORD dwFlagsAndAttributes, PHANDLE phChannel) 241 | { 242 | int status; 243 | GUID* pGuid; 244 | char* pBufferString; 245 | char* VmBusStringA = NULL; 246 | WCHAR* VmBusStringW = NULL; 247 | 248 | log.Write(""); 249 | 250 | if (!guest || !guest->VmbusPipeServerOfferChannel) 251 | return -1; 252 | 253 | pGuid = &(pVmbusChannelInfo->VirtualMachineGuid); 254 | pBufferString = BinToHexString((BYTE*) pVmbusChannelInfo->UserDefined, 116); 255 | 256 | log.Write("\tpGuid: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 257 | pGuid->Data1, pGuid->Data2, pGuid->Data3, 258 | pGuid->Data4[0], pGuid->Data4[1], 259 | pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], 260 | pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7]); 261 | 262 | /** 263 | * GUID Present on the Hyper-V Host: 264 | * {cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a} Interface Type? 265 | * HKEY_LOCAL_MACHINE\SYSTEM\DriverDatabase\DeviceIds\VMBUS\{CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} 266 | */ 267 | 268 | pGuid = (GUID*) &(pVmbusChannelInfo->InterfaceTypeGuid); 269 | 270 | log.Write("\tInterfaceTypeGuid: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 271 | pGuid->Data1, pGuid->Data2, pGuid->Data3, 272 | pGuid->Data4[0], pGuid->Data4[1], 273 | pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], 274 | pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7]); 275 | 276 | /** 277 | * GUID Present on the Hyper-V Guest: 278 | * {58f75a6d-d949-4320-99e1-a2a2576d581c} Interface Instance? 279 | */ 280 | 281 | pGuid = (GUID*) &(pVmbusChannelInfo->InterfaceInstanceGuid); 282 | 283 | log.Write("\tInterfaceInstanceGuid: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 284 | pGuid->Data1, pGuid->Data2, pGuid->Data3, 285 | pGuid->Data4[0], pGuid->Data4[1], 286 | pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], 287 | pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7]); 288 | 289 | log.Write("\tunknown01: 0x%04X flags3A: 0x%04X", 290 | pVmbusChannelInfo->unknown01, pVmbusChannelInfo->flags3A); 291 | 292 | log.Write("\tdwFlagsAndAttributes: %04X phChannel: %p", dwFlagsAndAttributes, phChannel); 293 | 294 | log.Write("\tpBufferString: %s", pBufferString); 295 | 296 | status = guest->VmbusPipeServerOfferChannel(pVmbusChannelInfo, dwFlagsAndAttributes, phChannel); 297 | 298 | log.Write(""); 299 | 300 | free(VmBusStringA); 301 | 302 | return status; 303 | } 304 | 305 | const char* DLL_MAIN_REASONS[4] = 306 | { 307 | "DLL_PROCESS_DETACH", 308 | "DLL_PROCESS_ATTACH", 309 | "DLL_THREAD_ATTACH", 310 | "DLL_THREAD_DETACH" 311 | }; 312 | 313 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 314 | { 315 | char logFileName[1024]; 316 | char moduleFileName[1024]; 317 | 318 | DisableThreadLibraryCalls(hinstDLL); 319 | 320 | #ifndef VMBUS_PIPER_STUB 321 | sprintf_s(logFileName, sizeof(logFileName), "%s\\VmBusPipeStub%04X.txt", 322 | "C:\\Windows\\Temp", GetProcessId(GetCurrentProcess())); 323 | #else 324 | sprintf_s(logFileName, sizeof(logFileName), "%s\\VmBusPiperStub%04X.txt", 325 | "C:\\Windows\\Temp", GetProcessId(GetCurrentProcess())); 326 | #endif 327 | 328 | GetModuleFileNameA(NULL, moduleFileName, sizeof(moduleFileName)); 329 | 330 | if (!guest) 331 | { 332 | #ifndef VMBUS_PIPER_STUB 333 | guest = VmBusPipeGuestInit("vmbuspipe_.dll"); 334 | #else 335 | guest = VmBusPipeGuestInit("vmbuspiper_.dll"); 336 | #endif 337 | 338 | log.OpenFile(logFileName, true); 339 | } 340 | 341 | log.Write("DllMain: %s, hModule: %p, fdwReason: %s (%d)", 342 | moduleFileName, hinstDLL, DLL_MAIN_REASONS[fdwReason], fdwReason); 343 | 344 | if (fdwReason == DLL_THREAD_DETACH) 345 | { 346 | log.CloseFile(); 347 | } 348 | 349 | return TRUE; 350 | } 351 | 352 | #ifdef __cplusplus 353 | } 354 | #endif 355 | --------------------------------------------------------------------------------