Programatically create native DLL using VsDevCmd.bat - winapi

I need to run VsDevCmd.bat with parameters but, when I run this code, VsDevCmd.bat gets executed but no parameters get passed in.
The code is following :
SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = NULL;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\Common7\\Tools\\VsDevCmd.bat";
ShExecInfo.lpParameters = "cl.exe /D_USRDLL /D_WINDLL C:\\MyDLL.cpp C:\\MyDLL.def /link /DLL /OUT:MyDLL.dll";
ShExecInfo.lpDirectory = "C:\\";
ShExecInfo.nShow = SW_MAXIMIZE;
ShExecInfo.hInstApp = NULL;
int nRet = (int) ShellExecuteEx(&ShExecInfo);
if (nRet >= 32)
{
DWORD dw = GetLastError();
char szMsg[250];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, dw, 0, szMsg, sizeof(szMsg), NULL);
MessageBox(hWnd, szMsg, "ERROR", MB_ICONEXCLAMATION | MB_OK);
}
WaitForSingleObject (ShExecInfo.hProcess, INFINITE);

If you want to compile a DLL from within your application and you're using Visual Studio why don't you execute devenv to build a solution file containing the DLL you want to build?
Have a look at the documentation of devenv.
So your code should look like this:
SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = NULL;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = "devenv";
ShExecInfo.lpParameters = "/build yoursolution.sln";
ShExecInfo.lpDirectory = "C:\\";
ShExecInfo.nShow = SW_MAXIMIZE;
ShExecInfo.hInstApp = NULL;
if (ShellExecuteEx(&ShExecInfo) != FALSE)
{
WaitForSingleObject (ShExecInfo.hProcess, INFINITE);
DWORD exitCode;
if (GetExitCodeProcess(ShExecInfo.hProcess, &exitCode) != FALSE)
{
/*
** Process exit code of devenv
** I haven't found something on the internet but I assume that exitCode=0 means success!
*/
if (exitCode != 0)
{
MessageBox(hWnd, "devenv failed!", "ERROR", MB_ICONEXCLAMATION | MB_OK);
}
}
else
{
DWORD dw = GetLastError();
char szMsg[250];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, dw, 0, szMsg, sizeof(szMsg), NULL);
MessageBox(hWnd, szMsg, "ERROR", MB_ICONEXCLAMATION | MB_OK);
}
CloseHandle(ShExecInfo.hProcess);
}
else
{
DWORD dw = GetLastError();
char szMsg[250];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, dw, 0, szMsg, sizeof(szMsg), NULL);
MessageBox(hWnd, szMsg, "ERROR", MB_ICONEXCLAMATION | MB_OK);
}

Related

Error creating a screenshot in the winapi service

I have a client application written in C++, and a server written in Python. This application has several functions, including getting a screenshot of the client's desktop and getting this file on the server.
When I run these programs without any add-ons, everything works. I need to upload my client to the service, and I do it through CreateProcess[client file] inside of my service. All other functions besides the screenshot work with this approach.
Server code, getting a screenshot:
if (cState == State.GETTING_SCREENSHOT):
message = "SCREENSHOT".encode('utf-8')
MySend(client_sock , message)
curr_number = 0
with open("settings.txt" , 'r') as settings:
curr_number_str = settings.readline()
curr_number = int(curr_number_str)
with open("settings.txt" , 'w') as settings:
settings.write(str(curr_number + 1))
screenshot_file = str(curr_number) + ".png"
with open(screenshot_file , 'wb') as file:
while True:
data = MyRecv(client_sock , 40000)
data_arr = bytearray(data)
if (data_arr[:10] == b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'):
continue
if (b'ENDOFF' in data):
break
file.write(data)
cState = State.INPUT_COMMAND
Client code:
case SENDING_SCREENSHOT_IN_PROGRESS:
{
wchar_t PathToLocalAppDataFolder[MAX_PATH];
if (FAILED(SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, PathToLocalAppDataFolder))) {
LoadMessage("Error in ShGetFolderPathW");
break;
}
std::wstring PathToScreenshot = std::wstring(PathToLocalAppDataFolder) + L"\\1.png";
if (!SaveScreen(PathToScreenshot.c_str())) {
LoadMessage("SaveScreen api-func failed");
break;
}
HANDLE hFile = CreateFile(PathToScreenshot.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
LoadMessage("Can not open screenshot file");
break;
}
DWORD dwRead = 1;
BYTE buffSend[BIG_BUFFLEN];
while (dwRead) {
ZeroMemory(buffSend, BIG_BUFFLEN);
dwRead = 0;
ReadFile(hFile, buffSend, BIG_BUFFLEN, &dwRead, NULL);
MySend(ClientSoc, (char*)buffSend, dwRead, 0);
}
CloseHandle(hFile);
char message[SMALL_BUFFLEN] = "ENDOFFILE";
MySend(ClientSoc, message, BIG_BUFFLEN, 0);
DeleteFile(PathToScreenshot.c_str());
cState = WAITING_FOR_INCOMING_COMMAND;
break;
}
Service code:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
#include <shlobj_core.h>
#include <string>
#include "api.h"
#include <fstream>
#pragma comment(lib , "API.lib")
#pragma warning(disable:4996)
wchar_t SERVICE_NAME[] = L"RemoteController";
bool isCreate = FALSE;
SERVICE_STATUS ServiceStatus = { 0 };
SERVICE_STATUS_HANDLE hServiceStatus; //StatusHandle
HANDLE ServiceStopEvent = INVALID_HANDLE_VALUE;
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv);
VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode);
DWORD WINAPI ServiceWorkerThreadEntry(LPVOID lpParam);
VOID Install(VOID);
BOOL dirExists(const wchar_t* dir_path);
int main(int argc, char* argv[]) {
FreeConsole();
Install();
SERVICE_TABLE_ENTRY ServiceTable[] = {
{SERVICE_NAME , (LPSERVICE_MAIN_FUNCTION)ServiceMain} ,
{NULL , NULL}
};
if (StartServiceCtrlDispatcher(ServiceTable) == FALSE) {
LoadMessage("Service.exe : StartServiceCtrlDIspathcer error");
return GetLastError();
}
return 0;
}
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv) {
DWORD Status = E_FAIL;
hServiceStatus = RegisterServiceCtrlHandler(
SERVICE_NAME,
ServiceCtrlHandler
);
if (hServiceStatus == NULL) {
LoadMessage("Service.exe : RegisterServiceCtrlHandler failed");
return;
}
ZeroMemory(&ServiceStatus, sizeof(ServiceStatus));
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
ServiceStatus.dwControlsAccepted = 0;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
if (SetServiceStatus(hServiceStatus, &ServiceStatus) == FALSE) {
LoadMessage("Service.exe : SetServiceStatus failed");
}
ServiceStopEvent = CreateEventW(NULL, TRUE, FALSE, L"RemoteControllerEvent");
if (ServiceStopEvent == NULL) {
ServiceStatus.dwControlsAccepted = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = GetLastError();
ServiceStatus.dwCheckPoint = 1;
if (SetServiceStatus(hServiceStatus, &ServiceStatus) == FALSE) {
LoadMessage("Service.exe : SetServiceStatus failed");
return;
}
}
//start
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
if (SetServiceStatus(hServiceStatus, &ServiceStatus) == FALSE) {
LoadMessage("Service.exe : SetServiceStatus failed");
}
HANDLE hThread = CreateThread(NULL, 0, ServiceWorkerThreadEntry, NULL, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(ServiceStopEvent);
ServiceStatus.dwControlsAccepted = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCheckPoint = 3;
if (!SetServiceStatus(hServiceStatus, &ServiceStatus) == FALSE) {
LoadMessage("Service.exe : SetServiceStatus failed");
}
return;
}
VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode) {
switch (CtrlCode) {
case SERVICE_CONTROL_STOP:
if (ServiceStatus.dwCurrentState != SERVICE_RUNNING) break;
ServiceStatus.dwControlsAccepted = 0;
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCheckPoint = 4;
if (SetServiceStatus(hServiceStatus, &ServiceStatus) == FALSE) {
LoadMessage("Service.exe : SetServiceStatus failed");
return;
}
SetEvent(ServiceStopEvent);
default:
break;
}
}
BOOL dirExists(const wchar_t* dir_path) {
DWORD dwAttributes = GetFileAttributes(dir_path);
if (dwAttributes == INVALID_FILE_ATTRIBUTES) return FALSE;
if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) return TRUE;
return FALSE;
}
VOID Install(VOID) {
SC_HANDLE schSCManager;
SC_HANDLE schService;
wchar_t curr_path[MAX_PATH];
if (!GetModuleFileName(NULL, curr_path, MAX_PATH)) {
LoadMessage("Service.exe : GetModuleFilename failed");
return;
}
schSCManager = OpenSCManager(
NULL, NULL, SC_MANAGER_ALL_ACCESS
);
if (schSCManager == NULL) {
LoadMessage("Service.exe : OpenSCManager failed[with SC_MANAGER_ALL_ACCESS]");
return;
}
schService = CreateService(
schSCManager, SERVICE_NAME, SERVICE_NAME, SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
curr_path, NULL, NULL, NULL, NULL, NULL);
if (schService == NULL) {
LoadMessage("Service.exe : CreateService failed");
CloseServiceHandle(schSCManager);
return;
}
if (StartService(schService , 0 , NULL) == 0){
LoadMessage("Service.exe : Start service failed");
CloseServiceHandle(schSCManager);
CloseServiceHandle(schService);
return;
}
LoadMessage("\tService instaled");
CloseServiceHandle(schSCManager);
CloseServiceHandle(schService);
}
DWORD WINAPI ServiceWorkerThreadEntry(LPVOID lpParam) {
if (isCreate) {
return ERROR_SUCCESS;
}
isCreate = TRUE;
wchar_t ProgramToRun[MAX_PATH];
ZeroMemory(ProgramToRun , sizeof(ProgramToRun));
SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, 0, ProgramToRun);
std::wstring tmp = std::wstring(ProgramToRun) + L"\\RemoteController\\MainClient.exe";
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
CreateProcess(tmp.c_str(), NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
return ERROR_SUCCESS;
}

Inject Dll and Create Thread When Launching Process with DEBUG_PROCESS on Windows

In the past, when not operating as a debugger, I have used this approach to inject a DLL and Create Thread In a Process which has worked well for me. Note: I need this to work on Windows XP 32-bit only (Although prefer methods that also work on latested OS):
#include <iostream>
#include <Windows.h>
#include <Psapi.h>
#include <pathcch.h>
#include "log.h"
#include <wchar.h>
#pragma comment(lib,"Pathcch.lib")
typedef void (WINAPI* PHookInit)();
HMODULE WINAPI GetRemoteModuleHandle(HANDLE hProcess, LPCWSTR lpModuleName)
{
HMODULE* ModuleArray = NULL;
DWORD ModuleArraySize = 100;
DWORD NumModules = 0;
WCHAR lpModuleNameCopy[MAX_PATH] = { 0 };
WCHAR ModuleNameBuffer[MAX_PATH] = { 0 };
if (lpModuleName == NULL) return NULL;
ModuleArray = new HMODULE[ModuleArraySize];
if (ModuleArray == NULL) return NULL;
if (!EnumProcessModulesEx(hProcess, ModuleArray,
ModuleArraySize * sizeof(HMODULE), &NumModules, LIST_MODULES_ALL))
{
DWORD dwResult = GetLastError();
LOG_E("Unable to get modules in process Error %i", dwResult);
}
else
{
NumModules /= sizeof(HMODULE);
if (NumModules > ModuleArraySize)
{
delete[] ModuleArray;
ModuleArray = NULL;
ModuleArray = new HMODULE[NumModules];
if (ModuleArray != NULL)
{
ModuleArraySize = NumModules;
if (EnumProcessModulesEx(
hProcess,
ModuleArray,
ModuleArraySize * sizeof(HMODULE),
&NumModules,
LIST_MODULES_ALL))
{
NumModules /= sizeof(HMODULE);
}
}
}
}
for (DWORD i = 0; i <= NumModules; ++i)
{
GetModuleBaseNameW(hProcess, ModuleArray[i],
ModuleNameBuffer, MAX_PATH);
LOG_I("Module = '%s'", ModuleNameBuffer);
if (_wcsicmp(ModuleNameBuffer, lpModuleName) == 0)
{
LOG_I("Target module found!");
HMODULE TempReturn = ModuleArray[i];
delete[] ModuleArray;
return TempReturn;
}
}
if (ModuleArray != NULL)
delete[] ModuleArray;
return NULL;
}
int wmain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, INT nCmdShow)
{
LPWSTR* argv;
int argc;
argv = CommandLineToArgvW(GetCommandLineW(), &argc);
LOG_I(L"LaunchAndInject Started");
wchar_t CurrentProcessDirectory[MAX_PATH];
wchar_t TargetDllFilename[MAX_PATH];
#ifdef _WIN64
wchar_t TargetDllName[] = L"HookInit64.dll";
#else
wchar_t TargetDllName[] = L"HookInit32.dll";
#endif
char TargetFunctionName[] = "HookInit";
STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD dwTimeOut = 60000;
if (argc < 2)
{
LOG_E(L"No command line parameters specified.");
return 1;
}
wchar_t* cmd_pos = wcsstr(GetCommandLine(), argv[1]) - 1;
if (cmd_pos)
{
if (cmd_pos[0] != L'"')
{
cmd_pos += 1;
}
}
LOG_I(L"Command Line='%s'", cmd_pos);
DWORD dwResult = GetModuleFileNameW(NULL, CurrentProcessDirectory, MAX_PATH);
PathCchRemoveFileSpec(CurrentProcessDirectory, MAX_PATH);
PathCchCombine(TargetDllFilename, MAX_PATH, CurrentProcessDirectory, TargetDllName);
LOG_I(L"Current Directory='%s' Result='%i'", CurrentProcessDirectory, dwResult);
LOG_I(L"Target DLL='%s'", TargetDllFilename);
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// Start the child process.
if (!CreateProcess(NULL, // No module name (use command line)
cmd_pos, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_SUSPENDED, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si,
&pi)
)
{
dwResult = GetLastError();
LOG_E(L"CreateProcess Failed with Error #%i", dwResult);
return 1;
}
LOG_I(L"Suspended Process created with PID '%i'", pi.dwProcessId);
LOG_I("Loading Target DLL");
// load DLL in this process first so we can calculate function offset
HMODULE hModuleTargetDll = LoadLibraryW(TargetDllFilename);
__int64 iTargetProcAddress = 0;
__int64 iTargetOffset = 0;
if (hModuleTargetDll != NULL)
{
iTargetProcAddress = (__int64)GetProcAddress(hModuleTargetDll, TargetFunctionName);
iTargetOffset = iTargetProcAddress - (__int64)hModuleTargetDll;
LOG_I("Function Target Offset = %i", iTargetOffset);
}
HMODULE hModuleKernel32 = GetModuleHandle(L"kernel32.dll");
LPVOID pLoadLibraryAddress = NULL;
if (hModuleKernel32 != NULL)
{
pLoadLibraryAddress = (LPVOID)GetProcAddress(hModuleKernel32, "LoadLibraryW");
}
else
{
LOG_E("Unable to get module handle for kernel32.dll");
}
if (pLoadLibraryAddress == NULL) {
dwResult = GetLastError();
LOG_E(L"ERROR: Unable to find LoadLibraryW in Kernel32.dll Error: %i", dwResult);
}
// allocate space for LoadLibrary arguments in target process
size_t iTargetDllSize = (wcslen(TargetDllFilename) + 1) * sizeof(wchar_t);
LPVOID pLoadLibraryArguments = (LPVOID)VirtualAllocEx(
pi.hProcess,
NULL,
iTargetDllSize,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (pLoadLibraryArguments == NULL) {
dwResult = GetLastError();
LOG_E(L"ERROR: Unable to allocate %i bytes in target process Error: %i",
iTargetDllSize,
dwResult);
}
else
{
if (!WriteProcessMemory(
pi.hProcess,
pLoadLibraryArguments,
TargetDllFilename,
iTargetDllSize,
NULL))
{
dwResult = GetLastError();
LOG_E("Unable to write bytes into target process address space. Error %i", dwResult);
}
else
{
LOG_I("LoadLibrary Arguments Successfully written to target process address space.");
HANDLE hThread = NULL;
if (pLoadLibraryAddress != NULL)
{
hThread = CreateRemoteThread(
pi.hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)pLoadLibraryAddress,
pLoadLibraryArguments,
NULL,
NULL);
}
if (hThread == NULL) {
dwResult = GetLastError();
LOG_E("The remote thread calling LoadLibrary could not be created. Error %i", dwResult);
}
else {
LOG_I("Remote Thread for LoadLibrary successfully created.");
dwResult = WaitForSingleObject(hThread, dwTimeOut);
if (dwResult == WAIT_FAILED)
{
dwResult = GetLastError();
LOG_I("Remote Thread for LoadLibrary Failed Error %i", dwResult);
}
if (dwResult == WAIT_TIMEOUT)
{
LOG_E("Remote Thread for LoadLibrary in hung state");
}
HMODULE hInjected = GetRemoteModuleHandle(pi.hProcess, TargetDllName);
PHookInit pHookInit = NULL;
if (hInjected == NULL)
{
LOG_E("Unable to get module handle in target process");
}
else
{
pHookInit = (PHookInit)((__int64)hInjected + iTargetOffset);
}
if (pHookInit != NULL)
{
LOG_I("Running HookInit function!");
hThread = CreateRemoteThread(pi.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pHookInit, NULL, NULL, NULL);
if (hThread == NULL)
{
dwResult = GetLastError();
LOG_E("The remote thread calling HookInit could not be created. Error %i", dwResult);
}
else
{
LOG_I("HookInit function started!");
dwResult = WaitForSingleObject(hThread, dwTimeOut);
if (dwResult == WAIT_FAILED)
{
dwResult = GetLastError();
LOG_I("Remote Thread for HookInit Failed Error %i", dwResult);
}
if (dwResult == WAIT_TIMEOUT)
{
LOG_E("Remote Thread for HookInit in hung state");
}
}
}
}
}
}
LOG_I("Resuming threads in target process");
ResumeThread(pi.hThread);
LOG_I("Process Resumed. Waiting for process to exit");
dwResult = WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exitCode = 0;
if (GetExitCodeProcess(pi.hProcess, &exitCode))
{
LOG_I("Process Terminated with exit code %i", exitCode);
}
else
{
LOG_W("Process terminated, unable to determine Exit Code");
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
However in this case I need to capture various debug events of process, and hook the process via Image Execution Debugger registry key (as I don't have control of its launch), including for child processes. While the inject code works fine with previous approach, when launched as a debugger I'm trying to work out how to create the remote thread (and have it complete) before resuming main application execution. While I can create the remote thread fine, it hangs when trying to wait for its completion when using the approach below. I'm trying to work out what method to use to create my remote thread and wait for it to complete before resuming main application.
// Start the child process.
if (!CreateProcess(NULL, // No module name (use command line)
cmd_pos, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
DEBUG_PROCESS, // Debug
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si,
&pi)
)
{
dwResult = GetLastError();
LOG_E(L"CreateProcess Failed with Error #%i", dwResult);
return 1;
}
DebugSetProcessKillOnExit(TRUE);
DebugActiveProcess(pi.dwProcessId);
DEBUG_EVENT DebugEv = { 0 };
DWORD dwContinueStatus = DBG_CONTINUE; // exception continuation
LOG_I(L"Debug Process created with PID '%i'", pi.dwProcessId);
LOG_I("Loading Target DLL");
/*
// load DLL in this process first so we can calculate function offset
*/
for (;;)
{
// Wait for a debugging event to occur. The second parameter indicates
// that the function does not return until a debugging event occurs.
WaitForDebugEvent(&DebugEv, INFINITE);
// Process the debugging event code.
switch (DebugEv.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
// Process the exception code. When handling
// exceptions, remember to set the continuation
// status parameter (dwContinueStatus). This value
// is used by the ContinueDebugEvent function.
OutputDebugString(L"EXCEPTION\r\n");
switch (DebugEv.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
// First chance: Pass this on to the system.
// Last chance: Display an appropriate error.
break;
case EXCEPTION_BREAKPOINT:
// First chance: Display the current
// instruction and register values.
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
// First chance: Pass this on to the system.
// Last chance: Display an appropriate error.
break;
case EXCEPTION_SINGLE_STEP:
// First chance: Update the display of the
// current instruction and register values.
break;
case DBG_CONTROL_C:
// First chance: Pass this on to the system.
// Last chance: Display an appropriate error.
break;
default:
// Handle other exceptions.
break;
}
break;
case CREATE_THREAD_DEBUG_EVENT:
OutputDebugString(L"CREATETHREAD\r\n");
// dwContinueStatus = OnCreateThreadDebugEvent(&DebugEv);
break;
case CREATE_PROCESS_DEBUG_EVENT:
dwContinueStatus = OnCreateProcessDebugEvent(&DebugEv);
break;
case EXIT_THREAD_DEBUG_EVENT:
// Display the thread's exit code.
OutputDebugString(L"EXITTHREAD\r\n");
// dwContinueStatus = OnExitThreadDebugEvent(&DebugEv);
break;
case EXIT_PROCESS_DEBUG_EVENT:
// Display the process's exit code.
OutputDebugString(L"EXITPROCESS\r\n");
// dwContinueStatus = OnExitProcessDebugEvent(&DebugEv);
break;
case LOAD_DLL_DEBUG_EVENT:
// Read the debugging information included in the newly
// loaded DLL. Be sure to close the handle to the loaded DLL
// with CloseHandle.
OutputDebugString(L"LOADDLL\r\n");
// dwContinueStatus = OnLoadDllDebugEvent(&DebugEv);
break;
case UNLOAD_DLL_DEBUG_EVENT:
// Display a message that the DLL has been unloaded.
OutputDebugString(L"UNLOADDLL\r\n");
// dwContinueStatus = OnUnloadDllDebugEvent(&DebugEv);
break;
case OUTPUT_DEBUG_STRING_EVENT:
OutputDebugString(L"OUTPUTDEBUG\r\n");
// Display the output debugging string.
// dwContinueStatus = OnOutputDebugStringEvent(&DebugEv);
break;
case RIP_EVENT:
OutputDebugString(L"RIP\r\n");
// dwContinueStatus = OnRipEvent(&DebugEv);
break;
}
// Resume executing the thread that reported the debugging event.
OutputDebugString(L"CONTINUE\r\n");
ContinueDebugEvent(DebugEv.dwProcessId,
DebugEv.dwThreadId,
dwContinueStatus);
}
DWORD OnCreateProcessDebugEvent(const LPDEBUG_EVENT DebugEv)
{
DWORD dwResult;
HMODULE hModuleTargetDll = LoadLibraryW(TargetDllFilename);
__int64 iTargetProcAddress = 0;
__int64 iTargetOffset = 0;
if (hModuleTargetDll != NULL)
{
iTargetProcAddress = (__int64)GetProcAddress(hModuleTargetDll, TargetFunctionName);
iTargetOffset = iTargetProcAddress - (__int64)hModuleTargetDll;
LOG_I("Function Target Offset = %i", iTargetOffset);
}
HMODULE hModuleKernel32 = GetModuleHandle(L"kernel32.dll");
LPVOID pLoadLibraryAddress = NULL;
if (hModuleKernel32 != NULL)
{
pLoadLibraryAddress = (LPVOID)GetProcAddress(hModuleKernel32, "LoadLibraryW");
}
else
{
LOG_E("Unable to get module handle for kernel32.dll");
}
if (pLoadLibraryAddress == NULL) {
dwResult = GetLastError();
LOG_E(L"ERROR: Unable to find LoadLibraryW in Kernel32.dll Error: %i", dwResult);
}
// allocate space for LoadLibrary arguments in target process
size_t iTargetDllSize = (wcslen(TargetDllFilename) + 1) * sizeof(wchar_t);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, DebugEv->dwProcessId);
LPVOID pLoadLibraryArguments = (LPVOID)VirtualAllocEx(
hProcess,
NULL,
iTargetDllSize,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (pLoadLibraryArguments == NULL) {
dwResult = GetLastError();
LOG_E(L"ERROR: Unable to allocate %i bytes in target process Error: %i",
iTargetDllSize,
dwResult);
}
else
{
if (!WriteProcessMemory(
hProcess,
pLoadLibraryArguments,
TargetDllFilename,
iTargetDllSize,
NULL))
{
dwResult = GetLastError();
LOG_E("Unable to write bytes into target process address space. Error %i", dwResult);
}
else
{
LOG_I("LoadLibrary Arguments Successfully written to target process address space.");
HANDLE hThread = NULL;
if (pLoadLibraryAddress != NULL)
{
hThread = CreateRemoteThread(
hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)pLoadLibraryAddress,
pLoadLibraryArguments,
NULL,
NULL);
}
if (hThread == NULL) {
dwResult = GetLastError();
LOG_E("The remote thread calling LoadLibrary could not be created. Error %i", dwResult);
}
else {
LOG_I("Remote Thread for LoadLibrary successfully created.");
ResumeThread(hThread);
dwResult = WaitForSingleObject(hThread, dwTimeOut);
if (dwResult == WAIT_FAILED)
{
dwResult = GetLastError();
LOG_I("Remote Thread for LoadLibrary Failed Error %i", dwResult);
}
if (dwResult == WAIT_TIMEOUT)
{
LOG_E("Remote Thread for LoadLibrary in hung state");
}
HMODULE hInjected = GetRemoteModuleHandle(hProcess, TargetDllName);
PHookInit pHookInit = NULL;
if (hInjected == NULL)
{
LOG_E("Unable to get module handle in target process");
}
else
{
pHookInit = (PHookInit)((__int64)hInjected + iTargetOffset);
}
if (pHookInit != NULL)
{
LOG_I("Running HookInit function!");
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pHookInit, NULL, NULL, NULL);
if (hThread == NULL)
{
dwResult = GetLastError();
LOG_E("The remote thread calling HookInit could not be created. Error %i", dwResult);
}
else
{
LOG_I("HookInit function started!");
dwResult = WaitForSingleObject(hThread, dwTimeOut);
if (dwResult == WAIT_FAILED)
{
dwResult = GetLastError();
LOG_I("Remote Thread for HookInit Failed Error %i", dwResult);
}
if (dwResult == WAIT_TIMEOUT)
{
LOG_E("Remote Thread for HookInit in hung state");
}
}
}
}
}
}
return DBG_CONTINUE;
}

how to control device disable with source code in visual studio 2019?

my pc is OS: windows10 x64.
i want to enable / disable virtual com port using code.
actually, error is happened below,
errorcode = #define ERROR_ACCESS_DENIED 5L
in window10, i cannot not control device disable or enable ???
or source code is wrong ??
if you know that, please help me
used code is below. that is get from stackoverflow.com
bool COhCoachView::ControlDeviceDriver(bool bStatus) {
IN LPTSTR HardwareId;
//HardwareId = L"DAUDIO\\FUNC_01&VEN_10DE&DEV_0018&SUBSYS_10DE0101";
// dock device name : \\?\USB#VID_0462&PID_5740#00000000001A#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
CString debug;
char* ptr;
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)"ControlDeviceDriver");
DWORD NewState;
if (bStatus) {
NewState = DICS_ENABLE;
}
else {
NewState = DICS_DISABLE;
}
DWORD i, err;
bool found = false;
HDEVINFO hDevInfo;
SP_DEVINFO_DATA spDevInfoData;
hDevInfo = SetupDiGetClassDevs(NULL, 0, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
printf("blad1");
return false;
}
spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
{
DWORD DataT;
LPTSTR p, buffer = NULL;
DWORD buffersize = 0;
// get all devices info
while (!SetupDiGetDeviceRegistryProperty(hDevInfo,
&spDevInfoData,
SPDRP_HARDWAREID,
&DataT,
(PBYTE)buffer,
buffersize,
&buffersize))
{
if (GetLastError() == ERROR_INVALID_DATA) {
break;
}
else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
if (buffer)
LocalFree(buffer);
buffer = (TCHAR*)LocalAlloc(LPTR, buffersize);
}
else {
goto cleanup_DeviceInfo;
}
}
if (GetLastError() == ERROR_INVALID_DATA)
continue;
ptr = strstr(buffer, "VID_0462&PID_5740");
if (ptr != NULL)
{
debug.Format("device name: %s", buffer);
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)debug);
found = true;
}
//find device with HardwerId
/*
for (p = buffer; *p && (p < &buffer[buffersize]); p += lstrlen(p) + sizeof(TCHAR)) {
//debug.Format("device name: %s", p);
//::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)debug);
if (!_tcscmp(HardwareId, p)) {
found = true;
break;
}
}
*/
if (buffer)
LocalFree(buffer);
// if device found change it's state
if (found)
{
SP_PROPCHANGE_PARAMS params;
params.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
params.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
params.Scope = DICS_FLAG_GLOBAL;
params.StateChange = NewState;
// setup proper parameters
if (!SetupDiSetClassInstallParams(hDevInfo, &spDevInfoData, &params.ClassInstallHeader, sizeof(params))) {
DWORD errorcode = GetLastError();
debug.Format("==== error %x ======", errorcode);
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)debug);
}
// use parameters
if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &spDevInfoData)) {
DWORD errorcode = GetLastError(); // error here
if (errorcode == 0x05)
{
for (int i = 0; i < 5; i++)
{
if (SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &spDevInfoData))
{
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)"retry succeeded for disabling device");
break;
}
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)"retry failed for disabling device");
Sleep(20);
}
}
debug.Format("==== error2 %x ======", errorcode);
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)debug);
}
switch (NewState) {
case DICS_DISABLE:
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)"Device OFF");
printf("off");
break;
case DICS_ENABLE:
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)"Device ON");
printf("on");
break;
}
break;
}
}
cleanup_DeviceInfo:
err = GetLastError();
SetupDiDestroyDeviceInfoList(hDevInfo);
SetLastError(err);
return true;
return true;
}
thanks a lot

Running WSReset.exe with CreateProcess or system

I'm trying to run WSReset.exe on Windows 10 but keep getting a file not found error. The WSReset.exe is definitely in "C:\Windows\System32\WSReset.exe" but a CMD/Powershell window started from my program cannot seem to find it. But a CMD/Powershell window started outside my program does execute the file.
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
ZeroMemory(&processInfo, sizeof(processInfo));
int t = (CreateProcess(L"C:/Windows/System32/wsreset.exe", L"", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo));
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
or
SHELLEXECUTEINFO ShExecInfo = { 0 };
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = L"C:/Windows/System32/wsreset.exe";
ShExecInfo.lpParameters = L"";
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOW;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
Produces the "Windows cannot find..." error message.
The app is 32 bits. Oddly System32 = 64 bit, SysWOW64 = 32 bit. So when I call "C:/Windows/System32/wsreset.exe" windows will turn it into "C:/Windows/SysWOW64/wsreset.exe" and there is no wsreset.exe at that location.
The solution is to disable redirection before calling CreateProcess/ShellExecuteEx/System.
//Disable redirection
PVOID OldValue = NULL;
Wow64DisableWow64FsRedirection(&OldValue);
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo = { 0 };
CreateProcess(L"C:/Windows/System32/WSReset.exe", L"", NULL, NULL, FALSE, 0, NULL, NULL, &info, &processInfo);
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
//Enable redirection (important, otherwise program can crash)
Wow64RevertWow64FsRedirection(OldValue);

c++ check installed programms

How do I list all programs installed on my computer? I've tried using the MsiEnumProducts and MsiGetProductInfo functions, but they do not return a full list of installed applications like I see in "Add/Remove Programs".
Enumerate the registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
bool EnumInstalledSoftware(void)
{
HKEY hUninstKey = NULL;
HKEY hAppKey = NULL;
WCHAR sAppKeyName[1024];
WCHAR sSubKey[1024];
WCHAR sDisplayName[1024];
WCHAR *sRoot = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
long lResult = ERROR_SUCCESS;
DWORD dwType = KEY_ALL_ACCESS;
DWORD dwBufferSize = 0;
//Open the "Uninstall" key.
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, sRoot, 0, KEY_READ, &hUninstKey) != ERROR_SUCCESS)
{
return false;
}
for(DWORD dwIndex = 0; lResult == ERROR_SUCCESS; dwIndex++)
{
//Enumerate all sub keys...
dwBufferSize = sizeof(sAppKeyName);
if((lResult = RegEnumKeyEx(hUninstKey, dwIndex, sAppKeyName,
&dwBufferSize, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS)
{
//Open the sub key.
wsprintf(sSubKey, L"%s\\%s", sRoot, sAppKeyName);
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, sSubKey, 0, KEY_READ, &hAppKey) != ERROR_SUCCESS)
{
RegCloseKey(hAppKey);
RegCloseKey(hUninstKey);
return false;
}
//Get the display name value from the application's sub key.
dwBufferSize = sizeof(sDisplayName);
if(RegQueryValueEx(hAppKey, L"DisplayName", NULL,
&dwType, (unsigned char*)sDisplayName, &dwBufferSize) == ERROR_SUCCESS)
{
wprintf(L"%s\n", sDisplayName);
}
else{
//Display name value doe not exist, this application was probably uninstalled.
}
RegCloseKey(hAppKey);
}
}
RegCloseKey(hUninstKey);
return true;
}

Resources