As the title says - it's reporting, "The specified service does not exist as an installed service."

I'm running this as an administrator and have a successful ALL_ACCESS handle to the SCM.

At some earlier points I did have some trouble with the narrow to wide conversion. I believe that's been resolved.

There was a little trouble parsing the string at first, it doesn't seem to be wrong anymore and all the values in the debugger seem to be correct.

I can't figure weather I'm completely screwing a step up, or if it needs some sort of special elevated privileges or something(doubt it).

struct service_t
{
    SC_HANDLE scService;
    wstring   name;
    bool      valid;
};

bool Services::Init()
{
    /*some unused login stuff commented out*/

    scHandle = OpenSCManager(NULL, NULL, /*SC_MANAGER_CONNECT*/SC_MANAGER_ALL_ACCESS);
    if(!scHandle) {
      log.Error(L"OpenSCManger() failed. ");
      return(false); }

    bSuccessful = true;
    return(true);
}

bool Services::PopulateTable()
{
    HANDLE    hFile;
    string    buffer;
    wstring   wsb; /*wide string buffer*/
    wchar_t   file[MAX_PATH];
    DWORD     file_sz, read = 0, required;
    size_t    pos = 0;
    service_t tmp;

    /*opening and reading a file that list all service names into buffer*/

    required = MultiByteToWideChar(CP_UTF8, 0, &buffer[0], (int)buffer.size(), NULL, 0);
    wsb.resize(required, 0);
    if(!MultiByteToWideChar(CP_UTF8, 0, &buffer[0], (int)buffer.size(), &wsb[0], required))
      log.Error(L"MB2WC() failed. ");
     buffer.clear();

     while(pos != string::npos) {
       pos = wsb.find_first_of(L'\n');
       if(pos != string::npos)
	 pos++;
       tmp.name = wsb.substr(0, pos);
       wsb.erase(0, (pos));
       if(pos != string::npos) {
	 pos--;
	 tmp.name[pos] = L'\0'; }
       if(tmp.name.size() > 0)
         service_table.push_back(tmp);
    }

    return(true);
}

bool Services::Pause()
{
    SERVICE_STATUS stat;

    if(!bSuccessful)
      return(false);

    for(size_t i = 0; i < service_table.size(); i++) {
      service_table[i].scService = OpenService(scHandle, service_table[i].name.c_str(), SERVICE_PAUSE_CONTINUE);
        if(service_table[i].scService) {
	  log.Append(3, L"Opened(", service_table[i].name.c_str(), ") \n");
          service_table[i].valid = true;

          if(!ControlService(service_table[i].scService, SERVICE_CONTROL_PAUSE, &stat))
	    log.Error(3, L"ControlService(", service_table[i].name.c_str(), L") failed. \n\t");
        }
	else
	  log.Error(3, L"OpenService( ", service_table[i].name.c_str(), L") failed. \n\t");
    }

    log.Display();
    return(true);
}

An example excerpt from the service name list file, they were copy-pasted from the Service Manager in Admin Tools:

iPod Service
PolicyAgent
Netman
netprofm
NlaSvc
nsi
NTI IScheduleSvc
Spooler

Dani AI

Generated

A few short, targeted points that address the usual causes when OpenService returns "The specified service does not exist as an installed service." — targeted to the thread and 's notes about having an SCM handle.

Passing the display name (the friendly name shown in Services MMC) or a name with trailing CR/LF will cause OpenService to fail because OpenService expects the service key name (the short "service name"). Convert display names to the key name with GetServiceKeyName before calling OpenService. GetServiceKeyName doc. (learn.microsoft.com)

Parsing issues are common when reading a file. MultiByteToWideChar does not automatically null-terminate when given an explicit input length, and Windows text pasted from services.msc often contains CR (\r). Always trim trailing \r/whitespace and log the exact wide string and its length before calling OpenService. Capture GetLastError() and use FormatMessage to show the failure reason rather than guessing. MultiByteToWideChar notes. (learn.microsoft.com)

A compact, robust flow (illustrative):

std::wistringstream iss(wsb);
std::wstring line;
while (std::getline(iss, line)) {
    if (!line.empty() && line.back() == L'\r') line.pop_back();   // strip CR
    if (line.empty()) continue;

    DWORD needed = 0;
    GetServiceKeyName(scHandle, line.c_str(), nullptr, &needed); // ask for size
    std::wstring svc = (needed ? std::wstring(needed, L'\0') : std::wstring());
    if (needed && GetServiceKeyName(scHandle, line.c_str(), &svc[0], &needed))
        svc.resize(wcslen(svc.c_str()));
    else
        svc = line; // fallback if input already was the key name

    SC_HANDLE s = OpenService(scHandle, svc.c_str(), SERVICE_PAUSE_CONTINUE);
    if (!s) { DWORD e = GetLastError(); /* log FormatMessage for e */ }
    else CloseServiceHandle(s);
}

If the source list is untrustworthy, enumerate installed services programmatically with EnumServicesStatusEx (it returns the actual lpServiceName) instead of relying on a pasted file. Also verify the process is elevated and the handle/access rights used are appropriate for the operations being attempted. [EnumServicesStatusEx doc] (https://learn.microsoft.com/en-us/windows/win32/api/winsvc/nf-winsvc-enumservicesstatusexa). (learn.microsoft.com)

One shameless bump before I let this die and get on with a dozen other programs.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.