Гость
Map
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как сделать NT Service? / 5 сообщений из 5, страница 1 из 1
28.10.2002, 23:29
    #32062490
Yalovenko
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать NT Service?
Доброго Всем дня или вечера!

Помогите пожал. сделать из этой проги NT Service. Я не имею опыта написания таких прогов.
..............

#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DEFAULT_PORT 5001
#define DEFAULT_PROTO SOCK_STREAM // TCP

void Usage(char *progname) {
fprintf(stderr,"Usage\n%s -p [protocol] -e [endpoint] -i [interface]\n",
progname);
fprintf(stderr,"Where:\n\tprotocol is one of TCP or UDP\n");
fprintf(stderr,"\tendpoint is the port to listen on\n");
fprintf(stderr,"\tinterface is the ipaddr (in dotted decimal notation)");
fprintf(stderr," to bind to\n");
fprintf(stderr,"Defaults are TCP,5001 and INADDR_ANY\n");
WSACleanup();
exit(1);
}
int main(int argc, char **argv) {

char Buffer[128];
char *interface= NULL;
unsigned short port=DEFAULT_PORT;
int retval;
int fromlen;
int i;
int socket_type = DEFAULT_PROTO;
struct sockaddr_in local, from;
WSADATA wsaData;
SOCKET listen_socket, msgsock;

/* Parse arguments */
if (argc >1) {
for(i=1;i <argc;i++) {
if ( (argv [0] == '-') || (argv[0] == '/') ) {
switch(tolower(argv)) {
case 'p':
if (!stricmp(argv[i+1], "TCP") )
socket_type = SOCK_STREAM;
else if (!stricmp(argv[i+1], "UDP") )
socket_type = SOCK_DGRAM;
else
Usage(argv[0]);
i++;
break;

case 'i':
interface = argv[++i];
break;
case 'e':
port = atoi(argv[++i]);
break;
default:
Usage(argv[0]);
break;
}
}
else
Usage(argv[0]);
}
}

if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR) {
fprintf(stderr,"WSAStartup failed with error %d\n",WSAGetLastError());
WSACleanup();
return -1;
}

if (port == 0){
Usage(argv[0]);
}

local.sin_family = AF_INET;
local.sin_addr.s_addr = (!interface)?INADDR_ANY:inet_addr(interface);

/*
* Port MUST be in Network Byte Order
*/
local.sin_port = htons(port);

listen_socket = socket(AF_INET, socket_type,0); // TCP socket

if (listen_socket == INVALID_SOCKET){
fprintf(stderr,"socket() failed with error %d\n",WSAGetLastError());
WSACleanup();
return -1;
}
//
// bind() associates a local address and port combination with the
// socket just created. This is most useful when the application is a
// server that has a well-known port that clients know about in advance.
//

if (bind(listen_socket,(struct sockaddr*)&local,sizeof(local) )
== SOCKET_ERROR) {
fprintf(stderr,"bind() failed with error %d\n",WSAGetLastError());
WSACleanup();
return -1;
}

//
// So far, everything we did was applicable to TCP as well as UDP.
// However, there are certain steps that do not work when the server is
// using UDP.
//

// We cannot listen() on a UDP socket.

if (socket_type != SOCK_DGRAM) {
if (listen(listen_socket,5) == SOCKET_ERROR) {
fprintf(stderr,"listen() failed with error %d\n",WSAGetLastError());
WSACleanup();
return -1;
}
}
printf("%s: 'Listening' on port %d, protocol %s\n",argv[0],port,
(socket_type == SOCK_STREAM)?"TCP":"UDP");
while(1) {
fromlen =sizeof(from);
//
// accept() doesn't make sense on UDP, since we do not listen()
//
if (socket_type != SOCK_DGRAM) {
msgsock = accept(listen_socket,(struct sockaddr*)&from, &fromlen);
if (msgsock == INVALID_SOCKET) {
fprintf(stderr,"accept() error %d\n",WSAGetLastError());
WSACleanup();
return -1;
}
printf("accepted connection from %s, port %d\n",
inet_ntoa(from.sin_addr),
htons(from.sin_port)) ;

}
else
msgsock = listen_socket;

//
// In the case of SOCK_STREAM, the server can do recv() and
// send() on the accepted socket and then close it.

// However, for SOCK_DGRAM (UDP), the server will do
// recvfrom() and sendto() in a loop.

if (socket_type != SOCK_DGRAM)
retval = recv(msgsock,Buffer,sizeof (Buffer),0 );
else {
retval = recvfrom(msgsock,Buffer,sizeof (Buffer),0,
(struct sockaddr *)&from,&fromlen);
printf("Received datagram from %s\n",inet_ntoa(from.sin_addr));
}

if (retval == SOCKET_ERROR) {
fprintf(stderr,"recv() failed: error %d\n",WSAGetLastError());
closesocket(msgsock);
continue;
}
if (retval == 0) {
printf("Client closed connection\n");
closesocket(msgsock);
continue;
}
printf("Received %d bytes, data [%s] from client\n",retval,Buffer);

printf("Echoing same data back to client\n");
if (socket_type != SOCK_DGRAM)
retval = send(msgsock,Buffer,sizeof(Buffer),0);
else
retval = sendto(msgsock,Buffer,sizeof (Buffer),0,
(struct sockaddr *)&from,fromlen);
if (retval == SOCKET_ERROR) {
fprintf(stderr,"send() failed: error %d\n",WSAGetLastError());
}
if (socket_type != SOCK_DGRAM){
printf("Terminating connection\n");
closesocket(msgsock);
}
else
printf("UDP server looping back for more requests\n");
continue;
}
}
...
Рейтинг: 0 / 0
29.10.2002, 10:42
    #32062567
Александр Спелицин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать NT Service?
В примерах MSDN есть пример реализации сервиса. Ищите файлы Client.c, Service.c, Service.h, Simple.c
...
Рейтинг: 0 / 0
29.10.2002, 15:36
    #32062781
Yalovenko
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать NT Service?
Я попробовал вставить кусок программы в Simple.c, но программа не выполняется, иницилизируется pipe и стартует сервис. Вот пример, может здесь чегото не так?

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (C) 1993-1996 Microsoft Corporation. All Rights Reserved.
//
// MODULE: simple.c
//
// PURPOSE: Implements the body of the service.
// The default behavior is to open a
// named pipe, \\.\pipe\simple, and read
// from it. It the modifies the data and
// writes it back to the pipe.
//
// FUNCTIONS:
// ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv);
// ServiceStop( );
//
// COMMENTS: The functions implemented in simple.c are
// prototyped in service.h
//
//
// AUTHOR: Craig Link - Microsoft Developer Support
//
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <tchar.h>
#include "service.h"
//------------------------------------------
#define WIN32_LEAN_AND_MEAN
//#include <stdio.h>
//#include <stdlib.h>
//#include <windows.h>
//#include <tchar.h>
#include <string.h>
#include <winsock.h>
#include <io.h>
#include <direct.h>
#include <time.h>
#include <string.h>
#include <sql.h>
#include <sqlext.h>
#include <odbcss.h>
//------------------------------------------
#define MAX_CONNECTION_NUM 100
#define MAX_REC_LEN 512
#define DATE_LEN 7
#define IPADDR_LEN 16
#define PORT_LEN 7
#define VERSION_LEN 11
#define MAX_NAME_LEN 32
#define MAX_CHASSIS_NUM 100
#define MAX_FILE_NAME_LEN 128
#define MAX_PATH_LEN 256
#define MAX_ESQN_LEN 10
#define MAX_PASSWORD_LEN 16
#define MAX_CDR_NUM 10000
#define MAX_RESETNUM_LEN 11

// States of the CDR Server
#define AVAIL -1
#define START 0
#define WELCOMED 1
#define CONNECTED 2
#define PASSWORDSENT 3
#define PASSWORDOK 4
#define GOTGWIP 5
#define GOTUNITNAME 6
#define GOTLASTSEQNO 7
#define READY 8

//
// Structure definition
//
// The context key keeps track of how the I/O
// is progressing for each individual file handle.
struct ContextKey
{
SOCKET sock;
// Input
char InBuffer[MAX_REC_LEN];
OVERLAPPED ovIn;
// Output
int nCDRBuffIndex;
int nOutBuffIndex;
char CDRBuffer[MAX_REC_LEN];
char OutBuffer[MAX_REC_LEN];
OVERLAPPED ovOut;
DWORD dwWritten;
int sid;
};
//
// Global variables
//
struct ContextKey *pCntx[MAX_CONNECTION_NUM];
HANDLE ghFile;
HANDLE ghCompletionPort[MAX_CONNECTION_NUM];
HANDLE hFile[MAX_CONNECTION_NUM];
OVERLAPPED overlap[MAX_CONNECTION_NUM];
char cdrfile_path[MAX_PATH_LEN];
char cdrpassword[MAX_PASSWORD_LEN];
char cdrport[PORT_LEN];
char cfgfile_path[MAX_PATH_LEN];
char version[VERSION_LEN];
int cid; //Current Connection Identifier
int state[MAX_CONNECTION_NUM];
int maxchano = MAX_CHASSIS_NUM;
int maxcdrno = MAX_CDR_NUM;
short cdrserverport;
typedef struct chassis {
short avail;
char IpAddr[IPADDR_LEN];
char unitname[MAX_NAME_LEN];
char resetnum[MAX_RESETNUM_LEN];
long resetno;
long curr_resetno;
} CHASSIS;

CHASSIS cha[MAX_CHASSIS_NUM];
//-----------------------------------------------------------------------
char cmd;
char slog1[20];
char spwd1[20];
char sdsn1[20];
SQLHENV henv2 = SQL_NULL_HENV;

SQLHDBC hdbc2 = SQL_NULL_HDBC;
SQLHSTMT hstmt2 = SQL_NULL_HSTMT;

RETCODE retcode;
// SQLBindParameter variables.
SQLINTEGER cbmu=SQL_NTS,cba1=SQL_NTS,cbb1=SQL_NTS,cbc1=SQL_NTS,cbd1=SQL_NTS,cbe1=SQL_NTS,cbf1=SQL_NTS,
cbg1=SQL_NTS,cbh1=SQL_NTS,cbi1=SQL_NTS,cbj1=SQL_NTS,cbk1=SQL_NTS,cbl1=SQL_NTS,cbm1=SQL_NTS,cbn1=SQL_NTS,
cbo1=SQL_NTS,cbp1=SQL_NTS,cbq1=SQL_NTS,cbr1=SQL_NTS,cbs1=SQL_NTS,cbt1=SQL_NTS,cbu1=SQL_NTS,
cbv1=SQL_NTS,cbw1=SQL_NTS,cbx1=SQL_NTS,cby1=SQL_NTS,cbz1=SQL_NTS,cbz11=SQL_NTS,cbz21=SQL_NTS;

SQLINTEGER cbrecno=SQL_NTS,cbipadr=SQL_NTS;
//SQLCHAR ipadr[16];
//SQLUINTEGER recno;
SQLUINTEGER a11;

SQLCHAR mu[5];
SQLCHAR a1[20];
SQLCHAR b1[20];
SQLCHAR c1[20];
SQLCHAR d1[20];
SQLCHAR e1[20];
SQLCHAR f1[20];
SQLCHAR g1[20];
SQLCHAR h1[20];
SQLCHAR i1[20];
SQLCHAR j1[20];
SQLCHAR k1[20];
SQLCHAR l1[20];
SQLCHAR m1[20];
SQLCHAR n1[20];
SQLCHAR o1[20];
SQLCHAR p1[20];
SQLCHAR q1[20];
SQLCHAR r1[20];
SQLCHAR s1[20];
SQLCHAR t1[20];
SQLCHAR u1[20];
SQLCHAR v1[20];
SQLCHAR w1[20];
SQLCHAR x1[20];
SQLCHAR y1[20];
SQLCHAR z1[20];
SQLCHAR z11[20];
SQLCHAR z21[20];
//-----------------------------------------------------------------------
// this event is signalled when the
// service should end
//
HANDLE hServerStopEvent = NULL;
//
// FUNCTION: ServiceStart
//
// PURPOSE: Actual code of the service
// that does the work.
//
// PARAMETERS:
// dwArgc - number of command line arguments
// lpszArgv - array of command line arguments
//
// RETURN VALUE:
// none
//
// COMMENTS:
// The default behavior is to open a
// named pipe, \\.\pipe\simple, and read
// from it. It the modifies the data and
// writes it back to the pipe. The service
// stops when hServerStopEvent is signalled
//
VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv)
{
HANDLE hPipe = INVALID_HANDLE_VALUE;
HANDLE hEvents = {NULL, NULL};
OVERLAPPED os;
PSECURITY_DESCRIPTOR pSD = NULL;
SECURITY_ATTRIBUTES sa;
TCHAR szIn[80];
TCHAR szOut[80];
LPTSTR lpszPipeName = TEXT("\\\\.\\pipe\\simple");
BOOL bRet;
DWORD cbRead;
DWORD cbWritten;
DWORD dwWait;
UINT ndx;
//------------------------------------------------------
SOCKET listener;
SOCKET AcceptSocket;
WSADATA WsaData;
struct sockaddr_in serverAddress;
struct sockaddr_in clientAddress;
int clientAddressLength;
int err;
int i = 0;
struct ContextKey *pKey[MAX_CONNECTION_NUM];
char *curr_path;
char ver[VERSION_LEN];
//------------------------------------------------------

///////////////////////////////////////////////////
//
// Service initialization
//
// report the status to the service control manager.
//
if (!ReportStatusToSCMgr(
SERVICE_START_PENDING, // service state
NO_ERROR, // exit code
3000)) // wait hint
goto cleanup;
// create the event object. The control handler function signals
// this event when it receives the "stop" control code.
//
hServerStopEvent = CreateEvent(
NULL, // no security attributes
TRUE, // manual reset event
FALSE, // not-signalled
NULL); // no name

if ( hServerStopEvent == NULL)
goto cleanup;
hEvents[0] = hServerStopEvent;
// report the status to the service control manager.
//
if (!ReportStatusToSCMgr(
SERVICE_START_PENDING, // service state
NO_ERROR, // exit code
3000)) // wait hint
goto cleanup;
// create the event object object use in overlapped i/o
//
hEvents = CreateEvent(
NULL, // no security attributes
TRUE, // manual reset event
FALSE, // not-signalled
NULL); // no name

if ( hEvents == NULL)
goto cleanup;
// report the status to the service control manager.
//
if (!ReportStatusToSCMgr(
SERVICE_START_PENDING, // service state
NO_ERROR, // exit code
3000)) // wait hint
goto cleanup;
// create a security descriptor that allows anyone to write to
// the pipe...
//
pSD = (PSECURITY_DESCRIPTOR) malloc( SECURITY_DESCRIPTOR_MIN_LENGTH );
if (pSD == NULL)
goto cleanup;
if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
goto cleanup;
// add a NULL disc. ACL to the security descriptor.
//
if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE))
goto cleanup;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = pSD;
sa.bInheritHandle = TRUE;
// report the status to the service control manager.
//

if (!ReportStatusToSCMgr(
SERVICE_START_PENDING, // service state
NO_ERROR, // exit code
3000)) // wait hint
goto cleanup;

// allow user tp define pipe name
for ( ndx = 1; ndx < dwArgc-1; ndx++ )
{
if ( ( (*(lpszArgv[ndx]) == TEXT('-')) ||
(*(lpszArgv[ndx]) == TEXT('/')) ) &&
_tcsicmp( TEXT("pipe"), lpszArgv[ndx]+1 ) == 0 )
{
lpszPipeName = lpszArgv[++ndx];
}
}

// open our named pipe...
//
hPipe = CreateNamedPipe(
lpszPipeName , // name of pipe
FILE_FLAG_OVERLAPPED |
PIPE_ACCESS_DUPLEX, // pipe open mode
PIPE_TYPE_MESSAGE |
PIPE_READMODE_MESSAGE |
PIPE_WAIT, // pipe IO type
1, // number of instances
0, // size of outbuf (0 == allocate as necessary)
0, // size of inbuf
1000, // default time-out value
&sa); // security attributes
if (hPipe == INVALID_HANDLE_VALUE) {
AddToMessageLog(TEXT("Unable to create named pipe"));
goto cleanup;
}
// report the status to the service control manager.
//
if (!ReportStatusToSCMgr(
SERVICE_RUNNING, // service state
NO_ERROR, // exit code
0)) // wait hint
goto cleanup;

//
// End of initialization
//
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
//
// Service is now running, perform work until shutdown
//

while ( 1 )
{

// init the overlapped structure
//
memset( &os, 0, sizeof(OVERLAPPED) );
os.hEvent = hEvents;
ResetEvent( hEvents );
// wait for a connection...
//
ConnectNamedPipe(hPipe, &os);
if ( GetLastError() == ERROR_IO_PENDING )
{
dwWait = WaitForMultipleObjects( 2, hEvents, FALSE, INFINITE );
if ( dwWait != WAIT_OBJECT_0+1 ) // not overlapped i/o event - error occurred,
// break; // or server stop signaled
goto cleanup;
}


// init the overlapped structure
//
memset( &os, 0, sizeof(OVERLAPPED) );
os.hEvent = hEvents;
ResetEvent( hEvents );
// grab whatever's coming through the pipe...
//
/*
bRet = ReadFile(
hPipe, // file to read from
szIn, // address of input buffer
sizeof(szIn), // number of bytes to read
&cbRead, // number of bytes read
&os); // overlapped stuff, not needed
if ( !bRet && ( GetLastError() == ERROR_IO_PENDING ) )
{
dwWait = WaitForMultipleObjects( 2, hEvents, FALSE, INFINITE );
if ( dwWait != WAIT_OBJECT_0+1 ) // not overlapped i/o event - error occurred,
break; // or server stop signaled
}

// munge the string
//
_stprintf(szOut, TEXT("Hello! [%s]"), szIn);
// init the overlapped structure
//
memset( &os, 0, sizeof(OVERLAPPED) );
os.hEvent = hEvents;
ResetEvent( hEvents );
// send it back out...
//
bRet = WriteFile(
hPipe, // file to write to
szOut, // address of output buffer
sizeof(szOut), // number of bytes to write
&cbWritten, // number of bytes written
&os); // overlapped stuff, not needed
*/



// Initialize cdrip to 9002 as the default value
// the cfg file path and cdr file path to the working directory path
strcpy(version, "10.06.2002.V2");
strcpy(cdrport, "9002");
curr_path = _getcwd(NULL, MAX_PATH_LEN);
strcpy(cfgfile_path, curr_path);
// printf("cfgfile_path = %s, cdrfile_path = %s\n", cfgfile_path, cdrfile_path);
free(curr_path);

cdrserverport = atoi(cdrport); // convert cdr tcp ip port number into integer
// fprintf(stdout, "TCP IP PORT = %d\n", cdrserverport);
//
// Now we are ready to open the cdrserver.cfg file to get the cdr password,
// the maximum number of gateways that it will collect CDRs from,
// the maximum records that each cdr file can contain.

ghFile = CreateFile(
cfgfile_path,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);

if (ghFile == INVALID_HANDLE_VALUE)
{
// FatalError("Open Cdrserver Configuration File Failed\n");
goto cleanup;
}
else
{
GetConfigInfo(&(cdrpassword[0]), &maxchano, &maxcdrno, &(slog1[0]), &(spwd1[0]), &(sdsn1[0]));
}


//----------------------------------------------------------------
// Allocate the ODBC environment and save handle.
retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv2);
// Notify ODBC that this is an ODBC 3.0 app.
retcode = SQLSetEnvAttr(henv2, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER);
// Allocate ODBC connection handle and connect.
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv2, &hdbc2);
retcode = SQLConnect(hdbc2, sdsn1, SQL_NTS,slog1, SQL_NTS, spwd1, SQL_NTS);
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) )
{
//fprintf(stdout,"Connect failed ODBC connection RetCode = %d\n",retcode);
//fprintf(stdout,"sdsn1 = %s slog1 = %s spwd1 = %s\n", sdsn1,slog1,spwd1);
// return EXIT_FAILURE;
goto cleanup;
}
//----------------------------------------------------------------

for (i=0; i < MAX_CHASSIS_NUM; i++)
{
strcpy(cha .IpAddr, "0.0.0.0\0");
strcpy(cha.unitname, "unit1\0");
strcpy(cha.resetnum, "-1\0");
cha.curr_resetno = -1;
cha.resetno = -1;
cha.avail = 1;
}

CheckOsVersion();

err = WSAStartup (0x0101, &WsaData);
if (err == SOCKET_ERROR)
{
// FatalError("WSAStartup Failed");
// return EXIT_FAILURE;
goto cleanup;
}
listener = socket(AF_INET, SOCK_STREAM, 0);
if (listener < 0)
{
// FatalError("socket() failed");
// return EXIT_FAILURE;
goto cleanup;
}
// set socket option to so_keepalive
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(cdrserverport);
err = bind(listener,
(struct sockaddr *)&serverAddress,
sizeof(serverAddress)
);
if (err < 0) {
// FatalError("bind() failed");
goto cleanup;
} else {
int keepalivestat = 1;
setsockopt(listener,
IPPROTO_TCP,
SO_KEEPALIVE,
(char *)&keepalivestat,
sizeof(int));
}
//
// Create a IO completion port for each incoming gateway connection
//

for (i = 0; i < MAX_CONNECTION_NUM; i++) {
ghCompletionPort = CreateIoCompletionPort(
INVALID_HANDLE_VALUE,
NULL, // No prior port
0, // No key
0 // Use default # of threads
);
if (ghCompletionPort == NULL)
// FatalError("CreateIoCompletionPort() failed");
goto cleanup;
CreateWorkerThreads(i);
state = AVAIL;
}

listen(listener, 10);

//
// Loop forever accepting requests new connections
// and starting reading from them.
//
cid = -1;

for (;;)
{

clientAddressLength = sizeof(clientAddress);
AcceptSocket = accept(listener,
(struct sockaddr *)&clientAddress,
&clientAddressLength);
if (AcceptSocket < 0)
{
// FatalError("accept() Failed");
// return EXIT_FAILURE;
goto cleanup;
}
for (i=0; i < MAX_CONNECTION_NUM; i++) {
if (state == AVAIL) {
cid = i;
// printf("AVAIL CONN ID = %d\n", cid);
break;
}
}
if (cid == -1)
// FatalError("NO AVAILABLE TCP/IP Connections");
goto cleanup;
pKey[cid] = calloc(1, sizeof(struct ContextKey));
pKey[cid]->sock = AcceptSocket;
pKey[cid]->ovOut.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
// Set the event for writing so that packets
// will not be sent to the completion port when
// a write finishes.
pKey[cid]->ovOut.hEvent = (HANDLE)((DWORD)pKey[cid]->ovOut.hEvent | 0x1);
pKey[cid]->sid = cid;
// Associate the socket with the completion port
CreateIoCompletionPort(
(HANDLE)AcceptSocket,
ghCompletionPort[cid],
(DWORD)pKey[cid], // No key
0 // Use default # of threads
);
// Kick off the first read
state[cid] = START;

if (IssueRead(pKey[cid]) < 0)
{
free(pKey[cid]);
state[cid] = AVAIL;
// fprintf(stderr, "CONNID = %d, IssueRead Failed\n", cid);
}

}

//------------------------------------------------------------------------------------


/*
// if ( !bRet && ( GetLastError() == ERROR_IO_PENDING ) )
if ( GetLastError() == ERROR_IO_PENDING )
{
dwWait = WaitForMultipleObjects( 2, hEvents, FALSE, INFINITE );
if ( dwWait != WAIT_OBJECT_0+1 ) // not overlapped i/o event - error occurred,
break; // or server stop signaled
}

// drop the connection...
//
*/
DisconnectNamedPipe(hPipe);

}


cleanup:
/* Clean up. */
SQLFreeHandle(SQL_HANDLE_STMT, hstmt2);
SQLDisconnect(hdbc2);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc2);
SQLFreeHandle(SQL_HANDLE_ENV, henv2);

if (hPipe != INVALID_HANDLE_VALUE )
CloseHandle(hPipe);
if (hServerStopEvent)
CloseHandle(hServerStopEvent);
if (hEvents) // overlapped i/o event
CloseHandle(hEvents);
if ( pSD )
free( pSD );
}
//
// FUNCTION: ServiceStop
//
// PURPOSE: Stops the service
//
// PARAMETERS:
// none
//
// RETURN VALUE:
// none
//
// COMMENTS:
// If a ServiceStop procedure is going to
// take longer than 3 seconds to execute,
// it should spawn a thread to execute the
// stop code, and return. Otherwise, the
// ServiceControlManager will believe that
// the service has stopped responding.
//
VOID ServiceStop()
{
if ( hServerStopEvent )
SetEvent(hServerStopEvent);
}
//---------------------------------------------------------------------------------------------
...
Рейтинг: 0 / 0
30.10.2002, 17:22
    #32063266
AHA
AHA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать NT Service?
Пример из Platform SDK:
/*---------------------------------------------------------------------------
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Copyright (C) 1993 - 2000. Microsoft Corporation. All rights reserved.

MODULE: service.c

PURPOSE: Implements functions required by all Windows NT services

FUNCTIONS:
main(int argc, char **argv);
service_ctrl(DWORD dwCtrlCode);
service_main(DWORD dwArgc, LPTSTR *lpszArgv);
CmdInstallService();
CmdRemoveService();
CmdDebugService(int argc, char **argv);
ControlHandler ( DWORD dwCtrlType );
GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );

---------------------------------------------------------------------------*/

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <tchar.h>

#include "service.h"

// internal variables
SERVICE_STATUS ssStatus; // current status of the service
SERVICE_STATUS_HANDLE sshStatusHandle;
DWORD dwErr = 0;
BOOL bDebug = FALSE;
TCHAR szErr[256];

// internal function prototypes
VOID WINAPI service_ctrl(DWORD dwCtrlCode);
VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv);
VOID CmdInstallService();
VOID CmdRemoveService();
VOID CmdDebugService(int argc, char **argv);
BOOL WINAPI ControlHandler ( DWORD dwCtrlType );
LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );

//
// FUNCTION: main
//
// PURPOSE: entrypoint for service
//
// PARAMETERS:
// argc - number of command line arguments
// argv - array of command line arguments
//
// RETURN VALUE:
// none
//
// COMMENTS:
// main() either performs the command line task, or
// call StartServiceCtrlDispatcher to register the
// main service thread. When the this call returns,
// the service has stopped, so exit.
//
void __cdecl main(int argc, char **argv)
{
SERVICE_TABLE_ENTRY dispatchTable[] =
{
{ TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main},
{ NULL, NULL}
};

if ( (argc > 1) &&
((*argv == '-') || (*argv == '/')) )
{
if ( _stricmp( "install", argv+1 ) == 0 )
{
CmdInstallService();
}
else if ( _stricmp( "remove", argv+1 ) == 0 )
{
CmdRemoveService();
}
else if ( _stricmp( "debug", argv+1 ) == 0 )
{
bDebug = TRUE;
CmdDebugService(argc, argv);
}
else
{
goto dispatch;
}
exit(0);
}

// if it doesn't match any of the above parameters
// the service control manager may be starting the service
// so we must call StartServiceCtrlDispatcher
dispatch:
// this is just to be friendly
printf( "%s -install to install the service\n", SZAPPNAME );
printf( "%s -remove to remove the service\n", SZAPPNAME );
printf( "%s -debug <params> to run as a console app for debugging\n", SZAPPNAME );
printf( "\nStartServiceCtrlDispatcher being called.\n" );
printf( "This may take several seconds. Please wait.\n" );

if (!StartServiceCtrlDispatcher(dispatchTable))
AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed."));
}



//
// FUNCTION: service_main
//
// PURPOSE: To perform actual initialization of the service
//
// PARAMETERS:
// dwArgc - number of command line arguments
// lpszArgv - array of command line arguments
//
// RETURN VALUE:
// none
//
// COMMENTS:
// This routine performs the service initialization and then calls
// the user defined ServiceStart() routine to perform majority
// of the work.
//
void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
{

// register our service control handler:
//
sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME), service_ctrl);

if (!sshStatusHandle)
goto cleanup;

// SERVICE_STATUS members that don't change in example
//
ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ssStatus.dwServiceSpecificExitCode = 0;


// report the status to the service control manager.
//
if (!ReportStatusToSCMgr(
SERVICE_START_PENDING, // service state
NO_ERROR, // exit code
3000)) // wait hint
goto cleanup;


ServiceStart( dwArgc, lpszArgv );

cleanup:

// try to report the stopped status to the service control manager.
//
if (sshStatusHandle)
(VOID)ReportStatusToSCMgr(
SERVICE_STOPPED,
dwErr,
0);

return;
}



//
// FUNCTION: service_ctrl
//
// PURPOSE: This function is called by the SCM whenever
// ControlService() is called on this service.
//
// PARAMETERS:
// dwCtrlCode - type of control requested
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
VOID WINAPI service_ctrl(DWORD dwCtrlCode)
{
// Handle the requested control code.
//
switch (dwCtrlCode)
{
// Stop the service.
//
// SERVICE_STOP_PENDING should be reported before
// setting the Stop Event - hServerStopEvent - in
// ServiceStop(). This avoids a race condition
// which may result in a 1053 - The Service did not respond...
// error.
case SERVICE_CONTROL_STOP:
ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0);
ServiceStop();
return;

// Update the service status.
//
case SERVICE_CONTROL_INTERROGATE:
break;

// invalid control code
//
default:
break;

}

ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
}



//
// FUNCTION: ReportStatusToSCMgr()
//
// PURPOSE: Sets the current status of the service and
// reports it to the Service Control Manager
//
// PARAMETERS:
// dwCurrentState - the state of the service
// dwWin32ExitCode - error code to report
// dwWaitHint - worst case estimate to next checkpoint
//
// RETURN VALUE:
// TRUE - success
// FALSE - failure
//
// COMMENTS:
//
BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
BOOL fResult = TRUE;


if ( !bDebug ) // when debugging we don't report to the SCM
{
if (dwCurrentState == SERVICE_START_PENDING)
ssStatus.dwControlsAccepted = 0;
else
ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

ssStatus.dwCurrentState = dwCurrentState;
ssStatus.dwWin32ExitCode = dwWin32ExitCode;
ssStatus.dwWaitHint = dwWaitHint;

if ( ( dwCurrentState == SERVICE_RUNNING ) ||
( dwCurrentState == SERVICE_STOPPED ) )
ssStatus.dwCheckPoint = 0;
else
ssStatus.dwCheckPoint = dwCheckPoint++;


// Report the status of the service to the service control manager.
//
if (!(fResult = SetServiceStatus( sshStatusHandle, &ssStatus)))
{
AddToMessageLog(TEXT("SetServiceStatus"));
}
}
return fResult;
}



//
// FUNCTION: AddToMessageLog(LPTSTR lpszMsg)
//
// PURPOSE: Allows any thread to log an error message
//
// PARAMETERS:
// lpszMsg - text for message
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
VOID AddToMessageLog(LPTSTR lpszMsg)
{
TCHAR szMsg[256];
HANDLE hEventSource;
LPTSTR lpszStrings;


if ( !bDebug )
{
dwErr = GetLastError();

// Use event logging to log the error.
//
hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME));

_stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr);
lpszStrings[0] = szMsg;
lpszStrings = lpszMsg;

if (hEventSource != NULL)
{
ReportEvent(hEventSource, // handle of event source
EVENTLOG_ERROR_TYPE, // event type
0, // event category
0, // event ID
NULL, // current user's SID
2, // strings in lpszStrings
0, // no bytes of raw data
lpszStrings, // array of error strings
NULL); // no raw data

(VOID) DeregisterEventSource(hEventSource);
}
}
}




///////////////////////////////////////////////////////////////////
//
// The following code handles service installation and removal
//


//
// FUNCTION: CmdInstallService()
//
// PURPOSE: Installs the service
//
// PARAMETERS:
// none
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
void CmdInstallService()
{
SC_HANDLE schService;
SC_HANDLE schSCManager;

TCHAR szPath[512];

if ( GetModuleFileName( NULL, szPath, 512 ) == 0 )
{
_tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256));
return;
}

schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
);
if ( schSCManager )
{
schService = CreateService(
schSCManager, // SCManager database
TEXT(SZSERVICENAME), // name of service
TEXT(SZSERVICEDISPLAYNAME), // name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
szPath, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
TEXT(SZDEPENDENCIES), // dependencies
NULL, // LocalSystem account
NULL); // no password

if ( schService )
{
_tprintf(TEXT("%s installed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
CloseServiceHandle(schService);
}
else
{
_tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(szErr, 256));
}

CloseServiceHandle(schSCManager);
}
else
_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
}



//
// FUNCTION: CmdRemoveService()
//
// PURPOSE: Stops and removes the service
//
// PARAMETERS:
// none
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
void CmdRemoveService()
{
SC_HANDLE schService;
SC_HANDLE schSCManager;

schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
);
if ( schSCManager )
{
schService = OpenService(schSCManager, TEXT(SZSERVICENAME), SERVICE_ALL_ACCESS);

if (schService)
{
// try to stop the service
if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
{
_tprintf(TEXT("Stopping %s."), TEXT(SZSERVICEDISPLAYNAME));
Sleep( 1000 );

while ( QueryServiceStatus( schService, &ssStatus ) )
{
if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
{
_tprintf(TEXT("."));
Sleep( 1000 );
}
else
break;
}

if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
_tprintf(TEXT("\n%s stopped.\n"), TEXT(SZSERVICEDISPLAYNAME) );
else
_tprintf(TEXT("\n%s failed to stop.\n"), TEXT(SZSERVICEDISPLAYNAME) );

}

// now remove the service
if ( DeleteService(schService) )
_tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
else
_tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256));


CloseServiceHandle(schService);
}
else
_tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));

CloseServiceHandle(schSCManager);
}
else
_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
}




///////////////////////////////////////////////////////////////////
//
// The following code is for running the service as a console app
//


//
// FUNCTION: CmdDebugService(int argc, char ** argv)
//
// PURPOSE: Runs the service as a console application
//
// PARAMETERS:
// argc - number of command line arguments
// argv - array of command line arguments
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
void CmdDebugService(int argc, char ** argv)
{
DWORD dwArgc;
LPTSTR *lpszArgv;

#ifdef UNICODE
lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) );
#else
dwArgc = (DWORD) argc;
lpszArgv = argv;
#endif

_tprintf(TEXT("Debugging %s.\n"), TEXT(SZSERVICEDISPLAYNAME));

SetConsoleCtrlHandler( ControlHandler, TRUE );

ServiceStart( dwArgc, lpszArgv );

#ifdef UNICODE
// Must free memory allocated for arguments

GlobalFree(lpszArgv);
#endif // UNICODE

}


//
// FUNCTION: ControlHandler ( DWORD dwCtrlType )
//
// PURPOSE: Handled console control events
//
// PARAMETERS:
// dwCtrlType - type of control event
//
// RETURN VALUE:
// True - handled
// False - unhandled
//
// COMMENTS:
//
BOOL WINAPI ControlHandler ( DWORD dwCtrlType )
{
switch ( dwCtrlType )
{
case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate
case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode
_tprintf(TEXT("Stopping %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
ServiceStop();
return TRUE;
break;

}
return FALSE;
}

//
// FUNCTION: GetLastErrorText
//
// PURPOSE: copies error message text to string
//
// PARAMETERS:
// lpszBuf - destination buffer
// dwSize - size of buffer
//
// RETURN VALUE:
// destination buffer
//
// COMMENTS:
//
LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize )
{
DWORD dwRet;
LPTSTR lpszTemp = NULL;

dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
GetLastError(),
LANG_NEUTRAL,
(LPTSTR)&lpszTemp,
0,
NULL );

// supplied buffer is not long enough
if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
lpszBuf[0] = TEXT('\0');
else
{
lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0'); //remove cr and newline character
_stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError() );
}

if ( lpszTemp )
LocalFree((HLOCAL) lpszTemp );

return lpszBuf;
}
...
Рейтинг: 0 / 0
30.10.2002, 22:20
    #32063365
Yalovenko
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать NT Service?
Спасибо, правда пришлось немного выправить код в argv , и lpszStrings, но все же как взаимодеиствует код в проге simple.c? Может у кого нибудь есть кусок проги?
Заранее благодарен.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как сделать NT Service? / 5 сообщений из 5, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]