Access violation when getting network adapters with GetAdaptersAddresses in C - 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));

Related

How do I read a dbus array of dicts with the c api sd-bus?

I am try to read a dbus data structure that looks like this a{sv} with sd-bus but when i use the code down below i can only read one of the 8 dicts.
#include <stdio.h>
#include <stdlib.h>
#include <systemd/sd-bus.h>
int main ()
{
sd_bus *bus = NULL;
sd_bus_error err = SD_BUS_ERROR_NULL;
sd_bus_message *msg = NULL;
char const *sign;
int signi = 0;
int error;
sd_bus_default_user (&bus);
sd_bus_get_property (bus,
"org.mpris.MediaPlayer2.plasma-browser-integration",
"/org/mpris/MediaPlayer2",
"org.mpris.MediaPlayer2.Player",
"Metadata", &err, &msg, "a{sv}");
sign = sd_bus_message_get_signature (msg, signi);
error = sd_bus_message_enter_container (msg, SD_BUS_TYPE_ARRAY, "{sv}");
while (error =
sd_bus_message_enter_container (msg, SD_BUS_TYPE_DICT_ENTRY,
"sv") > 0) {
const char *key;
sd_bus_message_read_basic (msg, SD_BUS_TYPE_STRING, &key);
sign = sd_bus_message_get_signature (msg, signi);
printf ("returned: %s \n", key);
sd_bus_message_exit_container (msg);
}
sd_bus_message_exit_container (msg);
if (err._need_free != 0) {
printf ("%d \n", error);
printf ("returned error: %s\n", err.message);
}
else {
printf ("%s", sign);
}
sd_bus_error_free (&err);
sd_bus_unref (bus);
return 0;
}
I have looked up the function sd_bus_message_enter_container on hotexamples.com and all of them seemed to have while more than one loop around the function that enters the dict it seemed to me that this would loop an tell it had all of the values but this dose not seem to work i also tried using the loop with the function that entered the array and that did not work. another way that tried is to run a for loop that cycled 8 times after that i tried to look for other solutions and there are none that i can see. i also use the documtation on freedesktops web site (https://www.freedesktop.org/software/systemd/man/sd-bus.html) i have it working with gdbus but as far as i understand that is depreciated. how come this is not working i don't understand.
Thank you in advance for your help.
I did not realise that I had to read each value otherwise it will throw an error and if you don't want to there is a skip function.
this is the code that worked
#include <stdio.h>
#include <stdlib.h>
#include <systemd/sd-bus.h>
#include <stdbool.h>
#include <string.h>
int bus_print_property(const char *name, sd_bus_message *property) {
char type;
const char *contents;
int r;
r = sd_bus_message_peek_type(property, &type, &contents);
if (r < 0)
return r;
switch (type) {
case SD_BUS_TYPE_STRING: {
const char *s;
r = sd_bus_message_read_basic(property, type, &s);
if (r < 0)
return r;
printf("%s=%s\n", name, s);
return 1;
}
case SD_BUS_TYPE_BOOLEAN: {
bool b;
r = sd_bus_message_read_basic(property, type, &b);
if (r < 0)
return r;
printf("%s\n", name);
return 1;
}
case SD_BUS_TYPE_INT64: {
int64_t i64;
r = sd_bus_message_read_basic(property, type, &i64);
if (r < 0)
return r;
printf("%s=%i\n", name, (int) i64);
return 1;
}
case SD_BUS_TYPE_INT32: {
int32_t i;
r = sd_bus_message_read_basic(property, type, &i);
if (r < 0)
return r;
printf("%s=%i\n", name, (int) i);
return 1;
}
case SD_BUS_TYPE_OBJECT_PATH:{
const char *p;
r = sd_bus_message_read_basic(property, type, &p);
if (r < 0)
return r;
printf("%s=%s\n", name, p);
return 1;
}
case SD_BUS_TYPE_DOUBLE: {
double d;
r = sd_bus_message_read_basic(property, type, &d);
if (r < 0)
return r;
printf("%s=%g\n", name, d);
return 1;
}
case SD_BUS_TYPE_ARRAY:
if (strcmp(contents, "s")==0) {
bool first = true;
const char *str;
r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
if (r < 0)
return r;
while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
if (first)
printf("%s=", name);
printf("%s%s", first ? "" : " ", str);
first = false;
}
if (r < 0)
return r;
if (first )
printf("%s=", name);
if (!first )
puts("");
r = sd_bus_message_exit_container(property);
if (r < 0)
return r;
return 1;
} else {
printf("array unreadable");
return 0;
}
break;
}
return 0;
}
int main()
{
sd_bus* bus = NULL;
sd_bus_error err = SD_BUS_ERROR_NULL;
sd_bus_message *msg = NULL;
int error;
sd_bus_default_user(&bus);
sd_bus_get_property(bus,
"org.mpris.MediaPlayer2.plasma-browser-integration",
"/org/mpris/MediaPlayer2",
"org.mpris.MediaPlayer2.Player",
"Metadata",
&err,&msg,"a{sv}");
error = sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY, "{sv}");
if (error < 0)
return error;
while ((error = sd_bus_message_enter_container(msg, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
const char *name;
const char *contents;
error = sd_bus_message_read_basic(msg, SD_BUS_TYPE_STRING, &name);
if (error < 0)
return error;
error = sd_bus_message_peek_type(msg, NULL, &contents);
if (error < 0)
return error;
error = sd_bus_message_enter_container(msg, SD_BUS_TYPE_VARIANT, contents);
if (error < 0)
return error;
error = bus_print_property(name, msg);
if (error < 0)
return error;
if (error == 0) {
printf("%s=[unprintable]\n", name);
/* skip what we didn't read */
error = sd_bus_message_skip(msg, contents);
if (error < 0)
return error;
}
error = sd_bus_message_exit_container(msg);
if (error < 0)
return error;
error = sd_bus_message_exit_container(msg);
if (error < 0)
return error;
}
if (error < 0)
return error;
error = sd_bus_message_exit_container(msg);
if (error < 0)
return error;
if(err._need_free!=0){
printf("%d \n",error);
printf("returned error: %s\n",err.message);
}else{
}
sd_bus_error_free(&err);
sd_bus_unref(bus);
return 0;
}

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.

C - segmentation fault on long running while loop

I wrote small daemon for rotating screen on Thinkpad X41 convertible laptop using built-in motion sensor (used by harddisk active protection system) or manually by button. Program works very well, but after some amount of time (5 to 15 minutes) will crash with segfault.
I know there are lot of scripts on the internet to do this written in bash or python, but none of them suit my needs and vision how should program work.
I know that for example mentioned bash is probably better for this, but I have zero experiences with it compared to C In which I have at least minimal basic experiences from few high school lessons, so I choose this.
here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#define TRUE 1
#define FALSE 0
#define NIL -1
#define XRANDR_GREP_COMMAND "xrandr -q --verbose|grep LVDS1|cut -b37-37"
#define DAEMON_LOCK_FILE "/dev/shm/thinkrotate.lock"
#define DAEMON_STATE_FILE "/dev/shm/thinkrotate.st"
#define SWIVEL_STATE_FILE "/sys/devices/platform/thinkpad_acpi/hotkey_tablet_mode"
#define GYRO_STATE_FILE "/sys/devices/platform/hdaps/position"
#define BUBBLE_TERMINATED "notify-send 'Ukončenie programu' 'ThinkRotate démon dostal príkaz na ukončenie'"
#define BUBBLE_SWIVEL_DOWN "notify-send 'Notebook v tablet móde' 'Veko bolo sklopené, aktivovaná automatická rotácia'"
#define BUBBLE_SWIVEL_UP "notify-send 'Notebook v štandartnom režime' 'Rotácia je deaktivovaná'"
#define BUBBLE_RETURN_POSITION "notify-send 'Automatická rotácia zapnutá' 'Pre vypnutie automatickej rotácie obrazu stlačte tlačítko rotácie.'"
#define BUBBLE_START_MANUAL_ROTATION "notify-send 'Automatická rotácia vypnutá' 'Rotácia bude zapnutá znovu až pri návrate do tejto polohy, dovtedy na otáčanie obrazu používajte tlačidlo.'"
#define SWIVEL_DOWN_COMMANDS ""
#define SWIVEL_UP_COMMANDS ""
#define WIDTH_COMMANDS ""
#define HEIGHT_COMMANDS ""
int get_lock(void) {
int fdlock;
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 1;
if((fdlock = open(DAEMON_LOCK_FILE, O_WRONLY|O_CREAT, 0666)) == -1) { return 0; }
if(fcntl(fdlock, F_SETLK, &fl) == -1) { return 0; }
return 1;
}
int next_rotation(int direction) {
int next;
int pos;
pos = current_pos();
if (direction == 1) {
switch (pos) {
case 0:
next = 1;
break;
case 1:
next = 2;
break;
case 2:
next = 3;
break;
case 3:
next = 0;
break;
}
} else if (direction == 2) {
switch (pos) {
case 0:
next = 3;
break;
case 1:
next = 0;
break;
case 2:
next = 1;
break;
case 3:
next = 2;
break;
}
}
return next;
}
int current_pos(void) {
FILE *frotpos;
char rotpos;
int pos;
frotpos = popen(XRANDR_GREP_COMMAND, "r");
fscanf(frotpos, "%c", &rotpos);
fclose(frotpos);
switch (rotpos) {
case 110:
pos = 0;
break;
case 108:
pos = 1;
break;
case 105:
pos = 2;
break;
case 114:
pos = 3;
break;
}
return pos;
}
void rotate(int poz) {
char buff[32];
if ((poz == 2)||(poz == 0)) {
system(WIDTH_COMMANDS);
} else {
system(HEIGHT_COMMANDS);
}
sprintf(buff, "xrandr -o %i", poz);
system(buff);
}
int main(int argc, char *argv[]) {
if(!get_lock()) {
if (argc >= 2) {
int cmd;
FILE *fparams;
fparams = fopen(DAEMON_STATE_FILE, "w");
if (!strncmp(argv[1], "r", 1)) { cmd = 1; }
else if (!strncmp(argv[1], "l", 1)) { cmd = 2; }
else if (!strncmp(argv[1], "k", 1)) { cmd = 0; }
fprintf(fparams, "%i", cmd);
fclose(fparams);
}
return 1;
}
int autorotate = TRUE;
int prevmode = NIL;
FILE *fstate;
int tabletmode;
FILE *fgyrovals;
char gyroval_x[5];
char gyroval_y[5];
int x;
int y;
FILE *fargs;
int argum = NIL;
int next_p;
int prev_p = current_pos();
int last_auto_p = NIL;
while (TRUE) {
fstate = fopen(SWIVEL_STATE_FILE, "r");
fscanf(fstate, "%d", &tabletmode);
if (fargs = fopen(DAEMON_STATE_FILE, "r")) {
if (fscanf(fargs, "%d", &argum) == NIL) { argum = NIL; }
}
fargs = fopen(DAEMON_STATE_FILE, "w");
fclose(fargs);
fclose(fstate);
if (argum == 0) {
system(BUBBLE_TERMINATED);
return 1;
}
if (prevmode != tabletmode) {
if (tabletmode) {
system(BUBBLE_SWIVEL_DOWN);
system(SWIVEL_DOWN_COMMANDS);
} else {
system(BUBBLE_SWIVEL_UP);
system(SWIVEL_UP_COMMANDS);
rotate(0);
}
}
if (tabletmode) {
if (argum == 1 || argum == 2) {
next_p = next_rotation(argum);
if (next_p == last_auto_p) {
rotate(next_p);
autorotate = TRUE;
last_auto_p = NIL;
system(BUBBLE_RETURN_POSITION);
} else if ((autorotate)&&(current_pos() == last_auto_p)) {
autorotate = FALSE;
system(BUBBLE_START_MANUAL_ROTATION);
} else {
if (autorotate) {
system(BUBBLE_START_MANUAL_ROTATION);
last_auto_p = current_pos();
} else {
rotate(next_p);
}
autorotate = FALSE;
}
}
if (autorotate) {
fgyrovals = fopen(GYRO_STATE_FILE, "r");
fscanf(fgyrovals, "(%4[^,], %4[^)]", &gyroval_x, &gyroval_y);
fclose(fgyrovals);
x = atoi(gyroval_x);
y = atoi(gyroval_y) * (-1);
if (y < 465) {
if (x < 210) {
next_p = 1;
} else if (x > 425) {
next_p = 3;
} else {
next_p = 2;
}
} else if (y > 525) {
if (x < 210) {
next_p = 1;
} else if (x > 425) {
next_p = 3;
} else {
next_p = 0;
}
} else {
if (x < 305) {
next_p = 1;
} else if (x > 345) {
next_p = 3;
}
}
if (next_p != prev_p) {
rotate(next_p);
prev_p = next_p;
}
}
} else {
if (argum == 1 || argum == 2) {
system(BUBBLE_SWIVEL_UP);
}
}
prevmode = tabletmode;
sleep(1);
}
return 0;
}
Thanks to comment of user "inspired". Now the program is running more than a hour without segfault.
if (fargs = fopen(DAEMON_STATE_FILE, "r")) {
if (fscanf(fargs, "%d", &argum) == NIL) { argum = NIL; }
fclose(fargs);
}
fargs = fopen(DAEMON_STATE_FILE, "w");
fclose(fargs);
As said, file should be closed before opened next time for writing.

Fix Buffer Overflow Exploit on Web Server

I have a buffer overflow vulnerability in a simple webserver. It can be exploited with a http GET request. I'm having trouble figuring out how to fix it. My guess is that it has to do with: char hdrval[1024]; but I could be wrong. Can anyone else see whats wrong?
Code:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <pthread.h>
#define _XOPEN_SOURCE
typedef struct {
char *method;
char *uri;
char *version;
char *headers;
} httpreq_t;
/* NOTE: this function is based on a function provided in the GNU "timegm" man
page. timegm is a GNU extension to time.h that returns the given tm struct as
a UNIX timestamp in GMT/UTC, rather than local time. The man page suggests a
function similar to the one below as a portable equivalent.
*/
time_t my_timegm(struct tm *tm) {
time_t ret;
char *tz;
tz = getenv("TZ");
putenv("TZ=GMT");
tzset();
ret = mktime(tm);
if (tz) {
char envstr[strlen(tz) + 4];
envstr[0] = '\0';
strcat(envstr, "TZ=");
strcat(envstr, tz);
putenv(envstr);
} else {
putenv("TZ=");
}
tzset();
return ret;
}
char *get_header(const httpreq_t *req, const char* headername) {
char *hdrptr;
char *hdrend;
char *retval = NULL;
char searchstr[strlen(headername) + 5];
strcpy(searchstr, "\r\n");
strcat(searchstr, headername);
strcat(searchstr, ": ");
if (hdrptr = strstr(req->headers, searchstr)) {
hdrptr += strlen(searchstr);
if (hdrend = strstr(hdrptr, "\r\n")) {
char hdrval[1024]; // temporary return value
memcpy((char *)hdrval, hdrptr, (hdrend - hdrptr));
hdrval[hdrend - hdrptr] = '\0'; // tack null onto end of header value
int hdrvallen = strlen(hdrval);
retval = (char *)malloc((hdrvallen + 1) * sizeof(char)); // malloc a space for retval
strcpy(retval, (char *)hdrval);
} else {
retval = (char *)malloc((strlen(hdrptr) + 1) * sizeof(char)); //
strcpy(retval, hdrptr);
}
}
return retval;
}
/* As long as str begins with a proper HTTP-Version followed by delim, returns a
pointer to the start of the version number (e.g., 1.0). Returns NULL otherwise.
*/
char *http_version_str(char *str, char *delim) {
char *vstart = strstr(str, "HTTP/");
char *vnumstart = str + 5;
char *vdot = strchr(str, '.');
char *vend = strstr(str, delim);
char *digits = "0123456789";
int majvlen = 0;
int minvlen = 0;
if (!vstart || !vdot // something's missing
|| vstart != str) // str doesn't start with "HTTP/"
return NULL;
majvlen = strspn(vnumstart, digits);
minvlen = strspn(vdot + 1, digits);
if (majvlen < 1 || (vnumstart + majvlen) != vdot // bad major version
|| minvlen < 1 || (vdot + minvlen + 1) != vend) // bad minor version
return NULL;
return vnumstart;
}
/* Fills req with the request data from datastr. Returns 0 on success.
*/
int parsereq(httpreq_t *req, char *datastr) {
char *position;
char *last_position = datastr;
char *temp_position;
int matchlen;
req->method = "";
req->uri = "";
req->version = "";
req->headers = "";
if (!(position = strchr(last_position, ' '))) {
return 1;
}
matchlen = (int)(position - last_position);
req->method = (char *)malloc((matchlen + 1) * sizeof(char));
memcpy(req->method, last_position, matchlen);
req->method[matchlen] = '\0';
last_position = position + 1;
if (!(position = strchr(last_position, ' '))
&& !(position = strstr(last_position, "\r\n"))) {
return 1;
}
// strip any query string out of the URI
if ((temp_position = strchr(last_position, '?')) && temp_position < position)
matchlen = (int)(temp_position - last_position);
else
matchlen = (int)(position - last_position);
req->uri = (char *)malloc((matchlen + 1) * sizeof(char));
memcpy(req->uri, last_position, matchlen);
req->uri[matchlen] = '\0';
if (position[0] == '\r') {
req->version = "0.9";
req->headers = "";
return 0; // simple req -- uri only
}
// If we get here, it's a full request, get the HTTP version and headers
last_position = position + 1;
if (!(position = strstr(last_position, "\r\n"))
|| !(last_position = http_version_str(last_position, "\r\n"))) {
return 1;
}
matchlen = (int)(position - last_position);
req->version = (char *)malloc((matchlen + 1) * sizeof(char));
memcpy(req->version, last_position, matchlen);
req->version[matchlen] = '\0';
last_position = position;
req->headers = (char *)malloc(strlen(last_position) * sizeof(char));
strcpy(req->headers, last_position);
return 0;
}
char *contype(char *ext) {
if (strcmp(ext, "html") == 0) return "text/html";
else if (strcmp(ext, "htm") == 0) return "text/html";
else if (strcmp(ext, "jpeg") == 0) return "image/jpeg";
else if (strcmp(ext, "jpg") == 0) return "image/jpeg";
else if (strcmp(ext, "gif") == 0) return "image/gif";
else if (strcmp(ext, "txt") == 0) return "text/plain";
else return "application/octet-stream";
}
char *status(int statcode) {
if (statcode == 200) return "200 OK";
else if (statcode == 304) return "304 Not Modified";
else if (statcode == 400) return "400 Bad Request";
else if (statcode == 403) return "403 Forbidden";
else if (statcode == 404) return "404 Not Found";
else if (statcode == 500) return "500 Internal Server Error";
else if (statcode == 501) return "501 Not Implemented";
else return "";
}
int send_response(int sockfd, httpreq_t *req, int statcode) {
int urifd;
const int BUFSIZE = 1024;
char sendmessage[BUFSIZE];
char *path = req->uri;
if (req->uri == NULL || req->method == NULL ||
req->headers == NULL || req->version == NULL) {
return 0;
}
if ((path[0] == '/') || ((strstr(path, "http://") == path)
&& (path = strchr(path + 7, '/')))) {
path += 1; // remove leading slash
if (path[0] == '\0') { // substituting in index.html for a blank URL!
path = "index.html";
} else if (path[strlen(path) - 1] == '/') {
//concatenating index.html for a /-terminated URL!
strcat(path, "index.html");
}
} else {
statcode = 400;
}
if (statcode == 200 && (urifd = open(path, O_RDONLY, 0)) < 0) {
if (errno == ENOENT || errno == ENOTDIR) { // file or directory doesn't exist
statcode = 404;
} else if (errno == EACCES) { // access denied
statcode = 403;
} else {
// some other file access problem
statcode = 500;
}
}
if (strstr(path, "..") != NULL) {
statcode = 500;
}
sendmessage[0] = '\0';
if (strcmp(req->version, "0.9") != 0) { // full request
char *ext; // file extension
time_t curtime;
char *imstime;
struct tm tm;
struct stat stbuf;
if (statcode == 200) {
if (ext = strrchr(path, '.')) ext++; // skip the '.'
else ext = "";
} else {
// errors are always html messages
ext = "html";
}
// Conditional GET
if ((strcmp(req->method, "GET") == 0)
&& (statcode == 200)
&& (imstime = get_header(req, "If-Modified-Since"))) {
// Get statistics about the requested URI from the local filesystem
if (stat(path, &stbuf) == -1) {
statcode = 500;
}
if (!strptime(imstime, "%a, %d %b %Y %H:%M:%S GMT", &tm)
&& !strptime(imstime, "%a, %d-%b-%y %H:%M:%S GMT", &tm)
&& !strptime(imstime, "%a %b %d %H:%M:%S %Y", &tm)) {
// badly formatted date
statcode = 400;
}
if (stbuf.st_mtime <= my_timegm(&tm)) {
// Not Modified
statcode = 304;
}
}
time(&curtime); // time for Date: header
strcat(sendmessage, "HTTP/1.0 ");
strcat(sendmessage, status(statcode));
strcat(sendmessage, "\r\nDate: ");
strncat(sendmessage, asctime(gmtime(&curtime)), 24);
strcat(sendmessage, "\r\nServer: Frobozz Magic Software Company Webserver v.002");
strcat(sendmessage, "\r\nConnection: close");
strcat(sendmessage, "\r\nContent-Type: ");
strcat(sendmessage, contype(ext));
strcat(sendmessage, "\r\n\r\n");
}
if (statcode != 200) {
strcat(sendmessage, "<html><head><title>");
strcat(sendmessage, status(statcode));
strcat(sendmessage, "</title></head><body><h2>HTTP/1.0</h2><h1>");
strcat(sendmessage, status(statcode));
strcat(sendmessage, "</h1><h2>URI: ");
strcat(sendmessage, path);
strcat(sendmessage, "</h2></body></html>");
}
if (sendmessage[0] != '\0') {
// send headers as long as there are headers to send
if (send(sockfd, sendmessage, strlen(sendmessage), 0) < 0) {
perror("send");
pthread_exit(NULL);
}
}
if (statcode == 200 && (strcmp(req->method, "HEAD") != 0)) {
// send the requested file as long as there's no error and the
// request wasn't just for the headers
int readbytes;
while (readbytes = read(urifd, sendmessage, BUFSIZE)) {
if (readbytes < 0) {
perror("read");
pthread_exit(NULL);
}
if (send(sockfd, sendmessage, readbytes, 0) < 0) {
perror("send");
pthread_exit(NULL);
}
}
}
}
void *data_thread(void *sockfd_ptr) {
int sockfd = *(int *) sockfd_ptr;
const int BUFSIZE = 5;
char recvmessage[BUFSIZE];
char *headerstr = NULL;
char *newheaderstr = NULL;
int recvbytes = 0;
int curheadlen = 0;
int totalheadlen = 0;
httpreq_t req;
int statcode = 200;
int done = 0;
int seen_header = 0;
char *header_end;
int content_length = 0;
char *qstr;
free(sockfd_ptr); // we have the int value out of this now
recvmessage[BUFSIZE - 1] = '\0'; // mark end of "string"
/* Read incoming client message from the socket */
while(!done && (recvbytes = recv(sockfd, recvmessage, BUFSIZE - 1, 0))) {
if (recvbytes < 0) {
perror("recv");
pthread_exit(NULL);
}
recvmessage[recvbytes] = '\0';
if (seen_header) {
// getting the entity body
content_length -= recvbytes;
if (content_length <= 0) done = 1;
} else {
newheaderstr = (char *) malloc((totalheadlen + recvbytes + 1) * sizeof(char));
newheaderstr[totalheadlen + recvbytes] = '\0';
memcpy(newheaderstr, headerstr, totalheadlen);
memcpy(newheaderstr + totalheadlen, recvmessage, recvbytes);
if (headerstr) free(headerstr);
headerstr = newheaderstr;
totalheadlen += recvbytes;
header_end = strstr(headerstr, "\r\n\r\n");
if (header_end) {
seen_header = 1;
header_end[2] = '\0';
if (parsereq(&req, headerstr) != 0) {
statcode = 400;
}
if (strcmp(req.method, "POST") == 0) {
// grab the body length
char *clenstr = get_header(&req, "Content-Length");
if (clenstr) {
content_length = atoi(clenstr) - ((headerstr + totalheadlen) - header_end - 4);
if (content_length <= 0) done = 1;
free(clenstr);
} else {
statcode = 400; // bad request -- no content length
done = 1;
}
} else {
// This isn't a POST, so there's no entity body
done = 1;
if (strcmp(req.method, "GET") != 0
&& strcmp(req.method, "HEAD") != 0) {
statcode = 501; // unknown request method
}
}
}
}
} // end of recv while loop
// used to deref a NULL pointer here... :(
if (headerstr != NULL) {
printf("%s\n", headerstr);
free(headerstr);
}
send_response(sockfd, &req, statcode);
close(sockfd);
return NULL;
}
int main(int argc, char *argv[]) {
int acc, sockfd, clen, port;
struct hostent *he;
struct sockaddr_in caddr, saddr;
if(argc <= 1) {
fprintf(stderr, "No port specified. Exiting!\n");
exit(1);
}
port = atoi(argv[1]);
/* Obtain name and address for the local host */
if((he=gethostbyname("localhost"))==NULL) {
herror("gethostbyname");
exit(1);
}
/* Open a TCP (Internet Stream) socket */
if((sockfd=socket(AF_INET,SOCK_STREAM,0)) == -1) {
perror("socket");
exit(1);
}
/* Create socket address structure for the local host */
memset((char *) &saddr, '\0', sizeof(saddr));
saddr.sin_family=AF_INET;
saddr.sin_port=htons(port);
saddr.sin_addr.s_addr=htonl(INADDR_ANY);
/* Bind our local address so that the client can send to us */
if(bind(sockfd,(struct sockaddr *) &saddr,sizeof(saddr)) == -1) {
perror("bind");
exit(1);
}
if(listen(sockfd,5) < 0) {
perror("listen");
exit(1);
}
/* Infinite loop for receiving and processing client requests */
for(;;) {
clen=sizeof(caddr);
/* Wait for a connection for a client process */
acc=accept(sockfd,(struct sockaddr *) &caddr,(socklen_t*)&clen);
if(acc < 0) {
perror("accept");
exit(1);
} else {
pthread_t *thread = (pthread_t *) malloc(sizeof(pthread_t));
int *sockfd_ptr = (int *) malloc(sizeof(int));
*sockfd_ptr = acc;
pthread_create(thread, NULL, data_thread, sockfd_ptr);
}
}
return 0;
}
I guess you could have a bound check before copying to the buffer?
For example, add
if(hdrend - hdrptr >= 1024)
exit(1)
before
memcpy((char *)hdrval, hdrptr, (hdrend - hdrptr));
The segfault happens at the point below.
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7ff4b70 (LWP 3902)]
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7ff4b70 (LWP 3902)]
0x08049507 in send_response (sockfd=6, req=0xb7ff4340, statcode=200)
at server/webserver.c:219
warning: Source file is more recent than executable.
219 if (req->uri == NULL || req->method == NULL ||
The memory address is
(gdb) p $_siginfo._sifields._sigfault.si_addr
$3 = (void *) 0x69cb120
The code that needs to be rewritten is
214 int urifd;
215 const int BUFSIZE = 1024;
216 char sendmessage[BUFSIZE];
217 char *path = req->uri;
218
219 if (req->uri == NULL || req->method == NULL ||
220 req->headers == NULL || req->version == NULL) {
221 return 0;

How to install/deinstall a Windows service in win32?

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);
}

Resources