How to install/deinstall a Windows service in win32? - c

I am trying to create a Win32 program that could delete temporary files in a specific path.
But I am actually in trouble with the install/uninstall functions in my code.
I'm working on Visual Studio 2012 and when I launch the debug process to test my code the debug window is closed immediately.
Maybe the problem is not coming from VS 2012 but from my code?
Here it is:
/*
** INCLUDES
*/
#include <Windows.h>
#include <stdio.h>
/*
** MACROS
*/
# define MY_SERVICE_NAME "DiskCleaner"
# define MY_SERVICE_DISPLAY_NAME "Nettoyeur de disque"
SERVICE_STATUS my_ServiceStatus;
SERVICE_STATUS_HANDLE my_ServiceStatusHandle;
BOOL bRunning;
BOOL InstallMyService();
BOOL DeleteMyService();
void WINAPI ServiceCtrlHandler(DWORD Opcode);
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
/* INSTALL THE SERVICE */
BOOL InstallMyService()
{
char strDir[MAX_PATH];
SC_HANDLE hSCManager;
SC_HANDLE hService;
LPCTSTR lpBinaryPathName;
GetCurrentDirectory(MAX_PATH, strDir);
strcat(strDir, "\\AutoClean.exe");
hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCManager == NULL)
return (FALSE);
lpBinaryPathName=strDir;
hService = CreateService(
hSCManager, MY_SERVICE_NAME,
MY_SERVICE_DISPLAY_NAME, SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
lpBinaryPathName,
NULL,
NULL,
NULL,
NULL,
NULL);
if (hService == NULL)
return (FALSE);
CloseServiceHandle(hService);
return (TRUE);
}
/* DELETE THE SERVICE */
BOOL DeleteMyService()
{
SC_HANDLE hSCManager;
SC_HANDLE hService;
hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCManager == NULL)
return (FALSE);
hService = OpenService (hSCManager, MY_SERVICE_NAME, SERVICE_ALL_ACCESS);
if (hService == NULL)
return (FALSE);
if (DeleteService(hService) == NULL)
return (FALSE);
if (CloseServiceHandle(hService) == NULL)
return (FALSE);
return (TRUE);
}
/* SERVICE EVENT HANDLER */
void WINAPI ServiceCtrlHandler(DWORD Opcode)
{
switch (Opcode)
{
case SERVICE_CONTROL_PAUSE:
my_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
my_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
my_ServiceStatus.dwWin32ExitCode = 0;
my_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
my_ServiceStatus.dwCheckPoint = 0;
my_ServiceStatus.dwWaitHint = 0;
SetServiceStatus (my_ServiceStatusHandle, &my_ServiceStatus);
bRunning = FALSE;
break;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
return;
}
/* SERVICE ENTRY POINT */
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
DWORD Status;
DWORD SpecificError;
my_ServiceStatus.dwServiceType = SERVICE_WIN32;
my_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
my_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
my_ServiceStatus.dwWin32ExitCode = 0;
my_ServiceStatus.dwServiceSpecificExitCode = 0;
my_ServiceStatus.dwCheckPoint = 0;
my_ServiceStatus.dwWaitHint = 0;
my_ServiceStatusHandle = RegisterServiceCtrlHandler(MY_SERVICE_NAME, ServiceCtrlHandler);
if (my_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
return;
}
my_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
my_ServiceStatus.dwCheckPoint = 0;
my_ServiceStatus.dwWaitHint = 0;
SetServiceStatus(my_ServiceStatusHandle, &my_ServiceStatus);
bRunning = TRUE;
while (bRunning)
{
printf("\nOK just to test if this part works well before implementing my cleaning part\n");
}
return;
}
/* ENTRY POINT */
int main(int argc, char* argv[])
{
if (argc > 1)
{
if (strcmp(argv[1], "-i"))
{
if (InstallMyService())
printf("\nService successfully installed\n");
else
printf("\nService installtion unsuccessfull\n");
}
else if (strcmp(argv[1], "-d"))
{
if (DeleteMyService())
printf("\nService successfully deleted\n");
else
printf("\nService delete unsuccesfull\n");
}
else
printf("\nUsage incorrect\n");
}
else
{
SERVICE_TABLE_ENTRY DispatchTable[]={{MY_SERVICE_NAME, ServiceMain}, {NULL, NULL}};
StartServiceCtrlDispatcher(DispatchTable);
}
return (EXIT_SUCCESS);
}

In your main function you have errors:
if (strcmp(argv[1], "-i"))
if (strcmp(argv[1], "-d"))
This condition is FALSE, so your InstallMyService() / DeleteMyService() is not executed.
Also for sake of complexity you forgot close service manager handle.

I've corrected my code and it works now. This is the entire solution :
#include <Windows.h>
#include <stdio.h>
/*
** MACROS
*/
# define MY_SERVICE_NAME "DiskCleaner"
# define MY_SERVICE_DESCRIPTOR "Nettoyeur de fichiers temporaires"
# define MY_SERVICE_BIN_NAME "DiskCleaner.exe"
/*
** GLOBALS
*/
SERVICE_STATUS g_ServiceStatus;
SERVICE_STATUS_HANDLE g_ServiceStatusHandle;
/*
** INSTALL THE SERVICE
*/
BOOL InstallMyService()
{
char strDir[MAX_PATH + 1];
SC_HANDLE schSCManager;
SC_HANDLE schService;
LPCTSTR lpszBinaryPathName;
GetCurrentDirectory(MAX_PATH, strDir);
strcat(strDir, "\\"MY_SERVICE_BIN_NAME);
if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL)
return (TRUE);
lpszBinaryPathName = strDir;
schService = CreateService(schSCManager, MY_SERVICE_NAME, MY_SERVICE_DESCRIPTOR,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
lpszBinaryPathName, NULL, NULL, NULL, NULL, NULL);
if (schService == NULL)
return (FALSE);
CloseServiceHandle(schService);
return (TRUE);
}
/*
** DELETE THE SERVICE
*/
BOOL DeleteMyService()
{
SC_HANDLE schSCManager;
SC_HANDLE hService;
if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL)
return (FALSE);
if ((hService = OpenService(schSCManager, MY_SERVICE_NAME, SERVICE_ALL_ACCESS)) == NULL)
return (FALSE);
if (!DeleteService(hService))
return (FALSE);
if (!CloseServiceHandle(hService))
return (FALSE);
return (TRUE);
}
/*
** SERVICE EVENT HANDLER
*/
void WINAPI ServiceCtrlHandler(DWORD Opcode)
{
switch (Opcode)
{
case SERVICE_CONTROL_PAUSE:
g_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
SetServiceStatus (g_ServiceStatusHandle, &g_ServiceStatus);
break;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
}
/*
** SERVICE MAIN ENTRY
*/
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
g_ServiceStatus.dwServiceType = SERVICE_WIN32;
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
g_ServiceStatusHandle = RegisterServiceCtrlHandler(MY_SERVICE_NAME, ServiceCtrlHandler);
if (g_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
return;
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
}
/*
** MAIN ENTRY
*/
int main(int argc, char* argv[])
{
if (argc > 1)
{
if (!strcmp(argv[1], "-i"))
if(InstallMyService())
printf("\nService correctly installed\n");
else
printf("\nService uncorrectly installed\n");
else if (!strcmp(argv[1], "-d"))
if(DeleteMyService())
printf("\nService correctly deleted\n");
else
printf("\nService uncorrectly deleted\n");
}
else
{
SERVICE_TABLE_ENTRY DispatchTable[]={{MY_SERVICE_NAME, ServiceMain}, {NULL, NULL}};
StartServiceCtrlDispatcher(DispatchTable);
}
return (EXIT_SUCCESS);
}

Related

Access violation when getting network adapters with GetAdaptersAddresses in C

I don't know if the code from https://learn.microsoft.com/en-us/windows/desktop/api/iphlpapi/nf-iphlpapi-getadaptersaddresses is wrong but when I try to use it in my C project I keep getting the infamous
Access violation reading location 0xFFFFFFFFFFFFFFFF
I have tried increasing the buffer size but nothing seems to fix it. I think this happens after the first adapter is passed through the loop.
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <winsock2.h>
#include <iptypes.h>
#include <iphlpapi.h>
#include <windows.h>
#pragma comment(lib, "IPHLPAPI.lib")
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
FILE* fLog = NULL;
void netinfo() {
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
DWORD dwRetVal = 0;
ULONG outBufLen = 15000;
ULONG iter = 0;
do {
pAddresses = (IP_ADAPTER_ADDRESSES*)MALLOC(outBufLen);
if (pAddresses == NULL) {
fwprintf(fLog, L"MALLOC error");
break;
dwRetVal = GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX,
NULL,
pAddresses,
&outBufLen
);
if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
FREE(pAddresses);
pAddresses = NULL;
fwprintf(fLog, L"GetAdaptersAddresses() error");
} else {
break;
}
iter++;
}
} while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (iter < 3));
wchar_t netAddressLog[256];
if (dwRetVal == NO_ERROR && pAddresses != NULL) {
pCurrAddresses = pAddresses;
while (pCurrAddresses) {
// this is where the debugger stops !!!
swprintf(netAddressLog, 256, L"Index: %u", pCurrAddresses->IfIndex);
fwprintf(fLog, netAddressLog);
pCurrAddresses = pCurrAddresses->Next;
}
} else {
fwprintf(fLog, L"GetAdaptersAddresses() error");
}
if (pAddresses) {
FREE(pAddresses);
}
}
int main(int argc, char **argv) {
errno_t error = _wfopen_s(&fLog, L"log.txt", L"a+");
netinfo();
fclose(fLog);
}
So, when trying to access pCurrAddresses->IfIndex it's where the program fails, after the first loop (in which it logs some weird large number for index). I am trying to compare mi slightly modified code to the one from MSDN but I can't figure it out.
I know my code needs better organization but for now this is a blocker
There is some problem in the while loop block:
do {
pAddresses = (IP_ADAPTER_ADDRESSES*)MALLOC(outBufLen);
if (pAddresses == NULL) {
fwprintf(fLog, L"MALLOC error");
break;
/* a } is missing here*/
dwRetVal = GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX,
NULL,
pAddresses,
&outBufLen
);
if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
FREE(pAddresses);
pAddresses = NULL;
fwprintf(fLog, L"GetAdaptersAddresses() error");
} else {
break;
}
iter++;
}
} while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (iter < 3));
The good corrected code could be:
do {
pAddresses = (IP_ADAPTER_ADDRESSES*)MALLOC(outBufLen);
if (pAddresses == NULL) {
fwprintf(fLog, L"MALLOC error");
break;
}
dwRetVal = GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX,
NULL,
pAddresses,
&outBufLen
);
if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
FREE(pAddresses);
pAddresses = NULL;
fwprintf(fLog, L"GetAdaptersAddresses() error");
} else {
break;
}
iter++;
} while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (iter < 3));

Redirect output in shell?

I have written a function for the purposes of redirecting output from some command to a file. Something like this
ls > ls.txt
Here is the function that does output redirection:
int redirect_output(char* cmdline, char **output_filename) {
int i;
char* args[MAX_ARGS];
// int nargs = get_args(cmdline, args);
for(i = 0; args[i] != NULL; i++) {
// Look for the >
if(!strcmp(args[i], ">")) {
// Get the filename
if(args[i+1] != NULL) {
*output_filename = args[i+1];
} else {
return -1; //syntax error
}
return 1; //there is an >
}
}
return 0; //no redirect
}
The function successfully redirects output from some command to a file, but for some reason it causes other commands to stop working. So for example, my program with redirect_output works for something like ls but it does not work for something like cat ls.txt, if I do not call the function it works for any command. And, by not work it mean it gets stuck. Here are the other important functions.
int get_args(char* cmdline, char* args[])
{
int i = 0;
/* if no args */
if((args[0] = strtok(cmdline, "\n\t ")) == NULL)
return 0;
while((args[++i] = strtok(NULL, "\n\t ")) != NULL) {
if(i >= MAX_ARGS) {
printf("Too many arguments!\n");
exit(1);
}
}
/* the last one is always NULL */
return i;
}
void execute(int output, char *outputefile, char* cmdline)
{
int pid, async;
char* args[MAX_ARGS];
int nargs = get_args(cmdline, args);
if(nargs <= 0) return;
if(!strcmp(args[0], "quit") || !strcmp(args[0], "exit")) {
exit(0);
}
/* check if async call */
if(!strcmp(args[nargs-1], "&")) {
async = 1;
args[--nargs] = 0;
}
else async = 0;
pid = fork();
if(pid == 0) { /* child process */
//if(output)
// freopen(outputefile, "w+", stdout);
execvp(args[0], args);
/* return only when exec fails */
perror("exec failed");
exit(-1);
} else if(pid > 0) { /* parent process */
if(!async) waitpid(pid, NULL, 0);
else printf("this is an async call\n");
} else { /* error occurred */
perror("fork failed");
exit(1);
}
}
And here is my main:
int main (int argc, char* argv [])
{
char cmdline[BUFSIZ];
char *output_filename;
char **args;
int output;
for(;;) {
printf("COP4338$ ");
if(fgets(cmdline, BUFSIZ, stdin) == NULL) {
perror("fgets failed");
exit(1);
}
output = redirect_output(cmdline, &output_filename);
switch(0) {
case -1:
printf("Syntax error!\n");
break;
case 0:
break;
case 1:
printf("Redirecting output to: %s\n", output_filename);
break;
}
execute (output, output_filename, cmdline);
}
return 0;
}
Any help will be much appreciated! Thanks!

Serial port reading in c, using WinApi functions; WaitCommEvent fails

I tried to write a small event-based application in C for serial port reading (sources below). My program is to use the WinApi functions. The comport.c has the functions written to handle COM-port (open, read, write), the utils.c has some helper functions.
My program produces always the following output:
COM1 is selected to be listened.
GetCommMask result: 0x00000029 (EV_RXCHAR: 0x0001, EV_CTS: 0x0008, EV_RLSD: 0x0020)
Press any key to proceed...
I/O is pending (WaitCommEvent)...
I/O is pending (WaitCommEvent)...
I/O is pending (WaitCommEvent)...
I/O is pending (WaitCommEvent)...
I/O is pending (WaitCommEvent)...
It seems, that the function WaitCommEvent fails, the GetLastError() gives back error 87 (I/O pending).
Please help me to find out what the problem is, which parameter is invalid? See below the code.
The main.c:
#include "stdafx.h"
#include "comport.h"
#include "utils.h"
#include <conio.h>
#define READ_BUFF_MAX_LENGTH 1024
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwEvtMask;
HANDLE hComPort;
OVERLAPPED oEventHandler;
int portNum;
DWORD readTotal;
BOOL bOverlappedPending = FALSE;
char readBuff[READ_BUFF_MAX_LENGTH];
if(2 > argc)
{
printf("Use the program: ZliFuerZlvbusInterface.exe XXX (where XXX is the number of com port), \r\ne.G. for COM1 -> ZliFuerZlvbusInterface.exe 1\r\n");
return 1;
}
else
{
portNum = atoi(argv[1]);
if(0 == IsValidComNumber(portNum))
{
printf("ERROR: COM port number %d is invalid (parsed from '%s').\r\n", portNum, argv[1]);
return 2;
}
else
{
printf("COM%d is selected to be listened.\r\n", portNum);
}
}
if(0 == CreateSerialConnection(&hComPort, &oEventHandler, portNum, 1200, 8, EVEN, STOP1))
{
return 3;
}
if(FALSE == GetCommMask(hComPort, &dwEvtMask))
{
printf("GetCommMask failed with error:\r\n");
PrintLastErrorText();
return 4;
}
else
{
printf("GetCommMask result: 0x%08X (EV_RXCHAR: 0x0001, EV_CTS: 0x0008, EV_RLSD: 0x0020)\r\n", dwEvtMask);
}
printf("Press any key to proceed...\r\n");
getch();
while(1)
{
if(0 != kbhit())
{
if(27 == getch()) // ESC pressed
{
printf("Key ESC pressed, exiting...\r\n");
break;
}
}
bOverlappedPending = FALSE;
readTotal = 0;
if(TRUE == WaitCommEvent(hComPort, &dwEvtMask, &oEventHandler))
{
if(dwEvtMask & EV_CTS) // Clear-to-send signal present
{
PrintCurrentDateTime();
printf("COM%d: Clear-to-send signal set\r\n", portNum);
}
if(dwEvtMask & EV_RLSD) // Data-carrier-detect signal present
{
PrintCurrentDateTime();
printf("COM%d: Data-carrier-detect signal set\r\n", portNum);
}
if(dwEvtMask & EV_RXCHAR) // Data received
{
ReadSerial(&hComPort, &oEventHandler, portNum, readBuff, READ_BUFF_MAX_LENGTH);
}
}
else
{
if(ERROR_IO_PENDING == GetLastError())
{
printf("I/O is pending (WaitCommEvent)...\r\n");
bOverlappedPending = TRUE;
}
else
{
printf("WaitCommEvent failed with error:\r\n");
PrintLastErrorText();
}
}
if(TRUE == bOverlappedPending)
{
if(FALSE == GetOverlappedResult(hComPort, &oEventHandler, &readTotal, TRUE))
{
printf("GetOverlappedResult failed with error:\r\n");
PrintLastErrorText();
}
}
}
CloseSerialConnection(&hComPort);
return 0;
}
The comport.c:
#include <stdio.h>
#include "comport.h"
#include "utils.h"
int IsValidComNumber(int com)
{
if ((com < 1) ||
(com > 256))
{
return 0;
}
return 1;
}
int IsValidBaud(int baud)
{
switch(baud)
{
case CBR_110:
case CBR_300:
case CBR_600:
case CBR_1200:
case CBR_2400:
case CBR_4800:
case CBR_9600:
case CBR_14400:
case CBR_19200:
case CBR_38400:
case CBR_56000:
case CBR_57600:
case CBR_115200:
case CBR_128000:
case CBR_256000:
{
return 1;
break;
}
default:
{
break;
}
}
return 0;
}
int IsValidBits(int bits)
{
if ((bits < 5) ||
(bits > 8))
{
return 0;
}
else
{
return 1;
}
}
int CreateSerialConnection(HANDLE* handle, OVERLAPPED* overlapped, int portNumber, int baud, int bits, enum ParType parity, enum StopType stopbits)
{
DCB dcb;
COMMTIMEOUTS timeouts;
TCHAR portVirtualFile[32];
// For serial port name this format must be used (as virtual file): "\\\\.\\COMx"
memset(portVirtualFile, 0, 32);
#ifdef _UNICODE
swprintf(portVirtualFile, 32, L"\\\\.\\COM%d", portNumber);
#else
sprintf_s(portVirtualFile, 32, "\\\\.\\COM%d", portNumber);
#endif
if(0 == IsValidBaud(baud))
{
printf("ERROR: Specified baud rate %d is invalid for serial connection to COM%d.\r\n", baud, portNumber);
return 0;
}
if(0 == IsValidBits(bits))
{
printf("ERROR: Specified number of data bits %d is invalid for serial connection to COM%d.\r\n", bits, portNumber);
return 0;
}
*handle = CreateFile(portVirtualFile, // Specify port device
GENERIC_READ | GENERIC_WRITE, // Specify mode that open device.
0, // the devide isn't shared.
NULL, // the object gets a default security.
OPEN_EXISTING, // Specify which action to take on file.
FILE_FLAG_OVERLAPPED, // Use overlapped I/O.
NULL); // default.
if(*handle == INVALID_HANDLE_VALUE)
{
printf("ERROR: Opening serial port COM%d failed\r\n", portNumber);
return 0;
}
if(FALSE == GetCommState(*handle, &dcb))
{
printf("ERROR: Getting current state of COM%d\r\n", portNumber);
PrintLastErrorText();
return 0;
}
memset(&dcb, 0, sizeof(dcb)); //zero initialize the structure
dcb.DCBlength = sizeof(dcb); //fill in length
dcb.BaudRate = baud; // baud rate
dcb.ByteSize = bits; // data size, xmit and rcv
dcb.Parity = parity; // parity bit
dcb.StopBits = stopbits; // stop bits
if(FALSE == SetCommState(*handle, &dcb))
{
printf("ERROR: Setting new state of COM%d failed.\r\n", portNumber);
PrintLastErrorText();
return 0;
}
if(FALSE == SetCommMask(*handle, EV_RXCHAR | EV_CTS | EV_RLSD))
{
printf("ERROR: Setting new COM MASK (events) for COM%d failed.\r\n", portNumber);
PrintLastErrorText();
return 0;
}
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
if(FALSE == SetCommTimeouts(*handle, &timeouts))
{
printf("ERROR: Setting timeout parameters for COM%d failed.\r\n", portNumber);
PrintLastErrorText();
return 0;
}
(*overlapped).hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
if(NULL == overlapped->hEvent)
{
printf("ERROR: CreateEvent for COM%d failed.\r\n", portNumber);
PrintLastErrorText();
return 0;
}
// Initialize the rest of the OVERLAPPED structure to zero.
overlapped->Internal = 0;
overlapped->InternalHigh = 0;
overlapped->Offset = 0;
overlapped->OffsetHigh = 0;
return 1;
}
int CloseSerialConnection(HANDLE* handle)
{
if(FALSE == CloseHandle(*handle))
{
printf("ERROR: Cannot close handle 0x8.8%X\r\n", *handle);
PrintLastErrorText();
return 0;
}
*handle = NULL;
return 1;
}
int ReadSerial(HANDLE* handle, LPOVERLAPPED ov, int num, char* buffer, int max_len)
{
DWORD readTotal = 0;
if(FALSE == ClearCommError(*handle, NULL, NULL))
{
printf("ClearCommError failed with error:\r\n");
PrintLastErrorText();
return 0;
}
else
{
memset(buffer, 0, max_len);
if(FALSE == ReadFile(*handle, buffer, max_len, &readTotal, ov))
{
printf("ERROR: Reading from port COM%d failed\r\n", num);
if(ERROR_IO_PENDING == GetLastError())
{
printf("I/O is pending (ReadFile)...\r\n");
if(FALSE == GetOverlappedResult(*handle, ov, &readTotal, TRUE))
{
printf("GetOverlappedResult failed with error:\r\n");
PrintLastErrorText();
return 0;
}
}
else
{
PrintLastErrorText();
return 0;
}
}
else
{
PrintCurrentDateTime();
printf("Received %d characters on port COM%d: ", readTotal, num);
PrintBufferContent(buffer, readTotal);
}
}
return 1;
}
The utils.c:
#include <Windows.h>
#include <stdio.h>
#include "utils.h"
void PrintLastErrorText(void)
{
DWORD retSize;
LPTSTR pTemp = NULL;
retSize = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL, GetLastError(), LANG_NEUTRAL, (LPTSTR)&pTemp, 0, NULL);
if ((retSize > 0) &&
(pTemp != NULL))
{
printf("Last error: %s (0x%08X)\r\n", pTemp, GetLastError());
LocalFree((HLOCAL)pTemp);
}
}
void PrintCurrentDateTime(void)
{
SYSTEMTIME systime;
GetLocalTime(&systime);
printf("%04d.%02d.%02d %02d:%02d:%02d:%03d ", systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute, systime.wSecond, systime.wMilliseconds);
}
void PrintBufferContent(char* buff, int len)
{
int i;
for(i = 0; i<len; i++)
{
printf("%02X ", buff[i]);
}
}
You're using the same OVERLAPPED structure for WaitCommEvent and ReadFile. Try using separate/independent OVERLAPPED for each.
UPDATE: Ignore that previous answer.
If your call to WaitCommEvent returns ERROR_IO_PENDING, you're not waiting for it to complete. Rather than loop around and call WaitCommEvent again, you need to wait for the operation to complete (typically via GetOverlappedResult).
You cannot have multiple pending asynchronous requests share a single OVERLAPPED structure. By looping and calling WaitCommEvent again after ERROR_IO_PENDING, that's exactly what's happening.

How to set l2tp preshared key?

I need to create RASENTRY for L2TP with pre-shared key set. So far, I can see that entry has somewhat correct flags, but no key is set, unfortunately.
Here is code:
int common_ras_manager_create_entry(const char* server_address, const char* username, const char* password, MY_VPN_CONNECTION_TYPE connection_type, const char* preshared_key)
{
DWORD EntryInfoSize = 0;
DWORD DeviceInfoSize = 0;
DWORD Ret;
LPRASENTRY lpRasEntry;
LPBYTE lpDeviceInfo;
// Get buffer sizing information for a default phonebook entry
if ((Ret = RasGetEntryProperties(NULL, "", NULL, &EntryInfoSize, lpDeviceInfo, &DeviceInfoSize)) != 0)
{
if (Ret != ERROR_BUFFER_TOO_SMALL)
{
printf("RasGetEntryProperties sizing failed with error %d\n", Ret);
return Ret;
}
}
lpRasEntry = (LPRASENTRY) GlobalAlloc(GPTR, EntryInfoSize);
if (DeviceInfoSize == 0)
lpDeviceInfo = NULL;
else
lpDeviceInfo = (LPBYTE) GlobalAlloc(GPTR, DeviceInfoSize);
// Get default phonebook entry
lpRasEntry->dwSize = sizeof(RASENTRY);
if ((Ret = RasGetEntryProperties(NULL, "", lpRasEntry, &EntryInfoSize, lpDeviceInfo, &DeviceInfoSize)) != 0)
{
printf("RasGetEntryProperties failed with error %d\n", Ret);
return Ret;
}
// Validate new phonebook name "Testentry"
if ((Ret = RasValidateEntryName(NULL, APP_NAME)) != ERROR_SUCCESS)
{
printf("RasValidateEntryName failed with error %d\n", Ret);
if (Ret != ERROR_ALREADY_EXISTS)
return Ret;
}
LPRASDEVINFO ras_devices;
DWORD cb =sizeof(RASDEVINFO);
DWORD cbDevices = 0;
ras_devices = (LPRASDEVINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
if (NULL == ras_devices)
{
printf("HeapAlloc failed.\n");
return ERROR_OUTOFMEMORY;
}
ras_devices->dwSize = sizeof(RASDEVINFO);
if ((Ret = RasEnumDevices(ras_devices, &cb, &cbDevices)) != ERROR_SUCCESS)
{
printf("RasEnumDevices failed with error %d\n", Ret);
switch(Ret)
{
case ERROR_BUFFER_TOO_SMALL:
printf("buffer too small");
HeapFree(GetProcessHeap(), 0, (LPVOID)ras_devices);
ras_devices = (LPRASDEVINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
if (NULL == ras_devices)
{
printf("HeapAlloc failed.\n");
return ERROR_OUTOFMEMORY;
}
ras_devices->dwSize = sizeof(RASDEVINFO);
Ret = RasEnumDevices(ras_devices, &cb, &cbDevices);
if (ERROR_SUCCESS == Ret)
{
//fSuccess = TRUE;
}
else
{
printf("RasEnumDevices failed again: Error = %d\n", Ret);
return Ret;
//goto done;
}
break;
case ERROR_NOT_ENOUGH_MEMORY:
printf("ERROR_NOT_ENOUGH_MEMORY");
return Ret;
break;
case ERROR_INVALID_PARAMETER:
printf("ERROR_INVALID_PARAMETER");
return Ret;
break;
case ERROR_INVALID_USER_BUFFER:
printf("ERROR_INVALID_USER_BUFFER");
return Ret;
break;
}
}
DWORD dwVpnStrategy = 0;
char device_name_mask[5];
strcpy(device_name_mask, "");
gboolean preshared_key_valid = 0;
switch(connection_type)
{
case PPTP:
strcpy(device_name_mask, "PPTP");
dwVpnStrategy = VS_PptpOnly;
break;
case L2TP:
if (preshared_key == 0 || strlen(preshared_key) == 0)
{
printf("CRITICAL: preshared key not set.");
return 1;
}
else
{
preshared_key_valid = TRUE;
}
strcpy(device_name_mask, "L2TP");
dwVpnStrategy = VS_L2tpOnly;
break;
}
int i =0;
for (i = 0; i < cbDevices; i++)
{
RASDEVINFO r = ras_devices[i];
if (strstr(r.szDeviceName, device_name_mask))
{
break;
}
}
//lpRasEntry->dwfOptions |= RASEO_SpecificIpAddr;
//lpRasEntry->szLocalPhoneNumber = RASDT_Vpn;
lpRasEntry->dwfNetProtocols |= RASNP_Ip;
lpRasEntry->dwFramingProtocol = RASFP_Ppp;
lstrcpy(lpRasEntry->szDeviceType, RASDT_Vpn);
lstrcpy(lpRasEntry->szDeviceName, ras_devices[i].szDeviceName);
lstrcpy(lpRasEntry->szLocalPhoneNumber, server_address);
lpRasEntry->dwVpnStrategy = dwVpnStrategy; // VS_PptpOnly; VS_SstpOnly
if (preshared_key_valid)
{
L2TP_CONFIG_DATA* data = GlobalAlloc(GPTR, sizeof(L2TP_CONFIG_DATA));
lpRasEntry->dwfOptions2 |= RASEO2_UsePreSharedKey;
data->dwOffsetKey = 16;
memcpy((PBYTE)data + data->dwOffsetKey, preshared_key, strlen(preshared_key));
data->dwAuthType =L2TP_IPSEC_AUTH_PRESHAREDKEY;
RasSetCustomAuthData(NULL, APP_NAME, data, sizeof(L2TP_CONFIG_DATA));
}
if ((Ret = RasSetEntryProperties(NULL, APP_NAME, lpRasEntry, EntryInfoSize, lpDeviceInfo, DeviceInfoSize)) != 0)
{
printf("RasSetEntryProperties failed with error %d\n", Ret);
return Ret;
}
//if ((Ret = RasSetCredentials(NULL, lpRasEntry.))
}
I cant find where is buffer to fill for pre-shared key.
Following code works fine.
// l2tp
if (preshared_key_valid)
{
RASCREDENTIALS ras_cre_psk = {0};
ras_cre_psk.dwSize = sizeof(ras_cre_psk);
ras_cre_psk.dwMask = 0x00000010; //RASCM_PreSharedKey;
wcscpy(ras_cre_psk.szPassword, preshared_key);
if ((Ret = RasSetCredentials(NULL, APP_NAME, &ras_cre_psk, FALSE)))
{
printf("RasSetCredentials failed with error %d\n", Ret);
return Ret;
}
}

Windows Service implementation - Error 1053: The service did not respond to start or control request in a timely fashion

I am trying to make a small Windows service in C but get stuck on where is the issue. Once I start it in Windows services, I recieve error:
"Windows could not start the MyService service on local computer.
Error 1053: The service did not respond to start or control request in a timely fashion."
#include <unistd.h>
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "log.h"
#define SERVICE "MyService"
#define SERVICE_UNKNOW 0x00000000
#define SERVICE_REFRESH 0xFFFFFFFF
SERVICE_STATUS_HANDLE serviceHandle;
void ServiceUpdateStatus(SERVICE_STATUS_HANDLE serviceHandle, DWORD newState)
{
static SERVICE_STATUS serviceStatus;
if (newState == SERVICE_UNKNOW)
{
serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwWin32ExitCode = NO_ERROR;
serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
serviceStatus.dwCheckPoint = 0;
serviceStatus.dwWaitHint = 0;
newState = SERVICE_STOPPED;
}
switch(newState)
{
case SERVICE_START_PENDING:
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
serviceStatus.dwControlsAccepted = 0;
SetServiceStatus(serviceHandle, &serviceStatus);
add_log("Service start pending");
break;
case SERVICE_RUNNING:
serviceStatus.dwCurrentState = SERVICE_RUNNING;
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN;
SetServiceStatus(serviceHandle, &serviceStatus);
add_log("Service running");
break;
case SERVICE_STOP_PENDING:
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
serviceStatus.dwControlsAccepted = 0;
SetServiceStatus(serviceHandle, &serviceStatus);
add_log("Service stop pending");
break;
case SERVICE_STOPPED:
serviceStatus.dwCurrentState = SERVICE_STOPPED;
serviceStatus.dwControlsAccepted = 0;
SetServiceStatus(serviceHandle, &serviceStatus);
add_log("Service stopped");
break;
case SERVICE_REFRESH:
SetServiceStatus(serviceHandle, &serviceStatus);
break;
}
}
void WINAPI ServiceControlHandler(DWORD controlCode)
{
switch (controlCode)
{
case SERVICE_CONTROL_PAUSE:
case SERVICE_CONTROL_CONTINUE:
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
/* stop service */
ServiceUpdateStatus(serviceHandle, SERVICE_STOP_PENDING);
make_ServiceMainThread_to_return();
WSACleanup();
/* stopped */
ServiceUpdateStatus(serviceHandle, SERVICE_STOPPED);
break;
}
ServiceUpdateStatus(serviceHandle, SERVICE_REFRESH);
}
DWORD ServiceMainThread(LPVOID parameters)
{
do_something_and_never_return();
return EXIT_SUCCESS;
}
VOID WINAPI ServiceMain(DWORD argc, char *argv[])
{
WSADATA wsa;
HANDLE mainThread;
serviceHandle = RegisterServiceCtrlHandler(SERVICE, ServiceControlHandler);
if(!serviceHandle)
{
add_log("Error: RegisterServiceCtrlHandler, error %u", (unsigned int)GetLastError());
return;
}
/* init service */
ServiceUpdateStatus(serviceHandle, SERVICE_START_PENDING);
if (WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
add_log("Error: WSAStartup, error %u", (unsigned int)GetLastError());
return;
}
mainThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&ServiceMainThread, NULL, 0, NULL);
if (mainThread == NULL)
{
ServiceUpdateStatus(serviceHandle, SERVICE_STOPPED);
add_log("Error: Unable to create service thread, error %u", (unsigned int)GetLastError());
return;
}
add_log("Service main thread: %u", (unsigned int)mainThread);
CloseHandle(mainThread);
/* run service */
ServiceUpdateStatus(serviceHandle, SERVICE_RUNNING);
}
void LaunchService()
{
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = SERVICE;
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
if (!StartServiceCtrlDispatcher(ServiceTable))
{
add_log("Error: StartServiceCtrlDispatcher, error %u", (unsigned int)GetLastError());
}
}
void InstallService()
{
SC_HANDLE scManager;
char path[MAX_PATH+1];
scManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE );
if (scManager)
{
if (GetModuleFileName( 0, path, sizeof(path)) > 0)
{
SC_HANDLE service;
service = CreateService(scManager, SERVICE, SERVICE, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path, 0, 0, 0, 0, 0 );
if (service)
CloseServiceHandle(service);
}
CloseServiceHandle(scManager);
}
}
void UninstallService()
{
SC_HANDLE scManager;
SC_HANDLE scService;
SERVICE_STATUS serviceStatus;
scManager = OpenSCManager( 0, 0, SC_MANAGER_CONNECT );
if (scManager)
{
scService = OpenService(scManager, SERVICE, SERVICE_QUERY_STATUS|DELETE);
if (scService)
{
if (QueryServiceStatus(scService, &serviceStatus))
{
if (serviceStatus.dwCurrentState == SERVICE_STOPPED)
DeleteService(scService);
}
CloseServiceHandle(scService);
}
CloseServiceHandle(scService);
}
}
int main(int argc, char *argv[])
{
if(strcmpi(argv[1], "install") == 0)
{
InstallService();
return EXIT_SUCCESS;
}
else if(strcmpi(argv[1], "uninstall") == 0)
{
UninstallService();
return EXIT_SUCCESS;
}
LaunchService();
return EXIT_SUCCESS;
}
Any ideas maybe?
Thanks in advance,
I found the issue.
During *_PENDING operation, we must specify the dwWaitHint field.
SetServiceStatus was reporting an error due to this and never updating the service status.
My corrected function ServiceUpdateStatus:
#define SERVICE_REFRESH 0xFFFFFFFF
// ...
void ServiceUpdateStatus(DWORD newState)
{
static SERVICE_STATUS serviceStatus;
serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwWin32ExitCode = NO_ERROR;
serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
switch(newState)
{
case SERVICE_START_PENDING:
serviceStatus.dwControlsAccepted = 0;
serviceStatus.dwCheckPoint = 1;
serviceStatus.dwWaitHint = 1000;
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
add_log("Service start pending");
break;
case SERVICE_RUNNING:
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN;
serviceStatus.dwCheckPoint = 0;
serviceStatus.dwCurrentState = SERVICE_RUNNING;
add_log("Service running");
break;
case SERVICE_STOP_PENDING:
serviceStatus.dwControlsAccepted = 0;
serviceStatus.dwCheckPoint = 1;
serviceStatus.dwWaitHint = 1000;
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
add_log("Service stop pending");
break;
case SERVICE_STOPPED:
serviceStatus.dwControlsAccepted = 0;
serviceStatus.dwCheckPoint = 0;
serviceStatus.dwCurrentState = SERVICE_STOPPED;
add_log("Service stopped");
break;
case SERVICE_REFRESH:
if (serviceStatus.dwCurrentState == SERVICE_STOP_PENDING &&
serviceStatus.dwCurrentState == SERVICE_START_PENDING)
serviceStatus.dwCheckPoint++;
break;
}
if (!SetServiceStatus(serviceHandle, &serviceStatus))
add_log("SetServiceStatus failed, error %u", GetLastError());
}
// ...

Resources