C++ boot task schedule error: No Mapping between account names and security ids was done (0x80070534)

champixncynthia 1 Reputation point
2021-03-28T18:01:48.49+00:00

So pretty much I've been following this tutorial along (https://learn.microsoft.com/en-us/windows/win32/taskschd/boot-trigger-example--c---) to add notepad to load at boot using the task scheduler in C++.

The only issue is when I get to RegisterTaskDefinition(), the function fails with the error code 0x80070534 which translates as: "No mapping between account names and security ids was done."

I've read around that I have to replace the userId parameter with "S-1-5-32-544", but that didn't solve anything.
I'm quite lost on how to continue and I don't know where to look inside the code to fix the problem since it's a one-on-one copy of the one inside the tutorial.

The faulty bit:
Notice that DLL_DEBUG is a macro that translates to printf.

//  Save the task in the root folder.  
    IRegisteredTask *pRegisteredTask = NULL;  
    VARIANT varPassword;  
    varPassword.vt = VT_EMPTY;  
    hr = pRootFolder->RegisterTaskDefinition(  
            _bstr_t( wszTaskName ),  
            pTask,  
            TASK_CREATE_OR_UPDATE,   
            _variant_t(L"Local Service"),   
            varPassword,   
            TASK_LOGON_SERVICE_ACCOUNT,  
            _variant_t(L""),  
            &pRegisteredTask);  
  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nError saving the Task : %x\n", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }  
      
    DLL_DEBUG("\n Success! Task successfully registered.\n" );  

and the whole code, for good measure:

bool ScheduleTask()  
{  
  
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);  
    if( FAILED(hr) )  
    {  
        printf("\nCoInitializeEx failed: %x", hr );  
        return 1;  
    }  
  
    //  Set general COM security levels.  
    hr = CoInitializeSecurity(  
        NULL,  
        -1,  
        NULL,  
        NULL,  
        RPC_C_AUTHN_LEVEL_PKT_PRIVACY,  
        RPC_C_IMP_LEVEL_IMPERSONATE,  
        NULL,  
        0,  
        NULL);  
  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nCoInitializeSecurity failed: %x", hr );  
        CoUninitialize();  
        return 1;  
    }  
  
    //  Create a name for the task.  
    LPCWSTR wszTaskName = L"Boot Trigger Test Task";  
  
    //  Get the Windows directory and set the path to Notepad.exe.  
    wstring wstrExecutablePath = _wgetenv( L"WINDIR");  
    wstrExecutablePath += L"\\SYSTEM32\\NOTEPAD.EXE";  
  
    //  Create an instance of the Task Service.   
    ITaskService *pService = NULL;  
    hr = CoCreateInstance( CLSID_TaskScheduler,  
                           NULL,  
                           CLSCTX_INPROC_SERVER,  
                           IID_ITaskService,  
                           (void**)&pService );    
    if (FAILED(hr))  
    {  
          DLL_DEBUG("Failed to create an instance of ITaskService: %x", hr);  
          CoUninitialize();  
          return 1;  
    }  
          
    //  Connect to the task service.  
    hr = pService->Connect(_variant_t(), _variant_t(),  
        _variant_t(), _variant_t());  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("ITaskService::Connect failed: %x", hr );  
        pService->Release();  
        CoUninitialize();  
        return 1;  
    }  
  
    //  Get the pointer to the root task folder.    
    //  This folder will hold the new task that is registered.  
    ITaskFolder *pRootFolder = NULL;  
    hr = pService->GetFolder( _bstr_t( L"\\") , &pRootFolder );  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("Cannot get Root Folder pointer: %x", hr );  
        pService->Release();  
        CoUninitialize();  
        return 1;  
    }  
      
    //  If the same task exists, remove it.  
    pRootFolder->DeleteTask( _bstr_t( wszTaskName), 0  );  
      
    //  Create the task builder object to create the task.  
    ITaskDefinition *pTask = NULL;  
    hr = pService->NewTask( 0, &pTask );  
  
    pService->Release();  // COM clean up.  Pointer is no longer used.  
    if (FAILED(hr))  
    {  
          DLL_DEBUG("Failed to create a task definition: %x", hr);  
          pRootFolder->Release();  
          CoUninitialize();  
          return 1;  
    }  
  
    //  Get the registration info for setting the identification.  
    IRegistrationInfo *pRegInfo= NULL;  
    hr = pTask->get_RegistrationInfo( &pRegInfo );  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nCannot get identification pointer: %x", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }  
      
    hr = pRegInfo->put_Author(L"Vladimir Putin");  
    pRegInfo->Release();  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nCannot put identification info: %x", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }  
  
     //  Create the settings for the task  
    ITaskSettings *pSettings = NULL;  
    hr = pTask->get_Settings( &pSettings );  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nCannot get settings pointer: %x", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }  
      
    //  Set setting values for the task.   
    hr = pSettings->put_StartWhenAvailable(VARIANT_TRUE);  
    pSettings->Release();  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nCannot put setting info: %x", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }  
  
    //  Get the trigger collection to insert the boot trigger.  
    ITriggerCollection *pTriggerCollection = NULL;  
    hr = pTask->get_Triggers( &pTriggerCollection );  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nCannot get trigger collection: %x", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }  
  
    ITrigger *pTrigger = NULL;  
    hr = pTriggerCollection->Create( TASK_TRIGGER_BOOT, &pTrigger );   
    pTriggerCollection->Release();  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nCannot create the trigger: %x", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }  
      
    IBootTrigger *pBootTrigger = NULL;  
    hr = pTrigger->QueryInterface(   
        IID_IBootTrigger, (void**) &pBootTrigger );  
    pTrigger->Release();  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nQueryInterface call failed for IBootTrigger: %x", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }  
  
    hr = pBootTrigger->put_Id( _bstr_t( L"Trigger1" ) );  
    if( FAILED(hr) )  
       DLL_DEBUG("\nCannot put the trigger ID: %x", hr);  
      
    //  Set the task to start at a certain time. The time   
    //  format should be YYYY-MM-DDTHH:MM:SS(+-)(timezone).  
    //  For example, the start boundary below  
    //  is January 1st 2005 at 12:05  
    hr = pBootTrigger->put_StartBoundary( _bstr_t(L"2021-01-01T12:05:00") );  
    if( FAILED(hr) )  
       DLL_DEBUG("\nCannot put the start boundary: %x", hr);  
    
    hr = pBootTrigger->put_EndBoundary( _bstr_t(L"2099-05-02T08:00:00") );  
    if( FAILED(hr) )  
       DLL_DEBUG("\nCannot put the end boundary: %x", hr);  
  
    // Delay the task to start 30 seconds after system start.   
    hr = pBootTrigger->put_Delay( L"PT30S" );  
    pBootTrigger->Release();  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nCannot put delay for boot trigger: %x", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }   
  
    //  Add an Action to the task. This task will execute Notepad.exe.       
    IActionCollection *pActionCollection = NULL;  
  
    //  Get the task action collection pointer.  
    hr = pTask->get_Actions( &pActionCollection );  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nCannot get Task collection pointer: %x", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }  
          
    //  Create the action, specifying it as an executable action.  
    IAction *pAction = NULL;  
    hr = pActionCollection->Create( TASK_ACTION_EXEC, &pAction );  
    pActionCollection->Release();  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nCannot create the action: %x", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }  
  
    IExecAction *pExecAction = NULL;  
    //  QI for the executable task pointer.  
    hr = pAction->QueryInterface(   
        IID_IExecAction, (void**) &pExecAction );  
    pAction->Release();  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nQueryInterface call failed for IExecAction: %x", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }  
  
    //  Set the path of the executable to Notepad.exe.  
    hr = pExecAction->put_Path( _bstr_t( wstrExecutablePath ) );  
    pExecAction->Release();   
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nCannot set path of executable: %x", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }  
  
    //  Save the task in the root folder.  
    //  The error happens here!!!  
  
    IRegisteredTask *pRegisteredTask = NULL;  
    VARIANT varPassword;  
    varPassword.vt = VT_EMPTY;  
    hr = pRootFolder->RegisterTaskDefinition(  
            _bstr_t( wszTaskName ),  
            pTask,  
            TASK_CREATE_OR_UPDATE,   
            _variant_t(L"Local Service"),   
            varPassword,   
            TASK_LOGON_SERVICE_ACCOUNT,  
            _variant_t(L""),  
            &pRegisteredTask);  
  
    if( FAILED(hr) )  
    {  
        DLL_DEBUG("\nError saving the Task : %x\n", hr );  
        pRootFolder->Release();  
        pTask->Release();  
        CoUninitialize();  
        return 1;  
    }  
      
    DLL_DEBUG("\n Success! Task successfully registered.\n" );  
  
    //  Clean up.  
    pRootFolder->Release();  
    pTask->Release();  
    pRegisteredTask->Release();  
    CoUninitialize();  
    return 0;  
}  
Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,386 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,481 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. MotoX80 31,316 Reputation points
    2021-03-28T18:58:20.943+00:00

    I would suggest that you might want to describe the overall problem that you are trying to solve.

    Writing a C++ program to schedule a task would not be my first choice. Even if you found a solution to the account mapping problem, running notepad at boot time will not accomplish anything. It is a GUI program that expects to interact with a user. But scheduling the program like this will cause it to run in a non-interactive session. The only way that you would know that is is executing would be to look in task manager.

    I assume that you are trying to launch notepad just as an example. Does the real program that you want to run expect to interact with the desktop user? Are you trying to run a program more or less like a Windows service? There are other options.

    0 comments No comments

  2. Castorix31 81,061 Reputation points
    2021-03-28T19:16:01.643+00:00

    It works for me, as Admin (Manifest), by replacing this line :

    hr = pRootFolder->RegisterTaskDefinition(
        _bstr_t(wszTaskName), pTask, TASK_CREATE_OR_UPDATE,
        _variant_t(), _variant_t(), TASK_LOGON_INTERACTIVE_TOKEN,
        _variant_t(L""), &pRegisteredTask);