Error Compiling cpp code in visual studio

-1


I am tr to compile the following code

#include "stdafx.h"
#include <windows.h>
#include <Winbase.h>
#include <Wtsapi32.h>
#include <Userenv.h>
#include <malloc.h>

#pragma comment(lib, "Wtsapi32.lib")
#pragma comment(lib, "Userenv.lib")

#define DLL_EXPORT __declspec(dllexport)

// Use Unicode Character Set
// Code generation Multi-threaded Debug (/MTd)

// Specify the command to run
LPCTSTR fixCmdLine = LPCTSTR(L"C:\\Windows\\System32\\cmd.exe");

bool StartInteractiveProcess(LPTSTR cmd) {
    LPCTSTR cmdDir;
    STARTUPINFO si;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.lpDesktop = LPTSTR(L"winsta0\\default");  // Use the default desktop for GUIs
    cmdDir = LPCTSTR(L"C:\\Windows\\");; // Default directory
    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(pi));
    HANDLE token;
    DWORD sessionId = WTSGetActiveConsoleSessionId();
    if (sessionId == 0xffffffff)  // Noone is logged-in
        return false;
    // This only works if the current user is the system-account (we are probably a Windows-Service)
    HANDLE dummy;
    TOKEN_PRIVILEGES tp;
    LUID luid;
    HANDLE hPToken = NULL;
    HANDLE hProcess = NULL;
    DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
    if (WTSQueryUserToken(sessionId, &dummy)) {
        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
            | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID
            | TOKEN_READ | TOKEN_WRITE, &hPToken))
        {
            return false;
        }
        if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
        {
            return false;
        }
        tp.PrivilegeCount = 1;
        tp.Privileges[0].Luid = luid;
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

        if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &token)) {
            return false;
        }

        if (!SetTokenInformation(token, TokenSessionId, (void*)&sessionId, sizeof(DWORD)))
        {
            return false;
        }
        if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, NULL))
        {
            return false;
        }
        LPVOID pEnv = NULL;
        if (CreateEnvironmentBlock(&pEnv, token, TRUE))
        {
            dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
        }
        else pEnv = NULL;
        // Create process for user with desktop
        if (!CreateProcessAsUser(token, NULL, cmd, NULL, NULL, FALSE, dwCreationFlags, pEnv, NULL, &si, &pi)) {  // The "new console" is necessary. Otherwise the process can hang our main process
            CloseHandle(token);
            return false;
        }
        CloseHandle(dummy);
        CloseHandle(token);
    }
    // Create process for current user
    else if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, cmdDir, &si, &pi))  // The "new console" is necessary. Otherwise the process can hang our main process
        return false;

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return true;
}


bool StartProcess() {
    BOOL b;
    SIZE_T rawSize = (_tcslen(fixCmdLine) + 1) * sizeof(TCHAR);
    LPTSTR commandLine = (LPTSTR)_malloca(rawSize); // Allocate on the stack
    memcpy(commandLine, fixCmdLine, rawSize);
    b = StartInteractiveProcess(commandLine);
    _freea(commandLine);
    return b;
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        StartProcess();
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}


DLL_EXPORT void Gen_000(void)
{
    return;
}

in visual studio, but i am getting the error Error LNK2019 unresolved external symbol _main referenced in function "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) , i have tried setting the windows subsystem to console application as well but issue remains the same.
Any help will be appreciated

c++
visual-studio
winapi
asked on Stack Overflow Feb 4, 2020 by qwe • edited Feb 4, 2020 by drescherjm

1 Answer

1

I created a new project in Visual Studio 2019 of type Dynamic DLL with exports then changed #include "stdafx.h" to #include "pch.h" and added #include <tchar.h> because it was required for _tcslen and after that and the code built fine as a DLL.

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"

#include <windows.h>
#include <Winbase.h>
#include <Wtsapi32.h>
#include <Userenv.h>
#include <malloc.h>
#include <tchar.h>

#pragma comment(lib, "Wtsapi32.lib")
#pragma comment(lib, "Userenv.lib")

#define DLL_EXPORT __declspec(dllexport)

// Use Unicode Character Set
// Code generation Multi-threaded Debug (/MTd)

// Specify the command to run
LPCTSTR fixCmdLine = LPCTSTR(L"C:\\Windows\\System32\\cmd.exe");

bool StartInteractiveProcess(LPTSTR cmd) {
    LPCTSTR cmdDir;
    STARTUPINFO si;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.lpDesktop = LPTSTR(L"winsta0\\default");  // Use the default desktop for GUIs
    cmdDir = LPCTSTR(L"C:\\Windows\\");; // Default directory
    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(pi));
    HANDLE token;
    DWORD sessionId = WTSGetActiveConsoleSessionId();
    if (sessionId == 0xffffffff)  // Noone is logged-in
        return false;
    // This only works if the current user is the system-account (we are probably a Windows-Service)
    HANDLE dummy;
    TOKEN_PRIVILEGES tp;
    LUID luid;
    HANDLE hPToken = NULL;
    HANDLE hProcess = NULL;
    DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
    if (WTSQueryUserToken(sessionId, &dummy)) {
        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
            | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID
            | TOKEN_READ | TOKEN_WRITE, &hPToken))
        {
            return false;
        }
        if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
        {
            return false;
        }
        tp.PrivilegeCount = 1;
        tp.Privileges[0].Luid = luid;
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

        if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &token)) {
            return false;
        }

        if (!SetTokenInformation(token, TokenSessionId, (void*)&sessionId, sizeof(DWORD)))
        {
            return false;
        }
        if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, NULL))
        {
            return false;
        }
        LPVOID pEnv = NULL;
        if (CreateEnvironmentBlock(&pEnv, token, TRUE))
        {
            dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
        }
        else pEnv = NULL;
        // Create process for user with desktop
        if (!CreateProcessAsUser(token, NULL, cmd, NULL, NULL, FALSE, dwCreationFlags, pEnv, NULL, &si, &pi)) {  // The "new console" is necessary. Otherwise the process can hang our main process
            CloseHandle(token);
            return false;
        }
        CloseHandle(dummy);
        CloseHandle(token);
    }
    // Create process for current user
    else if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, cmdDir, &si, &pi))  // The "new console" is necessary. Otherwise the process can hang our main process
        return false;

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return true;
}


bool StartProcess() {
    BOOL b;
    SIZE_T rawSize = (_tcslen(fixCmdLine) + 1) * sizeof(TCHAR);
    LPTSTR commandLine = (LPTSTR)_malloca(rawSize); // Allocate on the stack
    memcpy(commandLine, fixCmdLine, rawSize);
    b = StartInteractiveProcess(commandLine);
    _freea(commandLine);
    return b;
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        StartProcess();
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}


DLL_EXPORT void Gen_000(void)
{
    return;
}
answered on Stack Overflow Feb 4, 2020 by drescherjm

User contributions licensed under CC BY-SA 3.0