2

I'm writing a simple C++ WIN32 API program that install&start a windows service. I'm using SEH __try&__finaly in my code. Unfortunately I'm getting a known error as below:

error C2712 Cannot use __try in functions that require object unwinding.

I tried to solve it with some familiar methods, like moving the SEH code from the main function into another function, or playing error with the project properties : Enable C++ Exceptions. but nothing worked. anyway, this is the source:

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
using namespace std;

#define ERROR -1
#define SUCCESS 0;

string GetLastErrorAsString(DWORD errorMessageID);
DWORD Service();
int WINAPI main(void)
{
    wcout << "STARTING THE SERVICE INSTALLATION PROCESS..." << endl;
    Service();
    wcout << "FINISHED !" << endl;
    wcout << "ENTER ANYTHING TO EXIT..." << endl;
    getchar();
    return 0;
}

**DWORD Service() {** << the line that the error is pointing at
    SC_HANDLE hSCManager = NULL;
    SC_HANDLE hService = NULL;
    DWORD start_service = 0;
    LPCTSTR ExePath = TEXT("C:\Program Files\WinSecurityCheck.exe");
    __try { //guarded code here 

        hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
        if (hSCManager == NULL) {
            __leave;
        }
        hService = CreateService(hSCManager, TEXT("WinSecurityCheck"),
        TEXT("WinSeurityCheck"),
        SERVICE_START | DELETE | SERVICE_STOP,
        SERVICE_WIN32_OWN_PROCESS,
        SERVICE_AUTO_START,
        SERVICE_ERROR_IGNORE,
        ExePath, NULL, NULL, NULL, NULL, NULL);
        if (hService == NULL) {
            __leave;
        }
        start_service = StartService(hService, 0, NULL);
        if (start_service == 0) {
            __leave;
        }
    }
    __finally { //termination code
        if (!AbnormalTermination()) {
            wcout << TEXT("Successfully Created & Started The Desired     Service") << endl;
            CloseServiceHandle(hSCManager);
            CloseServiceHandle(hService);
            return SUCCESS;
        }
        if (hSCManager == NULL) {

            wcout << TEXT("Error Open SC Manager") << endl;
            GetLastErrorAsString(GetLastError());
            return ERROR;
        }
        if (hService)
        {
            wcout << TEXT("Error Creating Service") << endl;
            GetLastErrorAsString(GetLastError());

            CloseServiceHandle(hSCManager);
            return ERROR;
        }
        if (start_service == 0)
        {
            wcout << TEXT("Error Starting Service") << endl;
            GetLastErrorAsString(GetLastError());
            CloseServiceHandle(hService);
            CloseServiceHandle(hSCManager);
            return ERROR;
        }
    }
}

string GetLastErrorAsString(DWORD errorMessageID) {
    LPTSTR formatMessage;
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS     | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, errorMessageID, NULL, formatMessage, 64,       NULL);
    wcout << formatMessage << endl;
    LocalFree(formatMessage);
}
  • 3
    Basically don't mix structured exception handling and C++. Most calls into `std` can throw exceptions and require stack unwinding. Why do you need SEH at all ? – Richard Critten Nov 09 '17 at 09:56
  • 3
    It's unclear, why you are using SEH in a C++ application. That's totally not what you want. If you are doing so because you need the `__finally` semantics, simply switch to C++ exception handling and use RAII-type wrappers for cleanup. Besides, you are calling `GetLastError` too late. The value returned is no longer guaranteed to be valid at that point. You want to call it *immediately* after arriving at a condition where it's documented to return valid information, without interspersing *any* code (like you are). – IInspectable Nov 09 '17 at 10:03
  • So, what is your question? You just stated that you got an error. And that error is completely logical. Why do you disagree, and what do you want instead? – underscore_d Nov 09 '17 at 10:04
  • first of all, I'm reading this book you probably been heard of "windows internals" and they say it's totaly fine to use SEH in C++ applications, and give an examples also. Second, if that's not true I would like to know why, and what are the altenatives. And also why is the error logical ? @RichardCritten –  Nov 09 '17 at 11:01
  • Be nice to know the line number of the error please. And/or mark it in the code above. – Richard Critten Nov 09 '17 at 11:34
  • 1
    You *can* use SEH in a C++ application, as long as you don't mix SEH exception handling and C++ exception handling. This is what you are doing. Your `cout` stream operators can throw, C++ exceptions here, but the code is wrapped in an SEH handler. That won't work. The alternative: C++ exceptions (or no exceptions at all, if that's what you prefer). – IInspectable Nov 09 '17 at 11:35
  • 1
    Important here is that SEH does not implement automatic stack unwinding to run the respective d'tors for cleanup. SEH exceptions are also sometimes called C exceptions. There are no d'tors in C. So using SEH exceptions in a C++ application is possible, but largely useless: You don't get the benefits of C++ exception handling, specifically automatic stack unwinding. That's what the error message is trying to say. – IInspectable Nov 09 '17 at 11:40
  • 1
    You cannot mix SEH exception handling with any C++ objects that rely on RAII to get their destructor called. A simple side-effect of the compiler already having to inject SEH code to implement RAII and it not knowing how to combine it reliably with code that already uses it. I don't see any obvious candidates in the snippet and it does not provide a repro. Try chasing it down in the real code by commenting chunks of code. Once you found it then move that code into its own function. – Hans Passant Nov 09 '17 at 12:02

0 Answers0