Revision 368d31d4
Added by Hamish Coleman about 15 years ago
- ID 368d31d4816d2b3a346918bb426efce8ba716283
| .gitignore | ||
|---|---|---|
|
# Ignore the built binaries
|
||
|
wconsd.exe
|
||
|
portenum.exe
|
||
|
svctest.exe
|
||
|
|
||
|
# Ignore the object files
|
||
|
*.o
|
||
| Makefile | ||
|---|---|---|
|
|
||
|
all: wconsd.exe portenum.exe
|
||
|
all: wconsd.exe portenum.exe svctest.exe
|
||
|
|
||
|
get:
|
||
|
pscp 192.168.1.1:s/src/wconsd/*.c ./
|
||
| ... | ... | |
|
wconsd.exe: wconsd.o $(MODULES) $(LIBCLI)
|
||
|
$(CC) -o $@ $^ -lws2_32
|
||
|
|
||
|
svctest.exe: svctest.o win-scm.c
|
||
|
$(CC) -o $@ $^
|
||
|
|
||
|
portenum.exe: portenum.c
|
||
|
$(CC) $(CFLAGS) -o $@ portenum.c -lwinspool -lsetupapi
|
||
|
|
||
| ... | ... | |
|
/usr/lib/wine/wine.bin wconsd.exe.so -p 9600
|
||
|
|
||
|
clean:
|
||
|
rm -f *.o wconsd.exe portenum.exe
|
||
|
rm -f *.o wconsd.exe portenum.exe svctest.exe
|
||
| svctest.c | ||
|---|---|---|
|
/*
|
||
|
* Test framework for win-svc
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <getopt.h>
|
||
|
|
||
|
#include "scm.h"
|
||
|
|
||
|
/*
|
||
|
* log a debug message
|
||
|
*/
|
||
|
int dprintf_level = 1;
|
||
|
int dprintf_to_stdout = 0;
|
||
|
int dprintf(unsigned char severity, const char *fmt, ...) {
|
||
|
va_list args;
|
||
|
char buf[1024];
|
||
|
int i;
|
||
|
|
||
|
if (severity > dprintf_level)
|
||
|
return 0;
|
||
|
|
||
|
va_start(args,fmt);
|
||
|
i=vsnprintf(buf,sizeof(buf),fmt,args);
|
||
|
va_end(args);
|
||
|
|
||
|
if (dprintf_to_stdout) {
|
||
|
printf("%s",buf);
|
||
|
} else {
|
||
|
OutputDebugStringA(buf);
|
||
|
}
|
||
|
return i;
|
||
|
}
|
||
|
#define trace(s) \
|
||
|
dprintf(1,"%s:%i(%s) %s\n",__FILE__,__LINE__,__FUNCTION__,s)
|
||
|
|
||
|
int svctest_init(int argc, char **argv);
|
||
|
int svctest_main(int param1);
|
||
|
int svctest_stop(int param1);
|
||
|
|
||
|
struct SCM_def sd = {
|
||
|
.name = "svctest",
|
||
|
.desc = "svctest - test win-scm",
|
||
|
.init = svctest_init,
|
||
|
.main = svctest_main,
|
||
|
.stop = svctest_stop,
|
||
|
};
|
||
|
|
||
|
static int do_getopt(const int argc, char **argv) {
|
||
|
static struct option long_options[] = {
|
||
|
{"install", 1, 0, 'i'},
|
||
|
{"remove", 0, 0, 'r'},
|
||
|
{"debug", 2, 0, 'd'},
|
||
|
{0,0,0,0}
|
||
|
};
|
||
|
|
||
|
while(1) {
|
||
|
int c = getopt_long(argc,argv, "ird::",
|
||
|
long_options,NULL);
|
||
|
if (c==-1)
|
||
|
break;
|
||
|
|
||
|
switch(c) {
|
||
|
case 'i': {
|
||
|
/* request service installation */
|
||
|
char *path = SCM_Install(&sd,optarg);
|
||
|
if (!path) {
|
||
|
printf("Service installation failed\n");
|
||
|
return 2;
|
||
|
}
|
||
|
printf("Service '%s' installed, binary path '%s'\n",sd.name,path);
|
||
|
printf("You should now start the service using the service manager.\n");
|
||
|
return 1;
|
||
|
}
|
||
|
case 'r':
|
||
|
// request service removal
|
||
|
if (SCM_Remove(&sd)==0) {
|
||
|
printf("Deleted service '%s'\n",sd.name);
|
||
|
} else {
|
||
|
printf("Service removal failed\n");
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
int svctest_init(int argc, char **argv) {
|
||
|
dprintf(1,"%s:%i(%s) argc==%i\n",__FILE__,__LINE__,__FUNCTION__,argc);
|
||
|
int i;
|
||
|
for (i=0;i<argc;i++) {
|
||
|
dprintf(1,"%s:%i: argv==%s\n",__FILE__,__LINE__,argv[i]);
|
||
|
}
|
||
|
dprintf(1,"%s:%i(%s) sd.mode==%i\n",__FILE__,__LINE__,__FUNCTION__,sd.mode);
|
||
|
|
||
|
if (do_getopt(argc,argv)) {
|
||
|
/* do_getopt returns nonzero if we should not continue */
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
trace("return 0");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int run = 1;
|
||
|
int svctest_main(int param1) {
|
||
|
while(run) {
|
||
|
1;
|
||
|
/* FIXME - sleep */
|
||
|
}
|
||
|
trace("return 0");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int svctest_stop(int param1) {
|
||
|
run = 0;
|
||
|
trace("return 0");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int main(int argc, char **argv)
|
||
|
{
|
||
|
dprintf(1,"%s:%i: argc==%i\n",__FILE__,__LINE__,argc);
|
||
|
char **arg = argv;
|
||
|
while(*arg) {
|
||
|
dprintf(1,"%s:%i: argv==%s\n",__FILE__,__LINE__,*arg);
|
||
|
arg++;
|
||
|
}
|
||
|
|
||
|
if (SCM_Start(&sd,argc,argv)!=SVC_OK) {
|
||
|
dprintf(1,"%s:%i: SCM_Start!=SVC_OK\n",__FILE__,__LINE__);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
trace("return 0");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
| wconsd.c | ||
|---|---|---|
|
switch(c) {
|
||
|
case 'i': {
|
||
|
/* request service installation */
|
||
|
char *path = SCM_Install(&sd);
|
||
|
char *path = SCM_Install(&sd,NULL);
|
||
|
if (!path) {
|
||
|
printf("Service installation failed\n");
|
||
|
return 2;
|
||
| win-scm.c | ||
|---|---|---|
|
SetServiceStatus( svcHandle, &svcStatus );
|
||
|
|
||
|
sd->mode=SVC_OK;
|
||
|
/* TODO - use either saved cmdline args or scm args here */
|
||
|
if ((err=sd->init(argc,argv))!=0) {
|
||
|
svcStatus.dwCurrentState = SERVICE_STOPPED;
|
||
|
svcStatus.dwWin32ExitCode = err;
|
||
| ... | ... | |
|
return;
|
||
|
}
|
||
|
|
||
|
int SCM_Start_Console(int argc, char **argv) {
|
||
|
int SCM_Start_Console(struct SCM_def *sd) {
|
||
|
|
||
|
global_sd->mode=SVC_CONSOLE;
|
||
|
int err = global_sd->init(argc,argv);
|
||
|
sd->mode=SVC_CONSOLE;
|
||
|
int err = sd->init(sd->argc,sd->argv);
|
||
|
if (err!=0) {
|
||
|
return SVC_FAIL;
|
||
|
}
|
||
|
|
||
|
global_sd->main(0);
|
||
|
sd->main(0);
|
||
|
return SVC_OK;
|
||
|
}
|
||
|
|
||
| ... | ... | |
|
{ NULL, NULL }
|
||
|
};
|
||
|
|
||
|
/* save the cmdline for possible use later */
|
||
|
sd->argc=argc;
|
||
|
sd->argv=argv;
|
||
|
|
||
|
global_sd = sd;
|
||
|
|
||
|
#if 0
|
||
|
/* turns out to be untrue! */
|
||
|
/* If we have commandline args, then we cannot have been started
|
||
|
* by the Windows SCM
|
||
|
*/
|
||
|
if (argc>1) {
|
||
|
return SCM_Start_Console(argc,argv);
|
||
|
return SCM_Start_Console(sd);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* try to run as a service */
|
||
|
if (StartServiceCtrlDispatcher(ServiceTable)==0) {
|
||
|
int err = GetLastError();
|
||
|
|
||
|
if (err == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
|
||
|
return SCM_Start_Console(argc,argv);
|
||
|
return SCM_Start_Console(sd);
|
||
|
}
|
||
|
|
||
|
/* any other error, assume fatal */
|
||
| ... | ... | |
|
return SVC_OK;
|
||
|
}
|
||
|
|
||
|
char *SCM_Install(struct SCM_def *sd) {
|
||
|
char *SCM_Install(struct SCM_def *sd, char *args) {
|
||
|
SC_HANDLE schSCManager, schService;
|
||
|
|
||
|
static char path[MAX_PATH];
|
||
| ... | ... | |
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Note - the above path calculation does not work for paths containing
|
||
|
* spaces. This is because Windows is stupid, mosttly due to bad
|
||
|
* design - see the next below.
|
||
|
*/
|
||
|
|
||
|
static char cmdline[MAX_PATH+10];
|
||
|
if (args) {
|
||
|
/*
|
||
|
* The "BinaryPathName" can also have cmdline params
|
||
|
* embedded into it. Stupid windows
|
||
|
*/
|
||
|
|
||
|
snprintf(cmdline,sizeof(cmdline),"\"%s\" %s",path,args);
|
||
|
} else {
|
||
|
snprintf(cmdline,sizeof(cmdline),"\"%s\"",path);
|
||
|
}
|
||
|
|
||
|
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||
|
|
||
|
schService = CreateService(
|
||
| ... | ... | |
|
SERVICE_WIN32_OWN_PROCESS,
|
||
|
SERVICE_AUTO_START,
|
||
|
SERVICE_ERROR_NORMAL,
|
||
|
path,
|
||
|
cmdline,
|
||
|
NULL, NULL, NULL, NULL, NULL);
|
||
|
|
||
|
if (schService == NULL) {
|
||
Also available in: Unified diff
Update win-scm with new learnings, also add a service test helper program