Please enable JavaScript to view this site.

Bug Validator Help



The Bug Validator stub service libraries


The NT Service API is very simple, consisting of functions to load, start and unload the Bug Validator DLL.


We have also provided some debugging functions to help you debug the implementation of the NT Service API because getting data into and out of services is not always straightforward.


The stub service libraries used for this are shown in the following table:


32 bit Bug Validator

32 bit service





All the functions exported from these libraries are exported as extern "C" so that C and C++ users can use them.


Library name suffixes


The MD suffix indicates the library was built with the /MD compiler switch.

The MT suffix indicates the library was built with the /MT compiler switch.


2010 or 2012?


If you are using Visual Studio 2010 or earlier, use libraries from a directory with 2010 in the directory name.


If you are using Visual Studio 2012 or later, use libraries from a directory with 2012 in the directory name.



Header files


The header file svlBVStubService.h and svlServiceError.h is found in the svlBVStubService directory of the install area.


The header files provides an error enumeration and the API functions.



API changes - February 2018


To make the API easier to use with services we changed the API by adding many debugging functions to allow you to easily log information. We also extended the error enumeration to provide additional error status values.


We also split the function of loading and starting the validator into two functions - a load function and a start function.


We split the functionality so that you could setup a service callback prior to calling the start function. The service callback allows the service control manager to be informed that the service is still active during time consuming operations, such as starting the validator when the service is non-trivial in scope. Failure to inform the service control manager results in the service being killed by the service control manager because it thinks the service has hung. This change in the API is to ensure you get better results from using our software.


What do you need to do to move from the old API to the new API?


Change all SVL_ERROR declarations to SVL_SERVICE_ERROR.


Your previous startup code probably looked like this:


   SVL_ERROR errCode;
   errCode = svlBVStub_LoadBugValidator();


Change it to this:


   errCode = svlBVStub_LoadBugValidator();
   errCode = svlBVStub_SetServiceCallback(serviceCallback, NULL);
   errCode = svlBVStub_StartBugValidator();


   errCode = svlBVStub_StartBugValidatorForIIS();


The serviceCallback would look something like this:


   void serviceCallback(void   *userParam)
       static DWORD dwCheckPoint = 1;
       ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
       ssStatus.dwServiceSpecificExitCode = 0;
       ssStatus.dwControlsAccepted = 0;
       ssStatus.dwCurrentState = dwCurrentState;
       ssStatus.dwWin32ExitCode = dwWin32ExitCode;
       ssStatus.dwWaitHint = dwWaitHint;
       ssStatus.dwCheckPoint = dwCheckPoint++;
       // Report the status of the service to the service control manager.
       return SetServiceStatus(sshStatusHandle, &ssStatus);


In the code above we have omitted error handling. To see how to use the new logging function with error handling please examine the source code service.cpp in the example service project.




Once your service is running (rather than starting) your service callback should set the appropriate running status SERVICE_RUNNING rather than SERVICE_START_PENDING.

An alternative solution is to prevent the service callback from being called once the service status has been set to running. Do this by calling svlCVStub_SetServiceCallback(NULL, NULL);.


API Reference




typedef enum _svlServiceError
   SVL_OK,                                                              // Normal behaviour
   SVL_ALREADY_LOADED,                                                  // Stub DLL already loaded into service
   SVL_LOAD_FAILED,                                                     // Failed to load stub DLL into service
   SVL_FAILED_TO_ENABLE_STUB_SYMBOLS,                                   // Loaded DLL, but failed to enable stub symbols because couldn't find function
   SVL_NOT_LOADED,                                                      // Couldn't unload DLL because DLL not loaded
   SVL_FAIL_UNLOAD,                                                     // Couldn't unload DLL because couldn't find function
   SVL_FAIL_TO_CLEANUP_INTERNAL_HEAP,                                   // Couldn't get the internal stub heap and thus couldn't clean it up
   SVL_FAIL_MODULE_HANDLE                                               // Couldn't get the stub DLL handle so couldn't continue
   SVL_FAIL_SETSERVICECALLBACK,                                         // Couldn't call the set service callback

   SVL_FAIL_COULD_NOT_FIND_ENTRY_POINT,                                 // Couldn't find the DLL entry point to start the validator

   SVL_FAIL_TO_START,                                                   // Failed to start the Validator

   SVL_FAIL_SETSERVICECALLBACKTHRESHOLD,                                // Couldn't call the set service callback threshold

   SVL_FAIL_PATHS_DO_NOT_MATCH,                                        // Path to service in env vars doesn't match the service being run

   SVL_FAIL_INCORRECT_PRODUCT_PREFIX,                                // Wrong validator

   SVL_FAIL_X86_VALIDATOR_FOUND_EXPECTED_X64_VALIDATOR,        // Found wrong bit depth validator

   SVL_FAIL_X64_VALIDATOR_FOUND_EXPECTED_X86_VALIDATOR,        // Found wrong bit depth validator

   SVL_FAIL_DID_YOU_MONITOR_A_SERVICE_FROM_VALIDATOR,                // Looks like Monitor A Service wasn't used

   SVL_FAIL_ENV_VAR_NOT_FOUND,                                        // Env Var not found

   SVL_FAIL_VALIDATOR_ENV_VAR_NOT_FOUND,                                // Env Var identifying validator not found

   SVL_FAIL_VALIDATOR_ID_NOT_SPECIFIED,                                // Validator process not specified

   SVL_FAIL_VALIDATOR_ID_NOT_A_PROCESS,                                // Validator process identified doesn't exist

   SVL_FAIL_VALIDATOR_NOT_FOUND,                                        // Validator process identified doesn't exist



The API consists of the following functions. Each function will be documented in detail after the list of functions.


extern "C" SVL_SERVICE_ERROR svlBVStub_LoadBugValidator();
extern "C" SVL_SERVICE_ERROR svlBVStub_LoadBugValidator6432();
extern "C" SVL_SERVICE_ERROR svlBVStub_StartBugValidator();
extern "C" SVL_SERVICE_ERROR svlBVStub_ShutdownBugValidator();

extern "C" SVL_SERVICE_ERROR svlBVStub_UnloadBugValidator();
extern "C" SVL_SERVICE_ERROR svlBVStub_SetServiceCallback(serviceCallback_FUNC callback,
                                                          void*                userParam);
// debugging functions
extern "C" void svlBVStub_setLogFileName(const wchar_t* fileName);
extern "C" void svlBVStub_deleteLogFile();
extern "C" void svlBVStub_writeToLogFileA(const char* text);
extern "C" void svlBVStub_writeToLogFileW(const wchar_t* text);
extern "C" void svlBVStub_writeToLogFile(SVL_SERVICE_ERROR errCode);
extern "C" void svlBVStub_writeToLogFileLastError(DWORD errCode);
extern "C" void svlBVStub_dumpPathToLogFile();



Loading the Bug Validator DLL into your service


To load the Bug Validator stub dll svlBugValidatorStub.dll into your service, use the function below, not LoadLibrary().


extern "C" SVL_SERVICE_ERROR svlBVStub_LoadBugValidator();


This loads the DLL and sets up a few internal variables in the DLL to ensure that symbols are sent from the stub to the Bug Validator user interface.


This is necessary because the Bug Validator user interface can't open a process handle to a service and so is unable to get symbols from the process.


To solve this, symbols are sent from the stub to the user interface as needed.


If you just call LoadLibrary() on the DLL, symbols will not be sent to the Bug Validator user interface and you won't get meaningful function names in your stack traces.


This function can be used when monitoring:


32 bit services or applications with Bug Validator.



Which function you should call is shown in the table below.


32 bit Bug Validator

32 bit service




Shutting down the Bug Validator DLL from your service.


Similarly to starting, you'll need to use the following to shutdown the Bug Validator stub dll.


extern "C" SVL_SERVICE_ERROR svlBVStub_ShutdownBugValidator();


This sends the shutting down notification and removes any hooks for your process.



Unloading the Bug Validator DLL from your service.


Use this method to unload the Bug Validator stub dll, and not FreeLibrary().


extern "C" SVL_SERVICE_ERROR svlBVStub_UnloadBugValidator();



Setting a service notification callback


Once you have successfully loaded the Bug Validator DLL you can setup a service callback so that the service control manager can be kept updated during the process of starting the validator.


When a service is starting, Windows requires the service to inform the Service Control Manager (SCM) that is starting at least every ten seconds.


Failure to do so results in Windows concluding that the service has failed to start, and the service is terminated.


Instrumenting your service may well take more than 10 seconds, depending on the complexity and size of your service.


The solution is for Bug Validator to periodically call a user supplied callback from which you can regularly inform the SCM of the appropriate status.


extern "C" SVL_SERVICE_ERROR svlBVStub_SetServiceCallback(serviceCallback_FUNC callback, void *userParam);


userParam is a value you can supply which will then be passed to the callback every time the callback is called during instrumentation.


Here is an example callback which ignores the userParam.


   void serviceCallback(void   *userParam)
       static DWORD dwCheckPoint = 1;
       ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
       ssStatus.dwServiceSpecificExitCode = 0;
       ssStatus.dwControlsAccepted = 0;
       ssStatus.dwCurrentState = dwCurrentState;
       ssStatus.dwWin32ExitCode = dwWin32ExitCode;
       ssStatus.dwWaitHint = dwWaitHint;
       ssStatus.dwCheckPoint = dwCheckPoint++;
       // Report the status of the service to the service control manager.
       return SetServiceStatus(sshStatusHandle, &ssStatus);



Starting Bug Validator DLL in your service


Once you have successfully loaded the Bug Validator DLL you can start the Validator inspecting the service.


extern "C" SVL_SERVICE_ERROR svlBVStub_StartBugValidator();



Setting a filename for all logging data to be written to


To use any of the following logging functions you first need to set the name of the filename used for logging.

Setting this filename also sets the filename used by some of these API functions - you will find additional logging data from those functions that will help debug any issues with the service.


extern "C" void svlBVStub_setLogFileName(const wchar_t* fileName);


Deleting the logfile


This function deletes the log file.

extern "C" void svlBVStub_deleteLogFile();


Writing ANSI text to the logfile


Call this function to write a standard ANSI character string to the log file.

extern "C" void svlBVStub_writeToLogFileA(const char* text);


Write UNICODE text to the logfile


Call this function to write a unicode character string to the log file. The characters are cast to ANSI prior to writing. As such you can't write Korean to the log file. This is simply a convenience function to write wide characters as simply as ANSI characters.

extern "C" void svlBVStub_writeToLogFileW(const wchar_t* text);


Writing error code descriptions to the logfile


Call this function to write a human readable description of the SVL_SERVICE_ERROR error code to the log file.

extern "C" void svlBVStub_writeToLogFile(SVL_SERVICE_ERROR errCode);


Writing LastError code descriptions to the logfile


Call this function to write a human readable description of the Windows error code to the log file.

extern "C" void svlBVStub_writeToLogFileLastError(DWORD errCode);


Dumping the PATH environment to the logfile


Call this function to write the contents of the PATH environment variable to the log file. This can be useful if you want to know what the search path is when trying to debug why a DLL wasn't found during an attempt to load the Validator DLL.

extern "C" void svlBVStub_dumpPathToLogFile();



Bug Validator DLL behaviour


The DLL prepares itself in different ways and shuts itself down differently depending on whether:


The DLL is directly linked to the application for use with the API or injected with Bug Validator


The DLL expects to oversee and manage the application shutdown.


The DLL is loaded by using the function above


The DLL expects to be removed prior to application shutdown and the its behaviour is undefined once you enter the program shutdown sequence.


This difference in behaviour is intentional and is done to allow the use of the stub DLL in services.



Linker Problems


Some linkers cannot link the stub service library file.  If you have this problem see What do I do if I cannot use svlBVStubService.lib?



Troubleshooting - Service fails to start


If a service takes too long to start the service control manager kills the service.


The way to stop this is for a service to call ReportStatusToSCMgr() to tell the service control manager that the service is still OK.


Bug Validator can't do this for you as the call requires some data from any earlier call you have made.


The solution is that you provide a callback using svlBVStub_SetServiceCallback() that Bug Validator can call during the process of attaching to the service, and you can call the appropriate function.


Example code to set the callback:


 errCode = svlBVStub_SetServiceCallback(serviceCallback,                // the callback

                                              NULL);                                // some user data (we don't have any, so set NULL)

 if (bLogging)


         if (errCode != SVL_OK)


                 svlBVStub_writeToLogFileW(L"Setting service callback failed. \r\n");




         svlBVStub_writeToLogFileW(L"Starting Bug Validator\r\n");





Example callback:


static void serviceCallback(void        *userParam)


 // just tell the Service Control Manager that we are still busy

 // in this example userParam is not used


 // note that prior to the Validator loading it's DLL ssStatus.dwCurrentState must have been initialised, most likely to SERVICE_START_PENDING

 // you could pass a fixed value here, but it would need to change once the service has finished starting up so that you don't unintentionally change the service state

 // when this callback is called. This callback is called whenever instrumentation happens (when a DLL is loaded). Thus you can't assume this is only called during service startup,

 // it may also get called later in the service lifetime.


 ReportStatusToSCMgr(ssStatus.dwCurrentState,        // service state

                         NO_ERROR,                        // exit code

                         3000);                                // wait hint



We strongly recommend that you set a service callback. It won't harm your program and it will remove any likelihood of your service being killed by the service control manager.



Troubleshooting - Service starts, Bug Validator gets no data


If you have problems getting Bug Validator to monitor your service you'll need to find out what's failing.


Until Bug Validator loads correctly and successfully connects to the graphical user interface you have no way of knowing what is happening.


The solution is to set a log file that Bug Validator can write status messages to. You can also write your own status messages to this log file.


Set the log file using svlBVStub_setLogFileName. Write to it using svlBVStub_writeToLogFile(), svlBVStub_writeToLogFileA(), svlBVStub_writeToLogFileW().


Then when things are not working as expected take a look at the log file to see the errors. The Bug Validator will often suggest what the problem is.


We strongly recommend that you configure the log file and use it when working with services. It has saved us a lot of time.





Example demonstrating how to monitor a service.


Example demonstrating how to monitor an application launched from a service (how to monitor any application running on a service account).